PageSourceSearch

https://brustersonline.com/

html brustersonline.com collected 2026-09-29 00:15:54 UTC 203,568 bytes, 4,801 lines download raw bytes

1
2
3<!DOCTYPE html>
4<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
5<head>
6    
6<script>
7    var isAppWebView = false;
8
9    try {
10      var ua = navigator.userAgent || '';
11      if (ua.includes('wv') || ua.includes('WebView') || ua.includes('BrustersApp')) {
12        isAppWebView = true;
13      }
14    } catch(e){}
15    </script>
15
16
17        
17<script>
18
19       
20
21        window.dataLayer = window.dataLayer || [];
22        function gtag(){dataLayer.push(arguments);}
23
24        if(!isAppWebView){
25          gtag('consent','default',{
26            ad_user_data:'denied',
27            ad_personalization:'denied',
28            ad_storage:'denied',
29            analytics_storage:'denied',
30            wait_for_update:500
31          });
32        }
33        </script>
33
34
35      <!-- Google Tag Manager -->
36        
36<script>
vendor: 364 bytes, lines 36-40
36(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
37        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
38        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
39        ' https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
40        })(window,document,'script','dataLayer','
40GTM-WH48QBD
vendor: 3 bytes, line 40
40');
40</script>
40
41        <!-- End Google Tag Manager -->
42
43       
43<script>
44      if (!isAppWebView) {
45        var s = document.createElement('script');
46        s.id = 'Cookiebot';
47        s.src = 'https://consent.cookiebot.com/uc.js';
48        s.async = true;
49        s.setAttribute('data-cbid', '43aabde7-00fb-4fc3-839c-309c4d1aa2fb');
50        document.head.appendChild(s);
51      }
52    </script>
52
53
54  
55
56    <meta property="og:description" content="Order online from your local Bruster&#39;s Ice Cream! From custom ice cream cakes to sundaes, order your favorite treats today." /><meta property="og:title" content="Bruster&#39;s - Order Ice Cream Online" /><meta property="og:image" content="https://brustersazure.blob.core.windows.net/onlineproductimages/1400x800_Category-SundaesV2.png" /><meta property="og:type" content="website" /><meta property="og:url" content="https://brustersonline.com/BrustersCom/Cart.aspx" /><meta property="og:site_name" content="Bruster&#39;s Real Ice Cream" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="Bruster&#39;s - Order Online" /><meta name="twitter:description" content="Order online from your local Bruster&#39;s Ice Cream! From custom ice cream cakes to sundaes, order your favorite treats today." /><meta name="twitter:image" content="https://brustersazure.blob.core.windows.net/onlineproductimages/1400x800_Category-SundaesV2.png" /><meta name="description" content="Order online from your local Bruster&#39;s Ice Cream! Cakes, sundaes, and more available for pickup." /><meta name="robots" content="index, follow" /><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>
57	Bruster's - Order Ice Cream Online
58</title><link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" /><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" /><link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" rel="stylesheet" /><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@eonasdan/[email protected]/dist/css/tempus-dominus.min.css" crossorigin="anonymous" />
59    
59<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
59
60    
60<script src="https://web.squarecdn.com/v1/square.js"></script>
60
61    
61<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" crossorigin="anonymous"></script>
61
62    
62<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
62
63    
63<script src="https://cdn.jsdelivr.net/npm/@eonasdan/[email protected]/dist/js/tempus-dominus.min.js" crossorigin="anonymous"></script>
63
64    
64<script src="/BrustersCom/js/locationsearchV2.js?v=11"></script>
64
65    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
66     
66<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
66
67    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css" />
68    
68<script src="js/onlineordering-square-sdk-v2.js?v=118"></script>
68
69    <link href="BrustersCom/css/sqPaymentForm.css" rel="stylesheet" />
70    
70<script src="js/gtm.js?v=12"></script>
70
71    <style>
72        /* ADA - improved link contrast */
73.btn-link {
74    color: #0367FC;
75}
76
77/* ADA - visible keyboard focus */
78.btn:focus-visible {
79    outline: 3px solid #0367FC;
80    outline-offset: 2px;
81    box-shadow: 0 0 0 0.25rem rgba(3, 103, 252, 0.25);
82}
83
84        .gift-card-warning {
85    color: #990000;
86}
87
88 .header-logo-link:focus {
89    box-shadow: none;
90}
91
92.header-logo-link:focus-visible {
93    outline: none;
94    outline-offset: 3px;
95}
96  .menu-section button:focus {
97    box-shadow: none;
98}
99
100.menu-section button:focus:not(:focus-visible) {
101    outline: none;
102}
103
104.promo-label {
105    display: block;
106    margin-top: 4px;
107    font-size: 11px;
108    font-weight: 600;
109    color: #c0392b;
110}
111
112.promo-original {
113    font-weight: 400;
114    color: #555;
115}
116      
117         .modal-header, .modal-footer {
118        background-color: #990000;
119        color: #ffffff;
120    }
121    .modal-header .btn-close {
122        filter: invert(1); /* This inverts the color of the close button to make it visible on the dark background */
123    }
124.flavor-group-heading {
125    background-color: #f8f9fa;
126    color: #990000;
127    font-weight: bold;
128    padding: 10px;
129    border-radius: 5px;
130    margin-bottom: 10px;
131    text-align: center;
132    font-size: 1.2em;
133}
134
135        .fa-eye {
136            cursor: pointer;
137        }
138        .menu-section {
139            margin-bottom: 2rem;
140        }
141 /* Default shadow for all menu-img */
142/* Default styling for all menu-img */
143.menu-img {
144    max-width: 325px;
145    height: auto;
146    display: block;
147    margin-left: auto;
148    margin-right: auto;
149    cursor: pointer;
150    border-radius: 12px;
151    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Subtle shadow */
152    transition: transform 0.3s ease, box-shadow 0.3s ease;
153}
154
155.menu-img:hover {
156    transform: scale(1.05);
157    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
158}
159
160/* Styling for menu-img inside the modal */
161.modal .menu-img {
162    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); /* Increased shadow */
163    background-color: #f7f7f7; /* Set the background color */
164    padding: 10px; /* Add some padding to make the background more visible */
165    border-radius: 12px; /* Ensure rounded corners are still applied */
166}
167
168.modal .menu-img:hover {
169    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3); /* Even more shadow on hover */
170}
171
172/* Styling for menu-img inside the modal */
173.card-img-top {
174    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); /* Increased shadow */
175    background-color: #f7f7f7; /* Set the background color */
176    padding: 10px; /* Add some padding to make the background more visible */
177    border-radius: 12px; /* Ensure rounded corners are still applied */
178    transition: transform 0.3s ease, box-shadow 0.3s ease;
179}
180
181.card-img-top:hover {
182    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3); /* Even more shadow on hover */
183}
184
185
186
187        .selected-modifier {
188            background-color: lightgreen;
189        }
190        .section-links {
191            white-space: nowrap;
192            margin-bottom: 1rem;
193            overflow-x: auto; /* Enable horizontal scrolling */
194            -webkit-overflow-scrolling: touch; /* Smooth scrolling on iOS */
195            scrollbar-width: auto; /* Ensure scrollbar is visible in Firefox */
196            scrollbar-color: #990000 #f1f1f1; /* Customize scrollbar color in Firefox */
197        }
198
199        .section-links::-webkit-scrollbar {
200            height: 8px; /* WebKit-based browsers */
201        }
202
203        .section-links::-webkit-scrollbar-thumb {
204            background-color: #990000; /* WebKit-based browsers */
205            border-radius: 4px; /* WebKit-based browsers */
206        }
207
208        .section-links::-webkit-scrollbar-track {
209            background-color: #f1f1f1; /* WebKit-based browsers */
210            border-radius: 4px; /* WebKit-based browsers */
211        }
212
213        @media (max-width: 768px) {
214            .header-logo {
215                max-width: 150px;
216            }
217        }
218
219        .section-link {
220            display: inline-block;
221            padding: 0.5rem 1rem;
222            margin-right: 0.5rem;
223            background-color: #f8f9fa;
224            border: 1px solid #dee2e6;
225            border-radius: 0.25rem;
226            cursor: pointer;
227            text-decoration: none;
228            color: #000;
229        }
230        .cart {
231            position: fixed;
232            top: 100px;
233            right: 20px;
234            width: 300px;
235            background-color: white;
236            box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
237            padding: 15px;
238            z-index: 1000;
239        }
240        .cart-header {
241            font-weight: bold;
242            margin-bottom: 10px;
243        }
244        .cart-item {
245            display: flex;
246            justify-content: space-between;
247            align-items: center;
248            margin-bottom: 10px;
249        }
250        .cart-item-details {
251            flex: 1;
252            padding-right: 10px;
253        }
254        .cart-item button {
255            align-self: flex-start;
256        }
257        .cart-subtotal {
258            font-weight: bold;
259            margin-top: 10px;
260            padding-top: 10px;
261            border-top: 1px solid #dee2e6;
262            padding-left: 15px;
263        }
264        .cart-tax {
265            font-weight: bold;
266            margin-top: 10px;
267            padding-top: 10px;
268            border-top: 1px solid #dee2e6;
269            padding-left: 15px;
270        }
271        .cart-total {
272            font-weight: bold;
273            margin-top: 10px;
274            padding-top: 10px;
275            border-top: 1px solid #dee2e6;
276            padding-left: 15px;
277        }
278        .popper-image {
279            background: white;
280            border: 1px solid #ccc;
281            padding: 10px;
282            max-width: 300px;
283            z-index: 2000;
284            text-align: center;
285            position: fixed;
286            top: 50%;
287            left: 50%;
288            transform: translate(-50%, -50%);
289        }
290        .popper-image img {
291            max-width: 100%;
292            height: auto;
293        }
294        @media (min-width: 768px) {
295            .popper-image {
296                max-width: 300px;
297            }
298        }
299        @media (max-width: 767px) {
300            .popper-image {
301                max-width: 200px;
302            }
303        }
304        .popper-close {
305            position: absolute;
306            top: 5px;
307            right: 5px;
308            cursor: pointer;
309        }
310        .popper-alert {
311            position: absolute;
312            z-index: 1055; /* higher than Bootstrap's modal z-index of 1050 */
313            background-color: #dc3545; /* Bootstrap danger color */
314            color: white;
315            padding: 10px;
316            border-radius: 5px;
317        }
318        .hidden-items {
319            display: none;
320        }
321        .header-custom {
322            background-color: #990000;
323            display: flex;
324            align-items: center;
325            justify-content: space-between;
326            padding: 10px;
327            color: white;
328        }
329        .header-logo {
330            max-width: 200px;
331            height: auto;
332        }
333
334        @media (max-width: 768px) {
335            .header-logo {
336                max-width: 150px;
337            }
338        }
339
340             .cart-icon {
341            position: relative;
342            color: white;
343            padding: 0;
344            padding-right: 20px;
345            margin: 0;
346            background: none;
347            border: none;
348            font: inherit;
349            appearance: none;
350            -webkit-appearance: none;
351            cursor: pointer;
352        }
353
354        .cart-icon:focus {
355            box-shadow: none;
356        }
357
358        .cart-icon:focus:not(:focus-visible) {
359            outline: none;
360        }
361        .badge-custom {
362            position: absolute;
363            top: 0;
364            start: 100%;
365            transform: translate(-50%, -50%);
366            background-color: white;
367            color: #990000;
368        }
369        .address-display {
370            font-size: 1.2em;
371            font-weight: bold;
372            color: #990000;
373            padding: 10px;
374            border: 2px solid #990000;
375            border-radius: 5px;
376            text-align: center;
377            background-color: #fff5f5;
378            margin-bottom:8px;
379        }
380        /* Optional: Additional custom styling for the rounded header logo */
381        .header-custom.rounded {
382            border-radius: 0.4rem; /* Adjust as needed */
383        }
384        .monthly-features img {
385    margin-bottom: 1rem; /* Add space between the images and below */
386}
387
388.bg-image {
389    background-image: url('https://brusters.imgix.net/SMPost_24Jul_CookieJarCrunch.jpg?fit=clamp&w=1920&h=1080');
390    height: 100vh;
391    width: 100vw;
392    opacity: 0.5; /* Adjust opacity for watermark effect */
393    background-size: cover; /* Ensure the background image covers the entire element */
394    background-position: center top; /* Center the background image horizontally */
395    background-repeat: no-repeat; /* Prevent the background image from repeating */
396    position: absolute;
397    top: 0;
398    left: 0;
399    z-index: -1; /* Ensure the background image is behind the content */
400}
401
402.landing-header-custom {
403    background-color: #990000; /* Same color as the header-custom div */
404    color: white;
405    text-align: center;
406    padding: 10px 0;
407    width: 100%;
408    position: relative;
409    z-index: 2;
410}
411
412.landing-header-custom h2 {
413    margin: 0;
414    font-size: 2rem; /* Adjust the font size as needed */
415}
416
417.landing-content {
418    position: absolute;
419    top: 50%;
420    left: 50%;
421    transform: translate(-50%, -50%);
422    text-align: center;
423    color: white;
424    z-index: 1;
425}
426
427.landing-content img {
428    max-width: 200px;
429    margin-bottom: 20px;
430}
431
432.landing-content .search-section {
433    background-color: rgba(0, 0, 0, 0.5);
434    padding: 20px;
435    border-radius: 10px;
436}
437
438.landing-content .search-section input,
439.landing-content .search-section button {
440    margin: 10px 0;
441}
442
443.landing-content .search-section .or-separator {
444    margin: 10px 0;
445}
446
447.landing-page {
448    display: block; /* Ensure the landing page is visible */
449}
450.img-thumbnail {
451    max-width: 150px;
452    height: auto;
453}
454
455#divstores .list-group-item {
456    padding: 20px;
457    background-color: #fff;
458    border: 1px solid #ddd;
459    border-radius: 10px;
460    margin-bottom: 10px;
461}
462
463
464        .main-content {
465            display: none;
466        }
467
468        /* Absolute Center Spinner */
469.loading {
470    position: fixed;
471    z-index: 999;
472    height: 2em;
473    width: 2em;
474    overflow: show;
475    margin: auto;
476    top: 0;
477    left: 0;
478    bottom: 0;
479    right: 0;
480}
481
482    /* Transparent Overlay */
483    .loading:before {
484        content: '';
485        display: block;
486        position: fixed;
487        top: 0;
488        left: 0;
489        width: 100%;
490        height: 100%;
491        background-color: rgba(0,0,0,0.3);
492    }
493
494    /* :not(:required) hides these rules from IE9 and below */
495    .loading:not(:required) {
496        /* hide "loading..." text */
497        font: 0/0 a;
498        color: transparent;
499        text-shadow: none;
500        background-color: transparent;
501        border: 0;
502    }
503
504        .loading:not(:required):after {
505            content: '';
506            display: block;
507            font-size: 10px;
508            width: 1em;
509            height: 1em;
510            margin-top: -0.5em;
511            -webkit-animation: spinner 1500ms infinite linear;
512            -moz-animation: spinner 1500ms infinite linear;
513            -ms-animation: spinner 1500ms infinite linear;
514            -o-animation: spinner 1500ms infinite linear;
515            animation: spinner 1500ms infinite linear;
516            border-radius: 0.5em;
517            -webkit-box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.5) -1.5em 0 0 0, rgba(0, 0, 0, 0.5) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
518            box-shadow: rgba(0, 0, 0, 0.75) 1.5em 0 0 0, rgba(0, 0, 0, 0.75) 1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) 0 1.5em 0 0, rgba(0, 0, 0, 0.75) -1.1em 1.1em 0 0, rgba(0, 0, 0, 0.75) -1.5em 0 0 0, rgba(0, 0, 0, 0.75) -1.1em -1.1em 0 0, rgba(0, 0, 0, 0.75) 0 -1.5em 0 0, rgba(0, 0, 0, 0.75) 1.1em -1.1em 0 0;
519        }
520
521
522
523/* Animation */
524
525@-webkit-keyframes spinner {
526    0% {
527        -webkit-transform: rotate(0deg);
528        -moz-transform: rotate(0deg);
529        -ms-transform: rotate(0deg);
530        -o-transform: rotate(0deg);
531        transform: rotate(0deg);
532    }
533
534    100% {
535        -webkit-transform: rotate(360deg);
536        -moz-transform: rotate(360deg);
537        -ms-transform: rotate(360deg);
538        -o-transform: rotate(360deg);
539        transform: rotate(360deg);
540    }
541}
542
543@-moz-keyframes spinner {
544    0% {
545        -webkit-transform: rotate(0deg);
546        -moz-transform: rotate(0deg);
547        -ms-transform: rotate(0deg);
548        -o-transform: rotate(0deg);
549        transform: rotate(0deg);
550    }
551
552    100% {
553        -webkit-transform: rotate(360deg);
554        -moz-transform: rotate(360deg);
555        -ms-transform: rotate(360deg);
556        -o-transform: rotate(360deg);
557        transform: rotate(360deg);
558    }
559}
560
561@-o-keyframes spinner {
562    0% {
563        -webkit-transform: rotate(0deg);
564        -moz-transform: rotate(0deg);
565        -ms-transform: rotate(0deg);
566        -o-transform: rotate(0deg);
567        transform: rotate(0deg);
568    }
569
570    100% {
571        -webkit-transform: rotate(360deg);
572        -moz-transform: rotate(360deg);
573        -ms-transform: rotate(360deg);
574        -o-transform: rotate(360deg);
575        transform: rotate(360deg);
576    }
577}
578
579@keyframes spinner {
580    0% {
581        -webkit-transform: rotate(0deg);
582        -moz-transform: rotate(0deg);
583        -ms-transform: rotate(0deg);
584        -o-transform: rotate(0deg);
585        transform: rotate(0deg);
586    }
587
588    100% {
589        -webkit-transform: rotate(360deg);
590        -moz-transform: rotate(360deg);
591        -ms-transform: rotate(360deg);
592        -o-transform: rotate(360deg);
593        transform: rotate(360deg);
594    }
595}
596
597/* Add styles for the storelist-page */
598.storelist-page .bg-image {
599    background-image: url('https://brusters.imgix.net/SMPost_24Jul_CookieJarCrunch.jpg?fit=clamp&w=1920&h=1080');
600    height: 100vh;
601    width: 100vw;
602    opacity: 0.5;
603    background-size: cover;
604    background-position: center top;
605    background-repeat: no-repeat;
606    position: absolute;
607    top: 0;
608    left: 0;
609    z-index: -1;
610}
611
612.storelist-page .landing-header-custom {
613    background-color: #990000;
614    color: white;
615    text-align: center;
616    padding: 10px 0;
617    width: 100%;
618    position: relative;
619    z-index: 1;
620    border-radius: 10px;
621}
622
623.storelist-page .landing-header-custom h2 {
624    margin: 0;
625    font-size: 2rem;
626}
627
628#divstores {
629    position: relative;
630    z-index: 1;
631    padding: 20px;
632}
633
634.small-font {
635        font-size: 0.8em;
636    }
637   .font-weight-bold {
638        font-weight: bold;
639    }
640   .featured-product-card {
641        max-width: 200px;
642        flex: 0 0 auto;
643    }
644
645    @media (min-width: 768px) {
646        .d-flex.flex-nowrap.overflow-auto {
647            flex-wrap: wrap;
648            justify-content: space-around;
649        }
650
651        .featured-product-card {
652            flex: 1 1 calc(25% - 1rem); /* Adjust the card width and margin */
653            margin: 0.5rem;
654        }
655    }
656
657
658
659    </style>
660</head>
661<body>
662    <!-- Google Tag Manager (noscript) -->
vendor: 74 bytes, lines 662-663
662
663    <noscript><iframe src=" https://www.googletagmanager.com/ns.html?id=
663GTM-WH48QBD
vendor: 94 bytes, lines 663-665
663 "
664    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
665    
665<!-- End Google Tag Manager (noscript) -->
666     <form method="post" action="./" id="form1">
667<div class="aspNetHidden">
668<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
669<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
670<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTcwMjU4MDc2NA8WAh4TVmFsaWRhdGVSZXF1ZXN0TW9kZQIBZGRRCn7+/lAXA4OB8fqlj9UqzOa9Jw1dZtHeiJlpD9Noyw==" />
671</div>
672
673<script type="text/javascript">
674//<![CDATA[
675var theForm = document.forms['form1'];
676if (!theForm) {
677    theForm = document.form1;
678}
679function __doPostBack(eventTarget, eventArgument) {
680    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
681        theForm.__EVENTTARGET.value = eventTarget;
682        theForm.__EVENTARGUMENT.value = eventArgument;
683        theForm.submit();
684    }
685}
686//]]>
687</script>
687
688
689
690<div class="aspNetHidden">
691
692	<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="15ECB9E0" />
693	<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAFekkV+DNU9eNxtxHNgjOdjtwMbEJOwoVsSLDYPCE3G5HAAHZ+oVTfVxaqyuu9G/+n/3yreNFS8E/KpKYycKDEdkArt8ewAGDocERgSDWjTDRDWGGcLRc5vhLnlg3wW1MFTiE0/pr75ubVHBQmRK1hekzJtHovtyCS8eyTZCoFS3Q33Q/QLw+64IfQ/VF988mXffk3WNBwaNsoC/U/z/8VHjxEKD3SGWH/spCzyg42d8Qnj5SxjWapftyn1PJ53zbTwsnjzlxcwhPvvR2JwBgH13gHgEtgrdorlL4mGUyycpDzEqinOUKRa9CHfcuTgKbTEUS6BsSCxR7BYkWQs/wefeBMhqnz1crXMAb0Kt86cXIw8X1WIY7quvlGDtamUrNe7rHWS9YE1KiDIm00kjm894XfWKPZQ5yuO46xuKz5yPKEe8PZtCZYA/Ig4wO40kojCUenwv0sI6O+cV9KaCOcSyU9en8BECpqsW//1zoNRaa7Hc5KAJlSXv8PyjU4Lm2KYTUmVOiL8gXVPuefeS9AeUKNRpLLqEymPEWA+FRoPlLXOQRruLm4QuDEHoNUBPfjYAtv9olsPBTOgeh76nLyhxBbT1WKbwmYt2RCi9JBdL7Sp9ewXDxw1y+IUtOYkW8Ec1HENTVCXJKzEHUkHCxUfsRP15AOtlKL443Sqtx+vT8L58wD/vUMbhFGiCoAUsFVM5CAisSSg7eREwOgNwDB9x4zVTVHJuoads5e5hpNZ6nC/PUU09b7gWsldi1Lp4dQaX/glL6PCPewB4sRc8wptly3nvt2biflv6NfnwLpd4nCNpj3CUe4FAg9xquwgSMaHYpEJmN2nKi265p+50r4zGydHldIiRntTcaDKHRM1LtQNIAPeML3ZloNoImF+Y++5WRILd7tsFn06Mxiu9xp7Pi/TUeKbumH0eckUmQVSXfkvbXHZ1IxGG21l9t53Ya2SA28+1OaivfuaUakd/8ZMv8/jOOml9MQSHhqjIXNMVDi2612+Vyn+hKpiiwKdGIZ0i3tIIsOPjiXQSqQ9LgLqJaFJ6YBb7MV/smKXs+uzf/XHoLm1pbNQ1Wf+ZGjiDSeI6wUW+5WkWQTH+RHB2bAmnRe/6TpoJYPK1ETJ6muL1E6dp/EngC+ZspMFa+zUCHPu1KRIgO+mlYqmtLv4aUDzYJCO7kWocGf1EFvmssudlM5PhTOLX1wxlXnZRUHPivIDmjMswxyGe9ovM0HMWABz4pjsUVclid8USf95gJT5HLD+aPFeX46kNIe/FLwmImBtWB499TNKmHmHpwQxpKO9IuJQ9vkk4qmyriwDEG2ibJLQL/vQXEEKqTBAvV8opg/CYRUJtm3/JgaF0vghvSdUfO+ry4ztPVndwnoGJi5z93TqzQ/psN0pqmEr0IY1BTviieQhio2oswFtUAIWcBdVHqcfY9lCGHJffKo+cU2sURbmkvSpp4hlkykV2ruMKnBGsMyqYsBZMw4mHg2REVMkfFHFtjT3D6oO/VqUGKaMSrFA/MAwvnR3yYR4gIaAR1u+7gZ52+RmS45olUWTd5dZ4cGGdlbIs+C2SCtzpH8PtakI+3fo5gtDLzlRFUEzotEHAzZKyUmM/yqZ57c9IYiRff+lUzBflnd13gQJb2HUnjebZEypAjanRHVKRYwAIKvsz4oVEIuJfzufJUaY24FjgmUCXO/JNwTrexzlBqwjJnEEsf/ad8ONqeh+s7YGol6Y7HTZJrbYSQgaVr2+6HNjTES8hyJTnu9R/DaSAEbCthL5CCTaygXvrU88QYi2tZx7LeJk0RbFLah31K3kUbjeT2T8zLrQopZYSyTsy+Xy+qKbBe5mC5hM3L6RZ8jbuYsOpISLofszdfnSA2suj9bqkcxpqzs64WlejnBxYfYzJ1A==" />
694</div>
695         <input type="hidden" name="hfKiosk" id="hfKiosk" value="False" />
696          <input type="hidden" name="hfNumber" id="hfNumber" />
697           <input type="hidden" name="hfEvoAuthKey" id="hfEvoAuthKey" />
698        <input type="hidden" name="hfEvoCode" id="hfEvoCode" />
699        <input type="hidden" name="hfRoundedPaymentAmount" id="hfRoundedPaymentAmount" />
700        <input type="hidden" name="hfExistingYum" id="hfExistingYum" value="False" />
701        <input type="hidden" name="hfYumBalance" id="hfYumBalance" />
702        <input type="hidden" name="hfYumLoadOnly" id="hfYumLoadOnly" value="False" />
703        <input type="hidden" name="hfYumDiscountOnLoad" id="hfYumDiscountOnLoad" />
704        <input type="hidden" name="hfAddBalanceAmount" id="hfAddBalanceAmount" value="
7040" />
705        <input type="hidden" name="hfPin" id="hfPin" />
706         <input type="hidden" name="hfSquareResponse" id="hfSquareResponse" />
707        <input type="hidden" name="hfIsEvent" id="hfIsEvent" value="False" />
708        <input type="hidden" name="hfEventDate" id="hfEventDate" />
709        <input type="hidden" name="hfEventTime" id="hfEventTime" />
710        <input type="hidden" name="hfEventArray" id="hfEventArray" />
711        <input type="hidden" name="hfExtras" id="hfExtras" />
712        <input type="hidden" name="hfItemList" id="hfItemList" value="[]" />
713        <input type="hidden" name="hfTipOnly" id="hfTipOnly" value="False" />
714        <input type="hidden" name="hfState" id="hfState" />
715        <input type="hidden" name="hfOnlineFundraising" id="hfOnlineFundraising" />
716        <input type="hidden" name="hfPieCrusts" id="hfPieCrusts" value="[]" />
717        <input type="hidden" name="hfPickupOnly" id="hfPickupOnly" value="Yes" />
718        <input type="hidden" name="hfDeliveryDate" id="hfDeliveryDate" />
719        <input type="hidden" name="hfDeliveryInstructions" id="hfDeliveryInstructions" />
720        <input type="hidden" name="hfOrphanCakes" id="hfOrphanCakes" value="False" />
721        <input type="hidden" name="hfGifts" id="hfGifts" value="False" />
722        <input type="hidden" name="hfSundaes" id="hfSundaes" value="False" />
723        <input type="hidden" name="hfShakes" id="hfShakes" value="False" />
724        <input type="hidden" name="hfKits" id="hfKits" value="False" />
725        <input type="hidden" name="hfTakeHome" id="hfTakeHome" value="False" />
726        <input type="hidden" name="hfNathans" id="hfNathans" value="False" />
727        <input type="hidden" name="hfCustomCakes" id="hfCustomCakes" value="False" />
728        <input type="hidden" name="hfCurbside" id="hfCurbside" value="False" />
729        <input type="hidden" name="hfCurbsideSelected" id="hfCurbsideSelected" value="False" />
730        <input type="hidden" name="hfVehicleDescription" id="hfVehicleDescription" />
731        <input type="hidden" name="hfFlavorImages" id="hfFlavorImages" />
732        <input type="hidden" name="hfEGiftLive" id="hfEGiftLive" value="false" />
733        <input type="hidden" name="hfEGiftStoreLocation" id="hfEGiftStoreLocation" />
734        <input type="hidden" name="hfEGiftStoreApplicationId" id="hfEGiftStoreApplicationId" />
735        <input type="hidden" name="hfCustomerId" id="hfCustomerId" />
736        <input type="hidden" name="hfEGiftOrderId" id="hfEGiftOrderId" value="False" />
737        <input type="hidden" name="hfActivePromo" id="hfActivePromo" />
738         <input type="hidden" name="hfPromoProducts" id="hfPromoProducts" value="[]" />
739         <input type="hidden" name="hfTimeZoneOffset" id="hfTimeZoneOffset" />
740<div style="display:none !important" class="loading">Loading&#8230;</div>
741
742         
743
744         <div id="pnlLive">
745	
746
747    <div style="display:none" class="squarepaymentform">
748    <div id="form-container">
749        <div class="container">
750             <div class="landing-header-custom">
751            <h1>Online Ordering</h1>
752        </div>
753            <!-- Credit Card Payment Form - START -->
754            <div class="row">
755                <div class="col-12 col-lg-8">
756                    <div class="card">
757                        <div class="card-header">
758                            <div class="row">
759                                <div class="col">
760                                    <img class="img-fluid" src="https://brustersonline.com/brustersCom/images/paywithsquare.png" alt="Pay with Square">
761                                </div>
762                            </div>
763                        </div>
764                        <div class="card-body">
765                            <div class="row">
766                                <div id="paymentmessage" class="col-12"></div>
767                            </div>
768                            <div class="row" id="sqpaymentcontainer"></div>
769                            <div class="row" id="sqgcpaymentcontainer"></div>
770                            <div id="payment-status-container"></div>
771                        </div>
772                        <div class="card-footer">
773                            <div class="row">
774                                <div class="col-12">
775                                    <span class="storedisclaimer"></span>
776                                 <div style="display:flex;flex-direction:column;justify-content:space-between" class="paymentcontainer">
777                                            <div class="creditcardpaymentbutton"><button type="button" id="sq-creditcard" class="button-credit-card paymentform">Pay Now</button></div>
778                                            <div class="creditcardpayment"> <div id="sq-google-pay" class="button-google-pay2 paymentform"></div></div>
779                                            <div class="applepaycontainer creditcardpayment"> <button 
780                                            type="button" 
781                                            class="apple-pay-button2 apple-pay-button-black paymentform" 
782                                            id="sq-apple-pay"
783                                            aria-label="Pay with Apple Pay">
784                                        </button></div>
785                                   <!-- ✅ Disclaimer -->
786                                    <div class="mt-3 text-center">
787                                        <small class="gift-card-warning fw-semibold">
788                                            Gift Cards are not able to be redeemed for online ordering.
789                                        </small>
790                                    </div>  
791                                 </div>
792                                    <input type="hidden" id="cardNonce" name="nonce" />
793                                    <div class="text-danger" id="errors"></div>
794                                    <div class="text-primary" id="success"></div>
795                                    <div id="hidebutton" style="display:none">
796                                        <input type="button" name="btnTest" value="Button" onclick="javascript:__doPostBack(&#39;btnTest&#39;,&#39;&#39;)" id="btnTest" class="testme" />
797                                    </div>
798                                    <input type="hidden" name="hfNonce" id="hfNonce" />
799                                </div>
800                            </div>
801                        </div>
802                    </div>
803                </div>
804                <div class="col-12 col-lg-4">
805                    <div class="card">
806                        <div class="card-header">
807                            <div class="row">
808                                <div class="col-12">
809                                    <h3>ORDER DETAILS</h3>
810                                </div>
811                            </div>
812                        </div>
813                        <div class="card-body">
814                            <div class="row">
815                                <div id="customerInfo" class="col-12"></div>
816                            </div>
817                            <div class="row">
818                                
819                                <div id="orderDetailsCheckout" class="col-12"></div>
820                            </div>
821                        </div>
822                        <div class="card-footer">
823                            <div class="row"></div>
824                        </div>
825                    </div>
826                </div>
827            </div>
828            <!-- Credit Card Payment Form - END -->
829        </div>
830    </div>
831</div>
832
833
834<div id="divstoresclone" style="display:none" class="list-group">
835    <div class="list-group-item d-flex flex-column flex-md-row">
836        <div class="d-flex flex-shrink-0">
837            <img class="img-fluid img-thumbnail" alt="Map showing the location of [STORE NAME]" src="[MAPADDRESS]" style="max-width: 150px;">
838        </div>
839        <div class="flex-grow-1 ms-3 position-relative">
840            <h2 class="mb-1" style="font-weight:bold;font-size:1.5em">[STORE NAME]</h2>
841            <p class="mb-1" style="font-weight:bold;font-size:1.0em">[STORE ADDRESS]</p>
842            <p class="mb-1" style="font-weight:bold;font-size:1.2em">[STORE PHONE]</p>
843            <p class="mb-1" style="font-weight:bold;font-size:1.0em">[MILES AWAY]</p>
844            <!-- Button for larger screens -->
845            <a href="[ONLINEURL]" class="btn btn-primary position-absolute top-0 end-0 mt-2 me-2 d-none d-md-block">Order</a>
846            <!-- Button for smaller screens -->
847            <a href="[ONLINEURL]" class="btn btn-primary mt-2 d-block d-md-none">Order</a>
848        </div>
849    </div>
850</div>
851
852
853<div id="landingPage" class="landing-page">
854    <div class="bg-image" id="bg-image"></div>
855    <div class="landing-header-custom">
856        <h1>Online Ordering</h1>
857    </div>
858    <div class="landing-content">
859        <a class="header-logo-link" href="/BrustersCom/CartV2.aspx"
860   aria-label="Restart online ordering">
861    <img src="https://bic.blob.core.windows.net/departments/marketing/Graphics/Logos/brusterslogo-twocolor.png"
862         alt="Bruster's Logo"
863         class="header-logo" />
864</a>
865        <div class="search-section">
866            <h2>Find My Bruster's</h2>
867            <label for="zipcode">Zip Code</label>
868
869            <input type="text"
870                   style="text-align:center"
871                   id="zipcode"
872                   class="form-control"
873                   placeholder="Zip Code">
874            <button id="searchButton"
875                    type="button"
876                    class="btn btn-secondary">
877                Search
878            </button>
879            <div class="or-separator">OR</div>
880            <button id="useMyLocation" type="button" class="btn btn-primary">Use My Location</button>
881        </div>
882    </div>
883</div>
884
885<div id="storelist" class="storelist-page container" style="display:none">
886    <div class="landing-header-custom">
887        <h1>Order Online</h1>
888    </div>
889    <div id="divstores" class="list-group"></div>
890</div>
891
892 <main id="mainContent" class="main-content">
893        <h1 class="visually-hidden">Bruster's Online Ordering Menu</h1>
894        <div class="container mt-1">
895            <div class="header-custom mb-2 rounded">
896                <a class="header-logo-link" href="/BrustersCom/CartV2.aspx"
897   aria-label="Restart online ordering">
898    <img src="https://bic.blob.core.windows.net/departments/marketing/Graphics/Logos/brusterslogo-twocolor.png"
899         alt="Bruster's Logo"
900         class="header-logo" />
901</a>
902                <button type="button"
903                    id="cartIcon"
904                    class="cart-icon"
905                    aria-label="View shopping cart">
906                <i class="fas fa-shopping-cart fa-2x" aria-hidden="true"></i>
907                <span id="cartItemCount"
908                      class="badge rounded-pill badge-custom"
909                      aria-hidden="true">0</span>
910            </button>
911            </div>
912            <div id="addressDisplay" class="address-display mt-1"></div>
913         
914
915    <div class="mt-1 mb-3">
916    <h2 class="text-center">Featured Products</h2>
917    <div class="d-flex flex-nowrap overflow-auto">
918        
919    </div>
920</div>
921
922
923
924            <div id="section-links" class="section-links text-center"></div>
925            <div id="menu-container" class="row row-cols-1 row-cols-md-3 g-4"></div>
926        </div>
927
928         <input type="hidden" name="hiddenFieldMenuData" id="hiddenFieldMenuData" />
929        <input type="hidden" name="hiddenFieldAddress" id="hiddenFieldAddress" />
930        <input type="hidden" name="hfStoreLocation" id="hfStoreLocation" />
931        <input type="hidden" name="hfStoreLevelPromotion" id="hfStoreLevelPromotion" />
932        <input type="hidden" name="hiddenFieldLeadTime" id="hiddenFieldLeadTime" />
933        <input type="hidden" name="hfAllowHighRiskPayments" id="hfAllowHighRiskPayments" />
934        <input type="hidden" name="hfOnlineCorpPromo" id="hfOnlineCorpPromo" />
935        <input type="hidden" name="hfCorporatePromo" id="hfCorporatePromo" />
936        <input type="hidden" name="hfStoreClosed" id="hfStoreClosed" />
937        <input type="hidden" name="hfClosedMessage" id="hfClosedMessage" />
938        <input type="hidden" name="hfDisabledTimeIntervals" id="hfDisabledTimeIntervals" />
939        <input type="hidden" name="hfDaysDisabled" id="hfDaysDisabled" />
940        <input type="hidden" name="hfMaxDateTime" id="hfMaxDateTime" />
941        <input type="hidden" name="hfNextOpenDateTime" id="hfNextOpenDateTime" />
942        <input type="hidden" name="hfDatesDisabled" id="hfDatesDisabled" />
943        <input type="hidden" name="hfCurrentStoreTime" id="hfCurrentStoreTime" />
944        <input type="hidden" name="hfIsClosed" id="hfIsClosed" />
945        <input type="hidden" name="hfOpenTimeString" id="hfOpenTimeString" />
946        <input type="hidden" name="hfOpenHour" id="hfOpenHour" />
947        <input type="hidden" name="hfClosedHour" id="hfClosedHour" />
948        <input type="hidden" name="hfEnabledHours" id="hfEnabledHours" />
949        <input type="hidden" name="hfDisabledHours" id="hfDisabledHours" />
950        <input type="hidden" name="hfJsonOrder" id="hfJsonOrder" value="[]" />
951         <input type="hidden" name="hfSquareId" id="hfSquareId" />
952         <input type="hidden" name="hfSquareLocationId" id="hfSquareLocationId" />
953         <input type="hidden" name="hfFinalPaymentAmount" id="hfFinalPaymentAmount" />
954         <input type="hidden" name="hfApplePay" id="hfApplePay" />
955           <input type="hidden" name="hfSquareAccessToken" id="hfSquareAccessToken" />
956         <input type="hidden" name="hfMandatoryItems" id="hfMandatoryItems" value="[]" />
957         <input type="hidden" name="hfDisclaimer" id="hfDisclaimer" />
958         <input type="hidden" name="hfOrderResponse" id="hfOrderResponse" />
959         <input type="hidden" name="hfCustomerName" id="hfCustomerName" />
960         <input type="hidden" name="hfOrderId" id="hfOrderId" />
961         <input type="hidden" name="hfPaymentAmount" id="hfPaymentAmount" />
962         <input type="hidden" name="hfSquareFees" id="hfSquareFees" />
963         <input type="hidden" name="hfTotalDiscountAmount" id="hfTotalDiscountAmount" value="
9630" />
964         <input type="hidden" name="hfDiscountType" id="hfDiscountType" />
965         <input type="hidden" name="hfBackgroundImage" id="hfBackgroundImage" value="https://brustersazure.blob.core.windows.net/onlineproductimages/OLO_mainpage-backgroundv2.jpg" />
966    </main>
967             <footer>
968  <div class="container">
969   <div class="card border-0 mondelezfooter">
970    <div class="card-footer small text-center">
971        OREO, NILLA and NUTTER BUTTER are trademarks of Mondelēz International group, used with permission.
972    </div>
973</div>
974
975</div>
976             </footer>
977             <div class="container my-4">
978    <div class="card border-danger allergenfooter">
979
980        <!-- Header -->
981        <div class="card-header text-center fw-bold text-uppercase text-white bg-danger">
982            Allergen Statement
983        </div>
984
985        <!-- Body -->
986        <div class="card-body text-center">
987            <p class="mb-3">
988                Bruster’s products, except non-dairy sorbets and ices, contain
989                <strong class="text-danger">MILK</strong> products.
990                Some products also contain
991                <strong class="text-danger">
992                    EGGS, WHEAT, TREE NUTS, PEANUTS, SOY AND SESAME
993                </strong>.
994            </p>
995
996            <p class="mb-3">
997                Many of our products are produced or distributed on shared equipment,
998                creating a possibility that
999                <strong class="text-danger text-uppercase">
1000                    any flavor may contain allergens
1001                </strong>.
1002            </p>
1003
1004            <p class="mb-0">
1005                Full nutritional and ingredient information for each flavor
1006                is available at
1007                <a href="https://www.brusters.com" target="_blank" rel="noopener">
1008                    Brusters.com
1009                </a>.
1010            </p>
1011        </div>
1012
1013    </div>
1014</div>
1015
1016             
1017</div>
1018
1019         <div class="modal fade" id="promoModal" tabindex="-1" aria-labelledby="promoModalLabel" aria-hidden="true">
1020          <div class="modal-dialog modal-dialog-centered">
1021            <div class="modal-content">
1022              <div class="modal-header">
1023                <h5 class="modal-title" id="promoModalLabel">🎉 Special Promotion!</h5>
1024                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1025              </div>
1026              <div class="modal-body">
1027                
1028              </div>
1029            </div>
1030          </div>
1031        </div>
1032
1033         <!-- Modal Custom Image -->
1034<div class="modal fade" id="modifierImageModal" tabindex="-1">
1035  <div class="modal-dialog modal-dialog-centered modal-lg">
1036    <div class="modal-content">
1037    <div class="modal-header">
1038        <img class="img-fluid img-headerimage" style="float:right" src="https://brustersonline.com/Images/brusterslogo_headerimage.png" alt="Brusters Logo" />
1039        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1040    </div>
1041      <div class="modal-body text-center">
1042        <img id="modifierFullImage" src="" alt="modifier image" style="width:100%; height:auto; object-fit:contain;" />
1043      </div>
1044    </div>
1045  </div>
1046</div>
1047
1048
1049         <!-- Modal Pie -->
1050<div class="modal fade"
1051     id="modalPie1"
1052     tabindex="-1"
1053     aria-labelledby="modalPie1Label"
1054     aria-describedby="modalPie1Description"
1055     aria-hidden="true">
1056
1057    <div class="modal-dialog">
1058        <div class="modal-content">
1059
1060            <div class="modal-header">
1061                <h2 id="modalPie1Label" class="modal-title visually-hidden">
1062                    Customize Your Ice Cream Pie
1063                </h2>
1064
1065                <img
1066                    class="img-fluid img-headerimage"
1067                    style="float: right;"
1068                    src="https://brustersonline.com/Images/brusterslogo_headerimage.png"
1069                    alt="Bruster's Real Ice Cream">
1070
1071                <button
1072                    type="button"
1073                    class="btn-close"
1074                    data-bs-dismiss="modal"
1075                    aria-label="Close customize your ice cream pie dialog">
1076                </button>
1077            </div>
1078
1079            <div class="modal-body modal-greeting">
1080
1081                <p id="modalPie1Description" class="visually-hidden">
1082                    Select the flavor, crust, filling, writing color, and optional special message for your ice cream pie.
1083                </p>
1084
1085                <div id="pieheader">
1086                    <img
1087                        src="https://brusters.azurewebsites.net/brusterscom/cakeanatomy.jpg"
1088                        class="img-fluid pieimage menu-img mb-3 rounded"
1089                        alt="Diagram showing the parts of a customizable ice cream pie">
1090                </div>
1091
1092                <div id="pieselect">
1093                    <div class="form-group">
1094
1095                        <label for="pieicecreamselect" class="visually-hidden">
1096                            Ice cream flavor
1097                        </label>
1098                        <select
1099                            class="form-control"
1100                            id="pieicecreamselect"
1101                            name="pieicecreamselect">
1102                            <option value="" selected disabled>
1103                                Select Flavor
1104                            </option>
1105                        </select>
1106
1107                        <br>
1108
1109                        <label for="piecrustselect" class="visually-hidden">
1110                            Pie crust
1111                        </label>
1112                        <select
1113                            class="form-control"
1114                            id="piecrustselect"
1115                            name="piecrustselect">
1116                            <option value="" selected disabled>
1117                                Select Crust
1118                            </option>
1119                        </select>
1120
1121                        <br>
1122
1123                        <label for="piefillingselect" class="visually-hidden">
1124                            Pie filling
1125                        </label>
1126                        <select
1127                            class="form-control"
1128                            id="piefillingselect"
1129                            name="piefillingselect">
1130                            <option value="" selected disabled>
1131                                Select Filling
1132                            </option>
1133                        </select>
1134
1135                        <br>
1136
1137                        <label for="piecolorselect" class="visually-hidden">
1138                            Color of writing
1139                        </label>
1140                        <select
1141                            class="form-control prattville"
1142                            id="piecolorselect"
1143                            name="piecolorselect">
1144                            <option value="" selected disabled>
1145                                Select Color of Writing
1146                            </option>
1147                        </select>
1148
1149                        <br>
1150
1151                        <label for="piemessage" class="visually-hidden">
1152                            Special message
1153                        </label>
1154                        <textarea
1155                            class="form-control restrictemojis"
1156                            rows="5"
1157                            maxlength="30"
1158                            placeholder="Special Message"
1159                            id="piemessage"
1160                            name="piemessage"
1161                            aria-describedby="piemessageHelp"></textarea>
1162
1163                        <div id="piemessageHelp" class="visually-hidden">
1164                            Enter an optional special message of no more than 30 characters.
1165                        </div>
1166
1167                    </div>
1168                </div>
1169            </div>
1170
1171            <div class="modal-footer">
1172
1173                <div
1174                    id="modalpiefootertext"
1175                    role="status"
1176                    aria-live="polite">
1177                </div>
1178
1179                <button
1180                    type="button"
1181                    class="btn btn-danger"
1182                    data-bs-dismiss="modal">
1183                    Close
1184                </button>
1185
1186                <button
1187                    type="button"
1188                    class="btn btn-primary btn-pie-step1">
1189                    Continue
1190                </button>
1191
1192            </div>
1193        </div>
1194    </div>
1195</div>
1196
1197
1198         <!--Cake Modal -->
1199<div class="modal fade"
1200     id="modalCake1"
1201     tabindex="-1"
1202     aria-labelledby="modalCake1Label"
1203     aria-describedby="modalCake1Description"
1204     aria-hidden="true">
1205
1206    <div class="modal-dialog">
1207        <div class="modal-content">
1208
1209            <div class="modal-header">
1210                <h2 id="modalCake1Label" class="modal-title visually-hidden">
1211                    Customize Your Ice Cream Cake
1212                </h2>
1213
1214                <img class="img-fluid img-headerimage"
1215                     style="float:right"
1216                     src="https://brustersonline.com/Images/brusterslogo_headerimage.png"
1217                     alt="Bruster's Real Ice Cream">
1218
1219                <button type="button"
1220                        class="btn-close"
1221                        data-bs-dismiss="modal"
1222                        aria-label="Close customize your ice cream cake dialog">
1223                </button>
1224            </div>
1225
1226            <div class="modal-body modal-greeting">
1227
1228                <p id="modalCake1Description" class="visually-hidden">
1229                    Select the flavor, cake, filling, writing color, and optional special message for your ice cream cake.
1230                </p>
1231
1232                <div id="cakeheader">
1233                    <img src="https://brusters.azurewebsites.net/brusterscom/cakeanatomy.jpg"
1234                         class="img-fluid cakeimage menu-img mb-3 rounded"
1235                         alt="Diagram showing the parts of a customizable ice cream cake">
1236                </div>
1237
1238                <div id="cakeselect">
1239                    <div class="form-group">
1240
1241                        <label for="cakeicecreamselect" class="visually-hidden">
1242                            Ice cream flavor
1243                        </label>
1244                        <select class="form-control"
1245                                id="cakeicecreamselect"
1246                                name="cakeicecreamselect">
1247                            <option value="" selected disabled>
1248                                Select Flavor
1249                            </option>
1250                        </select>
1251
1252                        <br />
1253
1254                        <label for="cakecakeselect" class="visually-hidden">
1255                            Cake flavor
1256                        </label>
1257                        <select class="form-control"
1258                                id="cakecakeselect"
1259                                name="cakecakeselect">
1260                            <option value="" selected disabled>
1261                                Select Cake
1262                            </option>
1263                        </select>
1264
1265                        <br />
1266
1267                        <label for="cakefillingselect" class="visually-hidden">
1268                            Filling
1269                        </label>
1270                        <select class="form-control"
1271                                id="cakefillingselect"
1272                                name="cakefillingselect">
1273                            <option value="" selected disabled>
1274                                Select Filling
1275                            </option>
1276                        </select>
1277
1278                        <br />
1279
1280                        <label for="cakecolorselect" class="visually-hidden">
1281                            Color of writing
1282                        </label>
1283                        <select class="form-control prattville"
1284                                id="cakecolorselect"
1285                                name="cakecolorselect">
1286                            <option value="" selected disabled>
1287                                Select Color of Writing
1288                            </option>
1289                        </select>
1290
1291                        <br />
1292
1293                        <label for="cakemessage" class="visually-hidden">
1294                            Special message
1295                        </label>
1296                        <textarea class="form-control restrictemojis"
1297                                  rows="5"
1298                                  maxlength="35"
1299                                  placeholder="Special Message"
1300                                  id="cakemessage"
1301                                  name="cakemessage"
1302                                  aria-describedby="cakemessageHelp"></textarea>
1303
1304                        <div id="cakemessageHelp" class="visually-hidden">
1305                            Enter an optional special message of no more than 35 characters.
1306                        </div>
1307
1308                    </div>
1309                </div>
1310
1311            </div>
1312
1313            <div class="modal-footer">
1314
1315                <div id="modalcakefootertext"
1316                     role="status"
1317                     aria-live="polite">
1318                </div>
1319
1320                <button type="button"
1321                        class="btn btn-danger"
1322                        data-bs-dismiss="modal">
1323                    Close
1324                </button>
1325
1326                <button type="button"
1327                        class="btn btn-primary btn-cake-step1">
1328                    Continue
1329                </button>
1330
1331            </div>
1332
1333        </div>
1334    </div>
1335</div>
1336
1337
1338    <!-- Item Modal -->
1339    <div class="modal fade" id="itemModal" tabindex="-1" aria-labelledby="itemModalLabel" aria-hidden="true">
1340        <div class="modal-dialog modal-lg">
1341            <div class="modal-content">
1342                <div class="modal-header">
1343                    <h5 class="modal-title" id="itemModalLabel">Item Details</h5>
1344                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1345                </div>
1346                <div class="modal-body">
1347                    <!-- Top Buttons Section in Modal -->
1348                <!-- Top Buttons Section in Modal -->
1349                <div id="top-buttons" class="d-flex mt-3">
1350                    <button type="button" class="btn btn-danger me-2" id="backButtonTop" style="display: none;">Back</button>
1351                    <button type="button" class="btn btn-primary me-2" id="nextModifierGroupButtonTop">Continue</button>
1352                    <button type="button" class="btn btn-primary" id="addToCartButtonTop" style="display: none;">Add To Cart</button>
1353                </div>
1354
1355                    <!-- Content will be injected by JavaScript -->
1356                    <div id="modal-content"></div>
1357                </div>
1358                <div class="modal-footer">
1359                <button type="button" class="btn btn-danger" id="backButton" style="display: none;">Back</button>
1360                <button type="button" class="btn btn-primary" id="nextModifierGroupButton">Continue</button>
1361                <button type="button" class="btn btn-primary" id="addToCartButton" style="display: none;">Add To Cart</button>
1362            </div>
1363            </div>
1364        </div>
1365    </div>
1366
1367    <!-- Shopping Cart Modal -->
1368    <div class="modal fade" id="cartModal" tabindex="-1" aria-labelledby="cartModalLabel" aria-hidden="true">
1369        <div class="modal-dialog">
1370            <div class="modal-content">
1371                <div class="modal-header">
1372                    <h5 class="modal-title" id="cartModalLabel">Your Order</h5>
1373                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1374                </div>
1375                <div class="modal-body" id="cartModalBody">
1376                    <p>Your cart is empty.</p>
1377                </div>
1378                <div class="cart-subtotal" id="cartSubtotal">
1379                    Subtotal: $0.00
1380                </div>
1381                <div class="cart-tax" id="cartTax">
1382                    Tax: $0.00
1383                </div>
1384                <div class="cart-total" id="cartTotal">
1385                    Total: $0.00
1386                </div>
1387                <div class="modal-footer">
1388                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
1389                    <button type="button" class="btn btn-primary" id="checkoutButton">Checkout</button>
1390                </div>
1391            </div>
1392        </div>
1393    </div>
1394
1395                <!--Promo Modal -->
1396<div class="modal fade"
1397     id="modalPromo"
1398     tabindex="-1"
1399     aria-labelledby="modalPromoLabel"
1400     aria-hidden="true">
1401
1402    <div class="modal-dialog modal-dialog-centered">
1403        <div class="modal-content">
1404
1405            <div class="modal-header">
1406                <h2 id="modalPromoLabel" class="modal-title visually-hidden">
1407                    Promotional Offer
1408                </h2>
1409
1410                <button type="button"
1411                        class="btn-close"
1412                        data-bs-dismiss="modal"
1413                        aria-label="Close promotional offer">
1414                </button>
1415            </div>
1416
1417            <div class="modal-body text-center">
1418                <img class="img-fluid"
1419                     src=""
1420                     alt="Current promotional offer">
1421            </div>
1422
1423        </div>
1424    </div>
1425</div>
1426
1427
1428         <!-- Rewards Modal -->
1429<div class="modal fade"
1430     id="modalRewards"
1431     tabindex="-1"
1432     aria-labelledby="modalRewardsLabel"
1433     aria-describedby="modalRewardsDescription"
1434     aria-hidden="true">
1435
1436    <div class="modal-dialog modal-lg modal-dialog-centered">
1437        <div class="modal-content">
1438
1439            <div class="modal-header">
1440
1441                <h2 id="modalRewardsLabel" class="modal-title visually-hidden">
1442                    Loyalty Rewards
1443                </h2>
1444
1445                <img class="img-responsive img-headerimage"
1446                     style="float:right"
1447                     src="https://brustersonline.com/Images/brusterslogo_headerimage.png"
1448                     alt="Bruster's Real Ice Cream">
1449
1450                <button type="button"
1451                        class="btn-close"
1452                        data-bs-dismiss="modal"
1453                        aria-label="Close loyalty rewards dialog">
1454                </button>
1455
1456            </div>
1457
1458            <div class="modal-body modal-greeting">
1459
1460                <div id="modalRewardsDescription">
1461                    <h3>You have a reward available. Please select one.</h3>
1462
1463                    <div id="rewardoptions" class="list-group">
1464                        <a class="list-group-item list-group-item-danger rewardoptions nothanks"
1465                           data-wallet="0"
1466                           data-type="No Thanks"
1467                           href="#">
1468                            No Thanks - I'll Use Later
1469                        </a>
1470                    </div>
1471
1472                    <div id="rewarddisclaimer">
1473                        <p>
1474                            *Only one discount may be applied per transaction.
1475                            If you have entered a discount code and choose to use
1476                            your loyalty reward, the loyalty reward will be applied
1477                            instead of your discount code.
1478                        </p>
1479                    </div>
1480                </div>
1481
1482            </div>
1483
1484            <div class="modal-footer">
1485                <!-- Optional footer content -->
1486            </div>
1487
1488        </div>
1489    </div>
1490</div>
1491
1492
1493
1494<!-- Checkout Modal -->
1495<div class="modal fade" id="checkoutModal" tabindex="-1" aria-labelledby="checkoutModalLabel" aria-hidden="true">
1496    <div class="modal-dialog">
1497        <div class="modal-content">
1498            <div class="modal-header">
1499                <h2 class="modal-title" id="checkoutModalLabel">Checkout</h2>
1500                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1501            </div>
1502            <div id="checkoutForm" class="modal-body">
1503                <!-- Order Details Section -->
1504                <div id="orderDetails" class="small-font mb-3">
1505                    <!-- Order details will be injected here by JavaScript -->
1506                </div>
1507                <!-- Total Amount Section -->
1508                <div id="totalAmount" class="small-font mb-3 font-weight-bold">
1509                    <!-- Total amount will be injected here by JavaScript -->
1510                </div>
1511                <!-- Existing form elements -->
1512                <input type="hidden" id="cartTotalAmount" value="
15120">
1513                <input type="hidden" id="cartSubTotalAmount" value="0">
1514                <div class="mb-3">
1515                    <label for="name" class="form-label">Name</label>
1516                    <input type="text" class="form-control" id="name">
1517                </div>
1518                <div class="mb-3">
1519                    <label for="cellPhone" class="form-label">Cell Phone <small>(*loyalty number)</small></label>
1520                    <input 
1521                      type="tel" 
1522                      maxlength="10" 
1523                      placeholder="10 digit cell phone" 
1524                      class="form-control" 
1525                      id="cellPhone" 
1526                      autocomplete="tel" 
1527                      inputmode="numeric" />
1528                    <div style="color:red" id="error-message" class="animate__animated"></div>
1529                </div>
1530                <div class="mb-3">
1531                    <h6 class="form-label">Pickup Time</h6>
1532                   <fieldset>
1533                    <legend class="visually-hidden">Pickup Time</legend>
1534
1535                    <div class="form-check">
1536                        <input class="form-check-input" type="radio" name="pickupTimeOption" id="pickupAsap" value="ASAP" checked>
1537                        <label class="form-check-label radio-inline" for="pickupAsap">ASAP</label>
1538                    </div>
1539
1540                    <div class="form-check">
1541                        <input class="form-check-input" type="radio" name="pickupTimeOption" id="pickupDateTime" value="SelectDateTime">
1542                        <label class="form-check-label radio-inline" for="pickupDateTime">Select Date/Time</label>
1543                    </div>
1544
1545                </fieldset>
1546                   <label for="pickupDateTimeInput" class="visually-hidden">
1547                    Pickup Date and Time
1548                 </label>
1549
1550                <div class="input-group d-none mt-2" id="pickupDateTimePicker">
1551                    <input 
1552                        id="pickupDateTimeInput" 
1553                        type="text" 
1554                        class="form-control" 
1555                        data-td-target="#pickupDateTimePicker"
1556                    />
1557
1558                    <span 
1559                        class="input-group-text" 
1560                        data-td-target="#pickupDateTimePicker" 
1561                        data-td-toggle="datetimepicker">
1562                        <i class="fa fa-calendar"></i>
1563                    </span>
1564                </div>
1565                </div>
1566                <div class="mb-3">
1567                    <label for="discountCode" class="form-label">Discount Code <small>(Optional)</small></label>
1568                    <input type="text" class="form-control" id="discountCode">
1569                </div>
1570                <div class="mb-3">
1571                    <label for="additionalInstructions" class="form-label">Additional Instructions</label>
1572                    <textarea class="form-control" id="additionalInstructions" rows="3"></textarea>
1573                </div>
1574                <div class="mb-3">
1575                    <h6 class="form-label">Scooper Tip <small>(Optional)</small></h6>
1576                  <fieldset>
1577                    <legend class="visually-hidden">Select a scooper tip amount</legend>
1578
1579                    <div class="tip-group">
1580                        <div class="form-check form-check-inline">
1581                            <input class="form-check-input" type="radio" name="scooperTip" id="tip10" value="15%">
1582                            <label class="form-check-label" for="tip10">15%</label>
1583                        </div>
1584
1585                        <div class="form-check form-check-inline">
1586                            <input class="form-check-input" type="radio" name="scooperTip" id="tip15" value="20%">
1587                            <label class="form-check-label" for="tip15">20%</label>
1588                        </div>
1589
1590                        <div class="form-check form-check-inline">
1591                            <input class="form-check-input" type="radio" name="scooperTip" id="tip18" value="25%">
1592                            <label class="form-check-label" for="tip18">25%</label>
1593                        </div>
1594
1595                        <div class="form-check form-check-inline">
1596                            <input class="form-check-input" type="radio" name="scooperTip" id="tipOther" value="Other">
1597                            <label class="form-check-label" for="tipOther">Other</label>
1598                        </div>
1599
1600                        <label for="tipOtherAmount" class="visually-hidden">
1601                            Tip amount
1602                        </label>
1603
1604                        <input 
1605                            type="text" 
1606                            class="form-control d-none" 
1607                            id="tipOtherAmount" 
1608                            placeholder="Enter amount" />
1609                    </div>
1610                </fieldset>
1611                </div>
1612             <div class="form-check mb-3">
1613                <input class="form-check-input"
1614                       type="checkbox"
1615                       id="promotionalTextMessages"
1616                       checked>
1617
1618                <label class="form-check-label small text-muted" for="promotionalTextMessages">
1619                    By checking this box, you consent to receive recurring automated marketing and informational text messages from Bruster's Real Ice Cream at the mobile number provided. Consent is not a condition of purchase. Message frequency varies. Message and data rates may apply. Reply STOP to cancel or HELP for help. View our
1620                    <a href="https://brusters.com/privacy-policy/"
1621                       target="_blank"
1622                       rel="noopener noreferrer">Privacy Policy</a>.
1623                    For support, call 724-774-4250.
1624                </label>
1625            </div>
1626            </div>
1627            <div class="modal-footer">
1628                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
1629                <button type="button" class="btn btn-primary" id="submitCheckoutButton">Submit</button>
1630                <div style="color:white" id="error-message2" class="animate__animated"></div>
1631            </div>
1632        </div>
1633    </div>
1634</div>
1635
1636
1637
1638    <!-- Confirmation Modal -->
1639<div class="modal fade" id="confirmationModal" tabindex="-1" aria-labelledby="confirmationModalLabel" aria-hidden="true">
1640    <div class="modal-dialog">
1641        <div class="modal-content">
1642            <div class="modal-header">
1643                <h5 class="modal-title" id="confirmationModalLabel">Item added to cart</h5>
1644                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1645            </div>
1646            <div class="modal-body">
1647                <p>The item has been added to your cart.</p>
1648            </div>
1649            <div class="modal-footer">
1650                <button type="button" class="btn btn-secondary" id="continueShoppingButton">Continue Shopping</button>
1651                <button type="button" class="btn btn-primary" id="checkoutButtonConfirmation">Checkout</button>
1652            </div>
1653        </div>
1654    </div>
1655</div>
1656
1657
1658    <div id="popper-container"></div>
1659
1660        
1660<script type="text/javascript">
1661    
1662        function updateCheckoutErrors() {
1663            var errorMessage = '';
1664
1665            if (!$('#name').val().trim().length) {
1666                errorMessage += 'Name is required.<br/>';
1667            }
1668
1669            var cellPhone = $('#cellPhone').val().trim();
1670
1671            if (!cellPhone.length) {
1672                errorMessage += 'Cell phone is required.<br/>';
1673            }
1674            else if (!/^\d{10}$/.test(cellPhone)) {
1675                errorMessage += 'Please enter a valid 10-digit cell phone number.<br/>';
1676            }
1677
1678            if (errorMessage) {
1679                $('#error-message2')
1680                    .html(errorMessage)
1681                    .show();
1682            }
1683            else {
1684                $('#error-message2')
1685                    .html('')
1686                    .hide();
1687            }
1688        }
1689
1690        $(document).on('input', '#name', function () {
1691            if ($(this).val().trim().length) {
1692                $(this).css('border', '');
1693                updateCheckoutErrors();
1694            }
1695        });
1696
1697        $(document).on('input', '#cellPhone', function () {
1698            var cellPhone = $(this).val().trim();
1699
1700            if (/^\d{10}$/.test(cellPhone)) {
1701                $(this).css('border', '');
1702                updateCheckoutErrors();
1703            }
1704        });
1705
1706
1707            function markPromotionalProducts() {
1708
1709    var promoJson = document.getElementById("hfPromoProducts")?.value;
1710
1711    if (!promoJson) return;
1712
1713    var promoItems;
1714
1715    try {
1716
1717        promoItems = JSON.parse(promoJson);
1718
1719    } catch (e) {
1720
1721        console.error("Invalid hfPromoProducts JSON", e);
1722
1723        return;
1724    }
1725
1726    // Build quick lookup: ItemId → OriginalPrice
1727    var promoMap = {};
1728
1729    promoItems.flat().forEach(function (p) {
1730
1731        promoMap[String(p.ItemId)] = p.OriginalPrice;
1732
1733    });
1734
1735    document.querySelectorAll("[data-item-id]").forEach(function (el) {
1736
1737        var raw = el.getAttribute("data-item-id");
1738
1739        if (!raw) return;
1740
1741        // 412-3611089_9374 → 3611089
1742        var match = raw.match(/-(\d+)_/);
1743
1744        if (!match) return;
1745
1746        var itemId = match[1];
1747
1748        if (!(itemId in promoMap)) return;
1749
1750        var container =
1751            el.closest(".menu-item") ||
1752            el.closest(".item") ||
1753            el.closest(".product") ||
1754            el.closest("li") ||
1755            el.closest("div");
1756
1757        if (!container) return;
1758
1759        if (container.querySelector(".promo-label")) return;
1760
1761        var originalPrice = promoMap[itemId];
1762
1763        var label = document.createElement("small");
1764
1765        label.className = "promo-label";
1766
1767        label.innerHTML =
1768            `Promotional Product · <span class="promo-original">Originally $${originalPrice.toFixed(2)}</span>`;
1769
1770        container.appendChild(label);
1771
1772    });
1773
1774}
1775
1776
1777            function displayError(error) {
1778                const errorDiv = document.getElementById('errors');
1779                errorDiv.innerText = error.message || error.toString();
1780            }
1781
1782
1783            function setButtonWidths() {
1784                const googlePayButton = document.querySelector("#sq-google-pay div");
1785                const applePayButton = document.querySelector("#sq-apple-pay");
1786
1787                if (googlePayButton) {
1788                    googlePayButton.style.width = "100%";
1789                }
1790
1791                if (applePayButton) {
1792                    applePayButton.style.width = "100%";
1793                }
1794            }
1795
1796            function setBackgroundImage() {
1797                const bgImageElement = document.getElementById('bg-image');
1798                const hfBackgroundImage = document.getElementById('hfBackgroundImage').value;
1799                const viewportWidth = window.innerWidth;
1800                let imgixUrl;
1801
1802                if (viewportWidth <= 320) { // Extra small devices
1803                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=320&h=480`;
1804                } else if (viewportWidth <= 480) { // Small mobile devices
1805                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=480&h=720`;
1806                } else if (viewportWidth <= 768) { // Tablets
1807                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=768&h=1024`;
1808                } else if (viewportWidth <= 1024) { // Small desktops
1809                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=1024&h=768`;
1810                } else if (viewportWidth <= 1440) { // Medium desktops
1811                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=1440&h=900`;
1812                } else { // Large desktops
1813                    imgixUrl = `${hfBackgroundImage}?fit=clamp&w=1920&h=1080`;
1814                }
1815
1816                bgImageElement.style.backgroundImage = `url('${imgixUrl}')`;
1817            }
1818
1819
1820            // Set background image on initial load
1821            setBackgroundImage();
1822
1823            // Update background image on window resize
1824            window.addEventListener('resize', setBackgroundImage);
1825
1826    </script>
1826
1827
1828    
1828<script type="text/javascript">
1829
1830        const cartStoreNumber = new URLSearchParams(window.location.search).get('number');
1831        const cartStorageKey = `brustersCart-${cartStoreNumber}`;
1832
1833        let cart = JSON.parse(
1834            sessionStorage.getItem(cartStorageKey) || '[]'
1835        );
1836
1837        function saveCart() {
1838            sessionStorage.setItem(
1839                cartStorageKey,
1840                JSON.stringify(cart)
1841            );
1842        }
1843
1844        window.addEventListener('pageshow', function () {
1845            try {
1846                cart = JSON.parse(
1847                    sessionStorage.getItem(cartStorageKey)
1848                ) || [];
1849            } catch (error) {
1850                console.error('Unable to restore cart:', error);
1851                cart = [];
1852            }
1853
1854            renderCart();
1855        });
1856
1857        let currentItem = null;
1858        let currentModifierGroupIndex = 0;
1859        let isCake = false;
1860        let isPie = false;
1861
1862        function changeQuantity(action, id, maximum_amount) {
1863            const input = document.getElementById(`quantity-${id}`);
1864            let currentValue = parseInt(input.value);
1865    
1866            if (action === 'plus') {
1867                if (currentValue < maximum_amount) {
1868                    currentValue += 1;
1869                }
1870            } else if (action === 'minus' && currentValue > 0) {
1871                currentValue -= 1;
1872            }
1873    
1874            input.value = currentValue;
1875        }
1876
1877function handleFlavorQtyChange(groupName, maximumAmount, sectionName, event) {
1878    const checkbox = event.target;
1879    const li = checkbox.closest("li");
1880    const controls = li.querySelector(".flavor-qty-controls");
1881    const qtyInput = li.querySelector(".flavor-qty");
1882
1883    const showQtyControls =
1884    sectionName !== "Take Home" && maximumAmount > 1;
1885
1886    const visibleCard = checkbox.closest(".card");
1887
1888    const allChecked = Array.from(
1889        visibleCard.querySelectorAll(".flavor-checkbox:checked")
1890    );
1891
1892    if (checkbox.checked) {
1893
1894        if (showQtyControls) {
1895                controls.style.display = "flex";
1896            }
1897
1898        if (allChecked.length === 1) {
1899            checkbox.dataset.flavorQty = maximumAmount;
1900            qtyInput.value = maximumAmount;
1901        } else {
1902            let donor = allChecked.find(cb =>
1903                cb !== checkbox && Number(cb.dataset.flavorQty) > 1
1904            );
1905
1906            if (!donor) {
1907                checkbox.checked = false;
1908                checkbox.dataset.flavorQty = 0;
1909                qtyInput.value = 0;
1910                controls.style.display = "none";
1911
1912                showPopperAlert(`You have already allocated all ${maximumAmount} flavors.`, checkbox);
1913                return;
1914            }
1915
1916            donor.dataset.flavorQty = Number(donor.dataset.flavorQty) - 1;
1917            donor.closest("li").querySelector(".flavor-qty").value = donor.dataset.flavorQty;
1918
1919            checkbox.dataset.flavorQty = 1;
1920            qtyInput.value = 1;
1921        }
1922    } else {
1923        const removedQty = Number(checkbox.dataset.flavorQty || 0);
1924
1925        checkbox.dataset.flavorQty = 0;
1926        qtyInput.value = 0;
1927        controls.style.display = "none";
1928
1929        let remaining = allChecked.filter(cb => cb !== checkbox);
1930
1931        if (remaining.length > 0) {
1932            remaining[0].dataset.flavorQty =
1933                Number(remaining[0].dataset.flavorQty) + removedQty;
1934
1935            remaining[0].closest("li").querySelector(".flavor-qty").value =
1936                remaining[0].dataset.flavorQty;
1937        }
1938    }
1939
1940   if (!showQtyControls) {
1941        controls.style.display = "none";
1942    }
1943}
1944
1945   function changeFlavorQty(event, amount) {
1946    event.preventDefault();
1947    event.stopPropagation();
1948
1949    const li = event.target.closest("li");
1950    const checkbox = li.querySelector(".flavor-checkbox");
1951
1952    if (!checkbox || !checkbox.checked) return;
1953
1954    const visibleCard = checkbox.closest(".card");
1955
1956    const allChecked = Array.from(
1957        visibleCard.querySelectorAll(".flavor-checkbox:checked")
1958    );
1959
1960    let currentQty = Number(checkbox.dataset.flavorQty || 0);
1961
1962    if (amount === 1) {
1963
1964        let donor = allChecked.find(cb =>
1965            cb !== checkbox &&
1966            Number(cb.dataset.flavorQty) > 1
1967        );
1968
1969        if (!donor) return;
1970
1971        donor.dataset.flavorQty =
1972            Number(donor.dataset.flavorQty) - 1;
1973
1974        donor.closest("li")
1975            .querySelector(".flavor-qty")
1976            .value = donor.dataset.flavorQty;
1977
1978        checkbox.dataset.flavorQty = currentQty + 1;
1979    }
1980
1981    if (amount === -1) {
1982
1983        if (currentQty <= 1) return;
1984
1985        let receiver = allChecked.find(cb => cb !== checkbox);
1986
1987        if (!receiver) return;
1988
1989        receiver.dataset.flavorQty =
1990            Number(receiver.dataset.flavorQty) + 1;
1991
1992        receiver.closest("li")
1993            .querySelector(".flavor-qty")
1994            .value = receiver.dataset.flavorQty;
1995
1996        checkbox.dataset.flavorQty = currentQty - 1;
1997    }
1998
1999    li.querySelector(".flavor-qty").value =
2000        checkbox.dataset.flavorQty;
2001}
2002
2003
2004        function handleModifierChange(groupName, minimumAmount, maximumAmount, event) {
2005            let currentGroup;
2006            
2007            var blnNestedFlavors = false;
2008            if (getQueryStringParameter('number') != '999999'){
2009                blnNestedFlavors = true;
2010            }
2011
2012            if (groupName === "Flavors" || (groupName === "Flavor #1" && blnNestedFlavors) ||( groupName === "Flavor #2" && blnNestedFlavors) ||( groupName === "Flavor #3" && blnNestedFlavors)) {
2013                var modifiedGroupName = groupName;
2014                currentGroup = currentItem.modifier_groups.find(group => group.name === modifiedGroupName);
2015            }else {
2016                currentGroup = currentItem.modifier_groups.find(group => group.name === groupName);
2017            }
2018            
2019            if (!currentGroup) {
2020                console.error(`Modifier group with name ${groupName} not found.`);
2021                return;
2022            }
2023
2024            let selectedCount = 0;
2025            console.log(groupName);
2026
2027            if (groupName === "Flavors" || groupName === "Select Flavor" || (groupName === "Flavor #1" && blnNestedFlavors) || ( groupName === "Flavor #2" && blnNestedFlavors) || ( groupName === "Flavor #3" && blnNestedFlavors)) {
2028                console.log('checking here');
2029                currentGroup.modifiers.forEach(flavorGroup => {
2030                    if (flavorGroup.modifier_groups && flavorGroup.modifier_groups.length > 0) {
2031                        const visibleCard = Array.from(document.querySelectorAll('#modal-content .card.mt-3'))
2032                            .find(card => card.offsetParent !== null);
2033
2034                        if (visibleCard) {
2035                            flavorGroup.modifier_groups[0].modifiers.forEach(modifier => {
2036                                const escapedId = CSS.escape(`modifier-${flavorGroup.name}-${modifier.id}`);
2037                                const checkbox = visibleCard.querySelector(`#${escapedId}`);
2038                                if (checkbox && checkbox.checked) {
2039                                    selectedCount++;
2040                                }
2041                            });
2042                        }
2043                    }
2044
2045                });
2046            } else {
2047                console.log('checking the reg');
2048                currentGroup.modifiers.forEach(modifier => {
2049                    const checkbox = document.getElementById(`modifier-${groupName}-${modifier.id}`);
2050                    if (checkbox && checkbox.checked) {
2051                        selectedCount++;
2052                    }
2053                });
2054            }
2055
2056            if (selectedCount > maximumAmount) {
2057                showPopperAlert(`You can select a maximum of ${maximumAmount} ${groupName}.`, event.target);
2058                event.target.checked = false; // Uncheck the checkbox that triggered the event
2059            }
2060        }
2061
2062        function showPopperAlert(message, element) {
2063    console.log('popper alert');
2064    console.log(message);
2065    console.log(element);
2066
2067    const popperContainer = document.getElementById('popper-container');
2068
2069    popperContainer.innerHTML = `
2070        <div class="popper-alert"
2071             role="alert"
2072             aria-live="assertive"
2073             aria-atomic="true">
2074            ${message}
2075        </div>
2076    `;
2077
2078    const popperAlert = popperContainer.querySelector('.popper-alert');
2079
2080    Popper.createPopper(element, popperAlert, {
2081        placement: 'top',
2082        modifiers: [{
2083            name: 'offset',
2084            options: {
2085                offset: [0, 8]
2086            }
2087        }]
2088    });
2089
2090    setTimeout(() => {
2091        popperContainer.innerHTML = '';
2092    }, 3000);
2093}
2094
2095       function toggleItemsVisibility(index) {
2096    const itemsDiv = document.getElementById(`items-${index}`);
2097    const button = document.querySelector(
2098        `[aria-controls="items-${index}"]`
2099    );
2100
2101    if (itemsDiv.classList.contains('hidden-items')) {
2102        itemsDiv.classList.remove('hidden-items');
2103
2104        if (button) {
2105            button.setAttribute('aria-expanded', 'true');
2106        }
2107    } else {
2108        itemsDiv.classList.add('hidden-items');
2109
2110        if (button) {
2111            button.setAttribute('aria-expanded', 'false');
2112        }
2113    }
2114}
2115
2116        function buildGA4Items(cartItem) {
2117            var items = [];
2118
2119            var variantParts = [];
2120            if (cartItem.modifiers && cartItem.modifiers.length) {
2121                for (var i = 0; i < cartItem.modifiers.length; i++) {
2122                    variantParts.push(
2123                        cartItem.modifiers[i].group + ": " + cartItem.modifiers[i].name
2124                    );
2125                }
2126            }
2127
2128            // Base item
2129            items.push({
2130                item_id: cartItem.id,
2131                item_name: cartItem.name,
2132                item_category: "Menu Item",
2133                item_variant: variantParts.join(" | "),
2134                price: cartItem.price,
2135                quantity: cartItem.quantity
2136            });
2137
2138            // Paid extras
2139            if (cartItem.extras && cartItem.extras.length) {
2140                for (var j = 0; j < cartItem.extras.length; j++) {
2141                    var extra = cartItem.extras[j];
2142                    items.push({
2143                        item_id: "EXTRA_" + extra.id,
2144                        item_name: extra.name,
2145                        item_category: "Extras",
2146                        item_variant: extra.group,
2147                        price: extra.price,
2148                        quantity: extra.quantity
2149                    });
2150                }
2151            }
2152
2153            return items;
2154        }
2155
2156
2157        function buildGA4ItemsFromCart(cart) {
2158            var items = [];
2159
2160            if (!cart || !cart.length) return items;
2161
2162            for (var i = 0; i < cart.length; i++) {
2163                items = items.concat(buildGA4Items(cart[i]));
2164            }
2165
2166            return items;
2167        }
2168
2169
2170        function buildGA4ItemsFromOrder(orderItems) {
2171            var items = [];
2172
2173            if (!orderItems || !orderItems.length) return items;
2174
2175            for (var i = 0; i < orderItems.length; i++) {
2176                var order = orderItems[i];
2177
2178                var qty = parseInt(order.qty, 10) || 1;
2179                var totalPrice = parseFloat(order.totalprice) || 0;
2180
2181                // ✅ Convert extended price -> unit price for GA4
2182                var unitPrice = qty > 0 ? (totalPrice / qty) : totalPrice;
2183
2184                var variantParts = [];
2185                if (order.flavors && order.flavors.length) {
2186                    for (var f = 0; f < order.flavors.length; f++) {
2187                        variantParts.push(
2188                            order.flavors[f].group + ": " + order.flavors[f].name
2189                        );
2190                    }
2191                }
2192
2193                // Base item
2194                items.push({
2195                    item_id: order.itemid,
2196                    item_name: order.itemname,
2197                    item_category: "Menu Item",
2198                    item_variant: variantParts.join(" | "),
2199                    price: unitPrice,
2200                    quantity: parseInt(order.qty, 10) || 1
2201                });
2202
2203                // Extras
2204                if (order.extras && order.extras.length) {
2205                    for (var e = 0; e < order.extras.length; e++) {
2206                        var extra = order.extras[e];
2207                        items.push({
2208                            item_id: extra.itemid,
2209                            item_name: extra.itemName,
2210                            item_category: "Extras",
2211                            item_variant: "Extra",
2212                            price: extra.price,
2213                            quantity: parseInt(extra.Qty, 10) || 1
2214                        });
2215                    }
2216                }
2217            }
2218
2219            return items;
2220        }
2221
2222
2223
2224       function removeFromCart(index) {
2225
2226    if (window.console && console.log) {
2227        console.log("Removing item at index: " + index);
2228    }
2229
2230    var cartItem = cart[index];
2231
2232    if (!cartItem) {
2233        console.warn("Cart item not found at index: " + index);
2234        return;
2235    }
2236
2237    /*
2238     * Analytics must never prevent the cart from updating.
2239     */
2240    try {
2241        var ga4Items = buildGA4Items(cartItem) || [];
2242
2243        var totalValue = 0;
2244
2245        for (var i = 0; i < ga4Items.length; i++) {
2246            totalValue += (
2247                Number(ga4Items[i].price || 0) *
2248                Number(ga4Items[i].quantity || 0)
2249            );
2250        }
2251
2252        if (
2253            window.GTM &&
2254            typeof window.GTM.pushEvent === "function"
2255        ) {
2256            window.GTM.pushEvent({
2257                event: "remove_from_cart",
2258                store_number: getStoreNumber(),
2259                ecommerce: {
2260                    currency: "USD",
2261                    value: Number(totalValue.toFixed(2)),
2262                    items: ga4Items
2263                }
2264            });
2265        } else {
2266            console.warn(
2267                "GTM remove_from_cart event skipped because " +
2268                "window.GTM.pushEvent is unavailable."
2269            );
2270        }
2271    } catch (error) {
2272        console.error(
2273            "Unable to send GTM remove_from_cart event:",
2274            error
2275        );
2276    }
2277
2278    /*
2279     * Always remove and re-render, even when analytics fails.
2280     */
2281    cart.splice(index, 1);
2282    renderCart();
2283}
2284
2285
2286
2287        document.addEventListener("DOMContentLoaded", function () {
2288            const hiddenField = $("#hiddenFieldMenuData");
2289            const menuData = JSON.parse(hiddenField.val());
2290
2291            // Display the value of the hiddenFieldAddress below the header
2292            var hiddenFieldAddress = $("#hiddenFieldAddress");
2293            var addressDisplay = $("#addressDisplay");
2294            addressDisplay.text(hiddenFieldAddress.val());
2295
2296            const hiddenFieldLeadTime = $("#hiddenFieldLeadTime");
2297            const leadTimeHours = parseInt(hiddenFieldLeadTime.val(), 10);
2298
2299
2300            // Function to create the lead time text
2301            function createLeadTimeText() {
2302                return `<p class="text-center text-muted">Lead Time Required: ${leadTimeHours} hours</p>`;
2303            }
2304
2305            const pickupAsapRadio = document.getElementById("pickupAsap");
2306            const pickupDateTimeRadio = document.getElementById("pickupDateTime");
2307            const pickupDateTimePicker = document.getElementById("pickupDateTimePicker");
2308
2309            pickupAsapRadio.addEventListener("change", function () {
2310                if (this.checked) {
2311                    pickupDateTimePicker.classList.add("d-none");
2312                }
2313            });
2314
2315            pickupDateTimeRadio.addEventListener("change", function () {
2316                if (this.checked) {
2317                    pickupDateTimePicker.classList.remove("d-none");
2318                }
2319            });
2320
2321            function showPreviousModifierGroup() {
2322                if (currentModifierGroupIndex > 0) {
2323                    currentModifierGroupIndex--;
2324                    showNextModifierGroup();
2325                }
2326            }
2327
2328function createFlavorModifierGroup(modifierGroup, sectionName) {
2329
2330    const showQtyControls =
2331    sectionName !== "Take Home" && modifierGroup.maximum_amount > 1;
2332
2333    let flavorGroups = modifierGroup.modifiers.map(flavorGroup => {
2334        const isNonDairyOatMilk = flavorGroup.name === "Non-Dairy w/ OAT MILK";
2335
2336        let flavors = flavorGroup.modifier_groups[0].modifiers.map(modifier => {
2337            let modifierName = modifier.name;
2338
2339            if (isNonDairyOatMilk && modifierName.startsWith("Non-Dairy")) {
2340                modifierName = modifierName.replace(
2341                    "Non-Dairy",
2342                    `<span style="color: #047303; font-weight:bold">Non Dairy</span>`
2343                );
2344            }
2345
2346            if (modifier.hasOwnProperty("vegan") && modifier.vegan === true) {
2347                modifierName += ` <sup style="color: #047303; font-weight:bold">V</sup>`;
2348            }
2349
2350            return `
2351                <li class="list-group-item d-flex justify-content-between align-items-center">
2352
2353                    <div class="d-flex align-items-center">
2354
2355                    <input type="checkbox"
2356                           id="modifier-${flavorGroup.name}-${modifier.id}"
2357                           name="modifier-${flavorGroup.name}-${modifier.id}"
2358                           class="modifier-checkbox flavor-checkbox me-2"
2359                           data-flavor-qty="${modifier.selected ? modifierGroup.maximum_amount : 0}"
2360                           ${modifier.selected ? 'checked' : ''}
2361                           onchange="handleFlavorQtyChange('${modifierGroup.name}', ${modifierGroup.maximum_amount}, '${sectionName}', event);">
2362
2363                    <label class="mb-0"
2364                           for="modifier-${flavorGroup.name}-${modifier.id}">
2365                        ${modifierName}
2366                    </label>
2367
2368                    ${modifier.image_url ? `
2369                        <button type="button"
2370                                class="btn p-0 border-0 ms-1 flavor-image-button"
2371                                onclick="showFlavorImage('${modifier.name}', '${modifier.image_url}', 'modifier-${flavorGroup.name}-${modifier.id}', event); return false;"
2372                                aria-label="View image of ${modifier.n
2372ame}">
2373                            <i class="fas fa-eye" aria-hidden="true"></i>
2374                        </button>`
2375                        : ''}
2376
2377                </div>
2378
2379                    <div class="d-flex align-items-center">
2380
2381                        <div class="input-group input-group-sm flavor-qty-controls"
2382                             style="
2383                                width:100px;
2384                                ${modifier.selected ? '' : 'display:none;'}
2385                                ${!showQtyControls ? 'display:none;' : ''}
2386                             ">
2387
2388                           <button class="btn btn-outline-secondary"
2389                                type="button"
2390                                aria-label="Decrease ${modifier.name} quantity"
2391                                onclick="changeFlavorQty(event, -1)">
2392                            -
2393                        </button>
2394
2395                        <label for="flavor-qty-${modifier.id}"
2396                               class="visually-hidden">
2397                            ${modifier.name} quantity
2398                        </label>
2399
2400                        <input type="text"
2401                               id="flavor-qty-${modifier.id}"
2402                               class="form-control text-center flavor-qty"
2403                               value="${modifier.selected ? modifierGroup.maximum_amount : 0}"
2404                               readonly>
2405
2406                        <button class="btn btn-outline-secondary"
2407                                type="button"
2408                                aria-label="Increase ${modifier.name} quantity"
2409                                onclick="changeFlavorQty(event, 1)">
2410                            +
2411                        </button>
2412
2413                        </div>
2414
2415                        ${modifier.price > 0 ? `
2416                            <span class="badge bg-primary rounded-pill ms-2">
2417                                $${modifier.price.toFixed(2)}
2418                            </span>
2419                        ` : ''}
2420
2421                    </div>
2422
2423                </li>
2424            `;
2425        }).join('');
2426
2427        return `
2428            <div>
2429                <h6 class="flavor-group-heading">${flavorGroup.name}</h6>
2430                <ul class="list-group">
2431                    ${flavors}
2432                </ul>
2433            </div>
2434        `;
2435    }).join('');
2436
2437    return `
2438        <div class="card mt-3">
2439            <div class="card-header">
2440                <h5 class="mb-0">${modifierGroup.name}</h5>
2441            </div>
2442            <div class="card-body">
2443                ${flavorGroups}
2444            </div>
2445        </div>
2446    `;
2447}
2448
2449
2450            function createModifierGroup(modifierGroup,sectionName) {
2451                if (!modifierGroup.modifiers || modifierGroup.modifiers.length === 0) {
2452                    return ''; // Skip empty modifier groups
2453                }
2454
2455                if (modifierGroup.name === "Flavors" || modifierGroup.name === "Select Flavor" || modifierGroup.name === "Flavor #1"  || modifierGroup.name === "Flavor #2" ||modifierGroup.name === "Flavor #3" ) {
2456                    return createFlavorModifierGroup(modifierGroup,sectionName);
2457                }
2458
2459                let modifiers;
2460                if (modifierGroup.name === "Extras") {
2461                    modifiers = modifierGroup.modifiers.map(modifier => `
2462            <li class="list-group-item d-flex justify-content-between align-items-center">
2463                <div>
2464                    <span ${modifier.tax ? `data-tax="${modifier.tax}"` : ''}>${modifier.name}</span>
2465                    ${modifier.price > 0 ? `<span class="badge bg-primary rounded-pill ms-2">$${modifier.price.toFixed(2)}</span>` : ''}
2466                </div>
2467                <div class="input-group input-group-sm" style="max-width: 100px;">
2468                    <button class="btn btn-outline-secondary" type="button" onclick="changeQuantity('minus', '${modifierGroup.name}-${modifier.id}',${modifier.maximum_amount})">-</button>
2469                    <input type="text" class="form-control text-center" value="
24690" id="quantity-${modifierGroup.name}-${modifier.id}" readonly>
2470                    <button class="btn btn-outline-secondary" type="button" onclick="changeQuantity('plus', '${modifierGroup.name}-${modifier.id}',${modifier.maximum_amount})">+</button>
2471                </div>
2472            </li>
2473        `).join('');
2474                } else {
2475                    modifiers = modifierGroup.modifiers.map(modifier => {
2476                        if (modifier.inputType) {
2477                            let formElement = '';
2478                            if (modifier.inputType === 'textarea') {
2479                                formElement = `<textarea id="modifier-${modifierGroup.name}-${modifier.id}" class="form-control"></textarea>`;
2480                            } else if (modifier.inputType === 'file') {
2481                                formElement = `<input type="file" id="modifier-${modifierGroup.name}-${modifier.id}" class="form-control" />`;
2482                            } else {
2483                                formElement = `<input type="text" id="modifier-${modifierGroup.name}-${modifier.id}" class="form-control" />`;
2484                            }
2485
2486                            return `
2487            <li class="list-group-item d-flex justify-content-between align-items-center">
2488                <div>
2489                    <label for="modifier-${modifierGroup.name}-${modifier.id}">${modifier.name}</label>
2490                    ${formElement}
2491                </div>
2492                ${modifier.price > 0 ? `<span class="badge bg-primary rounded-pill">$${modifier.price.toFixed(2)}</span>` : ''}
2493            </li>
2494        `;
2495                        } else {
2496                            return `
2497    <li class="list-group-item d-flex justify-content-between align-items-start">
2498        <div class="me-3">
2499            <div class="form-check">
2500                <input type="checkbox" 
2501                    id="modifier-${modifierGroup.name}-${modifier.id}" 
2502                    name="modifier-${modifierGroup.name}-${modifier.id}" 
2503                    class="form-check-input modifier-checkbox"
2504                    ${modifier.selected ? 'checked' : ''} 
2505                    onchange="handleModifierChange('${modifierGroup.name}', ${modifierGroup.minimum_amount}, ${modifierGroup.maximum_amount}, event);">
2506                <label class="form-check-label" for="modifier-${modifierGroup.name}-${modifier.id}">
2507                    ${modifier.name}
2508                </label>
2509            </div>
2510
2511            ${modifier.customImg ? `
2512    <div class="mt-2">
2513        <img src="${modifier.image_url}" 
2514     class="clickable-modifier-img"
2515     data-full="${modifier.image_url.split('?')[0]}"
2516     style="width:120px; height:auto; object-fit:cover; cursor:pointer; 
2517                border:1px solid #dee2e6; border-radius:.25rem; padding:.25rem;">
2518        <div><small class="text-muted">Actual Design</small></div>
2519    </div>
2520` : ''}
2521        </div>
2522
2523        ${modifier.price > 0 ? `<span class="badge bg-primary rounded-pill">$${modifier.price.toFixed(2)}</span>` : ''}
2524    </li>
2525`;
2526                        }
2527                    }).join('');
2528
2529                }
2530
2531                return `
2532        <div class="card mt-3">
2533            <div class="card-header">
2534                <h5 class="mb-0">
2535                    ${modifierGroup.name}
2536                </h5>
2537            </div>
2538            <div class="card-body">
2539                <ul class="list-group">${modifiers}</ul>
2540            </div>
2541        </div>
2542    `;
2543            }
2544
2545
2546            function createMenuItem(item, index, sectionName) {
2547                // Replace line breaks with <br> and escape HTML special characters in the description
2548                const itemDescription = item.description
2549                    .replace(/(?:\r\n|\r|\n)/g, '<br>') // Replace line breaks
2550                    .replace(/&/g, '&amp;')            // Escape &
2551                    .replace(/</g, '&lt;')             // Escape <
2552                    .replace(/>/g, '&gt;')             // Escape >
2553                    .replace(/"/g, '&quot;')           // Escape "
2554                    .replace(/'/g, '&#39;');           // Escape '
2555
2556                return `
2557        <div class="card mt-3">
2558            <div class="card-header">
2559                <h5 class="mb-0">
2560                    <button class="btn btn-link" type="button"
2561                        data-item-id="${item.id}"
2562                        data-item-name="${item.name}"
2563                        data-item-description="${itemDescription}"
2564                        data-item-price="${item.price.toFixed(2)}"
2565                        data-item-tax-rate="${item.tax_rate}"
2566                        data-item-image="${item.image_url}"
2567                        data-section-index="${index}"
2568                        data-section-name="${sectionName}">
2569                        ${item.name} - $${item.price.toFixed(2)}
2570                    </button>
2571                </h5>
2572            </div>
2573        </div>
2574    `;
2575            }
2576
2577
2578            function createMenuSection(section, index) {
2579                function createMenuItemWithIndex(item) {
2580                    return createMenuItem(item, index, section.name);
2581                }
2582
2583                // Apply the same name transformation logic
2584                var displayName;
2585
2586                if (section.name === "Cakes") {
2587                    displayName = "Custom Ice Cream Cakes";
2588                } else if (section.name === "Pies") {
2589                    displayName = "Custom Ice Cream Pies";
2590                } else if (section.name === "Cakes & Pies") {
2591                    displayName = "Ready Made Cakes & Pies";
2592                }
2593                else if (section.name === "Miscellaneous") {
2594                    displayName = "Other";
2595                } 
2596                else if (section.name === "Blasts") {
2597                    displayName = "Bruster's Blasts";
2598                }
2599                else if (section.name === "Shakes") {
2600                    displayName = "Hand-Spun Shakes";
2601                }
2602                else if (section.name === "Cups / Dishes") {
2603                    displayName = "Cups";
2604                }
2605                else if (section.name === "Take Home") {
2606                    displayName = "Hand-Packed To Go";
2607                }
2608                else if (section.name === "Kids") {
2609                    displayName = "Kids' Stuff";
2610                }
2611                else if (section.name === "Freeze") {
2612                    displayName = "Freezes";
2613                }
2614                else if (section.name === "Oreo Sandwiches") {
2615                    displayName = "Ice Cream Sandwich Made With OREO® Wafers";
2616                }
2617                else {
2618                    displayName = section.name; // Fallback for all other cases
2619                }
2620
2621                const items = section.items.map(createMenuItemWithIndex).join('');
2622                const additionalText = section.name === "Cakes & Pies" ? '<p class="text-center text-muted">Available For Same Day Pick Up</p>' : '';
2623                const leadTimeText = section.items.some(item => item.leadTimeRequired) ? createLeadTimeText() : '';
2624
2625                return `
2626    <div class="col" id="section-${index}">
2627        <div class="card menu-section">
2628            <div class="card-header">
2629                <h2>${displayName}</h2>
2630            </div>
2631
2632            <div class="card-body">
2633                <button type="button"
2634                        class="btn p-0 border-0 w-100"
2635                        onclick="toggleItemsVisibility(${index})"
2636                        aria-label="Show ${displayName} items"
2637                        aria-controls="items-${index}"
2638                        aria-expanded="false">
2639                    <img src="${section.image_url}"
2640                         alt="${displayName}"
2641                         class="img-fluid menu-img mb-3 rounded">
2642                </button>
2643
2644                ${additionalText}
2645                ${leadTimeText}
2646
2647                <div class="items hidden-items"
2648                     id="items-${index}">
2649                    ${items}
2650                </div>
2651            </div>
2652        </div>
2653    </div>
2654`;
2655            }
2656
2657            function createSectionLink(section, index) {
2658                var displayName;
2659
2660                if (section.name === "Cakes") {
2661                    displayName = "Custom Ice Cream Cakes";
2662                } else if (section.name === "Pies") {
2663                    displayName = "Custom Ice Cream Pies";
2664                } else if (section.name === "Cakes & Pies") {
2665                    displayName = "Ready Made Cakes & Pies";
2666                }
2667                else if (section.name === "Miscellaneous") {
2668                    displayName = "Other";
2669                } 
2670                else if (section.name === "Blasts") {
2671                    displayName = "Bruster's Blasts";
2672                }
2673                else if (section.name === "Shakes") {
2674                    displayName = "Hand-Spun Shakes";
2675                }
2676                else if (section.name === "Cups / Dishes") {
2677                    displayName = "Cups";
2678                }
2679                else if (section.name === "Take Home") {
2680                    displayName = "Hand-Packed To Go";
2681                }
2682                else if (section.name === "Kids") {
2683                    displayName = "Kids' Stuff";
2684                }
2685                else if (section.name === "Freeze") {
2686                    displayName = "Freezes";
2687                }
2688                else if (section.name === "Oreo Sandwiches") {
2689                    displayName = "Ice Cream Sandwich Made With OREO® Wafers";
2690                }
2691                else {
2692                    displayName = section.name; // Fallback for all other cases
2693                }
2694
2695                return `
2696        <a href="#section-${index}" class="section-link">${displayName}</a>
2697    `;
2698            }
2699
2700
2701            function renderMenu(menuData) {
2702                const menuContainer = document.getElementById('menu-container');
2703                const sectionLinksContainer = document.getElementById('section-links');
2704                const sections = menuData[0].menu_sections.map((section, index) => createMenuSection(section, index)).join('');
2705                const sectionLinks = menuData[0].menu_sections.map((section, index) => createSectionLink(section, index)).join('');
2706                menuContainer.innerHTML = sections;
2707                sectionLinksContainer.innerHTML = sectionLinks;
2708
2709          
2710                function populateSelectLists(item, type) {
2711                    const flavorMap = new Map();
2712                    const cakeFlavorMap = new Map();
2713                    const fillingMap = new Map();
2714                    const colorMap = new Map();
2715                    const crustFlavorMap = new Map();
2716
2717                    let hasFlavor = false;
2718                    let hasCake = false;
2719                    let hasFilling = false;
2720                    let hasColor = false;
2721                    let hasCrust = false;
2722
2723                    if (item.modifier_groups && item.modifier_groups.length > 0) {
2724                        item.modifier_groups.forEach(modifierGroup => {
2725                            if (modifierGroup.name === 'Select Flavor' || modifierGroup.name === 'Flavors') {
2726                                hasFlavor = true;
2727                                if (modifierGroup.modifiers) {
2728                                    modifierGroup.modifiers.forEac
2728h(category => {
2729                                        if (category.modifier_groups && category.modifier_groups.length > 0) {
2730                                            category.modifier_groups.forEach(flavorGroup => {
2731                                                if (flavorGroup.modifiers) {
2732                                                    flavorGroup.modifiers.forEach(flavor => {
2733                                                        flavorMap.set(flavor.name, {
2734                                                            name: flavor.name,
2735                                                            itemId: flavor.id
2736                                                        });
2737                                                    });
2738                                                }
2739                                            });
2740                                        }
2741                                    });
2742                                }
2743                            }
2744
2745                            if (modifierGroup.name === 'Cake Flavor') {
2746                                hasCake = true;
2747                                if (modifierGroup.modifiers) {
2748                                    modifierGroup.modifiers.forEach(modifier => {
2749                                        cakeFlavorMap.set(modifier.name, {
2750                                            name: modifier.name,
2751                                            itemId: modifier.id
2752                                        });
2753                                    });
2754                                }
2755                            }
2756
2757                            if (modifierGroup.name === 'Crust Flavor') {
2758                                hasCrust = true;
2759                                if (modifierGroup.modifiers) {
2760                                    modifierGroup.modifiers.forEach(modifier => {
2761                                        crustFlavorMap.set(modifier.name, {
2762                                            name: modifier.name,
2763                                            itemId: modifier.id
2764                                        });
2765                                    });
2766                                }
2767                            }
2768
2769                            if (modifierGroup.name === 'Filling Flavor') {
2770                                hasFilling = true;
2771                                if (modifierGroup.modifiers) {
2772                                    modifierGroup.modifiers.forEach(modifier => {
2773                                        fillingMap.set(modifier.name, {
2774                                            name: modifier.name,
2775                                            itemId: modifier.id
2776                                        });
2777                                    });
2778                                }
2779                            }
2780
2781                            if (modifierGroup.name === 'Writing Color') {
2782                                hasColor = true;
2783                                if (modifierGroup.modifiers) {
2784                                    modifierGroup.modifiers.forEach(modifier => {
2785                                        colorMap.set(modifier.name, {
2786                                            name: modifier.name,
2787                                            itemId: modifier.id
2788                                        });
2789                                    });
2790                                }
2791                            }
2792                        });
2793                    }
2794
2795                    if (type === 'cake') {
2796                        populateDropdown('cakeicecreamselect', flavorMap, 'Select Flavor', hasFlavor);
2797                        populateDropdown('cakecakeselect', cakeFlavorMap, 'Select Cake', hasCake);
2798                        populateDropdown('cakefillingselect', fillingMap, 'Select Filling', hasFilling);
2799                        populateDropdown('cakecolorselect', colorMap, 'Select Color of Writing', hasColor);
2800
2801                        // ✅ Add this line at the end of this function
2802                        toggleMessageBox(item.modifier_groups);
2803
2804                    } else if (type === 'pie') {
2805                        populateDropdown('pieicecreamselect', flavorMap, 'Select Flavor', hasFlavor);
2806                        populateDropdown('piecrustselect', crustFlavorMap, 'Select Crust', hasCrust); // Crust = Cake flavor
2807                        populateDropdown('piefillingselect', fillingMap, 'Select Filling', hasFilling);
2808                        populateDropdown('piecolorselect', colorMap, 'Select Color of Writing', hasColor);
2809                    }
2810                }
2811
2812                function populateModifiers(modifiers, selectId) {
2813                    const selectElement = document.getElementById(selectId);
2814                    modifiers.forEach(modifier => {
2815                        const option = document.createElement('option');
2816                        option.value = modifier.name;
2817                        option.text = modifier.name;
2818                        option.setAttribute('data-item-id', modifier.itemId); // Set data-item-id attribute
2819                        selectElement.appendChild(option);
2820                    });
2821                }
2822
2823                function populateDropdown(selectId, map, defaultText, groupExists) {
2824                    console.log(selectId);
2825                    console.log(map);
2826                    console.log(groupExists);
2827                    const select = document.getElementById(selectId);
2828                    if (!select) return;
2829
2830                    select.innerHTML = "";
2831
2832                    const defaultOption = document.createElement("option");
2833                    defaultOption.value = "";
2834                    defaultOption.textContent = defaultText;
2835                    select.appendChild(defaultOption);
2836
2837                    map.forEach(value => {
2838                        const option = document.createElement("option");
2839                        option.value = value.name;
2840                        option.textContent = value.name;
2841                        option.setAttribute('data-item-id', value.itemId); // Set data-item-id attribute
2842                        select.appendChild(option);
2843                    });
2844
2845                    // Only hide the dropdown if the modifier group doesn't exist at all
2846                    select.style.display = groupExists ? "" : "none";
2847                }
2848
2849                function toggleMessageBox(modifierGroups) {
2850                    const hasCustomMessage = modifierGroups.some(group => 
2851                        group.name.toLowerCase().includes("message")
2852                    );
2853
2854                    const messageBox = document.getElementById("cakemessage");
2855                    if (messageBox) {
2856                        messageBox.style.display = hasCustomMessage ? "" : "none";
2857                    }
2858                }
2859
2860
2861
2862
2863                    document.querySelectorAll('.btn-link').forEach(button => {
2864                        button.addEventListener('click', function () {
2865                            const itemId = this.getAttribute('data-item-id');
2866                            const itemName = this.getAttribute('data-item-name');
2867                            const itemDescription = this.getAttribute('data-item-description').replace(/(?:\r\n|\r|\n)/g, '<br>'); // Replace line breaks with <br>
2868                            const itemPrice = this.getAttribute('data-item-price');
2869                            const itemTaxRate = this.getAttribute('data-item-tax-rate');
2870                            const itemImage = this.getAttribute('data-item-image');
2871                            const sectionName = this.getAttribute('data-section-name'); // Get the section name
2872
2873                            isCake = false;
2874                            isPie = false;
2875
2876                            console.log(sectionName);
2877
2878                            const item = menuData[0].menu_sections.flatMap(section => section.items).find(i => i.id == itemId && i.name == itemName);
2879
2880                            console.log(item);
2881
2882                            currentItem = item;
2883                            currentModifierGroupIndex = 0;
2884
2885                            const modifierGroups = item.modifier_groups
2886                            .filter(group => group.modifiers && group.modifiers.length > 0)
2887                            .map(group => createModifierGroup(group, sectionName))
2888                            .filter(groupHtml => groupHtml !== '');
2889
2890                            console.log(modifierGroups.length);
2891
2892                            // Add Quantity Input with Validation
2893                            const modalContent = `
2894            <h3>${itemName}</h3>
2895            <p>${itemDescription}</p>
2896            <img src="${itemImage}" alt="${itemName}" class="img-fluid menu-img mb-3 rounded">
2897            <h4>Price: $${itemPrice}</h4>
2898            <div class="mt-3">
2899                <label for="itemQuantity" class="d-block">Quantity:</label>
2900                <input type="text" id="itemQuantity" class="form-control" value="1" inputmode="numeric" style="width: 80px; -moz-appearance: textfield;">
2901                <small id="quantityError" class="text-danger" style="display: none;">Please enter a valid quantity.</small>
2902            </div>
2903            <div id="modifier-groups">${modifierGroups.join('')}</div>
2904        `;
2905
2906                            document.querySelector('#modal-content').innerHTML = modalContent;
2907
2908                            // Quantity Input Validation
2909                            const quantityInput = document.getElementById('itemQuantity');
2910                            const quantityError = document.getElementById('quantityError');
2911
2912                            quantityInput.addEventListener('input', function () {
2913                                const value = quantityInput.value;
2914                                if (!/^\d+$/.test(value) || parseInt(value, 10) < 1) {
2915                                    quantityError.style.display = 'block';
2916                                } else {
2917                                    quantityError.style.display = 'none';
2918                                }
2919                            });
2920
2921
2922
2923                            if (sectionName == 'Cakes') {
2924                                if (modifierGroups.length < 6) {
2925                                    $(".btn-cake-step1").text('Add To Cart');
2926                                }
2927                                isCake = true;
2928                                currentModifierGroupIndex = 4;
2929                                //populateSelectLists(menuData, 'cake');
2930                                populateSelectLists(item, 'cake');
2931                                $(".cakedescription").remove();
2932                                $(".cakeimage").before('<p class="text-muted cakedescription">' + itemDescription + '</p>');
2933                                $(".cakeimage").attr('src', itemImage);
2934                                $("#modalCake1").modal('show');
2935                            } else if (sectionName == 'Pies') {
2936                                if (modifierGroups.length < 6) {
2937                                    $(".btn-pie-step1").text('Add To Cart');
2938                                }
2939                                isPie = true;
2940                                currentModifierGroupIndex = 4;
2941                                //populateSelectLists(menuData, 'pie');
2942                                populateSelectLists(item, 'pie');
2943                                $(".piedescription").remove();
2944                                $(".pieimage").before('<p class="text-muted piedescription">' + itemDescription + '</p>');
2945                                $(".pieimage").attr('src', itemImage);
2946                                $("#modalPie1").modal('show');
2947                            } else {
2948                                const nextModifierGroupButtonTop = document.querySelector('#nextModifierGroupButtonTop');
2949                                const nextModifierGroupButton = document.querySelector('#nextModifierGroupButton');
2950                                const addToCartButtonTop = document.querySelector('#addToCartButtonTop');
2951                                const addToCartButton = document.querySelector('#addToCartButton');
2952
2953                                if (modifierGroups.length === 0) {
2954                                    if (nextModifierGroupButtonTop) nextModifierGroupButtonTop.style.display = 'none';
2955                                    if (nextModifierGroupButton) nextModifierGroupButton.style.display = 'none';
2956                                    if (addToCartButtonTop) addToCartButtonTop.style.display = 'block';
2957                                    if (addToCartButton) addToCartButton.style.display = 'block';
2958                                } else {
2959                                    if (nextModifierGroupButtonTop) nextModifierGroupButtonTop.style.display = 'block';
2960                                    if (nextModifierGroupButton) nextModifierGroupButton.style.display = 'block';
2961                                    if (addToCartButtonTop) addToCartButtonTop.style.display = 'none';
2962                                    if (addToCartButton) addToCartButton.style.display = 'none';
2963                                    showNextModifierGroup();
2964                                }
2965
2966                                const itemModal = new bootstrap.Modal(document.getElementById('itemModal'));
2967                                itemModal.show();
2968                            }
2969
2970                        });
2971                    });
2972
2973            }
2974
2975            let originalTopButtonsParent = null;
2976
2977            // Update the showNextModifierGroup function to handle Back button visibility
2978            function showNextModifierGroup() {
2979                const modifierGroups = Array.from(document.querySelectorAll('#modifier-groups .card')).filter(group => group.querySelector('.list-group-item'));
2980                const topButtonsContainer = document.getElementById('top-buttons');
2981                const modifierGroupsDiv = document.getElementById('modifier-groups');
2982
2983                // Store the original parent of the top buttons if not already stored
2984                if (!originalTopButtonsParent) {
2985                    originalTopButtonsParent = topButtonsContainer.parentNode;
2986                }
2987                // Move the top buttons to the new position
2988                if (topButtonsContainer && modifierGroupsDiv) {
2989                    modifierGroupsDiv.parentNode.insertBefore(topButtonsContainer, modifierGroupsDiv);
2990                }
2991
2992                if (currentModifierGroupIndex < modifierGroups.length) {
2993                    modifierGroups.forEach((group, index) => {
2994                        if (index === currentModifierGroupIndex) {
2995                            group.style.display = 'block';
2996                            // Scroll to the top-buttons element
2997                            topButtonsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
2998                        } else {
2999                            group.style.display = 'none';
3000                        }
3001                    });
3002
3003                    const nextModifierGroupButtonTop = document.querySelector('#nextModifierGroupButtonTop');
3004                    const nextModifierGroupButton = document.querySelector('#nextModifierGroupButton');
3005                    const addToCartButtonTop = document.querySelector('#addToCartButtonTop');
3006                    const addToCartButton = document.querySelector('#addToCartButton');
3007                    const backButtonTop = document.querySelector('#backButtonTop');
3008                    const backButton = document.querySelector('#backButton');
3009
3010                    if (currentModifierGroupIndex === modifierGroups.length - 1) {
3011                        if (nextModifierGroupButtonTop) nextModifierGroupButtonTop.style.display = 'none';
3012                        if (nextModifierGroupButton) nextModifierGroupButton.style.display = 'none';
3013                        if (addToCartButtonTop) addToCartButtonTop.style.display = 'block';
3014                        if (addToCartButton) addToCartButton.style.display = 'block';
3015                    } else {
3016                        if (nextModifierGroupButtonTop) nextModifierGroupButtonTop.style.display = 'block';
3017                        if (nextModifierGroupButton) nextModifierGroupButton.style.display = 'block';
3018                        if (addToCartButtonTop) addToCartButtonTop.style.display = 'none';
3019                        if (addToCartButton) addToCartButton.style.display = 'none';
3020                    }
3021
3022                    if (currentModifierGroupIndex > 0) {
3023                        if (backButtonTop) backButtonTop.style.display = 'block';
3024                        if (backButton) backButton.style.display = 'block';
3025                    } else {
3026                        if (backButtonTop) backButtonTop.style.display = 'none';
3027                        if (backButton) backButton.style.display = 'none';
3028                    }
3029                }
3030            }
3031
3032            // Function to move the top buttons back to their original position
3033            function moveTopButtonsBack() {
3034                const topButtonsContainer = document.getElementById('top-buttons');
3035                if (originalTopButtonsParent) {
3036                    originalTopButtonsParent.appendChild(topButtonsContainer);
3037                }
3038            }
3039
3040            function checkEmptyCake() {
3041                let somethingEmpty = false;
3042
3043                const selectors = [
3044                    '#cakeicecreamselect',
3045                    '#cakefillingselect',
3046                    '#cakecakeselect',
3047                    '#cakecolorselect'
3048                ];
3049
3050                selectors.forEach(selector => {
3051                    const $el = $(selector);
3052                    if ($el.is(':visible') && $el.val() === '') {
3053                        $el.animateCss('jello');
3054                        somethingEmpty = true;
3055                    }
3056                });
3057
3058                return somethingEmpty;
3059            }
3060
3061
3062            function checkEmptyPie() {
3063                let somethingEmpty = false;
3064
3065                if ($('#pieicecreamselect').val() == '') {
3066                    $('#pieicecreamselect').animateCss('jello');
3067                    somethingEmpty = true;
3068                }
3069
3070                if ($('#piefillingselect').val() == '') {
3071                    $('#piefillingselect').animateCss('jello');
3072                    somethingEmpty = true;
3073                }
3074
3075                //if ($('#piecrustselect').val() == '' && $("input[type='hidden'][id='hfProductSelected']").val() != 'Valentines Day Pie' && $("input[type='hidden'][id='hfProductSelected']").val() != 'Pink Valentines Day Pie' && $("input[type='hidden'][id='hfProductSelected']").val() != 'Red Valentines Day Pie') {
3076                //    $('#piecrustselect').animateCss('animated jello');
3077                //    somethingEmpty = true;
3078                //}
3079
3080                if ($('#piecrustselect').val() == '') {
3081                    $('#piecrustselect').animateCss('jello');
3082                    somethingEmpty = true;
3083                }
3084
3085                if ($('#piecolorselect').val() == '') {
3086                    $('#piecolorselect').animateCss('jello');
3087                    somethingEmpty = true;
3088                }
3089
3090                return somethingEmpty;
3091            }
3092
3093            //cake and pie continue listeners
3094            $(document).on('click', '.btn-cake-step1', function () {
3095                var $btn = $(this); // wrap this in jQuery to use jQuery methods
3096                var btnText = $btn.text(); // get the button's text value
3097
3098                if (!checkEmptyCake()) {
3099                    $("#modalCake1").modal('hide');
3100
3101
3102                    if (btnText != 'Add To Cart') {
3103                        $("#backButtonTop").hide();
3104                        $("#backButton").hide();
3105                        currentModifierGroupIndex++;
3106                        const itemModal = new bootstrap.Modal(document.getElementById('itemModal'));
3107                        itemModal.show();
3108                        showNextModifierGroup();
3109                    }
3110                    else {
3111                        //add it to the cart
3112                        addToCart();
3113                    }
3114
3115                }
3116
3117                              
3118                
3119            });
3120
3121            //cake and pie continue listeners
3122            $(document).on('click', '.btn-pie-step1', function () {
3123                var $btn = $(this); // wrap this in jQuery to use jQuery methods
3124                var btnText = $btn.text(); // get the button's text value
3125
3126                if (!checkEmptyPie()) {
3127
3128                    $("#modalPie1").modal('hide');
3129                    if (btnText != 'Add To Cart') {
3130                        $("#backButtonTop").hide();
3131                        $("#backButton").hide();
3132                        currentModifierGroupIndex++;
3133                        const itemModal = new bootstrap.Modal(document.getElementById('itemModal'));
3134                        itemModal.show();
3135                        showNextModifierGroup();
3136                    }
3137                    else {
3138                        //add it to the cart
3139                        addToCart();
3140                    }
3141                }
3142
3143
3144            });
3145
3146            // Event listeners for the Back buttons
3147            document.getElementById('backButton').addEventListener('click', function () {
3148                showPreviousModifierGroup();
3149            });
3150
3151            document.getElementById('backButtonTop').addEventListener('click', function () {
3152                showPreviousModifierGroup();
3153            });
3154
3155            // Event listeners for the buttons
3156            document.getElementById('nextModifierGroupButton').addEventListener('click', function () {
3157                if (validateModifierGroups(this)) {
3158                    currentModifierGroupIndex++;
3159                    moveTopButtonsBack();
3160                    showNextModifierGroup();
3161                }
3162            });
3163
3164            document.getElementById('nextModifierGroupButtonTop').addEventListener('click', function () {
3165                if (validateModifierGroups(this)) {
3166                    currentModifierGroupIndex++;
3167                    moveTopButtonsBack();
3168                    showNextModifierGroup();
3169                }
3170            });
3171
3172            document.getElementById('addToCartButton').addEventListener('click', function () {
3173                if (validateModifierGroups(this)) {
3174                    addToCart();
3175                    moveTopButtonsBack();
3176                }
3177            });
3178
3179            document.getElementById('addToCartButtonTop').addEventListener('click', function () {
3180                if (validateModifierGroups(this)) {
3181                    addToCart();
3182                    moveTopButtonsBack();
3183                }
3184            });
3185
3186            // Event listener for the modal close event to call moveTopButtonsBack()
3187            document.getElementById('itemModal').addEventListener('hidden.bs.modal', function () {
3188                moveTopButtonsBack();
3189            });
3190
3191            function validateModifierGroups(buttonElement) {
3192                if (!currentItem || !Array.isArray(currentItem.modifier_groups)) {
3193                    console.error('Invalid currentItem or modifier_groups not an array');
3194                    return false;
3195                }
3196
3197                // No modifier groups, skip validation
3198                if (currentItem.modifier_groups.length === 0) {
3199                    return true;
3200                }
3201
3202                // Check if currentModifierGroupIndex is valid
3203                if (typeof currentModifierGroupIndex !== 'number' ||
3204                    currentModifierGroupIndex < 0 ||
3205                    currentModifierGroupIndex >= currentItem.modifier_groups.length) {
3206                    console.error('Invalid modifier group index');
3207                    return false;
3208                }
3209
3210                const currentGroup = currentItem.modifier_groups[currentModifierGroupIndex];
3211
3212                if (!currentGroup || !Array.isArray(currentGroup.modifiers)) {
3213                    console.error('Invalid currentGroup or modifiers not an array');
3214                    return false;
3215                }
3216                console.log(currentGroup);
3217                console.log(currentGroup.modifiers);
3218
3219                let selectedCount = 0;
3220                let firstElement = null;
3221                let skipValidation = false;
3222
3223                // Check if the current group is a nested flavor group
3224                if (currentGroup.name === "Flavors" || currentGroup.name === "Select Flavor" || currentGroup.name === 'Flavor #1'  || currentGroup.name === 'Flavor #2'  || currentGroup.name === 'Flavor #3' ) {
3225                    currentGroup.modifiers.forEach(flavorGroup => {
3226                        if (flavorGroup.modifier_groups && flavorGroup.modifier_groups.length > 0) {
3227                            flavorGroup.modifier_groups[0].modifiers.forEach(modifier => {
3228                                const checkbox = document.getElementById(`modifier-${flavorGroup.name}-${modifier.id}`);
3229                                if (!firstElement) {
3230                                    firstElement = checkbox;
3231                                }
3232                                if (checkbox && checkbox.checked) {
3233                                    selectedCount++;
3234                                }
3235                            });
3236                        }
3237                    });
3238                } else {
3239                    currentGroup.modifiers.forEach(modifier => {
3240                        if (modifier.inputType === 'textarea') {
3241                            // Skip validation for optional input types like textarea
3242                            console.log('skip validation');
3243                            skipValidation = true;
3244                            return;
3245                        }
3246
3247                        if (currentGroup.name !== "Extras") {
3248                            const checkbox = document.getElementById(`modifier-${currentGroup.name}-${modifier.id}`);
3249                            if (!firstElement) {
3250                                firstElement = checkbox;
3251                            }
3252                            if (checkbox && checkbox.checked) {
3253                                selectedCount++;
3254                            }
3255                        } else {
3256                            const quantity = parseInt(document.getElementById(`quantity-${currentGroup.name}-${modifier.id}`).value);
3257                            if (!firstElement) {
3258                                firstElement = document.getElementById(`quantity-${currentGroup.name}-${modifier.id}`);
3259                            }
3260                            if (quantity > 0) {
3261                                selectedCount += quantity;
3262                            }
3263                        }
3264                    });
3265                }
3266
3267                if (skipValidation) {
3268                    return true;
3269                }
3270
3271                if (selectedCount < currentGroup.minimum_amount) {
3272                    showPopperAlert(`Please select at least ${currentGroup.minimum_amount} ${currentGroup.name}.`, buttonElement);
3273                    return false;
3274                } else if (selectedCount > currentGroup.maximum_amount) {
3275                    showPopperAlert(`Please select no more than ${currentGroup.maximum_amount} ${currentGroup.name}.`, buttonElement);
3276                    return false;
3277                }
3278
3279                return true;
3280            }
3281
3282
3283            const confirmationModalElement = document.getElementById('confirmationModal');
3284            const continueShoppingButton = document.getElementById('continueShoppingButton');
3285            const checkoutButtonConfirmation = document.getElementById('checkoutButtonConfirmation');
3286            const itemModalElement = document.getElementById('itemModal');
3287            const cartModalElement = document.getElementById('cartModal');
3288            let confirmationModal;
3289            let itemModal;
3290            let cartModal;
3291
3292            // Show confirmation modal
3293            function showConfirmationModal() {
3294                confirmationModal = new bootstrap.Modal(confirmationModalElement);
3295                confirmationModal.show();
3296            }
3297
3298            // Add event listeners for modal buttons
3299            continueShoppingButton.addEventListener('click', function () {
3300                confirmationModal.hide();
3301                //window.scrollTo({ top: 0, behavior: 'smooth' });
3302            });
3303
3304            checkoutButtonConfirmation.addEventListener('click', function () {
3305                confirmationModal.hide();
3306                cartModal = new bootstrap.Modal(cartModalElement);
3307                cartModal.show();
3308            });
3309
3310            // Add to cart function
3311            function addToCart() {
3312                var selectedModifiers = [];
3313                var selectedExtras = [];
3314
3315                var blnNestedFlavors = false;
3316                if (getQueryStringParameter('number') != '999999'){
3317                    blnNestedFlavors = true;
3318                }
3319
3320                var parentQty = $("#itemQuantity").val() && parseInt($("#itemQuantity").val()) > 0
3321                ? parseInt($("#itemQuantity").val())
3322                : 1;
3323
3324                if (!isPie && !isCake) {
3325                currentItem.modifier_groups.forEach(group => {
3326
3327                    if (
3328                        group.name === "Flavors" ||
3329                        group.name === "Select Flavor" ||
3330                        (group.name === "Flavor #1" && blnNestedFlavors) ||
3331                        (group.name === "Flavor #2" && blnNestedFlavors) ||
3332                        (group.name === "Flavor #3" && blnNestedFlavors)
3333                    ) {
3334
3335            group.modifiers.forEach(flavorGroup => {
3336
3337                if (flavorGroup.modifier_groups && flavorGroup.modifier_groups.length > 0) {
3338
3339                    flavorGroup.modifier_groups[0].modifiers.forEach(modifier => {
3340
3341                        const checkbox = document.getElementById(
3342                            `modifier-${flavorGroup.name}-${modifier.id}`
3343                        );
3344
3345                        if (checkbox && checkbox.checked) {
3346
3347                            const flavorQty = parseInt(
3348                                checkbox.dataset.flavorQty || "1",
3349                                10
3350                            );
3351
3352                            for (let i = 0; i < flavorQty; i++) {
3353
3354                                selectedModifiers.push({
3355                                    id: modifier.id,
3356                                    name: modifier.name,
3357                                    price: modifier.price,
3358                                    tax: currentItem.tax_rate,
3359                                    group: group.name,
3360                                    quantity: 1
3361                                });
3362
3363                            }
3364                        }
3365                    });
3366                }
3367            });
3368
3369        } else {
3370                        group.modifiers.forEach(modifier => {
3371                            if (modifier.inputType === 'textarea') {
3372                                const textarea = document.getElementById(`modifier-${group.name}-${modifier.id}`);
3373                                if (textarea && textarea.value.trim() !== "") {
3374                                    selectedModifiers.push({
3375                                        id: modifier.id,
3376                                        name: textarea.value.trim(),
3377                                        value: textarea.value.trim(), // Capture the textarea value
3378                                        price: modifier.price,
3379                                        tax: currentItem.tax_rate,
3380                                        group:group.name,
3381                                        quantity: 1
3382                                    });
3383                                }
3384                            } else if (group.name !== "Extras") {
3385                                const checkbox = document.getElementById(`modifier-${group.name}-${modifier.id}`);
3386                                if (checkbox && checkbox.checked) {
3387                                    selectedModifiers.push({
3388                                        id: modifier.id,
3389                                        name: modifier.name,
3390                                        price: modifier.price,
3391                                        tax: currentItem.tax_rate,
3392                                        group:group.name,
3393                                        quantity: 1
3394                                    });
3395                                }
3396                            } else {
3397                                const quantity = parseInt(document.getElementById(`quantity-${group.name}-${modifier.id}`).value);
3398                                if (quantity > 0) {
3399                                    //changing to include actual extra tax here
3400                                    //change tax from currentItem.tax_rate to modifier.tax
3401                                   
3402                                    selectedExtras.push({
3403                                        id: modifier.id,
3404                                        name: modifier.name,
3405                                        price: modifier.price,
3406                                        tax: modifier.tax,
3407                                        group:group.name,
3408                                        quantity: quantity
3409                                    });
3410                                }
3411                            }
3412                        });
3413                    }
3414                });
3415                }
3416                else if (isCake) {
3417                    //get the modifiers from the modal
3418                    // Iterate over the range
3419                    for (var i = 0; i < 6; i++) {
3420                        switch (i) {
3421                            case 0:
3422                                // flavor
3423                                console.log("Case 0");
3424                                // Your logic for case 0
3425                                var icecreamflavor = $('#cakeicecreamselect').val();
3426                                var itemid = $('#cakeicecreamselect').attr('data-item-id');
3427                                selectedModifiers.push({
3428                                    id: itemid,
3429                                    name: icecreamflavor,
3430                                    price: 0,
3431                                    tax: 0,
3432                                    group: 'Ice Cream Flavor',
3433                                    quantity: 1
3434                                });
3435                                break;
3436                            case 1:
3437                                // cake type
3438                                console.log("Case 1");
3439                                // Your logic for case 1
3440                                var icecreamflavor = $('#cakecakeselect').val();
3441                                var itemid = $('#cakecakeselect').attr('data-item-id');
3442                                selectedModifiers.push({
3443                                    id: itemid,
3444                                    name: icecreamflavor,
3445                                    price: 0,
3446                                    tax: 0,
3447                                    group: 'Cake Flavor',
3448                                    quantity: 1
3449                                });
3450                                break;
3451                            case 2:
3452                                // filling type
3453                                console.log("Case 2");
3454                                // Your logic for case 2
3455                                var icecreamflavor = $('#cakefillingselect').val();
3456                                var itemid = $('#cakefillingselect').attr('data-item-id');
3457                                selectedModifiers.push({
3458                                    id: itemid,
3459                                    name: icecreamflavor,
3460                                    price: 0,
3461                                    tax: 0,
3462                                    group: 'Filling Flavor',
3463                                    quantity: 1
3464                                });
3465                                break;
3466                            case 3:
3467                                // color type
3468                                console.log("Case 3");
3469                                // Your logic for case 3
3470                                var icecreamflavor = $('#cakecolorselect').val();
3471                                var itemid = $('#cakecolorselect').attr('data-item-id');
3472                                selectedModifiers.push({
3473                                    id: itemid,
3474                                    name: icecreamflavor,
3475                                    price: 0,
3476                                    tax: 0,
3477                                    group: 'Cake Color',
3478                                    quantity: 1
3479                                });
3480                                break;
3481                            case 4:
3482                                // message
3483                                console.log("Case 4");
3484                                // Your logic for case 4
3485                                var icecreamflavor = $("textarea[id='cakemessage']").val();
3486                                var itemid = $('#cakeicecreamselect').attr('data-item-id');
3487                                selectedModifiers.push({
3488                                    id: 'cakemessage',
3489                                    name: icecreamflavor,
3490                                    price: 0,
3491                                    tax: 0,
3492                                    group: 'Cake Message',
3493                                    quantity: 1
3494                                });
3495                                break;
3496                            case 5:
3497                                // grab the extras now if any...
3498                                console.log("Case 5");
3499                                // Your logic for case 4
3500                                currentItem.modifier_groups.forEach(group => {
3501                                    if (group.name === "Extras") {
3502                                        group.modifiers.forEach(modifier => {                                           
3503                                                const quantity = parseInt(document.getElementById(`quantity-${group.name}-${modifier.id}`).value);
3504                                                if (quantity > 0) {
3505
3506                                                    //changing to include actual extra tax here
3507                                                    //change tax from currentItem.tax_rate to modifier.tax
3508                                                    // If user selects "All Ice Cream Upcharge", remove "Cake Flavor" from selectedModifiers
3509                                                    console.log(modifier);
3510                                                    if (modifier.name === "All Ice Cream Upcharge") {
3511                                                        console.log('removing cake');
3512                                                        selectedModifiers = selectedModifiers.filter(mod => mod.group !== "Cake Flavor");
3513                                                    }
3514
3515                                                    selectedExtras.push({
3516                                                        id: modifier.id,
3517                                                        name: modifier.name,
3518                                                        price: modifier.price,
3519                                                        tax: currentItem.tax_rate,
3520                                                        group: group.name,                                                        quantity: quantity
3521                                                    });
3522                                                }
3523                                            
3524                                        });
3525                                    } 
3526                                });
3527                                break;
3528                            default:
3529                                // Handle default case if needed
3530                                console.log("Default case");
3531                                break;
3532                        }
3533                    }
3534
3535
3536                }
3537                else if (isPie) {
3538                    ///get the modifiers from the modal
3539                    for (var i = 0; i < 6; i++) {
3540                        switch (i) {
3541                            case 0:
3542                                // flavor
3543                                console.log("Case 0");
3544                                // Your logic for case 0
3545                                var icecreamflavor = $('#pieicecreamselect').val();
3546                                var itemid = $('#pieicecreamselect').attr('data-item-id');
3547                                selectedModifiers.push({
3548                                    id: itemid,
3549                                    name: icecreamflavor,
3550                                    price: 0,
3551                                    tax: 0,
3552                                    group: 'Ice Cream Flavor',
3553                                    quantity: 1
3554                                });
3555                                break;
3556                            case 1:
3557                                // cake type
3558                                console.log("Case 1");
3559                                // Your logic for case 1
3560                                var icecreamflavor = $('#piecrustselect').val();
3561                                var itemid = $('#piecrustselect').attr('data-item-id');
3562                                selectedModifiers.push({
3563                                    id: itemid,
3564                                    name: icecreamflavor,
3565                                    price: 0,
3566                                    tax: 0,
3567                                    group: 'Crust Flavor',
3568                                    quantity: 1
3569                                });
3570                                break;
3571                            case 2:
3572                                // filling type
3573                                console.log("Case 2");
3574                                // Your logic for case 2
3575                                var icecreamflavor = $('#piefillingselect').val();
3576                                var itemid = $('#piefillingselect').attr('data-item-id');
3577                                selectedModifiers.push({
3578                                    id: itemid,
3579                                    name: icecreamflavor,
3580                                    price: 0,
3581                                    tax: 0,
3582                                    group: 'Filling Flavor',
3583                                    quantity: 1
3584                                });
3585                                break;
3586                            case 3:
3587                                // color type
3588                                console.log("Case 3");
3589                                // Your logic for case 3
3590                                var icecreamflavor = $('#piecolorselect').val();
3591                                var itemid = $('#piecolorselect').attr('data-item-id');
3592                                selectedModifiers.push({
3593                                    id: itemid,
3594                                    name: icecreamflavor,
3595                                    price: 0,
3596                                    tax: 0,
3597                                    group: 'Pie Color',
3598                                    quantity: 1
3599                                });
3600                                break;
3601                            case 4:
3602                                // message
3603                                console.log("Case 4");
3604                                // Your logic for case 4
3605                                var icecreamflavor = $("textarea[id='piemessage']").val();
3606                                var itemid = $('#cakeicecreamselect').attr('data-item-id');
3607                                selectedModifiers.push({
3608                                    id: 'piemessage',
3609                                    name: icecreamflavor,
3610                                    price: 0,
3611                                    tax: 0,
3612                                    group: 'Pie Message',
3613                                    quantity: 1
3614                                });
3615                                break;
3616                            case 5:
3617                                // grab the extras now if any...
3618                                console.log("Case 5");
3619                                // Your logic for case 4
3620                                currentItem.modifier_groups.forEach(group => {
3621                                    if (group.name === "Extras") {
3622                                        group.modifiers.forEach(modifier => {
3623                                            const quantity = parseInt(document.getElementById(`quantity-${group.name}-${modifier.id}`).value);
3624                                            if (quantity > 0) {
3625                                                selectedExtras.push({
3626                                                    id: modifier.id,
3627                                                    name: modifier.name,
3628                                                    price: modifier.price,
3629                                                    tax: currentItem.tax_rate,
3630                                                    group: group.name,
3631                                                    quantity: quantity
3632                                                });
3633                                            }
3634
3635                                        });
3636                                    }
3637                                });
3638                                break;
3639                            default:
3640                                // Handle default case if needed
3641                                console.log("Default case");
3642                                break;
3643                        }
3644                    }
3645                }
3646
3647               
3648                for (var i = 0; i < parentQty; i++) {
3649
3650                    cart.push({
3651                        id: currentItem.id,
3652                        name: currentItem.name,
3653                        price: currentItem.price,
3654                        taxRate: currentItem.tax_rate,
3655                        quantity: 1, // Each line is a single item
3656                        modifiers: JSON.parse(JSON.stringify(selectedModifiers)), // deep copy
3657                        extras: JSON.parse(JSON.stringify(selectedExtras)), // deep copy
3658                        leadTimeRequired: currentItem.leadTimeRequired,
3659                        location: $("#hiddenFieldAddress").val().replace('Ordering for Pick Up From: ','')
3660                    });
3661
3662                }
3663
3664                
3665                // Persist the updated cart
3666                saveCart();
3667
3668                var newCartItems = cart.slice(-parentQty);
3669
3670        try {
3671            var ga4Items = [];
3672
3673            newCartItems.forEach(function (item) {
3674                ga4Items = ga4Items.concat(buildGA4Items(item));
3675            });
3676
3677            var totalValue = ga4Items.reduce(function (sum, item) {
3678                return sum + (Number(item.price || 0) * Number(item.quantity || 0));
3679            }, 0);
3680
3681        if (
3682            window.GTM &&
3683            typeof window.GTM.pushEvent === "function"
3684        ) {
3685            window.GTM.pushEvent({
3686                event: "add_to_cart",
3687                store_number: getStoreNumber(),
3688                ecommerce: {
3689                    currency: "USD",
3690                    value: Number(totalValue.toFixed(2)),
3691                    items: ga4Items
3692                }
3693            });
3694            } else {
3695                console.warn(
3696                    "GTM add_to_cart event skipped because window.GTM.pushEvent is unavailable."
3697                );
3698            }
3699            } catch (error) {
3700                console.error("Unable to send GTM add_to_cart event:", error);
3701            }
3702
3703            /*
3704                * Cart functionality must continue even when analytics fails.
3705                */
3706            renderCart();
3707
3708            try {
3709                const itemModal = bootstrap.Modal.getInstance(
3710                    document.getElementById("itemModal")
3711                );
3712
3713                if (itemModal) {
3714                    itemModal.hide();
3715                }
3716            } catch (error) {
3717                console.error("Error hiding itemModal:", error);
3718            }
3719
3720            showConfirmationModal();
3721            }
3722
3723            document.getElementById('cartIcon').addEventListener('click', function () {
3724                const cartModal = new bootstrap.Modal(document.getElementById('cartModal'));
3725                cartModal.show();
3726            });
3727
3728            renderMenu(menuData);
3729        });
3730
3731        function showFlavorImage(flavorName, imageUrl, checkboxId, event) {
3732            // Prevent default action and stop propagation
3733            event.preventDefault();
3734            event.stopPropagation();
3735
3736            const popperContainer = document.getElementById('popper-container');
3737            popperContainer.innerHTML = `<div class="popper-image" id="flavorImagePopper">
3738                                            <div class="popper-close" onclick="closePopper()">×</div>
3739                                            <strong>${flavorName}</strong>
3740                                            <img src="${imageUrl}" alt="${flavorName}">
3741                                        </div>`;
3742
3743            const flavorImagePopper = document.getElementById('flavorImagePopper');
3744            const checkboxElement = document.getElementById(checkboxId);
3745
3746            Popper.createPopper(checkboxElement, flavorImagePopper, {
3747                placement: 'top',
3748                modifiers: [{
3749                    name: 'offset',
3750                    options: {
3751                        offset: [0, 8],
3752                    },
3753                }],
3754            });
3755        }
3756
3757        function closePopper() {
3758            const popperContainer = document.getElementById('popper-container');
3759            popperContainer.innerHTML = '';
3760        }
3761
3762        function renderCart() {
3763            const cartModalBody = document.getElementById('cartModalBody');
3764            const cartItemCount = document.getElementById('cartItemCount');
3765            const cartSubtotal = document.getElementById('cartSubtotal');
3766            const cartTax = document.getElementById('cartTax');
3767            const cartTotal = document.getElementById('cartTotal');
3768
3769            if (cart.length === 0) {
3770                cartModalBody.innerHTML = '<p>Your cart is empty.</p>';
3771                cartItemCount.textContent = '0';
3772                cartSubtotal.textContent = 'Subtotal: $0.00';
3773                cartTax.textContent = 'Tax: $0.00';
3774                cartTotal.textContent = 'Total: $0.00';
3775                return;
3776            }
3777
3778            let subtotal = 0;
3779            let tax = 0;
3780
3781            const cartItemsHtml = cart.map((item, index) => {
3782                const itemSubtotal = item.price * item.quantity;
3783                let itemTax = itemSubtotal * (item.taxRate / 100);
3784
3785                const modifiersHtml = item.modifiers.map(modifier => {
3786                    const modifierSubtotal = modifier.price * modifier.quantity;
3787                    const modifierTax = modifierSubtotal * (modifier.tax / 100);
3788                    subtotal += modifierSubtotal;
3789                    tax += modifierTax;
3790                    return `
3791                    <div class="cart-item-modifier">
3791${modifier.name} ${modifier.price > 0 ? `- $${modifier.price.toFixed(2)}` : ''}</div>
3792                `;
3793                }).join('');
3794
3795                const extrasHtml = item.extras.map(extra => {
3796                    const extraSubtotal = extra.price * extra.quantity;
3797                    const extraTax = extraSubtotal * (extra.tax / 100);
3798                    subtotal += extraSubtotal;
3799                    tax += extraTax;
3800                    return `
3801                    <div class="cart-item-extra">${extra.quantity} x ${extra.name} ${extra.price > 0 ? `- $${extra.price.toFixed(2)}` : ''}</div>
3802                `;
3803                }).join('');
3804
3805                subtotal += itemSubtotal;
3806                tax += itemTax;
3807
3808                return `
3809                <div class="cart-item">
3810                    <div class="cart-item-details">
3811                        <div class="cart-item-name">
3812                            ${item.name} ${item.price > 0 ? `- $${item.price.toFixed(2)}` : ''}
3813                            ${item.quantity > 1 ? `<div class="cart-item-quantity">Quantity: ${item.quantity}</div>` : ''}
3814                        </div>
3815                        ${modifiersHtml}
3816                        ${extrasHtml}
3817                    </div>
3818                    <button class="btn btn-danger btn-sm" onclick="removeFromCart(${index})">Remove</button>
3819                </div>
3820            `;
3821            }).join('');
3822
3823            cartModalBody.innerHTML = cartItemsHtml;
3824            cartItemCount.textContent = cart.length.toString();
3825            cartSubtotal.textContent = `Subtotal: $${subtotal.toFixed(2)}`;
3826            cartTax.textContent = `Tax: $${tax.toFixed(2)}`;
3827            cartTotal.textContent = `Total: $${(subtotal + tax).toFixed(2)}`;
3828
3829            // Pass the total amount to the hidden field
3830            document.getElementById('cartTotalAmount').value = (subtotal + tax).toFixed(2);
3831        }
3832
3833
3834
3835
3836
3837        // Event listener for the checkout button
3838        document.getElementById('checkoutButton').addEventListener('click', function () {
3839
3840            // Inject mandatory items into cart only if they don't already exist
3841            try {
3842                const mandatoryItemsJson = document.getElementById('hfMandatoryItems').value;
3843                const mandatoryItems = JSON.parse(mandatoryItemsJson);
3844
3845                mandatoryItems.forEach(item => {
3846                    const alreadyInCart = cart.some(cartItem => cartItem.id === item.ItemId);
3847
3848                    if (!alreadyInCart) {
3849                        cart.push({
3850                            id: item.ItemId,
3851                            name: item.ItemName,
3852                            price: item.Price,
3853                            taxRate: item.Tax,
3854                            quantity: item.Qty,
3855                            modifiers: [],
3856                            extras: [],
3857                            leadTimeRequired: false,
3858                            location: $("#hiddenFieldAddress").val().replace('Ordering for Pick Up From: ', '')
3859                        });
3860                    }
3861                });
3862            } catch (err) {
3863                console.error("Failed to parse mandatory items:", err);
3864            }
3865
3866            const cartModal = bootstrap.Modal.getInstance(document.getElementById('cartModal'));
3867            cartModal.hide();
3868            const checkoutModal = new bootstrap.Modal(document.getElementById('checkoutModal'));
3869
3870            // Pass the total amount to the checkout modal
3871            const totalAmount = calculateTotalAmount();
3872            document.getElementById('cartTotalAmount').value = totalAmount.toFixed(2);
3873
3874            // Populate order details
3875            const orderDetailsContainer = document.getElementById('orderDetails');
3876            orderDetailsContainer.innerHTML = generateOrderDetailsHtml(cart);
3877
3878            // Populate total amount
3879            const totalAmountContainer = document.getElementById('totalAmount');
3880            totalAmountContainer.innerHTML = `Total Amount: $${totalAmount.toFixed(2)}`;
3881
3882            checkoutModal.show();
3883        });
3884
3885        function generateOrderDetailsHtml(cart) {
3886    let mainItemSubtotal = 0;
3887    let extrasSubtotal = 0;
3888
3889    let location = "";
3890    let pickupTime = "";
3891    let orderTip = 0;
3892
3893    let orderTax = 0;
3894    let orderTotal = 0;
3895    let orderDiscount = 0;
3896
3897    let useBackendTotals = false;
3898
3899    // 🔥 Get backend JSON
3900    let detailsJson = $("input[type='hidden'][id$='hfJsonOrder']").val();
3901
3902    let details = [];
3903
3904    try {
3905        details = JSON.parse(detailsJson || "[]");
3906    } catch (e) {
3907        console.log("Invalid JSON in hfJsonOrder.");
3908    }
3909
3910    // 🔥 Determine if backend totals exist
3911    if (
3912        details.length > 0 &&
3913        typeof details[0].order_total === "number"
3914    ) {
3915        location = details[0]?.location || "";
3916        pickupTime = details[0]?.datetime || "";
3917        orderTip = parseFloat(details[0]?.tip) || 0;
3918
3919        orderTax = parseFloat(details[0]?.order_tax) || 0;
3920        orderTotal = parseFloat(details[0]?.order_total) || 0;
3921        orderDiscount = parseFloat(details[0]?.order_discount) || 0;
3922
3923        useBackendTotals = true;
3924    }
3925
3926    // 🔥 Build item + extras UI
3927    const cartHtml = cart.map(item => {
3928
3929        const itemPrice = parseFloat(item.price) || 0;
3930        const itemQuantity = parseInt(item.quantity, 10) || 0;
3931        const itemSubtotal = itemPrice * itemQuantity;
3932
3933        mainItemSubtotal += itemSubtotal;
3934
3935        const modifiersHtml = (item.modifiers || []).map(modifier => {
3936            return `<div>
3936${modifier.name} ${modifier.price > 0 ? `- $${modifier.price.toFixed(2)}` : ''}</div>`;
3937        }).join('');
3938
3939        const extrasHtml = (item.extras || []).map(extra => {
3940            const extraPrice = parseFloat(extra.price) || 0;
3941            const extraQuantity = parseInt(extra.quantity, 10) || 0;
3942            const extraSubtotal = extraPrice * extraQuantity;
3943
3944            extrasSubtotal += extraSubtotal;
3945
3946            return `<div>${extraQuantity} x ${extra.name} ${extraPrice > 0 ? `- $${extraPrice.toFixed(2)}` : ''}</div>`;
3947        }).join('');
3948
3949        return `
3950            <div>
3951                <strong>${item.name}</strong> ${itemPrice > 0 ? `- $${itemPrice.toFixed(2)}` : ''}
3952                ${itemQuantity > 1 ? `<div>Quantity: ${itemQuantity}</div>` : ''}
3953                ${modifiersHtml}
3954                ${extrasHtml}
3955            </div>
3956            <hr>
3957        `;
3958    }).join('');
3959
3960    const subtotal = mainItemSubtotal + extrasSubtotal;
3961
3962    // 🔥 FRONTEND fallback calculation (only when backend not available)
3963    if (!useBackendTotals) {
3964        let tempTax = 0;
3965
3966        cart.forEach(item => {
3967            const itemPrice = parseFloat(item.price) || 0;
3968            const itemQuantity = parseInt(item.quantity, 10) || 0;
3969            const itemTaxRate = parseFloat(item.taxRate) || 0;
3970
3971            const itemSubtotal = itemPrice * itemQuantity;
3972            tempTax += itemSubtotal * (itemTaxRate / 100);
3973
3974            (item.extras || []).forEach(extra => {
3975                const extraPrice = parseFloat(extra.price) || 0;
3976                const extraQuantity = parseInt(extra.quantity, 10) || 0;
3977                const extraTaxRate = parseFloat(extra.tax) || 0;
3978
3979                const extraSubtotal = extraPrice * extraQuantity;
3980                tempTax += extraSubtotal * (extraTaxRate / 100);
3981            });
3982        });
3983
3984        orderTax = tempTax;
3985        orderDiscount = 0;
3986        orderTotal = subtotal + orderTax + orderTip;
3987    }
3988
3989    // 🔥 IMPORTANT: if backend total already includes tip, DO NOT add again
3990    const finalTotal = orderTotal; // adjust if needed
3991
3992    const summaryHtml = `
3993        <div><strong>Subtotal:</strong> $${subtotal.toFixed(2)}</div>
3994        ${orderDiscount > 0 ? `<div><strong>Discount:</strong> -$${orderDiscount.toFixed(2)}</div>` : ''}
3995        <div><strong>Tax:</strong> $${orderTax.toFixed(2)}</div>
3996        ${orderTip > 0 ? `<div><strong>Tip:</strong> $${orderTip.toFixed(2)}</div>` : ''}
3997        <div><strong>Total:</strong> $${finalTotal.toFixed(2)}</div>
3998    `;
3999
4000    let pickupHtml = "";
4001
4002    if (location) {
4003        pickupHtml += `<hr><br/><div><strong>Pickup Location:</strong> ${location}</div>`;
4004    }
4005
4006    if (pickupTime) {
4007        pickupHtml += `<div><strong>Pickup Time:</strong> ${pickupTime}</div>`;
4008    }
4009
4010    return cartHtml + summaryHtml + pickupHtml;
4011}
4012
4013
4014
4015        
4016        document.getElementsByName('scooperTip').forEach(tipRadio => {
4017            tipRadio.addEventListener('change', function () {
4018                const tipOtherAmount = document.getElementById('tipOtherAmount');
4019                //const totalAmount = parseFloat(document.getElementById('cartTotalAmount').value); // Get the total amount passed from the ShoppingCart modal
4020                const totalAmount = parseFloat(document.getElementById('cartSubTotalAmount').value); // Get the total amount passed from the ShoppingCart modal
4021                if (this.value === 'Other') {
4022                    tipOtherAmount.classList.remove('d-none');
4023                    tipOtherAmount.value = ''; // Clear the input when 'Other' is selected
4024                    tipOtherAmount.focus();
4025                } else {
4026                    tipOtherAmount.classList.remove('d-none');
4027                    let tipPercentage = 0;
4028                    if (this.value === '15%') {
4029                        tipPercentage = 0.15;
4030                    } else if (this.value === '20%') {
4031                        tipPercentage = 0.20;
4032                    } else if (this.value === '25%') {
4033                        tipPercentage = 0.25;
4034                    }
4035                    tipOtherAmount.value = (totalAmount * tipPercentage).toFixed(2);
4036                }
4037            });
4038        });
4039
4040        // Function to calculate the total amount
4041        function calculateTotalAmount() {
4042            let subtotal = 0;
4043            let tax = 0;
4044
4045            cart.forEach(item => {
4046                subtotal += item.price * item.quantity;
4047                tax += (item.price * item.quantity) * (item.taxRate / 100);
4048
4049                item.modifiers.forEach(modifier => {
4050                    subtotal += modifier.price * modifier.quantity;
4051                    tax += (modifier.price * modifier.quantity) * (modifier.tax / 100);
4052                });
4053
4054                item.extras.forEach(extra => {
4055                    subtotal += extra.price * extra.quantity;
4056                    tax += (extra.price * extra.quantity) * (extra.tax / 100);
4057                });
4058            });
4059            document.getElementById('cartSubTotalAmount').value = subtotal.toFixed(2);
4060            return subtotal + tax;
4061        }
4062
4063    </script>
4063
4064    
4064<script type="text/javascript">
4065
4066        function getQueryStringParameter(name) {
4067            const urlParams = new URLSearchParams(window.location.search);
4068            return urlParams.get(name);
4069        }
4070
4071        const inputElement = document.getElementById('tipOtherAmount');
4072
4073        inputElement.addEventListener('input', function (e) {
4074            // Remove invalid characters (anything that's not a digit or a single decimal point)
4075            const value = e.target.value;
4076
4077            // Allow only numbers and a single decimal point
4078            const validValue = value
4079                .replace(/[^0-9.]/g, '') // Remove non-numeric characters except '.'
4080                .replace(/(\..*?)\./g, '$1'); // Allow only one '.'
4081
4082            e.target.value = validValue;
4083        });
4084
4085
4086        var picker;
4087
4088         function validateLeadTime() {
4089
4090    if (!picker || !picker.dates) return false;
4091
4092    var selectedDateTime = (picker && picker.dates) ? picker.dates.lastPicked : null;
4093    var dateSelected = null;
4094
4095    // 🔥 Try picker first
4096    if (selectedDateTime && typeof selectedDateTime.toJSDate === "function") {
4097        dateSelected = selectedDateTime.toJSDate();
4098    }
4099
4100    // 🔥 Fallback to input (VERY important in WebView)
4101    if (!dateSelected) {
4102        var inputEl = document.querySelector('#pickupDateTimePicker input');
4103        var inputVal = inputEl ? inputEl.value : null;
4104
4105        if (inputVal) {
4106            dateSelected = new Date(inputVal);
4107        }
4108    }
4109
4110    // 🔥 Final guard
4111    if (!dateSelected || isNaN(dateSelected.getTime())) {
4112        console.log("Invalid dateSelected");
4113        return false;
4114    }
4115
4116    var leadTimeHours = parseInt($("input[type='hidden'][id$='hiddenFieldLeadTime']").val(), 10);
4117
4118    if (isNaN(leadTimeHours) || leadTimeHours <= 0) {
4119        console.log("Invalid leadTimeHours");
4120        return false;
4121    }
4122
4123    var currentDateTime = new Date();
4124    var leadTimeDate = new Date(currentDateTime.getTime() + (leadTimeHours * 60 * 60 * 1000));
4125
4126    console.log("Selected:", dateSelected);
4127    console.log("Required after:", leadTimeDate);
4128
4129    return dateSelected >= leadTimeDate;
4130}
4131
4132        $(document).ready(function () {
4133
4134            $(document).on('show.bs.modal', '.modal', function (event) {
4135                this._modalTrigger = event.relatedTarget || document.activeElement;
4136            });
4137
4138            $(document).on('hidden.bs.modal', '.modal', function () {
4139                const trigger = this._modalTrigger;
4140
4141                if (trigger && document.contains(trigger)) {
4142                    trigger.focus();
4143                }
4144
4145                this._modalTrigger = null;
4146            });
4147
4148
4149            $(document).on('input', 'textarea[id^="modifier-Custom Message"]', function () {
4150                var maxLength = 30;
4151                var currentVal = $(this).val();
4152                if (currentVal.length > maxLength) {
4153                    $(this).val(currentVal.substring(0, maxLength));
4154                }
4155            });
4156
4157
4158            //if (!getQueryStringParameter('number')){
4159            //    var footer = document.querySelector('.mondelezfooter');
4160            //    if (footer) {
4161            //        footer.style.position = 'fixed';
4162            //        footer.style.bottom = '5px';
4163            //        footer.style.left = '0';
4164            //        footer.style.right = '0';
4165            //        footer.style.margin = '0 auto';
4166            //        footer.style.width = '100%';
4167            //        footer.style.zIndex = '1030';
4168            //    }
4169            //}
4170            //else {
4171            //    var footer = document.querySelector('.mondelezfooter');
4172            //    if (footer) {
4173            //        footer.removeAttribute('style');
4174            //    }
4175            //}
4176
4177            function pinFooters(selectors) {
4178                var bottomOffset = 5; // starting offset from bottom
4179                var spacing = 50;     // vertical space per footer
4180
4181                selectors.forEach(function (selector) {
4182                    var el = document.querySelector(selector);
4183                    if (!el) return;
4184
4185                    el.style.position = 'fixed';
4186                    el.style.bottom = bottomOffset + 'px';
4187                    el.style.left = '0';
4188                    el.style.right = '0';
4189                    el.style.margin = '0 auto';
4190                    el.style.width = '100%';
4191                    el.style.zIndex = '1030';
4192
4193                    bottomOffset += spacing;
4194                });
4195            }
4196
4197            function resetFooters(selectors) {
4198                selectors.forEach(function (selector) {
4199                    var el = document.querySelector(selector);
4200                    if (el) el.removeAttribute('style');
4201                });
4202            }
4203
4204            var hasNumber = getQueryStringParameter('number');
4205
4206            var pinnedFooters = [
4207                '.mondelezfooter'
4208            ];
4209
4210            var allergen = document.querySelector('.allergenfooter');
4211
4212            if (!hasNumber) {
4213                // ✅ Pin ONLY Mondelez footer
4214                pinFooters(pinnedFooters);
4215
4216                // ❌ Hide allergen footer
4217                if (allergen) allergen.style.display = 'none';
4218            } else {
4219                // Restore everything
4220                resetFooters([
4221                    '.mondelezfooter',
4222                    '.allergenfooter'
4223                ]);
4224
4225                if (allergen) allergen.style.display = '';
4226            }
4227
4228
4229
4230          
4231
4232            $('#pickupDateTimePicker input').attr('readonly', true); // Prevent manual typing
4233
4234            $('.restrictemojis').on('input paste', function () {
4235                // Delay the handling to ensure the pasted content is processed
4236                setTimeout(() => {
4237                    var value = $(this).val();
4238                    var cleanValue = value.replace(/[\u{1F600}-\u{1F6FF}\u{2600}-\u{26FF}\u{1F300}-\u{1F5FF}\u{1F900}-\u{1F9FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{2700}-\u{27BF}\u{1F1E0}-\u{1F1FF}\u{1F900}-\u{1F9FF}\u{1FA70}-\u{1FAFF}\u{1F600}-\u{1F64F}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{1FB00}-\u{1FBFF}\u{1FC00}-\u{1FCFF}\u{1FD00}-\u{1FDFF}\u{1FE00}-\u{1FE0F}\u{1FE10}-\u{1FE1F}\u{1FE30}-\u{1FE4F}\u{1FE50}-\u{1FE6F}\u{1FE70}-\u{1FEFF}\u{1FF00}-\u{1FFEF}\u{1FFF0}-\u{1FFFF}]/gu, '');
4239                    $(this).val(cleanValue);
4240                }, 0);
4241            });
4242
4243            $.fn.extend({
4244                animateCss: function (animationName, callback) {
4245                    const animationEnd = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend';
4246                    this.addClass('animate__animated animate__' + animationName).one(animationEnd, function () {
4247                        $(this).removeClass('animate__animated animate__' + animationName);
4248                        if (callback) {
4249                            callback();
4250                        }
4251                    });
4252                    return this;
4253                }
4254            });
4255
4256
4257            $('#searchButton').on('click', function (e) {
4258                e.preventDefault();
4259                $(".loading").show();
4260                var search = $("input[type='text'][id='zipcode']").val();
4261                var searchurl = '/API/OnlineOrderStoreSearchZip.aspx?search=' + search;
4262
4263                $.getJSON(searchurl, function (data) {
4264                    $("#divstores").empty();
4265                    $(".list-group-item", $("#divstores")).remove();
4266                    var outerHtml = $("#divstoresclone .list-group-item").prop('outerHTML');
4267                    if (data.length > 0) {
4268                        var checkOlo = 0;
4269                        var currentPageUrl = window.location.href.split('?')[0]; // Get the current page URL without query string
4270
4271                        // Function to get query parameter value by name (compatible with older browsers)
4272                        function getQueryParamValue(name) {
4273                            var query = window.location.search.substring(1);
4274                            var vars = query.split('&');
4275                            for (var i = 0; i < vars.length; i++) {
4276                                var pair = vars[i].split('=');
4277                                if (decodeURIComponent(pair[0]) === name) {
4278                                    return decodeURIComponent(pair[1] || '');
4279                                }
4280                            }
4281                            return null;
4282                        }
4283
4284                        // Function to construct the new URL with preserved query parameters and hash
4285                        function constructNewUrl(baseUrl, newParamName, newParamValue) {
4286                            var baseParts = baseUrl.indexOf('http') === 0 ? baseUrl.split('?')[0] : window.location.origin + '/' + baseUrl;
4287                            var currentParams = window.location.search.substring(1);
4288                            var queryParams = [];
4289
4290                            if (currentParams) {
4291                                var paramArray = currentParams.split('&');
4292                                for (var i = 0; i < paramArray.length; i++) {
4293                                    var keyValue = paramArray[i].split('=');
4294                                    if (decodeURIComponent(keyValue[0]) !== newParamName) {
4295                                        queryParams.push(paramArray[i]);
4296                                    }
4297                                }
4298                            }
4299
4300                            // Add the new/updated parameter
4301                            queryParams.push(encodeURIComponent(newParamName) + '=' + encodeURIComponent(newParamValue));
4302
4303                            var finalUrl = baseParts + '?' + queryParams.join('&');
4304
4305                            if (window.location.hash) {
4306                                finalUrl += window.location.hash;
4307                            }
4308
4309                            return finalUrl;
4310                        }
4311
4312                        for (var i = 0; i < data.length; i++) {
4313                            if (data[i].OnlineUrl) {
4314                                checkOlo = 1;
4315                                var htmltoadd = outerHtml;
4316                                var baseUrl = data[i].isNewOLO ? 'BrustersCom/Cart.aspx' : 'BrustersCom/ShoppingCart.aspx';
4317                                var newUrl = constructNewUrl(baseUrl, 'number', data[i].Number); // Construct the new URL with query string
4318
4319                                htmltoadd = htmltoadd.replace('[LAT]', data[i].lat)
4320                                .replace('[LNG]', data[i].lng)
4321                                .replaceAll('[ONLINEURL]', newUrl)
4322                                .replace('[STORE PHONE]', data[i].phone)
4323                                .replaceAll('[STORE NAME]', data[i].Name)
4324                                .replace('[STORE ADDRESS]', data[i].MAPADDRESS)
4325                                .replace('[MILES AWAY]', data[i].Distance)
4326                                .replace('[MAPADDRESS]', data[i].googleMapImage)
4327                                .replace('[MAPADDRESS2]', data[i].googleMapImage);
4328
4329                            
4330                                $("#divstores").append(htmltoadd);
4331                            }
4332                        }
4333
4334                        if (checkOlo === 0) {
4335                            $("#divstores").append('<p>We are sorry. No participating stores in your area.</p>');
4336                        }
4337                    } else {
4338                        $("#divstores").append('<p>We are sorry. No participating stores in your area.</p>');
4339                    }
4340
4341                }).done(function () {
4342                    // Hide landing page and show store list page
4343                    $("#landingPage").hide();
4344                    $("#storelist").show();
4345                    $(".loading").hide();
4346                });
4347            });
4348
4349
4350           
4351
4352            const number = getQueryStringParameter('number');
4353
4354            if (number) {
4355                $('#mainContent').show();
4356                $('#landingPage').hide();
4357
4358                //need to call an API for order processing stuff with line items
4359                $(".loading").show();
4360                $.ajax({
4361                    type: "POST",
4362                    url: "../Service.asmx/getOnlineFlavors",
4363                    data: JSON.stringify({ 'number': number, 'fundraiser': 0 }),
4364                    contentType: "application/json; charset=utf-8",
4365                    //dataType: "json",
4366                    success: function (data) {
4367                        $(".loading").hide();
4368                        console.log(data.d);
4369                        var mydata = JSON.parse(data.d);
4370                        $("input[type='hidden'][id$='hfItemList']").val(mydata.Items);
4371
4372                        // 🔥 IMPORTANT: wait until DOM is updated/rendered
4373                        setTimeout(function () {
4374                            markPromotionalProducts();
4375                        }, 0);
4376
4377                    }});
4378
4379            } else {
4380                $('#mainContent').hide();
4381                $('#landingPage').show();
4382            }
4383
4384            var enabled = $("input[type='hidden'][id$='hfEnabledHours']").val();
4385            var disabled = $("input[type='hidden'][id$='hfDisabledHours']").val();
4386            var disabledDates = $("input[type='hidden'][id$='hfDaysDisabled']").val();
4387            var datesDisabled = $("input[type='hidden'][id$='hfDatesDisabled']").val();
4388            var closedHour = parseInt($("input[type='hidden'][id$='hfClosedHour']").val());
4389            var startCloseHour = closedHour - 1;
4390            var startCloseMinute = 45;
4391            var strOpenTime = $("input[type='hidden'][id$='hfOpenTimeString']").val();
4392            var hfIsClosed = $("input[type='hidden'][id$='hfIsClosed']").val();
4393            var hfNextOpenDateTime = $("input[type='hidden'][id$='hfNextOpenDateTime']").val();
4394            var hfMaxDateTime = $("input[type='hidden'][id$='hfMaxDateTime']").val();
4395            var hfCurrentStoreTime = $("input[type='hidden'][id$='hfCurrentStoreTime']").val();
4396
4397            var eArray = enabled ? JSON.parse(enabled) : [];
4398            var dArray = disabled ? JSON.parse(disabled) : [];
4399            var daysDisabled = disabledDates ? JSON.parse(disabledDates) : [];
4400            var datesDisabledArray = datesDisabled ? JSON.parse(datesDisabled) : [];
4401
4402            var startCloseDateTime = new tempusDominus.DateTime(new Date().setHours(startCloseHour, startCloseMinute));
4403            var endCloseDateTime = new tempusDominus.DateTime(new Date().setHours(closedHour - 1, 45));
4404
4405            console.log(endCloseDateTime);
4406
4407            var d = new Date();
4408            var n = d.getHours();
4409            var m = d.getMinutes();
4410
4411            var setDate;
4412            var isPM = strOpenTime.toLowerCase().indexOf('pm') != -1;
4413            if (strOpenTime.toLowerCase().indexOf('closed') == -1 || hfIsClosed.toLowerCase() == 'true') {
4414                strOpenTime = strOpenTime.replace(/AM|PM|am|pm|\s/g, '');
4415                var splitTime = strOpenTime.split(/:/);
4416                var openMinutes = splitTime[1];
4417                var thisOpenHour = parseInt(splitTime[0]);
4418
4419                if (isPM && thisOpenHour < 12) {
4420                    thisOpenHour += 12;
4421                } else if (!isPM && thisOpenHour === 12) {
4422                    thisOpenHour = 0;
4423                }
4424
4425                var openD = new Date(hfCurrentStoreTime);
4426                if (openD.getHours() < thisOpenHour) {
4427                    setDate = new Date(openD.setHours(thisOpenHour, openMinutes, 0));
4428                }
4429                else if (hfNextOpenDateTime){
4430                    console.log('next day');
4431                    setDate = new Date(hfNextOpenDateTime);
4432                }
4433                else {
4434                    setDate = new Date();
4435                }
4436            }
4437
4438            console.log(eArray);
4439            console.log(dArray);
4440
4441            // Create the DateTime objects for the disabled time intervals
4442            const disabledFrom = new tempusDominus.DateTime(new Date(hfCurrentStoreTime));
4443            disabledFrom.hours = startCloseHour;
4444            disabledFrom.minutes = startCloseMinute;
4445
4446            const disabledTo = new tempusDominus.DateTime(new Date(hfCurrentStoreTime));
4447            disabledTo.hours = closedHour;
4448            disabledTo.minutes = 0;
4449
4450            const pickerElement = document.getElementById('pickupDateTimePicker');
4451            picker = new tempusDominus.TempusDominus(pickerElement, {
4452                localization: {
4453                    today: 'Go to today',
4454                    clear: 'Clear selection',
4455                    close: 'Close the picker',
4456                    selectMonth: 'Select Month',
4457                    previousMonth: 'Previous Month',
4458                    nextMonth: 'Next Month',
4459                    selectYear: 'Select Year',
4460                    previousYear: 'Previous Year',
4461                    nextYear: 'Next Year',
4462                    selectDecade: 'Select Decade',
4463                    previousDecade: 'Previous Decade',
4464                    nextDecade: 'Next Decade',
4465                    previousCentury: 'Previous Century',
4466                    nextCentury: 'Next Century',
4467                    pickHour: 'Pick Hour',
4468                    incrementHour: 'Increment Hour',
4469                    decrementHour: 'Decrement Hour',
4470                    pickMinute: 'Pick Minute',
4471                    incrementMinute: 'Increment Minute',
4472                    decrementMinute: 'Decrement Minute',
4473                    pickSecond: 'Pick Second',
4474                    incrementSecond: 'Increment Second',
4475                    decrementSecond: 'Decrement Second',
4476                    toggleMeridiem: 'Toggle Meridiem',
4477                    selectTime: 'Select Time',
4478                    selectDate: 'Select Date',
4479                    dayViewHeaderFormat: { month: 'long', year: '2-digit' },
4480                    locale: 'en',
4481                    startOfTheWeek: 0,
4482                    hourCycle: undefined,
4483                    dateFormats: {
4484                        LTS: 'h:mm:ss T',
4485                        LT: 'h:mm T',
4486                        L: 'MM/dd/yyyy',
4487                        LL: 'MMMM d, yyyy',
4488                        LLL: 'MMMM d, yyyy h:mm T',
4489                        LLLL: 'dddd, MMMM d, yyyy h:mm T'
4490                    },
4491                    ordinal: (n) => n,
4492                    format: 'LLL'
4493                },
4494                allowInputToggle: false,
4495                container: undefined,
4496                dateRange: false,
4497                debug: false,
4498                defaultDate: setDate,
4499                display: {
4500                    icons: {
4501                        type: 'icons',
4502                        time: 'fa-solid fa-clock',
4503                        date: 'fa-solid fa-calendar',
4504                        up: 'fa-solid fa-arrow-up',
4505                        down: 'fa-solid fa-arrow-down',
4506                        previous: 'fa-solid fa-chevron-left',
4507                        next: 'fa-solid fa-chevron-right',
4508                        today: 'fa-solid fa-calendar-check',
4509                        clear: 'fa-solid fa-trash',
4510                        close: 'fa-solid fa-xmark'
4511                    },
4512                    sideBySide: false,
4513                    calendarWeeks: false,
4514                    viewMode: 'calendar',
4515                    toolbarPlacement: 'bottom',
4516                    keepOpen: false,
4517                    buttons: {
4518                        today: false,
4519                        clear: false,
4520                        close: false
4521                    },
4522                    components: {
4523                        calendar: true,
4524                        date: true,
4525                        month: true,
4526                        year: true,
4527                        decades: true,
4528                        clock: true,
4529                        hours: true,
4530                        minutes: true,
4531                        seconds: false,
4532                        useTwentyfourHour: undefined
4533                    },
4534                    inline: false,
4535                    theme: 'auto'
4536                },
4537                keepInvalid: false,
4538                meta: {},
4539                multipleDates: false,
4540                multipleDatesSeparator: '; ',
4541                promptTimeOnDateChange: false,
4542                promptTimeOnDateChangeTransitionDelay: 200,
4543                restrictions: {
4544                    minDate: hfNextOpenDateTime ? new tempusDominus.DateTime(new Date(hfNextOpenDateTime)) : new tempusDominus.DateTime(),
4545                    maxDate: hfMaxDateTime ? new tempusDominus.DateTime(new Date(hfMaxDateTime)) : undefined,
4546                    disabledDates: datesDisabledArray.map(date => new tempusDominus.DateTime(new Date(date))),
4547                    enabledDates: [],
4548                    daysOfWeekDisabled: daysDisabled,
4549                    disabledTimeIntervals: [
4550                { from: disabledFrom, to: disabledTo }
4551                    ],
4552                    disabledHours: dArray,
4553                    enabledHours: eArray
4554                },
4555                stepping: 1,
4556                useCurrent: true,
4557                viewDate: new tempusDominus.DateTime()
4558            });
4559
4560            pickerElement.addEventListener('change.td', function (e) {
4561                //code used to check for day specific closing times
4562                console.log(e.detail);
4563                console.log('triggered date change');
4564                if (!e.detail || !e.detail.date) return;
4565
4566                const d = (typeof e.detail.date.toDate === "function")
4567                    ? e.detail.date.toDate()
4568                    : new Date(e.detail.date);
4569
4570                const old = e.detail.oldDate
4571                    ? ((typeof e.detail.oldDate.toDate === "function")
4572                        ? e.detail.oldDate.toDate()
4573                        : new Date(e.detail.oldDate))
4574                    : null;
4575
4576                if (!old) return;
4577
4578                // only run when DATE changes (not time)
4579                if (old.toDateString() === d.toDateString()) return;
4580
4581                const disabledIntervalsRaw = $("input[type='hidden'][id$='hfDisabledTimeIntervals']").val();
4582                if (!disabledIntervalsRaw) return;
4583
4584                const mydates = JSON.parse(disabledIntervalsRaw);
4585                const dayofweek = d.getDay();
4586
4587                for (let i = 0; i < mydates.length; i++) {
4588
4589                    if (dayofweek !== mydates[i].dayofweek) continue;
4590
4591                    const beghour = mydates[i].starthour;
4592                    const begmin = mydates[i].startminute;
4593                    const endhour = mydates[i].endhour;
4594                    const endmin = mydates[i].endminute;
4595
4596                    // 🔒 compute closing window (same logic you had)
4597                    const startCloseHour = endhour - 1;
4598                    const startCloseMinute = 45;
4599
4600                    // build enabled / disabled hours
4601                    const allhours = [...Array(24).keys()];
4602                    const openhours = [];
4603                    const closedhours = [];
4604
4605                    for (let h of allhours) {
4606                        if (h >= beghour && h < endhour) {
4607                            openhours.push(h);
4608                        } else {
4609                            closedhours.push(h);
4610                        }
4611                    }
4612
4613                    // set the time to opening time for the new date
4614                    d.setHours(beghour, begmin, 0, 0);
4615
4616                    // update picker value
4617                    picker.dates.setValue(
4618                        new tempusDominus.DateTime(d)
4619                    );
4620
4621                    // update picker restrictions dynamically
4622                    picker.updateOptions({
4623                        restrictions: {
4624                            enabledHours: openhours,
4625                            disabledHours: closedhours,
4626                            disabledTimeIntervals: [
4627                                {
4628                                    from: new tempusDominus.DateTime(
4629                                        new Date(d.getFullYear(), d.getMonth(), d.getDate(), startCloseHour, startCloseMinute)
4630                                    ),
4631                                    to: new tempusDominus.DateTime(
4632                                        new Date(d.getFullYear(), d.getMonth(), d.getDate(), endhour, endmin)
4633                                    )
4634                                }
4635                            ]
4636                        }
4637                    });
4638
4639                    break;
4640                }
4641            });
4642
4643
4644
4645            var isClosed = false;
4646            var openMinutes = 0;
4647            var openHour = parseInt($("input[type='hidden'][id$='hfOpenHour']").val())
4648            var closedHour = parseInt($("input[type='hidden'][id$='hfClosedHour']").val())
4649
4650            var isStoreClosed = $("input[type='hidden'][id$='hfIsClosed']").val();
4651            //console.log(n);
4652
4653            if (n < openHour || n >= closedHour || (n == parseInt(closedHour - 1) && m >= 45) || isStoreClosed == 'True') {
4654                isClosed = true;
4655            }
4656
4657
4658
4659
4660            if (isClosed == true) {
4661                $("input[type='radio'][name='pickupTimeOption']").eq(0).hide();
4662                $("input[type='radio'][name='pickupTimeOption']").eq(1).show();
4663                $(".radio-inline").eq(0).hide();
4664                $(".radio-inline").eq(1).show();
4665                $("input[type='radio'][name='pickupTimeOption']").eq(1).prop('checked', true);
4666                $("#pickupDateTimePicker").removeClass('d-none')
4667            }
4668
4669            $("input[name='pickupTimeOption']").change(function () {
4670                if ($(this).val() === "SelectDateTime") {
4671                    $('#pickupDateTimePicker').removeClass('d-none');
4672                } else {
4673                    $('#pickupDateTimePicker').addClass('d-none');
4674                }
4675            });
4676
4677            // Step 1: Check if the query string contains "&prepacked=true"
4678            if (window.location.search.indexOf("prepacked=true") !== -1) {
4679
4680                // Step 2: Find the anchor with the text "Hand-Packed To Go"
4681                var handPackedLink = $("a.section-link").filter(function() {
4682                    return $(this).text().trim() === "Hand-Packed To Go";
4683                });
4684
4685                if (handPackedLink.length) {
4686                    // Step 3: Click the link to scroll to the section
4687                    handPackedLink[0].click();
4688
4689                    // Step 4: After a short delay, find and click the image that toggles items
4690                    setTimeout(function () {
4691                        // Find the section number dynamically from the link href
4692                        var sectionHref = handPackedLink.attr("href"); // e.g., "#section-4"
4693                        var sectionNumber = sectionHref.replace("#section-", ""); // e.g., "4"
4694
4695                        // Find the image with the matching onclick toggleItemsVisibility(sectionNumber)
4696                        var toggleImage = $("img[onclick='toggleItemsVisibility(" + sectionNumber + ")']");
4697
4698                        if (toggleImage.length) {
4699                            toggleImage[0].click(); // Simulate the click
4700                        }
4701                    }, 500); // Adjust delay if needed
4702                }
4703            }
4704
4705            
4706        });
4707
4708    </script>
4708
4709
4710  
4710<script>
4711
4712        $(document).on('click', '.section-link', function (event) {
4713    event.preventDefault();
4714
4715    const section = document.querySelector(this.getAttribute('href'));
4716
4717    if (section) {
4718        section.scrollIntoView({
4719            behavior: 'smooth',
4720            block: 'start'
4721        });
4722
4723        const categoryButton = section.querySelector(
4724            'button[aria-controls]'
4725        );
4726
4727        if (categoryButton) {
4728            categoryButton.focus({
4729                preventScroll: true
4730            });
4731        }
4732    }
4733});
4734
4735
4736      let lastOpenedModal = null;
4737
4738     
4739      document.addEventListener('click', function(e) {
4740          if (e.target.classList.contains('clickable-modifier-img')) {
4741
4742              const fullImageUrl = e.target.getAttribute('data-full');
4743              document.getElementById('modifierFullImage').src = fullImageUrl;
4744
4745              // store the modal we are coming from (if any)
4746              const currentModal = e.target.closest('.modal');
4747              if (currentModal) {
4748                  lastOpenedModal = bootstrap.Modal.getInstance(currentModal);
4749                  lastOpenedModal.hide();
4750              } else {
4751                  lastOpenedModal = null;
4752              }
4753
4754              // open image modal
4755              const fullModal = new bootstrap.Modal(document.getElementById('modifierImageModal'));
4756              fullModal.show();
4757          }
4758      });
4759
4760      document.getElementById('modifierImageModal').addEventListener('hidden.bs.modal', function () {
4761          if (lastOpenedModal) {
4762              lastOpenedModal.show();
4763          }
4764      });
4765
4766
4767</script>
4767
4768
4769<input type="hidden" name="hfShowInvalidKioskModal" id="hfShowInvalidKioskModal" />
4770<div class="modal fade" id="invalidKioskModal" tabindex="-1" aria-hidden="true"
4771     data-bs-backdrop="static" data-bs-keyboard="false">
4772  <div class="modal-dialog modal-dialog-centered">
4773    <div class="modal-content text-center p-4">
4774      <h4 class="mb-3">This on-lot link is no longer active.</h4>
4775      <p>Please scan the QR code if you are currently at the store.</p>
4776      <p class="mb-4">Or click below to visit the store’s online store:</p>
4777      <a id="btnGoToOnlineStore" class="btn btn-primary btn-lg" href="#">Visit Online Store</a>
4778    </div>
4779  </div>
4780</div>
4781
4782
4783
4784</form>
4785</body>
4786</html>
4787
4788<script>
4789document.addEventListener("DOMContentLoaded", function () {
4790    var show = document.getElementById("hfShowInvalidKioskModal").value;
4791    if (show === "True") {
4792        var modal = new bootstrap.Modal(document.getElementById('invalidKioskModal'));
4793        modal.show();
4794
4795        // Always redirect to store's online ordering using the number from querystring
4796        var storeNumber = '';
4797        document.getElementById("btnGoToOnlineStore").href = "https://brustersonline.com/store/" + storeNumber;
4798    }
4799});
4800</script>
4800
4801

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.