PageSourceSearch

https://www.customandcommercial.com/blog/

html customandcommercial.com collected 2026-09-25 18:32:08 UTC 398,882 bytes, 7,424 lines download raw bytes

1<!doctype html>
2<html lang="en">
3<head >
4    <meta charset="utf-8"/>
5<meta name="title" content="Blog"/>
6<meta name="robots" content="INDEX,FOLLOW"/>
7<meta name="viewport" content="width=device-width, initial-scale=1"/>
8<title>Blog</title><style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="18">.cmsb18-text-center {
9text-align: center
10}
11.cmsb18-text-sm {
12font-size: 0.875rem;
13line-height: 1.25rem
14}
15.cmsb18-font-normal {
16font-weight: 400
17}</style>
18        <link rel="stylesheet" type="text/css" media="all" href="https://www.customandcommercial.com/static/version1778675079/_cache/merged/df8d0e0e767407f31e3cf63e565eb9e1.css" />
19<script type="text/javascript" src="https://www.customandcommercial.com/static/version1778675079/frontend/Actuate/c-and-c/en_US/Smile_ElasticsuiteTracker/js/tracking.js"></script>
19
20<link rel="canonical" href="https://www.customandcommercial.com/blog/" />
21<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap" />
22<link type="text/css" rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300..900;1,300..900&display=swap" />
23<link rel="icon" type="image/x-icon" href="https://www.customandcommercial.com/media/favicon/stores/1/favicon.png" />
24<link rel="shortcut icon" type="image/x-icon" href="https://www.customandcommercial.com/media/favicon/stores/1/favicon.png" />
25<style>
26.message-success,
27.messages .message,
28.message.notice,
29.message-success.success.message {
30display:none !important;
31}
32</style>    <!-- NO Pixel ID is configured, please goto Admin -->
33<script type="text&#x2F;javascript">    console.log('No Meta pixel is configured, please log in as a admin and then visit Stores -> Meta -> Setup -> Get Started');</script>
33<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
34require(['sfgetid'], function(sfgetid) {
35    sfgetid();
36});
37</script>
vendor: 1 bytes, line 37
37
38<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
39sfDataLayer = window.sfDataLayer || [];
40sfDataLayer.push({
41    "salesfire": {
42        "platform": "magento2"
43    }
44});
45</script>
vendor: 1 bytes, line 45
45
46<script async src='https://cdn.salesfire.co.uk/code/66bc4c55-6168-4741-b651-aeb84ea6a384.js'></script>
46
47    
47<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
48        //<![CDATA[
49        function userConsentEsTraking(config)
50        {
51            return config.cookieRestrictionEnabled == false || hyva.getCookie(config.cookieRestrictionName) !== null;
52        }
53
54        try {
55            smileTracker.setConfig({
56                beaconUrl     : 'https://www.customandcommercial.com/elasticsuite/tracker/hit/image/h.png',
57                telemetryUrl     : 'https://t.elasticsuite.io/track',
58                telemetryEnabled : '',
59                sessionConfig : {"visit_cookie_name":"STUID","visit_cookie_lifetime":"3600","visitor_cookie_lifetime":"365","visitor_cookie_name":"STVID","domain":"www.customandcommercial.com","path":"\/"},
60                endpointUrl : 'https://www.customandcommercial.com/rest/V1/elasticsuite-tracker/hit'
61            });
62
63            smileTracker.addPageVar('store_id', '1');
64
65            document.addEventListener('DOMContentLoaded', function () {
66                if (userConsentEsTraking({"cookieRestrictionEnabled":"0","cookieRestrictionName":"user_allowed_save_cookie"})) {
67                    smileTracker.sendTag();
68                }
69            });
70        } catch (err) {
71            ;
72        }
73        //]]>
74    </script>
vendor: 1 bytes, line 74
74
75<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
76    var BASE_URL = 'https://www.customandcommercial.com/';
77    var THEME_PATH = 'https://www.customandcommercial.com/static/version1778675079/frontend/Actuate/c-and-c/en_US';
78    var COOKIE_CONFIG = {
79        "expires": null,
80        "path": "\u002F",
81        "domain": ".www.customandcommercial.com",
82        "secure": true,
83        "lifetime": "3600",
84        "cookie_restriction_enabled": false    };
85    var CURRENT_STORE_CODE = 'default';
86    var CURRENT_WEBSITE_ID = '1';
87
88    window.hyva = window.hyva || {}
89
90    window.cookie_consent_groups = window.cookie_consent_groups || {}
91    window.cookie_consent_groups['necessary'] = true;
92
93    window.cookie_consent_config = window.cookie_consent_config || {};
94    window.cookie_consent_config['necessary'] = [].concat(
95        window.cookie_consent_config['necessary'] || [],
96        [
97            'user_allowed_save_cookie',
98            'form_key',
99            'mage-messages',
100            'private_content_version',
101            'mage-cache-sessid',
102            'last_visited_store',
103            'section_data_ids'
104        ]
105    );
106</script>
vendor: 1 bytes, line 106
106
107<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
108    'use strict';
109    (function( hyva, undefined ) {
110
111        function lifetimeToExpires(options, defaults) {
112
113            const lifetime = options.lifetime || defaults.lifetime;
114
115            if (lifetime) {
116                const date = new Date;
117                date.setTime(date.getTime() + lifetime * 1000);
118                return date;
119            }
120
121            return null;
122        }
123
124        function generateRandomString() {
125
126            const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
127                length = 16;
128
129            let formKey = '',
130                charactersLength = allowedCharacters.length;
131
132            for (let i = 0; i < length; i++) {
133                formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))]
134            }
135
136            return formKey;
137        }
138
139        const sessionCookieMarker = {noLifetime: true}
140
141        const cookieTempStorage = {};
142
143        const internalCookie = {
144            get(name) {
145                const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
146                return v ? v[2] : null;
147            },
148            set(name, value, days, skipSetDomain) {
149                let expires,
150                    path,
151                    domain,
152                    secure,
153                    samesite;
154
155                const defaultCookieConfig = {
156                    expires: null,
157                    path: '/',
158                    domain: null,
159                    secure: false,
160                    lifetime: null,
161                    samesite: 'lax'
162                };
163
164                const cookieConfig = window.COOKIE_CONFIG || {};
165
166                expires = days && days !== sessionCookieMarker
167                    ? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig)
168                    : lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires;
169
170                path = cookieConfig.path || defaultCookieConfig.path;
171                domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain);
172                secure = cookieConfig.secure || defaultCookieConfig.secure;
173                samesite = cookieConfig.samesite || defaultCookieConfig.samesite;
174
175                document.cookie = name + "=" + encodeURIComponent(value) +
176                    (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') +
177                    (path ? '; path=' + path : '') +
178                    (domain ? '; domain=' + domain : '') +
179                    (secure ? '; secure' : '') +
180                    (samesite ? '; samesite=' + samesite : 'lax');
181            },
182            isWebsiteAllowedToSaveCookie() {
183                const allowedCookies = this.get('user_allowed_save_cookie');
184                if (allowedCookies) {
185                    const allowedWebsites = JSON.parse(unescape(allowedCookies));
186
187                    return allowedWebsites[CURRENT_WEBSITE_ID] === 1;
188                }
189                return false;
190            },
191            getGroupByCookieName(name) {
192                const cookieConsentConfig = window.cookie_consent_config || {};
193                let group = null;
194                for (let prop in cookieConsentConfig) {
195                    if (!cookieConsentConfig.hasOwnProperty(prop)) continue;
196                    if (cookieConsentConfig[prop].includes(name)) {
197                        group = prop;
198                        break;
199                    }
200                }
201                return group;
202            },
203            isCookieAllowed(name) {
204                const cookieGroup = this.getGroupByCookieName(name);
205                return cookieGroup
206                    ? window.cookie_consent_groups[cookieGroup]
207                    : this.isWebsiteAllowedToSaveCookie();
208            },
209            saveTempStorageCookies() {
210                for (const [name, data] of Object.entries(cookieTempStorage)) {
211                    if (this.isCookieAllowed(name)) {
212                        this.set(name, data['value'], data['days'], data['skipSetDomain']);
213                        delete cookieTempStorage[name];
214                    }
215                }
216            }
217        };
218
219        hyva.getCookie = (name) => {
220            const cookieConfig = window.COOKIE_CONFIG || {};
221
222            if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
223                return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null;
224            }
225
226            return internalCookie.get(name);
227        }
228
229        hyva.setCookie = (name, value, days, skipSetDomain) => {
230            const cookieConfig = window.COOKIE_CONFIG || {};
231
232            if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) {
233                cookieTempStorage[name] = {value, days, skipSetDomain};
234                return;
235            }
236            return internalCookie.set(name, value, days, skipSetDomain);
237        }
238
239
240        hyva.setSessionCookie = (name, value, skipSetDomain) => {
241            return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain)
242        }
243
244        hyva.getBrowserStorage = () => {
245            const browserStorage = window.localStorage || window.sessionStorage;
246            if (!browserStorage) {
247                console.warn('Browser Storage is unavailable');
248                return false;
249            }
250            try {
251                browserStorage.setItem('storage_test', '1');
252                browserStorage.removeItem('storage_test');
253            } catch (error) {
254                console.warn('Browser Storage is not accessible', error);
255                return false;
256            }
257            return browserStorage;
258        }
259
260        hyva.postForm = (postParams) => {
261            const form = document.createElement("form");
262
263            let data = postParams.data;
264
265            if (! postParams.skipUenc && ! data.uenc) {
266                data.uenc = btoa(window.location.href);
267            }
268            form.method = "POST";
269            form.action = postParams.action;
270
271            Object.keys(postParams.data).map(key => {
272                const field = document.createElement("input");
273                field.type = 'hidden'
274                field.value = postParams.data[key];
275                field.name = key;
276                form.appendChild(field);
277            });
278
279            const form_key = document.createElement("input");
280            form_key.type = 'hidden';
281            form_key.value = hyva.getFormKey();
282            form_key.name="form_key";
283            form.appendChild(form_key);
284
285            document.body.appendChild(form);
286
287            form.submit();
288        }
289
290        hyva.getFormKey = function () {
291            let formKey = hyva.getCookie('form_key');
292
293            if (!formKey) {
294                formKey = generateRandomString();
295                hyva.setCookie('form_key', formKey);
296            }
297
298            return formKey;
299        }
300
301        hyva.formatPrice = (value, showSign, options = {}) => {
302            const groupSeparator = options.groupSeparator;
303            const decimalSeparator = options.decimalSeparator
304            delete options.groupSeparator;
305            delete options.decimalSeparator;
306            const formatter = new Intl.NumberFormat(
307                'en\u002DUS',
308                Object.assign({
309                    style: 'currency',
310                    currency: 'GBP',
311                    signDisplay: showSign ? 'always' : 'auto'
312                }, options)
313            );
314            return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ?
315                formatter.formatToParts(value).map(({type, value}) => {
316                    switch (type) {
317                        case 'currency':
318                            return '\u00A3' || value;
319                        case 'minusSign':
320                            return '- ';
321                        case 'plusSign':
322                            return '+ ';
323                        case 'group':
324                            return groupSeparator !== undefined ? groupSeparator : value;
325                        case 'decimal':
326                            return decimalSeparator !== undefined ? decimalSeparator : value;
327                        default :
328                            return value;
329                    }
330                }).reduce((string, part) => string + part) :
331                formatter.format(value);
332        }
333
334        const formatStr = function (str, nStart) {
335            const args = Array.from(arguments).slice(2);
336
337            return str.replace(/(%+)([0-9]+)/g, (m, p, n) => {
338                const idx = parseInt(n) - nStart;
339
340                if (args[idx] === null || args[idx] === void 0) {
341                    return m;
342                }
343                return p.length % 2
344                    ? p.slice(0, -1).replace('%%', '%') + args[idx]
345                    : p.replace('%%', '%') + n;
346            })
347        }
348
349        hyva.str = function (string) {
350            const args = Array.from(arguments);
351            args.splice(1, 0, 1);
352
353            return formatStr.apply(undefined, args);
354        }
355
356        hyva.strf = function () {
357            const args = Array.from(arguments);
358            args.splice(1, 0, 0);
359
360            return formatStr.apply(undefined, args);
361        }
362
363        /**
364         * Take a html string as `content` parameter and
365         * extract an element from the DOM to replace in
366         * the current page under the same selector,
367         * defined by `targetSelector`
368         */
369        hyva.replaceDomElement = (targetSelector, content) => {
370            // Parse the content and extract the DOM node using the `targetSelector`
371            const parser = new DOMParser();
372            const doc = parser.parseFromString(content, 'text/html');
373            const contentNode = doc.querySelector(targetSelector);
374
375            // Bail if content or target can't be found
376            if (!contentNode || !document.querySelector(targetSelector)) {
377                return;
378            }
379
380                        hyva.activateScripts(contentNode);
381            
382            // Replace the old DOM node with the new content
383            document.querySelector(targetSelector).replaceWith(contentNode);
384
385            // Reload customerSectionData and display cookie-messages if present
386            window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
387            hyva.initMessages();
388        }
389
390        hyva.removeScripts = (contentNode) => {
391            const scripts = contentNode.getElementsByTagName('script');
392            for (let i = 0; i < scripts.length; i++) {
393                scripts[i].parentNode.removeChild(scripts[i]);
394            }
395            const templates = contentNode.getElementsByTagName('template');
396            for (let i = 0; i < templates.length; i++) {
397                const container = document.createElement('div');
398                container.innerHTML = templates[i].innerHTML;
399                hyva.removeScripts(container);
400                templates[i].innerHTML = container.innerHTML;
401            }
402        }
403
404        hyva.activateScripts = (contentNode) => {
405            // Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM.
406            const scripts = Array.from(contentNode.getElementsByTagName('script'));
407
408            // Iterate over all script tags to duplicate+inject each into the head
409            for (const original of scripts) {
410                const script = document.createElement('script');
411                original.type && (script.type = original.type);
412                script.innerHTML = original.innerHTML;
413
414                // Remove the original (non-executing) script from the contentNode
415                original.parentNode.removeChild(original)
416
417                // Add script to head
418                document.head.appendChild(script);
419            }
420
421            return contentNode;
422        }
423
424        const replace = {['+']: '-', ['/']: '_', ['=']: ','};
425        hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]);
426
427        let currentTrap;
428
429        const focusableElements = (rootElement) => {
430            const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]';
431            return Array.from(rootElement.querySelectorAll(selector))
432                .filter(el => {
433                    return el.style.display !== 'none'
434                        && !el.disabled
435                        && el.tabIndex !== -1
436                        && (el.offsetWidth || el.offsetHeight || el.getClientRects().length)
437                })
438        }
439
440        const focusTrap = (e) => {
441            const isTabPressed = e.key === 'Tab' || e.keyCode === 9;
442            if (!isTabPressed) return;
443
444            const focusable = focusableElements(currentTrap)
445            const firstFocusableElement = focusable[0]
446            const lastFocusableElement = focusable[focusable.length - 1]
447
448            e.shiftKey
449                ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault())
450                : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault())
451        };
452
453        hyva.releaseFocus = (rootElement) => {
454            if (currentTrap && (!rootElement || rootElement === currentTrap)) {
455                currentTrap.removeEventListener('keydown', focusTrap)
456                currentTrap = null
457            }
458        }
459        hyva.trapFocus = (rootElement) => {
460            if (!rootElement) return;
461            hyva.releaseFocus()
462            currentTrap = rootElement
463            rootElement.addEventListener('keydown', focusTrap)
464            const firstElement = focusableElements(rootElement)[0]
465            firstElement && firstElement.focus()
466        }
467
468        hyva.safeParseNumber = (rawValue) => {
469            const number = rawValue ? parseFloat(rawValue) : null;
470
471            return Array.isArray(number) || isNaN(number) ? rawValue : number;
472        }
473
474        const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join('');
475        hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => {
476
477            const camelCase = toCamelCase(name);
478            const key = '__hyva_bool_' + name
479
480            return new Proxy(Object.assign(
481                additionalMethods,
482                {
483                    [key]: !!value,
484                    [name]() {return !!this[key]},
485                    ['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine
486                    ['not' + camelCase]() {return !this[key]},
487                    ['toggle' + camelCase]() {this[key] = !this[key]},
488                    [`set${camelCase}True`]() {this[key] = true},
489                    [`set${camelCase}False`]() {this[key] = false},
490                }
491            ), {
492                set(target, prop, value) {
493                    return prop === name
494                        ? (target[key] = !!value)
495                        : Reflect.set(...arguments);
496                }
497            })
498        }
499
500                hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true})
501        window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true});
502                window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies())
503
504    }( window.hyva = window.hyva || {} ));
505</script>
vendor: 1 bytes, line 505
505
506<script nonce="dDlpdmJ2Y214eXB4aGtjOXZtenU2eWphNGp6Yzd4Nzg=">
507    if (!window.IntersectionObserver) {
508        window.IntersectionObserver = function (callback) {
509            this.observe = el => el && callback(this.takeRecords());
510            this.takeRecords = () => [{isIntersecting: true, intersectionRatio: 1}];
511            this.disconnect = () => {};
512            this.unobserve = () => {};
513        }
514    }
515</script>
vendor: 1 bytes, line 515
515
516<script src="https://www.customandcommercial.com/static/version1778675079/frontend/Actuate/c-and-c/en_US/js/swiper-bundle.min.js"></script>
516</head>
517<body id="html-body" class="wordpress-posttype-view page-layout-2columns-left">
518
519<script>
520    'use strict';
521    (function( vatSwitcher, undefined ) {
522        const defaultVatMode = 'excluding';
523
524        vatSwitcher.getVatModeFromBrowserStorage = () => {
525            const browserStorage = hyva.getBrowserStorage();
526            if (! browserStorage) {
527                console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
528                return null;
529            }
530
531            return browserStorage.getItem('vat-switch-mode');
532        }
533
534        vatSwitcher.setVatMode = (value) => {
535            const browserStorage = hyva.getBrowserStorage();
536
537            if (browserStorage) {
538                browserStorage.setItem('vat-switch-mode', value);
539            } else {
540                console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
541            }
542        }
543
544        vatSwitcher.getVatMode = () => {
545            return vatSwitcher.getVatModeFromBrowserStorage() || defaultVatMode;
546        }
547    }( window.vatSwitcher = window.vatSwitcher || {} ));
548</script>
548
549<input name="form_key" type="hidden" value="8yyKEOyvlaL6bVEW" />
550    <noscript>
551        <section class="message global noscript border-b-2 border-blue-500 bg-blue-50 shadow-none m-0 px-0 rounded-none font-normal">
552            <div class="container text-center">
553                <p>
554                    <strong>JavaScript seems to be disabled in your browser.</strong>
555                    <span>
556                        For the best experience on our site, be sure to turn on Javascript in your browser.                    </span>
557                </p>
558            </div>
559        </section>
560    </noscript>
561
562
563<script>
564    document.body.addEventListener('touchstart', () => {}, {passive: true})
565</script>
565
566
567<script data-cfasync="false">
568    window.amastyCookieManager = window.amastyCookieManager || {};
569</script>
569
570<div class="page-wrapper"><header class="page-header"><a class="action skip sr-only focus:not-sr-only focus:absolute focus:z-40 focus:bg-white
571   contentarea"
572   href="#contentarea">
573    <span>
574        Skip to Content    </span>
575</a>
576<div class="header content">
577<a x-data="initAmQuoteIcon"
578   @click.prevent.stop="toggleAmquoteEvent"
579   @private-content-loaded.window="privateContentLoadedEvent"
580   id="amquote-icon"
581   href="https://www.customandcommercial.com/request_quote/cart/"
582   class="quote-icon md:block text-center relative flex flex-col text-xs font-semibold leading-4 items-center mr-2.5">
583    <svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 44 44" width="24" height="24" class="text-white bg-ctaprimary rounded-full w-[30px] md:w-11 md:h-11 h-[30px] mb-1.5 mx-auto" role="img">
584	<defs>
585		<image width="24" height="24" id="img1" href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik02IDJMMyA2VjIwQzMgMjAuNTMwNCAzLjIxMDcxIDIxLjAzOTEgMy41ODU3OSAyMS40MTQyQzMuOTYwODYgMjEuNzg5MyA0LjQ2OTU3IDIyIDUgMjJIMTlDMTkuNTMwNCAyMiAyMC4wMzkxIDIxLjc4OTMgMjAuNDE0MiAyMS40MTQyQzIwLjc4OTMgMjEuMDM5MSAyMSAyMC41MzA0IDIxIDIwVjZMMTggMkg2WiIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgPHBhdGggZD0iTTMgNkgyMSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgogICAgPHBhdGggZD0iTTE2IDEwQzE2IDExLjA2MDkgMTUuNTc4NiAxMi4wNzgzIDE0LjgyODQgMTIuODI4NEMxNC4wNzgzIDEzLjU3ODYgMTMuMDYwOSAxNCAxMiAxNEMxMC45MzkxIDE0IDkuOTIxNzIgMTMuNTc4NiA5LjE3MTU3IDEyLjgyODRDOC40MjE0MyAxMi4wNzgzIDggMTEuMDYwOSA4IDEwIiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo="/>
586	</defs>
587	<style>
588		.s0 { fill: #e18438 } 
589	</style>
590	<path fill-rule="evenodd" class="s0" d="m22 0c12.15 0 22 9.85 22 22 0 12.15-9.85 22-22 22-12.15 0-22-9.85-22-22 0-12.15 9.85-22 22-22z"/>
591	<use id="quote" href="#img1" transform="matrix(1,0,0,1,10,10)"/>
592<title>quote</title></svg>
593    <span
594            class="font-serif inline-block text-center text-xs font-semibold text-center mx-auto tabular-nums"
595            aria-hidden="true"
596    >Quote</span>
597    <span x-text="quotecartSummaryCount"
598          class="absolute top-0 right-0 hidden h-5 px-2 py-1 -mt-5 -mr-4 text-xs font-semibold
599                        leading-none text-center text-white uppercase transform -translate-x-1
600                        translate-y-1/2 rounded-full bg-ctasecondary"
601          :class="summaryCountClass"
602    ></span>
603</a>
604
605<script>
606    'use strict';
607
608    (function () {
609        document.addEventListener('DOMContentLoaded', function () {
610            const quoteIcon = document.getElementById("amquote-icon");
611            const insertBeforeNode = document.querySelector('\u0023menu\u002Dcart\u002Dicon');
612            if (!insertBeforeNode) {
613                return;
614            }
615
616            const destination = insertBeforeNode.parentNode;
617            destination.insertBefore(quoteIcon, insertBeforeNode);
618            quoteIcon.classList.remove('hidden');
619        });
620    })()
621
622    function initAmQuoteIcon() {
623        return {
624            quotecart: {},
625
626            getData(data) {
627                if (data.quotecart) {
628                    this.quotecart = data.quotecart
629                }
630            },
631
632            summaryCountClass() {
633                return {
634                    'hidden': !this.quotecart.summary_count,
635                    'block': this.quotecart.summary_count
636                }
637            },
638
639            toggleAmquoteEvent() {
640                return this.$dispatch('toggle-amquote')
641            },
642
643            privateContentLoadedEvent(event) {
644                return this.getData(this.$event.detail.data)
645            },
646
647            quotecartSummaryCount() {
648                return this.quotecart.summary_count
649            }
650        }
651    }
652
653    window.addEventListener(
654        'alpine:init',
655        () => Alpine.data(
656            'initAmQuoteIcon',
657            initAmQuoteIcon
658        ),
659        {once: true}
660    );
661</script>
661
662<section id="quotecart-drawer"
663         x-data="initAmQuoteCartDrawer"
664         x-bind="eventListeners"
665         @private-content-loaded.window="privateContentLoadedEvent"
666         @keydown.window.escape="hideDialog">
667    <template x-if="quotecart">
668        <div role="dialog"
669             aria-labelledby="quote-cart-drawer-title"
670             aria-modal="true"
671             @click.away="hideDialog"
672             class="fixed inset-y-0 right-0 z-40 flex max-w-full">
673            <div class="backdrop"
674                 x-show="open"
675                 x-transition:enter="ease-in-out duration-500"
676                 x-transition:enter-start="opacity-0"
677                 x-transition:enter-end="opacity-100"
678                 x-transition:leave="ease-in-out duration-500"
679                 x-transition:leave-start="opacity-100"
680                 x-transition:leave-end="opacity-0"
681                 @click="hideDialog"
682                 role="button"
683                 aria-label="Close&#x20;panel"></div>
684
685            <div class="relative w-screen max-w-md shadow-2xl"
686                 x-show="open"
687                 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
688                 x-transition:enter-start="translate-x-full"
689                 x-transition:enter-end="translate-x-0"
690                 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
691                 x-transition:leave-start="translate-x-0"
692                 x-transition:leave-end="translate-x-full"
693            >
694                <div
695                    x-show="open"
696                    x-transition:enter="ease-in-out duration-500"
697                    x-transition:enter-start="opacity-0"
698                    x-transition:enter-end="opacity-100"
699                    x-transition:leave="ease-in-out duration-500"
700                    x-transition:leave-start="opacity-100"
701                    x-transition:leave-end="opacity-0" class="absolute top-0 right-0 flex p-2 mt-2">
702                    <button @click="hideDialog" aria-label="Close&#x20;panel"
703                            class="p-2 text-gray-300 transition duration-150 ease-in-out hover:text-black">
704                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
705  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
706</svg>
707                    </button>
708                </div>
709                <div class="flex flex-col h-full py-6 space-y-6 bg-white shadow-xl">
710                    
711                    <header class="px-4 sm:px-6">
712                        <h2 id="quote-cart-drawer-title" class="text-lg font-medium leading-7 text-gray-900">
713                            <span class="font-semibold">Quote Summary</span>
714                            <span class="items-total text-xs"
715                                  x-show="isItemCountShow"
716                                  x-text="getItemCountTitle"></span>
717                        </h2>
718                    </header>
719
720                    
721                    <div x-show="itemsCount" class="relative grid gap-6 px-4 py-6 overflow-y-auto bg-white border-b
722                        sm:gap-8 sm:px-6 border-container">
723                        <template x-for="item in quoteItems">
724                            <div class="flex items-start p-3 -m-3 space-x-4 transition duration-150
725                                ease-in-out rounded-lg hover:bg-gray-100">
726                                <a :href="productUrl" class="w-1/4">
727                                    <img
728                                        :src="productImageSrc"
729                                        :width="productImageWidth"
730                                        :height="productImageHeight"
731                                        :alt="productImageAlt"
732                                        loading="lazy"
733                                    />
734                                </a>
735                                <div class="w-3/4 space-y-2">
736                                    <div>
737                                        <p class="text-xl">
738                                            <span x-html="itemQty"></span> x <span x-html="productName"></span>
739                                        </p>
740
741                                        <p class="text-sm"><span x-html="productSku"></span></p>
742                                    </div>
743
744                                    <template x-for="option in itemOptions">
745                                        <div class="pt-2">
746                                            <p class="font-semibold" x-text="optionLabel"></p>
747                                            <p class="text-secondary" x-html="optionValue"></p>
748                                        </div>
749                                    </template>
750                                    <p><span x-html="productPrice"></span></p>
751                                    <div class="333 pt-4 quote-buttons">
752                                        <a :href="configureUrl"
753                                           x-show="isProductNotGrouped"
754                                           class="inline-flex p-2 mr-2 btn btn-primary">
755                                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" role="img">
756  <path stroke-linecap="round" stroke-linejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
757<title>pencil</title></svg>
758                                            <span class="sr-only">Edit&#x20;item</span>
759                                        </a>
760                                        <button class="inline-flex p-2 btn btn-primary"
761                                                @click="removeItem">
762                                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" role="img">
763  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
764<title>trash</title></svg>
765                                            <span class="sr-only">Remove&#x20;item</span>
766                                        </button>
767                                    </div>
768
769                                </div>
770                            </div>
771                        </template>
772                    </div>
773
774                    
775                    <div x-show="itemsCount" class="relative grid gap-6 px-4 py-6 bg-white sm:gap-8 sm:px-6">
776                        <div class="w-full p-3 -m-3 space-x-4 transition duration-150 ease-in-out rounded-lg
777                            hover:bg-gray-100">
778                            <p>Subtotal: <span x-html="quotecartSubtotal"></span></p>
779                        </div>
780                        <div class="flex justify-center w-full p-3 -m-3 space-x-4 transition duration-150 ease-in-out
781                            rounded-lg hover:bg-gray-100">
782                            <a @click.prevent.stop="quoteCart"
783                               data-url="https://www.customandcommercial.com/amasty_quote/cart/"
784                               href="https://www.customandcommercial.com/amasty_quote/cart/"
785                               class="inline-flex btn btn-primary">
786                                My Quote Cart                            </a>
787                        </div>
788                                            </div>
789
790                    <template x-if="quoteIsEmpty">
791                        <div class="relative px-4 py-6 bg-white border-bs sm:px-6 border-container">
792                            Quote is empty                        </div>
793                    </template>
794
795                                    </div>
796            </div>
797            <div
798    class="z-50 fixed inset-0 grid place-items-center bg-white/70 text-slate-800"
799    x-cloak
800    x-show="isLoading"
801    x-transition.opacity.duration.200ms
802>
803    <div class="flex gap-10 items-center p-4">
804        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="57" height="57" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
805    <style>
806        @keyframes spinner-ball-triangle1 {
807            0% { transform: translate(0%, 0%); }
808            33% { transform: translate(38%, -79%); }
809            66% { transform: translate(77%, 0%); }
810            100% { transform: translate(0%, 0%); }
811        }
812
813        @keyframes spinner-ball-triangle2 {
814            0% { transform: translate(0%, 0%); }
815            33% { transform: translate(38%, 79%); }
816            66% { transform: translate(-38%, 79%); }
817            100% { transform: translate(0%, 0%); }
818        }
819
820        @keyframes spinner-ball-triangle3 {
821            0% { transform: translate(0%, 0%); }
822            33% { transform: translate(-77%, 0%); }
823            66% { transform: translate(-38%, -79%); }
824            100% { transform: translate(0%, 0%); }
825        }
826    </style>
827    <circle cx="5" cy="50" r="5" style="animation: spinner-ball-triangle1 2.2s linear infinite"/>
828    <circle cx="27" cy="5" r="5" style="animation: spinner-ball-triangle2 2.2s linear infinite"/>
829    <circle cx="49" cy="50" r="5" style="animation: spinner-ball-triangle3 2.2s linear infinite"/>
830</svg>
831        <span class="text-xl select-none">
832            Loading...        </span>
833    </div>
834</div>
835        </div>
836    </template>
837</section>
838
839<script>
840    function initAmQuoteCartDrawer() {
841        return {
842            open: false,
843            isLoading: false,
844            quotecart: {},
845            maxItemsToDisplay: 10,
846            itemsCount: 0,
847            totalCartAmount: 0,
848
849            getData(data) {
850                if (data.quotecart) {
851                    this.quotecart = data.quotecart;
852                    this.itemsCount = data.quotecart.items && data.quotecart.items.length || 0;
853                    this.totalCartAmount = this.quotecart.summary_count;
854                    this.setQuoteItems();
855                }
856                this.isLoading = false;
857            },
858
859            quoteItems: [],
860
861            getItemCountTitle() {
862                return hyva.strf('(%0 of %1)', this.maxItemsToDisplay, this.itemsCount)
863            },
864
865            setQuoteItems() {
866                this.quoteItems = this.quotecart.items && this.quotecart.items.sort((a, b) => b.item_id - a.item_id) || [];
867
868                if (this.maxItemsToDisplay > 0) {
869                    this.quoteItems = this.quoteItems.slice(0, parseInt(this.maxItemsToDisplay, 10));
870                }
871            },
872
873            deleteItemFromQuote(itemId) {
874                this.isLoading = true;
875
876                const formKey = hyva.getFormKey();
877                const postUrl = BASE_URL + 'amasty_quote/sidebar/removeItem/';
878
879                fetch(postUrl, {
880                    "headers": {
881                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
882                    },
883                    "body": "form_key=" + formKey + "&item_id=" + itemId,
884                    "method": "POST",
885                    "mode": "cors",
886                    "credentials": "include"
887                }).then(response => {
888                    if (response.redirected) {
889                        window.location.href = response.url;
890                    } else if (response.ok) {
891                        return response.json();
892                    } else {
893                        window.dispatchMessages && window.dispatchMessages([{
894                            type: 'warning',
895                            text: 'Could\u0020not\u0020remove\u0020item\u0020from\u0020quote.'
896                        }]);
897                        this.isLoading = false;
898                    }
899                }).then(result => {
900                    window.dispatchMessages && window.dispatchMessages([{
901                        type: result.success ? 'success' : 'error',
902                        text: result.success
903                            ? 'You\u0020removed\u0020the\u0020item.'
904                            : result.error_message
905                    }], result.success ? 5000 : 0)
906                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
907                });
908            },
909
910            quoteIsEmpty() {
911                return !this.itemsCount
912            },
913
914            productImageAlt() {
915                return this.item.product_image.alt
916            },
917
918            openDialog() {
919                return this.open = true
920            },
921
922            hideDialog() {
923                return this.open = false
924            },
925
926            removeItem() {
927                return this.deleteItemFromQuote(this.item.item_id)
928            },
929
930            quoteCart() {
931                this.$dispatch(
932                    'toggle-authentication',
933                    {
934                        url: `${this.$el.dataset.url}`
935                    }
936                );
937            },
938
939            itemOptions() {
940                return this.item.options
941            },
942
943            productImageHeight() {
944                return this.item.product_image.height
945            },
946
947            productUrl() {
948                return this.item.product_url
949            },
950
951            configureUrl() {
952                return this.item.configure_url
953            },
954
955            itemQty() {
956                return this.item.qty
957            },
958
959            productName() {
960                return this.item.product_name
961            },
962
963            productSku() {
964                return this.item.product_sku
965            },
966
967            optionValue() {
968                return this.option.value
969            },
970
971            productPrice() {
972                return this.item.product_price
973            },
974
975            quotecartSubtotal() {
976                return this.quotecart.subtotal
977            },
978
979            privateContentLoadedEvent(event) {
980                return this.getData(this.$event.detail.data)
981            },
982
983            isItemCountShow() {
984                return this.maxItemsToDisplay && this.maxItemsToDisplay < this.itemsCount
985            },
986
987            isProductNotGrouped() {
988                return this.item.product_type !== 'grouped'
989            },
990
991            productImageSrc() {
992                return this.item.product_image.src
993            },
994
995            optionLabel() {
996                return this.option.label + ':'
997            },
998
999            productImageWidth() {
1000                return this.item.product_image.width
1001            },
1002
1003            eventListeners: {
1004                ['@toggle-amquote.window']() {
1005                    this.openDialog();
1006                }
1007            }
1008        }
1009    }
1010
1011    window.addEventListener(
1012        'alpine:init',
1013        () => Alpine.data(
1014            'initAmQuoteCartDrawer',
1015            initAmQuoteCartDrawer
1016        ),
1017        {once: true}
1018    );
1019</script>
1019
1020</div>
1020<script>
1021    function initHeader() {
1022        return {
1023            vatMode: vatSwitcher.getVatMode() || 'excluding',
1024            searchOpen: false,
1025            cart: {},
1026            isCartOpen: false,
1027            isMobile: true,
1028            prevScroll: 0, // Tracks the previous scroll position
1029            visible: true, // Tracks header visibility
1030            init() {
1031                this.checkIsSearchMobile();
1032
1033                // Initialize scroll listener for header visibility
1034                this.prevScroll = window.pageYOffset || document.documentElement.scrollTop;
1035                window.addEventListener('scroll', this.handleScroll.bind(this));
1036
1037                // Initialize header height sync
1038                this.updatePageHeaderHeight();
1039                window.addEventListener('resize', this.updatePageHeaderHeight.bind(this));
1040            },
1041            handleScroll() {
1042                const currentScroll = window.pageYOffset || document.documentElement.scrollTop;
1043
1044                // Show header when scrolling up by more than 5px
1045                if (this.prevScroll - currentScroll > 5) {
1046                    this.visible = true;
1047                }
1048                // Hide header when scrolling down
1049                else if (currentScroll > 100 && (currentScroll - this.prevScroll > 5)) {
1050                    this.visible = false;
1051                }
1052
1053                this.prevScroll = currentScroll;
1054            },
1055            updatePageHeaderHeight() {
1056                // Get the height of #header
1057                const headerHeight = this.$el.offsetHeight;
1058
1059                // Apply the height to the page header
1060                const pageHeader = document.querySelector('header.page-header');
1061                if (pageHeader) {
1062                    pageHeader.style.height = `${headerHeight}px`;
1063                }
1064
1065                this.checkIsSearchMobile();
1066            },
1067            getData(data) {
1068                if (data.cart) {
1069                    this.cart = data.cart;
1070                }
1071            },
1072            isCartEmpty() {
1073                return !this.cart.summary_count;
1074            },
1075            checkIsSearchMobile() {
1076                const {
1077                    searchContainerMobile: mobileEl,
1078                    searchContainerDesktop: desktopEl,
1079                    searchForm
1080                } = this.$refs;
1081
1082                if (!searchForm) return;
1083
1084                // Detect mobile
1085                const isMobile = mobileEl
1086                    ? getComputedStyle(mobileEl).display !== 'none'
1087                    : window.matchMedia('(max-width: 1023px)').matches;
1088
1089                this.isMobile = isMobile;
1090
1091                const targetContainer = isMobile ? mobileEl : desktopEl;
1092
1093                if (!targetContainer) return;
1094
1095                // Move only if not already inside target
1096                if (!targetContainer.contains(searchForm)) {
1097                    targetContainer.appendChild(searchForm);
1098                }
1099            },
1100            toggleCart(event) {
1101                if (event.detail && event.detail.isOpen !== undefined) {
1102                    this.isCartOpen = event.detail.isOpen;
1103                    if (!this.isCartOpen && this.$refs && this.$refs.cartButton) {
1104                        this.$refs.cartButton.focus();
1105                    }
1106                } else {
1107                    this.isCartOpen = true;
1108                }
1109            },
1110            eventListeners: {
1111                ['@private-content-loaded.window'](event) {
1112                    this.getData(event.detail.data);
1113                },
1114                ['@resize.window.debounce']() {
1115                    this.checkIsSearchMobile();
1116                },
1117                ['@visibilitychange.window.debounce']() {
1118                    this.checkIsSearchMobile();
1119                },
1120                ['@update-minicart-vat-mode.window'](event) {
1121                    this.vatMode = event.detail;
1122                },
1123            },
1124        };
1125    }
1126
1127    function initCompareHeader() {
1128        return {
1129            compareProducts: null,
1130            itemCount: 0,
1131            receiveCompareData(data) {
1132                if (data['compare-products']) {
1133                    this.compareProducts = data['compare-products'];
1134                    this.itemCount = this.compareProducts.count;
1135                }
1136            }
1137        }
1138    }
1139</script>
1139
1140<div id="header"
1141     class="bg-white transition-transform duration-300 ease-in-out fixed top-0 left-0 w-full z-[10]"
1142     x-data="initHeader()"
1143     x-bind="eventListeners"
1144     x-init="init()"
1145     :class="{'-translate-y-full': !visible}"
1146     @private-content-loaded.window="getData(event.detail.data)"
1147>
1148        <div class="header-notification">
1149        <div class="liveview-content"
1150    data-liveview-content
1151        >
1152                        <div data-liveview-element="row"
1153    class="not-prose"
1154            >
1155                        <div
1156    data-liveview-element="text"
1157    class="cmsb18-text-center cmsb18-text-sm cmsb18-font-normal"
1158            >
1159    <p>Sign Up To Our News Letter For All The Latest New Products</p></div>
1160            </div>
1161            </div>
1162    </div>
1163    <div class="header-info">
1164        <div class="container py-3.5 flex gap-4 items-center">
1165            <div class="header-contact">
1166                <ul>
1167                    <li><a href="mailto:[email protected]">[email protected]</a></li>
1168                </ul>
1169            </div>
1170            <div class="quick-links">
1171                <ul>
1172                    <li><a href="/kits.html">Kits</a></li>
1173                    <li><a href="/clearance.html">Clearance</a></li>
1174                    <li><a href="https://www.customandcommercial.com/line-drawings/">Line Drawings</a></li>
1175                    <li><a href="https://www.customandcommercial.com/lock-shop/">Lock Shop</a></li>
1176                    <li><a href="https://www.customandcommercial.com/vwshows/">Shows</a></li>
1177                    <li><a href="https://www.customandcommercial.com/contact/">Contact</a></li>
1178                </ul>
1179            </div>
1180        </div>
1181    </div>
1182    <div class="container relative py-2.5 lg:py-3.5 flex gap-4 md:items-center">
1183        
1184<a
1185    class="inline-block align-middle w-4/12 lg:w-2/12 xl:w-3/12"
1186    href="https://www.customandcommercial.com/"
1187    title="Go&#x20;to&#x20;Home&#x20;page"
1188>
1189            <img
1190            src="https://www.customandcommercial.com/media/logo/stores/1/PHOTO-2026-08-28-14-28-43_2_.jpg"
1191            alt="Custom&#x20;&amp;&#x20;Commercial"
1192            width="700"
1193            height="400"
1194            loading="eager"
1195            fetchpriority="high"
1196        >
1197    </a>
1198        <div x-ref="searchContainerDesktop" class="hidden lg:block xl:w-5/12 lg:ml-auto min-h-a11y px-6"></div>
1199        <div class="ml-auto flex gap-0.5 w-9/12 lg:w-4/12 justify-end max767:flex-wrap md:items-center">
1200            <div class="max767:hidden vat-switcher-block-header max767:my-5 max767:order-5 lg:relative lg:top-0 lg:inline-block lg:text-bodydark">
1201                <div x-data="initVatSwitcher()" x-bind="eventListeners" class="vat-toggle-container mr-1.5 lg:mr-7">
1202    <div class="vat-label"><span>Exc. Vat</span></div>
1203    <label class="toggle-switch">
1204        <input type="checkbox" x-on:change="toggleVatMode(event)" x-model="isChecked" />
1205        <span class="slider"></span>
1206    </label>
1207    <div class="vat-label"><span>Inc. Vat</span></div>
1208</div>
1209
1210<script>
1211    function initVatSwitcher() {
1212        const [excluding, including] = Object.keys({"excluding":"Excl. VAT","including":"Incl. VAT"});
1213
1214        return {
1215            isChecked: vatSwitcher.getVatMode() === including,
1216
1217            toggleVatMode(event) {
1218                const value = event.target.checked ? including : excluding;
1219                this.setVatMode(value);
1220
1221                const isCategoryPage = document.body.classList.contains('catalog-category-view')
1222                    || document.body.classList.contains('sales-order-invoice')
1223                    || document.body.classList.contains('sales-order-view');
1224                (isCategoryPage ? this.dispatchUpdate : this.updateVisibility).call(this, value);
1225
1226                const isProductPage = document.body.classList.contains('catalog-product-view');
1227                if (isProductPage) {
1228                    window.dispatchEvent(new CustomEvent('update-product-vat-switcher', { detail: value }));
1229                    this.updateVisibility(value);
1230                }
1231
1232                const isLineDrawingCategory = document.body.classList.contains('line-drawing-layout')
1233                if (isLineDrawingCategory) {
1234                    this.updateVisibility(value);
1235                }
1236                window.dispatchEvent(new CustomEvent('update-minicart-vat-mode', { detail: value }));
1237                window.dispatchEvent(new CustomEvent('update-cart-drawer-vat-mode', { detail: value }));
1238            },
1239
1240            updateVatMode(value) {
1241                this.isChecked = value === including;
1242                this.updateVisibility(value);
1243            },
1244
1245            setVatMode(value) {
1246                vatSwitcher.setVatMode(value);
1247            },
1248
1249            dispatchUpdate(value) {
1250                window.dispatchEvent(new CustomEvent('update-toolbar-vat-switcher', { detail: value }));
1251            },
1252
1253            updateVisibility(value) {
1254                const toggleVisibility = (taxType, action) => {
1255                    document.querySelectorAll(`.price-${taxType}-tax`).forEach(el => el.classList[action]('hidden'));
1256                };
1257
1258                toggleVisibility(value === including ? excluding : including, 'add');
1259                toggleVisibility(value, 'remove');
1260            },
1261            eventListeners: {
1262                ['@update-vat-switcher.window'](event) {
1263                    this.updateVatMode(event.detail);
1264                }
1265            }
1266        };
1267    }
1268</script>
1268
1269            </div>
1270                        <!--Customer Icon & Dropdown-->
1271            <!-- BLOCK header.customer -->
1272<div
1273    class="relative inline-block"
1274    x-data="{ open: false }"
1275    @keyup.escape="open = false"
1276    @click.outside="open = false"
1277>
1278    <button
1279        type="button"
1280        id="customer-menu"
1281        class="block flex flex-col text-xs font-semibold leading-4"
1282        @click="open = !open"
1283        :aria-expanded="open ? 'true' : 'false'"
1284        aria-label="Account&#x20;Dashboard"
1285        aria-haspopup="true"
1286    >
1287        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 44 44" fill="none" class="text-white bg-ctaprimary rounded-full w-[30px] md:w-11 md:h-11 h-[30px] mb-1.5 mx-auto" aria-hidden="true">
1288<rect width="44" height="44" rx="22" fill="#E18438"/>
1289<path d="M25.75 16C25.75 16.9946 25.3549 17.9484 24.6516 18.6517C23.9484 19.3549 22.9945 19.75 22 19.75C21.0054 19.75 20.0516 19.3549 19.3483 18.6517C18.6451 17.9484 18.25 16.9946 18.25 16C18.25 15.0054 18.6451 14.0516 19.3483 13.3483C20.0516 12.6451 21.0054 12.25 22 12.25C22.9945 12.25 23.9484 12.6451 24.6516 13.3483C25.3549 14.0516 25.75 15.0054 25.75 16ZM14.501 30.118C14.5331 28.1504 15.3373 26.2742 16.7402 24.894C18.143 23.5139 20.0321 22.7405 22 22.7405C23.9679 22.7405 25.857 23.5139 27.2598 24.894C28.6626 26.2742 29.4668 28.1504 29.499 30.118C27.1464 31.1968 24.5881 31.7535 22 31.75C19.324 31.75 16.784 31.166 14.501 30.118Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1290</svg>
1291 <span class="font-serif inline-block">Account</span>
1292    </button>
1293    <nav
1294        class="absolute right-0 z-20 w-40 py-2 mt-2 -mr-4 px-1 overflow-auto origin-top-right rounded-sm
1295            shadow-lg sm:w-48 lg:mt-3 bg-container-lighter"
1296        x-cloak
1297        x-show="open"
1298        x-transition
1299        aria-labelledby="customer-menu"
1300    >
1301                    
1302<a id="customer.header.sign.in.link"
1303   class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100"
1304   onclick="hyva.setCookie && hyva.setCookie(
1305       'login_redirect',
1306       window.location.href,
1307       1
1308   )"
1309   href="https://www.customandcommercial.com/customer/account/index/"
1310   title="Sign&#x20;In"
1311>
1312    Sign In</a>
1313
1314    <a id="customer.header.register.link"
1315       class="block px-4 py-2 lg:px-5 lg:py-2 hover:bg-gray-100"
1316       href="https://www.customandcommercial.com/customer/account/create/"
1317       title="Create&#x20;an&#x20;Account"
1318    >
1319        Create an Account    </a>
1320            </nav>
1321</div>
1322<!-- /BLOCK header.customer -->            <!-- Additional Header Elements -->
1323                        <!-- Wishlist not showing needs fixing -->
1324            
1325            <a
1326                id="wishlist-link"
1327                class="block flex flex-col text-xs font-semibold leading-4 items-center mx-2.5"
1328                href="https://www.customandcommercial.com/wishlist/"
1329                title="Wishlist"
1330            >
1331                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 44 44" fill="none" class="text-white bg-ctaprimary rounded-full w-[30px] md:w-11 md:h-11 h-[30px] mb-1.5 mx-auto" role="img">
1332<rect width="44" height="44" rx="22" fill="#E18438"/>
1333<path d="M31 18.25C31 15.765 28.901 13.75 26.312 13.75C24.377 13.75 22.715 14.876 22 16.483C21.285 14.876 19.623 13.75 17.687 13.75C15.1 13.75 13 15.765 13 18.25C13 25.47 22 30.25 22 30.25C22 30.25 31 25.47 31 18.25Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1334<title>wishlist</title></svg>
1335                <span
1336                        class="font-serif inline-block text-center text-xs font-semibold text-center mx-auto tabular-nums"
1337                        aria-hidden="true"
1338                >Wishlist</span>
1339            </a>
1340
1341            <!--Cart Icon-->
1342                            <button
1343                            id="menu-cart-icon"
1344                class="block flex flex-col text-xs font-semibold leading-4 items-center"
1345                x-ref="cartButton"
1346                :aria-disabled="isCartEmpty()"
1347                :aria-label="`
1348                    Toggle&#x20;minicart,
1349                    ${isCartEmpty()
1350                        ? 'Cart&#x20;is&#x20;empty'
1351                        : cart.summary_count > 1
1352                            ? hyva.str('&#x25;1&#x20;items', cart.summary_count)
1353                            : hyva.str('&#x25;1&#x20;item', cart.summary_count)
1354                    }`"
1355                                    @click.prevent.stop="() => {
1356                        $dispatch('toggle-cart', { isOpen: true })
1357                    }"
1358                    @toggle-cart.window="toggleCart($event)"
1359                    :aria-expanded="isCartOpen"
1360                    aria-haspopup="dialog"
1361                            >
1362                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 25 24" fill="none" class="text-white bg-ctaprimary rounded-full p-1.5 w-[30px] h-[30px] md:w-11 md:h-11 mb-1.5 mx-auto" aria-hidden="true">
1363<path d="M16.25 10.5V6C16.25 5.00544 15.8549 4.05161 15.1516 3.34835C14.4484 2.64509 13.4945 2.25 12.5 2.25C11.5054 2.25 10.5516 2.64509 9.84833 3.34835C9.14507 4.05161 8.74998 5.00544 8.74998 6V10.5M20.106 8.507L21.369 20.507C21.439 21.172 20.919 21.75 20.25 21.75H4.74998C4.59219 21.7502 4.43613 21.7171 4.29193 21.6531C4.14774 21.589 4.01863 21.4953 3.91301 21.3781C3.80738 21.2608 3.7276 21.1227 3.67884 20.9726C3.63008 20.8226 3.61343 20.6639 3.62999 20.507L4.89399 8.507C4.92314 8.23056 5.05361 7.9747 5.26024 7.78876C5.46686 7.60281 5.73501 7.49995 6.01298 7.5H18.987C19.563 7.5 20.046 7.935 20.106 8.507ZM9.12498 10.5C9.12498 10.5995 9.08548 10.6948 9.01515 10.7652C8.94482 10.8355 8.84944 10.875 8.74998 10.875C8.65053 10.875 8.55515 10.8355 8.48482 10.7652C8.41449 10.6948 8.37498 10.5995 8.37498 10.5C8.37498 10.4005 8.41449 10.3052 8.48482 10.2348C8.55515 10.1645 8.65053 10.125 8.74998 10.125C8.84944 10.125 8.94482 10.1645 9.01515 10.2348C9.08548 10.3052 9.12498 10.4005 9.12498 10.5ZM16.625 10.5C16.625 10.5995 16.5855 10.6948 16.5152 10.7652C16.4448 10.8355 16.3494 10.875 16.25 10.875C16.1505 10.875 16.0551 10.8355 15.9848 10.7652C15.9145 10.6948 15.875 10.5995 15.875 10.5C15.875 10.4005 15.9145 10.3052 15.9848 10.2348C16.0551 10.1645 16.1505 10.125 16.25 10.125C16.3494 10.125 16.4448 10.1645 16.5152 10.2348C16.5855 10.3052 16.625 10.4005 16.625 10.5Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1364</svg>
1365                <span
1366                    class="lg:inline-block text-center uppercase font-serif text-xs font-semibold leading-4 tabular-nums text-center"
1367                    aria-hidden="true"
1368                >
1369                    <template x-if="cart.subtotal !== undefined">
1370                        <div x-html="vatMode === 'excluding' ? cart.subtotal_excl_tax : cart.subtotal_incl_tax"></div>
1371                    </template>
1372                    <template x-if="cart.subtotal === undefined">
1373                        <span><span class="price" x-text="hyva.formatPrice(0)"></span></span>
1374                    </template>
1375                </span>
1376                            </button>
1377                        <!--Mobile Navigation-->
1378            
1379    
1379<script>
1380        'use strict';
1381
1382        const initMenuMobile_6ab315cb956cb = () => ({
1383            open: false,
1384            openMenu(event) {
1385                this.open = true
1386                this.$nextTick(() => hyva.trapFocus(this.$refs['menu-dialog']))
1387                // Prevent from body scrolling while mobile menu opened
1388                document.body.classList.add('fixed', 'w-full', 'menu-shown')
1389            },
1390            closeMenu(event) {
1391                event.stopPropagation()
1392                document.body.classList.remove('fixed', 'w-full', 'menu-shown')
1393                this.open = false
1394                window.dispatchEvent(new CustomEvent('reset-menu'));
1395                this.$nextTick(() => this.$refs['open-menu-button'].focus() || hyva.releaseFocus())
1396            },
1397            toggleSubmenu(index) {
1398                this[index] = !this[index]
1399
1400                if (this[index]) {
1401                    const focusableElements = 'button:not([disabled]), a[href]:not([tabindex="-1"]), [tabindex]:not([tabindex="-1"])'
1402                    this.$nextTick(() => {
1403                        this.$refs['submenu-' + index]?.querySelector(focusableElements)?.focus()
1404                    })
1405                }
1406            },
1407        })
1408    </script>
1408
1409    <nav
1410        class="
1411                        snowdog-topmenu-mobile z-20 order-2 ml-2.5 text-primary-darker sm:order-1 navigation lg:hidden
1412        "
1413        x-data="initMenuMobile_6ab315cb956cb()"
1414        @keydown.escape="open && closeMenu"
1415        @click.outside="open && closeMenu"
1416        aria-label="Main&#x20;menu"
1417        role="navigation"
1418    >
1419        <button x-ref="open-menu-button"
1420                @click="openMenu"
1421                x-show="!open"
1422                type="button"
1423                aria-label="Open&#x20;menu"
1424                :aria-expanded="open"
1425                aria-haspopup="menu"
1426        >
1427            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="text-white bg-ctaprimary rounded-full p-1.5 w-[30px] h-[30px] md:w-11 md:h-11 mx-auto" width="24" height="24" aria-hidden="true">
1428  <path stroke-linecap="round" stroke-linejoin="round" d="M4 6h16M4 12h16M4 18h16"/>
1429</svg>
1430            <span class="font-serif inline-block text-center text-xs font-semibold text-center mx-auto tabular-nums">
1431                Menu            </span>
1432        </button>
1433        <div x-show="open"
1434             x-cloak
1435             class="flex justify-end border-b border-white bg-white h-full">
1436            <button
1437                    @click="closeMenu"
1438                    class="flex items-center flex-col h-full justify-between"
1439                    aria-label="Close&#x20;menu"
1440                    type="button"
1441            >
1442                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 30 30" fill="none" class="w-[30px] h-[30px] md:w-11 md:h-11 " role="img">
1443<rect width="30" height="30" rx="15" fill="#48321F"/>
1444<path d="M10 20L20 10M10 10L20 20" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
1445<title>menu-close</title></svg>
1446                <span class="font-serif inline-block text-center text-xs font-semibold text-center mx-auto tabular-nums">
1447                    Close                </span>
1448            </button>
1449        </div>
1450        <div class="backdrop"
1451            x-show="open"
1452            x-transition:enter="ease-in-out duration-500"
1453            x-transition:enter-start="opacity-0"
1454            x-transition:enter-end="opacity-100"
1455            x-transition:leave="ease-in-out duration-500"
1456            x-transition:leave-start="opacity-100"
1457            x-transition:leave-end="opacity-0"
1458            @click="closeMenu"
1459            x-cloak
1460        ></div>
1461        <div class="menu-content fixed z-30 top-0 left-0 w-full max-w-lg h-full bg-lightorange overflow-y-auto overflow-x-hidden sm:transform sm:transition sm:ease-in-out sm:duration-700"
1462            :class="{
1463                '-translate-x-full' : !open,
1464                'translate-x-0 shadow-2xl' : open,
1465            }"
1466            x-cloak
1467            x-ref="menu-dialog"
1468            role="dialog"
1469            aria-modal="true"
1470            aria-label="Main&#x20;menu"
1471            :aria-hidden="open ? 'false' : 'true'"
1472        >
1473            <div x-show="open"
1474                class="flex flex-col-reverse"
1475            >
1476                <ul class="static-links">
1477                    <li class="level-1 !bg-lightorange">
1478                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/kits.html">Kits</a>
1479                    </li>
1480                    <li class="level-1 !bg-lightorange">
1481                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/line-drawings/">Line Drawings</a>
1482                    </li>
1483                    <li class="level-1 !bg-lightorange">
1484                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/lock-shop/">Lock Shop</a>
1485                    </li>
1486                    <li class="level-1 !bg-lightorange">
1487                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/vwshows/">Shows</a>
1488                    </li>
1489                    <li class="level-1 !bg-lightorange">
1490                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/contact/">Contact</a>
1491                    </li>
1492                    <li class="level-1 !bg-lightorange">
1493                        <a class="flex !text-bodydark !normal-case items-center w-full !no-underline" href="https://www.customandcommercial.com/wishlist/">Wishlist</a>
1494                    </li>
1495                </ul>
1496                <ul>
1497                                                                    <li x-data="{'node95': false }"
1498                            @reset-menu.window="node95 = false"
1499                            class="level-1  "
1500                        >
1501                                                            <div class="group">
1502                                    <a href="https://www.customandcommercial.com/brazilian-s
1502plitscreen.html"
1503    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1504            data-menu="menu-95"
1505    >
1506    Brazilian Splitscreen</a>
1507                                </div>
1508                                                    </li>
1509                                                                    <li x-data="{'node97': false }"
1510                            @reset-menu.window="node97 = false"
1511                            class="level-1  "
1512                        >
1513                                                            <div class="group">
1514                                    <a href="https://www.customandcommercial.com/split-screen.html"
1515    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1516            data-menu="menu-97"
1517    >
1518    Split Screen</a>
1519                                </div>
1520                                                    </li>
1521                                                                    <li x-data="{'node98': false }"
1522                            @reset-menu.window="node98 = false"
1523                            class="level-1  "
1524                        >
1525                                                            <div class="group">
1526                                    <a href="https://www.customandcommercial.com/beetle.html"
1527    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1528            data-menu="menu-98"
1529    >
1530    Beetle</a>
1531                                </div>
1532                                                    </li>
1533                                                                    <li x-data="{'node99': false }"
1534                            @reset-menu.window="node99 = false"
1535                            class="level-1  "
1536                        >
1537                                                            <div class="group">
1538                                    <a href="https://www.customandcommercial.com/baywindow.html"
1539    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1540            data-menu="menu-99"
1541    >
1542    Baywindow</a>
1543                                </div>
1544                                                    </li>
1545                                                                    <li x-data="{'node100': false }"
1546                            @reset-menu.window="node100 = false"
1547                            class="level-1  "
1548                        >
1549                                                            <div class="group">
1550                                    <a href="https://www.customandcommercial.com/brazilian-bay.html"
1551    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1552            data-menu="menu-100"
1553    >
1554    Brazilian Bay</a>
1555                                </div>
1556                                                    </li>
1557                                                                    <li x-data="{'node101': false }"
1558                            @reset-menu.window="node101 = false"
1559                            class="level-1  "
1560                        >
1561                                                            <div class="group">
1562                                    <a href="https://www.customandcommercial.com/type-25.html"
1563    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1564            data-menu="menu-101"
1565    >
1566    Type 25</a>
1567                                </div>
1568                                                    </li>
1569                                                                    <li x-data="{'node102': false }"
1570                            @reset-menu.window="node102 = false"
1571                            class="level-1  "
1572                        >
1573                                                            <div class="group">
1574                                    <a href="https://www.customandcommercial.com/type-3.html"
1575    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1576            data-menu="menu-102"
1577    >
1578    Type 3 </a>
1579                                </div>
1580                                                    </li>
1581                                                                    <li x-data="{'node106': false }"
1582                            @reset-menu.window="node106 = false"
1583                            class="level-1  "
1584                        >
1585                                                            <div class="group">
1586                                    <a href="https://www.customandcommercial.com/t4.html"
1587    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1588            data-menu="menu-106"
1589    >
1590    T4</a>
1591                                </div>
1592                                                    </li>
1593                                                                    <li x-data="{'node107': false }"
1594                            @reset-menu.window="node107 = false"
1595                            class="level-1  "
1596                        >
1597                                                            <div class="group">
1598                                    <a href="https://www.customandcommercial.com/t5.html"
1599    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1600            data-menu="menu-107"
1601    >
1602    T5</a>
1603                                </div>
1604                                                    </li>
1605                                                                    <li x-data="{'node103': false }"
1606                            @reset-menu.window="node103 = false"
1607                            class="level-1  "
1608                        >
1609                                                            <div class="group">
1610                                    <a href="https://www.customandcommercial.com/karmann-ghia.html"
1611    class="cursor-pointer snowdog-menu-link-topmenu-mobile "
1612            data-menu="menu-103"
1613    >
1614    Karmann Ghia </a>
1615                                </div>
1616                                                    </li>
1617                                    </ul>
1618                <div class="max767:hidden md:flex justify-end border-b border-white bg-white">
1619                    <button
1620                        @click="closeMenu"
1621                        class="flex justify-center items-center w-16 h-16"
1622                        aria-label="Close&#x20;menu"
1623                        type="button"
1624                    >
1625                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" aria-hidden="true">
1626  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
1627</svg>
1628                    </button>
1629                </div>
1630            </div>
1631        </div>
1632    </nav>
1633        </div>
1634    </div>
1635
1636    <div class="bg-white lg:bg-darkbrown">
1637        <div class="relative container hidden lg:block">
1638            
1639    
1639<script>
1640        'use strict';
1641
1642        const initTopmenuDesktop_6ab315cb99e0c = () => ({
1643            openSubmenuId: null,
1644            toggleSubmenu(menuNode) {
1645                if (menuNode === this.openSubmenuId) {
1646                    this.openSubmenuId = null
1647                    hyva.releaseFocus()
1648                } else {
1649                    this.openSubmenuId = menuNode
1650                    this.$nextTick(() => {
1651                        hyva.trapFocus(this.$refs['submenu-' + menuNode])
1652                    })
1653                }
1654            },
1655            onSubmenuEscape(event) {
1656                event.stopPropagation()
1657                this.$refs['sr-button-' + this.openSubmenuId]?.focus()
1658                this.openSubmenuId = null
1659            }
1660        })
1661    </script>
1661
1662
1663    <div x-data="initTopmenuDesktop_6ab315cb99e0c()"
1664        class="
1665                        navigation hidden w-full lg:block
1666        "
1667    >
1668        <nav
1669            class="snowdog-topmenu-desktop container lg:block"
1670            aria-label="Main&#x20;menu"
1671        >
1672            <ul
1673                class="relative flex justify-between h-12 font-serif"
1674                @mouseleave="openSubmenuId = null"
1675            >
1676                                                        <li class="
1677                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1678                                                    "
1679                        :class="{
1680                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '85'
1681                        }"
1682                        @mouseenter="openSubmenuId = '85'"
1683                        @keydown.escape="onSubmenuEscape"
1684                    >
1685                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1686                            
1687<a href="https://www.customandcommercial.com/brazilian-splitscreen.html"
1688    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1689            data-menu="menu-85"
1690    >
1691    Brazilian Splitscreen</a>
1692                        </div>
1693                                                                    </li>
1694                                                        <li class="
1695                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1696                                                    "
1697                        :class="{
1698                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '87'
1699                        }"
1700                        @mouseenter="openSubmenuId = '87'"
1701                        @keydown.escape="onSubmenuEscape"
1702                    >
1703                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1704                            
1705<a href="https://www.customandcommercial.com/split-screen.html"
1706    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1707            data-menu="menu-87"
1708    >
1709    Split Screen</a>
1710                        </div>
1711                                                                    </li>
1712                                                        <li class="
1713                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1714                                                    "
1715                        :class="{
1716                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '88'
1717                        }"
1718                        @mouseenter="openSubmenuId = '88'"
1719                        @keydown.escape="onSubmenuEscape"
1720                    >
1721                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1722                            
1723<a href="https://www.customandcommercial.com/beetle.html"
1724    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1725            data-menu="menu-88"
1726    >
1727    Beetle</a>
1728                        </div>
1729                                                                    </li>
1730                                                        <li class="
1731                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1732                                                    "
1733                        :class="{
1734                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '89'
1735                        }"
1736                        @mouseenter="openSubmenuId = '89'"
1737                        @keydown.escape="onSubmenuEscape"
1738                    >
1739                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1740                            
1741<a href="https://www.customandcommercial.com/baywindow.html"
1742    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1743            data-menu="menu-89"
1744    >
1745    Baywindow</a>
1746                        </div>
1747                                                                    </li>
1748                                                        <li class="
1749                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1750                                                    "
1751                        :class="{
1752                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '90'
1753                        }"
1754                        @mouseenter="openSubmenuId = '90'"
1755                        @keydown.escape="onSubmenuEscape"
1756                    >
1757                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1758                            
1759<a href="https://www.customandcommercial.com/brazilian-bay.html"
1760    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1761            data-menu="menu-90"
1762    >
1763    Brazilian Bay</a>
1764                        </div>
1765                                                                    </li>
1766                                                        <li class="
1767                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1768                                                    "
1769                        :class="{
1770                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '91'
1771                        }"
1772                        @mouseenter="openSubmenuId = '91'"
1773                        @keydown.escape="onSubmenuEscape"
1774                    >
1775                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1776                            
1777<a href="https://www.customandcommercial.com/type-25.html"
1778    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1779            data-menu="menu-91"
1780    >
1781    Type 25</a>
1782                        </div>
1783                                                                    </li>
1784                                                        <li class="
1785                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1786                                                    "
1787                        :class="{
1788                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '92'
1789                        }"
1790                        @mouseenter="openSubmenuId = '92'"
1791                        @keydown.escape="onSubmenuEscape"
1792                    >
1793                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1794                            
1795<a href="https://www.customandcommercial.com/type-3.html"
1796    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1797            data-menu="menu-92"
1798    >
1799    Type 3 </a>
1800                        </div>
1801                                                                    </li>
1802                                                        <li class="
1803                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1804                                                    "
1805                        :class="{
1806                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '104'
1807                        }"
1808                        @mouseenter="openSubmenuId = '104'"
1809                        @keydown.escape="onSubmenuEscape"
1810                    >
1811                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1812                            
1813<a href="https://www.customandcommercial.com/t4.html"
1814    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1815            data-menu="menu-104"
1816    >
1817    T4</a>
1818                        </div>
1819                                                                    </li>
1820                                                        <li class="
1821                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1822                                                    "
1823                        :class="{
1824                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '105'
1825                        }"
1826                        @mouseenter="openSubmenuId = '105'"
1827                        @keydown.escape="onSubmenuEscape"
1828                    >
1829                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1830                            
1831<a href="https://www.customandcommercial.com/t5.html"
1832    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1833            data-menu="menu-105"
1834    >
1835    T5</a>
1836                        </div>
1837                                                                    </li>
1838                                                        <li class="
1839                            flex items-center justify-between px-3 hover:!bg-ctaprimary
1840                                                    "
1841                        :class="{
1842                            'bg-ctaprimary shadow-md' : '' && openSubmenuId === '93'
1843                        }"
1844                        @mouseenter="openSubmenuId = '93'"
1845                        @keydown.escape="onSubmenuEscape"
1846                    >
1847                        <div class="group uppercase [&>a]:py-3.5 [&>a]:!text-base [&>a]:text-white [&>a]:font-semibold [&>a]:hover:!text-white">
1848                            
1849<a href="https://www.customandcommercial.com/karmann-ghia.html"
1850    class="snowdog-menu-link font-serif text-sm text-bodydark font-normal hover:!text-black "
1851            data-menu="menu-93"
1852    >
1853    Karmann Ghia </a>
1854                        </div>
1855                                                                    </li>
1856                            </ul>
1857        </nav>
1858    </div>
1859        </div>
1860        <div x-ref="searchContainerMobile" class="container lg:hidden pb-4">
1861            <div x-ref="searchForm">
1862                
1863<script>
1864    function initMiniSearchComponent() {
1865        "use strict";
1866
1867        return {
1868            show:false,
1869            formSelector: "#search_mini_form",
1870            url: "https://www.customandcommercial.com/search/ajax/suggest/",
1871            destinationSelector: "#search_autocomplete",
1872            templates: {"term":{"title":"Search terms","template":"Hyva_SmileElasticsuite::core\/autocomplete\/term.phtml"},"product":{"title":"Products","template":"Hyva_SmileElasticsuite::catalog\/autocomplete\/product.phtml"},"category":{"title":"Categories","template":"Hyva_SmileElasticsuite::catalog\/autocomplete\/category.phtml"},"product_attribute":{"title":"Attributes","template":"Hyva_SmileElasticsuite::catalog\/autocomplete\/product_attribute.phtml","titleRenderer":"renderEsAutocompleteTitleAttribute"},"cms_page":{"title":"Cms page","template":"Hyva_SmileElasticsuite::cms-search\/autocomplete\/cms.phtml"}},
1873            priceFormat: {"pattern":"\u00a3%s","precision":2,"requiredPrecision":2,"decimalSymbol":".","groupSymbol":",","groupLength":3,"integerRequired":false},
1874            minSearchLength: 2,
1875            searchResultsByType: {},
1876            currentRequest: null,
1877
1878            /**
1879             * Get search results.
1880             */
1881            getSearchResults: function () {
1882                let value = document.querySelector('#search').value.trim();
1883
1884                if (value.length < parseInt(this.minSearchLength, 10)) {
1885                    this.searchResultsByType = [];
1886
1887                    return false;
1888                }
1889
1890                let url = this.url + '?' + new URLSearchParams({
1891                    q: document.querySelector('#search').value,
1892                    _: Date.now()
1893                }).toString();
1894
1895                if (this.currentRequest !== null) {
1896                    this.currentRequest.abort();
1897                }
1898                this.currentRequest = new AbortController();
1899
1900                fetch(url, {
1901                    method: 'GET',
1902                    signal: this.currentRequest.signal,
1903                }).then((response) => {
1904                    if (response.ok) {
1905                        return response.json();
1906                    }
1907                }).then((data)  => {
1908                    this.show = data.length > 0;
1909
1910                    this.searchResultsByType = data.reduce((acc, result) => {
1911                        if (! acc[result.type]) acc[result.type] = [];
1912                        acc[result.type].push(result);
1913                        return acc;
1914                    }, {});
1915                }).catch((error) => {
1916                    ;
1917                });
1918            },
1919        }
1920    }
1921</script>
1921
1922<div id="elasticsuite-search-container" x-show="true">
1923    <div class="py-2 text-bodydark px-0" x-data="initMiniSearchComponent()" @click.away="show = false">
1924        <form class="form minisearch" id="search_mini_form" action="https://www.customandcommercial.com/catalogsearch/result/" method="get" role="search">
1925            <div class="relative w-full lg:max-w-[480px] mx-auto">
1926                <label class="sr-only" for="search">
1927                    What&#x20;are&#x20;you&#x20;looking&#x20;for&#x3F;                </label>
1928                <input id="search"
1929                       x-on:input.debounce="getSearchResults()"
1930                       x-ref="searchInput"
1931                       type="search"
1932                       class="w-full px-5 py-3 text-lg leading-normal transition appearance-none text-bodydark
1933                        focus:outline-none focus:border-transparent font-serif text-sm rounded-md border-bodydark"
1934                       autocapitalize="off" autocomplete="off" autocorrect="off"
1935                       name="q"
1936                       value=""
1937                       placeholder="What&#x20;are&#x20;you&#x20;looking&#x20;for&#x3F;"
1938                       maxlength="128"
1939                       @search-open.window.debounce.10="
1940                            $el.focus();
1941                            $el.select();
1942                       "
1943                />
1944                <button type="submit" class="absolute right-4 top-2.5">
1945                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" role="img">
1946<path d="M21 21L15.803 15.803M15.803 15.803C17.2096 14.3964 17.9998 12.4887 17.9998 10.4995C17.9998 8.51031 17.2096 6.60258 15.803 5.196C14.3965 3.78943 12.4887 2.99922 10.4995 2.99922C8.51035 2.99922 6.60262 3.78943 5.19605 5.196C3.78947 6.60258 2.99927 8.51031 2.99927 10.4995C2.99927 12.4887 3.78947 14.3964 5.19605 15.803C6.60262 17.2096 8.51035 17.9998 10.4995 17.9998C12.4887 17.9998 14.3965 17.2096 15.803 15.803Z" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
1947<title>search</title></svg>
1948                </button>
1949            </div>
1950            <div id="search_autocomplete" class="search-autocomplete relative w-full" x-show="show" style="display:none;">
1951                <div class="search-autocomplete-block absolute z-50 w-full">
1952
1953                    <!-- Grouped block: Search terms + Categories -->
1954                    <div class="search-block-group"
1955                         x-show="Object.values(searchResultsByType).some(s => ['Search terms','Categories'].includes(templates[s[0].type].title))">
1956
1957                        <template x-for="searchResultByType in Object.values(searchResultsByType)">
1958                            <template x-if="['Search terms','Categories'].includes(templates[searchResultByType[0].type].title)">
1959                                <div class="search-block">
1960                                    <!-- Titles -->
1961                                    <template x-if="templates[searchResultByType[0].type].titleRenderer === undefined">
1962                                        <div class="font-serif text-lg font-semibold mb-[20px]"
1963                                             x-text="templates[searchResultByType[0].type].title">
1964                                        </div>
1965                                    </template>
1966
1967                                    <template x-if="templates[searchResultByType[0].type].titleRenderer !== undefined">
1968                                        <div class="font-serif text-lg font-semibold mb-[20px]"
1969                                             x-text="window[templates[searchResultByType[0].type].titleRenderer](searchResultByType)">
1970                                        </div>
1971                                    </template>
1972
1973                                    <!-- Items -->
1974                                    <div class="item-grid">
1975                                        <template x-for="searchResult in searchResultByType">
1976                                            <div class="product-item">
1977                                                                                                    
1978<template x-if="searchResult.type == 'term'">
1979    <a class="w-full block py-2"
1980       x-bind:href="'https://www.customandcommercial.com/catalogsearch/result/?q=' + searchResult.title"
1981       :title="searchResult.title">
1982        <span class="text-sm" x-text="searchResult.title"></span>
1983        <span class="text-sm" x-text="'(' + searchResult.num_results + ')'"></span>
1984    </a>
1985</template>
1986                                                                                                    
1987<template x-if="searchResult.type == 'product'">
1988    <a class="w-full block" :href="searchResult.url" :title="searchResult.title">
1989        <div class="flex flex-col">
1990            <div>
1991                <img :src="searchResult.image" class="inline-block" />
1992            </div>
1993            <div>
1994                <span class="product-name text-sm font-semibold mb-2.5 block" x-text="searchResult.title"></span>
1995                <span class="product-price text-sm font-semibold" x-html="searchResult.price"></span>
1996            </div>
1997        </div>
1998    </a>
1999</template>
2000                                                                                                    
2001<template x-if="searchResult.type == 'category'">
2002    <a class="1 w-full block py-2" :href="searchResult.url" :title="searchResult.title">
2003        <span class="text-sm italic block text-gray-500" x-text="searchResult.breadcrumb.join(' > ').concat(' > ')"></span>
2004        <span class="text-sm" x-text="searchResult.title"></span>
2005    </a>
2006</template>
2007                                                                                                    
2008<template x-if="searchResult.type == 'product_attribute'">
2009    <a class="2 w-full block py-2" :href="searchResult.url" :title="searchResult.title">
2010        <span class="text-sm" x-text="searchResult.title"></span>
2011        <span class="text-xs uppercase text-gray-500" x-text="searchResult.attribute_label" style="vertical-align: super;"></span>
2012    </a>
2013</template>
2014
2015<script>
2016    function renderEsAutocompleteTitleAttribute(data)
2017    {
2018        data = data.filter(function(item) {
2019            return item.type === 'product_attribute';
2020        }).map(function(item) {
2021            return item['attribute_label']
2022        }).reduce(function(prev, item) {
2023            if (item in prev) {
2024                prev[item]++;
2025            } else {
2026                prev[item] = 1;
2027            }
2028            return prev;
2029        }, {});
2030
2031        data = Object.entries(data).sort(function(item1, item2) {
2032            return item2[1] - item1[1]
2033        }).map(function(item) {return item[0]});
2034
2035        if (data.length > 2) {
2036            data = data.slice(0, 2);
2037            data.push('...');
2038        }
2039
2040        return data.join(', ');
2041    }
2042</script>
2042
2043                                                                                                    
2044<template x-if="searchResult.type == 'cms_page'">
2045    <a class="w-full block p-2" :href="searchResult.url" :title="searchResult.title">
2046        <span class="text-sm" x-text="searchResult.title"></span>
2047    </a>
2048</template>
2049                                                                                            </div>
2050                                        </template>
2051                                    </div>
2052                                </div>
2053                            </template>
2054                        </template>
2055                    </div>
2056
2057
2058                    <!-- Normal block: All other result types -->
2059                    <template x-for="searchResultByType in Object.values(searchResultsByType)">
2060                        <template x-if="!['Search terms','Categories'].includes(templates[searchResultByType[0].type].title)">
2061                            <div class="search-block"
2062                                 :class="{'product-block' : templates[searchResultByType[0].type].title === 'Products'}">
2063
2064                                <!-- Titles -->
2065                                <template x-if="templates[searchResultByType[0].type].titleRenderer === undefined">
2066                                    <div class="font-serif text-lg font-semibold mb-[20px]"
2067                                         x-text="templates[searchResultByType[0].type].title"></div>
2068                                </template>
2069
2070                                <template x-if="templates[searchResultByType[0].type].titleRenderer !== undefined">
2071                                    <div class="font-serif text-lg font-semibold mb-[20px]"
2072                                         x-text="window[templates[searchResultByType[0].type].titleRenderer](searchResultByType)">
2073                                    </div>
2074                                </template>
2075
2076                                <!-- Items -->
2077                                <div class="item-grid">
2078                                    <template x-for="searchResult in searchResultByType">
2079                                        <div class="product-item">
2080                                                                                            
2081<template x-if="searchResult.type == 'term'">
2082    <a class="w-full block py-2"
2083       x-bind:href="'https://www.customandcommercial.com/catalogsearch/result/?q=' + searchResult.title"
2084       :title="searchResult.title">
2085        <span class="text-sm" x-text="searchResult.title"></span>
2086        <span class="text-sm" x-text="'(' + searchResult.num_results + ')'"></span>
2087    </a>
2088</template>
2089                                                                                            
2090<template x-if="searchResult.type == 'product'">
2091    <a class="w-full block" :href="searchResult.url" :title="searchResult.title">
2092        <div class="flex flex-col">
2093            <div>
2094                <img :src="searchResult.image" class="inline-block" />
2095            </div>
2096            <div>
2097                <span class="product-name text-sm font-semibold mb-2.5 block" x-text="searchResult.title"></span>
2098                <span class="product-price text-sm font-semibold" x-html="searchResult.price"></span>
2099            </div>
2100        </div>
2101    </a>
2102</template>
2103                                                                                            
2104<template x-if="searchResult.type == 'category'">
2105    <a class="1 w-full block py-2" :href="searchResult.url" :title="searchResult.title">
2106        <span class="text-sm italic block text-gray-500" x-text="searchResult.breadcrumb.join(' > ').concat(' > ')"></span>
2107        <span class="text-sm" x-text="searchResult.title"></span>
2108    </a>
2109</template>
2110                                                                                            
2111<template x-if="searchResult.type == 'product_attribute'">
2112    <a class="2 w-full block py-2" :href="searchResult.url" :title="searchResult.title">
2113        <span class="text-sm" x-text="searchResult.title"></span>
2114        <span class="text-xs uppercase text-gray-500" x-text="searchResult.attribute_label" style="vertical-align: super;"></span>
2115    </a>
2116</template>
2117
2118<script>
2119    function renderEsAutocompleteTitleAttribute(data)
2120    {
2121        data = data.filter(function(item) {
2122            return item.type === 'product_attribute';
2123        }).map(function(item) {
2124            return item['attribute_label']
2125        }).reduce(function(prev, item) {
2126            if (item in prev) {
2127                prev[item]++;
2128            } else {
2129                prev[item] = 1;
2130            }
2131            return prev;
2132        }, {});
2133
2134        data = Object.entries(data).sort(function(item1, item2) {
2135            return item2[1] - item1[1]
2136        }).map(function(item) {return item[0]});
2137
2138        if (data.length > 2) {
2139            data = data.slice(0, 2);
2140            data.push('...');
2141        }
2142
2143        return data.join(', ');
2144    }
2145</script>
2145
2146                                                                                            
2147<template x-if="searchResult.type == 'cms_page'">
2148    <a class="w-full block p-2" :href="searchResult.url" :title="searchResult.title">
2149        <span class="text-sm" x-text="searchResult.title"></span>
2150    </a>
2151</template>
2152                                                                                    </div>
2153                                    </template>
2154                                </div>
2155
2156                            </div>
2157                        </template>
2158                    </template>
2159                </div>
2160            </div>
2161                    </form>
2162    </div>
2163</div>
2164            </div>
2165        </div>
2166    </div>
2167    
2168<div class="py-3.5 bg-lightorange font-serif text-xs text-center font-medium uppercase border-b border-black-300">
2169    <div class="lg:container">
2170        <div class="usps-bar">
2171            <ul class="flex justify-between">
2172                <li class="flex items-center gap-3">
2173                    <span>Worldwide shipping</span>
2174                </li>
2175                <li class="flex items-center gap-3">
2176                    <span>Wholesale and trade customers welcome</span>
2177                </li>
2178                <li class="flex items-center gap-3">
2179                    <span>1900 unique product lines</span>
2180                </li>
2181                <li class="flex items-center gap-3">
2182                    <span>Manufacturers &amp; importers of classic vw parts</span>
2183                </li>
2184            </ul>
2185        </div>
2186    </div>
2187</div>
2188<script>
2189    document.addEventListener('DOMContentLoaded', function () {
2190        function uspsSwiperMode() {
2191            const bar = document.querySelector('.usps-bar');
2192            if (!bar) return;
2193
2194            const list = bar.querySelector('ul');
2195            const items = list.querySelectorAll('li');
2196            const isSwiper = bar.classList.contains('swiper-initialized');
2197            const isMobile = window.innerWidth < 1024;
2198
2199            if (isMobile && !isSwiper) {
2200                // Add necessary classes
2201                list.classList.add('swiper-wrapper');
2202                items.forEach(el => el.classList.add('swiper-slide', 'justify-center'));
2203
2204                // Init Swiper
2205                new Swiper(".usps-bar", {
2206                    slidesPerView: 1,
2207                    autoplay: {
2208                        delay: 4000,
2209                    },
2210                    breakpoints: {
2211                        640: { slidesPerView: 1 },
2212                        768: { slidesPerView: 4 },
2213                        1024: { slidesPerView: 4 },
2214                    },
2215                });
2216
2217            } else if (!isMobile && isSwiper) {
2218                // Remove classes
2219                list.classList.remove('swiper-wrapper');
2220                items.forEach(el => el.classList.remove('swiper-slide', 'justify-center'));
2221
2222                // Destroy instance
2223                bar.swiper.destroy(true, true);
2224            }
2225        }
2226
2227        window.addEventListener('load', uspsSwiperMode);
2228        window.addEventListener('resize', uspsSwiperMode);
2229    });
2230</script>
2230
2231    <!-- BLOCK authentication-popup -->
2231<script>
2232    function initAuthentication() {
2233        return {
2234            open: false,
2235            close() {
2236                this.open = false;
2237            },
2238            forceAuthentication: false,
2239            checkoutUrl: 'https://www.customandcommercial.com/checkout/index/',
2240            errors: 0,
2241            hasCaptchaToken: 0,
2242            displayErrorMessage: false,
2243            errorMessages: [],
2244            setErrorMessages(message) {
2245                this.errorMessages = [message];
2246                this.displayErrorMessage = true;
2247            },
2248            submitForm() {
2249                // Do not rename $form, the variable is expected to be declared in the recaptcha output
2250                const $form = document.querySelector('#login-form');
2251                
2252                if (this.errors === 0) {
2253                    this.dispatchLoginRequest($form);
2254                }
2255            },
2256            onPrivateContentLoaded() {
2257                const data = this.$event.detail.data;
2258                const isLoggedIn = data.customer && data.customer.firstname;
2259                if (data.cart && !isLoggedIn) {
2260                    this.forceAuthentication = !data.cart.isGuestCheckoutAllowed;
2261                }
2262            },
2263            redirectIfAuthenticated() {
2264                const event = this.$event;
2265                this.open = this.forceAuthentication;
2266
2267                if (event.detail && event.detail.url) {
2268                    this.checkoutUrl = event.detail.url;
2269                }
2270                if (!this.forceAuthentication) {
2271                    window.location.href = this.checkoutUrl;
2272                }
2273            },
2274            resetErrors() {
2275                this.errors = 0;
2276            },
2277            dispatchLoginRequest(form) {
2278                this.isLoading = true;
2279                const username = this.$refs['customer-email'].value;
2280                const password = this.$refs['customer-password'].value;
2281                const formKey = hyva.getFormKey();
2282                const bodyFields = {
2283                    'username': username,
2284                    'password': password,
2285                    'formKey': formKey
2286                };
2287                                const fieldName = 'g\u002Drecaptcha\u002Dresponse';
2288                const recaptchaField = fieldName && form[fieldName];
2289                if (recaptchaField) {
2290                    bodyFields[fieldName] = recaptchaField.value;
2291                }
2292                fetch('https://www.customandcommercial.com/customer/ajax/login/', {
2293                        method: 'POST',
2294                        headers: {
2295                            'Content-Type': 'application/json',
2296                            'X-Requested-With': 'XMLHttpRequest'
2297                        },
2298                        body: JSON.stringify(bodyFields)
2299                    }
2300                ).then(response => {
2301                        return response.json()
2302                    }
2303                ).then(data => {
2304                    this.isLoading = false;
2305                    if (data.errors) {
2306                        this.setErrorMessages(data.message);
2307                        this.errors = 1;
2308                        this.hasCaptchaToken = 0;
2309                    } else {
2310                        window.location.href = this.checkoutUrl;
2311                    }
2312                });
2313            }
2314        }
2315    }
2316
2317    window.addEventListener('alpine:init', () => Alpine.data('initAuthentication', initAuthentication), {once: true})
2318</script>
2318
2319<section id="authentication-popup"
2320         x-data="initAuthentication"
2321         @private-content-loaded.window="onPrivateContentLoaded"
2322         @toggle-authentication.window="redirectIfAuthenticated"
2323         @keydown.window.escape="close"
2324>
2325    <div
2326        class="backdrop"
2327        aria-hidden="true"
2328        x-cloak
2329        x-show="open"
2330        x-transition:enter="ease-in-out duration-500"
2331        x-transition:enter-start="opacity-0"
2332        x-transition:enter-end="opacity-100"
2333        x-transition:leave="ease-in-out duration-500"
2334        x-transition:leave-start="opacity-100"
2335        x-transition:leave-end="opacity-0"
2336        @click="close"
2337    ></div>
2338    <div role="dialog"
2339         aria-modal="true"
2340         @click.outside="close"
2341         class="inset-y-0 right-0 z-30 flex max-w-full fixed"
2342         x-cloak
2343         x-show="open"
2344    >
2345        <div class="relative w-screen max-w-md pt-16 bg-container-lighter"
2346             x-show="open"
2347             x-cloak
2348             x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
2349             x-transition:enter-start="translate-x-full"
2350             x-transition:enter-end="translate-x-0"
2351             x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
2352             x-transition:leave-start="translate-x-0"
2353             x-transition:leave-end="translate-x-full"
2354        >
2355            <div
2356                x-show="open"
2357                x-cloak
2358                x-transition:enter="ease-in-out duration-500"
2359                x-transition:enter-start="opacity-0"
2360                x-transition:enter-end="opacity-100"
2361                x-transition:leave="ease-in-out duration-500"
2362                x-transition:leave-start="opacity-100"
2363                x-transition:leave-end="opacity-0" class="absolute top-0 right-2 flex p-2 mt-2">
2364                <button
2365                    type="button"
2366                    @click="close"
2367                    aria-label="Close&#x20;panel"
2368                    class="p-2 text-gray-300 transition duration-150 ease-in-out hover:text-black"
2369                >
2370                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
2371  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
2372</svg>
2373                </button>
2374            </div>
2375            <template x-if="open">
2376                <div class="flex flex-col h-full py-6 space-y-6 bg-white shadow-xl overflow-y-auto">
2377                    <div class="mx-4">
2378                        <div class="message error mb-0" x-show="errors" x-cloak>
2379                            <template x-for="(message, index) in errorMessages" :key="index">
2380                                <div>
2381                                    <template x-if="message">
2382                                        <span x-html="message"></span>
2383                                    </template>
2384                                </div>
2385                            </template>
2386                        </div>
2387                    </div>
2388                    <div class="block-customer-login bg-container border border-container mx-4 p-4 shadow-sm">
2389                        <p id="authenticate-customer-login" class="text-lg leading-7 text-gray-900">
2390                            <strong class="font-medium">Checkout using your account</strong>
2391                        </p>
2392
2393                        <form class="form form-login"
2394                              method="post"
2395                              @submit.prevent="submitForm"
2396                              id="login-form"
2397                        >
2398                                                        <div class="fieldset login">
2399                                <div class="field email required">
2400                                    <label class="label" for="form-login-username" form="login-form" >
2401                                        <span>Email Address</span>
2402                                    </label>
2403                                    <div class="control">
2404                                        <input name="username"
2405                                               id="form-login-username"
2406                                               x-ref="customer-email"
2407                                               @change="resetErrors"
2408                                               type="email"
2409                                               required
2410                                               autocomplete="off"
2411                                               class="form-input"
2412                                        >
2413                                    </div>
2414                                </div>
2415                                <div class="field password required">
2416                                    <label for="form-login-password" class="label" form="login-form">
2417                                        <span>Password</span>
2418                                    </label>
2419                                    <div class="control">
2420                                        <input name="password"
2421                                               id="form-login-password"
2422                                               type="password"
2423                                               class="form-input"
2424                                               required
2425                                               x-ref="customer-password"
2426                                               autocomplete="off"
2427                                               @change="resetErrors"
2428                                        >
2429                                    </div>
2430                                </div>
2431
2432                                <input name="context" type="hidden" value="checkout" />
2433                                <div class="actions-toolbar pt-6 pb-2">
2434                                    <button type="submit"                                            class="inline-flex btn btn-primary disabled:opacity-75"
2435                                    >
2436                                        Sign In                                    </button>
2437                                    <a href="https://www.customandcommercial.com/customer/account/forgotpassword/"
2438                                    >
2439                                        Forgot Your Password?                                    </a>
2440                                </div>
2441
2442                            </div>
2443                        </form>
2444                    </div>
2445                    <div class="mx-4">
2446                                            </div>
2447                    <div class="block-new-customer bg-container border border-container mx-4 p-4 shadow-sm">
2448                        <p id="authenticate-new-customer" class="text-lg mb-2 leading-7 text-gray-900">
2449                            <strong class="font-medium">Checkout as a new customer</strong>
2450                        </p>
2451
2452                        <div class="block-content">
2453                            <p class="mb-1">
2454                                Creating an account has many benefits:                            </p>
2455                            <ul class="list-disc pl-5">
2456                                <li> See order and shipping status</li>
2457                                <li> Track order history</li>
2458                                <li> Check out faster</li>
2459                            </ul>
2460                            <div class="actions-toolbar mt-6 mb-2">
2461                                <a href="https://www.customandcommercial.com/customer/account/create/"
2462                                   class="inline-flex btn btn-primary">
2463                                    Create an Account                                </a>
2464                            </div>
2465                        </div>
2466                    </div>
2467                </div>
2468            </template>
2469        </div>
2470    </div>
2471</section>
2472<!-- /BLOCK authentication-popup --></div>
2473<script>
2474    function initCartDrawer() {
2475        return {
2476            vatMode: vatSwitcher.getVatMode() || 'excluding',
2477            open: false,
2478            isLoading: false,
2479            cart: {},
2480            maxItemsToDisplay: 10,
2481            itemsCount: 0,
2482            getData(data) {
2483                if (data.cart) {
2484                    this.cart = data.cart;
2485                    this.itemsCount = data.cart.items && data.cart.items.length || 0;
2486                    this.setCartItems();
2487                }
2488                this.isLoading = false;
2489            },
2490            cartItems: [],
2491            getItemCountTitle() {
2492                return hyva.strf('\u00250\u0020of\u0020\u00251\u0020products\u0020in\u0020cart\u0020displayed', this.maxItemsToDisplay, this.itemsCount)
2493            },
2494            setCartItems() {
2495                this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || [];
2496
2497                if (this.maxItemsToDisplay > 0) {
2498                    this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10));
2499                }
2500            },
2501            deleteItemFromCart(itemId) {
2502                this.isLoading = true;
2503
2504                const formKey = hyva.getFormKey();
2505                const postUrl = BASE_URL + 'checkout/sidebar/removeItem/';
2506
2507                fetch(postUrl, {
2508                    "headers": {
2509                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
2510                    },
2511                    "body": "form_key=" + formKey + "&item_id=" + itemId,
2512                    "method": "POST",
2513                    "mode": "cors",
2514                    "credentials": "include"
2515                }).then(response => {
2516                    if (response.redirected) {
2517                        window.location.href = response.url;
2518                    } else if (response.ok) {
2519                        return response.json();
2520                    } else {
2521                        window.dispatchMessages && window.dispatchMessages([{
2522                            type: 'warning',
2523                            text: 'Could\u0020not\u0020remove\u0020item\u0020from\u0020quote.'
2524                        }]);
2525                        this.isLoading = false;
2526                    }
2527                }).then(result => {
2528                    window.dispatchMessages && window.dispatchMessages([{
2529                        type: result.success ? 'success' : 'error',
2530                        text: result.success
2531                            ? 'You\u0020removed\u0020the\u0020item.'
2532                            : result.error_message
2533                    }], result.success ? 5000 : 0)
2534                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
2535                });
2536            },
2537            scrollLock(use = true) {
2538                document.body.style.overflow = use ? "hidden" : "";
2539            },
2540            toggleCartDrawer(event) {
2541                if (event.detail && event.detail.isOpen !== undefined) {
2542                    if (event.detail.isOpen) {
2543                        this.openCartDrawer();
2544                    } else {
2545                        this.open = false;
2546                        this.scrollLock(false);
2547                        this.$refs && this.$refs.cartDialogContent && hyva.releaseFocus(this.$refs.cartDialogContent);
2548                    }
2549                } else {
2550                                        this.openCartDrawer()
2551                }
2552            },
2553            getPriceHtml(productPrice) {
2554                if (vatSwitcher.getVatMode() === 'excluding') {
2555                    return productPrice.replace(
2556                        /<span class="price-including-tax"/,
2557                        `<span class="price-including-tax hidden"`
2558                    );
2559                } else {
2560                    return productPrice.replace(
2561                        /<span class="price-excluding-tax"/,
2562                        `<span class="price-excluding-tax hidden"`
2563                    );
2564                }
2565            },
2566            openCartDrawer() {
2567                this.open = true;
2568                this.scrollLock(true);
2569                this.$nextTick(() => {
2570                    this.$refs && this.$refs.cartDialogContent && hyva.trapFocus(this.$refs.cartDialogContent)
2571                })
2572            },
2573            closeCartDrawer() {
2574                this.$dispatch('toggle-cart', { isOpen: false })
2575            },
2576            getSectionDataExtraActions() {
2577                if (!this.cart.extra_actions) {
2578                    return '';
2579                }
2580
2581                const contentNode = document.createElement('div');
2582                contentNode.innerHTML = this.cart.extra_actions;
2583
2584                hyva.activateScripts(contentNode);
2585
2586                return contentNode.innerHTML;
2587            },
2588            eventListeners: {
2589                ['@update-cart-drawer-vat-mode.window'](event) {
2590                    this.vatMode = event.detail;
2591                },
2592            }
2593        }
2594    }
2595</script>
2595
2596<section x-cloak
2597         x-show="cart"
2598         id="cart-drawer"
2599         x-data="initCartDrawer()"
2600         x-bind="eventListeners"
2601         @private-content-loaded.window="getData($event.detail.data)"
2602         @toggle-cart.window="toggleCartDrawer($event)"
2603         @keydown.escape="closeCartDrawer"
2604>
2605    <div role="dialog"
2606         aria-labelledby="cart-drawer-title"
2607         aria-modal="true"
2608         :aria-hidden="!open"
2609         class="fixed inset-y-0 right-0 z-[100] flex max-w-full">
2610        <div class="backdrop"
2611             x-show="open"
2612             x-transition:enter="ease-in-out duration-500"
2613             x-transition:enter-start="opacity-0"
2614             x-transition:enter-end="opacity-100"
2615             x-transition:leave="ease-in-out duration-500"
2616             x-transition:leave-start="opacity-100"
2617             x-transition:leave-end="opacity-0"
2618             role="button"
2619             @click="closeCartDrawer"
2620             aria-label="Close&#x20;minicart"></div>
2621        <div class="relative w-screen max-w-md shadow-2xl"
2622             x-show="open"
2623             x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700"
2624             x-transition:enter-start="translate-x-full"
2625             x-transition:enter-end="translate-x-0"
2626             x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700"
2627             x-transition:leave-start="translate-x-0"
2628             x-transition:leave-end="translate-x-full"
2629             x-ref="cartDialogContent"
2630             role="region"
2631             :tabindex="open ? 0 : -1"
2632             aria-label="My&#x20;Cart"
2633
2634        >
2635            <div class="flex flex-col h-full max-h-screen bg-white shadow-xl">
2636                
2637                <header class="relative px-4 py-6 sm:px-6">
2638                    <p id="cart-drawer-title" class="text-lg font-medium leading-7 text-gray-900">
2639                        <strong>My Cart</strong>
2640                        <span class="items-total text-xs"
2641                              x-show="maxItemsToDisplay && maxItemsToDisplay < itemsCount"
2642                              x-text="getItemCountTitle()">
2643                        </span>
2644                    </p>
2645                </header>
2646
2647                
2648                <template x-if="!itemsCount">
2649                    <div class="relative px-4 py-6 bg-white border-bs sm:px-6 border-container">
2650                        Cart is empty                    </div>
2651                </template>
2652
2653                <template x-if="itemsCount">
2654                    <div class="relative grid gap-6 sm:gap-8 px-1 py-3 sm:px-3 bg-white border-b border-container overflow-y-auto overscroll-y-contain">
2655                        <template x-for="item in cartItems">
2656                            <div class="flex items-start p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100">
2657                                <a :href="item.product_url"
2658                                   class="w-1/4"
2659                                   :aria-label="hyva.strf('Product\u0020\u0022\u00250\u0022', item.product_name)"
2660                                >
2661                                    <img
2662                                        :src="item.product_image.src"
2663                                        :width="item.product_image.width"
2664                                        :height="item.product_image.height"
2665                                        loading="lazy"
2666                                        alt=""
2667                                    />
2668                                </a>
2669                                <div class="w-3/4 space-y-2">
2670                                    <div>
2671                                        <p class="text-lg font-serif font-medium">
2672                                            <span x-html="item.qty"></span> x <span x-html="item.product_name"></span>
2673                                        </p>
2674                                        <p class="text-sm">Part no: <span x-html="item.product_sku"></span></p>
2675                                    </div>
2676                                    <template x-if="item.product_type !== 'bundle'">
2677                                        <template x-for="option in item.options">
2678                                            <div class="pt-2">
2679                                                <p class="font-semibold" x-text="option.label + ':'"></p>
2680                                                <p class="text-secondary" x-html="option.value"></p>
2681                                            </div>
2682                                        </template>
2683                                    </template>
2684                                    <p class="text-lg"><span x-html="getPriceHtml(item.product_price)"></span></p>
2685                                    <div class="pt-4">
2686                                        <a :href="item.configure_url"
2687                                           x-show="item.product_type !== 'grouped' && item.is_visible_in_site_visibility"
2688                                           class="inline-flex p-2 mr-2"
2689                                           :aria-label="hyva.strf('Edit\u0020product\u
26890020\u0022\u00250\u0022', item.product_name)"
2690                                        >
2691                                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" aria-hidden="true">
2692  <path stroke-linecap="round" stroke-linejoin="round" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
2693</svg>
2694                                        </a>
2695                                        <button type="button"
2696                                                class="inline-flex p-2"
2697                                                @click="deleteItemFromCart(item.item_id)"
2698                                                :aria-label="hyva.strf('Remove\u0020product\u0020\u0022\u00250\u0022\u0020from\u0020cart', item.product_name)"
2699                                        >
2700                                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20" aria-hidden="true">
2701  <path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
2702</svg>
2703                                        </button>
2704                                    </div>
2705
2706                                </div>
2707                            </div>
2708                        </template>
2709                    </div>
2710                </template>
2711
2712                <template x-if="itemsCount">
2713                    <div>
2714                        <template x-if="cart.discount_amount">
2715    <div class="relative grid gap-6 sm:gap-8 px-1 pt-3 sm:px-3 bg-white">
2716        <div class="am-discount-amount w-full p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100">
2717            <p>Discount: <span x-html="cart.discount_amount"></span></p>
2718        </div>
2719    </div>
2720</template>
2721
2722                        <div class="relative grid gap-6 sm:gap-8 py-3 px-1 sm:px-3 bg-white">
2723                            <div class="w-full p-3 space-x-4 transition duration-150 ease-in-out rounded-lg hover:bg-gray-100">
2724                                <p>Subtotal: <span x-html="vatMode === 'excluding' ? cart.subtotal_excl_tax : cart.subtotal_incl_tax"></span></p>
2725                            </div>
2726                            <div class="w-full p-3 space-x-4 transition duration-150 ease-in-out">
2727                                <a href="https://www.customandcommercial.com/checkout/cart/" class="btn btn-primary !rounded bg-brandblue px-16 h-12">
2728                                    <span class="block mx-auto">Checkout</span>
2729                                </a>
2730                            </div>
2731                            <div x-html="getSectionDataExtraActions()"></div>
2732                                                    </div>
2733                    </div>
2734                </template>
2735
2736                
2736<script>
2737    function prepareMollieApplePayMinicart() {
2738        const objectToFormData = (object, prefix = null, formDataObject = null) => {
2739            const formData = formDataObject || new FormData();
2740            Object.keys(object).forEach(key => {
2741                const value = object[key];
2742                const name = prefix ? `${prefix}[${key}]` : key;
2743                if (value instanceof Object) {
2744                    objectToFormData(value, name, formData);
2745                } else {
2746                    formData.append(name, value);
2747                }
2748            });
2749
2750            return new URLSearchParams(formData).toString();
2751        };
2752
2753        return {
2754            totalAmount: 0,
2755
2756            init: () => {
2757                // Normally we would use private-content-loaded to get this information, but this component is
2758                // rendered after this event has been dispatched. So get the information from the browser storage.
2759                const browserStorage = hyva.getBrowserStorage();
2760                if (browserStorage) {
2761                    const cacheStorage = browserStorage.getItem('mage-cache-storage');
2762                    const cart = JSON.parse(cacheStorage).cart;
2763
2764                    this.totalAmount = cart.subtotalAmount;
2765                }
2766
2767                window.addEventListener('private-content-loaded', event => {
2768                    this.totalAmount = event.detail.data.cart.subtotalAmount
2769                })
2770            },
2771
2772            pay: () => {
2773                const amount = this.totalAmount;
2774                let countryCode, postalCode, shippingMethods, selectedShippingMethod, quoteTotals;
2775
2776                const request = {
2777                    countryCode: "GB",
2778                    currencyCode: "GBP",
2779                    supportedNetworks: ["amex","masterCard","visa","maestro","vPay"],
2780                    merchantCapabilities: ['supports3DS'],
2781                    total: {
2782                        label: "Default\u0020Store\u0020View",
2783                        amount: amount
2784                    },
2785                    shippingType: 'shipping',
2786                    requiredBillingContactFields: [
2787                        'postalAddress',
2788                        'name',
2789                        'email',
2790                        'phone'
2791                    ],
2792                    requiredShippingContactFields: [
2793                        'postalAddress',
2794                        'name',
2795                        'email',
2796                        'phone'
2797                    ]
2798                }
2799
2800                let session = new ApplePaySession(3, request);
2801
2802                const getTotal = () => {
2803                    const total = quoteTotals.find(item => item.code === 'grand_total') || quoteTotals[quoteTotals.length - 1];
2804
2805                    total.label = "Default\u0020Store\u0020View";
2806
2807                    const payload = { total };
2808                    window.dispatchEvent(new CustomEvent('mollie-applepay-total', {
2809                        detail: payload,
2810                    }));
2811
2812                    return payload.total;
2813                };
2814
2815                const getLineItems = () => {
2816                    let totals = [...quoteTotals];
2817                    totals = totals.filter(item => item.code !== 'grand_total');
2818
2819                    const payload = { lineItems: totals };
2820                    window.dispatchEvent(new CustomEvent('mollie-applepay-lineitems', {
2821                        detail: payload,
2822                    }));
2823
2824                    return payload.lineItems;
2825                };
2826
2827                const handleAjaxError = (message) => {
2828                    session.abort();
2829
2830                    dispatchMessages([
2831                        {
2832                            text: message,
2833                            type: 'error'
2834                        }
2835                    ]);
2836                };
2837
2838                session.onpaymentmethodselected = () => {
2839                    session.completePaymentMethodSelection(getTotal(), []);
2840                };
2841
2842                session.onshippingcontactselected = (event) => {
2843                    countryCode = event.shippingContact.countryCode;
2844                    postalCode = event.shippingContact.postalCode;
2845
2846                    fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, {
2847                        method: 'POST',
2848                        headers: {
2849                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
2850                        },
2851                        body: 'countryCode=' + event.shippingContact.countryCode +
2852                            '&postalCode=' + event.shippingContact.postalCode
2853                    })
2854                        .then(response => {
2855                            if (!response.ok) {
2856                                throw new Error('Network response was not ok');
2857                            }
2858                            return response.json();
2859                        })
2860                        .then(result => {
2861                            shippingMethods = result.shipping_methods;
2862                            selectedShippingMethod = result.shipping_methods[0];
2863                            quoteTotals = result.totals;
2864
2865                            session.completeShippingContactSelection(
2866                                ApplePaySession.STATUS_SUCCESS,
2867                                result.shipping_methods,
2868                                getTotal(),
2869                                getLineItems()
2870                            );
2871                        })
2872                        .catch(error => handleAjaxError(error));
2873                };
2874
2875                session.onshippingmethodselected = (event) => {
2876                    selectedShippingMethod = event.shippingMethod;
2877
2878                    fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, {
2879                        method: 'POST',
2880                        headers: {
2881                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
2882                        },
2883                        body: objectToFormData({
2884                            shippingMethod: selectedShippingMethod,
2885                            countryCode: countryCode,
2886                            postalCode: postalCode
2887                        })
2888                    })
2889                        .then(response => {
2890                            if (!response.ok) {
2891                                throw new Error('Network response was not ok');
2892                            }
2893                            return response.json();
2894                        })
2895                        .then(result => {
2896                            quoteTotals = result.totals;
2897
2898                            session.completeShippingMethodSelection(
2899                                ApplePaySession.STATUS_SUCCESS,
2900                                getTotal(),
2901                                getLineItems()
2902                            );
2903                        })
2904                        .catch(error => handleAjaxError(error));
2905                };
2906
2907                session.onpaymentauthorized = (event) => {
2908                    fetch(`${BASE_URL}mollie/applePay/placeOrder?form_key=${hyva.getFormKey()}`, {
2909                        method: 'POST',
2910                        headers: {
2911                            'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
2912                        },
2913                        body: objectToFormData({
2914                            shippingMethod: selectedShippingMethod,
2915                            billingAddress: event.payment.billingContact,
2916                            shippingAddress: event.payment.shippingContact,
2917                            applePayPaymentToken: JSON.stringify(event.payment.token)
2918                        })
2919                    })
2920                        .then(response => {
2921                            if (!response.ok) {
2922                                throw new Error('Network response was not ok');
2923                            }
2924                            return response.json();
2925                        })
2926                        .then(result => {
2927                            if (!session) {
2928                                console.warn('Payment canceled');
2929                                return;
2930                            }
2931
2932                            if (result.error) {
2933                                handleAjaxError(result.error_message);
2934                                return;
2935                            }
2936
2937                            if (!result.url) {
2938                                handleAjaxError('Something went wrong, please try again later.');
2939                                return;
2940                            }
2941
2942                            session.completePayment(ApplePaySession.STATUS_SUCCESS);
2943
2944                            window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
2945
2946                            setTimeout(() => {
2947                                location.href = result.url;
2948                            }, 1000);
2949                        })
2950                        .catch(error => handleAjaxError(error));
2951                };
2952
2953                session.onvalidatemerchant = (event) => {
2954                    fetch(
2955                        `${BASE_URL}mollie/checkout/applePayValidation?form_key=${hyva.getFormKey()}`,
2956                        {
2957                            method: 'POST',
2958                            headers: {
2959                                'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
2960                            },
2961                            body: objectToFormData({validationURL: event.validationURL}),
2962                        }
2963                    )
2964                        .then((response) => {
2965                            if (!response.ok) {
2966                                throw new Error('Merchant validation failed');
2967                            }
2968
2969                            return response.json()
2970                        })
2971                        .then((result) => session.completeMerchantValidation(result))
2972                        .catch(error => handleAjaxError(error));
2973                };
2974
2975                session.oncancel = () => {
2976                    session = null;
2977                }
2978
2979                session.begin();
2980            }
2981        }
2982    }
2983
2984    window.addEventListener(
2985        'alpine:init',
2986        () => Alpine.data('prepareMollieApplePayMinicart', prepareMollieApplePayMinicart),
2987        {once: true}
2988    )
2989</script>
2989
2990            </div>
2991
2992            <button
2993                type="button"
2994                @click="closeCartDrawer"
2995                aria-label="Close&#x20;minicart"
2996                class="absolute top-0 right-2 p-4 mt-2 text-gray-300 transition-colors hover:text-black"
2997            >
2998                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
2999  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
3000</svg>
3001            </button>
3002        </div>
3003        <div
3004    class="z-50 fixed inset-0 grid place-items-center bg-white/70 text-slate-800"
3005    x-cloak
3006    x-show="isLoading"
3007    x-transition.opacity.duration.200ms
3008>
3009    <div class="flex gap-10 items-center p-4">
3010        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="57" height="57" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
3011    <style>
3012        @keyframes spinner-ball-triangle1 {
3013            0% { transform: translate(0%, 0%); }
3014            33% { transform: translate(38%, -79%); }
3015            66% { transform: translate(77%, 0%); }
3016            100% { transform: translate(0%, 0%); }
3017        }
3018
3019        @keyframes spinner-ball-triangle2 {
3020            0% { transform: translate(0%, 0%); }
3021            33% { transform: translate(38%, 79%); }
3022            66% { transform: translate(-38%, 79%); }
3023            100% { transform: translate(0%, 0%); }
3024        }
3025
3026        @keyframes spinner-ball-triangle3 {
3027            0% { transform: translate(0%, 0%); }
3028            33% { transform: translate(-77%, 0%); }
3029            66% { transform: translate(-38%, -79%); }
3030            100% { transform: translate(0%, 0%); }
3031        }
3032    </style>
3033    <circle cx="5" cy="50" r="5" style="animation: spinner-ball-triangle1 2.2s linear infinite"/>
3034    <circle cx="27" cy="5" r="5" style="animation: spinner-ball-triangle2 2.2s linear infinite"/>
3035    <circle cx="49" cy="50" r="5" style="animation: spinner-ball-triangle3 2.2s linear infinite"/>
3036</svg>
3037        <span class="text-xl select-none">
3038            Loading...        </span>
3039    </div>
3040</div>
3041    </div>
3042
3043</section>
3044</header><div class="top-container"><nav class="breadcrumbs bg-white" aria-label="Breadcrumb">
3045    <div class="container">
3046        <ol class="items list-reset py-5 rounded flex flex-wrap text-bodydark font-serif font-semibold text-xs">
3047                            <li class="item flex home items-center">
3048                                                    <a href="https://www.customandcommercial.com"
3049                       class="no-underline"
3050                       title="Go&#x20;to&#x20;Home&#x20;Page"
3051                    >Home</a>
3052                                </li>
3053                            <li class="item flex blog items-center">
3054                                    <span aria-hidden="true" class="separator text-ctaprimary px-2"><svg width="6" height="10" viewBox="0 0 6 10" fill="none" xmlns="http://www.w3.org/2000/svg">
3055<path d="M1.4375 1.875L4.5625 5L1.4375 8.125" stroke="#333333" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3056</svg></span>
3057                                                    <a href="https://www.customandcommercial.com/blog/"
3058                       class="no-underline"
3059                       title="Blog"
3060                    >Blog</a>
3061                                </li>
3062                    </ol>
3063    </div>
3064</nav>
3065</div><main id="maincontent" class="page-main"><div id="contentarea" tabindex="-1"></div>
3066<div class="page messages">
3066<script>
3067        function initMessages() {
3068        "use strict";
3069        return {
3070            messages: window.mageMessages || [],
3071            isEmpty() {
3072                return this.messages.reduce(
3073                    function (isEmpty, message) {
3074                        return isEmpty && message === undefined
3075                    }, true
3076                )
3077            },
3078            hasMessages() {
3079                return !this.isEmpty();
3080            },
3081            hasMessage() {
3082                return !!this.message;
3083            },
3084            removeMessage() {
3085                this.messages[this.index] = undefined;
3086            },
3087            addMessages(messages, hideAfter) {
3088                messages.map((message) => {
3089                    this.messages = this.messages.concat(message);
3090                    if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) {
3091                        hideAfter = window.defaultSuccessMessageTimeout;
3092                    }
3093                    if (hideAfter) {
3094                        this.setHideTimeOut(this.messages.length -1, hideAfter);
3095                    }
3096                });
3097            },
3098            setHideTimeOut(messageIndex, hideAfter) {
3099                setTimeout((messageIndex) => {
3100                    this.messages[messageIndex] = undefined;
3101                }, hideAfter, messageIndex);
3102            },
3103            eventListeners: {
3104                ['@messages-loaded.window'](event) {
3105                    this.addMessages(event.detail.messages, event.detail.hideAfter)
3106                },
3107                ['@private-content-loaded.window'](event) {
3108                    const data = event.detail.data;
3109                    if (
3110                        data.messages &&
3111                        data.messages.messages &&
3112                        data.messages.messages.length
3113                    ) {
3114                        this.addMessages(data.messages.messages);
3115                    }
3116                },
3117                ['@clear-messages.window']() {
3118                    this.messages = [];
3119                }
3120            },
3121            getMessageUiId() {
3122                return 'message-' + this.message.type;
3123            }
3124        }
3125    }
3126
3127    window.addEventListener('alpine:init', () => Alpine.data('initMessages', initMessages), {once: true})
3128</script>
3128
3129<section id="messages"
3130         x-data="initMessages"
3131         x-bind="eventListeners"
3132         role="alert"
3133>
3134    <template x-if="hasMessages">
3135        <div class="w-full">
3136            <div class="messages container mx-auto py-3">
3137                <template x-for="(message, index) in messages" :key="index">
3138                    <div>
3139                        <template x-if="hasMessage">
3140                            <div class="message"
3141                                 :class="message.type"
3142                                 :ui-id="getMessageUiId"
3143                            >
3144                                <span x-html="message.text"></span>
3145                                <button
3146                                    type="button"
3147                                    class="text-gray-600 hover:text-black"
3148                                    aria-label="Close message"
3149                                    @click.prevent="removeMessage"
3150                                >
3151                                    <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="stroke-current" width="18" height="18" aria-hidden="true">
3152  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
3153</svg>
3154                                </button>
3155                            </div>
3156                        </template>
3157                    </div>
3158                </template>
3159            </div>
3160        </div>
3161    </template>
3162</section>
3163</div>            <div class="header-container&#x20;flex&#x20;flex-col&#x20;md&#x3A;flex-row&#x20;flex-wrap&#x20;py-8&#x20;font-bold&#x20;page-title-wrapper&#x20;text-xl&#x20;md&#x3A;text-2xl">
3164            <h1 class="font-serif text-xl md:text-2xl text-[#212121] font-medium text-center"
3165                >
3166                <span class="base" data-ui-id="page-title-wrapper" >Blog</span>            </h1>
3167                    </div>
3168    <div class="columns"><div class="column main">    <div class="blog-filter flex w-full justify-end">
3169        <div class="mb-[50px] sm:w-[300px] w-full relative" x-data="initializeBlogFilter()">
3170            <button @click="toggleFilter" class="w-full border h-[50px] text-left px-5" :class="{'active': open}">
3171                <span x-text="currentCategory">Filter by category</span>
3172            </button>
3173            <ul class="absolute z-10 bg-white w-full border" x-show="open" x-transition.opacity>
3174                <li class="hover:bg-eaeaea py-2.5 px-5">
3175                    <a class="hover:text-red duration-300 w-full block" href="https://www.customandcommercial.com/blog/">
3176                        Filter by category                    </a>
3177                </li>
3178                <template x-for="category in allCategories">
3179                    <li class="hover:bg-eaeaea py-2.5 px-5" :class="{'bg-eaeaea': category.name === currentCategory}">
3180                        <a class="hover:text-red duration-300 w-full block" :href="category.url" x-text="category.name">
3181                            Filter by category                        </a>
3182                    </li>
3183                </template>
3184            </ul>
3185        </div>
3186        
3186<script>
3187            function initializeBlogFilter() {
3188                return {
3189                    open: false,
3190                    currentCategory: 'Filter by category',
3191                    allCategories: [{"name":"Uncategorized","slug":"uncategorized","url":"https:\/\/www.customandcommercial.com\/blog\/category\/uncategorized\/"}],
3192                    init() {
3193                        const segments = window.location.pathname.split('/').filter(Boolean);
3194
3195                        // Find "category" and get the next segment
3196                        const categoryIndex = segments.indexOf('category');
3197                        const category = categoryIndex !== -1 && segments.length > categoryIndex + 1
3198                            ? segments[categoryIndex + 1]
3199                            : null;
3200
3201                        let curCategory = this.allCategories.find(_ => _.slug === category);
3202                        if (curCategory) {
3203                            this.currentCategory = curCategory.name || 'Filter by category';
3204                        }
3205                    },
3206                    toggleFilter() {
3207                        this.open = !this.open;
3208                    }
3209                }
3210            }
3211        </script>
3211
3212    </div>
3213    <div class="post-list-wrapper">
3214        <ol class="post-list grid">
3215                                                                    <li class="item">
3216                            <div class="post-list-item">
3217                    <div class="post-entry">
3218                                                        <div class="post-image">
3219                        <a href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-wiper-blades/" title="Made By C&amp;C Product Feature: Wiper Blades">
3220                            <img src="https://www.customandcommercial.com/media/wordpress/1fe1b085e0bab4a92ccf79747f2456bf.jpg" alt="Made By C&amp;C Product Feature: Wiper Blades"/>
3221                        </a>
3222                                                    <div class="post-categories post-meta-item">
3223                                <a href="https://www.customandcommercial.com/blog/category/uncategorized/">Uncategorized</a>                            </div>
3224                                            </div>
3225
3226
3227                                <div class="post-content">
3228                    <h2>
3229                        <a href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-wiper-blades/" title="Made&#x20;By&#x20;C&amp;C&#x20;Product&#x20;Feature&#x3A;&#x20;Wiper&#x20;Blades">
3230                            Made By C&amp;C Product Feature: Wiper Blades                        </a>
3231                    </h2>
3232                    <div class="post-excerpt post-text">Looking for wiper blades for your VW?
3233We have them for all vehicles in different colours, sizes and finishes</div>
3234                    <a class="post-read-more hover:underline"
3235                       href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-wiper-blades/"
3236                       title="Made By C&C Product Feature: Wiper Blades"
3237                    >
3238                        Read more                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="w-[20x] h-[20px]" role="img">
3239<path d="M11.25 3.75L17.5 10M17.5 10L11.25 16.25M17.5 10H2.5" stroke="#E18438" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3240<title>arrow-right</title></svg>
3241                    </a>
3242                </div>
3243
3244            </div>
3245                <!--<div class="post-meta">
3246                            <div class="post-tags post-meta-item">
3247                    <strong><?/*= $block->escapeHtml(__('Tags')) */?>:</strong> <?/*= $block->escapeHtml($tagString, ['a']) */?>
3248                </div>
3249                        <div class="post-date post-meta-item">
3250                <strong><?/*= $block->escapeHtml(__('Posted On')) */?>:</strong> <?/*= $block->escapeHtml($post->getPostDate()) */?>
3251            </div>
3252            <div class="post-user post-meta-item">
3253                <strong><?/*= $block->escapeHtml(__('Posted By')) */?>:</strong> <a href="<?/*= $block->escapeUrl($post->getUser()->getUrl()) */?>"><?/*= $block->escapeHtml($post->getUser()->getDisplayName()) */?></a>
3254            </div>
3255        </div>-->
3256    </div>
3257                    </li>
3258                                                                                    <li class="item">
3259                            <div class="post-list-item">
3260                    <div class="post-entry">
3261                                                        <div class="post-image">
3262                        <a href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-fuel-filler-parts/" title="Made By C&amp;C Product Feature: Fuel Filler Parts">
3263                            <img src="https://www.customandcommercial.com/media/wordpress/c70652799c6c1fbc80d40df265d1651d.png" alt="Made By C&amp;C Product Feature: Fuel Filler Parts"/>
3264                        </a>
3265                                                    <div class="post-categories post-meta-item">
3266                                <a href="https://www.customandcommercial.com/blog/category/uncategorized/">Uncategorized</a>                            </div>
3267                                            </div>
3268
3269
3270                                <div class="post-content">
3271                    <h2>
3272                        <a href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-fuel-filler-parts/" title="Made&#x20;By&#x20;C&amp;C&#x20;Product&#x20;Feature&#x3A;&#x20;Fuel&#x20;Filler&#x20;Parts">
3273                            Made By C&amp;C Product Feature: Fuel Filler Parts                        </a>
3274                    </h2>
3275                    <div class="post-excerpt post-text">Looking For Fuel Filler Parts?
3276
3277If you need to replace your fuel filler parts, we have you covered</div>
3278                    <a class="post-read-more hover:underline"
3279                       href="https://www.customandcommercial.com/blog/2025/12/11/made-by-cc-product-feature-fuel-filler-parts/"
3280                       title="Made By C&C Product Feature: Fuel Filler Parts"
3281                    >
3282                        Read more                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 20 20" fill="none" class="w-[20x] h-[20px]" role="img">
3283<path d="M11.25 3.75L17.5 10M17.5 10L11.25 16.25M17.5 10H2.5" stroke="#E18438" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
3284<title>arrow-right</title></svg>
3285                    </a>
3286                </div>
3287
3288            </div>
3289                <!--<div class="post-meta">
3290                            <div class="post-tags post-meta-item">
3291                    <strong><?/*= $block->escapeHtml(__('Tags')) */?>:</strong> <?/*= $block->escapeHtml($tagString, ['a']) */?>
3292                </div>
3293                        <div class="post-date post-meta-item">
3294                <strong><?/*= $block->escapeHtml(__('Posted On')) */?>:</strong> <?/*= $block->escapeHtml($post->getPostDate()) */?>
3295            </div>
3296            <div class="post-user post-meta-item">
3297                <strong><?/*= $block->escapeHtml(__('Posted By')) */?>:</strong> <a href="<?/*= $block->escapeUrl($post->getUser()->getUrl()) */?>"><?/*= $block->escapeHtml($post->getUser()->getDisplayName()) */?></a>
3298            </div>
3299        </div>-->
3300    </div>
3301                    </li>
3302                                    </ol>
3303        
3304            <div class="grid items-center grid-flow-row grid-cols-4 gap-2 pager
3305            sm:grid-cols-8 md:grid-cols-4 lg:grid-cols-8">
3306    
3307            <p class="flex order-3 col-span-2 text-sm leading-5 text-gray-700
3308                toolbar-amount sm:order-2 md:order-3 lg:order-2 gap-x-1">
3309            <span class="toolbar-number">
3310                            2 Item(s)                        </span>
3311        </p>
3312    
3313    <div class="flex justify-center order-2 col-span-4">
3314            </div>
3315
3316    
3317            </div>
3318    
3319    </div><div class="widget block block-static-block">
3320    </div>
3321</div><aside class="sidebar sidebar-additional">
3322<script>
3323function compareSidebarFetchHandler(postUrl, postHeaders, isSingleItem = true) {
3324    const messages = {
3325        "success": isSingleItem
3326            ? "You removed product Product from the comparison list"
3327            : "You removed all products from the comparison list",
3328        "warning": isSingleItem
3329            ? "Could not remove item from compare."
3330            : "Could not remove all item from compare.",
3331    }
3332
3333    return fetch(postUrl, postHeaders).then(function (response) {
3334        if (response.redirected) {
3335            window.location.href = response.url;
3336        } else if (response.ok) {
3337            return response.json();
3338        } else {
3339            typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
3340                [{ type: "warning", text: messages.warning }], 5000
3341            );
3342        }
3343    }).then(function (response) {
3344        if (!response) return;
3345        typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
3346            [{
3347                type: (response.success) ? "success" : "error",
3348                text: (response.success) ? messages.success : response.error_message
3349            }], 5000
3350        );
3351        let reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data");
3352        window.dispatchEvent(reloadCustomerDataEvent);
3353    }).catch(function (error) {
3354        typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
3355            [{ type: "error", text: error }], 5000
3356        );
3357    });
3358}
3359
3360function initCompareOnCompareSidebar() {
3361    return {
3362        compareProducts: null,
3363        itemCount: 0,
3364        compareItems: {},
3365        receiveCompareData: function (data) {
3366            if (data['compare-products']) {
3367                this.compareProducts = data['compare-products'];
3368                this.itemCount = this.compareProducts.count;
3369                this.compareItems = this.compareProducts.items;
3370            }
3371        },
3372        removeFromCompare: function(productId) {
3373            const formKey = hyva.getFormKey();
3374            const postUrl = BASE_URL + 'catalog/product_compare/remove/';
3375            const confirmMessage = "Are you sure you want to remove this item from your Compare Products list?";
3376            if (!window.confirm(confirmMessage)) return;
3377            const postHeaders = {
3378                "headers": {
3379                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
3380                },
3381                "body": "form_key=" + formKey + "&product=" + productId + "&uenc=" 
3381+ hyva.getUenc(),
3382                "method": "POST",
3383                "mode": "cors",
3384                "credentials": "include"
3385            };
3386
3387            compareSidebarFetchHandler(postUrl, postHeaders);
3388        }
3389    }
3390}
3391
3392function initCompareSidebarClear() {
3393    return {
3394        clearCompare: function() {
3395            const formKey = hyva.getFormKey();
3396            const postUrl = BASE_URL + 'catalog/product_compare/clear/';
3397            const confirmMessage = "Are you sure you want to remove all items from your Compare Products list?";
3398            if (!window.confirm(confirmMessage)) return;
3399            const postHeaders = {
3400                "headers": {
3401                    "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
3402                },
3403                "body": "form_key=" + formKey + "&uenc=" + hyva.getUenc(),
3404                "method": "POST",
3405                "mode": "cors",
3406                "credentials": "include"
3407            };
3408
3409            compareSidebarFetchHandler(postUrl, postHeaders, isSingleItem = false);
3410        }
3411    }
3412}
3413</script>
3413
3414
3415<div x-data="initCompareOnCompareSidebar()"
3416     @private-content-loaded.window="receiveCompareData($event.detail.data)"
3417     class="compare-widget"
3418>
3419    <template x-if="itemCount">
3420        <div class="mt-8">
3421            <h2 class="border-t border-container mb-6 pt-5 font-semibold text-lg"
3422                id="compare-sidebar"
3423            >
3424                Compare Products            </h2>
3425            <ul role="list" class="my-4" aria-labelledby="compare-sidebar">
3426                <template x-for="product in compareItems">
3427                    <li class="flex items-start mb-4">
3428                        <a
3429                            :href="product.product_url"
3430                            class="block mb-3 w-10 h-10 shrink-0 mr-4"
3431                            aria-hidden="true"
3432                            tabindex="-1"
3433                        >
3434                            <img
3435                                :src="product.image"
3436                                alt=""
3437                                loading="lazy"
3438                            >
3439                        </a>
3440                        <strong class="mr-2 text-sm leading-6 font-normal">
3441                            <a :href="product.product_url" :title="product.name" x-html="product.name"></a>
3442                        </strong>
3443                        <button
3444                            type="button"
3445                            @click.prevent="removeFromCompare(product.id)"
3446                            :aria-label="hyva.str('Remove\u0020product\u0020\u0022\u00251\u0022\u0020from\u0020the\u0020comparison', product.name)"
3447                            class="p-1 inline-flex shrink-0 items-center justify-center text-slate-400
3448                                   hover:text-slate-800 ml-auto"
3449                        >
3450                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
3451  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
3452</svg>
3453                        </button>
3454                    </li>
3455                </template>
3456            </ul>
3457            <div class="flex flex-wrap items-center md:mt-5 gap-2 text-sm">
3458                <a href="https://www.customandcommercial.com/catalog/product_compare/index/"
3459                    title="Compare&#x20;Products"
3460                    class="btn btn-secondary text-sm">
3461                    <span>Compare</span>
3462                </a>
3463                <button x-data="initCompareSidebarClear()"
3464                    @click.prevent="clearCompare()"
3465                    aria-label="Remove&#x20;all&#x20;Products"
3466                    class="btn text-sm shadow-none bg-transparent text-inherit">
3467                    <span>Remove All</span>
3468                </button>
3469            </div>
3470        </div>
3471    </template>
3472</div>
3473
3474    
3474<script>
3475        function initWishlistOnWishlistSidebar() {
3476            function wishlistSidebarFetchHandler(body, postUrl, isRemoveAction = true) {
3477                const messages = {
3478                    "success": isRemoveAction
3479                        ? "\u00251\u0020has\u0020been\u0020removed\u0020from\u0020your\u0020Wish\u0020List."
3480                        : "\u00251\u0020has\u0020been\u0020added\u0020to\u0020your\u0020Wish\u0020List.",
3481                    "warning": isRemoveAction
3482                        ? "Could\u0020not\u0020remove\u0020item\u0020from\u0020your\u0020Wish\u0020List."
3483                        : "Could\u0020not\u0020add\u0020item\u0020to\u0020your\u0020Wish\u0020List.",
3484                }
3485
3486                const postHeaders = {
3487                    "headers": {
3488                        "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
3489                    },
3490                    body: body,
3491                    "method": "POST",
3492                    "mode": "cors",
3493                    "credentials": "include"
3494                };
3495
3496                return fetch(postUrl, postHeaders).then(function (response) {
3497                    if (response.redirected) {
3498                        window.location.href = response.url;
3499                    } else if (response.ok) {
3500                        return response.json();
3501                    } else {
3502                        const message = { type: "warning", text: messages.warning };
3503                        window.dispatchMessages && window.dispatchMessages([message], 5000);
3504                    }
3505                }).then(function (response) {
3506                    if (!response) return;
3507                    const message = {
3508                        type: (response.success) ? "success" : "error",
3509                        text: (response.success) ? messages.success : response.error_message
3510                    }
3511                    window.dispatchMessages && window.dispatchMessages([message], 5000);
3512                    window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
3513                }).catch(function (error) {
3514                    const message = { type: "error", text: error };
3515                    window.dispatchMessages && window.dispatchMessages([message], 5000);
3516                });
3517            }
3518
3519            return {
3520                wishlistProducts: null,
3521                itemCount: 0,
3522                wishlistCountLabel: null,
3523                wishlistItems: {},
3524                receiveWishlistData: function (data) {
3525                    if (data['wishlist']) {
3526                        this.wishlistProducts = data['wishlist'];
3527                        this.wishlistCountLabel = '(' + this.wishlistProducts.counter + ')';
3528                        this.itemCount = this.wishlistProducts.items.length;
3529                        this.wishlistItems = this.wishlistProducts.items;
3530                    }
3531                },
3532                addToCart: function (json) {
3533                    const obj = JSON.parse(json);
3534                    const postUrl = obj.action;
3535                    const body = "form_key=" + hyva.getFormKey() + "&item=" + obj.data.item + "&qty=" + obj.data.qty + "&uenc=" 
3535+ hyva.getUenc();
3536                    wishlistSidebarFetchHandler(body, postUrl, /* isRemoveAction */ false);
3537                },
3538                removeFromWishlist: function(json) {
3539                    const obj = JSON.parse(json);
3540                    const postUrl = obj.action;
3541                    const body = "form_key=" + hyva.getFormKey() + "&item=" + obj.data.item+"&uenc=" + hyva.getUenc();
3542                    wishlistSidebarFetchHandler(body, postUrl);
3543                }
3544            }
3545        }
3546
3547    </script>
3547
3548
3549    <div x-data="initWishlistOnWishlistSidebar()"
3550         @private-content-loaded.window="receiveWishlistData($event.detail.data)"
3551         class="wishlist-widget"
3552    >
3553        <template x-if="itemCount">
3554            <div class="mt-8">
3555                <h2 class="border-t border-container mb-6 pt-5" id="wishlist-sidebar">
3556                    <strong class="title font-semibold text-lg">My Wish List</strong>
3557                    <span class="counter text-xs" x-html="wishlistCountLabel"></span>
3558                </h2>
3559                <ul role="list" class="my-4" aria-labelledby="wishlist-sidebar">
3560                    <template x-for="product in wishlistItems">
3561                        <li class="flex items-start mb-4">
3562                            <a
3563                                :href="product.product_url"
3564                                class="block mb-3 w-10 h-10 shrink-0 mr-4"
3565                                tabindex="-1"
3566                                aria-hidden="true"
3567                            >
3568                                <img
3569                                    :src="product.image.src"
3570                                    alt=""
3571                                    loading="lazy"
3572                                >
3573                            </a>
3574                            <div class="product-item-details">
3575                                <strong class="mr-2 text-sm leading-6 font-normal">
3576                                    <a :href="product.product_url" :title="product.product_name" x-html="product.product_name"></a>
3577                                </strong>
3578                                <div class="mr-2 text-sm leading-6 font-bold" x-html="product.product_price"></div>
3579                                <template x-if="product.product_is_saleable_and_visible">
3580                                    <div class="actions-primary my-2">
3581                                        <template x-if="!product.product_has_required_options">
3582                                            <button
3583                                                type="button"
3584                                                @click.prevent="addToCart(product.add_to_cart_params)"
3585                                                class="action tocart primary btn btn-primary text-sm"
3586                                                :aria-label="hyva.str('Add\u0020to\u0020Cart\u0020\u00251', product.product_name)"
3587                                                data-addto="cart"
3588                                            >
3589                                                Add to Cart                                            </button>
3590                                        </template>
3591                                    </div>
3592                                </template>
3593                            </div>
3594                            <button
3595                                type="button"
3596                                @click.prevent="removeFromWishlist(product.delete_item_params)"
3597                                :aria-label="hyva.str('Remove\u0020product\u0020\u0022\u00251\u0022\u0020from\u0020My\u0020Wish\u0020List', product.product_name)"
3598                                class="
3599                                    p-1 inline-flex shrink-0 items-center
3600                                    justify-center text-slate-400 hover:text-slate-800 ml-auto
3601                                "
3602                            >
3603                                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="24" height="24" aria-hidden="true">
3604  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
3605</svg>
3606                            </button>
3607                        </li>
3608                    </template>
3609                </ul>
3610                <div class="flex flex-wrap items-center md:mt-5 gap-2 text-sm">
3611                    <a href="https://www.customandcommercial.com/wishlist/"
3612                       aria-label="Go&#x20;to&#x20;Wish&#x20;List&#x20;page"
3613                       class="btn btn-secondary text-sm"
3614                    >
3615                        Go to Wish List                    </a>
3616                </div>
3617            </div>
3618        </template>
3619    </div>
3620</aside></div></main><footer class="page-footer"><div class="footer content">
3620<script>
3621  addEventListener('DOMContentLoaded', () => {
3622      for (const [selector, label] of Object.entries({"aside.sidebar-main":"Sidebar Main","aside.sidebar-additional":"Sidebar Additional"})) {
3623          const target = document.querySelector(selector);
3624          target && target.setAttribute('aria-label', label);
3625      }
3626  }, {once: true})
3627</script>
3627
3628
3629<div class="px-5 bg-lightorange text-white">
3630    <div class="lg:container lg:flex lg:justify-between lg:gap-4 py-7">
3631        <div class="w-full lg:w-6/12 lg:mx-auto">
3632            <div class="reviews-io-rating-bar-widget"
3633              widget-id="9RBX5208MQlWNmAe"
3634             data-store-name="www.bullerltd.co.uk"
3635             lang="en"
3636             ></div>
3637            
3637<script src='//widget.reviews.io/modern-widgets/rating-bar.js'></script>
3637
3638        </div>
3639    </div>
3640</div>
3641<div class="bg-darkbrown font-serif text-white text-sm font-medium">
3642    <div class="container py-8 mx-auto">
3643        <div class="flex flex-col lg:flex-row">
3644                            
3645                                                        
3646        <div
3647        x-data="{
3648            open: true,
3649            isMobile: false,
3650            checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' }
3651        }"
3652        x-id="['collapse-id']"
3653        x-init="checkIsMobileResolution()"
3654        @resize.window.debounce="checkIsMobileResolution()"
3655        @visibilitychange.window.debounce="checkIsMobileResolution()"
3656        class="border-b border-white lg:border-b-0 last:border-b-0 w-full address-col  lg:w-4/12"
3657    >
3658
3659        <div
3660            :id="$id('collapse-id')"
3661            :role="isMobile && 'button'"
3662            :tabindex="isMobile && '0'"
3663            class="group flex w-full items-center justify-between pt-4 gap-2 font-bold text-white lg:pt-0"
3664            @click="isMobile && (open = !open)"
3665            @keyup.enter="isMobile && (open = !open)"
3666            @keyup.space="isMobile && (open = !open)"
3667            :aria-expanded="isMobile ? open : null"
3668            :aria-controls="isMobile ? $id('collapse-id') : null"
3669        >
3670                            <h5 class="font-serif text-sm text-semibold w-full pb-1.5">Custom &amp; Commercial</h5>
3671
3672                        <span
3673                class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
3674                x-ref="toggleIcon"
3675            >
3676                &nbsp;
3677            </span>
3678        </div>
3679        <div
3680            class="lg:block"
3681            :class="{ 'hidden': isMobile && !open }"
3682            :aria-labelledby="isMobile ? $id('collapse-id') : null"
3683            :aria-hidden="isMobile && (open ? 'false' : 'true')"
3684        >
3685            <div class="pt-0.5 pb-2.5">
3686                <address class="text-sm font-normal">
3687	<p>Unit 32 Bookham Industrial Estate<br>
3688    Church Rd<br>
3689    Great Bookham<br>
3690    Surrey<br>
3691    KT23 3EU</p>
3692</address>
3693<p class="text-sm font-bold">Email: <a href="mailto:[email protected]">[email protected]</a></p>
3694<div class="flex justify-start gap-3 pb-8 pt-2.5">
3695    <a
3696        href="https://www.instagram.com/candcparts/"
3697        target="_blank"
3698        rel="noopener noreferrer"
3699        class="text-white transition-colors"
3700    >
3701        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 32 32" role="img">
3702    <path d="M12.668 16a3.333 3.333 0 1 1 6.666 0 3.333 3.333 0 0 1-6.666 0Zm-1.802 0a5.135 5.135 0 1 0 10.27 0 5.135 5.135 0 0 0-10.27 0Zm9.273-5.338a1.2 1.2 0 1 0 1.2-1.2 1.2 1.2 0 0 0-1.2 1.2ZM11.96 24.14c-.975-.045-1.505-.207-1.857-.344a3.109 3.109 0 0 1-1.15-.748 3.086 3.086 0 0 1-.748-1.15c-.137-.352-.3-.882-.344-1.857-.048-1.054-.058-1.37-.058-4.04 0-2.671.01-2.987.058-4.042.045-.975.208-1.504.344-1.857.182-.467.398-.8.748-1.15.35-.35.683-.567 1.15-.748.352-.138.882-.3 1.857-.344C13.014 7.81 13.331 7.8 16 7.8c2.67 0 2.987.01 4.042.059.975.044 1.504.208 1.857.344.466.18.8.398 1.15.748.35.35.566.683.748 1.15.137.352.3.882.344 1.857.048 1.055.058 1.37.058 4.041 0 2.67-.01 2.986-.058 4.041-.044.975-.208 1.505-.344 1.857a3.1 3.1 0 0 1-.748 1.15 3.11 3.11 0 0 1-1.15.748c-.352.137-.882.3-1.857.344-1.055.048-1.371.058-4.042.058-2.67 0-2.986-.01-4.04-.058Zm-.082-18.08c-1.065.049-1.792.218-2.428.465A4.905 4.905 0 0 0 7.68 7.678 4.886 4.886 0 0 0 6.525 9.45c-.247.636-.416 1.363-.464 2.427-.05 1.066-.06 1.407-.06 4.123s.01 3.057.06 4.123c.048 1.064.217 1.791.464 2.427a4.888 4.888 0 0 0 1.154 1.771 4.916 4.916 0 0 0 1.771 1.154c.637.247 1.363.416 2.428.464 1.066.049 1.407.061 4.122.061 2.716 0 3.057-.011 4.123-.06 1.065-.049 1.792-.218 2.427-.465a4.917 4.917 0 0 0 1.772-1.154 4.899 4.899 0 0 0 1.153-1.77c.248-.637.417-1.364.465-2.428.048-1.067.06-1.407.06-4.123s-.012-3.057-.06-4.123c-.049-1.064-.217-1.792-.465-2.427a4.918 4.918 0 0 0-1.153-1.772 4.893 4.893 0 0 0-1.77-1.153c-.637-.247-1.364-.417-2.428-.464C19.058 6.012 18.717 6 16.001 6s-3.057.011-4.123.06Z"/>
3703<title>Follow us on Instagram</title></svg>
3704    </a>
3705    <a
3706        href="https://www.facebook.com/customandcommercial.vw/"
3707        target="_blank"
3708        rel="noopener noreferrer"
3709        class="text-white transition-colors"
3710    >
3711        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 32 32" role="img">
3712    <path d="M17.068 26.667v-9.732h3.267l.489-3.792h-3.756v-2.421c0-1.098.305-1.847 1.88-1.847h2.008V5.483c-.347-.046-1.54-.15-2.926-.15-2.896 0-4.878 1.768-4.878 5.013v2.797H9.877v3.793h3.275v9.73h3.916Z"/>
3713<title>Follow us on Facebook</title></svg>
3714    </a>
3715    <a
3716        href="https://twitter.com/candcparts"
3717        target="_blank"
3718        rel="noopener noreferrer"
3719        class="text-white transition-colors"
3720    >
3721        <?xml version="1.0" encoding="UTF-8"?>
3722<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 35 35" version="1.1" role="img">
3723    <title>Group 9@1x</title>
3724    <g id="🧠-Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
3725        <g id="Components-/-Footer-/-Desktop" transform="translate(-320, -465)">
3726            <g id="Group-7" transform="translate(220, 465)">
3727                <g id="Group-9" transform="translate(100, 0)">
3728                    <circle id="Oval-Copy-2" fill="#807E7E" cx="17.5" cy="17.5" r="17.5"/>
3729                    <g id="Icon/search-Copy-23" transform="translate(10, 10.625)" fill="#FFFFFF">
3730                        <path d="M11.8133496,-1.77635684e-15 L8.0230957,4.33242187 L4.74606445,-1.77635684e-15 L0,-1.77635684e-15 L5.67082031,7.41550781 L0.296162109,13.5585645 L2.59772461,13.5585645 L6.74595703,8.81856445 L10.3711816,13.5585645 L15,13.5585645 L9.08844727,5.74335937 L14.1133301,-1.77635684e-15 L11.8133496,-1.77635684e-15 Z M2.68602539,1.30450195 L4.05363281,1.30450195 L12.2806055,12.1817871 L11.0060449,12.1817871 L2.68602539,1.30450195 Z" id="Fill-1"/>
3731                    </g>
3732                </g>
3733            </g>
3734        </g>
3735    </g>
3736</svg>
3737    </a>
3738</div>
3739<div class="pb-8">
3740    <form
3741        class="form subscribe lg:max-w-[280px]"
3742        action="https://www.customandcommercial.com/newsletter/subscriber/new/"
3743        method="post"
3744        x-data="initNewsletterForm()"
3745        @submit.prevent="submitForm()"
3746        id="newsletter-validate-detail"
3747        aria-label="Subscribe&#x20;to&#x20;Newsletter"
3748    >
3749        <div class="text-white space-y-1 mb-5">
3750            <p class="font-normal">Sign up to our newsletter and receive our latest special offers and discounts</p>
3751        </div>
3752        <div class="flex flex-col gap-5">
3753            <label class="grow m-0">
3754                <span class="sr-only">Email Address</span>
3755                <input
3756                    type="email"
3757                    id="newsletter-subscribe"
3758                    name="email"
3759                    class="form-input w-full py-2.5 px-5 rounded-[5px]"
3760                    required
3761                    placeholder="Enter&#x20;your&#x20;email&#x20;address"
3762                >
3763                <input name="form_key" type="hidden" value="8yyKEOyvlaL6bVEW" />                            </label>
3764            
3765
3766<script data-cfasync="false">
3767    'use strict';
3768
3769    function initAmGdprCheckbox() {
3770        return {
3771            checked: false,
3772            consentId: null,
3773
3774            /**
3775             * @returns {void}
3776             */
3777            init: function () {
3778                this.checked = this.$refs['checkbox'].checked;
3779                this.consentId = this.$el.dataset.consentId;
3780            },
3781
3782            /**
3783             * @param {Event & { detail: string}} event
3784             * @returns {void}
3785             */
3786            consentAcceptedHandler: function ({  detail: acceptedConsentId }) {
3787                if (acceptedConsentId === this.consentId) {
3788                    this.checked = true;
3789                }
3790            },
3791
3792            /**
3793             * @param {Event & { target: HTMLElement }} event
3794             * @returns {void}
3795             */
3796            consentTextClickHandler: function ({ target }) {
3797                target.tagName === 'A' && this.openLink(target);
3798            },
3799
3800            /**
3801             * @param {HTMLLinkElement} linkNode
3802             * @returns {void}
3803             */
3804            openLink: function (linkNode) {
3805                const linkHref = linkNode.getAttribute('href');
3806                linkHref === '#'
3807                    ? this.$dispatch('amgdpr-show-policy', this.consentId)
3808                    : window.location.href = linkHref;
3809            }
3810        }
3811    }
3812
3813    window.addEventListener(
3814        'alpine:init',
3815        () => Alpine.data('initAmGdprCheckbox', initAmGdprCheckbox),
3816        { once: true }
3817    );
3818</script>
3818
3819<button class="shrink-0 btn justify-center rounded-[5px] py-2.5 px-5 text-base shadow-none hover:shadow-lg active:shadow transition bg-[#e18438] text-white border border-transparent hover:bg-[#e18438] active:bg-[#e18438] disabled:bg-[#e18438] disabled:bg-[#e18438]">
3820                Subscribe            </button>
3821        </div>
3822        <template x-if="displayErrorMessage">
3823            <p class="flex items-center text-red mt-2">
3824                <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="inline-block mr-3" width="24" height="24" role="img">
3825  <path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
3826<title>exclamation-circle</title></svg>
3827                <template x-for="errorMessage in errorMessages">
3828                    <span x-html="errorMessage"></span>
3829                </template>
3830            </p>
3831        </template>
3832    </form>
3833    <div class="w-full">
3834            </div>
3835    
3835<script>
3836        function initNewsletterForm() {
3837            return {
3838                errors: 0,
3839                hasCaptchaToken: 0,
3840                displayErrorMessage: false,
3841                errorMessages: [],
3842                setErrorMessages(messages) {
3843                    this.errorMessages = [messages]
3844                    this.displayErrorMessage = this.errorMessages.length
3845                },
3846                submitForm() {
3847                    // Do not rename $form, the variable is expected to be declared in the recaptcha output
3848                    const $form = document.querySelector('#newsletter-validate-detail');
3849                    
3850                    if (this.errors === 0) {
3851                        $form.submit();
3852                    }
3853                }
3854            }
3855        }
3856    </script>
3856
3857</div>
3858            </div>
3859        </div>
3860    </div>
3861                            
3862        <div
3863        x-data="{
3864            open: false,
3865            isMobile: false,
3866            checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' }
3867        }"
3868        x-id="['collapse-id']"
3869        x-init="checkIsMobileResolution()"
3870        @resize.window.debounce="checkIsMobileResolution()"
3871        @visibilitychange.window.debounce="checkIsMobileResolution()"
3872        class="border-b border-white lg:border-b-0 last:border-b-0 w-full shop-model-col  lg:w-4/12"
3873    >
3874
3875        <div
3876            :id="$id('collapse-id')"
3877            :role="isMobile && 'button'"
3878            :tabindex="isMobile && '0'"
3879            class="group flex w-full items-center justify-between pt-4 gap-2 font-bold text-white lg:pt-0"
3880            @click="isMobile && (open = !open)"
3881            @keyup.enter="isMobile && (open = !open)"
3882            @keyup.space="isMobile && (open = !open)"
3883            :aria-expanded="isMobile ? open : null"
3884            :aria-controls="isMobile ? $id('collapse-id') : null"
3885        >
3886                            <h5 class="font-serif text-base text-semibold uppercase pb-2 mb-4 lg:border-b lg:border-white w-full">Customer Service</h5>
3887                        <span
3888                class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
3889                x-ref="toggleIcon"
3890            >
3891                &nbsp;
3892            </span>
3893        </div>
3894        <div
3895            class="hidden lg:block"
3896            :class="{ 'hidden': isMobile && !open }"
3897            :aria-labelledby="isMobile ? $id('collapse-id') : null"
3898            :aria-hidden="isMobile && (open ? 'false' : 'true')"
3899        >
3900            <div class="pt-0.5 pb-2.5">
3901                
3902<nav aria-label="Customer Service">
3903    <ul>
3904        <li>
3905            <a
3906                href="https://www.customandcommercial.com/contact/"
3907                class="block pb-1.5 hover:underline"
3908            >Contact Us</a>
3909        </li>
3910        <li>
3911            <a
3912                href="https://www.customandcommercial.com/terms/"
3913                class="block pb-1.5 hover:underline"
3914            >Terms</a>
3915        </li>
3916        <li>
3917            <a
3918                href="https://www.customandcommercial.com/delivery/"
3919                class="block pb-1.5 hover:underline"
3920            >Delivery</a>
3921        </li>
3922        <li>
3923            <a
3924                href="https://www.customandcommercial.com/returns/"
3925                class="block pb-1.5 hover:underline"
3926            >Returns</a>
3927        </li>
3928        <li>
3929            <a
3930                href="https://www.customandcommercial.com/privacy-policy/"
3931                class="block pb-1.5 hover:underline"
3932            >Privacy Policy</a>
3933        </li>
3934        <li>
3935            <a
3936                href="https://www.customandcommercial.com/faqs/"
3937                class="block pb-1.5 hover:underline"
3938            >FAQs</a>
3939        </li>
3940    </ul>
3941</nav>
3942            </div>
3943        </div>
3944    </div>
3945                            
3946        <div
3947        x-data="{
3948            open: false,
3949            isMobile: false,
3950            checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' }
3951        }"
3952        x-id="['collapse-id']"
3953        x-init="checkIsMobileResolution()"
3954        @resize.window.debounce="checkIsMobileResolution()"
3955        @visibilitychange.window.debounce="checkIsMobileResolution()"
3956        class="border-b border-white lg:border-b-0 last:border-b-0 w-full shop-parts-col  lg:w-4/12"
3957    >
3958
3959        <div
3960            :id="$id('collapse-id')"
3961            :role="isMobile && 'button'"
3962            :tabindex="isMobile && '0'"
3963            class="group flex w-full items-center justify-between pt-4 gap-2 font-bold text-white lg:pt-0"
3964            @click="isMobile && (open = !open)"
3965            @keyup.enter="isMobile && (open = !open)"
3966            @keyup.space="isMobile && (open = !open)"
3967            :aria-expanded="isMobile ? open : null"
3968            :aria-controls="isMobile ? $id('collapse-id') : null"
3969        >
3970                            <h5 class="font-serif text-base text-semibold uppercase pb-2 mb-4 lg:border-b lg:border-white w-full">Useful Links</h5>
3971                        <span
3972                class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
3973                x-ref="toggleIcon"
3974            >
3975                &nbsp;
3976            </span>
3977        </div>
3978        <div
3979            class="hidden lg:block"
3980            :class="{ 'hidden': isMobile && !open }"
3981            :aria-labelledby="isMobile ? $id('collapse-id') : null"
3982            :aria-hidden="isMobile && (open ? 'false' : 'true')"
3983        >
3984            <div class="pt-0.5 pb-2.5">
3985                
3986<nav aria-label="Useful Links">
3987    <ul>
3988        <li>
3989            <a
3990                href="https://www.customandcommercial.com/ourdistributors/"
3991                class="block pb-1.5 hover:underline"
3992            >Our Distributors</a>
3993        </li>
3994        <li>
3995            <a
3996                href="https://www.customandcommercial.com/ourtraders/"
3997                class="block pb-1.5 hover:underline"
3998            >Our Traders</a>
3999        </li>
4000        <li>
4001            <a
4002                href="https://www.customandcommercial.com/blog/"
4003                class="block pb-1.5 hover:underline"
4004            >Blog</a>
4005        </li>
4006        <li>
4007            <a
4008                href="https://www.customandcommercial.com/newsletters/"
4009                class="block pb-1.5 hover:underline"
4010            >Newsletters</a>
4011        </li>
4012
4013        <li>
4014            <a
4015                href="https://www.customandcommercial.com/about-us/"
4016                class="block pb-1.5 hover:underline"
4017            >About Us</a>
4018        </li>
4019    </ul>
4020</nav>
4021            </div>
4022        </div>
4023    </div>
4024                            
4025        <div
4026        x-data="{
4027            open: false,
4028            isMobile: false,
4029            checkIsMobileResolution() { this.isMobile = getComputedStyle(this.$refs.toggleIcon).display !== 'none' }
4030        }"
4031        x-id="['collapse-id']"
4032        x-init="checkIsMobileResolution()"
4033        @resize.window.debounce="checkIsMobileResolution()"
4034        @visibilitychange.window.debounce="checkIsMobileResolution()"
4035        class="border-b border-white lg:border-b-0 last:border-b-0 w-full info-col  lg:w-4/12"
4036    >
4037
4038        <div
4039            :id="$id('collapse-id')"
4040            :role="isMobile && 'button'"
4041            :tabindex="isMobile && '0'"
4042            class="group flex w-full items-center justify-between pt-4 gap-2 font-bold text-white lg:pt-0"
4043            @click="isMobile && (open = !open)"
4044            @keyup.enter="isMobile && (open = !open)"
4045            @keyup.space="isMobile && (open = !open)"
4046            :aria-expanded="isMobile ? open : null"
4047            :aria-controls="isMobile ? $id('collapse-id') : null"
4048        >
4049                            <h5 class="font-serif text-base text-semibold uppercase pb-2 mb-4 lg:border-b lg:border-white w-full">Vehicles</h5>
4050                        <span
4051                class="transition-transform group-aria-expanded:rotate-180 lg:hidden"
4052                x-ref="toggleIcon"
4053            >
4054                &nbsp;
4055            </span>
4056        </div>
4057        <div
4058            class="hidden lg:block"
4059            :class="{ 'hidden': isMobile && !open }"
4060            :aria-labelledby="isMobile ? $id('collapse-id') : null"
4061            :aria-hidden="isMobile && (open ? 'false' : 'true')"
4062        >
4063            <div class="pt-0.5 pb-2.5">
4064                
4065<nav aria-label="Vehicles">
4066    <ul>
4067        <li>
4068            <a
4069                href="https://www.customandcommercial.com/brazilian-splitscreen.html"
4070                class="block pb-1.5 hover:underline"
4071            >Brazilian Splitscreen</a>
4072        </li>
4073        <li>
4074            <a
4075                href="https://www.customandcommercial.com/split-screen.html"
4076                class="block pb-1.5 hover:underline"
4077            >Split Screen</a>
4078        </li>
4079        <li>
4080            <a
4081                href="https://www.customandcommercial.com/beetle.html"
4082                class="block pb-1.5 hover:underline"
4083            >Beetle</a>
4084        </li>
4085        <li>
4086            <a
4087                href="https://www.customandcommercial.com/baywindow.html"
4088                class="block pb-1.5 hover:underline"
4089            >Baywindow</a>
4090        </li>
4091        <li>
4092            <a
4093                href="https://www.customandcommercial.com/brazilian-bay.html"
4094                class="block pb-1.5 hover:underline"
4095            >Brazilian Bay</a>
4096        </li>
4097        <li>
4098            <a
4099                href="https://www.customandcommercial.com/type-25.html"
4100                class="block pb-1.5 hover:underline"
4101            >Type 25</a>
4102        </li>
4103        <li>
4104            <a
4105                href="https://www.customandcommercial.com/type-3.html"
4106                class="block pb-1.5 hover:underline"
4107            >Type 3</a>
4108        </li>
4109        <li>
4110            <a
4111                href="https://www.customandcommercial.com/karmann-ghia.html"
4112                class="block pb-1.5 hover:underline"
4113            >Karmann Ghia</a>
4114        </li>
4115        <li>
4116            <a
4117                href="https://www.customandcommercial.com/t4.html"
4118                class="block pb-1.5 hover:underline"
4119            >T4</a>
4120        </li>
4121        <li>
4122            <a
4123                href="https://www.customandcommercial.com/t5.html"
4124                class="block pb-1.5 hover:underline"
4125            >T5</a>
4126        </li>
4127    </ul>
4128</nav>
4129<div class="lg:mt-4">
4130    <div class="flex gap-2.5 flex-wrap justify-start" aria-label="Payment Providers">
4131        <svg xmlns="http://www.w3.org/2000/svg" width="47" height="31" fill="none" viewBox="0 0 48 32" role="img"><g clip-path="url(#a)"><path fill="#fff" d="M0 4a4 4 0 0 1 4-4h40a4 4 0 0 1 4 4v24a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4z"/><path fill="#1434CB" d="M19.108 10.212 14.243 21.82H11.07l-2.393-9.263c-.146-.57-.272-.78-.714-1.02-.722-.391-1.913-.759-2.962-.987l.071-.337h5.109c.651 0 1.237.434 1.385 1.184l1.264 6.715 3.124-7.9zm12.435 7.817c.013-3.063-4.236-3.232-4.206-4.6.009-.417.405-.86 1.273-.973.43-.056 1.616-.099 2.96.52l.527-2.461A8.1 8.1 0 0 0 29.29 10c-2.968 0-5.056 1.578-5.074 3.837-.019 1.67 1.491 2.603 2.629 3.158 1.17.569 1.563.934 1.558 1.443-.008.778-.933 1.122-1.798 1.135-1.509.024-2.385-.408-3.083-.733l-.544 2.543c.702.322 1.997.603 3.339.617 3.154 0 5.218-1.558 5.227-3.97m7.837 3.79h2.777l-2.424-11.607H37.17c-.577 0-1.063.336-1.278.852L31.387 21.82h3.152l.626-1.734h3.852zm-3.35-4.113 1.58-4.358.91 4.358zm-12.632-7.494L20.915 21.82h-3.002l2.483-11.607z"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h48v32H0z"/></clipPath></defs><title>visa</title></svg>
4132        <svg xmlns="http://www.w3.org/2000/svg" width="47" height="31" fill="none" viewBox="0 0 48 32" role="img"><g clip-path="url(#a_2)"><path fill="#fff" d="M0 4a4 4 0 0 1 4-4h40a4 4 0 0 1 4 4v24a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4z"/><path fill="#FF5F00" d="M28.376 8.139h-8.75v15.725h8.75z"/><path fill="#EB001B" d="M20.181 16a9.98 9.98 0 0 1 3.82-7.861A9.96 9.96 0 0 0 17.82 6c-5.522 0-10 4.478-10 10s4.478 10 10 10A9.96 9.96 0 0 0 24 23.861 9.98 9.98 0 0 1 20.182 16"/><path fill="#F79E1B" d="M40.178 16c0 5.522-4.477 10-10 10-2.333 0-4.477-.8-6.18-2.139A9.98 9.98 0 0 0 27.818 16a9.98 9.98 0 0 0-3.82-7.861A9.96 9.96 0 0 1 30.178 6c5.522 0 10 4.478 10 10"/></g><defs><clipPath id="a_2"><path fill="#fff" d="M0 0h48v32H0z"/></clipPath></defs><title>mastercard</title></svg>
4133        <svg xmlns="http://www.w3.org/2000/svg" width="47" height="31" fill="none" viewBox="0 0 48 32" role="img"><g clip-path="url(#a_3)"><path fill="#fff" d="M0 4a4 4 0 0 1 4-4h40a4 4 0 0 1 4 4v24a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4z"/><path fill="#000" d="M13.422 11.356a2.62 2.62 0 0 0 .604-1.856 2.6 2.6 0 0 0-1.718.88 2.47 2.47 0 0 0-.615 1.793 2.12 2.12 0 0 0 1.729-.817m.605.944c-.955-.063-1.761.541-2.217.541s-1.157-.509-1.91-.498a2.81 2.81 0 0 0-2.397 1.453c-1.06 1.76-.265 4.38.732 5.823.488.71 1.06 1.496 1.835 1.464s1.008-.467 1.888-.467 1.146.467 1.91.456c.763-.01 1.293-.71 1.781-1.421a6.4 6.4 0 0 0 .796-1.644 2.57 2.57 0 0 1-1.549-2.344 2.61 2.61 0 0 1 1.252-2.207 2.73 2.73 0 0 0-2.121-1.156m8.305-1.983a3.34 3.34 0 0 1 3.51 3.51 3.393 3.393 0 0 1-3.563 3.48h-2.291v3.648h-1.666V10.317zm-2.344 5.643h1.92a2.005 2.005 0 0 0 2.259-2.122 1.983 1.983 0 0 0-2.249-2.121h-1.91zm6.29 2.821c0-1.358 1.06-2.196 2.895-2.302l2.122-.127v-.594c0-.87-.584-1.39-1.56-1.39a1.485 1.485 0 0 0-1.644 1.146h-1.506c.096-1.39 1.294-2.45 3.214-2.45s3.097 1.008 3.097 2.567v5.367H31.37v-1.283a2.76 2.76 0 0 1-2.46 1.41 2.364 2.364 0 0 1-2.631-2.344m5.027-.7v-.615l-1.92.116c-.954.064-1.495.488-1.495 1.157 0 .668.562 1.124 1.421 1.124a1.87 1.87 0 0 0 1.994-1.782m3.033 5.781V22.61q.26.024.52 0a1.305 1.305 0 0 0 1.39-1.06l.137-.478-2.81-7.86h1.728l1.973 6.365 1.962-6.365H41l
4133-2.917 8.189c-.657 1.888-1.432 2.493-3.044 2.493-.18 0-.573-.011-.7-.032"/></g><defs><clipPath id="a_3"><path fill="#fff" d="M0 0h48v32H0z"/></clipPath></defs><title>apple-pay</title></svg>
4134        <svg xmlns="http://www.w3.org/2000/svg" width="47" height="31" fill="none" viewBox="0 0 48 32" role="img"><g clip-path="url(#a_4)"><path fill="#fff" d="M0 4a4 4 0 0 1 4-4h40a4 4 0 0 1 4 4v24a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4z"/><path fill="#3C4043" d="M22.869 16.488v3.933H21.62v-9.712h3.309q1.259 0 2.139.838.897.84.897 2.048c0 .826-.3 1.508-.898 2.06q-.869.828-2.138.827h-2.061zm0-4.583v3.387h2.087c.494 0 .91-.17 1.235-.5.331-.332.5-.735.5-1.19a1.62 1.62 0 0 0-.5-1.177q-.486-.516-1.235-.514h-2.087zm8.361 1.651q1.383 0 2.183.741.8.74.8 2.029v4.095h-1.19v-.923h-.052q-.771 1.139-2.06 1.138-1.1.001-1.84-.65-.741-.652-.741-1.626 0-1.033.78-1.638.781-.613 2.08-.611 1.113 0 1.827.41v-.287c0-.435-.17-.8-.514-1.105a1.76 1.76 0 0 0-1.209-.455c-.695 0-1.248.293-1.651.884l-1.099-.689q.909-1.314 2.685-1.313m-1.613 4.824c0 .325.136.598.416.812q.411.324.968.325.79 0 1.405-.585.616-.583.617-1.371-.584-.46-1.625-.462-.76.002-1.268.364-.515.381-.513.917M41 13.77l-4.16 9.57h-1.288l1.547-3.348-2.743-6.221h1.359l1.976 4.771h.026l1.924-4.771z"/><path fill="#4285F4" d="M17.904 15.695q-.001-.61-.104-1.171h-5.232v2.145l3.013.001a2.58 2.58 0 0 1-1.118 1.728v1.392h1.794c1.047-.97 1.647-2.402 1.647-4.095"/><path fill="#34A853" d="M14.464 18.398c-.5.337-1.142.534-1.895.534-1.453 0-2.685-.98-3.127-2.3h-1.85v1.436a5.57 5.57 0 0 0 4.977 3.067c1.505 0 2.768-.494 3.688-1.346z"/><path fill="#FABB05" d="M9.268 15.568c0-.37.062-.729.174-1.065v-1.436h-1.85A5.54 5.54 0 0 0 7 15.568c0 .9.214 1.749.592 2.501l1.85-1.435a3.4 3.4 0 0 1-.174-1.066"/><path fill="#E94235" d="M12.57 12.204c.82 0 1.556.283 2.136.835l1.59-1.588c-.966-.9-2.224-1.451-3.727-1.451a5.57 5.57 0 0 0-4.977 3.067l1.85 1.436c.442-1.32 1.674-2.3 3.127-2.3"/></g><defs><clipPath id="a_4"><path fill="#fff" d="M0 0h48v32H0z"/></clipPath></defs><title>google-pay</title></svg>
4135        <svg xmlns="http://www.w3.org/2000/svg" width="47" height="31" viewBox="0 0 47 31" fill="none" class="bg-white rounded-[3px] p-1.5" role="img">
4136<path d="M3.5 0.5H43.5C45.1439 0.5 46.5 1.85614 46.5 3.5V27.5C46.5 29.1439 45.1439 30.5 43.5 30.5H3.50098C1.89739 30.4952 0.58863 29.2369 0.503906 27.6533L0.5 27.499V3.5C0.5 1.85614 1.85614 0.5 3.5 0.5Z" fill="white" stroke="#D8DADF"/>
4137<g clip-path="url(#clip0_2745_13775)">
4138<path d="M20.1333 11L19.2139 15.3856H19.2422C19.8505 14.4895 20.7277 14.0201 21.6473 14.0201C23.1471 14.0201 23.713 15.2343 23.713 16.4205C23.713 18.4618 22.199 21 19.4546 21C18.252 21 17.3467 20.5173 17.3467 19.2761C17.3467 18.9587 17.4031 18.5585 17.46 18.2411L18.959 11H20.1335H20.1333ZM18.6341 18.2685C18.5773 18.4893 18.535 18.7652 18.5489 19.1104C18.5489 19.7447 18.9169 20.1033 19.6527 20.1033C21.4211 20.1033 22.4962 18.0482 22.4962 16.572C22.4962 15.7442 22.1282 14.9718 21.1948 14.9718C20.1758 14.9718 19.1291 15.9923 18.7897 17.5654L18.6341 18.2684V18.2685ZM28.5651 20.8483C28.5651 20.4483 28.6363 19.8138 28.7206 19.124H28.6923C27.9424 20.5035 27.0086 21 26.0325 21C24.8303 21 24.0664 20.0625 24.0664 18.7928C24.0664 16.4758 25.8201 14.0203 28.8056 14.0203C29.4566 14.0203 30.1776 14.1307 30.6447 14.2826L29.9516 17.7586C29.7252 18.9175 29.6257 20.1041 29.6544 20.8485H28.5651V20.8483ZM29.3289 15.0274C29.1594 14.986 28.9047 14.9306 28.5084 14.9306C26.7401 14.9306 25.297 16.7379 25.2826 18.5859C25.2826 19.3307 25.5517 20.0623 26.4571 20.0623C27.4334 20.0623 28.5932 18.8206 28.933 17.0415L29.3289 15.0274ZM35.3255 19.6757C34.9717 19.8416 34.4344 20.0485 33.7409 20.0485C32.6236 20.0485 32.0434 19.3445 32.0434 18.2687C32.0434 16.6965 33.1611 14.9862 34.9432 14.9862C35.4531 14.9862 35.8343 15.1098 36.1033 15.2345L36.443 14.324C36.231 14.2137 35.6506 14.0343 35.014 14.0343C32.5528 14.0343 30.8268 16.131 30.8268 18.4068C30.8268 19.8281 31.6898 21.0002 33.4583 21.0002C34.3777 21.0002 35.085 20.7519 35.4388 20.5862L35.3255 19.6759V19.6757ZM36.1759 20.531C36.4874 20.7653 37.1378 20.986 37.8736 20.9996C39.3166 20.9996 40.4907 20.1998 40.4907 18.7928C40.4907 18.0484 39.9675 17.4691 39.2037 17.0416C38.5954 16.7101 38.2699 16.4067 38.2699 15.9241C38.2699 15.3446 38.779 14.9167 39.4869 14.9167C39.9957 14.9167 40.4342 15.0828 40.675 15.2205L41.0001 14.3516C40.7458 14.1859 40.1939 14.0204 39.5714 14.0204C38.1285 14.0204 37.0959 14.9169 37.0959 16.0896C37.0959 16.7657 37.5341 17.3584 38.3265 17.7863C39.0339 18.1723 39.2743 18.4896 39.2743 19.0137C39.2743 19.6069 38.7651 20.1037 37.9729 20.1037C37.421 20.1037 3
41386.8271 19.8826 36.5016 19.6899L36.1761 20.5313L36.1759 20.531Z" fill="black"/>
4139<path d="M7.76188 17.8014C7.37742 17.8014 7.00421 17.7677 6.6471 17.7057L7.9192 11.23C10.4213 11.2888 12.4241 12.7362 12.4241 14.5139C12.4241 16.2915 10.3367 17.8014 7.76188 17.8014ZM10.1115 18.1401C12.3909 17.6705 14.0479 16.255 14.0479 14.5793C14.0479 12.9036 12.3455 11.4499 10.018 11H9.4516C11.7929 11.3635 13.5449 12.8312 13.5449 14.588C13.5449 16.3449 11.6265 17.9499 9.12243 18.2209C9.18566 18.2184 9.24909 18.2171 9.31291 18.2141C9.58428 18.2003 9.85042 18.1744 10.1117 18.1399M11.34 11C13.7852 11.5112 15.5634 12.9361 15.6586 14.7013C15.7853 17.0384 12.9127 19.0865 9.24269 19.2749C8.22975 19.3273 7.2622 19.232 6.3895 19.0181L6 20.9983H11.8709C14.1992 20.983 15.6474 19.1346 16.0256 17.3261L17.2634 11H11.3398H11.34ZM15.1448 14.2633C15.0558 12.6199 13.1771 11.3251 10.6762 11H10.3984C12.8454 11.4509 14.6354 12.8821 14.6354 14.5791C14.6354 15.8658 13.6075 17.0006 12.0429 17.6707C13.9555 16.9664 15.221 15.675 15.1446 14.2633" fill="#E40138"/>
4140</g>
4141<defs>
4142<clipPath id="clip0_2745_13775">
4143<rect width="35" height="10" fill="white" transform="translate(6 11)"/>
4144</clipPath>
4145</defs>
4146<title>bacs</title></svg>
4147    </div>
4148</div>            </div>
4149        </div>
4150    </div>
4151                                                                            </div>
4152    </div>
4153    </div>
4154<div class="lower-footer bg-lightorange">
4155     <div class="container py-3.5 flex justify-between items-center flex-col sm:flex-row text-sm text-center">
4156        <small class="font-serif text-sm font-normal">
4157    <span>Copyright © 2026 Custom &amp; Commercial All right reserved</span>
4158</small>
4159        <nav aria-label="Legal">
4160            <ul class="m-0 p-0 list-none flex gap-4">
4161                <li class="m-0 p-0">
4162                    <a
4163                        href="https://www.customandcommercial.com/terms/"
4164                        class="block hover:underline"
4165                    >Terms &amp; Conditions</a>
4166                </li>
4167                <li class="m-0 p-0">
4168                    <a
4169                        href="https://www.customandcommercial.com/cookie-policy/"
4170                        class="block hover:underline"
4171                    >Cookie Policy</a>
4172                </li>
4173                <li class="m-0 p-0">
4174                    <a
4175                        href="https://www.customandcommercial.com/privacy-policy/"
4176                        class="block hover:underline"
4177                    >Privacy Policy</a>
4178                </li>
4179            </ul>
4180        </nav>
4181    </div>
4182</div>
4183</div></footer>
4184<div x-data="initAmGdprPolicyPopup" x-bind="eventListeners">
4185    <div x-cloak
4186         x-bind="overlay"
4187         class="fixed inset-0 flex items-center justify-center text-left bg-black bg-opacity-50 bg-black/50 z-40"
4188    >
4189        <div x-ref="amgdpr-policy-popup" role="dialog" aria-labelledby="amgdpr-policy-content"
4190             class="flex flex-col bg-white shadow-xl rounded-lg p-10 max-h-[95vh] max-w-6xl relative">
4191            <div tabindex="0" @focusin="focusAcceptButton"></div>
4192            <button @click="hidePopup"
4193                    x-ref="amgdpr-close-policy"
4194                    aria-label="Close"
4195                    class="absolute right-4 top-4 text-gray-300 transition
4196                    hover:text-black focus:drop-shadow-md hover:drop-shadow-md"
4197            >
4198                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="h-6 w-6" width="24" height="24" role="img">
4199  <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"/>
4200<title>x</title></svg>
4201            </button>
4202            <div class="flex w-full">
4203                <p class="w-full text-blue-500 text-3xl mb-5 ml-3" x-text="title"></p>
4204            </div>
4205            <div x-show="isNotificationTextVisible" class="flex w-full">
4206                <p class="mb-4 p-4 bg-yellow-100 w-full" x-text="notificationText"></p>
4207            </div>
4208            <div id="amgdpr-policy-content"
4209                 class="max-h-[500px] overflow-auto first:mx-0 child:mx-0"
4210                 tabindex="0"
4211                 x-html="policyText"
4212            ></div>
4213            <div class="mt-8 flex w-full justify-center">
4214                <button x-focus-first
4215                        @click="triggerAcceptPolicy"
4216                        x-ref="amgdpr-accept-policy"
4217                        type="button"
4218                        class="btn btn-primary uppercase font-bold"
4219                        aria-label="I&#x20;have&#x20;read&#x20;and&#x20;accept"
4220                >
4221                    I have read and accept                </button>
4222            </div>
4223            <div tabindex="0" @focusin="focusCloseButton"></div>
4224        </div>
4225
4226    </div>
4227</div>
4228
4229<script data-cfasync="false">
4230    'use strict';
4231
4232    /**
4233     * @typedef PolicyData
4234     * @property {string} policyVersion
4235     * @property {boolean} show
4236     * @property {string} title
4237     * @property{boolean} versionChanged
4238     * @property {boolean} hideClose
4239     * @property {boolean} action
4240     */
4241
4242    function initAmGdprPolicyPopup() {
4243        return {
4244            ...hyva.modal({
4245                dialog: 'amgdpr-policy-popup'
4246            }),
4247            eventListeners: {
4248                ['@amgdpr-accept-policy']() {
4249                    if (this.consentId) {
4250                        window.dispatchEvent(new CustomEvent('amgdpr-consent-accepted', {detail: this.consentId}));
4251                        this.consentId = undefined;
4252                        this.hidePopup();
4253                    } else {
4254                        this.acceptPolicy();
4255                    }
4256                },
4257                ['@amgdpr-show-policy.window'](event) {
4258                    this.consentId = event.detail;
4259                    this.fetchPolicyContent().then(() => {
4260                        this.$nextTick(() => {
4261                            this.showPopup();
4262                        });
4263                    });
4264                },
4265                ['@amgdpr-close-policy']() {
4266                    this.hidePopup();
4267                }
4268            },
4269            textUrl: 'https://www.customandcommercial.com/gdpr/policy/policytext/',
4270            acceptUrl: 'https://www.customandcommercial.com/gdpr/policy/accept/',
4271            popupDataUrl: 'https://www.customandcommercial.com/gdpr/policy/popupData/',
4272            notificationText: 'We would like to inform you that our Privacy Policy has been amended.Please, read and accept the new terms.',
4273            showOnPageLoad: false,
4274            /**
4275             * @type PolicyData
4276             */
4277            policyData: {
4278                policyVersion: '',
4279                show: false,
4280                title: '',
4281                versionChanged: false,
4282                hideClose: false,
4283                action: true
4284            },
4285            title: '',
4286            policyText: '',
4287            consentId: undefined,
4288            init: async function () {
4289                await this.fetchPolicyData();
4290                if ((this.showOnPageLoad && this.policyData.show) || this.policyData.versionChanged) {
4291                    await this.fetchPolicyContent();
4292                    this.$nextTick(() => {
4293                        this.show('amgdpr-policy-popup');
4294                    });
4295                }
4296            },
4297
4298            /**
4299             * @returns {void}
4300             */
4301            hidePopup: function () {
4302                this.hide('amgdpr-policy-popup');
4303            },
4304
4305            /**
4306             * @returns {void}
4307             */
4308            showPopup: function () {
4309                this.show('amgdpr-policy-popup');
4310            },
4311
4312            /**
4313             * @returns {void}
4314             */
4315            triggerAcceptPolicy: function () {
4316                this.$dispatch('amgdpr-accept-policy');
4317            },
4318
4319            /**
4320             * @returns {Boolean}
4321             */
4322            isNotificationTextVisible: function () {
4323                return this.notificationText && this.policyData.versionChanged;
4324            },
4325
4326            /**
4327             * @returns {Promise}
4328             */
4329            fetchPolicyData: function () {
4330                return fetch(this.popupDataUrl)
4331                    .then(response => response.json())
4332                    .then((data) => {
4333                        this.policyData = {...data}
4334                    })
4335                    .catch(error => this.dispatchErrorMessage(error));
4336            },
4337
4338            /**
4339             * @returns {Promise}
4340             */
4341            fetchPolicyContent: function () {
4342                this.title = '';
4343                this.policyText = '';
4344
4345                const params = !!this.consentId
4346                    ? '?' + new URLSearchParams({consent_id: this.consentId})
4347                    : ''
4348
4349                return fetch(this.textUrl + params)
4350                    .then(response => response.json())
4351                    .then(policyContent => {
4352                        this.title = policyContent.title;
4353                        this.policyText = policyContent.content;
4354                    }).catch(error => this.dispatchErrorMessage(error));
4355            },
4356
4357            /**
4358             * @returns {void}
4359             */
4360            acceptPolicy: function () {
4361                window.dispatchEvent(new Event('amgdpr-loading-start'));
4362
4363                const body = new URLSearchParams({form_key: hyva.getFormKey(), ...this.policyData});
4364                const contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
4365
4366                fetch(this.acceptUrl, {method: 'POST', body, headers: {'Content-Type': contentType}})
4367                    .then(response => response.json())
4368                    .then(data => {
4369                        if (data.error) {
4370                            this.dispatchErrorMessage(data.message)
4371                        } else {
4372                            this.notificationText = '';
4373                            this.hide('amgdpr-policy-popup');
4374                        }
4375                    })
4376                    .catch(error => this.dispatchErrorMessage(error))
4377                    .finally(() => window.dispatchEvent(new Event('amgdpr-loading-stop')));
4378            },
4379
4380            /**
4381             * @param {string} message
4382             * @returns {void}
4383             */
4384            dispatchErrorMessage: function (message) {
4385                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
4386                    {
4387                        type: "error",
4388                        text: message
4389                    }
4390                ]);
4391            },
4392
4393            /**
4394             * @returns {void}
4395             */
4396            focusAcceptButton: function () {
4397                this.$refs['amgdpr-accept-policy']?.focus();
4398            },
4399
4400            /**
4401             * @returns {void}
4402             */
4403            focusCloseButton: function () {
4404                this.$refs['amgdpr-close-policy']?.focus();
4405            }
4406        }
4407    }
4408
4409    window.addEventListener(
4410        'alpine:init',
4411        () => Alpine.data('initAmGdprPolicyPopup', initAmGdprPolicyPopup),
4412        { once: true }
4413    );
4414</script>
4414
4415
4416<script>
4417    (() => {
4418        function alpineSnapSlider(Alpine) {
4419            function roundUpIfGreaterThan(number, min = 8) {
4420                const decimalPart = number - Math.floor(number);
4421                return decimalPart >= min ? Math.ceil(number) : Math.floor(number);
4422            }
4423            Alpine.directive("snap-slider", (el, { modifiers }, { cleanup }) => {
4424                const track = el.querySelector("[data-track]");
4425                if (!track) {
4426                    console.warn(
4427                        "No Slider track defined, reverting back to CSS slider.\nPlease create a wrapper element for your slides with the attribute data-track"
4428                    );
4429                    return;
4430                }
4431                let initialLoad = true;
4432                let pager = el.querySelector("[data-pager]");
4433                let slides = [];
4434                let inViewObserver, mutationObserver, resizeObserver;
4435                const navBtns = Array.from(
4436                    el.querySelectorAll("[data-next], [data-prev]")
4437                );
4438                const slideLabelSepparator = el.dataset.slideLabelSepparator || "of";
4439                const useAutoPager = modifiers.includes("auto-pager");
4440                const useGroupPager = modifiers.includes("group-pager");
4441                const sliderLabel = el.hasAttribute("aria-label") && el.getAttribute("aria-label").toLowerCase().trim().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
4442                const sliderId = el.id || sliderLabel || "slider";
4443                const markerIdName = "data-target-id";
4444                const pagerClasses = el.dataset.pagerClass || "pager";
4445                const markerClasses = el.dataset.markerClass || "pager-item";
4446                function getInViewItems() {
4447                    const inViewSlides = track.querySelectorAll("[data-in-view]");
4448                    const firstInViewSlide = inViewSlides[0] || null;
4449                    const lastInViewSlide = inViewSlides[inViewSlides.length - 1] || null;
4450                    const isAtStart = firstInViewSlide === slides[0];
4451                    const isAtEnd = lastInViewSlide === slides[slides.length - 1];
4452                    return {
4453                        inViewSlides,
4454                        totalInViewSlides: inViewSlides.length,
4455                        firstInViewSlide,
4456                        lastInViewSlide,
4457                        isAtStart,
4458                        isAtEnd,
4459                        hasNoOverflow: isAtStart && isAtEnd
4460                    };
4461                }
4462                function groupPagerMarkers() {
4463                    if (!pager || !useGroupPager) return;
4464                    const totalVisibleSlides = roundUpIfGreaterThan(
4465                        track.offsetWidth / slides[0].offsetWidth
4466                    );
4467                    const markers = Array.from(pager.querySelectorAll("a, button"));
4468                    markers.forEach((marker, index) => {
4469                        marker.style.display = index % totalVisibleSlides === 0 ? null : "none";
4470                    });
4471                }
4472                function handleInView(entries) {
4473                    entries.forEach((entry) => {
4474                        const marker = pager && (pager.querySelector(`[href="#${entry.target.id}"]`) || pager.querySelector(
4475                            `[${markerIdName}="${entry.target.id}"]`
4476                        ));
4477                        entry.target.toggleAttribute(
4478                            "data-in-view",
4479                            entry.isIntersecting
4480                        );
4481                        entry.target.toggleAttribute("inert", !entry.isIntersecting);
4482                        marker?.setAttribute("aria-current", entry.isIntersecting);
4483                        marker?.setAttribute(
4484                            "tabindex",
4485                            entry.isIntersecting ? "0" : "-1"
4486                        );
4487                    });
4488                    const { isAtStart, isAtEnd, hasNoOverflow } = getInViewItems();
4489                    navBtns.forEach((btn) => {
4490                        if (btn.hasAttribute("data-next")) {
4491                            btn.style.visibility = hasNoOverflow ? "hidden" : null;
4492                            isAtEnd ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled");
4493                        }
4494                        if (btn.hasAttribute("data-prev")) {
4495                            btn.style.visibility = hasNoOverflow ? "hidden" : null;
4496                            isAtStart ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled");
4497                        }
4498                    });
4499                    if (pager) {
4500                        pager.style.visibility = hasNoOverflow ? "hidden" : null;
4501                    }
4502                    if (!initialLoad) {
4503                        el.dispatchEvent(
4504                            new CustomEvent("slideChange", { detail: getInViewItems() })
4505                        );
4506                    } else {
4507                        initialLoad = false;
4508                    }
4509                    if (document.activeElement.parentElement.hasAttribute("data-pager")) {
4510                        const activeItems = pager.querySelectorAll('[tabindex="0"]');
4511                        if (activeItems.length) {
4512                            activeItems[0].focus();
4513                        }
4514                    }
4515                }
4516                function getSlides() {
4517                    if (!track) return [];
4518                    return Array.from(track.children).filter(
4519                        (child) => child.tagName.toLowerCase() !== "template" && child.tagName.toLowerCase() !== "script"
4520                    );
4521                }
4522                function refreshSlides() {
4523                    initialLoad = true;
4524                    slides = getSlides();
4525                    setupSlides();
4526                    if (useAutoPager) {
4527                        createPager();
4528                    } else {
4529                        setupPager();
4530                    }
4531                    groupPagerMarkers();
4532                    setupObservers();
4533                }
4534                function setupSlides() {
4535                    slides = getSlides();
4536                    slides.forEach((slide, index) => {
4537                        const totalSlides = slides.length;
4538                        const currentSlide = index + 1;
4539                        const existingLabel = slide.getAttribute("aria-label") || "";
4540                        const isImage = slide.tagName.toLowerCase() === "img" || slide.tagName.toLowerCase() === "picture";
4541                        const slideLabelTag = isImage ? "alt" : "aria-label";
4542                        const hasAutoLabel = existingLabel.startsWith(`${currentSlide} ${slideLabelSepparator} `);
4543                        if (!slide.hasAttribute("id")) {
4544                            slide.setAttribute("id", `${sliderId}-item-${currentSlide}`);
4545                        }
4546
4547                        if ((!slide.hasAttribute(slideLabelTag) || slide.getAttribute(slideLabelTag) === "") || hasAutoLabel) {
4548                            slide.setAttribute(slideLabelTag, `${currentSlide} ${slideLabelSepparator} ${totalSlides}`);
4549                        }
4550
4551                        if (slide.tagName.toLowerCase() === "div" && !slide.hasAttribute("role")) {
4552                            slide.setAttribute("role", "group");
4553                        }
4554
4555                        if (pager && !isImage) {
4556                            slide.setAttribute("role", "tabpanel");
4557                        }
4558
4559                        if (slide.getAttribute('role') === "group") {
4560                            slide.setAttribute("aria-roledescription", "item");
4561                        }
4562                    });
4563                    if (!el.hasAttribute("role")) {
4564                        el.setAttribute("role", "region");
4565                    }
4566                    if (!el.hasAttribute("aria-roledescription")) {
4567                        el.setAttribute("aria-roledescription", "carousel");
4568                    }
4569                    track.setAttribute("tabindex", 0);
4570                    track.setAttribute("aria-live", "polite");
4571                }
4572                function setupNav() {
4573                    navBtns.forEach((btn) => {
4574                        btn.setAttribute("disabled", "");
4575                        btn.removeAttribute("hidden");
4576                        btn.classList.remove("invisible");
4577                        btn.style.visibility = null;
4578                    });
4579                }
4580                function createPager() {
4581                    const newPager = document.createElement("nav");
4582                    newPager.setAttribute("data-pager", "");
4583                    newPager.setAttribute("role", "tablist");
4584                    newPager.classList.add(...pagerClasses.split(" "));
4585
4586                    slides.forEach((slide, index) => {
4587                        const marker = document.createElement("button");
4588                        const slideId = slide.id || `${sliderId}-item-${index + 1}`;
4589                        marker.setAttribute(markerIdName, slideId);
4590                        marker.classList.add(...markerClasses.split(" "));
4591                        setupPagerMarker(marker, index);
4592                        newPager.appendChild(marker);
4593
4594                        if (slide.tagName.toLowerCase() !== "img" && slide.tagName.toLowerCase() !== "picture") {
4595                            slide.removeAttribute("aria-roledescription");
4596                            slide.setAttribute("role", "tabpanel");
4597                        }
4598                    });
4599
4600                    if (pager) {
4601                        pager.setAttribute("role", "tablist");
4602                        pager.replaceChildren(...newPager.children);
4603                    } else {
4604                        track.after(newPager);
4605                        pager = el.querySelector("[data-pager]");
4606                    }
4607                }
4608                function setupPager() {
4609                    if (!pager) return;
4610                    pager.setAttribute("role", "tablist");
4611                    const items = Array.from(pager.querySelectorAll("a, button"));
4612                    items.forEach((marker, index) => setupPagerMarker(marker, index));
4613                }
4614                function setupPagerMarker(marker, index) {
4615                    const markerId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(markerIdName);
4616                    const slideId = markerId || `${sliderId}-item-${index + 1}`;
4617                    if (!markerId) {
4618                        marker.setAttribute(markerIdName, slideId);
4619                    }
4620                    marker.setAttribute("role", "tab");
4621                    marker.setAttribute("aria-controls", slideId);
4622                    marker.setAttribute("aria-posinset", index + 1);
4623                    marker.setAttribute("aria-setsize", slides.length);
4624                    marker.setAttribute("tabindex", "-1");
4625                    if (!marker.hasAttribute("aria-label")) {
4626                        marker.setAttribute("aria-label", `Slide ${index + 1}`);
4627                    }
4628                }
4629                function setupObservers() {
4630                    if (inViewObserver) {
4631                        inViewObserver.disconnect();
4632                    }
4633                    inViewObserver = new IntersectionObserver(
4634                        handleInView.bind(track),
4635                        { root: track, threshold: 0.8 }
4636                    );
4637                    slides.forEach((slide) => inViewObserver.observe(slide));
4638                }
4639                function setupMutationObserver() {
4640                    mutationObserver = new MutationObserver(refreshSlides.bind(track));
4641                    mutationObserver.observe(track, {
4642                        childList: true,
4643                        subtree: false
4644                    });
4645                }
4646                function setupResizeObserver() {
4647                    resizeObserver = new ResizeObserver(groupPagerMarkers.bind(el));
4648                    resizeObserver.observe(el);
4649                }
4650                function goToSlideDir(dir = "next") {
4651                    const { firstInViewSlide, lastInViewSlide } = getInViewItems();
4652                    const isPrev = dir === "prev";
4653                    let targetSlide = isPrev ? firstInViewSlide?.previousElementSibling : lastInViewSlide?.nextElementSibling;
4654                    if (!targetSlide) return;
4655                    if (targetSlide.tagName.toLowerCase() === "template") {
4656                        targetSlide = isPrev ? targetSlide?.previousElementSibling : targetSlide?.nextElementSibling;
4657                    }
4658                    targetSlide.scrollIntoView({
4659                        block: "nearest",
4660                        inline: isPrev ? "end" : "start",
4661                        behavior: "smooth"
4662                    });
4663                }
4664                function pagerToSlide(event) {
4665                    if (!event.target.closest("[data-pager]")) return;
4666                    const marker = event.target.closest("a, button");
4667                    if (!marker) return;
4668                    event.preventDefault();
4669                    const slideId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(markerIdName);
4670                    const targetSlide = track.querySelector(`#${slideId}`);
4671                    targetSlide?.scrollIntoView({
4672                        block: "nearest",
4673                        inline: "start",
4674                        behavior: "smooth"
4675                    });
4676                }
4677                setupSlides();
4678                setupNav();
4679                if (useAutoPager) {
4680                    createPager();
4681                } else {
4682                    setupPager();
4683                }
4684                setupObservers();
4685                setupMutationObserver();
4686                setupResizeObserver();
4687                function eventHandler(event) {
4688                    const target = event.target.closest(
4689                        "[data-next], [data-prev], [data-pager]"
4690                    );
4691                    if (!target) return;
4692                    if (event.type === "click") {
4693                        if (target.hasAttribute("data-next")) {
4694                            goToSlideDir("next");
4695                        } else if (target.hasAttribute("data-prev")) {
4696                            goToSlideDir("prev");
4697                        } else if (target.closest("[data-pager]")) {
4698                            pagerToSlide(event);
4699                        }
4700                    }
4701                    if (event.type === "keydown" && target.closest("[data-pager]")) {
4702                        if (event.key === "ArrowRight") {
4703                            goToSlideDir("next");
4704                        } else if (event.key === "ArrowLeft") {
4705                            goToSlideDir("prev");
4706                        }
4707                    }
4708                }
4709                el.addEventListener("click", eventHandler);
4710                el.addEventListener("keydown", eventHandler);
4711                cleanup(() => {
4712                    inViewObserver?.disconnect();
4713                    mutationObserver?.disconnect();
4714                    resizeObserver?.disconnect();
4715                    el.removeEventListener("click", eventHandler);
4716                    el.removeEventListener("keydown", eventHandler);
4717                });
4718            });
4719        }
4720
4721        document.addEventListener("alpine:init", () => {
4722            window.Alpine.plugin(alpineSnapSlider);
4723        });
4724    })();
4725</script>
vendor: 1 bytes, line 4725
4725
4726<script>
4727    (() => {
4728        function src_default(Alpine) {
4729            Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => {
4730                let evaluate = evaluateLater(expression);
4731                let options = {
4732                    rootMargin: getRootMargin(modifiers),
4733                    threshold: getThreshold(modifiers)
4734                };
4735                let observer = new IntersectionObserver((entries) => {
4736                    entries.forEach((entry) => {
4737                        if (entry.isIntersecting === (value === "leave"))
4738                            return;
4739                        evaluate();
4740                        modifiers.includes("once") && observer.disconnect();
4741                    });
4742                }, options);
4743                observer.observe(el);
4744                cleanup(() => {
4745                    observer.disconnect();
4746                });
4747            }));
4748        }
4749        function getThreshold(modifiers) {
4750            if (modifiers.includes("full"))
4751                return 0.99;
4752            if (modifiers.includes("half"))
4753                return 0.5;
4754            if (!modifiers.includes("threshold"))
4755                return 0;
4756            let threshold = modifiers[modifiers.indexOf("threshold") + 1];
4757            if (threshold === "100")
4758                return 1;
4759            if (threshold === "0")
4760                return 0;
4761            return Number(`.${threshold}`);
4762        }
4763        function getLengthValue(rawValue) {
4764            let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/);
4765            return match ? match[1] + (match[2] || "px") : void 0;
4766        }
4767        function getRootMargin(modifiers) {
4768            const key = "margin";
4769            const fallback = "0px 0px 0px 0px";
4770            const index = modifiers.indexOf(key);
4771            if (index === -1)
4772                return fallback;
4773            let values = [];
4774            for (let i = 1; i < 5; i++) {
4775                values.push(getLengthValue(modifiers[index + i] || ""));
4776            }
4777            values = values.filter((v) => v !== void 0);
4778            return values.length ? values.join(" ").trim() : fallback;
4779        }
4780
4781        document.addEventListener("alpine:init", () => {
4782            window.Alpine.plugin(src_default);
4783        });
4784    })();
4785</script>
vendor: 1 bytes, line 4785
4785
4786<script>
4787    for (const [selector, deferUntil] of Object.entries({".product-slider section[x-data]":"intersect",".product-info [x-data]":"intersect","#filters-content [x-data]":"intersect","#review_form":"intersect","section[x-data^=initRecentlyViewedProductsComponent]":"intersect","div[x-data^=initBundleOptions]":"intersect","#product_addtocart_form [x-data]":"intersect","#notice-cookie-block":"idle"})) {
4788        document.querySelectorAll(selector).forEach(el => el.setAttribute('x-defer', `${deferUntil}`));
4789    }
4790</script>
vendor: 1 bytes, line 4790
4790
4791<script>
4792    (function () {
4793        "use strict";
4794
4795        const hasAlpine = new Promise(resolve => {
4796            window.addEventListener('alpine:initialized', resolve, {once: true, passive: true});
4797        });
4798
4799        const hasInteract = new Promise(resolve => {
4800            (events => {
4801                const onInteract = () => {
4802                    resolve();
4803                    events.forEach(type => window.removeEventListener(type, onInteract));
4804                }
4805                events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true}))
4806            })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown'])
4807        });
4808
4809        const onIntersect = (el) => {
4810            return new Promise(resolve => {
4811                const observer = new IntersectionObserver(entries => {
4812                    for (const entry of entries) {
4813                        if (entry.isIntersecting) {
4814                            observer.disconnect()
4815                            resolve();
4816                        }
4817                    }
4818                }, {});
4819                observer.observe(el);
4820            });
4821        }
4822
4823        function runComponent(el) {
4824            hasAlpine.then(() => {
4825                el.removeAttribute('x-ignore');
4826                queueMicrotask(() => Alpine.initTree(el));
4827            });
4828        }
4829
4830        function initDeferredComponents() {
4831            document.querySelectorAll('[x-data][x-defer]').forEach(el => {
4832                el.setAttribute('x-ignore', '');
4833                const deferUntil = (el.getAttribute('x-defer') || '').trim();
4834                switch (deferUntil) {
4835                    case 'interact':
4836                        hasInteract.then(() => runComponent(el));
4837                        break;
4838                    case 'intersect':
4839                        onIntersect(el).then(() => runComponent(el))
4840                        break;
4841                    case 'idle':
4842                        window.requestIdleCallback
4843                            ? window.requestIdleCallback(() => runComponent(el), {timeout: 4000})
4844                            : setTimeout(() => runComponent(el), 4000);
4845                        break;
4846                    case 'eager':
4847                        runComponent(el);
4848                        break;
4849                    default:
4850                        if (deferUntil.startsWith('event:') && deferUntil.length > 6) {
4851                            window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true});
4852                        }
4853                }
4854            });
4855        }
4856
4857        window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true});
4858    })()
4859</script>
vendor: 1 bytes, line 4859
4859
vendor: 4,405 bytes, lines 4860-4967
4860<script>
4861    (() => {
4862        // packages/collapse/src/index.js
4863        function src_default(Alpine) {
4864            Alpine.directive("collapse", collapse);
4865            collapse.inline = (el, {
4866                modifiers
4867            }) => {
4868                if (!modifiers.includes("min"))
4869                    return;
4870                el._x_doShow = () => {};
4871                el._x_doHide = () => {};
4872            };
4873
4874            function collapse(el, {
4875                modifiers
4876            }) {
4877                let duration = modifierValue(modifiers, "duration", 250) / 1e3;
4878                let floor = modifierValue(modifiers, "min", 0);
4879                let fullyHide = !modifiers.includes("min");
4880                if (!el._x_isShown)
4881                    el.style.height = `${floor}px`;
4882                if (!el._x_isShown && fullyHide)
4883                    el.hidden = true;
4884                if (!el._x_isShown)
4885                    el.style.overflow = "hidden";
4886                let setFunction = (el2, styles) => {
4887                    let revertFunction = Alpine.setStyles(el2, styles);
4888                    return styles.height ? () => {} : revertFunction;
4889                };
4890                let transitionStyles = {
4891                    transitionProperty: "height",
4892                    transitionDuration: `${duration}s`,
4893                    transitionTimingFunction: "cubic-bezier(0.4, 0.0, 0.2, 1)"
4894                };
4895                el._x_transition = {
4896                    in(before = () => {}, after = () => {}) {
4897                        if (fullyHide)
4898                            el.hidden = false;
4899                        if (fullyHide)
4900                            el.style.display = null;
4901                        let current = el.getBoundingClientRect().height;
4902                        el.style.height = "auto";
4903                        let full = el.getBoundingClientRect().height;
4904                        if (current === full) {
4905                            current = floor;
4906                        }
4907                        Alpine.transition(el, Alpine.setStyles, {
4908                            during: transitionStyles,
4909                            start: {
4910                                height: current + "px"
4911                            },
4912                            end: {
4913                                height: full + "px"
4914                            }
4915                        }, () => el._x_isShown = true, () => {
4916                            if (Math.abs(el.getBoundingClientRect().height - full) < 1) {
4917                                el.style.overflow = null;
4918                            }
4919                        });
4920                    },
4921                    out(before = () => {}, after = () => {}) {
4922                        let full = el.getBoundingClientRect().height;
4923                        Alpine.transition(el, setFunction, {
4924                            during: transitionStyles,
4925                            start: {
4926                                height: full + "px"
4927                            },
4928                            end: {
4929                                height: floor + "px"
4930                            }
4931                        }, () => el.style.overflow = "hidden", () => {
4932                            el._x_isShown = false;
4933                            if (el.style.height == `${floor}px` && fullyHide) {
4934                                el.style.display = "none";
4935                                el.hidden = true;
4936                            }
4937                        });
4938                    }
4939                };
4940            }
4941        }
4942
4943        function modifierValue(modifiers, key, fallback) {
4944            if (modifiers.indexOf(key) === -1)
4945                return fallback;
4946            const rawValue = modifiers[modifiers.indexOf(key) + 1];
4947            if (!rawValue)
4948                return fallback;
4949            if (key === "duration") {
4950                let match = rawValue.match(/([0-9]+)ms/);
4951                if (match)
4952                    return match[1];
4953            }
4954            if (key === "min") {
4955                let match = rawValue.match(/([0-9]+)px/);
4956                if (match)
4957                    return match[1];
4958            }
4959            return rawValue;
4960        }
4961
4962        // packages/collapse/builds/cdn.js
4963        document.addEventListener("alpine:init", () => {
4964            window.Alpine.plugin(src_default);
4965        });
4966    })();
4967</script>
4967
4968
4969<script>
4970    function createAjaxLoader() {
4971        const loader = document.createElement('div');
4972        loader.className = 'absolute inset-0 flex justify-center items-center loader';
4973        loader.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" class="w-full h-full p-2" role="img">
4974    <style>
4975        @keyframes spinner-ball-triangle1 {
4976            0% { transform: translate(0%, 0%); }
4977            33% { transform: translate(38%, -79%); }
4978            66% { transform: translate(77%, 0%); }
4979            100% { transform: translate(0%, 0%); }
4980        }
4981
4982        @keyframes spinner-ball-triangle2 {
4983            0% { transform: translate(0%, 0%); }
4984            33% { transform: translate(38%, 79%); }
4985            66% { transform: translate(-38%, 79%); }
4986            100% { transform: translate(0%, 0%); }
4987        }
4988
4989        @keyframes spinner-ball-triangle3 {
4990            0% { transform: translate(0%, 0%); }
4991            33% { transform: translate(-77%, 0%); }
4992            66% { transform: translate(-38%, -79%); }
4993            100% { transform: translate(0%, 0%); }
4994        }
4995    </style>
4996    <circle cx="5" cy="50" r="5" style="animation: spinner-ball-triangle1 2.2s linear infinite"/>
4997    <circle cx="27" cy="5" r="5" style="animation: spinner-ball-triangle2 2.2s linear infinite"/>
4998    <circle cx="49" cy="50" r="5" style="animation: spinner-ball-triangle3 2.2s linear infinite"/>
4999<title>Loading...</title></svg>
5000`;
5001        return loader;
5002    }
5003
5004    function addAjaxLoader(button, loader) {
5005        button.setAttribute('data-label', button.getAttribute('aria-label'));
5006        button.removeAttribute('aria-label');
5007        button.prepend(loader);
5008        button.classList.add('relative', '[&>:not(.loader)]:invisible');
5009        button.disabled = true;
5010    }
5011
5012    function removeAjaxLoader(button, loader) {
5013        button.setAttribute('aria-label', button.getAttribute('data-label'));
5014        button.removeAttribute('data-label');
5015        loader.remove();
5016        button.classList.remove('[&>:not(.loader)]:invisible');
5017        button.disabled = false;
5018    }
5019
5020    async function addAjaxCartForm(form, extraDelay = 500) {
5021        if (!form) return;
5022        event.preventDefault();
5023
5024        if (form.hasAttribute('enctype') || !form.reportValidity()) {
5025            return form.submit();
5026        }
5027
5028        const formData = new FormData(form);
5029        const button = form.querySelector('button:not([type=button], [type=reset])')
5030            ? form.querySelector('button:not([type=button], [type=reset])')
5031            : document.getElementById('product-addtocart-button');
5032        const loader = createAjaxLoader(button);
5033        const formUenc = hyva.getUenc();
5034        const postUrl = event.target.action.replace('%25uenc%25', formUenc);
5035
5036        let bodyUrl = new URLSearchParams(formData);
5037        bodyUrl.append("uenc", formUenc);
5038        addAjaxLoader(button, loader);
5039
5040        try {
5041            const response = await fetch(postUrl, {
5042                method: 'POST',
5043                body: bodyUrl.toString(),
5044                mode: "cors",
5045                credentials: "include",
5046                headers: {
5047                    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
5048                    'X-Requested-With': 'XMLHttpRequest'
5049                }
5050            });
5051
5052            if (!response.ok) {
5053                return form.submit();
5054            }
5055
5056            if (response.redirected) {
5057                return window.location.href = response.url;
5058            }
5059
5060            const responseData = await response.json();
5061            if (responseData.backUrl) {
5062                return window.location.href = responseData.backUrl;
5063            }
5064
5065            window.dispatchEvent(new CustomEvent("reload-customer-section-data"));
5066
5067                            const productFormData = {
5068                    productId: formData.get("product"),
5069                    options: {}
5070                }
5071
5072                for (const formEntry of formData.entries()) {
5073                    if (!formEntry[0].startsWith('super_attribute')) continue;
5074                    const formEntryOption = { [formEntry[0].match(/\[(\d+)\]/)[1]]: formEntry[
50741] };
5075                    productFormData.options = { ...productFormData.options, ...formEntryOption };
5076                }
5077
5078                window.dispatchEvent(new CustomEvent('open-ajax-cart', { detail: productFormData }));
5079                    } catch (err) {
5080            console.warn(err);
5081            window.dispatchEvent(new CustomEvent('product-addtocart-error'));
5082
5083            if (typeof window.dispatchMessages === "undefined") return;
5084            window.dispatchMessages([{
5085                text:'There\u0020was\u0020a\u0020problem\u0020adding\u0020your\u0020item\u0020to\u0020the\u0020cart.',
5086                type: 'error'
5087            }], 5000);
5088        } finally {
5089            setTimeout(() => removeAjaxLoader(button, loader), extraDelay);
5090        }
5091    }
5092
5093    function removeAjaxCartForm(form) {
5094        removeEventListener('submit', form);
5095    }
5096
5097    document.addEventListener('submit', function(event) {
5098        if (!event.target.matches('#product_addtocart_form, .product_addtocart_form')) return;
5099        addAjaxCartForm(event.target, 500);
5100    });
5101</script>
5101
5102
5103    <div x-data="initAjaxCartModal" x-bind="eventListeners"></div>
5104
5105
5106    
5106<script>
5107        function initAjaxCartModal() {
5108            return {
5109                open: false,
5110                cart: {},
5111                initialTotalCartAmount: 0,
5112                totalCartAmount: 0,
5113                cartItem: null,
5114                showSku: true,
5115                init() {
5116                    window.addEventListener('private-content-loaded', (event) => {
5117                        const cartData = event.detail.data && event.detail.data.cart;
5118                        if (!cartData) return;
5119
5120                        this.cart = cartData;
5121                        this.totalCartAmount = this.cart.summary_count;
5122                        this.initialTotalCartAmount = this.cart.summary_count;
5123                    }, { once: true });
5124
5125                    this.$watch('totalCartAmount', (value, oldValue) => {
5126                        if (this.initialTotalCartAmount === this.totalCartAmount) return;
5127                        this.initialTotalCartAmount = this.totalCartAmount;
5128                    })
5129                },
5130                sortObjectByNumberKey(obj) {
5131                    let keys = Object.keys(obj).map(Number).sort((a, b) => a - b);
5132                    let sortedObj = {};
5133                    keys.forEach(key => sortedObj[key] = obj[key]);
5134                    return sortedObj;
5135                },
5136                setNewCartData(event) {
5137                    const productData = event.detail;
5138                    window.addEventListener('private-content-loaded', (event) => {
5139                        const cartData = event.detail.data && event.detail.data.cart;
5140                        if (!cartData) return;
5141                        this.cart = cartData;
5142                        this.totalCartAmount = this.cart.summary_count;
5143
5144                        if (!productData) return;
5145                        this.getCurrentProductFromCart(productData);
5146                    });
5147                },
5148                getCurrentProductFromCart(productData) {
5149                    if (!this.cart.items) return;
5150                    this.cartItem = this.cart.items.filter((item) => {
5151                        if (item.product_id !== productData.productId) return;
5152                        if (item.product_type !== "configurable") {
5153                            return item;
5154                        }
5155
5156                        let cartItemOptions = {};
5157                        for (const option of item.options) {
5158                            const filterOptions = { [option.option_id]: option.option_value };
5159                            cartItemOptions = { ...cartItemOptions, ...filterOptions }
5160                        }
5161
5162                        const cartItemOptionsCompare = JSON.stringify(this.sortObjectByNumberKey(cartItemOptions));
5163                        const productDataOptionsCompare = JSON.stringify(this.sortObjectByNumberKey(productData.options));
5164                        if (cartItemOptionsCompare === productDataOptionsCompare) {
5165                            return item;
5166                        }
5167                    });
5168
5169                    if (this.cartItem > 1) {
5170                        this.cartItem = this.cartItem.slice(0, 1);
5171                    }
5172
5173                    this.cartItem = this.cartItem[0];
5174                },
5175                getItemCountText() {
5176                    if (this.totalCartAmount > 1) {
5177                        return hyva.str('(\u00251\u0020items)', this.totalCartAmount);
5178                    }
5179
5180                    return hyva.str('(\u00251\u0020item)', this.totalCartAmount);
5181                },
5182                getProductAlt() {
5183                    const name = this.$el.dataset.productName;
5184                    return name ? hyva.str('Product\u0020\u0022\u00251\u0022', name) : '';
5185                },
5186                hasCartItem() {
5187                    return !!this.cartItem;
5188                },
5189                canShowDetails() {
5190                    return (this.cartItem.options && this.cartItem.options.length > 0) || this.showSku;
5191                },
5192                canShowSku() {
5193                    return this.cartItem.product_sku && this.showSku;
5194                },
5195                openDialog() {
5196                    this.open = true;
5197                },
5198                closeDialog() {
5199                    this.open = false;
5200                },
5201                openAuthentication() {
5202                    this.closeDialog();
5203                    this.$dispatch('toggle-authentication', {
5204                        url: 'https://www.customandcommercial.com/checkout/'
5205                    });
5206                },
5207                eventListeners: {
5208                    ['@open-ajax-cart.window'](event) {
5209                        this.setNewCartData(event);
5210                                                    window.dispatchEvent(new CustomEvent('toggle-cart'));
5211                                                                    }
5212                }
5213            }
5214        }
5215        window.addEventListener('alpine:init', () => Alpine.data('initAjaxCartModal', initAjaxCartModal), { once: true });
5216    </script>
5216
5217    
5218<script type="module"
5219        src="https://www.customandcommercial.com/static/version1778675079/frontend/Actuate/c-and-c/en_US/Hyva_Theme/js/alpine3.min.js"
5220        defer
5221        crossorigin
5222></script>
vendor: 1 bytes, line 5222
5222
5223<script>try {
5224smileTracker.addPageVar('type.identifier', 'wordpress_postType_view');
5225smileTracker.addPageVar('type.label', '');
5226smileTracker.addPageVar('locale', 'en_US');
5227} catch (err) { ; }</script>
5227<script>
5228    'use strict';
5229    function dispatchMessages(messages, hideAfter) {
5230        const messagesEvent = new CustomEvent("messages-loaded", {
5231            detail: {
5232                messages: messages,
5233                hideAfter: hideAfter
5234            }
5235        });
5236        window.dispatchEvent(messagesEvent);
5237    }
5238
5239    if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
5240        console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
5241    }
5242
5243    (function( hyva, undefined ) {
5244
5245        hyva.initFormKey = () => {
5246            const inputSelector = 'input[name="form_key"]',
5247                formKey = hyva.getFormKey();
5248
5249            Array.from(document.querySelectorAll(inputSelector)).map(function (input) {
5250                input.value = formKey
5251            });
5252        }
5253
5254        hyva.initMessages = () => {
5255            try {
5256                const messages = hyva.getCookie('mage-messages');
5257                window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : [];
5258
5259                dispatchMessages(window.mageMessages);
5260
5261                                // empty `mage-messages` cookie
5262                const skipSetDomain = true;
5263                hyva.setCookie('mage-messages','', -1, skipSetDomain);
5264
5265            } catch (error) {
5266                console.warn('Error parsing Cookie Messages:', error);
5267            }
5268        }
5269
5270        window.addEventListener('DOMContentLoaded', hyva.initFormKey);
5271        hyva.alpineInitialized(hyva.initMessages)
5272
5273    }( window.hyva = window.hyva || {} ));
5274</script>
vendor: 1 bytes, line 5274
5274
5275<script>
5276    'use strict';
5277    {
5278        const private_content_key = 'mage-cache-storage';
5279        const private_content_expire_key = 'mage-cache-timeout';
5280        const private_content_version_key = 'private_content_version';
5281        const section_data_ids_key = 'section_data_ids';
5282        const mage_cache_session_id_key = 'mage-cache-sessid';
5283        const last_visited_store_key = 'last_visited_store';
5284
5285        const ttl = 3600;
5286
5287        if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) {
5288            console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script");
5289        }
5290
5291        function loadSectionData () {
5292            const browserStorage = hyva.getBrowserStorage();
5293            if (!browserStorage) {
5294                typeof window.dispatchMessages !== "undefined" && window.dispatchMessages(
5295                    [{
5296                        type: "warning",
5297                        text: "Please enable LocalStorage in your browser."
5298                    }]
5299                );
5300                return;
5301            }
5302            try {
5303                let isInvalid = false;
5304
5305                if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) {
5306                    isInvalid = true;
5307                }
5308                hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false);
5309
5310                if (!hyva.getCookie(mage_cache_session_id_key)) {
5311                    isInvalid = true;
5312                    browserStorage.removeItem(private_content_key);
5313                    const skipSetDomain = true;
5314                    const days = false;
5315                    hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain)
5316                }
5317
5318                const cookieVersion = hyva.getCookie(private_content_version_key);
5319                const storageVersion = browserStorage.getItem(private_content_version_key);
5320
5321                if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) {
5322                    isInvalid = true;
5323                }
5324
5325                const privateContentExpires = browserStorage.getItem(private_content_expire_key);
5326                if (privateContentExpires && new Date(privateContentExpires) < new Date()) {
5327                    browserStorage.removeItem(private_content_key);
5328                }
5329
5330                if (isInvalid && cookieVersion) {
5331                    fetchPrivateContent([]);
5332                } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) {
5333                    const privateContent = JSON.parse(browserStorage.getItem(private_content_key));
5334                    if (
5335                        privateContent &&
5336                        privateContentExpires &&
5337                        privateContent.cart &&
5338                        privateContent.customer
5339                    ) {
5340                        dispatchPrivateContent(privateContent);
5341                    } else {
5342                        fetchPrivateContent([]);
5343                    }
5344                } else {
5345                    if (document.getElementById('default-section-data')) {
5346                        const privateContent = JSON.parse(document.getElementById('default-section-data').innerText.trim());
5347                        dispatchPrivateContent(privateContent);
5348                    } else {
5349                        dispatchPrivateContent({});
5350                    }
5351                }
5352
5353            } catch (error) {
5354                console.warn('Error retrieving Private Content:', error);
5355            }
5356        }
5357
5358        hyva.alpineInitialized(loadSectionData)
5359        window.addEventListener('reload-customer-section-data', loadSectionData);
5360
5361        window.processSectionDataBeforeDispatch = window.processSectionDataBeforeDispatch || (data => data);
5362
5363        function dispatchPrivateContent(data) {
5364
5365            const privateContentEvent = new CustomEvent("private-content-loaded", {
5366                detail: {
5367                    data: window.processSectionDataBeforeDispatch(data)
5368                }
5369            });
5370            window.dispatchEvent(privateContentEvent);
5371        }
5372
5373        function fetchPrivateContent(sections) {
5374            fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, {
5375                method: 'GET',
5376                headers: {
5377                    'Content-Type': 'application/json',
5378                    'X-Requested-With': 'XMLHttpRequest'
5379                }
5380            })
5381                .then(response => response.ok && response.json())
5382                .then(
5383                    data => {
5384                        if (data) {
5385                            try {
5386                                const browserStorage = hyva.getBrowserStorage();
5387
5388                                // merge new data preserving non-invalidated sections
5389                                const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {};
5390
5391                                if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) {
5392                                    delete oldSectionData['checkout-data'];
5393                                }
5394                                const newSectionData = Object.assign(oldSectionData, data);
5395
5396                                dispatchPrivateContent(newSectionData);
5397
5398                                // don't persist messages, they've been dispatched already
5399                                if (newSectionData.messages && newSectionData.messages.messages ) {
5400                                    newSectionData.messages.messages = [];
5401                                }
5402
5403                                browserStorage.setItem(private_content_key, JSON.stringify(newSectionData));
5404
5405                                const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString();
5406                                browserStorage.setItem(private_content_expire_key, expiresAt);
5407
5408                                const newCookieVersion = hyva.getCookie(private_content_version_key);
5409                                browserStorage.setItem(private_content_version_key, newCookieVersion);
5410
5411                                // We don't need the section_data_ids in Hyvä, but we store them for compatibility
5412                                // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout
5413                                hyva.setCookie(
5414                                    section_data_ids_key,
5415                                    JSON.stringify(
5416                                        Object.keys(data).reduce((sectionDataIds, sectionKey) => {
5417                                            sectionDataIds[sectionKey] = data[sectionKey]['data_id'];
5418                                            return sectionDataIds;
5419                                        }, {})
5420                                    ),
5421                                    false,
5422                                    true
5423                                );
5424                            } catch (error) {
5425                                console.warn("Couldn't store privateContent", error);
5426                            }
5427                        }
5428                    }
5429                );
5430        }
5431    }
5432</script>
5432
5433<!-- View Model Identities:  -->
5433<script>
5434    (() => {
5435        document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc()));
5436    })()
5437</script>
vendor: 1 bytes, line 5437
5437
5438<script>
5439    (events => {
5440        const dispatchUserInteractionEvent = () => {
5441            events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent))
5442            window.dispatchEvent(new Event('init-external-scripts'))
5443        };
5444        events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true}))
5445    })(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown'])
5446</script>
vendor: 1 bytes, line 5446
5446
5447<script>
5448    function initConfigurableOptions(productId, optionConfig) {
5449
5450        function findPathParam(key) {
5451                        const baseUrl = (BASE_URL.substring(0, 2) === '//' ? 'http:' : '') + BASE_URL;
5452            const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/');
5453            const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3);
5454            for (let i = 0; i < pathParts.length; i += 2) {
5455                if (pathParts[i] === key && pathParts.length > i) {
5456                    return pathParts[i + 1];
5457                }
5458            }
5459        }
5460
5461        return {
5462            optionConfig,
5463            productId,
5464            itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'),
5465            allowedAttributeOptions: [],
5466            selectedValues: [],
5467            init() {
5468                this.findAllowedAttributeOptions();
5469                this.$nextTick(() => {
5470                    if (typeof this.optionConfig.defaultValues === 'object') {
5471                        for (const [attributeId, value] of Object.entries(this.optionConfig.defaultValues)) {
5472                            this.changeOption(attributeId, value + '');
5473                        }
5474                    }
5475                    this.preselectQuerystringItems();
5476                    this.preselectLocationHashItems();
5477                });
5478            },
5479            productIndex: 0,
5480            productIndexForPrice: 0,
5481            optionIsActive(attributeId, optionId) {
5482                                return !!this.getAllowedAttributeOptions(attributeId).find(
5483                    option => option.id === optionId
5484                )
5485            },
5486            optionIsEnabled(attributeId, optionId) {
5487                                for (const productId in this.optionConfig.index) {
5488                    if (this.optionConfig.index[productId][attributeId] === optionId) {
5489                        return true;
5490                    }
5491                }
5492                return false;
5493            },
5494            findSimpleIndex() {
5495                                this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues);
5496                this.productIndexForPrice = this.findCheapestProductForPartialSelection(this.selectedValues);
5497            },
5498            calculateSimpleIndexForPartialSelection(selectedValues) {
5499                if (selectedValues.length === 0) return 0;
5500                return this.findProductIdsForPartialSelection(selectedValues)[0];
5501            },
5502            calculateSimpleIndexForFullSelection(selectedValues) {
5503                if (! this.isFullSelection(selectedValues)) return false;
5504
5505                const productIndexes = this.optionConfig.index;
5506                return Object.keys(productIndexes).find(productIndex => {
5507                    const productCandidateOptions = productIndexes[productIndex];
5508
5509                    for (const productOption in productCandidateOptions) {
5510                        if (
5511                            !selectedValues[productOption] ||
5512                            selectedValues[productOption] !== productCandidateOptions[productOption]
5513                        ) {
5514                            return false;
5515                        }
5516                    }
5517                    return productIndex;
5518                });
5519            },
5520            findAllowedAttributeOptions() {
5521                                this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues);
5522            },
5523            calculateAllowedAttributeOptions(selectedValues) {
5524                const allAttributes = this.optionConfig.attributes;
5525                const allAttributesSorted = Object.values(allAttributes).sort((a,b) => {
5526                    return a.position - b.position
5527                });
5528
5529                const newAllowedAttributeOptions = [];
5530
5531                allAttributesSorted.forEach(attribute => {
5532                    const selectionWithoutAttr = Object.assign({}, this.removeAttrFromSelection(selectedValues, attribute.id));
5533                    const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr);
5534                    newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => {
5535                        return !!option.products.find(product => {
5536                            return availableIndexes.includes(product);
5537                        })
5538                    });
5539                });
5540                return newAllowedAttributeOptions;
5541            },
5542            calculateAvailableProductIndexes(selectedOptions) {
5543                if (Object.keys(selectedOptions).length === 0) {
5544                                        if (Object.values(this.optionConfig.salable || {}).length) {
5545                                                return [].concat.apply([], [].concat.apply([], Object.values(this.optionConfig.salable).map(Object.values))).filter((x, i, a) => a.indexOf(x) === i)
5546                    }
5547                                        return Object.keys(this.optionConfig.index);
5548                }
5549
5550                                const selectedIds = Object.keys(selectedOptions);
5551                if (Object.values(this.optionConfig.salable || {}).length) {
5552                                        const selectedOptionIndexes = selectedIds.map(attrId => {
5553                        const optionValue = selectedOptions[attrId];
5554                        return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || []
5555                    })
5556                                        return selectedOptionIndexes.reduce((acc, optionIndexes) => {
5557                        return acc.filter(index => optionIndexes.includes(index));
5558                    });
5559                } else {
5560                                        const productIndexes = this.optionConfig.index;
5561                    return Object.keys(productIndexes).filter(index => {
5562                                                for (const attrId of selectedIds) {
5563                            if (productIndexes[index][attrId] !== `${selectedOptions[attrId]}`) return false
5564                        }
5565                        return true
5566                    });
5567                }
5568            },
5569            findAttributeByOptionId(optionId) {
5570                for (const attributeId in this.optionConfig.attributes) {
5571                    const attributeOptions = this.optionConfig.attributes[attributeId].options || [];
5572                    if (attributeOptions.find(option => option.id === optionId)) {
5573                        return attributeId;
5574                    }
5575                }
5576            },
5577            getAllowedAttributeOptions(attributeId) {
5578                return this.allowedAttributeOptions[attributeId] || []
5579            },
5580            getAllAttributeOptions(attributeId) {
5581                return (
5582                    this.optionConfig.attributes[attributeId] &&
5583                    this.optionConfig.attributes[attributeId].options
5584                ) || []
5585            },
5586            getProductIdsForOption(option) {
5587                const attributeId = this.findAttributeByOptionId(option.id);
5588                const allOptions = this.optionConfig.attributes[attributeId];
5589                const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id);
5590                return opt && opt.products
5591                    ? opt.products
5592                    : [];
5593            },
5594            findProductIdsForPartialSelection(optionSelection) {
5595                const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => {
5596                    const newCandidates = this.getProductIdsForOption({id: optionId});
5597                    return candidates === null
5598                        ? newCandidates
5599                        : candidates.filter(productId => newCandidates.includes(productId));
5600                }, null);
5601                return candidateProducts || [];
5602            },
5603            findCheapestProductForPartialSelection(optionSelection) {
5604                const candidateProducts = this.findProductIdsForPartialSelection(optionSelection);
5605                return candidateProducts.reduce((cheapest, simpleIdx) => {
5606                    // in the first iteration we start with simpleIdx as the currently cheapest product
5607                    if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx;
5608                    const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount;
5609                    return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount
5610                        ? simpleIdx
5611                        : cheapest;
5612                }, 0)
5613            },
5614            findProductIdToUseForOptionPrice(option) {
5615                // try to find a product for a complete selection
5616                const attributeId = this.findAttributeByOptionId(option.id);
5617                const optionSelection = Object.assign({}, this.selectedValues, {[attributeId]: option.id});
5618                const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection);
5619                // if there is no complete selection, use the cheapest product for the option
5620                return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection);
5621            },
5622            getAttributeOptionLabel(option) {
5623                const optionProduct = this.findProductIdToUseForOptionPrice(option);
5624
5625                if ((! optionProduct) || (optionProduct === this.productIndexForPrice)) {
5626                    return option.label;
5627                }
5628
5629                const currentPrice = this.getOptionPriceAdjustmentBasePrice();
5630
5631                if (this.optionConfig.optionPrices[optionProduct]) {
5632                    const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount;
5633                    if (optionPrice !== currentPrice){
5634                        return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true);
5635                    }
5636                }
5637                return option.label;
5638            },
5639            getOptionPriceAdjustmentBasePrice() {
5640                if (this.optionConfig.optionPrices[this.productIndexForPrice]) {
5641                    return this.optionConfig.optionPrices[this.productIndexForPrice].finalPrice.amount
5642                }
5643                return this.optionConfig.prices.finalPrice.amount; // default price if no option selection
5644            },
5645            clearOptionIfActive(optionId, value) {
5646                if (this.selectedValues[optionId] === value) {
5647                    this.blurLabel()
5648                    this.changeOption(optionId, '')
5649                }
5650            },
5651            removeAttrFromSelection(selectedValues, attributeId) {
5652                                attributeId = parseInt(attributeId);
5653                return selectedValues.reduce((newSelection, val, attr) => {
5654                    if (attr !== attributeId) {
5655                        newSelection[attr] = val;
5656                    }
5657                    return newSelection;
5658                }, []);
5659            },
5660            changeOption(attributeId, value) {
5661                if (value === '') {
5662                    this.selectedValues = this.removeAttrFromSelection(this.selectedValues, attributeId)
5663                } else if (value && this.getAllowedAttributeOptions(attributeId).find(option => option.id === value)) {
5664                                        this.selectedValues[attributeId] = value;
5665                }
5666                this.findSimpleIndex();
5667                this.findAllowedAttributeOptions();
5668                this.updatePrices();
5669                this.updateGallery();
5670
5671                const candidates = this.findProductIdsForPartialSelection(this.selectedValues);
5672
5673                                window.dispatchEvent(
5674                    new CustomEvent(
5675                        'configurable-selection-changed',
5676                        {
5677                            detail: {
5678                                productId: this.productId,
5679                                optionId: attributeId,
5680                                value: value,
5681                                productIndex: this.productIndex,
5682                                selectedValues: this.selectedValues,
5683                                candidates: candidates,
5684                                skuCandidates: Object.values(candidates).map(id =>
5684 this.optionConfig.sku?.[id] ?? null).filter(Boolean),
5685                            }
5686                        }
5687                    )
5688                );
5689            },
5690            calculateIsMinimalPrice() {
5691                return ! this.isFullSelection(this.selectedValues);
5692            },
5693            isFullSelection(selectedValues) {
5694                return Object.values(selectedValues).length === Object.keys(this.optionConfig.attributes).length;
5695            },
5696            updatePrices() {
5697                const value = this.optionConfig.optionPrices[this.productIndexForPrice] || this.optionConfig.prices;
5698                window.dispatchEvent(
5699                    new CustomEvent(
5700                        "update-prices-" + this.productId,
5701                        {
5702                            detail: Object.assign(
5703                                value,
5704                                { isMinimalPrice: this.calculateIsMinimalPrice() }
5705                            )
5706                        }
5707                    )
5708                );
5709            },
5710            updateGallery () {
5711                if (this.productIndex) {
5712                    const images = this.optionConfig.images[this.productIndex];
5713                    images && window.dispatchEvent(new CustomEvent(
5714                        "update-gallery",
5715                        { detail: this.sortImagesByPosition(images) }
5716                    ));
5717                } else {
5718                    window.dispatchEvent(new Event("reset-gallery"));
5719                }
5720            },
5721            sortImagesByPosition(images) {
5722                return images.sort((x, y) => {
5723                    return x.position === y.position ? 0 : (parseInt(x.position) > parseInt(y.position) ? 1 : -1)
5724                });
5725            },
5726            onGetCartData(data) {
5727                            },
5728            preselectCartItems(data) {
5729                // pre-select options based on cart data for current (quote) itemId
5730                const cart = data && data.cart;
5731                if (cart && cart.items) {
5732                    const cartItem = cart.items.find((item) => {
5733                        return (
5734                            item.item_id === this.itemId
5735                            && item.product_id === this.productId
5736                        )
5737                    });
5738                    if (cartItem && cartItem.options && cartItem.options.length) {
5739                        cartItem.options.map(option => {
5740                            this.changeOption(option.option_id, option.option_value);
5741                        })
5742                    }
5743                }
5744            },
5745            preselectQuerystringItems() {
5746                // pre-select option like ?size=167
5747                const urlQueryParams = new URLSearchParams(window.location.search.replace('?',''));
5748                this.preselectItemsBasedOnLocation(attribute => urlQueryParams.get(attribute.code));
5749            },
5750            preselectLocationHashItems() {
5751                // pre-select option like #144=167
5752                const urlHashParams = new URLSearchParams(window.location.hash.replace('#',''));
5753                this.preselectItemsBasedOnLocation(attribute => urlHashParams.get(attribute.id));
5754            },
5755            preselectItemsBasedOnLocation(getLocationValue) {
5756                Object.values(this.optionConfig.attributes).map(attribute => {
5757                    const v = getLocationValue(attribute);
5758                    v && this.changeOption(attribute.id, v)
5759                });
5760            }
5761        }
5762    }
5763</script>
vendor: 1 bytes, line 5763
5763
5764<script>
5765    function initSwatchOptions(swatchConfig) {
5766        return {
5767            swatchConfig,
5768            getAttributeSwatchData(attributeId) {
5769                const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]);
5770                swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']);
5771
5772                return swatchConfig;
5773            },
5774            mapSwatchTypeNumberToTypeCode(typeNumber) {
5775                switch ("" + typeNumber) {
5776                    case "1":
5777                        return "color"
5778                    case "2":
5779                        return "image"
5780                    case "3":
5781                        return "empty"
5782                    case "0":
5783                    default:
5784                        return "text"
5785                }
5786            },
5787            getTypeOfFirstOption(attributeId) {
5788                for (const optionId in this.swatchConfig[attributeId]) {
5789                    const option = this.swatchConfig[attributeId][optionId];
5790                    if (typeof option.type !== 'undefined') {
5791                        return this.mapSwatchTypeNumberToTypeCode(option.type);
5792                    }
5793                }
5794            },
5795            getVisualSwatchType(attributeId, targetOptionId) {
5796                // If a type configuration is present for the given option id, use it
5797                const config = this.swatchConfig[attributeId];
5798                if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') {
5799                    return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type);
5800                }
5801
5802                // Otherwise - if no config is present for the target option - use the type of the first option
5803                // with a type property from the attribute, thus assuming its the same type as the target option.
5804                // (This edge case condition can occur on single swatch products if some options are not salable)
5805                return this.getTypeOfFirstOption(attributeId);
5806            },
5807            getSwatchType(attributeId, optionId) {
5808                // Deserialize the attribute details the first time they are used
5809                if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) {
5810                    this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId);
5811                }
5812                const type =  this.swatchConfig[attributeId] &&
5813                    this.swatchConfig[attributeId].details &&
5814                    this.swatchConfig[attributeId].details.swatch_input_type ||
5815                    "empty";
5816                return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type;
5817            },
5818            isTextSwatch(attributeId, optionId) {
5819                return this.getSwatchType(attributeId, optionId) === 'text';
5820            },
5821            isVisualSwatch(attributeId, optionId) {
5822                const type = this.getSwatchType(attributeId, optionId);
5823
5824                return ['image', 'color'].includes(type);
5825            },
5826            getSwatchBackgroundStyle(attributeId, optionId) {
5827                const config = this.getSwatchConfig(attributeId, optionId);
5828                const type = this.getSwatchType(attributeId, optionId);
5829
5830                if (type === "color") {
5831                        return 'background-color:' + config.value;
5832                } else if (type === "image") {
5833                        return "background: #fff url('" + config.value + "') no-repeat center";
5834                } else {
5835                    return '';
5836                }
5837            },
5838            getSwatchText(attributeId, optionId) {
5839                const config = this.getSwatchConfig(attributeId, optionId);
5840                return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId);
5841            },
5842            getOptionLabelFromOptionConfig(attributeId, optionId) {
5843                // Fallback if no value is present in swatchConfig data
5844                // Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190
5845                const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId);
5846                return option && option[0] && option[0].label ||'';
5847            },
5848            getSwatchConfig(attributeId, optionId) {
5849                return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId]
5850                    ? this.swatchConfig[attributeId][optionId]
5851                    : false;
5852            },
5853            activeTooltipItem: false,
5854            tooltipPositionElement: false,
5855            isTooltipVisible() {
5856                return this.activeTooltipItem &&
5857                    this.getSwatchConfig(
5858                        this.activeTooltipItem.attribute,
5859                        this.activeTooltipItem.item
5860                    );
5861            },
5862            isFirstItemCol() {
5863                return this.activeTooltipItem.index === 0;
5864            },
5865            getTooltipImageStyle(attributeId, optionId) {
5866                const config = this.getSwatchConfig(attributeId, optionId);
5867                const type = this.getSwatchType(attributeId, optionId);
5868
5869                if (type === "color") {
5870                    return 'background-color:' + config.value + '; width: 110px; height: 90px;';
5871                } else if (type === "image") {
5872                    return "background: #ffffff url('" + config.thumb +
5873                        "') center center no-repeat; width: 110px; height: 90px;";
5874                } else {
5875                    return 'display:none';
5876                }
5877            },
5878            getTooltipPosition() {
5879                return this.tooltipPositionElement ?
5880                    `top: ${this.tooltipPositionElement.offsetTop}px;` +
5881                    `left: ${
5882                        this.tooltipPositionElement.offsetLeft - (
5883                            this.tooltipPositionElement.closest('.snap') &&
5884                            this.tooltipPositionElement.closest('.snap').scrollLeft ||
5885                            0
5886                        )
5887                    }px;` : ''
5888            },
5889            getTooltipLabel() {
5890                return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label
5891            },
5892            focusedLabel: false,
5893            focusLabel(optionId) {
5894                this.focusedLabel = optionId;
5895            },
5896            blurLabel() {
5897                this.focusedLabel = false;
5898            },
5899            showSwatches: false,
5900            initShowSwatchesIntersect() {
5901                if ('IntersectionObserver' in window && !window.scrollY) {
5902                    let io = new IntersectionObserver(
5903                        entries => {
5904                            entries.map(entry => {
5905                                if (entry.isIntersecting) {
5906                                    this.showSwatches = true;
5907                                    io.unobserve(this.$root);
5908                                }
5909                            })
5910                        }
5911                    );
5912                    io.observe(this.$root);
5913                } else {
5914                    this.showSwatches = true
5915                }
5916            }
5917        }
5918    }
5919</script>
vendor: 1 bytes, line 5919
5919
5920<script>
5921    'use strict';
5922
5923    const grecaptchaV2LoadCallbacks = [];
5924
5925    function executeRecaptchaLoadCallbacks () {
5926        while (window.grecaptcha && grecaptchaV2LoadCallbacks.length > 0) {
5927            const callback = grecaptchaV2LoadCallbacks.pop();
5928            typeof callback === 'string' ? window[callback]() : callback();
5929        }
5930    }
5931
5932    (function() {
5933        const loadRecaptchaScript = (event) => {
5934
5935            if (window.grecaptcha || !event.target.form) {
5936                return;
5937            }
5938
5939            const url = 'https://www.google.com/recaptcha/api.js?onload=executeRecaptchaLoadCallbacks';
5940            const siteKey = '';
5941            const script = document.createElement('script');
5942            script.type = 'text/javascript';
5943            script.src = siteKey ? `${url}&render=${siteKey}` : `${url}&render=explicit`;
5944            script.async = true;
5945            document.head.appendChild(script);
5946
5947            script.addEventListener('load', () => {
5948                Array.from(document.querySelectorAll('button[data-recaptcha-btn]:disabled')).forEach(btn => btn.removeAttribute('disabled'));
5949            });
5950        }
5951
5952        window.forceLoadRecaptchaScript = (form) => {
5953            loadRecaptchaScript({target: {form: form || 'dummy'}});
5954            executeRecaptchaLoadCallbacks();
5955        };
5956
5957        document.body.addEventListener('input', loadRecaptchaScript, { once: true });
5958        document.body.addEventListener('focus', loadRecaptchaScript, { once: true });
5959
5960    }());
5961
5962</script>
vendor: 1 bytes, line 5962
5962
5963<script>
5964    'use strict';
5965
5966    (function () {
5967        const modals = [];
5968        const excludedFromFocusTrapping = new Set();
5969
5970        function trapFocusInNextModalWithOverlay() {
5971            for (let idx = modals.length -1; idx >= 0; idx--) {
5972                const nextOnStack = modals[idx];
5973                const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name];
5974                if (! isOverlayDisabled(nextDialogElement)) {
5975                    hyva.trapFocus(nextDialogElement);
5976                    break;
5977                }
5978            }
5979        }
5980
5981        function focusables(dialogElement) {
5982            const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
5983            return Array.from(dialogElement.querySelectorAll(selector))
5984                .filter(el => !el.hasAttribute('disabled'));
5985        }
5986
5987        function firstVisible(elements) {
5988            const a = Array.from(elements);
5989            for (let i = 0; i < a.length; i++) {
5990                if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i];
5991            }
5992            return null;
5993        }
5994
5995        function isInViewport(element) {
5996            const rect = element && element.getBoundingClientRect();
5997            return rect &&
5998                rect.top >= 0 &&
5999                rect.left >= 0 &&
6000                rect.right <= window.innerWidth &&
6001                rect.bottom <= window.innerHeight;
6002        }
6003
6004        function setFocusAfterTransition(dialogElement, duration) {
6005                        const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]'));
6006            const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]'));
6007            next: for (let candidate of candidates) {
6008                for (let child of nested) {
6009                    if (child.contains(candidate)) continue next;
6010                }
6011                setTimeout(() => candidate.focus(), 50);
6012                break;
6013            }
6014            window.setTimeout(() => {
6015                const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
6016                    focusables(dialogElement)[0] ||
6017                    null;
6018                focusElement && isInViewport(focusElement) && focusElement.focus();
6019            }, Math.max(1, duration));
6020        }
6021
6022        function determineTrigger($refs, dialog, trigger) {
6023                        if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) {
6024                return dialog.target;
6025            }
6026                        if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) {
6027                return trigger.target;
6028            }
6029                        if (typeof trigger === 'string') {
6030                try {
6031                    return $refs[trigger] || document.querySelector(trigger)
6032                } catch (e) {}
6033            }
6034                        if (trigger instanceof Element) {
6035                return trigger;
6036            }
6037
6038                        return null;
6039        }
6040
6041        function isOverlayDisabled(dialog) {
6042            return dialog && dialog.hasAttribute('x-no-overlay')
6043        }
6044
6045        function areRemainingModalsWithoutOverlay(modals)
6046        {
6047            const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled);
6048
6049            return overflowDisabled.length === modals.length;
6050        }
6051
6052        window.hyva.modal = function(options = {}) {
6053                        if (this.$el && this.$el.dataset && this.$el.dataset.options) {
6054                try {
6055                    options = Object.assign(options, JSON.parse(this.$el.dataset.options || '{}'));
6056                } catch (e) {
6057                    throw new Error('Cannot read the dialog options from the data-options attribute: not valid JSON');
6058                }
6059            }
6060
6061            const config = Object.assign({
6062                dialog: 'dialog',                 duration: 300,                 transitionEnter: 'transition ease-out duration-300',
6063                transitionEnterStart: 'opacity-0',
6064                transitionEnterEnd: 'opacity-100',
6065                transitionLeave: 'transition ease-in duration-300',
6066                transitionLeaveStart: 'opacity-100',
6067                transitionLeaveEnd: 'opacity-0',
6068            }, options);
6069            let lastHide = 0;
6070
6071            return {
6072                opened: {},
6073                show(dialog, trigger) {
6074                    const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger);
6075                    const name = typeof dialog === 'string' ? dialog : config.dialog;
6076                    const dialogElement = this.$refs[name];
6077                    if (! dialogElement) {
6078                                                console.error(`Use $modal->getShowJs() in the open trigger, or specify a custom name with\n$modal->withDialogRefName("my-name") and use show("my-name", $event).`);
6079                                                return;
6080                    }
6081                    const useOverlay = ! dialogElement.hasAttribute('x-no-overlay');
6082
6083                    dialogElement.scrollTop = 0;
6084
6085                                        if (this.opened[name]) {
6086                        return;
6087                    }
6088
6089                    if (focusTargetAfterHide) {
6090                        focusTargetAfterHide.setAttribute('aria-expanded', 'true');
6091                    }
6092
6093                    this.opened[name] = true;
6094                    useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement));
6095                    setFocusAfterTransition(dialogElement, config.duration);
6096
6097                    const frame = {name, instance: this, focusTarget: focu
6097sTargetAfterHide, time: Date.now()};
6098
6099                    modals.push(frame);
6100                    if (useOverlay) {
6101                        document.body.classList.add('overflow-hidden');
6102                    }
6103                    return new Promise(resolve => frame.resolve = resolve);
6104                },
6105                cancel() {
6106                    this.hide(false);
6107                },
6108                ok() {
6109                    this.hide(true);
6110                },
6111                hide(value) {
6112                                        if (Date.now() - lastHide < config.duration) {
6113                        return;
6114                    }
6115                    lastHide = Date.now();
6116
6117                    const modal = modals.pop() || {};
6118                    if (! modal.instance) {
6119                        return;
6120                    }
6121
6122                    const name = modal.name;
6123                    this.opened[name] = false;
6124                    hyva.releaseFocus(modal.instance.$refs[modal.name])
6125                    trapFocusInNextModalWithOverlay();
6126
6127                    const nextFocusAfterHide = modal.focusTarget;
6128                    nextFocusAfterHide && setTimeout(() => {
6129                        nextFocusAfterHide.setAttribute('aria-expanded', 'false');
6130                        nextFocusAfterHide.focus()
6131                    }, config.duration);
6132
6133                    if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
6134                        document.body.classList.remove('overflow-hidden');
6135                    }
6136
6137                    modal.resolve(value);
6138                },
6139                overlay(dialog) {
6140                    dialog = this.$el.dataset.dialogRefName || dialog;
6141                    const name = typeof dialog === 'string' ? dialog : config.dialog;
6142                    return {
6143                        ['x-show']() {
6144                            return this.opened[name]
6145                        },
6146                        ['x-transition:enter']: config.transitionEnter,
6147                        ['x-transition:enter-start']: config.transitionEnterStart,
6148                        ['x-transition:enter-end']: config.transitionEnterEnd,
6149                        ['x-transition:leave']: config.transitionLeave,
6150                        ['x-transition:leave-start']: config.transitionLeaveStart,
6151                        ['x-transition:leave-end']: config.transitionLeaveEnd,
6152                        ['@hyva-modal-show.window'](event) {
6153                            event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide)
6154                        }
6155                    };
6156                },
6157                showDialogOnInit() {
6158                    const parent = this.$el.closest('[data-dialog-ref-name]');
6159                    if (parent && parent.dataset.dialogRefName) {
6160                        this.$dispatch('hyva-modal-show', {dialog: parent.dataset.dialogRefName})
6161                    }
6162                }
6163            };
6164        }
6165
6166        window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length -1]
6167
6168        window.hyva.modal.pop = function () {
6169            if (modals.length > 0) {
6170                const modal = modals[modals.length -1];
6171                modal.instance.hide();
6172            }
6173        }
6174
6175        window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {
6176            typeof selectors === 'string' || selectors instanceof String
6177                ? excludedFromFocusTrapping.add(selectors)
6178                : selectors.map(selector => excludedFromFocusTrapping.add(selector));
6179        }
6180
6181        window.hyva.modal.eventListeners = {
6182            keydown: event => {
6183                if (event.key === 'Escape') {
6184                    window.hyva.modal.pop();
6185                }
6186            },
6187                        click: event => {
6188                if (modals.length > 0) {
6189                    const modal = modals[modals.length -1];
6190                    const dialog = modal.instance.$refs[modal.name];
6191                    if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago
6192                        ! isOverlayDisabled(dialog) && // if dialog has overlay
6193                        ! dialog.contains(event.target)) { // if click is outside of dialog
6194                        modal.instance.hide();
6195                    }
6196                }
6197            }
6198        };
6199
6200        document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);
6201
6202        document.addEventListener('click', window.hyva.modal.eventListeners.click);
6203    })();
6204    window.addEventListener('alpine:init', () => {
6205        Alpine.data('hyvaModal', window.hyva.modal);
6206    }, {once: true});
6207</script>
6207
6208
6209<script data-cfasync="false">
6210    'use strict';
6211
6212    /**
6213     * @typedef {Object} CookieGroupData
6214     * @prop {Boolean} checked
6215     * @prop {[{description: string, lifetime: number|null, name: string, provider: string, type: string}]} cookies
6216     * @prop {String} description
6217     * @prop {string|null} groupId
6218     * @prop {Boolean} isEssential
6219     * @prop {String} name
6220     */
6221
6222    function initAmastyCookieGroupsStorage() {
6223        return {
6224            /**
6225             * @type {[CookieGroupData]}
6226             */
6227            groupData: [],
6228            cookiePolicy: undefined,
6229            lastUpdate: undefined,
6230
6231            /**
6232             * @returns {string|number[]}
6233             */
6234            getEssentialGroupIds: function () {
6235                return this.groupData.reduce(function (essentialGroupIds, group) {
6236                    if (group.isEssential) {
6237                        essentialGroupIds.push(group.groupId)
6238                    }
6239
6240                    return essentialGroupIds;
6241                }, []);
6242            },
6243
6244            /**
6245             * @returns {string|number[]}
6246             */
6247            getCheckedGroupIds: function () {
6248                return this.groupData.reduce(function (checkedGroupIds, group) {
6249                    if (group.checked) {
6250                        checkedGroupIds.push(group.groupId);
6251                    }
6252
6253                    return checkedGroupIds;
6254                }, []);
6255            },
6256
6257            /**
6258             * @param {string} cookieName
6259             * @returns {boolean}
6260             */
6261            isCookieEssential: function (cookieName) {
6262                const allEssentialCookies = this.getEssentialCookies();
6263
6264                return !!allEssentialCookies.find(cookie => cookie.name === cookieName);
6265            },
6266
6267            /**
6268             * @returns {array}
6269             */
6270            getEssentialCookies: function () {
6271                return this.groupData
6272                    .filter(group => group.isEssential)
6273                    .map(group => group.cookies)
6274                    .flat();
6275            },
6276
6277            /**
6278             * @returns {boolean}
6279             */
6280            hasGroupData: function () {
6281                return !!this.groupData.length;
6282            },
6283
6284            /**
6285             * @param {string} cookieName
6286             * @param {string} pattern
6287             * @returns {boolean}
6288             */
6289            isEssentialByPattern: function (cookieName, pattern) {
6290                const essentialCookiePatterns = this.getEssentialCookiesPattern(pattern);
6291
6292                return essentialCookiePatterns.some((pattern) => !!cookieName.match(this.getCookiePattern(pattern)));
6293            },
6294
6295            /**
6296             * @param {string} pattern
6297             * @return {Array}
6298             */
6299            getEssentialCookiesPattern: function (pattern) {
6300                return this.getCookiesByPattern(pattern, this.getEssentialCookies());
6301            },
6302
6303            /**
6304             * @param {string} pattern
6305             * @param {Array|undefined} cookies
6306             * @return {Array}
6307             */
6308            getCookiesByPattern: function (pattern, cookies) {
6309                if (typeof cookie === 'undefined') {
6310                    cookies = this.getAllCookies();
6311                }
6312
6313                return cookies
6314                    .map((cookie) => typeof cookie === 'object' ? cookie.name : cookie.split('=')[0].trim())
6315                    .filter((cookie) => cookie.match(pattern) !== null);
6316            },
6317
6318            /**
6319             * @returns {array}
6320             */
6321            getDisallowedCookies: function () {
6322                const disallowedCookie = decodeURIComponent(hyva.getCookie('amcookie_disallowed') ?? '');
6323                if (!disallowedCookie) {
6324                    return [];
6325                }
6326
6327                return disallowedCookie.split(',');
6328            },
6329
6330            /**
6331             * @returns {string}
6332             */
6333            getCookiePattern: function (pattern) {
6334                return `^${pattern.replaceAll('*', '.*')}$`;
6335            },
6336
6337            /**
6338             * @returns {array}
6339             */
6340            getAllCookies: function () {
6341                return document.cookie.split(';');
6342            },
6343
6344            /**
6345             * @param {boolean} setAcceptance
6346             * @returns {Promise}
6347             */
6348            updateGroupData: function (setAcceptance = false) {
6349                const cookieFetchUrl = `${BASE_URL}amcookie/cookie/cookies`;
6350                return fetch(cookieFetchUrl, {
6351                    method: "POST",
6352                    headers: {
6353                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
6354                        'X-Requested-With': 'XMLHttpRequest'
6355                    },
6356                    body: new URLSearchParams({
6357                        allowed: hyva.getCookie('amcookie_allowed'),
6358                        restriction: hyva.getCookie('amcookie_policy_restriction')
6359                    })
6360                }).then(response => {
6361                    if (response.ok) {
6362                        return response.json();
6363                    }
6364
6365                    return Promise.reject(`${response.status} ${response.statusText}`);
6366                }).then(data => {
6367                    this.cookiePolicy = data.cookiePolicy ?? 'allowed';
6368                    this.lastUpdate = data.lastUpdate ?? 0;
6369                    this.groupData = [...data.groupData];
6370
6371                    hyva.setCookie('amcookie_policy_restriction', this.cookiePolicy, 10);
6372                    if (setAcceptance) {
6373                        amastyCookieManager.setLastCookieAcceptance(this.lastUpdate);
6374                    }
6375
6376                    return data;
6377                }).catch(error => {
6378                    typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
6379                        {
6380                            type: "error",
6381                            text: error
6382                        }
6383                    ]);
6384                }).finally(() => window.dispatchEvent(new CustomEvent('amasty-cookie-group-updated')));
6385            }
6386        }
6387    }
6388
6389    window.addEventListener(
6390        'alpine:init',
6391        () => Alpine.store('AmastyCookieGroups', initAmastyCookieGroupsStorage()),
6392        { once: true }
6393    );
6394</script>
6394
6395
6396<script data-cfasync="false">
6397    (function (amastyCookieManager) {
6398        'use strict';
6399
6400        amastyCookieManager.pattern = '{(?<cookiePattern>.*)}';
6401
6402        amastyCookieManager.getAmastyCookieGroupStorage = function () {
6403            return Alpine.store('AmastyCookieGroups') ?? {};
6404        };
6405
6406        amastyCookieManager.deleteDisallowedCookie = function () {
6407            const amastyCookieGroupStorage = this.getAmastyCookieGroupStorage();
6408            const disallowedCookies = amastyCookieGroupStorage?.getDisallowedCookies() ?? [];
6409
6410            disallowedCookies.forEach((name) => {
6411                const pattern = name.match(this.pattern);
6412                if (!!pattern && !!amastyCookieGroupStorage) {
6413                    const cookiePattern = amastyCookieGroupStorage.getCookiePattern(pattern.groups.cookiePattern) ?? '';
6414
6415                    amastyCookieGroupStorage.getCookiesByPattern(cookiePattern).forEach((cookieName) => {
6416                        this.deleteNotEssentialCookie(cookieName);
6417                    });
6418                } else {
6419                    this.deleteNotEssentialCookie(name);
6420                }
6421            });
6422        };
6423
6424        amastyCookieManager.isCookieAllowed = function (cookieName) {
6425            const allowedGroups = hyva.getCookie('amcookie_allowed');
6426            const disallowedCookie = this.getAmastyCookieGroupStorage()?.getDisallowedCookies() ?? [];
6427            const isCookiePolicyAllowed = hyva.getCookie('amcookie_policy_restriction') === 'allowed';
6428            const isCookieEssential = this.getAmastyCookieGroupStorage()?.isCookieEssential(cookieName);
6429            const isCookieEssentialByPattern = this.getAmastyCookieGroupStorage()?.isEssentialByPattern(cookieName, this.pattern);
6430
6431            if (!isCookiePolicyAllowed || isCookieEssential || isCookieEssentialByPattern) {
6432                return true;
6433            }
6434
6435            return !((!allowedGroups && !disallowedCookie) || this.isCookieDisallowed(cookieName));
6436        };
6437
6438        amastyCookieManager.isCookieDisallowed = function (cookieName) {
6439            const amastyCookieGroupStorage = this.getAmastyCookieGroupStorage();
6440            const disallowedCookies = amastyCookieGroupStorage?.getDisallowedCookies() ?? [];
6441
6442            return disallowedCookies.some((cookie) => {
6443                const pattern = cookie.match(this.pattern);
6444
6445                return !!pattern && !!cookieName.match(amastyCookieGroupStorage?.getCookiePattern(pattern.groups.cookiePattern));
6446            }) || disallowedCookies.indexOf(cookieName) !== -1;
6447        };
6448
6449        amastyCookieManager.processManageableCookies = function () {
6450            let cookieScripts = document.querySelectorAll('script[data-amcookie-groupid][type="text/plain"]');
6451
6452            cookieScripts.forEach((elem) => {
6453                if (this.isChecked(elem.dataset['amcookie-groupid'])) {
6454                    let elClone = elem.cloneNode(true).setAttribute('type', 'text/javascript');
6455
6456                    elem.remove();
6457                    document.body.appendChild(elClone);
6458                }
6459            });
6460        };
6461
6462        amastyCookieManager.deleteNotEssentialCookie = function (cookieName) {
6463            if (!this.getAmastyCookieGroupStorage()?.isCookieEssential(cookieName)) {
6464                hyva.setCookie(cookieName, '', -1, true);
6465            }
6466        };
6467
6468        amastyCookieManager.setLastCookieAcceptance = function (lastUpdate) {
6469            localStorage.setItem('am-last-cookie-acceptance', lastUpdate);
6470        };
6471
6472        window.addEventListener('amasty-cookie-group-updated', () => {
6473            amastyCookieManager.deleteDisallowedCookie();
6474        });
6475
6476        window.addEventListener('private-content-loaded', () => {
6477            amastyCookieManager.getAmastyCookieGroupStorage()?.hasGroupData() && amastyCookieManager.deleteDisallowedCookie();
6478        });
6479    }(window.amastyCookieManager = window.amastyCookieManager || {}));
6480</script>
6480
6481
6482<script data-cfasync="false">
6483    (function () {
6484        'use strict';
6485
6486        window.addEventListener('cookiebar-action-accept', (event) => {
6487            const groups = event.detail?.include_checked_groups ? Alpine.store('AmastyCookieGroups').getCheckedGroupIds() : [];
6488            const url = `${BASE_URL}amcookie/cookie/savegroups`;
6489            const contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
6490            const body = new URLSearchParams({
6491                form_key: hyva.getFormKey()
6492            });
6493            groups.length && groups.map(groupId => body.append('groups[]', groupId));
6494
6495            fetch(url, {method: 'POST', body, headers: {'Content-Type': contentType}})
6496                .then(response => {
6497                    if (response.ok) {
6498                        return response.json();
6499                    }
6500
6501                    return Promise.reject(`${response.status} ${response.statusText}`);
6502                })
6503                .then(data => {
6504                    !!data.success && Alpine.store('AmastyCookieGroups').updateGroupData(true);
6505                })
6506                .catch(error => {
6507                    typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
6508                        {
6509                            type: "error",
6510                            text: error
6511                        }
6512                    ]);
6513                })
6514                .finally(() => {
6515                    amastyCookieManager.processManageableCookies();
6516                    window.dispatchEvent(new CustomEvent('cookiebar-action-accept-finish'));
6517                    window.dispatchEvent(new CustomEvent('amasty-cookie-group-updated'));
6518                    // Wait cookiebar close animation
6519                    setTimeout(() => {
6520                        window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
6521                    }, 100);
6522                });
6523        });
6524    })();
6525</script>
6525
6526
6527<script data-cfasync="false">
6528    (function () {
6529        'use strict';
6530
6531        window.addEventListener('cookiebar-action-allow', () => {
6532            const url = `${BASE_URL}amcookie/cookie/allow`;
6533            const contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
6534            const body = new URLSearchParams({
6535                form_key: hyva.getFormKey()
6536            });
6537            fetch(url, {method: 'POST', body, headers: {'Content-Type': contentType}})
6538                .then(response => {
6539                    if (response.ok) {
6540                        return response;
6541                    }
6542
6543                    return Promise.reject(`${response.status} ${response.statusText}`);
6544                })
6545                .then(() => {
6546                    Alpine.store('AmastyCookieGroups').updateGroupData(true);
6547                })
6548                .catch(error => {
6549                    typeof window.dispatchMessages !== "undefined" && window.dispatchMessages([
6550                        {
6551                            type: "error",
6552                            text: error
6553                        }
6554                    ]);
6555                })
6556                .finally(() => {
6557                    amastyCookieManager.processManageableCookies();
6558                    window.dispatchEvent(new CustomEvent('cookiebar-action-allow-finish'));
6559                    // Wait cookiebar close animation
6560                    setTimeout(() => {
6561                        window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
6562                    }, 100);
6563                });
6564        });
6565    })();
6566</script>
6566
6567
6568<style>
6569    :root {
6570        /* Bar Color Settings */
6571        --ambar-background: #fff;
6572        --ambar-links-color: #326ed1;
6573        --ambar-policy-text: #374151;
6574        --ambar-toggle-active-color: #2563eb;
6575        --ambar-toggle-inactive-color: #fff;
6576
6577        /* Buttons Color Settings */
6578        --ambar-button-accept-color: #337ab7;
6579        --ambar-button-accept-hover-color: #337ab7;
6580        --ambar-button-accept-text: #fff;
6581        --ambar-button-accept-hover-text: #fff;
6582
6583        --ambar-button-allow-color: #337ab7;
6584        --ambar-button-allow-hover-color: #337ab7;
6585        --ambar-button-allow-text: #fff;
6586        --ambar-button-allow-hover-text: #fff;
6587
6588        --ambar-button-decline-color: #337ab7;
6589        --ambar-button-decline-hover-color: #337ab7;
6590        --ambar-button-decline-text: #fff;
6591        --ambar-button-decline-hover-text: #fff;
6592
6593        --ambar-button-settings-color: #337ab7;
6594        --ambar-button-settings-hover-color: #337ab7;
6595        --ambar-button-settings-text: #fff;
6596        --ambar-button-settings-hover-text: #fff;
6597
6598        /* Buttons Order Settings */
6599        --ambar-button-accept-order: 0;
6600        --ambar-button-allow-order: 0;
6601        --ambar-button-settings-order: 0;
6602        --ambar-button-decline-order: 0;
6603
6604        /* Cookie Information Bar Color Settings */
6605        --ambar-information-background: #fff;
6606        --ambar-information-title: #374151;
6607        --ambar-information-description: #374151;
6608        --ambar-information-table-header: #374151;
6609        --ambar-information-table-content: #374151;
6610
6611        /* Cookie Information Bar Done Button Settings */
6612        --ambar-information-button-color: #1d4ed8;
6613        --ambar-information-button-hover-color: #1d4ed8;
6614        --ambar-information-button-text: #fff;
6615        --ambar-information-button-hover-text: #fff;
6616
6617        /* Settings Bar Done Button Settings */
6618        --ambar-setting-button-color: #1d4ed8;
6619        --ambar-setting-button-hover-color: #1d4ed8;
6620        --ambar-setting-button-text: #fff;
6621        --ambar-setting-button-hover-text: #fff;
6622
6623        /* cookie_settings_bar_customisation */
6624        --ambar-setting-bar-group-background: #fff;
6625        --ambar-setting-bar-group-title: #000;
6626        --ambar-setting-bar-group-description: #000;
6627        --ambar-setting-bar-group-links: #326ed1;
6628    }
6629</style>
6630
6631<style>
6632    :root {
6633        /* Sidebar Color Settings */
6634        --ambar-sidebar-group-title-text: #374151;
6635        --ambar-sidebar-group-description-text: #374151;
6636        --ambar-sidebar-toggle-active-color: #2563eb;
6637        --ambar-sidebar-toggle-inactive-color: #fff;
6638    }
6639</style>
6640
6641<script data-cfasync="false">
6642    'use strict';
6643
6644    function initAmCookieActionDispatcherBtn() {
6645        return {
6646            actiondispatchHandler: function (event) {
6647                const { dispatchAction, dispatchPayload } = event.currentTarget.dataset;
6648                this.$dispatch(dispatchAction, this.parsePayload(dispatchPayload));
6649            },
6650            parsePayload: function (payload) {
6651                try {
6652                    return JSON.parse(payload);
6653                } catch (e) {
6654                    return null;
6655                }
6656            }
6657        };
6658    }
6659
6660    window.addEventListener(
6661        'alpine:init',
6662        () => Alpine.data('initAmCookieActionDispatcherBtn', initAmCookieActionDispatcherBtn),
6663        { once: true }
6664    );
6665</script>
6665
6666
6667<script data-cfasync="false">
6668    'use strict';
6669
6670    function initAmCookieGroups() {
6671        return {
6672            /**
6673             * @withContext x-for: $store.AmastyCookieGroups.groupData
6674             * @returns {string}
6675             */
6676            getInputGroupId: function () {
6677                return `amcookie-${this.$el.dataset.groupPrefix}group-${this.group.groupId}`
6678            },
6679
6680            /**
6681             * @withContext x-for: $store.AmastyCookieGroups.groupData
6682             * @returns {{"!bg-gray-400": boolean}}
6683             */
6684            getInputStyles: function () {
6685                return {
6686                    '!bg-gray-400': this.group.isEssential
6687                }
6688            },
6689
6690            /**
6691             * @withContext x-for: $store.AmastyCookieGroups.groupData
6692             * @returns {void}
6693             */
6694            toggleGroup: function () {
6695                this.group.checked = !this.group.checked;
6696            },
6697
6698            /**
6699             * @withContext x-for: $store.AmastyCookieGroups.groupData
6700             * @returns {void}
6701             */
6702            moreInfoClickHandler: function () {
6703                this.$dispatch(this.$el.dataset.dispatchAction, this.group);
6704            },
6705
6706            moreInformationAboutCookieGroup: function () {
6707                return hyva.str('About\u0020\u0022\u00251\u0022\u0020Cookie\u0020Group', this.group.name);
6708            }
6709        }
6710    }
6711
6712    window.addEventListener(
6713        'alpine:init',
6714        () => Alpine.data('initAmCookieGroups', initAmCookieGroups),
6715        {once: true}
6716    );
6717</script>
6717
6718
6719<section x-data="initAmGdprLoader"
6720         @amgdpr-loading-start.window="showLoader"
6721         @amgdpr-loading-stop.window="hideLoader"
6722>
6723    <div
6724    class="z-50 fixed inset-0 grid place-items-center bg-white/70 text-slate-800"
6725    x-cloak
6726    x-show="isLoading"
6727    x-transition.opacity.duration.200ms
6728>
6729    <div class="flex gap-10 items-center p-4">
6730        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="57" height="57" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
6731    <style>
6732        @keyframes spinner-ball-triangle1 {
6733            0% { transform: translate(0%, 0%); }
6734            33% { transform: translate(38%, -79%); }
6735            66% { transform: translate(77%, 0%); }
6736            100% { transform: translate(0%, 0%); }
6737        }
6738
6739        @keyframes spinner-ball-triangle2 {
6740            0% { transform: translate(0%, 0%); }
6741            33% { transform: translate(38%, 79%); }
6742            66% { transform: translate(-38%, 79%); }
6743            100% { transform: translate(0%, 0%); }
6744        }
6745
6746        @keyframes spinner-ball-triangle3 {
6747            0% { transform: translate(0%, 0%); }
6748            33% { transform: translate(-77%, 0%); }
6749            66% { transform: translate(-38%, -79%); }
6750            100% { transform: translate(0%, 0%); }
6751        }
6752    </style>
6753    <circle cx="5" cy="50" r="5" style="animation: spinner-ball-triangle1 2.2s linear infinite"/>
6754    <circle cx="27" cy="5" r="5" style="animation: spinner-ball-triangle2 2.2s linear infinite"/>
6755    <circle cx="49" cy="50" r="5" style="animation: spinner-ball-triangle3 2.2s linear infinite"/>
6756</svg>
6757        <span class="text-xl select-none">
6758            Loading...        </span>
6759    </div>
6760</div>
6761</section>
6762
6763<script data-cfasync="false">
6764    'use strict';
6765
6766    function initAmGdprLoader() {
6767        return {
6768            isLoading: false,
6769
6770            /**
6771             * @returns {void}
6772             */
6773            showLoader: function () {
6774                this.isLoading = true;
6775            },
6776
6777            /**
6778             * @returns {void}
6779             */
6780            hideLoader: function () {
6781                this.isLoading = false;
6782            }
6783        }
6784    }
6785
6786    window.addEventListener(
6787        'alpine:init',
6788        () => Alpine.data('initAmGdprLoader', initAmGdprLoader),
6789        { once: true }
6790    );
6791</script>
vendor: 1 bytes, line 6791
6791
6792<script>
6793    'use strict';
6794
6795    function initAmQuoteButton(addUrl, isProductListing, isLoggedIn) {
6796        return {
6797            addUrl: addUrl,
6798            isProductListing: isProductListing,
6799            isLoggedIn: isLoggedIn,
6800            initButton: function ($el) {
6801                if (!this.isProductListing) {
6802                    $el.parentNode.classList.add('flex-wrap');
6803                }
6804            },
6805            submitQuote: async function ($el) {
6806                const originalForm = this.getFormNode($el);
6807                if (!originalForm || !originalForm.checkValidity()) {
6808                    originalForm?.reportValidity();
6809                    return;
6810                }
6811
6812                const formToSubmit = this.cloneForm(originalForm);
6813                const action = this.isProductListing
6814                    ? formToSubmit.action.replace('checkout', 'amasty_quote')
6815                    : this.addUrl;
6816
6817                const formData = new FormData(formToSubmit);
6818                const bodyUrl = new URLSearchParams(formData);
6819
6820                try {
6821                    const response = await fetch(action, {
6822                        method: 'POST',
6823                        body: bodyUrl.toString(),
6824                        mode: 'cors',
6825                        credentials: 'include',
6826                        headers: {
6827                            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
6828                            'X-Requested-With': 'XMLHttpRequest'
6829                        }
6830                    });
6831
6832                    if (!response.ok) {
6833                        formToSubmit.classList.add('hidden');
6834                        document.body.appendChild(formToSubmit);
6835                        formToSubmit.requestSubmit();
6836                        return;
6837                    }
6838
6839                    const responseData = await response.json();
6840
6841                    if (responseData.backUrl) {
6842                        window.location.href = responseData.backUrl;
6843                        return;
6844                    }
6845
6846                    // Reload quote cart customer section data
6847                    window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
6848
6849                    // Open the quote minicart drawer
6850                    window.dispatchEvent(new CustomEvent('toggle-amquote'));
6851
6852                } catch (err) {
6853                    console.warn('Add to Quote error:', err);
6854                    // Fallback to full page submit on network error
6855                    formToSubmit.classList.add('hidden');
6856                    document.body.appendChild(formToSubmit);
6857                    formToSubmit.requestSubmit();
6858                }
6859            },
6860            getFormNode: function ($el) {
6861                if (this.isProductListing) {
6862                    return $el.closest('form');
6863                }
6864
6865                return $el.form;
6866            },
6867            cloneForm: function(originalForm) {
6868                const clonedForm = originalForm.cloneNode();
6869                Array.from(originalForm.elements).forEach((element) => {
6870                    const clonedElement = element.cloneNode();
6871                    this.removeAlpineAttributes(clonedElement.attributes);
6872                    clonedElement.removeAttribute('form');
6873                    this.cloneSelectedElements(element, clonedElement);
6874                    clonedForm.appendChild(clonedElement);
6875                });
6876
6877                return clonedForm;
6878            },
6879            removeAlpineAttributes: function (AttrNodeMap) {
6880                Array.from(AttrNodeMap)
6881                    .filter((attribute) => /^(:|x-|@)\S*/.test(attribute.name))
6882                    .forEach((attribute) => AttrNodeMap.removeNamedItem(attribute.name));
6883            },
6884            cloneSelectedElements: function (element, clonedElement) {
6885                if (element.tagName === 'SELECT') {
6886                    for (const option of element.options) {
6887                        const clonedOption = option.cloneNode();
6888                        this.removeAlpineAttributes(clonedOption.attributes);
6889                        clonedOption.selected = option.selected;
6890                        clonedElement.appendChild(clonedOption);
6891                    }
6892                }
6893            }
6894        };
6895    }
6896</script>
6896
6897
6898<div x-cloak
6899     x-data="initModifyCartQuoteRemoveRequest"
6900     @toggle-cart.window="modifyRemoveRequest"
6901     @amquote-remove-request.window="amquoteRemoveRequest">
6902    <dialog class="amquote-dialog-request">
6903        <div x-cloak    data-dialog-ref-name="amquote-remove-request"
6904    x-bind="overlay"
6905    class="fixed inset-0 bg-black bg-opacity-50 z-50">
6906    <div class="fixed flex justify-center items-center text-left z-40 inset-0">
6907        <div x-ref="amquote-remove-request" role="dialog" aria-modal="true"
6908                                                  class="inline-block bg-white shadow-xl rounded-lg p-10 max-h-screen overflow-auto overscroll-y-contain max-w-lg">
6909            
6910<div class="flex flex-col w-full">
6911    <p>
6912        Are you sure you would like to remove this item from the shopping cart?    </p>
6913    <p>
6914        This item is a part of the approved quote. Removing it will remove all quote items from the cart.    </p>
6915</div>
6916<div class="w-full flex flex-row gap-3 mt-4">
6917    <button type="button"
6918            class="btn btn-secondary"
6919            @click="hideDialog"
6920            data-dialog-name="amquote-remove-request">
6921        Cancel    </button>
6922    <button type="button"
6923            class="btn btn-primary"
6924            @click="removeFromMiniCart">
6925        OK    </button>
6926</div>
6927        </div>
6928    </div>
6929    </div>
6930    </dialog>
6931</div>
6932
6933<script>
6934    'use strict';
6935
6936    function initModifyCartQuoteRemoveRequest() {
6937        const selectors = {
6938            configureQuoteButtons: '#cart-drawer .btn[href^="#hide-element"]',
6939            deleteQuoteButton: 'button.btn.btn-primary,  button[\\@click="deleteItemFromCart"]',
6940            dialogContainer: 'dialog.amquote-dialog-request'
6941        }
6942        const originalModal = hyva.modal();
6943        const originalHide = originalModal.hide;
6944
6945        originalModal.hide = function (value) {
6946            this.getAmRequestModalDialog()?.close();
6947
6948            return originalHide.call(this, value);
6949        };
6950
6951    return Object.assign(
6952        originalModal,
6953        {
6954            itemId: null,
6955
6956            modifyRemoveRequest: function () {
6957                const configureQuoteButtons = document.querySelectorAll(selectors.configureQuoteButtons);
6958
6959                configureQuoteButtons.forEach((configureButton) => {
6960                    const itemId = configureButton.href?.match(/(?:#hide-element-)(?<itemId>\d+)/).groups?.itemId;
6961
6962                    !!itemId && this.replaceDeleteAction(
6963                        itemId.toString(),
6964                        this.findDeleteQuoteButton(configureButton.parentNode)
6965                    );
6966                });
6967            },
6968
6969            findDeleteQuoteButton: function (parentNode) {
6970                const allButtons = parentNode.querySelectorAll(selectors.deleteQuoteButton);
6971                return Array.from(allButtons).filter((button) => {
6972                    return button.attributes['@click']?.value.includes('deleteItemFromCart');
6973                });
6974            },
6975
6976            replaceDeleteAction: function (itemId, deleteButtons) {
6977                deleteButtons.forEach((deleteButton) => {
6978                    const cloneButton = deleteButton.cloneNode(true);
6979                    cloneButton.removeAttribute('@click');
6980                    cloneButton.addEventListener('click', () => {
6981                        window.dispatchEvent(new CustomEvent('amquote-remove-request', { detail: itemId }));
6982                    });
6983                    deleteButton.parentNode.insertBefore(cloneButton, deleteButton);
6984                    deleteButton.remove();
6985                });
6986            },
6987
6988            showConfirm: function ({ detail: itemId }) {
6989                this.itemId = itemId;
6990                this.show('amquote\u002Dremove\u002Drequest');
6991
6992                // Open <dialog> on top, so it’s not blocked by other dialogs
6993                this.$nextTick(() => {
6994                    this.getAmRequestModalDialog().showModal();
6995                });
6996            },
6997
6998            getAmRequestModalDialog: function () {
6999                return document.querySelector(selectors.dialogContainer);
7000            },
7001
7002            removeFromMiniCart: function () {
7003                const url = BASE_URL + 'amasty_quote/quote/removeFromMinicart';
7004
7005                fetch(url, {
7006                    headers: {
7007                        'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
7008                    },
7009                    body: 'form_key=' + hyva.getFormKey() + '&item_id=' + this.itemId,
7010                    method: 'POST'
7011                }).then((response) => {
7012                    if (response.redirected) {
7013                        window.location.href = response.url;
7014                    } else if (response.ok) {
7015                        return response.json();
7016                    }
7017                }).then((response) => {
7018                    if (response.success === true) {
7019                        window.dispatchEvent(new CustomEvent('reload-customer-section-data'));
7020                    } else if (!!response.error_message)  {
7021                        window.dispatchMessages && window.dispatchMessages([{
7022                            type: 'error',
7023                            text: response.error_message
7024                        }]);
7025                    }
7026                }).finally(() => {
7027                    this.itemId = null;
7028                    this.hide('amquote\u002Dremove\u002Drequest');
7029                });
7030            },
7031
7032            amquoteRemoveRequest(event) {
7033                return this.showConfirm(this.$event)
7034            },
7035
7036            hideDialog(event) {
7037                return this.hide(`${this.$el.dataset.dialogName}`)
7038            }
7039        })
7040    }
7041
7042    window.addEventListener(
7043        'alpine:init',
7044        () => Alpine.data(
7045            'initModifyCartQuoteRemoveRequest',
7046            initModifyCartQuoteRemoveRequest
7047        ),
7048        {once: true}
7049    );
7050</script>
7050
7051
7052<div x-data="initAmastyCookieBar"
7053     x-bind="eventListeners"
7054     x-cloak
7055     id="am-cookie-bar"
7056    >
7057    <div x-cloak    data-dialog-ref-name="am-cookie-bar"
7058    x-bind="overlay"
7059    class="overflow-y-auto overflow-x-hidden fixed z-40 inset-0 backdrop-blur-sm bg-white/30 am-cookie-sidebar">
7060    <div class="fixed left-0 top-0 flex h-full max-w-md min-w-[320px] w-[20%]
7061                        border-t border-b border-container-darker bg-container-darker shadow inset-0">
7062        <div x-ref="am-cookie-bar" role="dialog" aria-modal="true"
7063                                         aria-label="Cookie&#x20;Bar"
7064                                     class="max-h-full w-full visible p-4 pt-2 pb-6 bg-ambar-background">
7065            
7066<div class="flex flex-col flex-nowrap justify-start h-full text-sm">
7067    <div class="flex justify-end">
7068                    <button @click="closeCookieBarHandler"
7069                    aria-label="Close&#x20;Cookie&#x20;Bar"
7070                    class="text-gray-300 transition hover:text-black focus:drop-shadow-md hover:drop-shadow-md mt-1"
7071            >
7072                <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
7073                     stroke="currentColor" stroke-width="2">
7074                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
7075                </svg>
7076            </button>
7077            </div>
7078
7079    <div class="flex flex-wrap overflow-y-auto ambar-sidebar-group-list mb-3 mt-4 ml-3 pr-2">
7080        
7081<div x-data="initAmCookieGroups" class="w-full flex flex-col">
7082    <template x-for="group in $store.AmastyCookieGroups.groupData" :key="group.groupId">
7083        <div class="mb-2">
7084            <div class="header flex justify-between items-start py-2">
7085                <h3 class="text-lg font-semibold pr-6 ambar-group-title text-ambar-settings-bar-group-title" x-text="group.name"></h3>
7086                <div>
7087                    <input type="checkbox"
7088                           :name="getInputGroupId"
7089                           data-group-prefix="sidebar-"
7090                           @change="toggleGroup"
7091                           :checked="group.checked"
7092                           :aria-checked="group.checked"
7093                           :id="getInputGroupId"
7094                           :disabled="group.isEssential"
7095                           :value="group.groupId"
7096                           class="amsettings-bar-input-toggle"
7097                           :class="getInputStyles"
7098                    >
7099                    <label data-group-prefix="sidebar-"
7100                           :for="getInputGroupId" class="sr-only" x-text="group.name">
7101                    </label>
7102                </div>
7103            </div>
7104            <p class="py-2 text-sm ambar-group-description text-ambar-settings-bar-group-description" x-html="group.description"></p>
7105            <button class="btn btn-secondary px-4 text-xs mb-4 rounded-xs before:content-none after:content-none"
7106                    type="button"
7107                    data-dispatch-action="sidebar-open-am-cookie-group-info"
7108                    @click="moreInfoClickHandler">
7109                <span class="">More Information</span>
7110                <span class="sr-only" x-text="moreInformationAboutCookieGroup"></span>
7111            </button>
7112        </div>
7113    </template>
7114</div>
7115
7116
7117<div x-data="initCookieGroupInfo_6ab6be2810b9e" x-bind="eventListeners">
7118    <div x-cloak
7119         x-bind="overlay"
7120         class="fixed inset-0 flex items-center justify-center text-left bg-gray-500/50 z-50"
7121    >
7122        <div x-ref="sidebar-am-cookie-group-info"
7123             role="dialog"
7124             aria-labelledby="amcookie-group-info"
7125             class="inline-block max-h-[92vh] max-w-[90vw] overflow-auto
7126                bg-ambar-info-bar-background shadow-xl rounded-lg p-8 text-gray-700 relative"
7127        >
7128            <template x-if="group">
7129                <div id="amcookie-group-info">
7130                    <button @click="closeHandler"
7131                            aria-label="Close"
7132                            class="absolute right-2 top-2 text-gray-300 transition
7133                                hover:text-black focus:drop-shadow-md hover:drop-shadow-md"
7134                    >
7135                        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
7136                             stroke="currentColor"
7137                             stroke-width="2">
7138                            <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
7139                        </svg>
7140                    </button>
7141                    <div class="md:flex md:justify-start pb-4">
7142                        <h3 class="text-xl font-semibold text-ambar-info-bar-title" x-text="group.name"></h3>
7143                    </div>
7144                    <template x-if="group.description">
7145                        <p class="mb-4 text-ambar-info-bar-description" x-html="group.description"></p>
7146                    </template>
7147                    <div class="overflow-x-scroll md:overflow-x-auto">
7148                        <table class="table-auto w-full mb-4 text-left">
7149                            <thead class="text-ambar-info-bar-table-header">
7150                            <tr>
7151                                <th class="pr-4">Cookie Name</th>
7152                                <th class="pr-4">Cookie Provider</th>
7153                                <th class="min-w-[30%] pr-4">Cookie Description</th>
7154                                <th class="pr-4">Cookie Lifetime</th>
7155                                <th class="pr-4">Cookie Type</th>
7156                            </tr>
7157                            </thead>
7158                            <tbody class="text-ambar-info-bar-table-content">
7159                            <template x-for="(item, index) in group.cookies" :key="index">
7160                                <tr>
7161                                    <td x-text="item.name" class="font-semibold pr-4"></td>
7162                                    <td x-text="item.provider" class="pr-4"></td>
7163                                    <td x-html="item.description" class="min-w-[30%] pr-4"></td>
7164                                    <td x-text="item.lifetime" class="pr-4"></td>
7165                                    <td x-text="item.type" class="pr-4"></td>
7166                                </tr>
7167                            </template>
7168                            </tbody>
7169                        </table>
7170                    </div>
7171                </div>
7172            </template>
7173            <button
7174                @click="closeHandler"
7175                aria-label="Done"
7176                class="mt-4 w-full text-xs font-semibold text-ambar-info-bar-button-text
7177                    hover:text-ambar-info-bar-button-hover-text uppercase bg-ambar-info-bar-button
7178                    hover:bg-ambar-info-bar-button-hover ambar-action-btn rounded-sm text-center text-sm transition-colors focus:drop-shadow hover:drop-shadow px-2 py-4"
7179            >
7180                Done            </button>
7181        </div>
7182    </div>
7183
7184</div>
7185<script data-cfasync="false">
7186    'use strict';
7187
7188    function initCookieGroupInfo_6ab6be2810b9e() {
7189        return {
7190            ...hyva.modal({
7191                dialog: 'sidebar-am-cookie-group-info'
7192            }),
7193            group: null,
7194            eventListeners: {
7195                ['@sidebar-close-am-cookie-group-info.window']() {
7196                    this.closeHandler();
7197                },
7198                ['@sidebar-open-am-cookie-group-info.window'](event) {
7199                    this.group = event.detail;
7200
7201                    if (!!this.group) {
7202                        /*
7203                         If modal have big cookies list this can lead to
7204                         trigger hide event in hyva.modal.eventListeners.click,
7205                         so we should wait till this.group is reassigned
7206                         */
7207                        this.$nextTick(() => this.show('sidebar-am-cookie-group-info'));
7208                    }
7209                }
7210            },
7211            closeHandler: function () {
7212                this.hide('sidebar-am-cookie-group-info');
7213            }
7214        }
7215    }
7216
7217    window.addEventListener(
7218        'alpine:init',
7219        () => Alpine.data(
7220            'initCookieGroupInfo_6ab6be2810b9e',
7221            initCookieGroupInfo_6ab6be2810b9e        ),
7222        {once: true}
7223    );
7224</script>
7224
7225    </div>
7226
7227    <div class="flex flex-wrap flex-col mt-auto border-t pt-4">
7228                    <div id="amcookie-bar-content" class="flex flex-wrap w-full text-ambar-policy-text py-2">
7229                We use cookies to improve our services, make personal offers, and enhance your experience. If you do not accept optional cookies below, your experience may be affected. If you want to know more, please, read the <a href="privacy-policy-cookie-restriction-mode" title="Cookie Policy">Cookie Policy</a>            </div>
7230        
7231        <div class="flex flex-wrap w-full">
7232            
7233            
7234<button
7235    type="button"
7236    x-data="initAmCookieActionDispatcherBtn"
7237    data-dispatch-action="cookiebar-action-accept"
7238            data-dispatch-payload='&#x7B;&quot;include_checked_groups&quot;&#x3A;true&#x7D;'
7239        @click.prevent="actiondispatchHandler"
7240    class="ambar-btn-accept&#x20;ambar-action-btn&#x20;w-full&#x20;justify-center&#x20;mt-2"
7241>
7242    Accept Cookies</button>
7243                
7244<button
7245    type="button"
7246    x-data="initAmCookieActionDispatcherBtn"
7247    data-dispatch-action="cookiebar-action-accept"
7248        @click.prevent="actiondispatchHandler"
7249    class="ambar-btn-decline&#x20;ambar-action-btn&#x20;w-full&#x20;justify-center&#x20;mt-2"
7250>
7251    Decline Cookies</button>
7252                
7253<button
7254    type="button"
7255    x-data="initAmCookieActionDispatcherBtn"
7256    data-dispatch-action="cookiebar-action-allow"
7257        @click.prevent="actiondispatchHandler"
7258    class="ambar-btn-allow&#x20;ambar-action-btn&#x20;w-full&#x20;justify-center&#x20;mt-2"
7259>
7260    Allow all Cookies</button>
7261            </div>
7262    </div>
7263</div>
7264        </div>
7265    </div>
7266    </div>
7267</div>
7268
7269<script data-cfasync="false">
7270    'use strict';
7271
7272    function initAmastyCookieBar() {
7273        return {
7274            ...hyva.modal({
7275                duration: 150,
7276                transitionEnter: 'transform duration-150',
7277                transitionLeave: 'transform duration-150'
7278            }),
7279            eventListeners: {
7280                ['@close-cookie-bar']() {
7281                    this.hide('am-cookie-bar');
7282                },
7283                ['@open-cookie-bar']() {
7284                    this.show('am-cookie-bar');
7285                    this.$nextTick(() => hyva.trapFocus(this.modalElement));
7286                },
7287                ['@amasty-cookie-group-updated.window']() {
7288                    const lastUpdate = Alpine.store('AmastyCookieGroups').lastUpdate;
7289                    if (this.isShowNotificationBar(this.firstShowProcess, lastUpdate)) {
7290                        !this.opened['am-cookie-bar'] &&
7291                        this.show('am-cookie-bar');
7292                        this.$nextTick(() => hyva.trapFocus(this.modalElement));
7293                    } else {
7294                        !!this.opened['am-cookie-bar'] &&
7295                        this.hide('am-cookie-bar');
7296                    }
7297                }
7298            },
7299
7300            firstShowProcess: '0',
7301
7302            /**
7303             * @returns {void}
7304             */
7305            init: function () {
7306                window.isGdprCookieEnabled = true;
7307                Alpine.store('AmastyCookieGroups').updateGroupData();
7308                this.modalElement = this.$refs['am-cookie-bar'];
7309                this.modalElement.setAttribute('aria-describedby', 'amcookie-bar-content');
7310            },
7311
7312            /**
7313             * @param {string|number} firstShowProcess
7314             * @param {number} lastUpdate
7315             * @returns {boolean}
7316             */
7317            isShowNotificationBar: function (firstShowProcess, lastUpdate) {
7318                return (this.isNeedFirstShow(firstShowProcess, lastUpdate) && !hyva.getCookie('amcookie_allowed')
7319                    || this.isNeedShowOnUpdate(lastUpdate));
7320            },
7321
7322            /**
7323             * @param {string|number} firstShowProcess
7324             * @param {number} lastUpdate
7325             * @returns {boolean}
7326             */
7327            isNeedFirstShow: function (firstShowProcess, lastUpdate) {
7328                hyva.getBrowserStorage().setItem('amCookieBarFirstShowTime', lastUpdate);
7329
7330                if (firstShowProcess === '0') {
7331                    return true;
7332                }
7333
7334                if (hyva.getBrowserStorage().getItem('amCookieBarFirstShow') !== '1') {
7335                    hyva.getBrowserStorage().setItem('amCookieBarFirstShow', '1');
7336
7337                    return true;
7338                }
7339
7340                return false;
7341            },
7342
7343            /**
7344             * @param {number} lastUpdate
7345             * @returns {boolean}
7346             */
7347            isNeedShowOnUpdate: function (lastUpdate) {
7348                if (!lastUpdate) {
7349                    return false;
7350                }
7351
7352                return this.isNeedShowAfterLastVisit(lastUpdate) || this.isNeedShowAfterLastAccept(lastUpdate);
7353            },
7354
7355            /**
7356             * @param {number} lastUpdate
7357             * @returns {boolean}
7358             */
7359            isNeedShowAfterLastVisit: function (lastUpdate) {
7360                let needToShowAfterLastVisit =
7361                    lastUpdate > hyva.getBrowserStorage().getItem('amCookieBarFirstShowTime');
7362
7363                if (needToShowAfterLastVisit) {
7364                    hyva.getBrowserStorage().setItem('amCookieBarFirstShow', null);
7365                    hyva.setCookie('amcookie_allowed', '', -1, true);
7366                }
7367
7368                return needToShowAfterLastVisit;
7369            },
7370
7371            /**
7372             * @param {number} lastUpdate
7373             * @returns {boolean}
7374             */
7375            isNeedShowAfterLastAccept: function (lastUpdate) {
7376                let needToShowAfterLastAccept = false;
7377
7378                if (hyva.getBrowserStorage().getItem('am-last-cookie-acceptance')) {
7379                    needToShowAfterLastAccept =
7380                        lastUpdate > hyva.getBrowserStorage().getItem('am-last-cookie-acceptance');
7381                }
7382
7383                return needToShowAfterLastAccept;
7384            },
7385
7386            /**
7387             * @returns {void}
7388             */
7389            closeCookieBarHandler: function () {
7390                this.$dispatch('close-cookie-bar');
7391            }
7392        };
7393    }
7394
7395    window.addEventListener('alpine:init', () => Alpine.data('initAmastyCookieBar', initAmastyCookieBar), {once: true});
7396</script>
vendor: 1 bytes, line 7396
7396
7397<script type="text/json" id="default-section-data">
7398    {"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"cart":[],"directory-data":{"AD":{"name":"Andorra"},"AE":{"name":"United Arab Emirates"},"AF":{"name":"Afghanistan"},"AG":{"name":"Antigua & Barbuda"},"AI":{"name":"Anguilla"},"AL":{"name":"Albania","regions":{"512":{"code":"AL-01","name":"Berat"},"513":{"code":"AL-09","name":"Dib\u00ebr"},"514":{"code":"AL-02","name":"Durr\u00ebs"},"515":{"code":"AL-03","name":"Elbasan"},"516":{"code":"AL-04","name":"Fier"},"517":{"code":"AL-05","name":"Gjirokast\u00ebr"},"518":{"code":"AL-06","name":"Kor\u00e7\u00eb"},"519":{"code":"AL-07","name":"Kuk\u00ebs"},"520":{"code":"AL-08","name":"Lezh\u00eb"},"521":{"code":"AL-10","name":"Shkod\u00ebr"},"522":{"code":"AL-11","name":"Tiran\u00eb"},"523":{"code":"AL-12","name":"Vlor\u00eb"}}},"AM":{"name":"Armenia"},"AN":{"name":null},"AO":{"name":"Angola"},"AQ":{"name":"Antarctica"},"AR":{"name":"Argentina","regions":{"525":{"code":"AR-B","name":"Buenos Aires"},"526":{"code":"AR-K","name":"Catamarca"},"527":{"code":"AR-H","name":"Chaco"},"528":{"code":"AR-U","name":"Chubut"},"524":{"code":"AR-C","name":"Ciudad Aut\u00f3noma de Buenos Aires"},"529":{"code":"AR-X","name":"C\u00f3rdoba"},"530":{"code":"AR-W","name":"Corrientes"},"531":{"code":"AR-E","name":"Entre R\u00edos"},"532":{"code":"AR-P","name":"Formosa"},"533":{"code":"AR-Y","name":"Jujuy"},"534":{"code":"AR-L","name":"La Pampa"},"535":{"code":"AR-F","name":"La Rioja"},"536":{"code":"AR-M","name":"Mendoza"},"537":{"code":"AR-N","name":"Misiones"},"538":{"code":"AR-Q","name":"Neuqu\u00e9n"},"539":{"code":"AR-R","name":"R\u00edo Negro"},"540":{"code":"AR-A","name":"Salta"},"541":{"code":"AR-J","name":"San Juan"},"542":{"code":"AR-D","name":"San Luis"},"543":{"code":"AR-Z","name":"Santa Cruz"},"544":{"code":"AR-S","name":"Santa Fe"},"545":{"code":"AR-G","name":"Santiago del Estero"},"546":{"code":"AR-V","name":"Tierra del Fuego"},"547":{"code":"AR-T","name":"Tucum\u00e1n"}}},"AS":{"name":"American Samoa"},"AT":{"name":"Austria","regions":{"102":{"code":"BL","name":"Burgenland"},"99":{"code":"KN","name":"K\u00e4rnten"},"96":{"code":"NO","name":"Nieder\u00f6sterreich"},"97":{"code":"OO","name":"Ober\u00f6sterreich"},"98":{"code":"SB","name":"Salzburg"},"100":{"code":"ST","name":"Steiermark"},"101":{"code":"TI","name":"Tirol"},"103":{"code":"VB","name":"Vorarlberg"},"95":{"code":"WI","name":"Wien"}}},"AU":{"name":"Australia","regions":{"605":{"code":"ACT","name":"Australian Capital Territory"},"606":{"code":"NSW","name":"New South Wales"},"612":{"code":"NT","name":"Northern Territory"},"608":{"code":"QLD","name":"Queensland"},"609":{"code":"SA","name":"South Australia"},"610":{"code":"TAS","name":"Tasmania"},"607":{"code":"VIC","name":"Victoria"},"611":{"code":"WA","name":"Western Australia"}}},"AW":{"name":"Aruba"},"AX":{"name":"\u00c5land Islands"},"AZ":{"name":"Azerbaijan"},"BA":{"name":"Bosnia & Herzegovina"},"BB":{"name":"Barbados"},"BD":{"name":"Bangladesh"},"BE":{"name":"Belgium","regions":{"620":{"code":"VAN","name":"Antwerpen"},"621":{"code":"WBR","name":"Brabant wallon"},"622":{"code":"BRU","name":"Brussels-Capital Region"},"623":{"code":"WHT","name":"Hainaut"},"625":{"code":"WLG","name":"Li\u00e8ge"},"624":{"code":"VLI","name":"Limburg"},"626":{"code":"WLX","name":"Luxembourg"},"627":{"code":"WNA","name":"Namur"},"628":{"code":"VOV","name":"Oost-Vlaanderen"},"629":{"code":"VBR","name":"Vlaams-Brabant"},"630":{"code":"VWV","name":"West-Vlaanderen"}}},"BF":{"name":"Burkina Faso"},"BG":{"name":"Bulgaria","regions":{"640":{"code":"BG-01","name":"Blagoevgrad"},"641":{"code":"BG-02","name":"Burgas"},"647":{"code":"BG-08","name":"Dobrich"},"646":{"code":"BG-07","name":"Gabrovo"},"665":{"code":"BG-26","name":"Haskovo"},"648":{"code":"BG-09","name":"Kardzhali"},"649":{"code":"BG-10","name":"Kyustendil"},"650":{"code":"BG-11","name":"Lovech"},"651":{"code":"BG-12","name":"Montana"},"652":{"code":"BG-13","name":"Pazardzhik"},"653":{"code":"BG-14","name":"Pernik"},"654":{"code":"BG-15","name":"Pleven"},"655":{"code":"BG-16","name":"Plovdiv"},"656":{"code":"BG-17","name":"Razgrad"},"657":{"code":"BG-18","name":"Ruse"},"666":{"code":"BG-27","name":"Shumen"},"658":{"code":"BG-19","name":"Silistra"},"659":{"code":"BG-20","name":"Sliven"},"660":{"code":"BG-21","name":"Smolyan"},"661":{"code":"BG-22","name":"Sofia City"},"662":{"code":"BG-23","name":"Sofia Province"},"663":{"code":"BG-24","name":"Stara Zagora"},"664":{"code":"BG-25","name":"Targovishte"},"642":{"code":"BG-03","name":"Varna"},"643":{"code":"BG-04","name":"Veliko Tarnovo"},"644":{"code":"BG-05","name":"Vidin"},"645":{"code":"BG-06","name":"Vratsa"},"667":{"code":"BG-28","name":"Yambol"}}},"BH":{"name":"Bahrain"},"BI":{"name":"Burundi"},"BJ":{"name":"Benin"},"BL":{"name":"St. Barth\u00e9lemy"},"BM":{"name":"Bermuda"},"BN":{"name":"Brunei"}
7398,"BO":{"name":"Bolivia","regions":{"632":{"code":"BO-H","name":"Chuquisaca"},"631":{"code":"BO-C","name":"Cochabamba"},"633":{"code":"BO-B","name":"El Beni"},"634":{"code":"BO-L","name":"La Paz"},"635":{"code":"BO-O","name":"Oruro"},"636":{"code":"BO-N","name":"Pando"},"637":{"code":"BO-P","name":"Potos\u00ed"},"638":{"code":"BO-S","name":"Santa Cruz"},"639":{"code":"BO-T","name":"Tarija"}}},"BQ":{"name":"Caribbean Netherlands"},"BR":{"name":"Brazil","regions":{"485":{"code":"AC","name":"Acre"},"486":{"code":"AL","name":"Alagoas"},"487":{"code":"AP","name":"Amap\u00e1"},"488":{"code":"AM","name":"Amazonas"},"489":{"code":"BA","name":"Bahia"},"490":{"code":"CE","name":"Cear\u00e1"},"511":{"code":"DF","name":"Distrito Federal"},"491":{"code":"ES","name":"Esp\u00edrito Santo"},"492":{"code":"GO","name":"Goi\u00e1s"},"493":{"code":"MA","name":"Maranh\u00e3o"},"494":{"code":"MT","name":"Mato Grosso"},"495":{"code":"MS","name":"Mato Grosso do Sul"},"496":{"code":"MG","name":"Minas Gerais"},"497":{"code":"PA","name":"Par\u00e1"},"498":{"code":"PB","name":"Para\u00edba"},"499":{"code":"PR","name":"Paran\u00e1"},"500":{"code":"PE","name":"Pernambuco"},"501":{"code":"PI","name":"Piau\u00ed"},"502":{"code":"RJ","name":"Rio de Janeiro"},"503":{"code":"RN","name":"Rio Grande do Norte"},"504":{"code":"RS","name":"Rio Grande do Sul"},"505":{"code":"RO","name":"Rond\u00f4nia"},"506":{"code":"RR","name":"Roraima"},"507":{"code":"SC","name":"Santa Catarina"},"508":{"code":"SP","name":"S\u00e3o Paulo"},"509":{"code":"SE","name":"Sergipe"},"510":{"code":"TO","name":"Tocantins"}}},"BS":{"name":"Bahamas"},"BT":{"name":"Bhutan"},"BV":{"name":"Bouvet Island"},"BW":{"name":"Botswana"},"BY":{"name":"Belarus","regions":{"613":{"code":"BY-BR","name":"Bresckaja voblas\u0107"},"614":{"code":"BY-HO","name":"Homie\u013askaja voblas\u0107"},"615":{"code":"BY-HM","name":"Horad Minsk"},"616":{"code":"BY-HR","name":"Hrodzienskaja voblas\u0107"},"617":{"code":"BY-MA","name":"Mahilio\u016dskaja voblas\u0107"},"618":{"code":"BY-MI","name":"Minskaja voblas\u0107"},"619":{"code":"BY-VI","name":"Viciebskaja voblas\u0107"}}},"BZ":{"name":"Belize"},"CA":{"name":"Canada","regions":{"66":{"code":"AB","name":"Alberta"},"67":{"code":"BC","name":"British Columbia"},"68":{"code":"MB","name":"Manitoba"},"70":{"code":"NB","name":"New Brunswick"},"69":{"code":"NL","name":"Newfoundland and Labrador"},"72":{"code":"NT","name":"Northwest Territories"},"71":{"code":"NS","name":"Nova Scotia"},"73":{"code":"NU","name":"Nunavut"},"74":{"code":"ON","name":"Ontario"},"75":{"code":"PE","name":"Prince Edward Island"},"76":{"code":"QC","name":"Quebec"},"77":{"code":"SK","name":"Saskatchewan"},"78":{"code":"YT","name":"Yukon Territory"}}},"CC":{"name":"Cocos (Keeling) Islands"},"CD":{"name":"Congo - Kinshasa"},"CF":{"name":"Central African Republic"},"CG":{"name":"Congo - Brazzaville"},"CH":{"name":"Switzerland","regions":{"104":{"code":"AG","name":"Aargau"},"106":{"code":"AR","name":"Appenzell Ausserrhoden"},"105":{"code":"AI","name":"Appenzell Innerrhoden"},"108":{"code":"BL","name":"Basel-Landschaft"},"109":{"code":"BS","name":"Basel-Stadt"},"107":{"code":"BE","name":"Bern"},"110":{"code":"FR","name":"Friburg"},"111":{"code":"GE","name":"Geneva"},"112":{"code":"GL","name":"Glarus"},"113":{"code":"GR","name":"Graub\u00fcnden"},"114":{"code":"JU","name":"Jura"},"115":{"code":"LU","name":"Lucerne"},"116":{"code":"NE","name":"Neuch\u00e2tel"},"117":{"code":"NW","name":"Nidwalden"},"118":{"code":"OW","name":"Obwalden"},"120":{"code":"SH","name":"Schaffhausen"},"122":{"code":"SZ","name":"Schwyz"},"121":{"code":"SO","name":"Solothurn"},"119":{"code":"SG","name":"St. Gallen"},"123":{"code":"TG","name":"Thurgau"},"124":{"code":"TI","name":"Ticino"},"125":{"code":"UR","name":"Uri"},"126":{"code":"VD","name":"Vaud"},"127":{"code":"VS","name":"Wallis"},"128":{"code":"ZG","name":"Zug"},"129":{"code":"ZH","name":"Z\u00fcrich"}}},"CI":{"name":"C\u00f4te d\u2019Ivoire"},"CK":{"name":"Cook Islands"},"CL":{"name":"Chile","regions":{"668":{"code":"CL-AI","name":"Ais\u00e9n del General Carlos Iba\u00f1ez del Campo"},"669":{"code":"CL-AN","name":"Antofagasta"},"670":{"code":"CL-AP","name":"Arica y Parinacota"},"672":{"code":"CL-AT","name":"Atacama"},"673":{"code":"CL-BI","name":"Biob\u00edo"},"674":{"code":"CL-CO","name":"Coquimbo"},"671":{"code":"CL-AR","name":"La Araucan\u00eda"},"675":{"code":"CL-LI","name":"Libertador General Bernardo O'Higgins"}
7398,"676":{"code":"CL-LL","name":"Los Lagos"},"677":{"code":"CL-LR","name":"Los R\u00edos"},"678":{"code":"CL-MA","name":"Magallanes"},"679":{"code":"CL-ML","name":"Maule"},"680":{"code":"CL-NB","name":"\u00d1uble"},"681":{"code":"CL-RM","name":"Regi\u00f3n Metropolitana de Santiago"},"682":{"code":"CL-TA","name":"Tarapac\u00e1"},"683":{"code":"CL-VS","name":"Valpara\u00edso"}}},"CM":{"name":"Cameroon"},"CN":{"name":"China","regions":{"684":{"code":"CN-AH","name":"Anhui Sheng"},"685":{"code":"CN-BJ","name":"Beijing Shi"},"686":{"code":"CN-CQ","name":"Chongqing Shi"},"687":{"code":"CN-FJ","name":"Fujian Sheng"},"688":{"code":"CN-GS","name":"Gansu Sheng"},"689":{"code":"CN-GD","name":"Guangdong Sheng"},"690":{"code":"CN-GX","name":"Guangxi Zhuangzu Zizhiqu"},"691":{"code":"CN-GZ","name":"Guizhou Sheng"},"692":{"code":"CN-HI","name":"Hainan Sheng"},"693":{"code":"CN-HE","name":"Hebei Sheng"},"694":{"code":"CN-HL","name":"Heilongjiang Sheng"},"695":{"code":"CN-HA","name":"Henan Sheng"},"696":{"code":"CN-HK","name":"Hong Kong SAR"},"697":{"code":"CN-HB","name":"Hubei Sheng"},"698":{"code":"CN-HN","name":"Hunan Sheng"},"699":{"code":"CN-JS","name":"Jiangsu Sheng"},"700":{"code":"CN-JX","name":"Jiangxi Sheng"},"701":{"code":"CN-JL","name":"Jilin Sheng"},"702":{"code":"CN-LN","name":"Liaoning Sheng"},"703":{"code":"CN-MO","name":"Macao SAR"},"704":{"code":"CN-NM","name":"Nei Mongol Zizhiqu"},"705":{"code":"CN-NX","name":"Ningxia Huizi Zizhiqu"},"706":{"code":"CN-QH","name":"Qinghai Sheng"},"707":{"code":"CN-SN","name":"Shaanxi Sheng"},"708":{"code":"CN-SD","name":"Shandong Sheng"},"709":{"code":"CN-SH","name":"Shanghai Shi"},"710":{"code":"CN-SX","name":"Shanxi Sheng"},"711":{"code":"CN-SC","name":"Sichuan Sheng"},"712":{"code":"CN-TW","name":"Taiwan Sheng"},"713":{"code":"CN-TJ","name":"Tianjin Shi"},"714":{"code":"CN-XJ","name":"Xinjiang Uygur Zizhiqu"},"715":{"code":"CN-XZ","name":"Xizang Zizhiqu"},"716":{"code":"CN-YN","name":"Yunnan Sheng"},"717":{"code":"CN-ZJ","name":"Zhejiang Sheng"}}},"CO":{"name":"Colombia","regions":{"718":{"code":"CO-AMA","name":"Amazonas"},"719":{"code":"CO-ANT","name":"Antioquia"},"720":{"code":"CO-ARA","name":"Arauca"},"721":{"code":"CO-ATL","name":"Atl\u00e1ntico"},"722":{"code":"CO-BOL","name":"Bol\u00edvar"},"723":{"code":"CO-BOY","name":"Boyac\u00e1"},"724":{"code":"CO-CAL","name":"Caldas"},"725":{"code":"CO-CAQ","name":"Caquet\u00e1"},"726":{"code":"CO-CAS","name":"Casanare"},"727":{"code":"CO-CAU","name":"Cauca"},"728":{"code":"CO-CES","name":"Cesar"},"729":{"code":"CO-CHO","name":"Choc\u00f3"},"730":{"code":"CO-COR","name":"C\u00f3rdoba"},"731":{"code":"CO-CUN","name":"Cundinamarca"},"732":{"code":"CO-GUA","name":"Guain\u00eda"},"733":{"code":"CO-GUV","name":"Guaviare"},"734":{"code":"CO-HUL","name":"Huila"},"735":{"code":"CO-LAG","name":"La Guajira"},"736":{"code":"CO-MAG","name":"Magdalena"},"737":{"code":"CO-MET","name":"Meta"},"738":{"code":"CO-NAR","name":"Nari\u00f1o"},"739":{"code":"CO-NSA","name":"Norte de Santander"},"740":{"code":"CO-PUT","name":"Putumayo"},"741":{"code":"CO-QUI","name":"Quind\u00edo"},"742":{"code":"CO-RIS","name":"Risaralda"},"743":{"code":"CO-SAP","name":"San Andr\u00e9s y Providencia"},"744":{"code":"CO-SAN","name":"Santander"},"745":{"code":"CO-SUC","name":"Sucre"},"746":{"code":"CO-TOL","name":"Tolima"},"747":{"code":"CO-VAC","name":"Valle del Cauca"},"748":{"code":"CO-VAU","name":"Vaup\u00e9s"},"749":{"code":"CO-VID","name":"Vichada"}}},"CR":{"name":"Costa Rica","regions":{"751":{"code":"CR-AL","name":"Alajuela"},"752":{"code":"CR-CA","name":"Cartago"},"754":{"code":"CR-GU","name":"Guanacaste"},"753":{"code":"CR-HE","name":"Heredia"},"756":{"code":"CR-LI","name":"Lim\u00f3n"},"755":{"code":"CR-PU","name":"Puntarenas"},"750":{"code":"CR-SJ","name":"San Jos\u00e9"}}},"CU":{"name":"Cuba"},"CV":{"name":"Cape Verde"},"CW":{"name":"Cura\u00e7ao"},"CX":{"name":"Christmas Island"},"CY":{"name":"Cyprus"},"CZ":{"name":"Czechia","regions":{"759":{"code":"CZ-31","name":"Jiho\u010desk\u00fd kraj"},"767":{"code":"CZ-64","name":"Jihomoravsk\u00fd kraj"},"761":{"code":"CZ-41","name":"Karlovarsk\u00fd kraj"},"766":{"code":"CZ-63","name":"Kraj Vyso\u010dina"},"764":{"code":"CZ-52","name":"Kr\u00e1lov\u00e9hradeck\u00fd kraj"},"763":{"code":"CZ-51","name":"Libereck\u00fd kraj"},"770":{"code":"CZ-80","name":"Moravskoslezsk\u00fd kraj"}
7398,"768":{"code":"CZ-71","name":"Olomouck\u00fd kraj"},"765":{"code":"CZ-53","name":"Pardubick\u00fd kraj"},"760":{"code":"CZ-32","name":"Plze\u0148sk\u00fd kraj"},"757":{"code":"CZ-10","name":"Praha, Hlavn\u00ed m\u011bsto"},"758":{"code":"CZ-20","name":"St\u0159edo\u010desk\u00fd kraj"},"762":{"code":"CZ-42","name":"\u00dasteck\u00fd kraj"},"769":{"code":"CZ-72","name":"Zl\u00ednsk\u00fd kraj"}}},"DE":{"name":"Germany","regions":{"80":{"code":"BAW","name":"Baden-W\u00fcrttemberg"},"81":{"code":"BAY","name":"Bayern"},"82":{"code":"BER","name":"Berlin"},"83":{"code":"BRG","name":"Brandenburg"},"84":{"code":"BRE","name":"Bremen"},"85":{"code":"HAM","name":"Hamburg"},"86":{"code":"HES","name":"Hessen"},"87":{"code":"MEC","name":"Mecklenburg-Vorpommern"},"79":{"code":"NDS","name":"Niedersachsen"},"88":{"code":"NRW","name":"Nordrhein-Westfalen"},"89":{"code":"RHE","name":"Rheinland-Pfalz"},"90":{"code":"SAR","name":"Saarland"},"91":{"code":"SAS","name":"Sachsen"},"92":{"code":"SAC","name":"Sachsen-Anhalt"},"93":{"code":"SCN","name":"Schleswig-Holstein"},"94":{"code":"THE","name":"Th\u00fcringen"}}},"DJ":{"name":"Djibouti"},"DK":{"name":"Denmark","regions":{"771":{"code":"DK-84","name":"Hovedstaden"},"772":{"code":"DK-82","name":"Midtjylland"},"773":{"code":"DK-81","name":"Nordjylland"},"774":{"code":"DK-85","name":"Sj\u00e6lland"},"775":{"code":"DK-83","name":"Syddanmark"}}},"DM":{"name":"Dominica"},"DO":{"name":"Dominican Republic"},"DZ":{"name":"Algeria"},"EC":{"name":"Ecuador","regions":{"776":{"code":"EC-A","name":"Azuay"},"777":{"code":"EC-B","name":"Bol\u00edvar"},"778":{"code":"EC-F","name":"Ca\u00f1ar"},"779":{"code":"EC-C","name":"Carchi"},"780":{"code":"EC-H","name":"Chimborazo"},"781":{"code":"EC-X","name":"Cotopaxi"},"782":{"code":"EC-O","name":"El Oro"},"783":{"code":"EC-E","name":"Esmeraldas"},"784":{"code":"EC-W","name":"Gal\u00e1pagos"},"785":{"code":"EC-G","name":"Guayas"},"786":{"code":"EC-I","name":"Imbabura"},"787":{"code":"EC-L","name":"Loja"},"788":{"code":"EC-R","name":"Los R\u00edos"},"789":{"code":"EC-M","name":"Manab\u00ed"},"790":{"code":"EC-S","name":"Morona Santiago"},"791":{"code":"EC-N","name":"Napo"},"792":{"code":"EC-D","name":"Orellana"},"793":{"code":"EC-Y","name":"Pastaza"},"794":{"code":"EC-P","name":"Pichincha"},"795":{"code":"EC-SE","name":"Santa Elena"},"796":{"code":"EC-SD","name":"Santo Domingo de los Ts\u00e1chilas"},"797":{"code":"EC-U","name":"Sucumb\u00edos"},"798":{"code":"EC-T","name":"Tungurahua"},"799":{"code":"EC-Z","name":"Zamora Chinchipe"}}},"EE":{"name":"Estonia","regions":{"340":{"code":"EE-37","name":"Harjumaa"},"341":{"code":"EE-39","name":"Hiiumaa"},"342":{"code":"EE-44","name":"Ida-Virumaa"},"344":{"code":"EE-51","name":"J\u00e4rvamaa"},"343":{"code":"EE-49","name":"J\u00f5gevamaa"},"346":{"code":"EE-59","name":"L\u00e4\u00e4ne-Virumaa"},"345":{"code":"EE-57","name":"L\u00e4\u00e4nemaa"},"348":{"code":"EE-67","name":"P\u00e4rnumaa"},"347":{"code":"EE-65","name":"P\u00f5lvamaa"},"349":{"code":"EE-70","name":"Raplamaa"},"350":{"code":"EE-74","name":"Saaremaa"},"351":{"code":"EE-78","name":"Tartumaa"},"352":{"code":"EE-82","name":"Valgamaa"},"353":{"code":"EE-84","name":"Viljandimaa"},"354":{"code":"EE-86","name":"V\u00f5rumaa"}}},"EG":{"name":"Egypt"},"EH":{"name":"Western Sahara"},"ER":{"name":"Eritrea"},"ES":{"name":"Spain","regions":{"130":{"code":"A Coru\u0441a","name":"A Coru\u00f1a"},"131":{"code":"Alava","name":"Alava"},"132":{"code":"Albacete","name":"Albacete"},"133":{"code":"Alicante","name":"Alicante"},"134":{"code":"Almeria","name":"Almeria"},"135":{"code":"Asturias","name":"Asturias"},"136":{"code":"Avila","name":"Avila"},"137":{"code":"Badajoz","name":"Badajoz"},"138":{"code":"Baleares","name":"Baleares"},"139":{"code":"Barcelona","name":"Barcelona"},"140":{"code":"Burgos","name":"Burgos"},"141":{"code":"Caceres","name":"Caceres"},"142":{"code":"Cadiz","name":"Cadiz"},"143":{"code":"Cantabria","name":"Cantabria"},"144":{"code":"Castellon","name":"Castellon"},"145":{"code":"Ceuta","name":"Ceuta"},"146":{"code":"Ciudad Real","name":"Ciudad Real"},"147":{"code":"Cordoba","name":"Cordoba"},"148":{"code":"Cuenca","name":"Cuenca"},"149":{"code":"Girona","name":"Girona"},"150":{"code":"Granada","name":"Granada"},"151":{"code":"Guadalajara","name":"Guadalajara"},"152":{"code":"Guipuzcoa","name":"Guipuzcoa"},"153":{"code":"Huelva","name":"Huelva"},"154":{"code":"Huesca","name":"Huesca"},"155":{"code":"Jaen","name":"Jaen"},"156":{"code":"La Rioja","name":"La Rioja"},"157":{"code":"Las Palmas","name":"Las Palmas"},"158":{"code":"Leon","name":"Leon"},"159":{"code":"Lleida","name":"Lleida"},"160":{"code":"Lugo","name":"Lugo"},"161":{"code":"Madrid","name":"Madrid"},"162":{"code":"Malaga","name":"Malaga"},"163":{"code":"Melilla","name":"Melilla"},"164":{"code":"Murcia","name":"Murcia"},"165":{"code":"Navarra","name":"Navarra"},"166":{"code":"Ourense","name":"Ourense"},"167":{"code":"Palencia","name":"Palencia"},"168":{"code":"Pontevedra","name":"Pontevedra"},"169":{"code":"Salamanca","name":"Salamanca"},"170":{"code":"Santa Cruz de Tenerife","name":"Santa Cruz de Tenerife"},"171":{"code":"Segovia","name":"Segovia"},"172":{"code":"Sevilla","name":"Sevilla"},"173":{"code":"Soria","name":"Soria"},"174":{"code":"Tarragona","name":"Tarragona"},"175":{"code":"Teruel","name":"Teruel"},"176":{"code":"Toledo","name":"Toledo"},"177":{"code":"Valencia","name":"Valencia"},"178":{"code":"Valladolid","name":"Valladolid"}
7398,"179":{"code":"Vizcaya","name":"Vizcaya"},"180":{"code":"Zamora","name":"Zamora"},"181":{"code":"Zaragoza","name":"Zaragoza"}}},"ET":{"name":"Ethiopia"},"FI":{"name":"Finland","regions":{"339":{"code":"Ahvenanmaa","name":"Ahvenanmaa"},"333":{"code":"Etel\u00e4-Karjala","name":"Etel\u00e4-Karjala"},"326":{"code":"Etel\u00e4-Pohjanmaa","name":"Etel\u00e4-Pohjanmaa"},"325":{"code":"Etel\u00e4-Savo","name":"Etel\u00e4-Savo"},"337":{"code":"It\u00e4-Uusimaa","name":"It\u00e4-Uusimaa"},"322":{"code":"Kainuu","name":"Kainuu"},"335":{"code":"Kanta-H\u00e4me","name":"Kanta-H\u00e4me"},"330":{"code":"Keski-Pohjanmaa","name":"Keski-Pohjanmaa"},"331":{"code":"Keski-Suomi","name":"Keski-Suomi"},"338":{"code":"Kymenlaakso","name":"Kymenlaakso"},"320":{"code":"Lappi","name":"Lappi"},"334":{"code":"P\u00e4ij\u00e4t-H\u00e4me","name":"P\u00e4ij\u00e4t-H\u00e4me"},"328":{"code":"Pirkanmaa","name":"Pirkanmaa"},"327":{"code":"Pohjanmaa","name":"Pohjanmaa"},"323":{"code":"Pohjois-Karjala","name":"Pohjois-Karjala"},"321":{"code":"Pohjois-Pohjanmaa","name":"Pohjois-Pohjanmaa"},"324":{"code":"Pohjois-Savo","name":"Pohjois-Savo"},"329":{"code":"Satakunta","name":"Satakunta"},"336":{"code":"Uusimaa","name":"Uusimaa"},"332":{"code":"Varsinais-Suomi","name":"Varsinais-Suomi"}}},"FJ":{"name":"Fiji"},"FK":{"name":"Falkland Islands"},"FM":{"name":"Micronesia"},"FO":{"name":"Faroe Islands"},"FR":{"name":"France","regions":{"182":{"code":"1","name":"Ain"},"183":{"code":"2","name":"Aisne"},"184":{"code":"3","name":"Allier"},"185":{"code":"4","name":"Alpes-de-Haute-Provence"},"187":{"code":"6","name":"Alpes-Maritimes"},"188":{"code":"7","name":"Ard\u00e8che"},"189":{"code":"8","name":"Ardennes"},"190":{"code":"9","name":"Ari\u00e8ge"},"191":{"code":"10","name":"Aube"},"192":{"code":"11","name":"Aude"},"193":{"code":"12","name":"Aveyron"},"249":{"code":"67","name":"Bas-Rhin"},"194":{"code":"13","name":"Bouches-du-Rh\u00f4ne"},"195":{"code":"14","name":"Calvados"},"196":{"code":"15","name":"Cantal"},"197":{"code":"16","name":"Charente"},"198":{"code":"17","name":"Charente-Maritime"},"199":{"code":"18","name":"Cher"},"200":{"code":"19","name":"Corr\u00e8ze"},"201":{"code":"2A","name":"Corse-du-Sud"},"203":{"code":"21","name":"C\u00f4te-d'Or"},"204":{"code":"22","name":"C\u00f4tes-d'Armor"},"205":{"code":"23","name":"Creuse"},"261":{"code":"79","name":"Deux-S\u00e8vres"},"206":{"code":"24","name":"Dordogne"},"207":{"code":"25","name":"Doubs"},"208":{"code":"26","name":"Dr\u00f4me"},"273":{"code":"91","name":"Essonne"},"209":{"code":"27","name":"Eure"},"210":{"code":"28","name":"Eure-et-Loir"},"211":{"code":"29","name":"Finist\u00e8re"},"212":{"code":"30","name":"Gard"},"214":{"code":"32","name":"Gers"},"215":{"code":"33","name":"Gironde"},"250":{"code":"68","name":"Haut-Rhin"},"202":{"code":"2B","name":"Haute-Corse"},"213":{"code":"31","name":"Haute-Garonne"},"225":{"code":"43","name":"Haute-Loire"},"234":{"code":"52","name":"Haute-Marne"},"252":{"code":"70","name":"Haute-Sa\u00f4ne"},"256":{"code":"74","name":"Haute-Savoie"},"269":{"code":"87","name":"Haute-Vienne"},"186":{"code":"5","name":"Hautes-Alpes"},"247":{"code":"65","name":"Hautes-Pyr\u00e9n\u00e9es"},"274":{"code":"92","name":"Hauts-de-Seine"},"216":{"code":"34","name":"H\u00e9rault"},"217":{"code":"35","name":"Ille-et-Vilaine"},"218":{"code":"36","name":"Indre"},"219":{"code":"37","name":"Indre-et-Loire"},"220":{"code":"38","name":"Is\u00e8re"},"221":{"code":"39","name":"Jura"},"222":{"code":"40","name":"Landes"},"223":{"code":"41","name":"Loir-et-Cher"},"224":{"code":"42","name":"Loire"},"226":{"code":"44","name":"Loire-Atlantique"},"227":{"code":"45","name":"Loiret"},"228":{"code":"46","name":"Lot"},"229":{"code":"47","name":"Lot-et-Garonne"},"230":{"code":"48","name":"Loz\u00e8re"},"231":{"code":"49","name":"Maine-et-Loire"},"232":{"code":"50","name":"Manche"},"233":{"code":"51","name":"Marne"},"235":{"code":"53","name":"Mayenne"},"236":{"code":"54","name":"Meurthe-et-Moselle"},"237":{"code":"55","name":"Meuse"},"238":{"code":"56","name":"Morbihan"},"239":{"code":"57","name":"Moselle"},"240":{"code":"58","name":"Ni\u00e8vre"},"241":{"code":"59","name":"Nord"},"242":{"code":"60","name":"Oise"},"243":{"code":"61","name":"Orne"},"257":{"code":"75","name":"Paris"},"244":{"code":"62","name":"Pas-de-Calais"},"245":{"code":"63","name":"Puy-de-D\u00f4me"},"246":{"code":"64","name":"Pyr\u00e9n\u00e9es-Atlantiques"},"248":{"code":"66","name":"Pyr\u00e9n\u00e9es-Orientales"},"251":{"code":"69","name":"Rh\u00f4ne"},"253":{"code":"71","name":"Sa\u00f4ne-et-Loire"},"254":{"code":"72","name":"Sarthe"},"255":{"code":"73","name":"Savoie"},"259":{"code":"77","name":"Seine-et-Marne"},"258":{"code":"76","name":"Seine-Maritime"},"275":{"code":"93","name":"Seine-Saint-Denis"},"262":{"code":"80","name":"Somme"},"263":{"code":"81","name":"Tarn"},"264":{"code":"82","name":"Tarn-et-Garonne"},"272":{"code":"90","name":"Territoire-de-Belfort"},"277":{"code":"95","name":"Val-d'Oise"}
7398,"276":{"code":"94","name":"Val-de-Marne"},"265":{"code":"83","name":"Var"},"266":{"code":"84","name":"Vaucluse"},"267":{"code":"85","name":"Vend\u00e9e"},"268":{"code":"86","name":"Vienne"},"270":{"code":"88","name":"Vosges"},"271":{"code":"89","name":"Yonne"},"260":{"code":"78","name":"Yvelines"}}},"GA":{"name":"Gabon"},"GB":{"name":"United Kingdom"},"GD":{"name":"Grenada"},"GE":{"name":"Georgia"},"GF":{"name":"French Guiana"},"GG":{"name":"Guernsey"},"GH":{"name":"Ghana"},"GI":{"name":"Gibraltar"},"GL":{"name":"Greenland"},"GM":{"name":"Gambia"},"GN":{"name":"Guinea"},"GP":{"name":"Guadeloupe"},"GQ":{"name":"Equatorial Guinea"},"GR":{"name":"Greece","regions":{"813":{"code":"GR-69","name":"\u00c1gion \u00d3ros"},"800":{"code":"GR-A","name":"Anatolik\u00ed Makedon\u00eda kai Thr\u00e1ki"},"801":{"code":"GR-I","name":"Attik\u00ed"},"802":{"code":"GR-G","name":"Dytik\u00ed Ell\u00e1da"},"803":{"code":"GR-C","name":"Dytik\u00ed Makedon\u00eda"},"804":{"code":"GR-F","name":"Ion\u00eda N\u00edsia"},"805":{"code":"GR-D","name":"\u00cdpeiros"},"806":{"code":"GR-B","name":"Kentrik\u00ed Makedon\u00eda"},"807":{"code":"GR-M","name":"Kr\u00edti"},"808":{"code":"GR-L","name":"N\u00f3tio Aiga\u00edo"},"809":{"code":"GR-J","name":"Pelop\u00f3nnisos"},"810":{"code":"GR-H","name":"Stere\u00e1 Ell\u00e1da"},"811":{"code":"GR-E","name":"Thessal\u00eda"},"812":{"code":"GR-K","name":"V\u00f3reio Aiga\u00edo"}}},"GS":{"name":"South Georgia & South Sandwich Islands"},"GT":{"name":"Guatemala"},"GU":{"name":"Guam"},"GW":{"name":"Guinea-Bissau"},"GY":{"name":"Guyana","regions":{"814":{"code":"GY-BA","name":"Barima-Waini"},"815":{"code":"GY-CU","name":"Cuyuni-Mazaruni"},"816":{"code":"GY-DE","name":"Demerara-Mahaica"},"817":{"code":"GY-EB","name":"East Berbice-Corentyne"},"818":{"code":"GY-ES","name":"Essequibo Islands-West Demerara"},"819":{"code":"GY-MA","name":"Mahaica-Berbice"},"820":{"code":"GY-PM","name":"Pomeroon-Supenaam"},"821":{"code":"GY-PT","name":"Potaro-Siparuni"},"822":{"code":"GY-UD","name":"Upper Demerara-Berbice"},"823":{"code":"GY-UT","name":"Upper Takutu-Upper Essequibo"}}},"HK":{"name":"Hong Kong SAR China"},"HM":{"name":"Heard & McDonald Islands"},"HN":{"name":"Honduras"},"HR":{"name":"Croatia","regions":{"554":{"code":"HR-07","name":"Bjelovarsko-bilogorska \u017eupanija"},"559":{"code":"HR-12","name":"Brodsko-posavska \u017eupanija"},"566":{"code":"HR-19","name":"Dubrova\u010dko-neretvanska \u017eupanija"},"568":{"code":"HR-21","name":"Grad Zagreb"},"565":{"code":"HR-18","name":"Istarska \u017eupanija"},"551":{"code":"HR-04","name":"Karlova\u010dka \u017eupanija"},"553":{"code":"HR-06","name":"Koprivni\u010dko-kri\u017eeva\u010dka \u017eupanija"},"549":{"code":"HR-02","name":"Krapinsko-zagorska \u017eupanija"},"556":{"code":"HR-09","name":"Li\u010dko-senjska \u017eupanija"},"567":{"code":"HR-20","name":"Me\u0111imurska \u017eupanija"},"561":{"code":"HR-14","name":"Osje\u010dko-baranjska \u017eupanija"},"558":{"code":"HR-11","name":"Po\u017ee\u0161ko-slavonska \u017eupanija"},"555":{"code":"HR-08","name":"Primorsko-goranska \u017eupanija"},"562":{"code":"HR-15","name":"\u0160ibensko-kninska \u017eupanija"},"550":{"code":"HR-03","name":"Sisa\u010dko-moslava\u010dka \u017eupanija"},"564":{"code":"HR-17","name":"Splitsko-dalmatinska \u017eupanija"},"552":{"code":"HR-05","name":"Vara\u017edinska \u017eupanija"},"557":{"code":"HR-10","name":"Viroviti\u010dko-podravska \u017eupanija"},"563":{"code":"HR-16","name":"Vukovarsko-srijemska \u017eupanija"},"560":{"code":"HR-13","name":"Zadarska \u017eupanija"},"548":{"code":"HR-01","name":"Zagreba\u010dka \u017eupanija"}}},"HT":{"name":"Haiti"},"HU":{"name":"Hungary"},"ID":{"name":"Indonesia"},"IE":{"name":"Ireland"},"IL":{"name":"Israel"},"IM":{"name":"Isle of Man"},"IN":{"name":"India","regions":{"569":{"code":"AN","name":"Andaman and Nicobar Islands"},"570":{"code":"AP","name":"Andhra Pradesh"},"571":{"code":"AR","name":"Arunachal Pradesh"},"572":{"code":"AS","name":"Assam"},"573":{"code":"BR","name":"Bihar"},"574":{"code":"CH","name":"Chandigarh"},"575":{"code":"CT","name":"Chhattisgarh"},"576":{"code":"DN","name":"Dadra and Nagar Haveli"},"577":{"code":"DD","name":"Daman and Diu"},"578":{"code":"DL","name":"Delhi"},"579":{"code":"GA","name":"Goa"},"580":{"code":"GJ","name":"Gujarat"},"581":{"code":"HR","name":"Haryana"},"582":{"code":"HP","name":"Himachal Pradesh"},"583":{"code":"JK","name":"Jammu and Kashmir"},"584":{"code":"JH","name":"Jharkhand"},"585":{"code":"KA","name":"Karnataka"},"586":{"code":"KL","name":"Kerala"},"1156":{"code":"LA","name":"Ladakh"},"587":{"code":"LD","name":"Lakshadweep"},"588":{"code":"MP","name":"Madhya Pradesh"},"589":{"code":"MH","name":"Maharashtra"},"590":{"code":"MN","name":"Manipur"},"591":{"code":"ML","name":"Meghalaya"},"592":{"code":"MZ","name":"Mizoram"},"593":{"code":"NL","name":"Nagaland"}
7398,"594":{"code":"OR","name":"Odisha"},"595":{"code":"PY","name":"Puducherry"},"596":{"code":"PB","name":"Punjab"},"597":{"code":"RJ","name":"Rajasthan"},"598":{"code":"SK","name":"Sikkim"},"599":{"code":"TN","name":"Tamil Nadu"},"600":{"code":"TG","name":"Telangana"},"601":{"code":"TR","name":"Tripura"},"602":{"code":"UP","name":"Uttar Pradesh"},"603":{"code":"UT","name":"Uttarakhand"},"604":{"code":"WB","name":"West Bengal"}}},"IO":{"name":"British Indian Ocean Territory"},"IQ":{"name":"Iraq"},"IR":{"name":"Iran"},"IS":{"name":"Iceland","regions":{"830":{"code":"IS-07","name":"Austurland"},"824":{"code":"IS-01","name":"H\u00f6fu\u00f0borgarsv\u00e6\u00f0i"},"829":{"code":"IS-06","name":"Nor\u00f0urland eystra"},"828":{"code":"IS-05","name":"Nor\u00f0urland vestra"},"831":{"code":"IS-08","name":"Su\u00f0urland"},"825":{"code":"IS-02","name":"Su\u00f0urnes"},"827":{"code":"IS-04","name":"Vestfir\u00f0ir"},"826":{"code":"IS-03","name":"Vesturland"}}},"IT":{"name":"Italy","regions":{"832":{"code":"AG","name":"Agrigento"},"833":{"code":"AL","name":"Alessandria"},"834":{"code":"AN","name":"Ancona"},"835":{"code":"AO","name":"Aosta"},"837":{"code":"AR","name":"Arezzo"},"838":{"code":"AP","name":"Ascoli-Piceno"},"839":{"code":"AT","name":"Asti"},"840":{"code":"AV","name":"Avellino"},"841":{"code":"BA","name":"Bari"},"842":{"code":"BT","name":"Barletta-Andria-Trani"},"843":{"code":"BL","name":"Belluno"},"844":{"code":"BN","name":"Benevento"},"845":{"code":"BG","name":"Bergamo"},"846":{"code":"BI","name":"Biella"},"847":{"code":"BO","name":"Bologna"},"848":{"code":"BZ","name":"Bolzano"},"849":{"code":"BS","name":"Brescia"},"850":{"code":"BR","name":"Brindisi"},"851":{"code":"CA","name":"Cagliari"},"852":{"code":"CL","name":"Caltanissetta"},"853":{"code":"CB","name":"Campobasso"},"854":{"code":"CI","name":"Carbonia Iglesias"},"855":{"code":"CE","name":"Caserta"},"856":{"code":"CT","name":"Catania"},"857":{"code":"CZ","name":"Catanzaro"},"858":{"code":"CH","name":"Chieti"},"859":{"code":"CO","name":"Como"},"860":{"code":"CS","name":"Cosenza"},"861":{"code":"CR","name":"Cremona"},"862":{"code":"KR","name":"Crotone"},"863":{"code":"CN","name":"Cuneo"},"864":{"code":"EN","name":"Enna"},"865":{"code":"FM","name":"Fermo"},"866":{"code":"FE","name":"Ferrara"},"867":{"code":"FI","name":"Firenze"},"868":{"code":"FG","name":"Foggia"},"869":{"code":"FC","name":"Forli-Cesena"},"870":{"code":"FR","name":"Frosinone"},"871":{"code":"GE","name":"Genova"},"872":{"code":"GO","name":"Gorizia"},"873":{"code":"GR","name":"Grosseto"},"874":{"code":"IM","name":"Imperia"},"875":{"code":"IS","name":"Isernia"},"836":{"code":"AQ","name":"L'Aquila"},"876":{"code":"SP","name":"La-Spezia"},"877":{"code":"LT","name":"Latina"},"878":{"code":"LE","name":"Lecce"},"879":{"code":"LC","name":"Lecco"},"880":{"code":"LI","name":"Livorno"},"881":{"code":"LO","name":"Lodi"},"882":{"code":"LU","name":"Lucca"},"883":{"code":"MC","name":"Macerata"},"884":{"code":"MN","name":"Mantova"},"885":{"code":"MS","name":"Massa-Carrara"},"886":{"code":"MT","name":"Matera"},"887":{"code":"VS","name":"Medio Campidano"},"888":{"code":"ME","name":"Messina"},"889":{"code":"MI","name":"Milano"},"890":{"code":"MO","name":"Modena"},"891":{"code":"MB","name":"Monza-Brianza"},"892":{"code":"NA","name":"Napoli"},"893":{"code":"NO","name":"Novara"},"894":{"code":"NU","name":"Nuoro"},"895":{"code":"OG","name":"Ogliastra"},"896":{"code":"OT","name":"Olbia Tempio"},"897":{"code":"OR","name":"Oristano"},"898":{"code":"PD","name":"Padova"},"899":{"code":"PA","name":"Palermo"},"900":{"code":"PR","name":"Parma"},"901":{"code":"PV","name":"Pavia"},"902":{"code":"PG","name":"Perugia"},"903":{"code":"PU","name":"Pesaro-Urbino"},"904":{"code":"PE","name":"Pescara"},"905":{"code":"PC","name":"Piacenza"},"906":{"code":"PI","name":"Pisa"},"907":{"code":"PT","name":"Pistoia"},"908":{"code":"PN","name":"Pordenone"},"909":{"code":"PZ","name":"Potenza"},"910":{"code":"PO","name":"Prato"},"911":{"code":"RG","name":"Ragusa"},"912":{"code":"RA","name":"Ravenna"},"913":{"code":"RC","name":"Reggio-Calabria"},"914":{"code":"RE","name":"Reggio-Emilia"},"915":{"code":"RI","name":"Rieti"},"916":{"code":"RN","name":"Rimini"},"917":{"code":"RM","name":"Roma"},"918":{"code":"RO","name":"Rovigo"},"919":{"code":"SA","name":"Salerno"},"920":{"code":"SS","name":"Sassari"},"921":{"code":"SV","name":"Savona"},"922":{"code":"SI","name":"Siena"},"923":{"code":"SR","name":"Siracusa"},"924":{"code":"SO","name":"Sondrio"},"925":{"code":"TA","name":"Taranto"},"926":{"code":"TE","name":"Teramo"},"927":{"code":"TR","name":"Terni"},"928":{"code":"TO","name":"Torino"},"929":{"code":"TP","name":"Trapani"},"930":{"code":"TN","name":"Trento"},"931":{"code":"TV","name":"Treviso"},"932":{"code":"TS","name":"Trieste"},"933":{"code":"UD","name":"Udine"},"934":{"code":"VA","name":"Varese"},"935":{"code":"VE","name":"Venezia"},"936":{"code":"VB","name":"Verbania"},"937":{"code":"VC","name":"Vercelli"},"938":{"code":"VR","name":"Verona"}
7398,"939":{"code":"VV","name":"Vibo-Valentia"},"940":{"code":"VI","name":"Vicenza"},"941":{"code":"VT","name":"Viterbo"}}},"JE":{"name":"Jersey"},"JM":{"name":"Jamaica"},"JO":{"name":"Jordan"},"JP":{"name":"Japan"},"KE":{"name":"Kenya"},"KG":{"name":"Kyrgyzstan"},"KH":{"name":"Cambodia"},"KI":{"name":"Kiribati"},"KM":{"name":"Comoros"},"KN":{"name":"St. Kitts & Nevis"},"KP":{"name":"North Korea"},"KR":{"name":"South Korea"},"KW":{"name":"Kuwait"},"KY":{"name":"Cayman Islands"},"KZ":{"name":"Kazakhstan"},"LA":{"name":"Laos"},"LB":{"name":"Lebanon"},"LC":{"name":"St. Lucia"},"LI":{"name":"Liechtenstein"},"LK":{"name":"Sri Lanka"},"LR":{"name":"Liberia"},"LS":{"name":"Lesotho"},"LT":{"name":"Lithuania","regions":{"475":{"code":"LT-AL","name":"Alytaus Apskritis"},"476":{"code":"LT-KU","name":"Kauno Apskritis"},"477":{"code":"LT-KL","name":"Klaip\u0117dos Apskritis"},"478":{"code":"LT-MR","name":"Marijampol\u0117s Apskritis"},"479":{"code":"LT-PN","name":"Panev\u0117\u017eio Apskritis"},"480":{"code":"LT-SA","name":"\u0160iauli\u0173 Apskritis"},"481":{"code":"LT-TA","name":"Taurag\u0117s Apskritis"},"482":{"code":"LT-TE","name":"Tel\u0161i\u0173 Apskritis"},"483":{"code":"LT-UT","name":"Utenos Apskritis"},"484":{"code":"LT-VL","name":"Vilniaus Apskritis"}}},"LU":{"name":"Luxembourg"},"LV":{"name":"Latvia","regions":{"471":{"code":"\u0100da\u017eu novads","name":"\u0100da\u017eu novads"},"366":{"code":"Aglonas novads","name":"Aglonas novads"},"367":{"code":"LV-AI","name":"Aizkraukles novads"},"368":{"code":"Aizputes novads","name":"Aizputes novads"},"369":{"code":"Akn\u012bstes novads","name":"Akn\u012bstes novads"},"370":{"code":"Alojas novads","name":"Alojas novads"},"371":{"code":"Alsungas novads","name":"Alsungas novads"},"372":{"code":"LV-AL","name":"Al\u016bksnes novads"},"373":{"code":"Amatas novads","name":"Amatas novads"},"374":{"code":"Apes novads","name":"Apes novads"},"375":{"code":"Auces novads","name":"Auces novads"},"376":{"code":"Bab\u012btes novads","name":"Bab\u012btes novads"},"377":{"code":"Baldones novads","name":"Baldones novads"},"378":{"code":"Baltinavas novads","name":"Baltinavas novads"},"379":{"code":"LV-BL","name":"Balvu novads"},"380":{"code":"LV-BU","name":"Bauskas novads"},"381":{"code":"Bever\u012bnas novads","name":"Bever\u012bnas novads"},"382":{"code":"Broc\u0113nu novads","name":"Broc\u0113nu novads"},"383":{"code":"Burtnieku novads","name":"Burtnieku novads"},"384":{"code":"Carnikavas novads","name":"Carnikavas novads"},"387":{"code":"LV-CE","name":"C\u0113su novads"},"385":{"code":"Cesvaines novads","name":"Cesvaines novads"},"386":{"code":"Ciblas novads","name":"Ciblas novads"},"388":{"code":"Dagdas novads","name":"Dagdas novads"},"355":{"code":"LV-DGV","name":"Daugavpils"},"389":{"code":"LV-DA","name":"Daugavpils novads"},"390":{"code":"LV-DO","name":"Dobeles novads"},"391":{"code":"Dundagas novads","name":"Dundagas novads"},"392":{"code":"Durbes novads","name":"Durbes novads"},"393":{"code":"Engures novads","name":"Engures novads"},"472":{"code":"\u0112rg\u013cu novads","name":"\u0112rg\u013cu novads"},"394":{"code":"Garkalnes novads","name":"Garkalnes novads"},"395":{"code":"Grobi\u0146as novads","name":"Grobi\u0146as novads"},"396":{"code":"LV-GU","name":"Gulbenes novads"},"397":{"code":"Iecavas novads","name":"Iecavas novads"},"398":{"code":"Ik\u0161\u0137iles novads","name":"Ik\u0161\u0137iles novads"},"399":{"code":"Il\u016bkstes novads","name":"Il\u016bkstes novads"},"400":{"code":"In\u010dukalna novads","name":"In\u010dukalna novads"},"401":{"code":"Jaunjelgavas novads","name":"Jaunjelgavas novads"},"402":{"code":"Jaunpiebalgas novads","name":"Jaunpiebalgas novads"},"403":{"code":"Jaunpils novads","name":"Jaunpils novads"},"357":{"code":"J\u0113kabpils","name":"J\u0113kabpils"},"405":{"code":"LV-JK","name":"J\u0113kabpils novads"},"356":{"code":"LV-JEL","name":"Jelgava"},"404":{"code":"LV-JL","name":"Jelgavas novads"},"358":{"code":"LV-JUR","name":"J\u016brmala"},"406":{"code":"Kandavas novads","name":"Kandavas novads"},"412":{"code":"K\u0101rsavas novads","name":"K\u0101rsavas novads"},"473":{"code":"\u0136eguma novads","name":"\u0136eguma novads"},"474":{"code":"\u0136ekavas novads","name":"\u0136ekavas novads"},"407":{"code":"Kokneses novads","name":"Kokneses novads"},"410":{"code":"LV-KR","name":"Kr\u0101slavas novads"},"408":{"code":"Krimuldas novads","name":"Krimuldas novads"},"409":{"code":"Krustpils novads","name":"Krustpils novads"},"411":{"code":"LV-KU","name":"Kuld\u012bgas novads"},"413":{"code":"Lielv\u0101rdes novads","name":"Lielv\u0101rdes novads"},"359":{"code":"LV-LPX","name":"Liep\u0101ja"},"360":{"code":"LV-LE","name":"Liep\u0101jas novads"},"417":{"code":"L\u012bgatnes novads","name":"L\u012bgatnes novads"},"414":{"code":"LV-LM","name":"Limba\u017eu novads"},"418":{"code":"L\u012bv\u0101nu novads","name":"L\u012bv\u0101nu novads"},"415":{"code":"Lub\u0101nas novads","name":"Lub\u0101nas novads"},"416":{"code":"LV-LU","name":"Ludzas novads"},"419":{"code":"LV-MA","name":"Madonas novads"},"421":{"code":"M\u0101lpils novads","name":"M\u0101lpils novads"},"422":{"code":"M\u0101rupes novads","name":"M\u0101rupes novads"},"420":{"code":"Mazsalacas novads","name":"Mazsalacas novads"},"423":{"code":"Nauk\u0161\u0113nu novads","name":"Nauk\u0161\u0113nu novads"},"424":{"code":"Neretas novads","name":"Neretas novads"},"425":{"code":"N\u012bcas novads","name":"N\u012bcas novads"},"426":{"code":"LV-OG","name":"Ogres novads"},"427":{"code":"Olaines novads","name":"Olaines novads"},"428":{"code":"Ozolnieku novads","name":"Ozolnieku novads"},"432":{"code":"P\u0101rgaujas novads","name":"P\u0101rgaujas novads"},"433":{"code":"P\u0101vilostas novads","name":"P\u0101vilostas novads"},"434":{"code":"P\u013cavi\u0146u novads","name":"P\u013cavi\u0146u novads"},"429":{"code":"LV-PR","name":"Prei\u013cu novads"},"430":{"code":"Priekules novads","name":"Priekules novads"},"431":{"code":"Prieku\u013cu novads","name":"Prieku\u013cu novads"},"435":{"code":"Raunas novads","name":"Raunas novads"},"361":{"code":"LV-REZ","name":"R\u0113zekne"},"442":{"code":"LV-RE","name":"R\u0113zeknes novads"},"436":{"code":"Riebi\u0146u novads","name":"Riebi\u0146u novads"},"362":{"code":"LV-RIX","name":"R\u012bga"},"363":{"code":"LV-RI","name":"R\u012bgas novads"},"437":{"code":"Rojas novads","name":"Rojas novads"},"438":{"code":"Ropa\u017eu novads","name":"Ropa\u017eu novads"},"439":{"code":"Rucavas novads","name":"Rucavas novads"},"440":{"code":"Rug\u0101ju novads","name":"Rug\u0101ju novads"},"443":{"code":"R\u016bjienas novads","name":"R\u016bjienas novads"},"441":{"code":"Rund\u0101les novads","name":"Rund\u0101les novads"},"444":{"code":"Salacgr\u012bvas novads","name":"Salacgr\u012bvas novads"},"445":{"code":"Salas novads","name":"Salas novads"},"446":{"code":"Salaspils novads","name":"Salaspils novads"},"447":{"code":"LV-SA","name":"Saldus novads"},"448":{"code":"Saulkrastu novads","name":"Saulkrastu novads"},"455":{"code":"S\u0113jas novads","name":"S\u0113jas novads"},"449":{"code":"Siguldas novads","name":"Siguldas novads"}
7398,"451":{"code":"Skr\u012bveru novads","name":"Skr\u012bveru novads"},"450":{"code":"Skrundas novads","name":"Skrundas novads"},"452":{"code":"Smiltenes novads","name":"Smiltenes novads"},"453":{"code":"Stopi\u0146u novads","name":"Stopi\u0146u novads"},"454":{"code":"Stren\u010du novads","name":"Stren\u010du novads"},"456":{"code":"LV-TA","name":"Talsu novads"},"458":{"code":"T\u0113rvetes novads","name":"T\u0113rvetes novads"},"457":{"code":"LV-TU","name":"Tukuma novads"},"459":{"code":"Vai\u0146odes novads","name":"Vai\u0146odes novads"},"460":{"code":"LV-VK","name":"Valkas novads"},"364":{"code":"Valmiera","name":"Valmiera"},"461":{"code":"LV-VM","name":"Valmieras novads"},"462":{"code":"Varak\u013c\u0101nu novads","name":"Varak\u013c\u0101nu novads"},"469":{"code":"V\u0101rkavas novads","name":"V\u0101rkavas novads"},"463":{"code":"Vecpiebalgas novads","name":"Vecpiebalgas novads"},"464":{"code":"Vecumnieku novads","name":"Vecumnieku novads"},"365":{"code":"LV-VEN","name":"Ventspils"},"465":{"code":"LV-VE","name":"Ventspils novads"},"466":{"code":"Vies\u012btes novads","name":"Vies\u012btes novads"},"467":{"code":"Vi\u013cakas novads","name":"Vi\u013cakas novads"},"468":{"code":"Vi\u013c\u0101nu novads","name":"Vi\u013c\u0101nu novads"},"470":{"code":"Zilupes novads","name":"Zilupes novads"}}},"LY":{"name":"Libya"},"MA":{"name":"Morocco"},"MC":{"name":"Monaco"},"MD":{"name":"Moldova"},"ME":{"name":"Montenegro"},"MF":{"name":"St. Martin"},"MG":{"name":"Madagascar"},"MH":{"name":"Marshall Islands"},"MK":{"name":"North Macedonia"},"ML":{"name":"Mali"},"MM":{"name":"Myanmar (Burma)"},"MN":{"name":"Mongolia"},"MO":{"name":"Macao SAR China"},"MP":{"name":"Northern Mariana Islands"},"MQ":{"name":"Martinique"},"MR":{"name":"Mauritania"},"MS":{"name":"Montserrat"},"MT":{"name":"Malta"},"MU":{"name":"Mauritius"},"MV":{"name":"Maldives"},"MW":{"name":"Malawi"},"MX":{"name":"Mexico","regions":{"942":{"code":"AGU","name":"Aguascalientes"},"943":{"code":"BCN","name":"Baja California"},"944":{"code":"BCS","name":"Baja California Sur"},"945":{"code":"CAM","name":"Campeche"},"946":{"code":"CHP","name":"Chiapas"},"947":{"code":"CHH","name":"Chihuahua"},"948":{"code":"CMX","name":"Ciudad de M\u00e9xico"},"949":{"code":"COA","name":"Coahuila"},"950":{"code":"COL","name":"Colima"},"951":{"code":"DUR","name":"Durango"},"952":{"code":"MEX","name":"Estado de M\u00e9xico"},"953":{"code":"GUA","name":"Guanajuato"},"954":{"code":"GRO","name":"Guerrero"},"955":{"code":"HID","name":"Hidalgo"},"956":{"code":"JAL","name":"Jalisco"},"957":{"code":"MIC","name":"Michoac\u00e1n"},"958":{"code":"MOR","name":"Morelos"},"959":{"code":"NAY","name":"Nayarit"},"960":{"code":"NLE","name":"Nuevo Le\u00f3n"},"961":{"code":"OAX","name":"Oaxaca"},"962":{"code":"PUE","name":"Puebla"},"963":{"code":"QUE","name":"Quer\u00e9taro"},"964":{"code":"ROO","name":"Quintana Roo"},"965":{"code":"SLP","name":"San Luis Potos\u00ed"},"966":{"code":"SIN","name":"Sinaloa"},"967":{"code":"SON","name":"Sonora"},"968":{"code":"TAB","name":"Tabasco"},"969":{"code":"TAM","name":"Tamaulipas"},"970":{"code":"TLA","name":"Tlaxcala"},"971":{"code":"VER","name":"Veracruz"},"972":{"code":"YUC","name":"Yucat\u00e1n"},"973":{"code":"ZAC","name":"Zacatecas"}}},"MY":{"name":"Malaysia"},"MZ":{"name":"Mozambique"},"NA":{"name":"Namibia"},"NC":{"name":"New Caledonia"},"NE":{"name":"Niger"},"NF":{"name":"Norfolk Island"},"NG":{"name":"Nigeria"},"NI":{"name":"Nicaragua"},"NL":{"name":"Netherlands"},"NO":{"name":"Norway"},"NP":{"name":"Nepal"},"NR":{"name":"Nauru"},"NU":{"name":"Niue"},"NZ":{"name":"New Zealand"},"OM":{"name":"Oman"},"PA":{"name":"Panama"},"PE":{"name":"Peru","regions":{"993":{"code":"PE-AMA","name":"Amazonas"},"994":{"code":"PE-ANC","name":"Ancash"},"995":{"code":"PE-APU","name":"Apur\u00edmac"},"996":{"code":"PE-ARE","name":"Arequipa"},"997":{"code":"PE-AYA","name":"Ayacucho"},"998":{"code":"PE-CAJ","name":"Cajamarca"},"999":{"code":"PE-CUS","name":"Cusco"},"1000":{"code":"PE-CAL","name":"El Callao"},"1001":{"code":"PE-HUV","name":"Huancavelica"},"1002":{"code":"PE-HUC","name":"Hu\u00e1nuco"},"1003":{"code":"PE-ICA","name":"Ica"},"1004":{"code":"PE-JUN","name":"Jun\u00edn"},"1005":{"code":"PE-LAL","name":"La Libertad"},"1006":{"code":"PE-LAM","name":"Lambayeque"},"1007":{"code":"PE-LIM","name":"Lima"},"1008":{"code":"PE-LOR","name":"Loreto"},"1009":{"code":"PE-MDD","name":"Madre de Dios"},"1010":{"code":"PE-MOQ","name":"Moquegua"}
7398,"992":{"code":"PE-LMA","name":"Municipalidad Metropolitana de Lima"},"1011":{"code":"PE-PAS","name":"Pasco"},"1012":{"code":"PE-PIU","name":"Piura"},"1013":{"code":"PE-PUN","name":"Puno"},"1014":{"code":"PE-SAM","name":"San Mart\u00edn"},"1015":{"code":"PE-TAC","name":"Tacna"},"1016":{"code":"PE-TUM","name":"Tumbes"},"1017":{"code":"PE-UCA","name":"Ucayali"}}},"PF":{"name":"French Polynesia"},"PG":{"name":"Papua New Guinea"},"PH":{"name":"Philippines"},"PK":{"name":"Pakistan"},"PL":{"name":"Poland","regions":{"1018":{"code":"PL-02","name":"dolno\u015bl\u0105skie"},"1019":{"code":"PL-04","name":"kujawsko-pomorskie"},"1020":{"code":"PL-06","name":"lubelskie"},"1021":{"code":"PL-08","name":"lubuskie"},"1024":{"code":"PL-14","name":"mazowieckie"},"1023":{"code":"PL-12","name":"ma\u0142opolskie"},"1025":{"code":"PL-16","name":"opolskie"},"1026":{"code":"PL-18","name":"podkarpackie"},"1027":{"code":"PL-20","name":"podlaskie"},"1028":{"code":"PL-22","name":"pomorskie"},"1029":{"code":"PL-24","name":"\u015bl\u0105skie"},"1030":{"code":"PL-26","name":"\u015bwi\u0119tokrzyskie"},"1031":{"code":"PL-28","name":"warmi\u0144sko-mazurskie"},"1032":{"code":"PL-30","name":"wielkopolskie"},"1033":{"code":"PL-32","name":"zachodniopomorskie"},"1022":{"code":"PL-10","name":"\u0142\u00f3dzkie"}}},"PM":{"name":"St. Pierre & Miquelon"},"PN":{"name":"Pitcairn Islands"},"PS":{"name":"Palestinian Territories"},"PT":{"name":"Portugal","regions":{"1034":{"code":"PT-01","name":"Aveiro"},"1035":{"code":"PT-02","name":"Beja"},"1036":{"code":"PT-03","name":"Braga"},"1037":{"code":"PT-04","name":"Bragan\u00e7a"},"1038":{"code":"PT-05","name":"Castelo Branco"},"1039":{"code":"PT-06","name":"Coimbra"},"1040":{"code":"PT-07","name":"\u00c9vora"},"1041":{"code":"PT-08","name":"Faro"},"1042":{"code":"PT-09","name":"Guarda"},"1043":{"code":"PT-10","name":"Leiria"},"1044":{"code":"PT-11","name":"Lisboa"},"1045":{"code":"PT-12","name":"Portalegre"},"1046":{"code":"PT-13","name":"Porto"},"1053":{"code":"PT-30","name":"Regi\u00e3o Aut\u00f3noma da Madeira"},"1052":{"code":"PT-20","name":"Regi\u00e3o Aut\u00f3noma dos A\u00e7ores"},"1047":{"code":"PT-14","name":"Santar\u00e9m"},"1048":{"code":"PT-15","name":"Set\u00fabal"},"1049":{"code":"PT-16","name":"Viana do Castelo"},"1050":{"code":"PT-17","name":"Vila Real"},"1051":{"code":"PT-18","name":"Viseu"}}},"PW":{"name":"Palau"},"PY":{"name":"Paraguay","regions":{"975":{"code":"PY-16","name":"Alto Paraguay"},"976":{"code":"PY-10","name":"Alto Paran\u00e1"},"977":{"code":"PY-13","name":"Amambay"},"974":{"code":"PY-ASU","name":"Asunci\u00f3n"},"978":{"code":"PY-19","name":"Boquer\u00f3n"},"979":{"code":"PY-5","name":"Caaguaz\u00fa"},"980":{"code":"PY-6","name":"Caazap\u00e1"},"981":{"code":"PY-14","name":"Canindey\u00fa"},"982":{"code":"PY-11","name":"Central"},"983":{"code":"PY-1","name":"Concepci\u00f3n"},"984":{"code":"PY-3","name":"Cordillera"},"985":{"code":"PY-4","name":"Guair\u00e1"},"986":{"code":"PY-7","name":"Itap\u00faa"},"987":{"code":"PY-8","name":"Misiones"},"988":{"code":"PY-12","name":"\u00d1eembuc\u00fa"},"989":{"code":"PY-9","name":"Paraguar\u00ed"},"990":{"code":"PY-15","name":"Presidente Hayes"},"991":{"code":"PY-2","name":"San Pedro"}}},"QA":{"name":"Qatar"},"RE":{"name":"R\u00e9union"},"RO":{"name":"Romania","regions":{"278":{"code":"AB","name":"Alba"},"279":{"code":"AR","name":"Arad"},"280":{"code":"AG","name":"Arge\u015f"},"281":{"code":"BC","name":"Bac\u0103u"},"282":{"code":"BH","name":"Bihor"},"283":{"code":"BN","name":"Bistri\u0163a-N\u0103s\u0103ud"},"284":{"code":"BT","name":"Boto\u015fani"},"286":{"code":"BR","name":"Br\u0103ila"},"285":{"code":"BV","name":"Bra\u015fov"},"287":{"code":"B","name":"Bucure\u015fti"},"288":{"code":"BZ","name":"Buz\u0103u"},"290":{"code":"CL","name":"C\u0103l\u0103ra\u015fi"},"289":{"code":"CS","name":"Cara\u015f-Severin"},"291":{"code":"CJ","name":"Cluj"},"292":{"code":"CT","name":"Constan\u0163a"},"293":{"code":"CV","name":"Covasna"},"294":{"code":"DB","name":"D\u00e2mbovi\u0163a"},"295":{"code":"DJ","name":"Dolj"},"296":{"code":"GL","name":"Gala\u0163i"},"297":{"code":"GR","name":"Giurgiu"},"298":{"code":"GJ","name":"Gorj"},"299":{"code":"HR","name":"Harghita"},"300":{"code":"HD","name":"Hunedoara"},"301":{"code":"IL","name":"Ialomi\u0163a"},"302":{"code":"IS","name":"Ia\u015fi"},"303":{"code":"IF","name":"Ilfov"},"304":{"code":"MM","name":"Maramure\u015f"},"305":{"code":"MH","name":"Mehedin\u0163i"},"306":{"code":"MS","name":"Mure\u015f"},"307":{"code":"NT","name":"Neam\u0163"},"308":{"code":"OT","name":"Olt"},"309":{"code":"PH","name":"Prahova"},"311":{"code":"SJ","name":"S\u0103laj"},"310":{"code":"SM","name":"Satu-Mare"},"312":{"code":"SB","name":"Sibiu"},"313":{"code":"SV","name":"Suceava"},"314":{"code":"TR","name":"Teleorman"},"315":{"code":"TM","name":"Timi\u015f"},"316":{"code":"TL","name":"Tulcea"},"318":{"code":"VL","name":"V\u00e2lcea"},"317":{"code":"VS","name":"Vaslui"},"319":{"code":"VN","name":"Vrancea"}}},"RS":{"name":"Serbia"},"RU":{"name":"Russia"},"RW":{"name":"Rwanda"},"SA":{"name":"Saudi Arabia"},"SB":{"name":"Solomon Islands"},"SC":{"name":"Seychelles"},"SD":{"name":"Sudan"},"SE":{"name":"Sweden","regions":{"1064":{"code":"SE-K","name":"Blekinge l\u00e4n"}
7398,"1065":{"code":"SE-W","name":"Dalarnas l\u00e4n"},"1067":{"code":"SE-X","name":"G\u00e4vleborgs l\u00e4n"},"1066":{"code":"SE-I","name":"Gotlands l\u00e4n"},"1068":{"code":"SE-N","name":"Hallands l\u00e4n"},"1069":{"code":"SE-Z","name":"J\u00e4mtlands l\u00e4n"},"1070":{"code":"SE-F","name":"J\u00f6nk\u00f6pings l\u00e4n"},"1071":{"code":"SE-H","name":"Kalmar l\u00e4n"},"1072":{"code":"SE-G","name":"Kronobergs l\u00e4n"},"1073":{"code":"SE-BD","name":"Norrbottens l\u00e4n"},"1083":{"code":"SE-T","name":"\u00d6rebro l\u00e4n"},"1084":{"code":"SE-E","name":"\u00d6sterg\u00f6tlands l\u00e4n"},"1074":{"code":"SE-M","name":"Sk\u00e5ne l\u00e4n"},"1076":{"code":"SE-D","name":"S\u00f6dermanlands l\u00e4n"},"1075":{"code":"SE-AB","name":"Stockholms l\u00e4n"},"1077":{"code":"SE-C","name":"Uppsala l\u00e4n"},"1078":{"code":"SE-S","name":"V\u00e4rmlands l\u00e4n"},"1079":{"code":"SE-AC","name":"V\u00e4sterbottens l\u00e4n"},"1080":{"code":"SE-Y","name":"V\u00e4sternorrlands l\u00e4n"},"1081":{"code":"SE-U","name":"V\u00e4stmanlands l\u00e4n"},"1082":{"code":"SE-O","name":"V\u00e4stra G\u00f6talands l\u00e4n"}}},"SG":{"name":"Singapore"},"SH":{"name":"St. Helena"},"SI":{"name":"Slovenia"},"SJ":{"name":"Svalbard & Jan Mayen"},"SK":{"name":"Slovakia"},"SL":{"name":"Sierra Leone"},"SM":{"name":"San Marino"},"SN":{"name":"Senegal"},"SO":{"name":"Somalia"},"SR":{"name":"Suriname","regions":{"1054":{"code":"SR-BR","name":"Brokopondo"},"1055":{"code":"SR-CM","name":"Commewijne"},"1056":{"code":"SR-CR","name":"Coronie"},"1057":{"code":"SR-MA","name":"Marowijne"},"1058":{"code":"SR-NI","name":"Nickerie"},"1059":{"code":"SR-PR","name":"Para"},"1060":{"code":"SR-PM","name":"Paramaribo"},"1061":{"code":"SR-SA","name":"Saramacca"},"1062":{"code":"SR-SI","name":"Sipaliwini"},"1063":{"code":"SR-WA","name":"Wanica"}}},"ST":{"name":"S\u00e3o Tom\u00e9 & Pr\u00edncipe"},"SV":{"name":"El Salvador"},"SX":{"name":"Sint Maarten"},"SY":{"name":"Syria"},"SZ":{"name":"Eswatini"},"TC":{"name":"Turks & Caicos Islands"},"TD":{"name":"Chad"},"TF":{"name":"French Southern Territories"},"TG":{"name":"Togo"},"TH":{"name":"Thailand"},"TJ":{"name":"Tajikistan"},"TK":{"name":"Tokelau"},"TL":{"name":"Timor-Leste"},"TM":{"name":"Turkmenistan"},"TN":{"name":"Tunisia"},"TO":{"name":"Tonga"},"TR":{"name":"T\u00fcrkiye"},"TT":{"name":"Trinidad & Tobago"},"TV":{"name":"Tuvalu"},"TW":{"name":"Taiwan"},"TZ":{"name":"Tanzania"},"UA":{"name":"Ukraine","regions":{"1109":{"code":"UA-43","name":"Avtonomna Respublika Krym"},"1085":{"code":"UA-71","name":"Cherkaska oblast"},"1086":{"code":"UA-74","name":"Chernihivska oblast"},"1087":{"code":"UA-77","name":"Chernivetska oblast"},"1088":{"code":"UA-12","name":"Dnipropetrovska oblast"},"1089":{"code":"UA-14","name":"Donetska oblast"},"1090":{"code":"UA-26","name":"Ivano-Frankivska oblast"},"1091":{"code":"UA-63","name":"Kharkivska oblast"},"1092":{"code":"UA-65","name":"Khersonska oblast"},"1093":{"code":"UA-68","name":"Khmelnytska oblast"},"1094":{"code":"UA-35","name":"Kirovohradska oblast"},"1110":{"code":"UA-30","name":"Kyiv"},"1095":{"code":"UA-32","name":"Kyivska oblast"},"1096":{"code":"UA-09","name":"Luhanska oblast"},"1097":{"code":"UA-46","name":"Lvivska oblast"},"1098":{"code":"UA-48","name":"Mykolaivska oblast"},"1099":{"code":"UA-51","name":"Odeska oblast"},"1100":{"code":"UA-53","name":"Poltavska oblast"},"1101":{"code":"UA-56","name":"Rivnenska oblast"},"1111":{"code":"UA-40","name":"Sevastopol"},"1102":{"code":"UA-59","name":"Sumska oblast"},"1103":{"code":"UA-61","name":"Ternopilska oblast"},"1104":{"code":"UA-05","name":"Vinnytska oblast"},"1105":{"code":"UA-07","name":"Volynska oblast"},"1106":{"code":"UA-21","name":"Zakarpatska oblast"},"1107":{"code":"UA-23","name":"Zaporizka oblast"},"1108":{"code":"UA-18","name":"Zhytomyrska oblast"}}},"UG":{"name":"Uganda"},"UM":{"name":"U.S. Outlying Islands"},"US":{"name":"United States","regions":{"1":{"code":"AL","name":"Alabama"},"2":{"code":"AK","name":"Alaska"},"3":{"code":"AS","name":"American Samoa"},"4":{"code":"AZ","name":"Arizona"},"5":{"code":"AR","name":"Arkansas"},"6":{"code":"AE","name":"Armed Forces Africa"},"7":{"code":"AA","name":"Armed Forces Americas"},"8":{"code":"AE","name":"Armed Forces Canada"},"9":{"code":"AE","name":"Armed Forces Europe"},"10":{"code":"AE","name":"Armed Forces Middle East"},"11":{"code":"AP","name":"Armed Forces Pacific"},"12":{"code":"CA","name":"California"},"13":{"code":"CO","name":"Colorado"},"14":{"code":"CT","name":"Connecticut"},"15":{"code":"DE","name":"Delaware"},"16":{"code":"DC","name":"District of Columbia"},"17":{"code":"FM","name":"Federated States Of Micronesia"}
7398,"18":{"code":"FL","name":"Florida"},"19":{"code":"GA","name":"Georgia"},"20":{"code":"GU","name":"Guam"},"21":{"code":"HI","name":"Hawaii"},"22":{"code":"ID","name":"Idaho"},"23":{"code":"IL","name":"Illinois"},"24":{"code":"IN","name":"Indiana"},"25":{"code":"IA","name":"Iowa"},"26":{"code":"KS","name":"Kansas"},"27":{"code":"KY","name":"Kentucky"},"28":{"code":"LA","name":"Louisiana"},"29":{"code":"ME","name":"Maine"},"30":{"code":"MH","name":"Marshall Islands"},"31":{"code":"MD","name":"Maryland"},"32":{"code":"MA","name":"Massachusetts"},"33":{"code":"MI","name":"Michigan"},"34":{"code":"MN","name":"Minnesota"},"35":{"code":"MS","name":"Mississippi"},"36":{"code":"MO","name":"Missouri"},"37":{"code":"MT","name":"Montana"},"38":{"code":"NE","name":"Nebraska"},"39":{"code":"NV","name":"Nevada"},"40":{"code":"NH","name":"New Hampshire"},"41":{"code":"NJ","name":"New Jersey"},"42":{"code":"NM","name":"New Mexico"},"43":{"code":"NY","name":"New York"},"44":{"code":"NC","name":"North Carolina"},"45":{"code":"ND","name":"North Dakota"},"46":{"code":"MP","name":"Northern Mariana Islands"},"47":{"code":"OH","name":"Ohio"},"48":{"code":"OK","name":"Oklahoma"},"49":{"code":"OR","name":"Oregon"},"50":{"code":"PW","name":"Palau"},"51":{"code":"PA","name":"Pennsylvania"},"52":{"code":"PR","name":"Puerto Rico"},"53":{"code":"RI","name":"Rhode Island"},"54":{"code":"SC","name":"South Carolina"},"55":{"code":"SD","name":"South Dakota"},"56":{"code":"TN","name":"Tennessee"},"57":{"code":"TX","name":"Texas"},"58":{"code":"UT","name":"Utah"},"59":{"code":"VT","name":"Vermont"},"60":{"code":"VI","name":"Virgin Islands"},"61":{"code":"VA","name":"Virginia"},"62":{"code":"WA","name":"Washington"},"63":{"code":"WV","name":"West Virginia"},"64":{"code":"WI","name":"Wisconsin"},"65":{"code":"WY","name":"Wyoming"}}},"UY":{"name":"Uruguay","regions":{"1112":{"code":"UY-AR","name":"Artigas"},"1113":{"code":"UY-CA","name":"Canelones"},"1114":{"code":"UY-CL","name":"Cerro Largo"},"1115":{"code":"UY-CO","name":"Colonia"},"1116":{"code":"UY-DU","name":"Durazno"},"1117":{"code":"UY-FS","name":"Flores"},"1118":{"code":"UY-FD","name":"Florida"},"1119":{"code":"UY-LA","name":"Lavalleja"},"1120":{"code":"UY-MA","name":"Maldonado"},"1121":{"code":"UY-MO","name":"Montevideo"},"1122":{"code":"UY-PA","name":"Paysandu"},"1123":{"code":"UY-RN","name":"R\u00edo Negro"},"1124":{"code":"UY-RV","name":"Rivera"},"1125":{"code":"UY-RO","name":"Rocha"},"1126":{"code":"UY-SA","name":"Salto"},"1127":{"code":"UY-SJ","name":"San Jos\u00e9"},"1128":{"code":"UY-SO","name":"Soriano"},"1129":{"code":"UY-TA","name":"Tacuaremb\u00f3"},"1130":{"code":"UY-TT","name":"Treinta y Tres"}}},"UZ":{"name":"Uzbekistan"},"VA":{"name":"Vatican City"},"VC":{"name":"St. Vincent & Grenadines"},"VE":{"name":"Venezuela","regions":{"1133":{"code":"VE-Z","name":"Amazonas"},"1134":{"code":"VE-B","name":"Anzo\u00e1tegui"},"1135":{"code":"VE-C","name":"Apure"},"1136":{"code":"VE-D","name":"Aragua"},"1137":{"code":"VE-E","name":"Barinas"},"1138":{"code":"VE-F","name":"Bol\u00edvar"},"1139":{"code":"VE-G","name":"Carabobo"},"1140":{"code":"VE-H","name":"Cojedes"},"1141":{"code":"VE-Y","name":"Delta Amacuro"},"1131":{"code":"VE-W","name":"Dependencias Federales"},"1132":{"code":"VE-A","name":"Distrito Capital"},"1142":{"code":"VE-I","name":"Falc\u00f3n"},"1143":{"code":"VE-J","name":"Gu\u00e1rico"},"1144":{"code":"VE-K","name":"Lara"},"1145":{"code":"VE-L","name":"M\u00e9rida"},"1146":{"code":"VE-M","name":"Miranda"},"1147":{"code":"VE-N","name":"Monagas"},"1148":{"code":"VE-O","name":"Nueva Esparta"},"1149":{"code":"VE-P","name":"Portuguesa"},"1150":{"code":"VE-R","name":"Sucre"},"1151":{"code":"VE-S","name":"T\u00e1chira"},"1152":{"code":"VE-T","name":"Trujillo"},"1153":{"code":"VE-X","name":"Vargas"},"1154":{"code":"VE-U","name":"Yaracuy"},"1155":{"code":"VE-V","name":"Zulia"}}},"VG":{"name":"British Virgin Islands"},"VI":{"name":"U.S. Virgin Islands"},"VN":{"name":"Vietnam"},"VU":{"name":"Vanuatu"},"WF":{"name":"Wallis & Futuna"},"WS":{"name":"Samoa"},"XK":{"name":"Kosovo"},"YE":{"name":"Yemen"},"YT":{"name":"Mayotte"},"ZA":{"name":"South Africa"},"ZM":{"name":"Zambia"},"ZW":{"name":"Zimbabwe"},"data_id":1790361128},"captcha":[],"instant-purchase":[],"loggedAsCustomer":[],"persistent":[],"review":[],"payments":[],"wishlist":{"items":[]},"quotecart":[],"hyva_checkout":[],"hyva_commerce_messages":[],"capi-event-ids":[],"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[],"paypal-buyer-country":[]}</script>
vendor: 1 bytes, line 7398
7398
7399<script>
7400    window.processSectionDataBeforeDispatch && (window.processSectionDataBeforeDispatch = new Proxy(window.processSectionDataBeforeDispatch, {
7401        apply(target, thisArg, [data]) {
7402            data.hyva_commerce_messages = data.hyva_commerce_messages || {};
7403            return target.call(thisArg, data);
7404        }
7405    }));
7406</script>
7406
7407    
7407<script>
7408        let vatMode = vatSwitcher.getVatMode() || excluding;
7409        let elemSelector = vatMode === 'including' ? '.price-excluding-tax' : '.price-including-tax';
7410
7411        if (document.body.classList.contains('sales-order-view')
7412            || document.body.classList.contains('sales-order-invoice')) {
7413            elemSelector = null;
7414        }
7415        if (elemSelector) {
7416            document.querySelectorAll(elemSelector).forEach(function (el) {
7417                if (!el.classList.contains('hidden')) {
7418                    el.classList.add('hidden')
7419                }
7420            });
7421        }
7422    </script>
7422
7423</div></body>
7424</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.