PageSourceSearch

https://fine-label.com/pages/store-locator

html fine-label.com collected 2026-10-06 19:07:34 UTC 173,896 bytes, 7,107 lines download raw bytes

1<!doctype html>
2<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
3<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
4<!--[if IE 8]><html class="no-js lt-ie9" lang="en"> <![endif]-->
5<!--[if IE 9 ]><html class="ie9 no-js"> <![endif]-->
6<!--[if (gt IE 9)|!(IE)]><!--> <html class="no-js"> <!--<![endif]-->
7<head>
8
9  <!-- Basic page needs ================================================== -->
10  <meta charset="utf-8">
11  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
12
13  
14  <link rel="icon" href="https://cdn.store-assets.com/s/1325208/f/11789123.png" />
15  
16
17  <!-- Title and description ================================================== -->
18  <title>
19  Store Locator &ndash; FINE LABEL
20  </title>
21
22  
23
24  <!-- Social meta ================================================== -->
25  
26
27  <meta property="og:type" content="website">
28  <meta property="og:title" content="Store Locator">
29  <meta property="og:url" content="https://www.fine-label.com/pages/store-locator">
30  
31    <meta property="og:image" content="https://cdn.store-assets.com/s/1325208/f/17866599.png">
32    <meta property="og:image:secure_url" content="https://cdn.store-assets.com/s/1325208/f/17866599.png">
33  
34
35
36<meta property="og:description" content="FINE LABEL">
37<meta property="og:site_name" content="FINE LABEL">
38
39
40
41  <meta name="twitter:card" content="summary">
42
43
44
45  <meta name="twitter:site" content="@">
46
47
48
49
50
51  <!-- Helpers ================================================== -->
52  <link rel="canonical" href="https://www.fine-label.com/pages/store-locator">
53  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
54  <meta name="theme-color" content="#000000">
55  
56  
56<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript" ></script>
56
57  
58  <!-- Header hook for plugins ================================================== -->
59  
60<!-- ScriptTags -->
61<script>window.__st={p: "page",cid: null,cem: null,cph: null,cfn: null,cln: null,cge: null,cdb: null,ccc: null};</script>
61<script src='/assets/events.js'></script>
61<script>(function(){function asyncLoad(){var urls=['/assets/facebook-pixel.js?v=1.2.1787999665','/assets/traffic.js?v=1','https://apps.easystore.co/timer-discount/script.js?shop=miyacostore.easy.co&t=1697164155','https://apps.easystore.co/google-analytics/script.js?shop=miyacostore.easy.co&t=1696147478','https://apps.easystore.co/google-analytics-4/script.js?shop=miyacostore.easy.co&t=1771850563','https://smartarget.online/loader.js?type=int&u=5b005cd48353d53dc05b0d4340a6efeda1aa07d6&source=easystore_whatsapp','https://smartarget.online/loader.js?type=int&u=9ab458647cd423cbc5665f224ad3b23a5107759f&source=easystore_whatsapp','https://apps.easystore.co/facebook-login/script.js?shop=miyacostore.easy.co&t=1728305893'];for(var i=0;i<urls.length;i++){var s=document.createElement('script');s.type='text/javascript';s.async=true;s.src=urls[i];var x=document.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);}}window.attachEvent ? window.attachEvent('onload', asyncLoad) : window.addEventListener('load', asyncLoad, false);})();</script>
61
62<!-- /ScriptTags -->
63
64  
65  
66  
66<script src="https://store-themes.easystore.co/1325208/themes/308896/assets/global.js?t=1791095546" defer="defer"></script>
66
67
68  
69  
70  
70<script>
71  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
72  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
73  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
74  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
75
76  ga('create', '', 'auto','myTracker');
77  ga('myTracker.send', 'pageview');
78
79  </script>
79
80  
81  
81<script src="/assets/storefront.js?id=1d419de2011a5572c98b" type="text/javascript" ></script>
81
82  
83
84  <!-- CSS ================================================== -->
85  <style>
86      @font-face {
87        font-family: 'Alata';
88        font-style: normal;
89        font-weight: regular;
90        src: local('Alata regular'), local('Alata-regular'), url(https://fonts.gstatic.com/s/alata/v2/PbytFmztEwbIofe6xKcRQEOX.ttf) format('truetype');
91      }
92
93      @font-face {
94        font-family: 'Alata';
95        font-style: normal;
96        font-weight: regular;
97        src: local('Alata regular'), local('Alata-regular'), url(https://fonts.gstatic.com/s/alata/v2/PbytFmztEwbIofe6xKcRQEOX.ttf) format('truetype');
98      }
99
100      :root {
101        --font-body-family: 'Alata', sans-serif;
102        --font-body-style: normal;
103        --font-body-weight: 500;
104
105        --font-heading-family: 'Alata', sans-serif;
106        --font-heading-style: normal;
107        --font-heading-weight: 700;
108
109        --color-heading-text: 0,0,0;
110        --color-base-text: 0,0,0;
111        --color-base-background-1: 255,255,255;
112        --color-base-background-2: 255,255,255;
113        
114        --color-base-solid-button-labels: 255,255,255;
115        --color-base-outline-button-labels: 5,28,98;
116        
117        --color-base-accent-1: 0,0,0;
118        --color-base-accent-2: 0,0,0;
119        --payment-terms-background-color: 255,255,255;
120
121        --gradient-base-background-1: 255,255,255;
122        --gradient-base-background-2: 255,255,255;
123        --gradient-base-accent-1: 0,0,0;
124        --gradient-base-accent-2: 0,0,0;
125
126        --page-width: 145rem;
127      }
128
129      *,
130      *::before,
131      *::after {
132        box-sizing: inherit;
133      }
134
135      html {
136        box-sizing: border-box;
137        font-size: 62.5%;
138        height: 100%;
139      }
140
141      body {
142        display: grid;
143        grid-template-rows: auto auto 1fr auto;
144        grid-template-columns: 100%;
145        min-height: 100%;
146        margin: 0;
147        font-size: 1.5rem;
148        letter-spacing: 0.06rem;
149        line-height: 1.8;
150        font-family: var(--font-body-family);
151        font-style: var(--font-body-style);
152        font-weight: var(--font-body-weight);
153        
154      }
155
156      @media screen and (min-width: 750px) {
157        body {
158          font-size: 1.6rem;
159        }
160      }
161   </style>
162  
163  <link href="https://store-themes.easystore.co/1325208/themes/308896/assets/base.css?t=1791095546" rel="stylesheet" type="text/css" media="screen" />
164
165  
166  
167<!-- Snippet:global/head: OnVoard AOV Progress Bar -->
168<script>
169  (function() {
170    window.OnVoard = window.OnVoard || function() {
171      (window.OnVoard.q = window.OnVoard.q || []).push(arguments);
172    };
173    var script = document.createElement("script");
174    var parent = document.getElementsByTagName("script")[0].parentNode;
175    script.async = 1;
176
177    
178    script.src = "https://scripts.onvoard.com/apps/loader.js";
179    
180    parent.appendChild(script);
181  })();
182</script>
182
183
184
185<script>
186
187var ovData = {};
188ovData["ecommerce_platform"] = "easystore";
189ovData["account_id"] = "acct_6r1h4l52ykzoduq";
190
191
192  ovData["template"] = "page";
193  ovData["cart"] = {"item_count":0,"total_price":0,"announcements":[]};
194  ovData["product"] = "";
195  ovData["shop"] = {};
196  ovData["customer"] = {};
197
198  
199    ovData["shop"] = {
200      "currency": "MYR",
201      "domain": "fine-label.com",
202      "url": "https://fine-label.com",
203      "money_format": "<span class=money data-ori-price='{{amount}}'>RM {{amount}} </span>",
204    };
205  
206
207  
208
209  window.OnVoardData = ovData;
210</script>
210
211
212<!-- /Snippet -->
213
214<!-- Snippet:global/head: Recently View -->
215
216          <link rel="stylesheet" href="https://apps.easystore.co/assets/css/recently-view/main.css?v1">
217<!-- /Snippet -->
218
219<!-- Snippet:global/head: Site Verification -->
220<meta name="google-site-verification" content="AJWgo3mh5nhLCv5weJY01jpS9ahI3dWpdV2-iqNEKBY" />
221<!-- /Snippet -->
222
223
224  
224<script>document.documentElement.className = document.documentElement.className.replace('no-js', 'js');</script>
224
225</head>
226
227<body id="store-locator" class="template-page" >
228	
229  
230<!-- Snippet:global/body_start: Announcement Bar -->
231<link rel="stylesheet" href="https://apps.easystore.co/assets/css/annoucement-bar/slider.css?v1.01">
232
233<input type="hidden" id="total_announcement_left" name="total_announcement_left" value="4">
234<input type="hidden" id="locale" name="locale" value="en_US">
235
236<slider-announcement-bar-app id="announcement-bar" name="announcement-bar" style="
237    border: unset;
238    padding: 4px 0px;
239    margin: 0px;
240    z-index:2999;
241    background:rgb(250, 250, 250);
242    color:rgb(0, 0, 0);
243    
244">
245
246  <div style="
247    display: flex;
248    justify-content: space-between;
249    align-items: center;
250    padding: 3px 0px;
251    border-top: 1px dashed;
252    border-bottom: 1px dashed;
253    border-color: rgb(0, 0, 0);
254  ">
255    <div style="height: 24px;">
256            <a id="previous-announcement-bar-button" class="announcement-bar-direction-button" type="button" name="previous" style="height: 24px;">
257        <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="white" fill="none" stroke-linecap="round" stroke-linejoin="round">
258          <path stroke="none" d="M0 0h24v24H0z" fill="none" />
259          <polyline points="15 6 9 12 15 18" />
260        </svg>
261      </a>
262          </div>
263
264    <ul style="flex-grow: 2; margin: 0px;">
265            <li id="announcement_bar_0" style="
266          display: flex;
267          justify-content: center;
268          align-items: center;
269          flex-wrap: wrap;
270          margin: 0px;
271          width: 100%;
272          word-wrap: break-word;
273        ">
274        Hello October ✨ New Month, New Looks · Every 2pcs Off RM10 | Code: HELLOOCT
275                        <input type="hidden" id="expired_at_0" name="expired_at_0" value="2026-09-10 12:00">
276      </li>
277            <li id="announcement_bar_1" style="
278          display: flex;
279          justify-content: center;
280          align-items: center;
281          flex-wrap: wrap;
282          margin: 0px;
283          width: 100%;
284          word-wrap: break-word;
285        ">
286        ? 02/09 休息一天|门市暂停营业,客服与出货将于 03/09 恢复处理,官网照常下单 ❤️
287                        <div id='announcementBar_countdown_1' class="announcementBar_timer style_1" style="color: rgb(233, 69, 69); background: rgb(255, 255, 255); display: none;">
288        </div>
289                <input type="hidden" id="expired_at_1" name="expired_at_1" value="2026-06-10 00:00">
290      </li>
291            <li id="announcement_bar_2" style="
292          display: flex;
293          justify-content: center;
294          align-items: center;
295          flex-wrap: wrap;
296          margin: 0px;
297          width: 100%;
298          word-wrap: break-word;
299        ">
300        ? 只要买满 RM100,就能拿红包封 ×2(送完为止)
301                        <div id='announcementBar_countdown_2' class="announcementBar_timer style_2" style="color: rgb(233, 69, 69); background: rgb(255, 255, 255); display: none;">
302        </div>
303                <input type="hidden" id="expired_at_2" name="expired_at_2" value="2024-08-19 00:00">
304      </li>
305            <li id="announcement_bar_3" style="
306          display: flex;
307          justify-content: center;
308          align-items: center;
309          flex-wrap: wrap;
310          margin: 0px;
311          width: 100%;
312          word-wrap: break-word;
313        ">
314        姐妹们 圣诞优惠10%折扣结束倒计时!不要让你的购物车空着过圣诞啦~?❄️ Use Code: XMAS10
315                        <div id='announcementBar_countdown_3' class="announcementBar_timer style_1" style="color: rgb(233, 69, 69); background: rgb(255, 255, 255); display: none;">
316        </div>
317                <input type="hidden" id="expired_at_3" name="expired_at_3" value="2024-09-02 00:00">
318      </li>
319          </ul>
320
321    <div style="display: flex;">
322            <a id="next-announcement-bar-button" class="announcement-bar-direction-button" type="button" name="next" style="height: 24px;">
323        <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-right" width="24" height="24" viewBox="0 0 24 24" stroke-width="1.5" stroke="white" fill="none" stroke-linecap="round" stroke-linejoin="round">
324          <path stroke="none" d="M0 0h24v24H0z" fill="none" />
325          <polyline points="9 6 15 12 9 18" />
326        </svg>
327      </a>
328                  <span id="announcement-close-button" name="announcement-close-button" class="announcement-close-button" style="margin-right: 10px;"></span>
329          </div>
330  </div>
331
332
333</slider-announcement-bar-app>
334
335<script>
336  $(function() {
337    var is_top_enabled =  0;
338
339    const loadScript = function(url, callback) {
340      const script = document.createElement("script");
341      script.type = "text/javascript";
342      // If the browser is Internet Explorer.
343      if (script.readyState) {
344        script.onreadystatechange = function() {
345          if (script.readyState == "loaded" || script.readyState == "complete") {
346            script.onreadystatechange = null;
347            callback();
348          }
349        };
350        // For any other browser.
351      } else {
352        script.onload = function() {
353          callback();
354        };
355      }
356      script.src = url;
357      document.getElementsByTagName("head")[0].appendChild(script);
358    };
359
360    const announcementBarAppJS = function($) {
361
362      $('#announcement-close-button').on('click', function() {
363        $('#announcement-bar, #announcement-bar-top').hide();
364        $('#easystore-section-header, .sticky-topbar').css('top', '');
365      });
366    }
367
368    if (typeof jQuery === 'undefined') {
369      loadScript('//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js', function() {
370        jQuery = jQuery.noConflict(true);
371        announcementBarAppJS(jQuery);
372      });
373    } else {
374      announcementBarAppJS(jQuery);
375    }
376
377
378    
379    if(is_top_enabled){
380      // Prevent announcement bar block header
381      setTimeout(()=>{
382        $('#easystore-section-header, .sticky-topbar').css('top', $('#announcement-bar').height()+'px');
383      }, 2000);
384    }
385  });
386
387  setInterval(function() {
388    const total_announcement = "4"
389    var total_announcement_left = $("#total_announcement_left").val();
390
391    for (let i = 0; i <= total_announcement; i++) {
392      const startDate = new Date();
393      const endDateStr = $("#expired_at_" + i).val();
394      const endDate = endDateStr == undefined ? new Date() : new Date(endDateStr.replace(/-/g, "/"));
395      const seconds = (endDate.getTime() - startDate.getTime()) / 1000;
396
397      const days = parseInt(seconds / 86400);
398      const hours = parseInt((seconds % 86400) / 3600);
399      const mins = parseInt((seconds % 86400 % 3600) / 60);
400      const secs = parseInt((seconds % 86400 % 3600) % 60);
401
402      // use to translate countdown unit
403      // (translate based on the preferred language when save announcement bar setting)
404      String.prototype.translate = function() {
405        try {
406          if ($("#locale").val() == "zh_TW") {
407            if (this.toString() === 'day') {
408              return "天";
409            }
410            if (this.toString() === 'hour') {
411              return "小時";
412            }
413            if (this.toString() === 'min') {
414              return "分鐘";
415            }
416            if (this.toString() === 'sec') {
417              return "秒";
418            }
419          } else {
420            if (this.toString() === 'day') {
421              if (days > 0) {
422                return "Days";
423              } else {
424                return "Day";
425              }
426            } else if (this.toString() === 'hour') {
427              if (hours > 0) {
428                return "Hours";
429              } else {
430                return "Hour";
431              }
432            } else if (this.toString() === 'min') {
433              if (mins > 0) {
434                return "Mins";
435              } else {
436                return "Min";
437              }
438            } else if (this.toString() === 'sec') {
439              if (secs > 0) {
440                return "Secs";
441              } else {
442                return "Sec";
443              }
444            }
445          }
446        } catch (error) {
447          console.log("Some errors heres", error);
448        }
449      };
450
451      const announcementBar_countdown = document.getElementById("announcementBar_countdown_" + i);
452      if (announcementBar_countdown && seconds > 0) {
453
454        $(announcementBar_countdown).show()
455        announcementBar_countdown.innerHTML = `
456          <div>
457            ${days} <small>${'day'.translate()}</small>
458          </div>
459          <div>
460            ${hours} <small>${'hour'.translate()}</small>
461          </div>
462          <div>
463            ${mins} <small>${'min'.translate()}</small>
464          </div>
465          <div>
466            ${secs} <small>${'sec'.translate()}</small>
467          </div>
468        `;
469
470
471      } else if (announcementBar_countdown && seconds <= 0) {
472        $("#announcement_bar_" + i).remove();
473        total_announcement_left = total_announcement_left - 1;
474        $("#total_announcement_left").val(total_announcement_left);
475      }
476    }
477
478    showOrHide(total_announcement_left);
479  }, 1000);
480
481
482  function showOrHide(total_announcement_left) {
483    if (total_announcement_left <= 1) {
484      $("#previous-announcement-bar-button,#next-announcement-bar-button").hide();
485    } else {
486      $("#previous-announcement-bar-button,#next-announcement-bar-button").show();
487    }
488
489    if (total_announcement_left == 0) {
490      $("#announcement-close-button").hide();
491      $("#announcement-bar").hide();
492      $('#announcement-bar-top').hide();
493      $('#easystore-section-header, .sticky-topbar').css('top', '');
494    }
495  };
496
497  let annoucementBarAutoMoveInterval = '';
498  class AnnouncementBarAppSlider extends HTMLElement {
499    constructor() {
500      super();
501      this.slider = this.querySelector('ul');
502      this.sliderItems = this.querySelectorAll('li');
503      this.prevButton = this.querySelector('a[name="previous"]');
504      this.nextButton = this.querySelector('a[name="next"]');
505
506      if (!this.slider || !this.nextButton) return;
507
508      const resizeObserver = new ResizeObserver(entries => this.initPages());
509      resizeObserver.observe(this.slider);
510
511      this.slider.addEventListener('scroll', this.update.bind(this));
512      this.prevButton.addEventListener('click', this.onButtonClick.bind(this));
513      this.nextButton.addEventListener('click', this.onButtonClick.bind(this));
514
515
516    }
517
518    initPages() {
519      const sliderItemsToShow = Array.from(this.sliderItems).filter(element => element.clientWidth > 0);
520      this.sliderLastItem = sliderItemsToShow[sliderItemsToShow.length - 1];
521      if (sliderItemsToShow.length === 0) return;
522      this.slidesPerPage = Math.floor(this.slider.clientWidth / sliderItemsToShow[0].clientWidth);
523      this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 1;
524      this.update();
525      let self = this
526      var total_announcement_left = $("#total_announcement_left").val();
527      annoucementBarAutoMoveInterval = setInterval(function() {
528        if (total_announcement_left > 1) {
529          self.moveSlide('next')
530        }
531      }, 5000)
532    }
533
534    update() {
535      this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 1;
536    }
537
538    onButtonClick(event) {
539      event.preventDefault();
540      let self = this;
541      self.moveSlide(event.currentTarget.name);
542    }
543
544
545    moveSlide(move_to) {
546
547      clearInterval(annoucementBarAutoMoveInterval);
548      let self = this;
549      annoucementBarAutoMoveInterval = setInterval(function() {
550        self.moveSlide('next');
551      }, 5000)
552
553      if (move_to === 'previous' && this.currentPage === 1) {
554        this.slider.scrollTo({
555          left: this.sliderLastItem.clientWidth * (this.totalPages - 1)
556        });
557      } else if (move_to === 'next' && this.currentPage === this.totalPages) {
558        this.slider.scrollTo({
559          left: 0
560        });
561      } else {
562        const slideScrollPosition = move_to === 'next' ? this.slider.scrollLeft + this.sliderLastItem
563          .clientWidth : this.slider.scrollLeft - this.sliderLastItem.clientWidth;
564        this.slider.scrollTo({
565          left: slideScrollPosition
566        });
567      }
568    }
569
570  }
571
572  customElements.define('slider-announcement-bar-app', AnnouncementBarAppSlider);
573</script>
573
574
575<!-- /Snippet -->
576
577<!-- Snippet:global/body_start: Console Extension -->
578<div id='es_console' style='display: none;'>1325208</div>
579<!-- /Snippet -->
580
581	
582 	<style>
583  header {
584    --logo-width: 105px;
585  }
586  .header-wrapper,
587  .header-wrapper .list-menu--disclosure,
588  .header-wrapper .search-modal{
589    background-color: #FFFFFF;
590  }
591  .header-wrapper .search-modal .field__input{
592    background-color: rgb(var(--color-background));
593  }
594  .header-wrapper summary .icon-caret,
595  .header-wrapper .header__menu-item a,
596  .header-wrapper .list-menu__item,
597  .header-wrapper .link--text{
598    color: #000000;
599  }
600  
601  .search-modal__form{
602    position: relative;
603  }
604  
605  .dropdown {
606    display: none;
607    position: absolute;
608    top: 100%;
609    left: 0;
610    width: 100%;
611    padding: 5px 0;
612    background-color: #fff;
613    color:#000;
614    z-index: 1000;
615    border-bottom-left-radius: 15px;
616    border-bottom-right-radius: 15px;
617    border: 1px solid rgba(var(--color-foreground), 1);
618    border-top: none;
619    overflow-x: hidden;
620    overflow-y: auto;
621    max-height: 350px;
622  }
623  
624  .dropdown-item {
625    padding: 0.4rem 2rem;
626    cursor: pointer;
627    line-height: 1.4;
628    overflow: hidden;
629    text-overflow: ellipsis;
630    white-space: nowrap;
631  }
632  
633  .dropdown-item:hover{
634    background-color: #f3f3f3;
635  }
636  
637  .search__input.is-focus{
638    border-radius: 15px;
639    border-bottom-left-radius: 0;
640    border-bottom-right-radius: 0;
641    border: 1px solid rgba(var(--color-foreground), 1);
642    border-bottom: none;
643    box-shadow: none;
644  }
645  
646  .clear-all {
647    text-align: right;
648    padding: 0 2rem 0.2rem;
649    line-height: 1;
650    font-size: 70%;
651    margin-bottom: -2px;
652  }
653  
654  .clear-all:hover{
655    background-color: #fff;
656  }
657  
658  .search-input-focus .easystore-section-header-hidden{
659    transform: none;
660  }
661  .referral-notification {
662    position: absolute;
663    top: 100%;
664    right: 0;
665    background: white;
666    border: 1px solid #e0e0e0;
667    border-radius: 8px;
668    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
669    width: 280px;
670    z-index: 1000;
671    padding: 16px;
672    margin-top: 8px;
673    font-size: 14px;
674    line-height: 1.4;
675  }
676  
677  .referral-notification::before {
678    content: '';
679    position: absolute;
680    top: -8px;
681    right: 20px;
682    width: 0;
683    height: 0;
684    border-left: 8px solid transparent;
685    border-right: 8px solid transparent;
686    border-bottom: 8px solid white;
687  }
688  
689  .referral-notification::after {
690    content: '';
691    position: absolute;
692    top: -9px;
693    right: 20px;
694    width: 0;
695    height: 0;
696    border-left: 8px solid transparent;
697    border-right: 8px solid transparent;
698    border-bottom: 8px solid #e0e0e0;
699  }
700  
701  .referral-notification h4 {
702    margin: 0 0 8px 0;
703    color: #2196F3;
704    font-size: 16px;
705    font-weight: 600;
706  }
707  
708  .referral-notification p {
709    margin: 0 0 12px 0;
710    color: #666;
711  }
712  
713  .referral-notification .referral-code {
714    background: #f5f5f5;
715    padding: 8px;
716    border-radius: 4px;
717    font-family: monospace;
718    font-size: 13px;
719    text-align: center;
720    margin: 8px 0;
721    border: 1px solid #ddd;
722  }
723  
724  .referral-notification .close-btn {
725    position: absolute;
726    top: 8px;
727    right: 8px;
728    background: none;
729    border: none;
730    font-size: 18px;
731    color: #999;
732    cursor: pointer;
733    padding: 0;
734    width: 20px;
735    height: 20px;
736    line-height: 1;
737  }
738  
739  .referral-notification .close-btn:hover {
740    color: #333;
741  }
742  
743  .referral-notification .action-btn {
744    background: #2196F3;
745    color: white;
746    border: none;
747    padding: 8px 16px;
748    border-radius: 4px;
749    cursor: pointer;
750    font-size: 12px;
751    margin-right: 8px;
752    margin-top: 8px;
753  }
754  
755  .referral-notification .action-btn:hover {
756    background: #1976D2;
757  }
758  
759  .referral-notification .dismiss-btn {
760    background: transparent;
761    color: #666;
762    border: 1px solid #ddd;
763    padding: 8px 16px;
764    border-radius: 4px;
765    cursor: pointer;
766    font-size: 12px;
767    margin-top: 8px;
768  }
769  
770  .referral-notification .dismiss-btn:hover {
771    background: #f5f5f5;
772  }
773  .referral-modal__dialog {
774    transform: translate(-50%, 0);
775    transition: transform var(--duration-default) ease, visibility 0s;
776    z-index: 10000;
777    position: fixed;
778    top: 20vh;
779    left: 50%;
780    width: 100%;
781    max-width: 350px;
782    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
783    border-radius: 12px;
784    background-color: #fff;
785    color: #000;
786    padding: 20px;
787    text-align: center;
788  }
789
790  .modal-overlay.referral-modal-overlay {
791    position: fixed;
792    top: 0;
793    left: 0;
794    width: 100%;
795    height: 100%;
796    background-color: rgba(0, 0, 0, 0.7);
797    z-index: 2001;
798    display: block;
799    opacity: 1;
800    transition: opacity var(--duration-default) ease, visibility 0s;
801  }
802</style>
803
804<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/section-header.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
805<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-list-menu.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
806<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-menu-drawer.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
807<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-cart-notification.css?v1.1?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
808
809<script src="https://store-themes.easystore.co/1325208/themes/308896/assets/cart-notification.js?t=1791095546" defer="defer"></script>
vendor: 2 bytes, line 809
809
810<script src="https://store-themes.easystore.co/1325208/themes/308896/assets/details-modal.js?t=1791095546" defer="defer"></script>
810
811
812<svg xmlns="http://www.w3.org/2000/svg" class="hidden">
813  <symbol id="icon-search" viewbox="0 0 18 19" fill="none">
814    <path fill-rule="evenodd" clip-rule="evenodd" d="M11.03 11.68A5.784 5.784 0 112.85 3.5a5.784 5.784 0 018.18 8.18zm.26 1.12a6.78 6.78 0 11.72-.7l5.4 5.4a.5.5 0 11-.71.7l-5.41-5.4z" fill="currentColor"/>
815  </symbol>
816
817  <symbol id="icon-close" class="icon icon-close" fill="none" viewBox="0 0 18 17">
818    <path d="M.865 15.978a.5.5 0 00.707.707l7.433-7.431 7.579 7.282a.501.501 0 00.846-.37.5.5 0 00-.153-.351L9.712 8.546l7.417-7.416a.5.5 0 10-.707-.708L8.991 7.853 1.413.573a.5.5 0 10-.693.72l7.563 7.268-7.418 7.417z" fill="currentColor">
819  </symbol>
820</svg>
821
822
823<div id="easystore-section-header">
824  <sticky-header class="header-wrapper header-wrapper--border-bottom">
825    <header class="header header--middle-left page-width header--has-menu" itemscope itemtype="http://schema.org/Organization">
826      <header-drawer data-breakpoint="tablet">
827        <details class="menu-drawer-container menu-opening">
828          <summary class="header__icon header__icon--menu header__icon--summary link link--text focus-inset" aria-label="Menu" role="button" aria-expanded="true" aria-controls="menu-drawer">
829            <span>
830              
831
832
833    <svg class="icon icon-hamburger " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><path d="M32.5,65h535a25,25,0,0,0,0-50H32.5a25,25,0,0,0,0,50Z" fill="currentColor"/><path d="M567.5,275H32.5a25,25,0,0,0,0,50h535a25,25,0,0,0,0-50Z" fill="currentColor"/><path d="M567.5,535H32.5a25,25,0,0,0,0,50h535a25,25,0,0,0,0-50Z" fill="currentColor"/></svg>
834
835  
836
837              
838
839
840    <svg class="icon icon-close " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><path d="M335.36,300,581.87,53.48a25,25,0,0,0-35.35-35.35L300,264.64,53.48,18.13A25,25,0,0,0,18.13,53.48L264.64,300,18.13,546.52a25,25,0,0,0,35.35,35.35L300,335.36,546.52,581.87a25,25,0,0,0,35.35-35.35Z" fill="currentColor"/></svg>
841
842  
843
844            </span>
845          </summary>
846          <div id="menu-drawer" class="menu-drawer motion-reduce" tabindex="-1">
847            <div class="menu-drawer__inner-container">
848              <div class="menu-drawer__navigation-container">
849                <nav class="menu-drawer__navigation">
850                  <ul class="menu-drawer__menu list-menu" role="list">
851                    
852                    
853                      
854                        <li>
855                          <a href="/"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
856                            Home
857                          </a>
858                        </li>
859                      
860                    
861                    
862                      
863                        <li>
864                          <a href="/collections/10-10-2026"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
865                            优惠加码区 ✨ 
866                          </a>
867                        </li>
868                      
869                    
870                    
871                      
872                        <li>
873                          <a href="/collections/new-arrivals"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
874                            新品 | New Arrivals!
875                          </a>
876                        </li>
877                      
878                    
879                    
880                      
881                        
882                        <li>
883                          <details>
884                                <summary class="menu-drawer__menu-item list-menu__item link link--text focus-inset" role="button" aria-expanded="false" aria-controls="link-Bags">
885                                  <a href="/collections/shop-all"  class="link--text list-menu__item menu-drawer__menu-item">
886                                    Shop All
887                                  </a>
888                                  
889
890
891    <svg class="icon icon-arrow " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 339.56"><path d="M31.06,196.67H504l-88.56,88.56a26.89,26.89,0,1,0,38,38L588,188.79a26.89,26.89,0,0,0,0-38L453.49,16.29a26.89,26.89,0,0,0-38,38L504,142.88H31.06a26.9,26.9,0,0,0,0,53.79Z" fill="currentColor"/></svg>
892
893  
894
895                                  
896
897
898    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-caret " viewBox="0 0 10 6">
899      <path fill-rule="evenodd" clip-rule="evenodd" d="M9.354.646a.5.5 0 00-.708 0L5 4.293 1.354.646a.5.5 0 00-.708.708l4 4a.5.5 0 00.708 0l4-4a.5.5 0 000-.708z" fill="currentColor"></path>
900    </svg>
901
902  
903
904                                </summary>
905                                <div class="menu-drawer__submenu motion-reduce" tabindex="-1">
906                                  <div class="menu-drawer__inner-submenu">
907                                    <button class="menu-drawer__close-button link link--text focus-inset" aria-expanded="true">
908                                      
909
910
911    <svg class="icon icon-arrow " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 339.56"><path d="M31.06,196.67H504l-88.56,88.56a26.89,26.89,0,1,0,38,38L588,188.79a26.89,26.89,0,0,0,0-38L453.49,16.29a26.89,26.89,0,0,0-38,38L504,142.88H31.06a26.9,26.9,0,0,0,0,53.79Z" fill="currentColor"/></svg>
912
913  
914
915                                      Shop All
916                                    </button>
917                                    <ul class="menu-drawer__menu list-menu" role="list" tabindex="-1">
918                                      
919                                        
920                                        
921                                          <li>
922                                            <a href="/collections/tops"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
923                                              Tops
924                                            </a>
925                                          </li>
926                                        
927                                      
928                                        
929                                        
930                                          <li>
931                                            <a href="/collections/bottoms"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
932                                              Bottoms
933                                            </a>
934                                          </li>
935                                        
936                                      
937                                        
938                                        
939                                          <li>
940                                            <a href="/collections/dresses"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
941                                              Dresses
942                                            </a>
943                                          </li>
944                                        
945                                      
946                                        
947                                        
948                                          <li>
949                                            <a href="/collections/jumpsuits"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
950                                              Jumpsuits
951                                            </a>
952                                          </li>
953                                        
954                                      
955                                        
956                                        
957                                          <li>
958                                            <a href="/collections/shoes"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
959                                              Shoes
960                                            </a>
961                                          </li>
962                                        
963                                      
964                                        
965                                        
966                                          <li>
967                                            <a href="/collections/accessories"  class="menu-drawer__menu-item link link--text list-menu__item focus-inset">
968                                              Accessories
969                                            </a>
970                                          </li>
971                                        
972                                      
973                                      
974                                    </ul>
975                                  </div>
976                                </div>
977                          </details>
978                        </li>
979                      
980                    
981                    
982                      
983                        <li>
984                          <a href="/collections/plus-size"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
985                            Plus Size
986                          </a>
987                        </li>
988                      
989                    
990                    
991                      
992                        <li>
993                          <a href="/collections/fine-label"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
994                            FINE LABEL
995                          </a>
996                        </li>
997                      
998                    
999                    
1000                      
1001                        <li>
1002                          <a href="/pages/store-locator"  class="menu-drawer__menu-item list-menu__item link link--text focus-inset">
1003                            STORE LOCATOR
1004                          </a>
1005                        </li>
1006                      
1007                    
1008                  </ul>
1009                </nav>
1010
1011                <div class="menu-drawer__utility-links">
1012
1013                  
1014
1015
1016
1017
1018
1019                  
1020                  
1021                  
1022                    <a href="/account/login" class="menu-drawer__account link link--text focus-inset h5">
1023                       
1024
1025
1026    <svg class="icon icon-account " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><path d="M300,296.19c-70.7,0-137.11,28.74-187,80.93-49.59,51.87-76.9,120.77-76.9,194v25H563.89v-25c0-73.22-27.31-142.12-76.9-194C437.11,324.93,370.7,296.19,300,296.19ZM87.42,546.11C99.29,433.81,190.1,346.19,300,346.19s200.71,87.62,212.58,199.92Z" fill="currentColor"/><path d="M300,285.34c77.6,0,140.73-63.13,140.73-140.73S377.6,3.89,300,3.89,159.27,67,159.27,144.61,222.4,285.34,300,285.34Zm0-231.45a90.73,90.73,0,1,1-90.73,90.72A90.82,90.82,0,0,1,300,53.89Z" fill="currentColor"/></svg>
1027
1028  
1029 
1030                      
1031                      Log in
1032                    </a>
1033                  
1034                    <a href="/account/register" class="menu-drawer__account link link--text focus-inset h5">
1035                      
1036                       
1037
1038
1039    <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" role="presentation" class="icon icon-plus " fill="none" viewBox="0 0 10 10">
1040      <path fill-rule="evenodd" clip-rule="evenodd" d="M1 4.51a.5.5 0 000 1h3.5l.01 3.5a.5.5 0 001-.01V5.5l3.5-.01a.5.5 0 00-.01-1H5.5L5.49.99a.5.5 0 00-1 .01v3.5l-3.5.01H1z" fill="currentColor"></path>
1041    </svg>
1042
1043  
1044 
1045                      Create account
1046                    </a>
1047                  
1048                  
1049                  
1050                </div>
1051              </div>
1052            </div>
1053          </div>
1054        </details>
1055      </header-drawer>
1056  
1057      
1058        <a href="/" class="header__heading-link link link--text focus-inset" itemprop="url">
1059          <img src="https://cdn.store-assets.com/s/1325208/f/17866599.png" class="header__heading-logo" alt="FINE LABEL" loading="lazy" itemprop="logo">
1060        </a>
1061      
1062
1063      
1064      <div class="header__search-input" tabindex="-1">
1065        <form action="/search" method="get" role="search" class="search search-modal__form">
1066          <div class="field">
1067            <input class="search__input field__input" 
1068              id="Search-In-Modal"
1069              type="search"
1070              name="q"
1071              value=""
1072              placeholder="Search"
1073              autocomplete="off"
1074            >
1075            <label class="field__label" for="Search-In-Modal">Search</label>
1076            <div class="dropdown" id="searchDropdown"></div>
1077            <input type="hidden" name="search_history" class="hidden_search_history">
1078            <input type="hidden" name="options[prefix]" value="last">
1079            <button class="search__button field__button" aria-label="Search">
1080              <svg class="icon icon-search" aria-hidden="true" focusable="false" role="presentation">
1081                <use href="#icon-search">
1082              </svg>
1083            </button> 
1084          </div>
1085        </form>
1086      </div>
1087      
1088
1089      <nav class="header__inline-menu">
1090        <ul class="list-menu list-menu--inline" role="list">
1091          
1092            
1093              
1094                <li>
1095                  <a href="/"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1096                    Home
1097                  </a>
1098                </li>
1099              
1100            
1101            
1102              
1103                <li>
1104                  <a href="/collections/10-10-2026"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1105                    优惠加码区 ✨ 
1106                  </a>
1107                </li>
1108              
1109            
1110            
1111              
1112                <li>
1113                  <a href="/collections/new-arrivals"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1114                    新品 | New Arrivals!
1115                  </a>
1116                </li>
1117              
1118            
1119            
1120              
1121                
1122                <li>
1123                  <details-disclosure>
1124                    <details>
1125                      <summary class="header__menu-item list-menu__item link focus-inset">
1126                        <a href="/collections/shop-all"  >Shop All</a>
1127                        
1128
1129
1130    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-caret " viewBox="0 0 10 6">
1131      <path fill-rule="evenodd" clip-rule="evenodd" d="M9.354.646a.5.5 0 00-.708 0L5 4.293 1.354.646a.5.5 0 00-.708.708l4 4a.5.5 0 00.708 0l4-4a.5.5 0 000-.708z" fill="currentColor"></path>
1132    </svg>
1133
1134  
1135
1136                      </summary>
1137                      <ul class="header__submenu list-menu list-menu--disclosure caption-large motion-reduce" role="list" tabindex="-1">
1138                        
1139                        
1140                        
1141                          
1142                            
1143                            <li>
1144                              <a href="/collections/tops"  class="header__menu-item list-menu__item link link--text focus-inset caption-large">
1145                                Tops
1146                              </a>
1147                            </li>
1148                          
1149                        
1150                        
1151                          
1152                            
1153                            <li>
1154                              <a href="/collections/bottoms"  class="header__menu-item list-menu__item link link--text focus-inset caption-large">
1155                                Bottoms
1156                              </a>
1157                            </li>
1158                          
1159                        
1160                        
1161                          
1162                            
1163                            <li>
1164                              <a href="/collections/dresses"  class="head
1164er__menu-item list-menu__item link link--text focus-inset caption-large">
1165                                Dresses
1166                              </a>
1167                            </li>
1168                          
1169                        
1170                        
1171                          
1172                            
1173                            <li>
1174                              <a href="/collections/jumpsuits"  class="header__menu-item list-menu__item link link--text focus-inset caption-large">
1175                                Jumpsuits
1176                              </a>
1177                            </li>
1178                          
1179                        
1180                        
1181                          
1182                            
1183                            <li>
1184                              <a href="/collections/shoes"  class="header__menu-item list-menu__item link link--text focus-inset caption-large">
1185                                Shoes
1186                              </a>
1187                            </li>
1188                          
1189                        
1190                        
1191                          
1192                            
1193                            <li>
1194                              <a href="/collections/accessories"  class="header__menu-item list-menu__item link link--text focus-inset caption-large">
1195                                Accessories
1196                              </a>
1197                            </li>
1198                          
1199                        
1200                      </ul>
1201                    </details>
1202                  </details-disclosure>
1203                </li>
1204              
1205            
1206            
1207              
1208                <li>
1209                  <a href="/collections/plus-size"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1210                    Plus Size
1211                  </a>
1212                </li>
1213              
1214            
1215            
1216              
1217                <li>
1218                  <a href="/collections/fine-label"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1219                    FINE LABEL
1220                  </a>
1221                </li>
1222              
1223            
1224            
1225              
1226                <li>
1227                  <a href="/pages/store-locator"  class="header__menu-item header__menu-item list-menu__item link link--text focus-inset">
1228                    STORE LOCATOR
1229                  </a>
1230                </li>
1231              
1232            
1233            
1234            
1235              
1236                
1237                  
1238                
1239                  
1240                
1241              
1242            
1243        </ul>
1244      </nav>
1245      <div class="header__icons">
1246
1247        
1248          
1249            <div class="header__icon header__icon--account link link--text focus-inset small-hide medium-hide" style="position: relative;">
1250              <a href="/account/login" class="header__icon link link--text focus-inset p-2">
1251                
1252
1253
1254    <svg class="icon icon-account " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><path d="M300,296.19c-70.7,0-137.11,28.74-187,80.93-49.59,51.87-76.9,120.77-76.9,194v25H563.89v-25c0-73.22-27.31-142.12-76.9-194C437.11,324.93,370.7,296.19,300,296.19ZM87.42,546.11C99.29,433.81,190.1,346.19,300,346.19s200.71,87.62,212.58,199.92Z" fill="currentColor"/><path d="M300,285.34c77.6,0,140.73-63.13,140.73-140.73S377.6,3.89,300,3.89,159.27,67,159.27,144.61,222.4,285.34,300,285.34Zm0-231.45a90.73,90.73,0,1,1-90.73,90.72A90.82,90.82,0,0,1,300,53.89Z" fill="currentColor"/></svg>
1255
1256  
1257
1258                <span id="my-account" class="header__link-label">Login</span>
1259              </a>
1260
1261              <!-- Referral Notification Popup for Desktop -->
1262              <div id="referralNotification" class="referral-notification" style="display: none;">
1263                <button class="close-btn" onclick="dismissReferralNotification()">&times;</button>
1264                <div style="text-align: center; margin-bottom: 16px;">
1265                  <div style="width: 100px; height: 100px; margin: 0 auto;">
1266                    <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg">
1267                  </div>
1268                </div>
1269                <p id="referralSignupMessage" style="text-align: center; font-size: 14px; color: #666; margin: 0 0 20px 0;">
1270                  Your friend gifted you   credit! Sign up now to redeem.
1271                </p>
1272                <div style="text-align: center;">
1273                  <button class="btn" onclick="goToSignupPage()" style="width: 100%;">
1274                    Sign Up
1275                  </button>
1276                </div>
1277              </div>
1278            </div>
1279          
1280        
1281
1282        <a href="/cart" class="header__icon link link--text focus-inset" id="cart-icon-bubble">
1283          <span class="header__icon--cart">
1284            
1285
1286
1287    <svg class="icon icon-cart-empty " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496.56 600"><path d="M453.52,128.63a25,25,0,0,0-24.91-22.8H364.72a117.48,117.48,0,0,0-232.89,0H67.94A25,25,0,0,0,43,128.63L8.8,515.21a72.11,72.11,0,0,0,19.05,55.6,79,79,0,0,0,58.22,25.3H410.49a79,79,0,0,0,58.22-25.3,72.11,72.11,0,0,0,19.05-55.6ZM248.28,53.89a67.58,67.58,0,0,1,65.65,51.94H182.63A67.57,67.57,0,0,1,248.28,53.89ZM431.83,537.05a28.85,28.85,0,0,1-21.34,9.06H86.07a28.85,28.85,0,0,1-21.34-9.06,22.69,22.69,0,0,1-6.13-17.43L90.82,155.83h40v51.23a25,25,0,0,0,50,0V155.83h135v51.23a25,25,0,0,0,50,0V155.83h40L438,519.62A22.68,22.68,0,0,1,431.83,537.05Z" fill="currentColor"/></svg>
1288
1289  
1290
1291            <div class="cart-count-bubble hidden">
1292              <span aria-hidden="true" class="js-content-cart-count">0</span>
1293            </div>
1294          </span>
1295          <span class="header__link-label medium-hide small-hide">
1296            Cart
1297          </span>
1298        </a>
1299
1300        
1301          
1302          <!-- Referral Notification Modal for Mobile -->
1303          <details-modal class="referral-modal" id="referralMobileModal">
1304            <details>
1305              <summary class="referral-modal__toggle" aria-haspopup="dialog" aria-label="Open referral modal" style="display: none;">
1306              </summary>
1307              <div class="modal-overlay referral-modal-overlay"></div>
1308              <div class="referral-modal__dialog" role="dialog" aria-modal="true" aria-label="Referral notification">
1309                <div class="referral-modal__content">
1310                  <button type="button" class="modal__close-button" aria-label="Close" onclick="closeMobileReferralModal()" style="position: absolute; top: 16px; right: 16px; background: none; border: none; font-size: 24px; cursor: pointer;">
1311                    &times;
1312                  </button>
1313                  
1314                  <div style="margin-bottom: 24px;">
1315                    <div style="width: 120px; height: 120px; margin: 0 auto 20px;">
1316                      <img src="https://resources.easystore.co/storefront/icons/channels/vector_referral_program.svg" style="width: 100%; height: 100%;">
1317                    </div>
1318                  </div>
1319                  
1320                  <p id="referralSignupMessageMobile" style="font-size: 16px; color: #333; margin: 0 0 30px 0; line-height: 1.5;">
1321                    Your friend gifted you   credit! Sign up now to redeem.
1322                  </p>
1323                  
1324                  <button type="button" class="btn" onclick="goToSignupPageFromMobile()" style="width: 100%;">
1325                    Sign Up
1326                  </button>
1327                </div>
1328              </div>
1329            </details>
1330          </details-modal>
1331          
1332        
1333        
1334      </div>
1335    </header>
1336  </sticky-header>
1337  
1338<cart-notification>
1339  <div class="cart-notification-wrapper page-width color-background-1">
1340    <div id="cart-notification" class="cart-notification focus-inset" aria-modal="true" aria-label="Added to cart" role="dialog" tabindex="-1">
1341      <div class="cart-notification__header">
1342        <h2 class="cart-notification__heading caption-large">
1343
1344
1345    <svg class="icon icon-checkmark color-foreground-text " aria-hidden="true" focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 9" fill="none">
1346      <path fill-rule="evenodd" clip-rule="evenodd" d="M11.35.643a.5.5 0 01.006.707l-6.77 6.886a.5.5 0 01-.719-.006L.638 4.845a.5.5 0 11.724-.69l2.872 3.011 6.41-6.517a.5.5 0 01.707-.006h-.001z" fill="currentColor"></path>
1347    </svg>
1348
1349  
1350 Added to cart</h2>
1351        <button type="button" class="cart-notification__close modal__close-button link link--text focus-inset" aria-label="accessibility.close">
1352          
1353
1354
1355    <svg class="icon icon-close " data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600"><path d="M335.36,300,581.87,53.48a25,25,0,0,0-35.35-35.35L300,264.64,53.48,18.13A25,25,0,0,0,18.13,53.48L264.64,300,18.13,546.52a25,25,0,0,0,35.35,35.35L300,335.36,546.52,581.87a25,25,0,0,0,35.35-35.35Z" fill="currentColor"/></svg>
1356
1357  
1358
1359        </button>
1360      </div>
1361      <div id="cart-notification-product" class="cart-notification-product"></div>
1362      <div class="cart-notification__links">
1363        <a href="/cart" id="cart-notification-button" class="button button--secondary button--full-width">View cart (<span class="js-content-cart-count">0</span>)</a>
1364        <form action="/cart" method="post" id="cart-notification-form">
1365          <input type="hidden" name="_token" value="1ajnERQGYBXr92PAa8BfcMsXdRFvZvjf7BJ2cIbT">
1366          <input type="hidden" name="current_currency" value="">
1367          <button class="button button--primary button--full-width" name="checkout" value="true">Checkout</button>
1368        </form>
1369        <a href="/collections/all" class="link button-label">Continue shopping</a>
1370      </div>
1371    </div>
1372  </div>
1373</cart-notification>
1374<style>
1375  .cart-notification {
1376     display: none;
1377  }
1378</style>
1379<script>
1380document.getElementById('cart-notification-form').addEventListener('submit',(event)=>{
1381  if(event.submitter) event.submitter.classList.add('loading');
1382})
1383
1384</script>
1384
1385
1386</div>
1387
1388
1389<script>
1390
1391  class StickyHeader extends HTMLElement {
1392    constructor() {
1393      super();
1394    }
1395
1396    connectedCallback() {
1397      this.header = document.getElementById('easystore-section-header');
1398      this.headerBounds = {};
1399      this.currentScrollTop = 0;
1400      this.preventReveal = false;
1401
1402      this.onScrollHandler = this.onScroll.bind(this);
1403      this.hideHeaderOnScrollUp = () => this.preventReveal = true;
1404
1405      this.addEventListener('preventHeaderReveal', this.hideHeaderOnScrollUp);
1406      window.addEventListener('scroll', this.onScrollHandler, false);
1407
1408      this.createObserver();
1409    }
1410
1411    disconnectedCallback() {
1412      this.removeEventListener('preventHeaderReveal', this.hideHeaderOnScrollUp);
1413      window.removeEventListener('scroll', this.onScrollHandler);
1414    }
1415
1416    createObserver() {
1417      let observer = new IntersectionObserver((entries, observer) => {
1418        this.headerBounds = entries[0].intersectionRect;
1419        observer.disconnect();
1420      });
1421
1422      observer.observe(this.header);
1423    }
1424
1425    onScroll() {
1426      const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
1427
1428      if (scrollTop > this.currentScrollTop && scrollTop > this.headerBounds.bottom) {
1429        requestAnimationFrame(this.hide.bind(this));
1430      } else if (scrollTop < this.currentScrollTop && scrollTop > this.headerBounds.bottom) {
1431        if (!this.preventReveal) {
1432          requestAnimationFrame(this.reveal.bind(this));
1433        } else {
1434          window.clearTimeout(this.isScrolling);
1435
1436          this.isScrolling = setTimeout(() => {
1437            this.preventReveal = false;
1438          }, 66);
1439
1440          requestAnimationFrame(this.hide.bind(this));
1441        }
1442      } else if (scrollTop <= this.headerBounds.top) {
1443        requestAnimationFrame(this.reset.bind(this));
1444      }
1445
1446
1447      this.currentScrollTop = scrollTop;
1448    }
1449
1450    hide() {
1451      this.header.classList.add('easystore-section-header-hidden', 'easystore-section-header-sticky');
1452      this.closeMenuDisclosure();
1453      // this.closeSearchModal();
1454    }
1455
1456    reveal() {
1457      this.header.classList.add('easystore-section-header-sticky', 'animate');
1458      this.header.classList.remove('easystore-section-header-hidden');
1459    }
1460
1461    reset() {
1462      this.header.classList.remove('easystore-section-header-hidden', 'easystore-section-header-sticky', 'animate');
1463    }
1464
1465    closeMenuDisclosure() {
1466      this.disclosures = this.disclosures || this.header.querySelectorAll('details-disclosure');
1467      this.disclosures.forEach(disclosure => disclosure.close());
1468    }
1469
1470    // closeSearchModal() {
1471    //   this.searchModal = this.searchModal || this.header.querySelector('details-modal');
1472    //   this.searchModal.close(false);
1473    // }
1474  }
1475
1476  customElements.define('sticky-header', StickyHeader);
1477
1478  
1479  class DetailsDisclosure extends HTMLElement{
1480    constructor() {
1481      super();
1482      this.mainDetailsToggle = this.querySelector('details');
1483      // this.mainDetailsToggle.addEventListener('focusout', this.onFocusOut.bind(this));
1484      this.mainDetailsToggle.addEventListener('mouseover', this.open.bind(this));
1485      this.mainDetailsToggle.addEventListener('mouseleave', this.close.bind(this));
1486    }
1487
1488    onFocusOut() {
1489      setTimeout(() => {
1490        if (!this.contains(document.activeElement)) this.close();
1491      })
1492    }
1493
1494    open() {
1495      this.mainDetailsToggle.setAttribute('open',1)
1496    }
1497
1498    close() {
1499      this.mainDetailsToggle.removeAttribute('open')
1500    }
1501  }
1502
1503  customElements.define('details-disclosure', DetailsDisclosure);
1504
1505  function clearAll() {
1506    localStorage.removeItem('searchHistory'); 
1507    
1508    var customer = "";
1509    if(customer) {
1510      // Your logic to clear all data or call an endpoint
1511      fetch('/account/search_histories', {
1512          method: 'DELETE',
1513          headers: {
1514            "Content-Type": "application/json",
1515            "X-Requested-With": "XMLHttpRequest"
1516          },
1517          body: JSON.stringify({
1518            _token: "1ajnERQGYBXr92PAa8BfcMsXdRFvZvjf7BJ2cIbT"
1519          }),
1520      })
1521      .then(response => response.json())
1522    }
1523  }
1524  // End - delete search history from local storage
1525  
1526  // search history dropdown  
1527  var searchInputs = document.querySelectorAll('.search__input');
1528  
1529  if(searchInputs.length > 0) {
1530    
1531    searchInputs.forEach((searchInput)=> {
1532    
1533      searchInput.addEventListener('focus', function() {
1534        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1535        searchDropdown.innerHTML = ''; // Clear existing items
1536  
1537        // retrieve data from local storage
1538        var searchHistoryData = JSON.parse(localStorage.getItem('searchHistory')) || [];
1539  
1540        // Convert JSON to string
1541        var search_history_json = JSON.stringify(searchHistoryData);
1542  
1543        // Set the value of the hidden input
1544        searchInput.closest('form').querySelector(".hidden_search_history").value = search_history_json;
1545  
1546        // create dropdown items
1547        var clearAllItem = document.createElement('div');
1548        clearAllItem.className = 'dropdown-item clear-all';
1549        clearAllItem.textContent = 'Clear';
1550        clearAllItem.addEventListener('click', function() {
1551          clearAll();
1552          searchDropdown.style.display = 'none';
1553          searchInput.classList.remove('is-focus');
1554        });
1555        searchDropdown.appendChild(clearAllItem);
1556  
1557        // create dropdown items
1558        searchHistoryData.forEach(function(item) {
1559          var dropdownItem = document.createElement('div');
1560          dropdownItem.className = 'dropdown-item';
1561          dropdownItem.textContent = item.term;
1562          dropdownItem.addEventListener('click', function() {
1563            searchInput.value = item.term;
1564            searchInput.closest('form').submit();
1565            searchDropdown.style.display = 'none';
1566          });
1567          searchDropdown.appendChild(dropdownItem);
1568        });
1569  
1570        if(searchHistoryData.length > 0){
1571          // display the dropdown
1572          searchInput.classList.add('is-focus');
1573          document.body.classList.add('search-input-focus');
1574          searchDropdown.style.display = 'block';
1575        }
1576      });
1577  
1578      searchInput.addEventListener("focusout", (event) => {
1579        var searchDropdown = searchInput.closest('form').querySelector('#searchDropdown');
1580        searchInput.classList.remove('is-focus');
1581        searchDropdown.classList.add('transparent');
1582        setTimeout(()=>{
1583          searchDropdown.style.display = 'none';
1584          searchDropdown.classList.remove('transparent');
1585          document.body.classList.remove('search-input-focus');
1586        }, 400);
1587      });
1588    })
1589  }
1590  // End - search history dropdown
1591
1592  // referral notification popup
1593  const referralMessageTemplate = 'Your friend gifted you __CURRENCY_CODE__ __CREDIT_AMOUNT__ credit! Sign up now to redeem.';
1594  const shopCurrency = 'RM';
1595
1596  function getCookie(name) {
1597    const value = `; ${document.cookie}`;
1598    const parts = value.split(`; ${name}=`);
1599    if (parts.length === 2) return parts.pop().split(';').shift();
1600    return null;
1601  }
1602
1603  function removeCookie(name) {
1604    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
1605  }
1606
1607  function showReferralNotification() {
1608    const referralCode = getCookie('customer_referral_code');
1609    
1610    
1611    const customerReferralCode = null;
1612    
1613    
1614    const activeReferralCode = referralCode || customerReferralCode;
1615    const referralData = JSON.parse(localStorage.getItem('referral_notification_data')) || {};
1616    
1617    if (referralData.timestamp && referralData.expirationDays) {
1618      const expirationTime = referralData.timestamp + (referralData.expirationDays * 24 * 60 * 60 * 1000);
1619      if (Date.now() > expirationTime) {
1620        localStorage.removeItem('referral_notification_data');
1621        return;
1622      }
1623    }
1624    
1625    if (referralData.dismissed) return;
1626    
1627    if (activeReferralCode) {
1628      if (referralData.creditAmount) {
1629        displayReferralNotification(referralData.creditAmount);
1630      } else {
1631        fetchReferralCampaignData(activeReferralCode);
1632      }
1633    }
1634  }
1635    
1636  function fetchReferralCampaignData(referralCode) {
1637    fetch(`/customer/referral_program/campaigns/${referralCode}`)
1638      .then(response => {
1639        if (!response.ok) {
1640          throw new Error('Network response was not ok');
1641        }
1642        return response.json();
1643      })
1644      .then(data => {
1645        let refereeCreditAmount = null;
1646        if (data.data.campaign && data.data.campaign.referral_rules) {
1647          const refereeRule = data.data.campaign.referral_rules.find(rule => 
1648            rule.target_type === 'referee' && 
1649            rule.event_name === 'customer/create' && 
1650            rule.entitlement && 
1651            rule.entitlement.type === 'credit'
1652          );
1653          
1654          if (refereeRule) {
1655            refereeCreditAmount = refereeRule.entitlement.amount;
1656          }
1657        }
1658        
1659        const referralData = JSON.parse(localStorage.getItem('referral_notification_data')) || {};
1660        referralData.creditAmount = refereeCreditAmount;
1661        referralData.dismissed = referralData.dismissed || false;
1662        referralData.timestamp = Date.now();
1663        referralData.expirationDays = 3;
1664        localStorage.setItem('referral_notification_data', JSON.stringify(referralData));
1665        
1666        displayReferralNotification(refereeCreditAmount);
1667      })
1668      .catch(error => {
1669        removeCookie('customer_referral_code');
1670      });
1671  }
1672    
1673  function displayReferralNotification(creditAmount = null) {
1674    const isMobile = innerWidth <= 749;
1675    
1676    if (isMobile) {
1677      const mobileModal = document.querySelector('#referralMobileModal details');
1678      const mobileMessageElement = document.getElementById('referralSignupMessageMobile');
1679      
1680      if (mobileModal && mobileMessageElement) {
1681        if (creditAmount) {
1682          const finalMessage = referralMessageTemplate
1683            .replace('__CREDIT_AMOUNT__', creditAmount)
1684            .replace('__CURRENCY_CODE__', shopCurrency);
1685          
1686          mobileMessageElement.textContent = finalMessage;
1687        }
1688        
1689        mobileModal.setAttribute('open', '');
1690      }
1691    } else {
1692      const notification = document.getElementById('referralNotification');
1693      
1694      if (notification) {
1695        if (creditAmount) {
1696          const messageElement = document.getElementById('referralSignupMessage');
1697          if (messageElement) {
1698            const finalMessage = referralMessageTemplate
1699              .replace('__CREDIT_AMOUNT__', creditAmount)
1700              .replace('__CURRENCY_CODE__', shopCurrency);
1701            
1702            messageElement.textContent = finalMessage;
1703          }
1704        }
1705        
1706        notification.style.display = 'block';
1707      }
1708    }
1709  }
1710
1711  showReferralNotification();
1712
1713  addEventListener('beforeunload', function() {
1714    const referralData = JSON.parse(localStorage.getItem('referral_notification_data')) || {};
1715    
1716    if (referralData.creditAmount !== undefined) {
1717      referralData.creditAmount = null;
1718      localStorage.setItem('referral_notification_data', JSON.stringify(referralData));
1719    }
1720  });
1721
1722  function closeReferralNotification() {
1723    const notification = document.getElementById('referralNotification');
1724    if (notification) {
1725      notification.style.display = 'none';
1726    }
1727  }
1728
1729  function dismissReferralNotification() {
1730    const referralData = JSON.parse(localStorage.getItem('referral_notification_data')) || {};
1731    
1732    referralData.dismissed = true;
1733    referralData.timestamp = referralData.timestamp || Date.now();
1734    referralData.expirationDays = referralData.expirationDays || 3;
1735    
1736    localStorage.setItem('referral_notification_data', JSON.stringify(referralData));
1737    
1738    closeReferralNotification();
1739  }
1740
1741  function goToSignupPage() {
1742    location.href = '/account/register';
1743    dismissReferralNotification();
1744  }
1745
1746  function closeMobileReferralModal() {
1747    const mobileModal = document.querySelector('#referralMobileModal details');
1748    if (mobileModal) {
1749      mobileModal.removeAttribute('open');
1750    }
1751    
1752    const referralData = JSON.parse(localStorage.getItem('referral_notification_data')) || {};
1753    referralData.dismissed = true;
1754    referralData.timestamp = referralData.timestamp || Date.now();
1755    referralData.expirationDays = referralData.expirationDays || 3;
1756    localStorage.setItem('referral_notification_data', JSON.stringify(referralData));
1757  }
1758
1759  function goToSignupPageFromMobile() {
1760    location.href = '/account/register';
1761    closeMobileReferralModal();
1762  }
1763  // End - referral notification popup
1764</script>
1764
1765
1766
1767
1768  <main id="MainContent" class="content-for-layout focus-none" role="main" tabindex="-1">
1769    
1770    
1771
1772
1773<section class="spaced-section page-width">
1774  <div class="rte">
1775    <link href='/assets/css/froala_style.min.css' rel='stylesheet' type='text/css'/><div class='fr-view'><style>
1776@media (min-width: 768px) {
1777  .fl-store-page {
1778    margin-top: -280px;
1779  }
1780}
1781</style>
1782
1783<div class="fl-store-page">
1784<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3985.2988313053997!2d101.9234359137365!3d2.7273868555824055!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x31cddd6890538af1%3A0xaa502e87cd1e9ad3!2sFine%20Label%20Sdn%20Bhd!5e0!3m2!1sen!2smy!4v1783157857083!5m2!1sen!2smy" width="100%" height="450" style="border:0;" allowfullscreen="">
1785</iframe>
1786
1787
1788<h2>📍 Visit Our Boutique</h2>
1789
1790<p><strong>Fine Label Sdn Bhd</strong>
1791<br> No.20-G, Jalan PKL 2,
1792<br> Pusat Komersial Lobak,
1793<br> 70200 Seremban, Negeri Sembilan,
1794<br> Malaysia.
1795</p>
1796
1797<p><strong>🕒 Opening Hours</strong>
1798<br> Mon, Thu &amp; Sun: 10:00AM &ndash; 5:30PM
1799<br> Tue, Wed, Fri &amp; Sat: 10:00AM &ndash; 7:00PM</p>
1800
1801<p><strong>📱 WhatsApp</strong>
1802<br>
1803<a href="https://wa.me/60105133557">+6010-5133557</a></p>
1804
1805<p>
1806<a href="https://www.google.com/maps/search/?api=1&query=Fine%20Label%20Sdn%20Bhd%20No.20-G%20Jalan%20PKL%202%20Pusat%20Komersial%20Lobak%2070200%20Seremban" target="_blank" style="display:inline-block;padding:12px 18px;background:#111;color:#fff;text-decoration:none;border-radius:6px;">
1807Get Directions &rarr;
1808</a>
1809</p></div>
1810    
1810<script type="text/javascript">
1811      $("img[data-type=youtube]").click(function(){
1812        var this_parent = $(this).closest("div.Grid-cell--wrapper");
1813        var height = $(this_parent).height();
1814        var youtube_player = document.createElement("iframe");
1815        youtube_player.setAttribute("style", "width:100%;  height:"+height+"px;");
1816        youtube_player.setAttribute("allowfullscreen","");
1817        youtube_player.setAttribute("src","https://www.youtube.com/embed/"+$(this).data("youtube-id")+"?autoplay=1&fs=1");
1818        this_parent.html(youtube_player);
1819      });
1820    </script>
1820</div>
1821    <link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-card.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
1822<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-price.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
1823<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/component-product-grid.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
1824
1825
1826
1827
1828  </div>
1829</section>
1830
1831
1832    
1833  </main>
1834 	<style>
1835  .footer{
1836    background-color: #FFFFFF;
1837    color: #000000;
1838    --color-foreground: 0,0,0;
1839  }
1840  .footer .link--text,
1841  .footer .list-menu__item--link,
1842  .footer .footer-block__details-content .list-menu__item--link{
1843    color: #000000;
1844  }
1845  .footer-block__heading{
1846    color: #000000;
1847  }
1848</style>
1849
1850<link rel="preload" href="https://store-themes.easystore.co/1325208/themes/308896/assets/section-footer.css?t=1791095546" as="style" onload="this.onload=null;this.rel='stylesheet'">
1851
1852<footer class="footer color-background-1">
1853  <div class="footer__content-top page-width">
1854    <div class="grid grid--1-col grid--4-col-tablet ">
1855      
1856      
1857      
1858        <div class="grid__item">
1859          
1860              <h2 class="footer-block__heading">Follow us</h2>
1861              <ul class="footer__list-social list-unstyled list-social footer-block__details-content" role="list">
1862                
1863                
1864                  <li class="list-social__item">
1865                    <a href="https://www.facebook.com/finelabel22" class="link link--text list-social__link">
1866                      
1867
1868
1869    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-facebook "
1870    viewBox="0 0 18 18">
1871      <path fill="currentColor"
1872        d="M16.42.61c.27 0 .5.1.69.28.19.2.28.42.28.7v15.44c0 .27-.1.5-.28.69a.94.94 0 01-.7.28h-4.39v-6.7h2.25l.31-2.65h-2.56v-1.7c0-.4.1-.72.28-.93.18-.2.5-.32 1-.32h1.37V3.35c-.6-.06-1.27-.1-2.01-.1-1.01 0-1.83.3-2.45.9-.62.6-.93 1.44-.93 2.53v1.97H7.04v2.65h2.24V18H.98c-.28 0-.5-.1-.7-.28a.94.94 0 01-.28-.7V1.59c0-.27.1-.5.28-.69a.94.94 0 01.7-.28h15.44z">
1873      </path>
1874    </svg>
1875
1876  
1877
1878                    </a>
1879                  </li>
1880                
1881                
1882                  <li class="list-social__item">
1883                    <a href="https://www.instagram.com/finelabel22" class="link link--text list-social__link">
1884                      
1885
1886
1887    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-instagram "
1888    viewBox="0 0 18 18">
1889      <path fill="currentColor"
1890        d="M8.77 1.58c2.34 0 2.62.01 3.54.05.86.04 1.32.18 1.63.3.41.17.7.35 1.01.66.3.3.5.6.65 1 .12.32.27.78.3 1.64.05.92.06 1.2.06 3.54s-.01 2.62-.05 3.54a4.79 4.79 0 01-.3 1.63c-.17.41-.35.7-.66 1.01-.3.3-.6.5-1.01.66-.31.12-.77.26-1.63.3-.92.04-1.2.05-3.54.05s-2.62 0-3.55-.05a4.79 4.79 0 01-1.62-.3c-.42-.16-.7-.35-1.01-.66-.31-.3-.5-.6-.66-1a4.87 4.87 0 01-.3-1.64c-.04-.92-.05-1.2-.05-3.54s0-2.62.05-3.54c.04-.86.18-1.32.3-1.63.16-.41.35-.7.66-1.01.3-.3.6-.5 1-.65.32-.12.78-.27 1.63-.3.93-.05 1.2-.06 3.55-.06zm0-1.58C6.39 0 6.09.01 5.15.05c-.93.04-1.57.2-2.13.4-.57.23-1.06.54-1.55 1.02C1 1.96.7 2.45.46 3.02c-.22.56-.37 1.2-.4 2.13C0 6.1 0 6.4 0 8.77s.01 2.68.05 3.61c.04.94.2 1.57.4 2.13.23.58.54 1.07 1.02 1.56.49.48.98.78 1.55 1.01.56.22 1.2.37 2.13.4.94.05 1.24.06 3.62.06 2.39 0 2.68-.01 3.62-.05.93-.04 1.57-.2 2.13-.41a4.27 4.27 0 001.55-1.01c.49-.49.79-.98 1.01-1.56.22-.55.37-1.19.41-2.13.04-.93.05-1.23.05-3.61 0-2.39 0-2.68-.05-3.62a6.47 6.47 0 00-.4-2.13 4.27 4.27 0 00-1.02-1.55A4.35 4.35 0 0014.52.46a6.43 6.43 0 00-2.13-.41A69 69 0 008.77 0z">
1891      </path>
1892      <path fill="currentColor"
1893        d="M8.8 4a4.5 4.5 0 100 9 4.5 4.5 0 000-9zm0 7.43a2.92 2.92 0 110-5.85 2.92 2.92 0 010 5.85zM13.43 5a1.05 1.05 0 100-2.1 1.05 1.05 0 000 2.1z">
1894      </path>
1895    </svg>
1896
1897  
1898
1899                    </a>
1900                  </li>
1901                
1902                
1903                  <li class="list-social__item">
1904                    <a href="https://www.tiktok.com/finelabel22" class="link link--text list-social__link">
1905                      
1906
1907
1908    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-tiktok " width="16"
1909    height="18" fill="none" xmlns="http://www.w3.org/2000/svg">
1910      <path
1911        d="M8.02 0H11s-.17 3.82 4.13 4.1v2.95s-2.3.14-4.13-1.26l.03 6.1a5.52 5.52 0 11-5.51-5.52h.77V9.4a2.5 2.5 0 101.76 2.4L8.02 0z"
1912        fill="currentColor">
1913      </path>
1914    </svg>
1915
1916  
1917
1918                    </a>
1919                  </li>
1920                
1921                
1922                  <li class="list-social__item">
1923                    <a href="https://wa.me/60105133557" class="link link--text list-social__link">
1924                      
1925
1926
1927    <svg class="icon icon-whatsapp " fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 750 750">
1927<path d="M703.5,195.64A371,371,0,0,0,572,56C523.89,26,471.51,8.4,415.21,2.51A370.48,370.48,0,0,0,316.5,5.42,364,364,0,0,0,215.23,37.47a369,369,0,0,0-132.68,108Q17.36,230.17,7,336.63A370.11,370.11,0,0,0,53.42,554.94a7.23,7.23,0,0,1,.61,4.9Q36.48,624.6,18.7,689.27C13.24,709.19,7.75,729.1,2.14,749.5c1.23-.26,1.93-.36,2.61-.55q95.75-25.11,191.54-50.2a8.43,8.43,0,0,1,5.19.61c12.79,5.8,25.28,12.34,38.29,17.59A370.28,370.28,0,0,0,666.09,604q69.06-86.36,80-196.47A370.36,370.36,0,0,0,743,311.86,361,361,0,0,0,703.5,195.64ZM684.64,388c-3.6,65.27-25.48,123.75-66.06,174.9-44.89,56.63-102.85,93.24-173.19,109.84a297.41,297.41,0,0,1-91.27,7A305.68,305.68,0,0,1,215.31,635a17.54,17.54,0,0,0-15.2-2.14c-35.5,9.58-71.1,18.74-106.66,28-.49.13-1,.21-2.14.45,1.72-6.37,3.29-12.22,4.89-18Q109,596.7,121.66,550.07a7.12,7.12,0,0,0-1-5.07c-12.37-19.32-23.31-39.25-31.6-60.64A309,309,0,0,1,70.4,410.63c-6.11-49.35-.93-97.44,16.1-144.15,57.86-160.1,234.55-243,394.65-185.11a308.31,308.31,0,0,1,120.2,79.18c34.9,37.19,59.32,80.31,72.81,129.53A304.75,304.75,0,0,1,684.64,388Z"/><path d="M556,454.42c-13.84-6.52-27.43-13.55-41.24-20.12-11.47-5.46-23-10.89-34.73-15.69-9.1-3.73-13.09-1.72-19.12,6.06-9.39,12.09-19.09,23.95-28.89,35.71-4.7,5.63-9.47,6.79-16.1,3.8-12.32-5.56-24.82-10.9-36.58-17.51-39.6-22.29-69.59-54.3-92.67-93.11-4.87-8.2-4.3-12.16,2.14-19.13,9.07-9.9,18.4-19.63,24.09-32.12a17.42,17.42,0,0,0,.47-14.67c-9.55-23-19-46-28.75-68.92a75.82,75.82,0,0,0-7-12.7c-2.56-3.82-6.6-5.49-11.28-5.36H255.78v-.56c-5.48.29-11,.11-16.39,1-8.66,1.37-15,6.75-20.95,12.94-25.46,26.48-34.58,57.89-28.66,93.83a145.64,145.64,0,0,0,20.75,53.75C220.48,377.5,231.32,393,242.65,408a435.09,435.09,0,0,0,70.53,73.19c31.48,26,67,44.54,105.56,57.58,16.1,5.44,32.08,11.08,49.36,11.42,11.52.22,23,.08,34.16-3.22a110.77,110.77,0,0,0,42.1-23.61c5.48-4.81,10.48-10.18,13.19-17a110.56,110.56,0,0,0,7.57-37.2C565.27,461.93,562.42,457.42,556,454.42Z"/></svg>
1928
1929  
1930
1931                    </a>
1932                  </li>
1933                
1934                
1935                
1936                
1937                  <li class="list-social__item">
1938                    <a href="https://www.youtube.com/@finelabel5830" class="link link--text list-social__link">
1939                      
1940
1941
1942    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon-youtube "
1943    viewBox="0 0 100 70">
1944      <path
1945        d="M98 11c2 7.7 2 24 2 24s0 16.3-2 24a12.5 12.5 0 01-9 9c-7.7 2-39 2-39 2s-31.3 0-39-2a12.5 12.5 0 01-9-9c-2-7.7-2-24-2-24s0-16.3 2-24c1.2-4.4 4.6-7.8 9-9 7.7-2 39-2 39-2s31.3 0 39 2c4.4 1.2 7.8 4.6 9 9zM40 50l26-15-26-15v30z"
1946        fill="currentColor">
1947      </path>
1948    </svg>
1949
1950  
1951
1952                    </a>
1953                  </li>
1954                
1955                
1956              </ul>
1957            
1958        </div>
1959      
1960      
1961      
1962        <div class="grid__item">
1963          
1964              <h2 class="footer-block__heading">We accept</h2>
1965              <div class="footer-block__details-content footer__payment">
1966                <ul class="list list-payment" role="list">
1967                  
1968                    <li class="list-payment__item">
1969                      
1970
1971
1972    <svg class="icon icon--full-color " viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" role="img"
1973    width="38" height="24" aria-labelledby="pi-visa">
1974      <path opacity=".07"
1975        d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path>
1976      <path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32">
1977      </path>
1978      <path
1979        d="M28.3 10.1H28c-.4 1-.7 1.5-1 3h1.9c-.3-1.5-.3-2.2-.6-3zm2.9 5.9h-1.7c-.1 0-.1 0-.2-.1l-.2-.9-.1-.2h-2.4c-.1 0-.2 0-.2.2l-.3.9c0 .1-.1.1-.1.1h-2.1l.2-.5L27 8.7c0-.5.3-.7.8-.7h1.5c.1 0 .2 0 .2.2l1.4 6.5c.1.4.2.7.2 1.1.1.1.1.1.1.2zm-13.4-.3l.4-1.8c.1 0 .2.1.2.1.7.3 1.4.5 2.1.4.2 0 .5-.1.7-.2.5-.2.5-.7.1-1.1-.2-.2-.5-.3-.8-.5-.4-.2-.8-.4-1.1-.7-1.2-1-.8-2.4-.1-3.1.6-.4.9-.8 1.7-.8 1.2 0 2.5 0 3.1.2h.1c-.1.6-.2 1.1-.4 1.7-.5-.2-1-.4-1.5-.4-.3 0-.6 0-.9.1-.2 0-.3.1-.4.2-.2.2-.2.5 0 .7l.5.4c.4.2.8.4 1.1.6.5.3 1 .8 1.1 1.4.2.9-.1 1.7-.9 2.3-.5.4-.7.6-1.4.6-1.4 0-2.5.1-3.4-.2-.1.2-.1.2-.2.1zm-3.5.3c.1-.7.1-.7.2-1 .5-2.2 1-4.5 1.4-6.7.
19791-.2.1-.3.3-.3H18c-.2 1.2-.4 2.1-.7 3.2-.3 1.5-.6 3-1 4.5 0 .2-.1.2-.3.2M5 8.2c0-.1.2-.2.3-.2h3.4c.5 0 .9.3 1 .8l.9 4.4c0 .1 0 .1.1.2 0-.1.1-.1.1-.1l2.1-5.1c-.1-.1 0-.2.1-.2h2.1c0 .1 0 .1-.1.2l-3.1 7.3c-.1.2-.1.3-.2.4-.1.1-.3 0-.5 0H9.7c-.1 0-.2 0-.2-.2L7.9 9.5c-.2-.2-.5-.5-.9-.6-.6-.3-1.7-.5-1.9-.5L5 8.2z"
1980        fill="#142688"></path>
1981    </svg>
1982
1983  
1984
1985                    </li>
1986                  
1987                  
1988                    <li class="list-payment__item">
1989                      
1990
1991
1992    <svg class="icon icon--full-color " viewBox="0 0 38 24" xmlns="http://www.w3.org/2000/svg" role="img"
1993    width="38" height="24" aria-labelledby="pi-master">
1994      <path opacity=".07"
1995        d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z"></path>
1996      <path fill="#fff" d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32">
1997      </path>
1998      <circle fill="#EB001B" cx="15" cy="12" r="7"></circle>
1999      <circle fill="#F79E1B" cx="23" cy="12" r="7"></circle>
2000      <path fill="#FF5F00"
2001        d="M22 12c0-2.4-1.2-4.5-3-5.7-1.8 1.3-3 3.4-3 5.7s1.2 4.5 3 5.7c1.8-1.2 3-3.3 3-5.7z"></path>
2002    </svg>
2003
2004  
2005
2006                    </li>
2007                  
2008                  
2009                  
2010                  
2011                  
2012									
2013                    
2014                      <li class="list-payment__item">
2015                        <img src="https://s3.dualstack.ap-southeast-1.amazonaws.com/eesb.public/images/payment/payments_ipay88.svg" alt="payment_ipay88" loading="lazy" width="85px">
2016                      </li>
2017                    
2018                      <li class="list-payment__item">
2019                        <img src="https://s3.dualstack.ap-southeast-1.amazonaws.com/eesb.public/images/payment/payments_tngpay.svg" alt="payment_tngpay" loading="lazy" width="85px">
2020                      </li>
2021                    
2022                 
2023              </div>
2024              
2025        </div>
2026      
2027      
2028      
2029        <div class="grid__item">
2030          
2031              <h2 class="footer-block__heading">
2032                Quick links
2033              </h2>
2034              <ul class="footer-block__details-content list-unstyled">
2035                
2036                <li>
2037                  <a href="/store-locator"  class="link link--text list-menu__item list-menu__item--link">
2038                    Location
2039                  </a>
2040                </li>
2041                
2042                <li>
2043                  <a href="/a/contact-form"  class="link link--text list-menu__item list-menu__item--link">
2044                    Contact us
2045                  </a>
2046                </li>
2047                
2048                
2049              </ul>
2050            
2051        </div>
2052      
2053      
2054      
2055        <div class="grid__item">
2056          
2057              <h2 class="footer-block__heading">Company Infos</h2>
2058              <div class="footer-block__details-content">
2059                <p>Fine Label Sdn Bhd (202201022221) No.20-G, Jalan PKL 2, Pusat Komersir Lobak, 70200 Seremban, N.S.D.K.</p>
2060              </div>
2061            
2062        </div>
2063      
2064    </div>
2065  </div>
2066  <div class="footer__content-bottom">
2067    <div class="footer__content-bottom-wrapper page-width">
2068      <div class="footer__column footer__column--info">
2069
2070        
2071
2072
2073
2074
2075        
2076        <div class="footer__copyright caption">
2077          <div class="copyright__content">Copyright to FINE LABEL © 2026</div>
2078        </div>
2079
2080        <div class="footer__copyright caption">
2081          
2082            <div>
2083            
2084            
2085              
2086                <a href="/legal/terms-of-service">Terms of Service</a>
2087              
2088              
2089            
2090              
2091                | <a href="/legal/privacy-policy">Privacy Policy</a>
2092              
2093              
2094            
2095              
2096                | <a href="/legal/refund-policy">Returns Policy</a>
2097              
2098              
2099            
2100              
2101                | <a href="/legal/shipping-delivery">Shipping &amp; Delivery</a>
2102              
2103              
2104            
2105            </div>
2106         
2107        </div>
2108        
2109      </div>
2110    </div>
2111  </div>
2112</footer>
2113
2114
2115
2116
2117  
2118
2119  
2119<script>
2120  EasyStore.Currencies.init([{"name":"Malaysian Ringgit","code":"MYR","rate":"1.0","format_prefix":"RM","format_suffix":null,"format_decimals":2,"thousand_separator":",","is_primary":true}], 1)
2121</script>
2121
2122
2123
2124
2125  
2125<script>
2126    let page_template = 'page';
2127
2128    if(document.querySelector('.currency-picker')) {
2129      EasyStore.Currencies.change(document.querySelector('.currency-picker').value)
2130      EasyStore.Currencies.convertAll() 
2131    }
2132
2133    document.querySelectorAll('.currency-picker').forEach((el)=>{
2134      el.addEventListener('change',(event)=>{
2135        EasyStore.Currencies.change(event.target.value)
2136
2137        
2138          if (page_template == 'cart') {
2139            const params = new URLSearchParams(window.location.search);
2140            params.set('delete_cache', 1);
2141            window.location.search = params;
2142          } else {
2143            window.location.reload();
2144          }
2145
2146          return
2147        
2148
2149        document.querySelectorAll('[name=currencies],[name=current_currency]').forEach((el)=>{
2150          el.value = event.target.value
2151        })
2152
2153        if(page_template == 'cart') location.reload();
2154      })
2155    })
2156  </script>
2156
2157
2158
2159
2160
2161  
2161<script>
2162
2163    window.variantStrings = {
2164      addToCart: `Add to Cart`,
2165      soldOut: `Sold Out`,
2166      unavailable: `Unavailable`,
2167    }
2168
2169    window.accessibilityStrings = {
2170      shareSuccess: `Link copied to clipboard`,
2171    }
2172  </script>
2172
2173  
2174<!-- Snippet:global/body_end: Product Label -->
2175<link href='https://apps.easystore.co/assets/css/product-label/main.css?v2.3' rel='stylesheet' type='text/css' media='screen' />
2175<script src='https://apps.easystore.co/product-labels/productlabelv2.js?shop=miyacostore.easy.co' type='text/javascript'></script>
2175
2176<!-- /Snippet -->
2177
2178<!-- Snippet:global/body_end: Insert Code -->
2179
2180<!--Fine Label Browser Test - PageView-->
2181<script>
2182(function () {
2183
2184  if (
2185    window.__FL_META_BROWSER_MATCH_INSTALLED__
2186  ) {
2187    return;
2188  }
2189
2190  window.__FL_META_BROWSER_MATCH_INSTALLED__ =
2191    true;
2192
2193
2194  /*
2195   * ============================================================
2196   * Fine Label Browser Tracking
2197   *
2198   * CURRENT PRODUCTION STATE
2199   *
2200   * Browser Match Capture:
2201   *   LIVE
2202   *
2203   * Fine Label Meta Browser Events (fbq):
2204   *   BUILT BUT DISABLED
2205   *
2206   * Fine Label Server ViewContent CAPI:
2207   *   PRODUCTION READY / GLOBAL OFF
2208   *
2209   * Fine Label Server AddToCart CAPI:
2210   *   PRODUCTION ON
2211   *   /cart/add fetch fallback enabled
2212   *
2213   * Fine Label Server InitiateCheckout CAPI:
2214   *   PRODUCTION ON
2215   *
2216   * Production CAPI Purchase:
2217   *   Controlled separately server-side
2218   *
2219   * IMPORTANT:
2220   * Keep this FALSE while EasyStore
2221   * native Meta integration is ON.
2222   * ============================================================
2223   */
2224
2225
2226  var FL_META_BROWSER_EVENTS_ENABLED = false
2227
2228
2229  /*
2230   * Server-side ViewContent test sender.
2231   *
2232   * This does NOT call fbq() and does NOT
2233   * initialize the Fine Label main pixel.
2234   */
2235
2236  var FL_META_SERVER_VIEWCONTENT_ENABLED =
2237    true;
2238
2239
2240  var FL_META_SERVER_TEST_SESSION_KEY =
2241    'FL_META_SERVER_TEST_V1';
2242
2243
2244  /*
2245   * Server-side AddToCart test sender.
2246   *
2247   * Global switch stays FALSE.
2248   * Only a browser tab/session that explicitly
2249   * opts in can send AddToCart test events.
2250   */
2251
2252var FL_META_SERVER_ADDTOCART_ENABLED =
2253  true;
2254
2255
2256  var FL_META_SERVER_ADDTOCART_TEST_SESSION_KEY =
2257    'FL_META_SERVER_ATC_TEST_V1';
2258
2259
2260  /*
2261   * Server-side InitiateCheckout test sender.
2262   *
2263   * Global switch stays FALSE.
2264   * Only a browser tab/session that explicitly
2265   * opts in can send InitiateCheckout test events.
2266   */
2267
2268  var FL_META_SERVER_INITIATECHECKOUT_ENABLED =
2269    true;
2270
2271
2272  var FL_META_SERVER_INITIATECHECKOUT_TEST_SESSION_KEY =
2273    'FL_META_SERVER_IC_TEST_V1';
2274
2275
2276  /*
2277   * Fine Label MAIN Meta Pixel
2278   */
2279
2280  var META_PIXEL_ID =
2281    '102469937081458';
2282
2283
2284  /*
2285   * Fine Label Cloud Run
2286   * Browser Match endpoint
2287   */
2288
2289  var ENDPOINT =
2290    'https://fine-label-ai-backend-72rwgpxz4a-as.a.run.app/v1/meta/browser-match';
2291
2292
2293  /*
2294   * Fine Label Cloud Run
2295   * Server Browser Event endpoints
2296   *
2297   * TEST:
2298   *   Sends with TEST45364 through the
2299   *   test-tagged Cloud Run revision.
2300   *
2301   * PRODUCTION:
2302   *   Sends without test_event_code through
2303   *   the production-candidate tagged revision.
2304   *
2305   * All three production global switches
2306   * remain FALSE until final cutover.
2307   */
2308
2309  var SERVER_BROWSER_EVENT_TEST_ENDPOINT =
2310    'https://meta-browser-event-test---fine-label-ai-backend-72rwgpxz4a-as.a.run.app/v1/meta/browser-event';
2311
2312
2313  var SERVER_BROWSER_EVENT_PROD_ENDPOINT =
2314    'https://meta-browser-event-prod---fine-label-ai-backend-72rwgpxz4a-as.a.run.app/v1/meta/browser-event';
2315
2316
2317  function getServerBrowserEventEndpoint(
2318    globalEnabled,
2319    sessionKey
2320  ) {
2321
2322    if (globalEnabled === true) {
2323
2324      return (
2325        SERVER_BROWSER_EVENT_PROD_ENDPOINT
2326      );
2327
2328    }
2329
2330
2331    try {
2332
2333      if (
2334        sessionStorage.getItem(
2335          sessionKey
2336        ) === '1'
2337      ) {
2338
2339        return (
2340          SERVER_BROWSER_EVENT_TEST_ENDPOINT
2341        );
2342
2343      }
2344
2345    } catch (e) {}
2346
2347
2348    return '';
2349
2350  }
2351
2352
2353  /*
2354   * ============================================================
2355   * Session Storage Keys
2356   * ============================================================
2357   */
2358
2359
2360  var CART_TOKEN_KEY =
2361    'FL_META_CART_TOKEN_V1';
2362
2363
2364  var ORDER_TOKEN_KEY =
2365    'FL_META_ORDER_TOKEN_V1';
2366
2367
2368  var INITIATE_CHECKOUT_SENT_KEY =
2369    'FL_META_IC_SENT_CART_V1';
2370
2371
2372  /*
2373   * ============================================================
2374   * Runtime State
2375   * ============================================================
2376   */
2377
2378
2379  var lastAddToCart =
2380    null;
2381
2382
2383  var lastInitiateCheckout =
2384    null;
2385
2386
2387  var metaEventsSent =
2388    0;
2389
2390
2391  var lastMetaEvent =
2392    null;
2393
2394
2395  var pageViewSent =
2396    false;
2397
2398
2399  var lastServerViewContentKey =
2400    null;
2401
2402
2403  var serverViewContentRequests =
2404    0;
2405
2406
2407  var lastServerViewContent =
2408    null;
2409
2410
2411  var serverAddToCartRequests =
2412    0;
2413
2414
2415  var lastServerAddToCart =
2416    null;
2417
2418
2419  var lastAddToCartSource =
2420    null;
2421
2422
2423  var lastAddToCartFallback =
2424    null;
2425
2426
2427  var pendingCartAddRequests =
2428    [];
2429
2430
2431  var cartAddRequestSequence =
2432    0;
2433
2434
2435  var serverInitiateCheckoutRequests =
2436    0;
2437
2438
2439  var lastServerInitiateCheckout =
2440    null;
2441
2442
2443  /*
2444   * ============================================================
2445   * Cookie Helper
2446   * ============================================================
2447   */
2448
2449
2450  function getCookie(name) {
2451
2452    var prefix =
2453      name + '=';
2454
2455
2456    var parts =
2457      document.cookie.split(';');
2458
2459
2460    for (
2461      var i = 0;
2462      i < parts.length;
2463      i += 1
2464    ) {
2465
2466      var item =
2467        parts[i].trim();
2468
2469
2470      if (
2471        item.indexOf(prefix) === 0
2472      ) {
2473
2474        return decodeURIComponent(
2475          item.substring(
2476            prefix.length
2477          )
2478        );
2479
2480      }
2481
2482    }
2483
2484
2485    return '';
2486
2487  }
2488
2489
2490  /*
2491   * ============================================================
2492   * Session Token Helpers
2493   * ============================================================
2494   */
2495
2496
2497  function saveTokens(
2498    cartToken,
2499    orderToken
2500  ) {
2501
2502    try {
2503
2504      if (cartToken) {
2505
2506        sessionStorage.setItem(
2507          CART_TOKEN_KEY,
2508          String(cartToken)
2509        );
2510
2511      }
2512
2513
2514      if (orderToken) {
2515
2516        sessionStorage.setItem(
2517          ORDER_TOKEN_KEY,
2518          String(orderToken)
2519        );
2520
2521      }
2522
2523    } catch (e) {}
2524
2525  }
2526
2527
2528  function getSavedCartToken() {
2529
2530    try {
2531
2532      return (
2533        sessionStorage.getItem(
2534          CART_TOKEN_KEY
2535        ) || ''
2536      );
2537
2538    } catch (e) {
2539
2540      return '';
2541
2542    }
2543
2544  }
2545
2546
2547  function getSavedOrderToken() {
2548
2549    try {
2550
2551      return (
2552        sessionStorage.getItem(
2553          ORDER_TOKEN_KEY
2554        ) || ''
2555      );
2556
2557    } catch (e) {
2558
2559      return '';
2560
2561    }
2562
2563  }
2564
2565
2566  /*
2567   * ============================================================
2568   * Checkout URL Token
2569   *
2570   * /sf/checkout/<cart_token>
2571   * ============================================================
2572   */
2573
2574
2575  function checkoutTokenFromUrl() {
2576
2577    var match =
2578      location.pathname.match(
2579        /^\/sf\/checkout\/([^/?#]+)/
2580      );
2581
2582
2583    return match
2584      ? match[1]
2585      : '';
2586
2587  }
2588
2589
2590  /*
2591   * ============================================================
2592   * Browser Match Diagnostic
2593   * ============================================================
2594   */
2595
2596
2597  function setLastStatus(data) {
2598
2599    window
2600      .__FL_META_BROWSER_MATCH_LAST__ =
2601        data;
2602
2603  }
2604
2605
2606  /*
2607   * ============================================================
2608   * Browser Match Capture
2609   *
2610   * THIS PART IS LIVE.
2611   * ============================================================
2612   */
2613
2614
2615  function capture(
2616    eventName,
2617    cartToken,
2618    orderToken
2619  ) {
2620
2621    cartToken =
2622      String(
2623        cartToken || ''
2624      ).trim();
2625
2626
2627    orderToken =
2628      String(
2629        orderToken || ''
2630      ).trim();
2631
2632
2633    if (!cartToken) {
2634
2635      setLastStatus({
2636
2637        success:
2638          false,
2639
2640        skipped:
2641          true,
2642
2643        reason:
2644          'NO_CART_TOKEN',
2645
2646        event:
2647          eventName,
2648
2649        captured_at:
2650          new Date()
2651            .toISOString()
2652
2653      });
2654
2655
2656      return;
2657
2658    }
2659
2660
2661    saveTokens(
2662      cartToken,
2663      orderToken
2664    );
2665
2666
2667    var payload = {
2668
2669      cart_token:
2670        cartToken,
2671
2672      order_token:
2673        orderToken,
2674
2675      fbp:
2676        getCookie('_fbp'),
2677
2678      fbc:
2679        getCookie('_fbc'),
2680
2681      path:
2682        location.pathname,
2683
2684      event:
2685        eventName
2686
2687    };
2688
2689
2690    fetch(
2691      ENDPOINT,
2692      {
2693
2694        method:
2695          'POST',
2696
2697        headers: {
2698
2699          'Content-Type':
2700            'application/json'
2701
2702        },
2703
2704        body:
2705          JSON.stringify(
2706            payload
2707          ),
2708
2709        keepalive:
2710          true
2711
2712      }
2713    )
2714
2715    .then(
2716      function (response) {
2717
2718        setLastStatus({
2719
2720          success:
2721            response.ok,
2722
2723          status:
2724            response.status,
2725
2726          event:
2727            eventName,
2728
2729          has_fbp:
2730            Boolean(
2731              payload.fbp
2732            ),
2733
2734          has_fbc:
2735            Boolean(
2736              payload.fbc
2737            ),
2738
2739          captured_at:
2740            new Date()
2741              .toISOString()
2742
2743        });
2744
2745      }
2746    )
2747
2748    .catch(
2749      function () {
2750
2751        setLastStatus({
2752
2753          success:
2754            false,
2755
2756          status:
2757            null,
2758
2759          event:
2760            eventName,
2761
2762          has_fbp:
2763            Boolean(
2764              payload.fbp
2765            ),
2766
2767          has_fbc:
2768            Boolean(
2769              payload.fbc
2770            ),
2771
2772          captured_at:
2773            new Date()
2774              .toISOString()
2775
2776        });
2777
2778      }
2779    );
2780
2781  }
2782
2783
2784  /*
2785   * ============================================================
2786   * Meta Pixel Loader
2787   *
2788   * IMPORTANT:
2789   *
2790   * This runs ONLY when:
2791   *
2792   * FL_META_BROWSER_EVENTS_ENABLED = true
2793   *
2794   * It does NOT run now.
2795   * ============================================================
2796   */
2797
2798
2799  function ensureFineLabelMetaPixel() {
2800
2801    if (
2802      !FL_META_BROWSER_EVENTS_ENABLED
2803    ) {
2804
2805      return false;
2806
2807    }
2808
2809
2810    if (!window.fbq) {
2811
2812      (function (
2813        f,
2814        b,
2815        e,
2816        v,
2817        n,
2818        t,
2819        s
2820      ) {
2821
2822        if (f.fbq) {
2823          return;
2824        }
2825
2826
2827        n =
2828          f.fbq =
2829          function () {
2830
2831            n.callMethod
2832              ? n.callMethod
2833                  .apply(
2834                    n,
2835                    arguments
2836                  )
2837              : n.queue
2838                  .push(
2839                    arguments
2840                  );
2841
2842          };
2843
2844
2845        if (!f._fbq) {
2846
2847          f._fbq =
2848            n;
2849
2850        }
2851
2852
2853        n.push =
2854          n;
2855
2856
2857        n.loaded =
2858          true;
2859
2860
2861        n.version =
2862          '2.0';
2863
2864
2865        n.queue =
2866          [];
2867
2868
2869        t =
2870          b.createElement(
2871            e
2872          );
2873
2874
2875        t.async =
2876          true;
2877
2878
2879        t.src =
2880          v;
2881
2882
2883        s =
2884          b.getElementsByTagName(
2885            e
2886          )[0];
2887
2888
2889        s.parentNode.insertBefore(
2890          t,
2891          s
2892        );
2893
2894      })(
2895        window,
2896        document,
2897        'script',
2898        'https://connect.facebook.net/en_US/fbevents.js'
2899      );
2900
2901    }
2902
2903
2904    /*
2905     * Fine Label controlled init.
2906     *
2907     * At final cutover:
2908     *
2909     * EasyStore Meta integration
2910     * must already be OFF.
2911     */
2912
2913    if (
2914      !window
2915        .__FL_META_MAIN_PIXEL_INITIALIZED__
2916    ) {
2917
2918      window.fbq(
2919        'init',
2920        META_PIXEL_ID
2921      );
2922
2923
2924      window
2925        .__FL_META_MAIN_PIXEL_INITIALIZED__ =
2926          true;
2927
2928    }
2929
2930
2931    return (
2932      typeof window.fbq ===
2933        'function'
2934    );
2935
2936  }
2937
2938
2939  /*
2940   * ============================================================
2941   * Fine Label Meta Sender
2942   *
2943   * Uses trackSingle so Fine Label
2944   * explicitly targets MAIN Pixel only.
2945   *
2946   * CURRENTLY DISABLED.
2947   * ============================================================
2948   */
2949
2950
2951  function sendFineLabelMetaEvent(
2952    eventName,
2953    params
2954  ) {
2955
2956    if (
2957      !FL_META_BROWSER_EVENTS_ENABLED
2958    ) {
2959
2960      return false;
2961
2962    }
2963
2964
2965    if (
2966      !ensureFineLabelMetaPixel()
2967    ) {
2968
2969      return false;
2970
2971    }
2972
2973
2974    try {
2975
2976      window.fbq(
2977        'trackSingle',
2978        META_PIXEL_ID,
2979        eventName,
2980        params || {}
2981      );
2982
2983
2984      metaEventsSent +=
2985        1;
2986
2987
2988      lastMetaEvent = {
2989
2990        event_name:
2991          eventName,
2992
2993        sent_at:
2994          new Date()
2995            .toISOString()
2996
2997      };
2998
2999
3000      return true;
3001
3002    } catch (e) {
3003
3004      lastMetaEvent = {
3005
3006        event_name:
3007          eventName,
3008
3009        sent_at:
3010          null,
3011
3012        error:
3013          true
3014
3015      };
3016
3017
3018      return false;
3019
3020    }
3021
3022  }
3023
3024
3025  /*
3026   * ============================================================
3027   * Fine Label Server ViewContent Sender
3028   *
3029   * TEST OR PRODUCTION MODE.
3030   *
3031   * Sends directly to Cloud Run.
3032   * It does NOT call fbq().
3033   * It does NOT initialize Pixel 1458.
3034   *
3035   * Consecutive duplicate products/viewed
3036   * events for the same product + path are
3037   * suppressed in this page runtime.
3038   * ============================================================
3039   */
3040
3041
3042  function getFineLabelServerViewContentEndpoint() {
3043
3044    return getServerBrowserEventEndpoint(
3045      FL_META_SERVER_VIEWCONTENT_ENABLED,
3046      FL_META_SERVER_TEST_SESSION_KEY
3047    );
3048
3049  }
3050
3051
3052  function isFineLabelServerViewContentEnabled() {
3053
3054    return Boolean(
3055      getFineLabelServerViewContentEndpoint()
3056    );
3057
3058  }
3059
3060
3061  function sendFineLabelServerViewContent(
3062    built
3063  ) {
3064
3065    var endpoint =
3066      getFineLabelServerViewContentEndpoint();
3067
3068
3069    if (
3070      !endpoint ||
3071      !built ||
3072      !Array.isArray(
3073        built.content_ids
3074      ) ||
3075      !built.content_ids.length
3076    ) {
3077
3078      return false;
3079
3080    }
3081
3082
3083    var eventKey =
3084      location.pathname +
3085      '|' +
3086      built.content_ids.join(',');
3087
3088
3089    if (
3090      lastServerViewContentKey ===
3091      eventKey
3092    ) {
3093
3094      lastServerViewContent = {
3095
3096        event_name:
3097          'ViewContent',
3098
3099        skipped:
3100          true,
3101
3102        reason:
3103          'DUPLICATE_SAME_PAGE_PRODUCT',
3104
3105        request_count:
3106          serverViewContentRequests,
3107
3108        has_fbp:
3109          Boolean(
3110            getCookie('_fbp')
3111          ),
3112
3113        has_fbc:
3114          Boolean(
3115            getCookie('_fbc')
3116          ),
3117
3118        updated_at:
3119          new Date()
3120            .toISOString()
3121
3122      };
3123
3124
3125      return false;
3126
3127    }
3128
3129
3130    /*
3131     * Mark before fetch so a duplicate
3132     * EasyStore event cannot race a second
3133     * request for the same product page.
3134     */
3135    lastServerViewContentKey =
3136      eventKey;
3137
3138
3139    var payload = {
3140
3141      event_name:
3142        'ViewContent',
3143
3144      content_ids:
3145        built.content_ids,
3146
3147      content_type:
3148        built.content_type,
3149
3150      value:
3151        built.value,
3152
3153      currency:
3154        built.currency,
3155
3156      fbp:
3157        getCookie('_fbp'),
3158
3159      fbc:
3160        getCookie('_fbc'),
3161
3162      event_source_url:
3163        location.href
3164
3165    };
3166
3167
3168    serverViewContentRequests +=
3169      1;
3170
3171
3172    lastServerViewContent = {
3173
3174      event_name:
3175        'ViewContent',
3176
3177      success:
3178        null,
3179
3180      status:
3181        null,
3182
3183      skipped:
3184        false,
3185
3186      request_count:
3187        serverViewContentRequests,
3188
3189      has_fbp:
3190        Boolean(
3191          payload.fbp
3192        ),
3193
3194      has_fbc:
3195        Boolean(
3196          payload.fbc
3197        ),
3198
3199      requested_at:
3200        new Date()
3201          .toISOString()
3202
3203    };
3204
3205
3206    fetch(
3207      endpoint,
3208      {
3209
3210        method:
3211          'POST',
3212
3213        headers: {
3214
3215          'Content-Type':
3216            'application/json'
3217
3218        },
3219
3220        body:
3221          JSON.stringify(
3222            payload
3223          ),
3224
3225        keepalive:
3226          true
3227
3228      }
3229    )
3230
3231    .then(
3232      function (response) {
3233
3234        lastServerViewContent = {
3235
3236          event_name:
3237            'ViewContent',
3238
3239          success:
3240            response.ok,
3241
3242          status:
3243            response.status,
3244
3245          skipped:
3246            false,
3247
3248          request_count:
3249            serverViewContentRequests,
3250
3251          has_fbp:
3252            Boolean(
3253              payload.fbp
3254            ),
3255
3256          has_fbc:
3257            Boolean(
3258              payload.fbc
3259            ),
3260
3261          completed_at:
3262            new Date()
3263              .toISOString()
3264
3265        };
3266
3267      }
3268    )
3269
3270    .catch(
3271      function () {
3272
3273        lastServerViewContent = {
3274
3275          event_name:
3276            'ViewContent',
3277
3278          success:
3279            false,
3280
3281          status:
3282            null,
3283
3284          skipped:
3285            false,
3286
3287          request_count:
3288            serverViewContentRequests,
3289
3290          has_fbp:
3291            Boolean(
3292              payload.fbp
3293            ),
3294
3295          has_fbc:
3296            Boolean(
3297              payload.fbc
3298            ),
3299
3300          completed_at:
3301            new Date()
3302              .toISOString()
3303
3304        };
3305
3306      }
3307    );
3308
3309
3310    return true;
3311
3312  }
3313
3314
3315  /*
3316   * ============================================================
3317   * Fine Label Server AddToCart Sender
3318   *
3319   * TEST MODE ONLY.
3320   *
3321   * Sends directly to Cloud Run.
3322   * It does NOT call fbq().
3323   * It does NOT initialize Pixel 1458.
3324   *
3325   * Each EasyStore carts/item_added event
3326   * is treated as one intentional AddToCart.
3327   * ============================================================
3328   */
3329
3330
3331  function getFineLabelServerAddToCartEndpoint() {
3332
3333    return getServerBrowserEventEndpoint(
3334      FL_META_SERVER_ADDTOCART_ENABLED,
3335      FL_META_SERVER_ADDTOCART_TEST_SESSION_KEY
3336    );
3337
3338  }
3339
3340
3341  function isFineLabelServerAddToCartEnabled() {
3342
3343    return Boolean(
3344      getFineLabelServerAddToCartEndpoint()
3345    );
3346
3347  }
3348
3349
3350  function sendFineLabelServerAddToCart(
3351    built
3352  ) {
3353
3354    var endpoint =
3355      getFineLabelServerAddToCartEndpoint();
3356
3357
3358    if (
3359      !endpoint ||
3360      !built ||
3361      !Array.isArray(
3362        built.content_ids
3363      ) ||
3364      !built.content_ids.length
3365    ) {
3366
3367      return false;
3368
3369    }
3370
3371
3372    var payload = {
3373
3374      event_name:
3375        'AddToCart',
3376
3377      content_ids:
3378        built.content_ids,
3379
3380      content_type:
3381        built.content_type,
3382
3383      value:
3384        built.value,
3385
3386      currency:
3387        built.currency,
3388
3389      fbp:
3390        getCookie('_fbp'),
3391
3392      fbc:
3393        getCookie('_fbc'),
3394
3395      event_source_url:
3396        location.href
3397
3398    };
3399
3400
3401    serverAddToCartRequests +=
3402      1;
3403
3404
3405    lastServerAddToCart = {
3406
3407      event_name:
3408        'AddToCart',
3409
3410      success:
3411        null,
3412
3413      status:
3414        null,
3415
3416      request_count:
3417        serverAddToCartRequests,
3418
3419      has_fbp:
3420        Boolean(
3421          payload.fbp
3422        ),
3423
3424      has_fbc:
3425        Boolean(
3426          payload.fbc
3427        ),
3428
3429      requested_at:
3430        new Date()
3431          .toISOString()
3432
3433    };
3434
3435
3436    fetch(
3437      endpoint,
3438      {
3439
3440        method:
3441          'POST',
3442
3443        headers: {
3444
3445          'Content-Type':
3446            'application/json'
3447
3448        },
3449
3450        body:
3451          JSON.stringify(
3452            payload
3453          ),
3454
3455        keepalive:
3456          true
3457
3458      }
3459    )
3460
3461    .then(
3462      function (response) {
3463
3464        lastServerAddToCart = {
3465
3466          event_name:
3467            'AddToCart',
3468
3469          success:
3470            response.ok,
3471
3472          status:
3473            response.status,
3474
3475          request_count:
3476            serverAddToCartRequests,
3477
3478          has_fbp:
3479            Boolean(
3480              payload.fbp
3481            ),
3482
3483          has_fbc:
3484            Boolean(
3485              payload.fbc
3486            ),
3487
3488          completed_at:
3489            new Date()
3490              .toISOString()
3491
3492        };
3493
3494      }
3495    )
3496
3497    .catch(
3498      function () {
3499
3500        lastServerAddToCart = {
3501
3502          event_name:
3503            'AddToCart',
3504
3505          success:
3506            false,
3507
3508          status:
3509            null,
3510
3511          request_count:
3512            serverAddToCartRequests,
3513
3514          has_fbp:
3515            Boolean(
3516              payload.fbp
3517            ),
3518
3519          has_fbc:
3520            Boolean(
3521              payload.fbc
3522            ),
3523
3524          completed_at:
3525            new Date()
3526              .toISOString()
3527
3528        };
3529
3530      }
3531    );
3532
3533
3534    return true;
3535
3536  }
3537
3538
3539  /*
3540   * ============================================================
3541   * Fine Label Server InitiateCheckout Sender
3542   *
3543   * TEST MODE ONLY
3543.
3544   *
3545   * Sends directly to Cloud Run.
3546   * It does NOT call fbq().
3547   * It does NOT initialize Pixel 1458.
3548   * ============================================================
3549   */
3550
3551
3552  function getFineLabelServerInitiateCheckoutEndpoint() {
3553
3554    return getServerBrowserEventEndpoint(
3555      FL_META_SERVER_INITIATECHECKOUT_ENABLED,
3556      FL_META_SERVER_INITIATECHECKOUT_TEST_SESSION_KEY
3557    );
3558
3559  }
3560
3561
3562  function isFineLabelServerInitiateCheckoutEnabled() {
3563
3564    return Boolean(
3565      getFineLabelServerInitiateCheckoutEndpoint()
3566    );
3567
3568  }
3569
3570
3571  function sendFineLabelServerInitiateCheckout(
3572    built
3573  ) {
3574
3575    var endpoint =
3576      getFineLabelServerInitiateCheckoutEndpoint();
3577
3578
3579    if (
3580      !endpoint ||
3581      !built ||
3582      !Array.isArray(
3583        built.content_ids
3584      ) ||
3585      !built.content_ids.length ||
3586      !Number.isFinite(
3587        Number(
3588          built.num_items
3589        )
3590      ) ||
3591      Number(
3592        built.num_items
3593      ) < 1
3594    ) {
3595
3596      return false;
3597
3598    }
3599
3600
3601    var payload = {
3602
3603      event_name:
3604        'InitiateCheckout',
3605
3606      content_ids:
3607        built.content_ids,
3608
3609      content_type:
3610        built.content_type,
3611
3612      num_items:
3613        built.num_items,
3614
3615      value:
3616        built.value,
3617
3618      currency:
3619        built.currency,
3620
3621      fbp:
3622        getCookie('_fbp'),
3623
3624      fbc:
3625        getCookie('_fbc'),
3626
3627      event_source_url:
3628        location.href
3629
3630    };
3631
3632
3633    serverInitiateCheckoutRequests +=
3634      1;
3635
3636
3637    lastServerInitiateCheckout = {
3638
3639      event_name:
3640        'InitiateCheckout',
3641
3642      success:
3643        null,
3644
3645      status:
3646        null,
3647
3648      request_count:
3649        serverInitiateCheckoutRequests,
3650
3651      has_fbp:
3652        Boolean(
3653          payload.fbp
3654        ),
3655
3656      has_fbc:
3657        Boolean(
3658          payload.fbc
3659        ),
3660
3661      requested_at:
3662        new Date()
3663          .toISOString()
3664
3665    };
3666
3667
3668    fetch(
3669      endpoint,
3670      {
3671
3672        method:
3673          'POST',
3674
3675        headers: {
3676
3677          'Content-Type':
3678            'application/json'
3679
3680        },
3681
3682        body:
3683          JSON.stringify(
3684            payload
3685          ),
3686
3687        keepalive:
3688          true
3689
3690      }
3691    )
3692
3693    .then(
3694      function (response) {
3695
3696        lastServerInitiateCheckout = {
3697
3698          event_name:
3699            'InitiateCheckout',
3700
3701          success:
3702            response.ok,
3703
3704          status:
3705            response.status,
3706
3707          request_count:
3708            serverInitiateCheckoutRequests,
3709
3710          has_fbp:
3711            Boolean(
3712              payload.fbp
3713            ),
3714
3715          has_fbc:
3716            Boolean(
3717              payload.fbc
3718            ),
3719
3720          completed_at:
3721            new Date()
3722              .toISOString()
3723
3724        };
3725
3726      }
3727    )
3728
3729    .catch(
3730      function () {
3731
3732        lastServerInitiateCheckout = {
3733
3734          event_name:
3735            'InitiateCheckout',
3736
3737          success:
3738            false,
3739
3740          status:
3741            null,
3742
3743          request_count:
3744            serverInitiateCheckoutRequests,
3745
3746          has_fbp:
3747            Boolean(
3748              payload.fbp
3749            ),
3750
3751          has_fbc:
3752            Boolean(
3753              payload.fbc
3754            ),
3755
3756          completed_at:
3757            new Date()
3758              .toISOString()
3759
3760        };
3761
3762      }
3763    );
3764
3765
3766    return true;
3767
3768  }
3769
3770
3771  /*
3772   * ============================================================
3773   * Product Viewed State
3774   * ============================================================
3775   */
3776
3777
3778  function saveProductViewed(data) {
3779
3780    data =
3781      data || {};
3782
3783
3784    var product =
3785      data.product || {};
3786
3787
3788    window.__FL_PRODUCT_VIEWED__ = {
3789
3790      product_id:
3791        product.id ||
3792        product.product_id ||
3793        null,
3794
3795      title:
3796        product.title ||
3797        product.name ||
3798        null,
3799
3800      handle:
3801        product.handle ||
3802        null,
3803
3804      price:
3805        product.price ||
3806        null,
3807
3808      compare_at_price:
3809        product.compare_at_price ||
3810        null,
3811
3812      currency:
3813        data.store &&
3814        data.store.currency
3815          ? (
3816              data.store
3817                .currency.code ||
3818              data.store
3819                .currency
3820            )
3821          : null,
3822
3823      available:
3824        product.available,
3825
3826      variants:
3827        Array.isArray(
3828          product.variants
3829        )
3830          ? product.variants.map(
3831              function (
3832                variant
3833              ) {
3834
3835                return {
3836
3837                  id:
3838                    variant.id ||
3839                    null,
3840
3841                  sku:
3842                    variant.sku ||
3843                    null,
3844
3845                  price:
3846                    variant.price ||
3847                    null,
3848
3849                  available:
3850                    variant.available
3851
3852                };
3853
3854              }
3855            )
3856          : []
3857
3858    };
3859
3860  }
3861
3862
3863  /*
3864   * ============================================================
3865   * PageView Builder
3866   * ============================================================
3867   */
3868
3869
3870  function buildPageView() {
3871
3872    return {
3873
3874      event_name:
3875        'PageView',
3876
3877      path:
3878        location.pathname
3879
3880    };
3881
3882  }
3883
3884
3885  /*
3886   * ============================================================
3887   * ViewContent Builder
3888   * ============================================================
3889   */
3890
3891
3892  function buildViewContent() {
3893
3894    var product =
3895      window
3896        .__FL_PRODUCT_VIEWED__ ||
3897      null;
3898
3899
3900    if (
3901      !product ||
3902      !product.product_id
3903    ) {
3904
3905      return null;
3906
3907    }
3908
3909
3910    return {
3911
3912      event_name:
3913        'ViewContent',
3914
3915      content_ids: [
3916        String(
3917          product.product_id
3918        )
3919      ],
3920
3921      content_type:
3922        'product',
3923
3924      value:
3925        Number(
3926          product.price || 0
3927        ),
3928
3929      currency:
3930        'MYR'
3931
3932    };
3933
3934  }
3935
3936
3937  /*
3938   * ============================================================
3939   * AddToCart Builder
3940   *
3941   * Uses latest_items ONLY.
3942   * ============================================================
3943   */
3944
3945
3946  function buildAddToCart(
3947    cart
3948  ) {
3949
3950    cart =
3951      cart || {};
3952
3953
3954    var latestItems =
3955      Array.isArray(
3956        cart.latest_items
3957      )
3958        ? cart.latest_items
3959        : [];
3960
3961
3962    if (!latestItems.length) {
3963
3964      return null;
3965
3966    }
3967
3968
3969    var contentIds =
3970      latestItems
3971        .map(
3972          function (item) {
3973
3974            return item.product_id
3975              ? String(
3976                  item.product_id
3977                )
3978              : null;
3979
3980          }
3981        )
3982        .filter(Boolean);
3983
3984
3985    if (!contentIds.length) {
3986
3987      return null;
3988
3989    }
3990
3991
3992    var value =
3993      latestItems.reduce(
3994        function (
3995          total,
3996          item
3997        ) {
3998
3999          return (
4000            total +
4001            (
4002              Number(
4003                item.price || 0
4004              ) *
4005              Number(
4006                item.quantity || 1
4007              )
4008            )
4009          );
4010
4011        },
4012        0
4013      );
4014
4015
4016    return {
4017
4018      event_name:
4019        'AddToCart',
4020
4021      content_ids:
4022        contentIds,
4023
4024      content_type:
4025        'product',
4026
4027      value:
4028        value,
4029
4030      currency:
4031        'MYR'
4032
4033    };
4034
4035  }
4036
4037
4038
4039  /*
4040   * ============================================================
4041   * AddToCart Fetch Fallback
4042   *
4043   * EasyStore currently performs:
4044   *
4045   * POST /cart/add?retrieve=true
4046   *
4047   * but carts/item_added is not consistently
4048   * emitted on the storefront.
4049   *
4050   * This fallback observes that successful
4051   * same-origin cart request without changing
4052   * its request or response.
4053   *
4054   * Request body gives:
4055   * - variant id
4056   * - quantity just added
4057   *
4058   * Response cart gives:
4059   * - product id
4060   * - variant price
4061   * - currency
4062   * - cart/order tokens for Browser Match
4063   *
4064   * If EasyStore does emit carts/item_added
4065   * for the same request, the pending request
4066   * is marked handled so the fallback does not
4067   * send a duplicate Server AddToCart.
4068   * ============================================================
4069   */
4070
4071
4072  function parseCartAddBody(
4073    body
4074  ) {
4075
4076    if (!body) {
4077
4078      return null;
4079
4080    }
4081
4082
4083    if (
4084      typeof body ===
4085        'string'
4086    ) {
4087
4088      try {
4089
4090        return JSON.parse(
4091          body
4092        );
4093
4094      } catch (e) {
4095
4096        try {
4097
4098          var params =
4099            new URLSearchParams(
4100              body
4101            );
4102
4103          var result = {};
4104
4105          params.forEach(
4106            function (
4107              value,
4108              key
4109            ) {
4110
4111              result[key] =
4112                value;
4113
4114            }
4115          );
4116
4117          return result;
4118
4119        } catch (e2) {
4120
4121          return null;
4122
4123        }
4124
4125      }
4126
4127    }
4128
4129
4130    if (
4131      typeof URLSearchParams !==
4132        'undefined' &&
4133      body instanceof
4134        URLSearchParams
4135    ) {
4136
4137      var paramsResult = {};
4138
4139      body.forEach(
4140        function (
4141          value,
4142          key
4143        ) {
4144
4145          paramsResult[key] =
4146            value;
4147
4148        }
4149      );
4150
4151      return paramsResult;
4152
4153    }
4154
4155
4156    if (
4157      typeof FormData !==
4158        'undefined' &&
4159      body instanceof
4160        FormData
4161    ) {
4162
4163      var formResult = {};
4164
4165      body.forEach(
4166        function (
4167          value,
4168          key
4169        ) {
4170
4171          formResult[key] =
4172            value;
4173
4174        }
4175      );
4176
4177      return formResult;
4178
4179    }
4180
4181
4182    return null;
4183
4184  }
4185
4186
4187  function getCartAddRequestInfo(
4188    input,
4189    init
4190  ) {
4191
4192    var requestUrl = '';
4193
4194    try {
4195
4196      requestUrl =
4197        typeof input ===
4198          'string'
4199          ? input
4200          : (
4201              input &&
4202              input.url
4203                ? input.url
4204                : ''
4205            );
4206
4207
4208      var url =
4209        new URL(
4210          requestUrl,
4211          location.href
4212        );
4213
4214
4215      if (
4216        url.origin !==
4217          location.origin ||
4218        url.pathname !==
4219          '/cart/add' ||
4220        url.searchParams.get(
4221          'retrieve'
4222        ) !== 'true'
4223      ) {
4224
4225        return null;
4226
4227      }
4228
4229    } catch (e) {
4230
4231      return null;
4232
4233    }
4234
4235
4236    var method =
4237      String(
4238        (
4239          init &&
4240          init.method
4241        ) ||
4242        (
4243          input &&
4244          input.method
4245        ) ||
4246        'GET'
4247      )
4248        .trim()
4249        .toUpperCase();
4250
4251
4252    if (
4253      method !==
4254        'POST'
4255    ) {
4256
4257      return null;
4258
4259    }
4260
4261
4262    var parsed =
4263      parseCartAddBody(
4264        init &&
4265        init.body
4266      );
4267
4268
4269    if (!parsed) {
4270
4271      return null;
4272
4273    }
4274
4275
4276    var variantId =
4277      String(
4278        parsed.id ||
4279        parsed.variant_id ||
4280        ''
4281      ).trim();
4282
4283
4284    var quantity =
4285      Number(
4286        parsed.quantity || 1
4287      );
4288
4289
4290    if (
4291      !variantId ||
4292      !Number.isFinite(
4293        quantity
4294      ) ||
4295      quantity <= 0
4296    ) {
4297
4298      return null;
4299
4300    }
4301
4302
4303    return {
4304
4305      variant_id:
4306        variantId,
4307
4308      quantity:
4309        quantity
4310
4311    };
4312
4313  }
4314
4315
4316  function createPendingCartAdd(
4317    requestInfo
4318  ) {
4319
4320    if (!requestInfo) {
4321
4322      return null;
4323
4324    }
4325
4326
4327    cartAddRequestSequence +=
4328      1;
4329
4330
4331    var pending = {
4332
4333      request_id:
4334        cartAddRequestSequence,
4335
4336      variant_id:
4337        requestInfo.variant_id,
4338
4339      quantity:
4340        requestInfo.quantity,
4341
4342      handled_by_easystore:
4343        false,
4344
4345      created_at:
4346        Date.now()
4347
4348    };
4349
4350
4351    pendingCartAddRequests.push(
4352      pending
4353    );
4354
4355
4356    /*
4357     * Keep the queue bounded even if a browser
4358     * extension or storefront error prevents a
4359     * response from completing.
4360     */
4361    if (
4362      pendingCartAddRequests.length >
4363        20
4364    ) {
4365
4366      pendingCartAddRequests =
4367        pendingCartAddRequests.slice(
4368          -20
4369        );
4370
4371    }
4372
4373
4374    return pending;
4375
4376  }
4377
4378
4379  function markPendingCartAddHandledByEasyStore(
4380    cart
4381  ) {
4382
4383    cart =
4384      cart || {};
4385
4386
4387    var latestItems =
4388      Array.isArray(
4389        cart.latest_items
4390      )
4391        ? cart.latest_items
4392        : [];
4393
4394
4395    if (!latestItems.length) {
4396
4397      return;
4398
4399    }
4400
4401
4402    var variantIds =
4403      latestItems
4404        .map(
4405          function (item) {
4406
4407            return String(
4408              item.variant_id ||
4409              item.variantId ||
4410              item.id ||
4411              ''
4412            ).trim();
4413
4414          }
4415        )
4416        .filter(Boolean);
4417
4418
4419    if (!variantIds.length) {
4420
4421      return;
4422
4423    }
4424
4425
4426    for (
4427      var i = 0;
4428      i <
4429        pendingCartAddRequests.length;
4430      i += 1
4431    ) {
4432
4433      var pending =
4434        pendingCartAddRequests[i];
4435
4436
4437      if (
4438        !pending ||
4439        pending.handled_by_easystore
4440      ) {
4441
4442        continue;
4443
4444      }
4445
4446
4447      if (
4448        variantIds.indexOf(
4449          pending.variant_id
4450        ) !== -1
4451      ) {
4452
4453        pending.handled_by_easystore =
4454          true;
4455
4456        return;
4457
4458      }
4459
4460    }
4461
4462  }
4463
4464
4465  function removePendingCartAdd(
4466    pending
4467  ) {
4468
4469    if (!pending) {
4470
4471      return;
4472
4473    }
4474
4475
4476    pendingCartAddRequests =
4477      pendingCartAddRequests
4478        .filter(
4479          function (item) {
4480
4481            return (
4482              item !==
4483              pending
4484            );
4485
4486          }
4487        );
4488
4489  }
4490
4491
4492  function buildAddToCartFromCartResponse(
4493    pending,
4494    cart
4495  ) {
4496
4497    if (
4498      !pending ||
4499      !cart
4500    ) {
4501
4502      return null;
4503
4504    }
4505
4506
4507    var items =
4508      Array.isArray(
4509        cart.items
4510      )
4511        ? cart.items
4512        : [];
4513
4514
4515    var matchingItem =
4516      null;
4517
4518
4519    for (
4520      var i = 0;
4521      i < items.length;
4522      i += 1
4523    ) {
4524
4525      var item =
4526        items[i] || {};
4527
4528
4529      var variantId =
4530        String(
4531          item.variant_id ||
4532          item.variantId ||
4533          ''
4534        ).trim();
4535
4536
4537      if (
4538        variantId ===
4539          pending.variant_id
4540      ) {
4541
4542        matchingItem =
4543          item;
4544
4545        break;
4546
4547      }
4548
4549    }
4550
4551
4552    if (
4553      !matchingItem ||
4554      !matchingItem.product_id
4555    ) {
4556
4557      return null;
4558
4559    }
4560
4561
4562    var quantity =
4563      Number(
4564        pending.quantity
4565      );
4566
4567
4568    var unitPrice =
4569      Number(
4570        matchingItem.price || 0
4571      );
4572
4573
4574    if (
4575      !Number.isFinite(
4576        quantity
4577      ) ||
4578      quantity <= 0 ||
4579      !Number.isFinite(
4580        unitPrice
4581      ) ||
4582      unitPrice < 0
4583    ) {
4584
4585      return null;
4586
4587    }
4588
4589
4590    var currency =
4591      'MYR';
4592
4593
4594    if (
4595      cart.currency &&
4596      typeof cart.currency ===
4597        'object' &&
4598      cart.currency.code
4599    ) {
4600
4601      currency =
4602        String(
4603          cart.currency.code
4604        );
4605
4606    } else if (
4607      cart.currency
4608    ) {
4609
4610      currency =
4611        String(
4612          cart.currency
4613        );
4614
4615    }
4616
4617
4618    return {
4619
4620      event_name:
4621        'AddToCart',
4622
4623      content_ids: [
4624        String(
4625          matchingItem.product_id
4626        )
4627      ],
4628
4629      content_type:
4630        'product',
4631
4632      value:
4633        unitPrice *
4634        quantity,
4635
4636      currency:
4637        currency
4638
4639    };
4640
4641  }
4642
4643
4644  function processFineLabelAddToCart(
4645    cart,
4646    built,
4647    source
4648  ) {
4649
4650    if (!built) {
4651
4652      return false;
4653
4654    }
4655
4656
4657    lastAddToCart =
4658      built;
4659
4660
4661    lastAddToCartSource =
4662      source || null;
4663
4664
4665    /*
4666     * Fine Label browser fbq sender remains
4667     * disabled while EasyStore native Meta
4668     * integration is active.
4669     */
4670    maybeSendAddToCart(
4671      built
4672    );
4673
4674
4675    /*
4676     * Fine Label controlled Server CAPI.
4677     */
4678    var serverSent =
4679      sendFineLabelServerAddToCart(
4680        built
4681      );
4682
4683
4684    /*
4685     * Browser Match Capture remains live.
4686     */
4687    capture(
4688      'carts/item_added',
4689
4690      cart &&
4691      cart.token
4692        ? cart.token
4693        : '',
4694
4695      cart &&
4696      cart.order_token
4697        ? cart.order_token
4698        : ''
4699    );
4700
4701
4702    return serverSent;
4703
4704  }
4705
4706
4707  function installCartAddFetchFallback() {
4708
4709    if (
4710      window
4711        .__FL_META_CART_ADD_FETCH_FALLBACK_INSTALLED__
4712    ) {
4713
4714      return;
4715
4716    }
4717
4718
4719    if (
4720      typeof window.fetch !==
4721        'function'
4722    ) {
4723
4724      return;
4725
4726    }
4727
4728
4729    window
4730      .__FL_META_CART_ADD_FETCH_FALLBACK_INSTALLED__ =
4731        true;
4732
4733
4734    var originalFetch =
4735      window.fetch;
4736
4737
4738    window.fetch =
4739      function (
4740        input,
4741        init
4742      ) {
4743
4744        var requestInfo =
4745          getCartAddRequestInfo(
4746            input,
4747            init
4748          );
4749
4750
4751        var pending =
4752          createPendingCartAdd(
4753            requestInfo
4754          );
4755
4756
4757        var promise =
4758          originalFetch.apply(
4759            this,
4760            arguments
4761          );
4762
4763
4764        if (!pending) {
4765
4766          return promise;
4767
4768        }
4769
4770
4771        return promise.then(
4772          function (response) {
4773
4774            if (
4775              !response ||
4776              !response.ok
4777            ) {
4778
4779              lastAddToCartFallback = {
4780
4781                request_id:
4782                  pending.request_id,
4783
4784                success:
4785                  false,
4786
4787                skipped:
4788                  true,
4789
4790                reason:
4791                  'CART_ADD_RESPONSE_NOT_OK',
4792
4793                handled_by_easystore:
4794                  pending
4795                    .handled_by_easystore,
4796
4797                updated_at:
4798                  new Date()
4799                    .toISOString()
4800
4801              };
4802
4803
4804              removePendingCartAdd(
4805                pending
4806              );
4807
4808
4809              return response;
4810
4811            }
4812
4813
4814            try {
4815
4816              response
4817                .clone()
4818                .json()
4819                .then(
4820                  function (cart) {
4821
4822                    /*
4823                     * Give EasyStore's own
4824                     * carts/item_added callback a
4825                     * brief chance to run first.
4826                     */
4827                    setTimeout(
4828                      function () {
4829
4830                        if (
4831                          pending
4832                            .handled_by_easystore
4833                        ) {
4834
4835                          lastAddToCartFallback = {
4836
4837                            request_id:
4838                              pending
4839                                .request_id,
4840
4841                            success:
4842                              true,
4843
4844                            skipped:
4845                              true,
4846
4847                            reason:
4848                              'EASYSTORE_EVENT_HANDLED',
4849
4850                            handled_by_easystore:
4851                              true,
4852
4853                            updated_at:
4854                              new Date()
4855                                .toISOString()
4856
4857                          };
4858
4859
4860                          removePendingCartAdd(
4861                            pending
4862                          );
4863
4864
4865                          return;
4866
4867                        }
4868
4869
4870                        var built =
4871                          buildAddToCartFromCartResponse(
4872                            pending,
4873                            cart
4874                          );
4875
4876
4877                        if (!built) {
4878
4879                          lastAddToCartFallback = {
4880
4881                            request_id:
4882                              pending
4883                                .request_id,
4884
4885                            success:
4886                              false,
4887
4888                            skipped:
4889                              true,
4890
4891                            reason:
4892                              'UNABLE_TO_BUILD_FROM_CART_RESPONSE',
4893
4894                            handled_by_easystore:
4895                              false,
4896
4897                            updated_at:
4898                              new Date()
4899                                .toISOString()
4900
4901                          };
4902
4903
4904                          removePendingCartAdd(
4905                            pending
4906                          );
4907
4908
4909                          return;
4910
4911                        }
4912
4913
4914                        var sent =
4915                          processFineLabelAddToCart(
4916                            cart,
4917                            built,
4918                            'fetch_fallback'
4919                          );
4920
4921
4922                        lastAddToCartFallback = {
4923
4924                          request_id:
4925                            pending
4926                              .request_id,
4927
4928                          success:
4929                            sent,
4930
4931                          skipped:
4932                            false,
4933
4934                          reason:
4935                            null,
4936
4937                          handled_by_easystore:
4938                            false,
4939
4940                          updated_at:
4941                            new Date()
4942                              .toISOString()
4943
4944                        };
4945
4946
4947                        removePendingCartAdd(
4948                          pending
4949                        );
4950
4951                      },
4952                      300
4953                    );
4954
4955                  }
4956                )
4957                .catch(
4958                  function () {
4959
4960                    lastAddToCartFallback = {
4961
4962                      request_id:
4963                        pending
4964                          .request_id,
4965
4966                      success:
4967                        false,
4968
4969                      skipped:
4970                        true,
4971
4972                      reason:
4973                        'INVALID_CART_ADD_RESPONSE',
4974
4975                      handled_by_easystore:
4976                        pending
4977                          .handled_by_easystore,
4978
4979                      updated_at:
4980                        new Date()
4981                          .toISOString()
4982
4983                    };
4984
4985
4986                    removePendingCartAdd(
4987                      pending
4988                    );
4989
4990                  }
4991                );
4992
4993            } catch (e) {
4994
4995              lastAddToCartFallback = {
4996
4997                request_id:
4998                  pending.request_id,
4999
5000                success:
5001                  false,
5002
5003                skipped:
5004                  true,
5005
5006                reason:
5007                  'CART_ADD_FALLBACK_ERROR',
5008
5009                handled_by_easystore:
5010                  pending
5011                    .handled_by_easystore,
5012
5013                updated_at:
5014                  new Date()
5015                    .toISOString()
5016
5017              };
5018
5019
5020              removePendingCartAdd(
5021                pending
5022              );
5023
5024            }
5025
5026
5027            return response;
5028
5029          }
5030        );
5031
5032      };
5033
5034  }
5035
5036
5037  /*
5038   * ============================================================
5039   * InitiateCheckout Builder
5040   *
5041   * Source:
5042   *
5043   * EasyStore.Checkout.data.checkout
5044   *
5045   * item_count is NOT trusted.
5046   *
5047   * num_items is calculated from
5048   * line_items.quantity.
5049   *
5050   * Shipping is excluded from value.
5051   * ============================================================
5052   */
5053
5054
5055  function buildInitiateCheckout(
5056    checkout
5057  ) {
5058
5059    checkout =
5060      checkout || {};
5061
5062
5063    var items =
5064      Array.isArray(
5065        checkout.line_items
5066      )
5067        ? checkout.line_items
5068        : [];
5069
5070
5071    if (!items.length) {
5072
5073      return null;
5074
5075    }
5076
5077
5078    var seenContentIds = {};
5079
5080
5081    var contentIds =
5082      items
5083        .map(
5084          function (item) {
5085
5086            return item.product_id
5087              ? String(
5088                  item.product_id
5089                )
5090              : null;
5091
5092          }
5093        )
5094        .filter(
5095          function (contentId) {
5096
5097            if (
5098              !contentId ||
5099              seenContentIds[contentId]
5100            ) {
5101
5102              return false;
5103
5104            }
5105
5106
5107            seenContentIds[contentId] =
5108              true;
5109
5110
5111            return true;
5112
5113          }
5114        );
5115
5116
5117    if (!contentIds.length) {
5118
5119      return null;
5120
5121    }
5122
5123
5124    var numItems =
5125      items.reduce(
5126        function (
5127          total,
5128          item
5129        ) {
5130
5131          return (
5132            total +
5133            Number(
5134              item.quantity || 1
5135            )
5136          );
5137
5138        },
5139        0
5140      );
5141
5142
5143    var currency =
5144      'MYR';
5145
5146
5147    if (
5148      checkout.currency &&
5149      typeof checkout.currency ===
5150        'object' &&
5151      checkout.currency.code
5152    ) {
5153
5154      currency =
5155        String(
5156          checkout.currency.code
5157        );
5158
5159    } else if (
5160      checkout.currency
5161    ) {
5162
5163      currency =
5164        String(
5165          checkout.currency
5166        );
5167
5168    }
5169
5170
5171    var value =
5172      Number(
5173        checkout.subtotal_price ||
5174        checkout
5175          .line_items_subtotal_price ||
5176        checkout
5177          .total_line_items_price ||
5178        0
5179      );
5180
5181
5182    return {
5183
5184      event_name:
5185        'InitiateCheckout',
5186
5187      content_ids:
5188        contentIds,
5189
5190      content_type:
5191        'product',
5192
5193      num_items:
5194        numItems,
5195
5196      value:
5197        value,
5198
5199      currency:
5200        currency
5201
5202    };
5203
5204  }
5205
5206
5207  /*
5208   * ============================================================
5209   * Current EasyStore Checkout State
5210   * ============================================================
5211   */
5212
5213
5214  function getCurrentCheckout() {
5215
5216    try {
5217
5218      if (
5219        window.EasyStore &&
5220        EasyStore.Checkout &&
5221        EasyStore.Checkout.data &&
5222        EasyStore.Checkout.data.checkout
5223      ) {
5224
5225        return (
5226          EasyStore
5227            .Checkout
5228            .data
5229            .checkout
5230        );
5231
5232      }
5233
5234    } catch (e) {}
5235
5236
5237    return null;
5238
5239  }
5240
5241
5242  function buildCurrentInitiateCheckout() {
5243
5244    var checkout =
5245      getCurrentCheckout();
5246
5247
5248    if (!checkout) {
5249
5250      return null;
5251
5252    }
5253
5254
5255    return (
5256      buildInitiateCheckout(
5257        checkout
5258      )
5259    );
5260
5261  }
5262
5263
5264  /*
5265   * ============================================================
5266   * InitiateCheckout Deduplication
5267   *
5268   * Avoid repeated InitiateCheckout
5269   * when same checkout page is refreshed.
5270   * ============================================================
5271   */
5272
5273
5274  function getCheckoutIdentity(
5275    checkout
5276  ) {
5277
5278    checkout =
5279      checkout || {};
5280
5281
5282    return String(
5283      checkout.cart_token ||
5284      checkout.token ||
5285      checkout.id ||
5286      checkoutTokenFromUrl() ||
5287      ''
5288    ).trim();
5289
5290  }
5291
5292
5293  function wasInitiateCheckoutSent(
5294    checkoutIdentity
5295  ) {
5296
5297    if (!checkoutIdentity) {
5298
5299      return false;
5300
5301    }
5302
5303
5304    try {
5305
5306      return (
5307        sessionStorage.getItem(
5308          INITIATE_CHECKOUT_SENT_KEY
5309        ) ===
5310        checkoutIdentity
5311      );
5312
5313    } catch (e) {
5314
5315      return false;
5316
5317    }
5318
5319  }
5320
5321
5322  function markInitiateCheckoutSent(
5323    checkoutIdentity
5324  ) {
5325
5326    if (!checkoutIdentity) {
5327
5328      return;
5329
5330    }
5331
5332
5333    try {
5334
5335      sessionStorage.setItem(
5336        INITIATE_CHECKOUT_SENT_KEY,
5337        checkoutIdentity
5338      );
5339
5340    } catch (e) {}
5341
5342  }
5343
5344
5345  /*
5346   * ============================================================
5347   * Send PageView
5348   * ============================================================
5349   */
5350
5351
5352  function maybeSendPageView() {
5353
5354    if (pageViewSent) {
5355
5356      return;
5357
5358    }
5359
5360
5361    var sent =
5362      sendFineLabelMetaEvent(
5363        'PageView',
5364        {}
5365      );
5366
5367
5368    if (sent) {
5369
5370      pageViewSent =
5371        true;
5372
5373    }
5374
5375  }
5376
5377
5378  /*
5379   * ============================================================
5380   * Send ViewContent
5381   * ============================================================
5382   */
5383
5384
5385  function maybeSendViewContent(
5386    attempt,
5387    built,
5388    expectedPath
5389  ) {
5390
5391    attempt =
5392      attempt || 0;
5393
5394
5395    built =
5396      built ||
5397      buildViewContent();
5398
5399
5400    expectedPath =
5401      expectedPath ||
5402      location.pathname;
5403
5404
5405    if (!built) {
5406
5407      return;
5408
5409    }
5410
5411
5412    /*
5413     * If navigation happened while waiting,
5414     * do not send the old product against
5415     * the new page URL.
5416     */
5417    if (
5418      location.pathname !==
5419        expectedPath
5420    ) {
5421
5422      return;
5423
5424    }
5425
5426
5427    /*
5428     * EasyStore products/viewed may fire
5429     * before Meta has created _fbp.
5430     *
5431     * If _fbp is not ready yet, wait up to
5432     * about 5 seconds before sending CAPI
5433     * ViewContent.
5434     *
5435     * 17 retries × 300ms = ~5.1 seconds.
5436     *
5437     * If _fbp still does not exist after
5438     * the wait, send anyway so ViewContent
5439     * is not lost.
5440     */
5441    if (
5442      !getCookie('_fbp') &&
5443      attempt < 17
5444    ) {
5445
5446      setTimeout(
5447        function () {
5448
5449          maybeSendViewContent(
5450            attempt + 1,
5451            built,
5452            expectedPath
5453          );
5454
5455        },
5456        300
5457      );
5458
5459
5460      return;
5461
5462    }
5463
5464
5465    /*
5466     * Server CAPI ViewContent.
5467     *
5468     * No fbq() call.
5469     * Fine Label main pixel remains
5470     * uninitialized in this script.
5471     */
5472    sendFineLabelServerViewContent(
5473      built
5474    );
5475
5476  }
5477
5478
5479  /*
5480   * ============================================================
5481   * Send AddToCart
5482   * ============================================================
5483   */
5484
5485
5486  function maybeSendAddToCart(
5487    built
5488  ) {
5489
5490    if (!built) {
5491
5492      return;
5493
5494    }
5495
5496
5497    sendFineLabelMetaEvent(
5498      'AddToCart',
5499      {
5500
5501        content_ids:
5502          built.content_ids,
5503
5504        content_type:
5505          built.content_type,
5506
5507        value:
5508          built.value,
5509
5510        currency:
5511          built.currency
5512
5513      }
5514    );
5515
5516  }
5517
5518
5519  /*
5520   * ============================================================
5521   * Send InitiateCheckout
5522   * ============================================================
5523   */
5524
5525
5526  function maybeSendInitiateCheckout(
5527    checkout,
5528    built
5529  ) {
5530
5531    if (
5532      !checkout ||
5533      !built
5534    ) {
5535
5536      return;
5537
5538    }
5539
5540
5541    var checkoutIdentity =
5542      getCheckoutIdentity(
5543        checkout
5544      );
5545
5546
5547    if (
5548      wasInitiateCheckoutSent(
5549        checkoutIdentity
5550      )
5551    ) {
5552
5553      return;
5554
5555    }
5556
5557
5558    var browserSent =
5559      sendFineLabelMetaEvent(
5560        'InitiateCheckout',
5561        {
5562
5563          content_ids:
5564            built.content_ids,
5565
5566          content_type:
5567            built.content_type,
5568
5569          num_items:
5570            built.num_items,
5571
5572          value:
5573            built.value,
5574
5575          currency:
5576            built.currency
5577
5578        }
5579      );
5580
5581
5582    var serverSent =
5583      sendFineLabelServerInitiateCheckout(
5584        built
5585      );
5586
5587
5588    if (
5589      browserSent ||
5590      serverSent
5591    ) {
5592
5593      markInitiateCheckoutSent(
5594        checkoutIdentity
5595      );
5596
5597    }
5598
5599  }
5600
5601
5602  /*
5603   * ============================================================
5604   * Checkout State Watcher
5605   * ============================================================
5606   */
5607
5608
5609  function watchCheckoutState(
5610    attempt
5611  ) {
5612
5613    attempt =
5614      attempt || 0;
5615
5616
5617    var checkout =
5618      getCurrentCheckout();
5619
5620
5621    if (checkout) {
5622
5623      var built =
5624        buildInitiateCheckout(
5625          checkout
5626        );
5627
5628
5629      if (built) {
5630
5631        lastInitiateCheckout =
5632          built;
5633
5634
5635        maybeSendInitiateCheckout(
5636          checkout,
5637          built
5638        );
5639
5640
5641        return;
5642
5643      }
5644
5645    }
5646
5647
5648    if (attempt < 120) {
5649
5650      setTimeout(
5651        function () {
5652
5653          watchCheckoutState(
5654            attempt + 1
5655          );
5656
5657        },
5658        500
5659      );
5660
5661    }
5662
5663  }
5664
5665
5666  /*
5667   * ============================================================
5668   * EasyStore Event Listeners
5669   * ============================================================
5670   */
5671
5672
5673 function installEasyStoreListeners(
5674  attempt
5675) {
5676
5677  attempt =
5678    attempt || 0;
5679
5680
5681  /*
5682   * Prevent duplicate listener installation.
5683   */
5684  if (
5685    window
5686      .__FL_META_EASYSTORE_LISTENERS_INSTALLED__
5687  ) {
5688
5689    return;
5690
5691  }
5692
5693
5694  if (
5695    window.EasyStore &&
5696    EasyStore.Event &&
5697    typeof EasyStore.Event.subscribe ===
5698      'function'
5699  ) {
5700
5701    /*
5702     * Mark before subscribing so another
5703     * delayed retry cannot install twice.
5704     */
5705    window
5706      .__FL_META_EASYSTORE_LISTENERS_INSTALLED__ =
5707        true;
5708
5709
5710    /*
5711     * ViewContent
5712     */
5713    EasyStore.Event.subscribe(
5714      'products/viewed',
5715
5716      function () {
5717
5718        var data =
5719          arguments[0] || {};
5720
5721
5722        saveProductViewed(
5723          data
5724        );
5725
5726
5727        maybeSendViewContent();
5728
5729      }
5730    );
5731
5732
5733    /*
5734     * AddToCart
5735     */
5736    EasyStore.Event.subscribe(
5737      'carts/item_added',
5738
5739      function () {
5740
5741        var data =
5742          arguments[0] || {};
5743
5744
5745        var cart =
5746          (
5747            data.cart &&
5748            typeof data.cart ===
5749              'object'
5750          )
5751            ? data.cart
5752            : data;
5753
5754
5755        markPendingCartAddHandledByEasyStore(
5756          cart
5757        );
5758
5759
5760        var built =
5761          buildAddToCart(
5762            cart
5763          );
5764
5765
5766        processFineLabelAddToCart(
5767          cart,
5768          built,
5769          'easystore_event'
5770        );
5771
5772      }
5773    );
5774
5775
5776    /*
5777     * Checkout event retained
5778     * for Browser Match Capture.
5779     */
5780 EasyStore.Event.subscribe(
5781  'checkouts/initiated',
5782
5783  function () {
5784
5785    var data =
5786      arguments[0] || {};
5787
5788
5789    var cart =
5790      (
5791        data.cart &&
5792        typeof data.cart ===
5793          'object'
5794      )
5795        ? data.cart
5796        : data;
5797
5798
5799    /*
5800     * Save checkout identifiers only.
5801     *
5802     * Browser Match itself is sent
5803     * after navigation by the
5804     * /sf/checkout/<cart_token>
5805     * URL fallback.
5806     *
5807     * This prevents duplicate
5808     * checkouts/initiated capture.
5809     */
5810    saveTokens(
5811      cart.token ||
5812        getSavedCartToken(),
5813
5814      cart.order_token ||
5815        getSavedOrderToken()
5816    );
5817
5818  }
5819);
5820
5821    return;
5822
5823  }
5824
5825
5826  /*
5827   * EasyStore may initialise quite late.
5828   *
5829   * Retry for up to ~2 minutes:
5830   * 240 attempts × 500ms.
5831   */
5832  if (attempt < 240) {
5833
5834    setTimeout(
5835      function () {
5836
5837        installEasyStoreListeners(
5838          attempt + 1
5839        );
5840
5841      },
5842      500
5843    );
5844
5845  }
5846
5847}
5848
5849  /*
5850   * ============================================================
5851   * Checkout URL Browser Match Fallback
5852   * ============================================================
5853   */
5854
5855
5856  var checkoutToken =
5857    checkoutTokenFromUrl();
5858
5859
5860  if (checkoutToken) {
5861
5862    capture(
5863      'checkouts/initiated',
5864
5865      checkoutToken,
5866
5867      getSavedOrderToken()
5868    );
5869
5870  }
5871
5872
5873  /*
5874   * ============================================================
5875   * Start
5876   * ============================================================
5877   */
5878
5879
5880  installCartAddFetchFallback();
5881
5882
5883  installEasyStoreListeners(0);
5884
5885
5886  /*
5887   * PageView sender.
5888   *
5889   * Currently does nothing because
5890   * browser events flag is FALSE.
5891   */
5892
5893  maybeSendPageView();
5894
5895
5896  /*
5897   * Checkout state watcher.
5898   */
5899
5900  if (checkoutToken) {
5901
5902    watchCheckoutState(0);
5903
5904  }
5905
5906
5907  /*
5908   * ============================================================
5909   * Browser Match Safe Diagnostic
5910   * ============================================================
5911   */
5912
5913
5914  window.FLMetaBrowserMatch = {
5915
5916    status:
5917      function () {
5918
5919        return (
5920          window
5921            .__FL_META_BROWSER_MATCH_LAST__ ||
5922          {
5923
5924            success:
5925              null,
5926
5927            status:
5928              null,
5929
5930            event:
5931              null,
5932
5933            has_fbp:
5934              Boolean(
5935                getCookie('_fbp')
5936              ),
5937
5938            has_fbc:
5939              Boolean(
5940                getCookie('_fbc')
5941              )
5942
5943          }
5944        );
5945
5946      }
5947
5948  };
5949
5950
5951  /*
5952   * ============================================================
5953   * Fine Label Browser Event Inspector
5954   *
5955   * Safe to use in production.
5956   *
5957   * Does NOT expose raw fbp/fbc.
5958   * ============================================================
5959   */
5960
5961
5962  window.FLMetaBrowserEvents = {
5963
5964    inspect:
5965      function () {
5966
5967        var checkout =
5968          getCurrentCheckout();
5969
5970
5971        var liveInitiateCheckout =
5972          checkout
5973            ? buildInitiateCheckout(
5974                checkout
5975              )
5976            : null;
5977
5978
5979        if (liveInitiateCheckout) {
5980
5981          lastInitiateCheckout =
5982            liveInitiateCheckout;
5983
5984        }
5985
5986
5987        return {
5988
5989          browser_events_enabled:
5990            FL_META_BROWSER_EVENTS_ENABLED,
5991
5992          server_view_content_enabled:
5993            isFineLabelServerViewContentEnabled(),
5994
5995          server_view_content_mode:
5996            FL_META_SERVER_VIEWCONTENT_ENABLED === true
5997              ? 'production'
5998              : (
5999                  isFineLabelServerViewContentEnabled()
6000                    ? 'test'
6001                    : 'off'
6002                ),
6003
6004          server_view_content_global_enabled:
6005            FL_META_SERVER_VIEWCONTENT_ENABLED,
6006
6007          server_view_content_requests:
6008            serverViewContentRequests,
6009
6010          last_server_view_content:
6011            lastServerViewContent,
6012
6013          server_add_to_cart_enabled:
6014            isFineLabelServerAddToCartEnabled(),
6015
6016          server_add_to_cart_mode:
6017            FL_META_SERVER_ADDTOCART_ENABLED === true
6018              ? 'production'
6019              : (
6020                  isFineLabelServerAddToCartEnabled()
6021                    ? 'test'
6022                    : 'off'
6023                ),
6024
6025          server_add_to_cart_global_enabled:
6026            FL_META_SERVER_ADDTOCART_ENABLED,
6027
6028          server_add_to_cart_requests:
6029            serverAddToCartRequests,
6030
6031          last_server_add_to_cart:
6032            lastServerAddToCart,
6033
6034          add_to_cart_source:
6035            lastAddToCartSource,
6036
6037          last_add_to_cart_fallback:
6038            lastAddToCartFallback,
6039
6040          cart_add_fetch_fallback_installed:
6041            Boolean(
6042              window
6043                .__FL_META_CART_ADD_FETCH_FALLBACK_INSTALLED__
6044            ),
6045
6046          pending_cart_add_requests:
6047            pendingCartAddRequests.length,
6048
6049          server_initiate_checkout_enabled:
6050            isFineLabelServerInitiateCheckoutEnabled(),
6051
6052          server_initiate_checkout_mode:
6053            FL_META_SERVER_INITIATECHECKOUT_ENABLED === true
6054              ? 'production'
6055              : (
6056                  isFineLabelServerInitiateCheckoutEnabled()
6057                    ? 'test'
6058                    : 'off'
6059                ),
6060
6061          server_initiate_checkout_global_enabled:
6062            FL_META_SERVER_INITIATECHECKOUT_ENABLED,
6063
6064          server_initiate_checkout_requests:
6065            serverInitiateCheckoutRequests,
6066
6067          last_server_initiate_checkout:
6068            lastServerInitiateCheckout,
6069
6070          pixel_id:
6071            META_PIXEL_ID,
6072
6073          page_view:
6074            buildPageView(),
6075
6076          view_content:
6077            buildViewContent(),
6078
6079          add_to_cart:
6080            lastAddToCart,
6081
6082          initiate_checkout:
6083            lastInitiateCheckout,
6084
6085          checkout_source_ready:
6086            Boolean(
6087              checkout
6088            ),
6089
6090          checkout_line_items:
6091            checkout &&
6092            Array.isArray(
6093              checkout.line_items
6094            )
6095              ? checkout
6096                  .line_items
6097                  .length
6098              : 0,
6099
6100          meta_events_sent:
6101            metaEventsSent,
6102
6103          last_meta_event:
6104            lastMetaEvent
6105
6106        };
6107
6108      }
6109
6110  };
6111
6112
6113})();
6114</script>
6114
6115<!-- /Snippet -->
6116
6117<!-- Snippet:global/body_end: Product Description Tabs -->
6118<style>
6119    .product-description-tabs{
6120        color: #000000;
6121    }
6122    .prod-desc-tab-container {
6123        padding: 15px;
6124        margin-right: auto;
6125        margin-left: auto;
6126        background-color: #ffffff;
6127    }
6128    /* Style the list */
6129    .prod-desc-tab {
6130        list-style-type: none;
6131        margin: 0;
6132        padding: 0;
6133        border-bottom: solid 1px #ddd;
6134        /*overflow: hidden;
6135        border: 1px solid #e6e6e6;
6136        background-color: #fefefe;
6137        border-bottom: 1px solid #ddd;*/
6138    }
6139
6140    /* Float the list items side by side */
6141    li.tablinks {
6142        display: inline-block;
6143        border-top: 3px solid transparent;
6144        border-left: 1px solid transparent;
6145        border-right: 1px solid transparent;
6146        margin-bottom: -1px;
6147        margin-right: 3px;
6148        border-radius: 4px 4px 0 0;
6149        background-color: rgba(212,212,212,0.3);
6150    }
6151
6152    /* Style the links inside the list items */
6153    li.tablinks a {
6154        color: #000000;
6155        cursor: pointer;
6156        margin-right: 2px;
6157        line-height: 1.42857143;
6158        display: block;
6159        padding: 10px 15px;
6160    }
6161
6162    /* Change background color of links on hover */
6163    li.tablinks:hover {
6164        background-color: #ffffff;
6165        border-bottom-color: transparent;
6166        border-top: 3px solid #ddd;
6167        border-left: 1px solid #ddd;
6168        border-right: 1px solid #ddd;
6169    } /*rgba(212,212,212,0.3)*/
6170
6171    /* Create an active/current tablink class */
6172    li.tablinks a:focus, li.tablinks.active{
6173        border-top: 3px solid #ddd;
6174        border-left: 1px solid #ddd;
6175        border-right: 1px solid #ddd;
6176        background-color: #ffffff;
6177    }
6178
6179    /* Style the tab content */
6180    .prod-desc-tab-content {
6181        display: none;
6182        padding: 15px 15px;
6183        /*border: 1px solid #ccc;*/
6184        border-top: none;
6185        clear: both;
6186        -webkit-animation: fadeEffect 1s;
6187        animation: fadeEffect 1s; /* Fading effect takes 1 second */
6188    }
6189    .prod-desc-tab-content ul{
6190        list-style-type: disc;
6191    }
6192
6193    /* if user select is_show_title is true, the title will be displayed; if not, hide the title*/
6194    .prod-desc-tab-content > h2{
6195                display:block;
6196            }
6197
6198    @-webkit-keyframes fadeEffect {
6199        from {opacity: 0;}
6200        to {opacity: 1;}
6201    }
6202
6203    @keyframes  fadeEffect {
6204        from {opacity: 0;}
6205        to {opacity: 1;}
6206    }
6207
6208    .tab_drawer_heading { display: none; }
6209
6210    @media  screen and (max-width: 480px) {
6211        .prod-desc-tab {
6212            display: none;
6213        }
6214        .tab_drawer_heading {
6215            background-color: transparent;
6216            color: #000000;
6217            border-bottom: 1px solid #ddd;
6218            margin: 0;
6219            padding: 6px 12px;
6220            display: block;
6221            cursor: pointer;
6222            -webkit-touch-callout: none;
6223            -webkit-user-select: none;
6224            -khtml-user-select: none;
6225            -moz-user-select: none;
6226            -ms-user-select: none;
6227            user-select: none;
6228            position: relative;
6229        }
6230        .tab_drawer_heading:after {
6231            content: '';
6232            top: 50%;
6233            right: 40px;
6234            position: absolute;
6235            border: solid black;
6236            border-width: 0 3px 3px 0;
6237            display: inline-block;
6238            width: 10px;
6239            height: 10px;
6240            margin-top: -5px;
6241            transform: rotate(45deg);
6242            -webkit-transform: rotate(45deg);
6243            -webkit-transition: all 200ms linear;
6244               -moz-transition: all 200ms linear;
6245                -ms-transition: all 200ms linear;
6246                 -o-transition: all 200ms linear;
6247                    transition: all 200ms linear;
6248        }
6249        .d_active {
6250            background-color: rgba(212,212,212,0.3);
6251        }
6252        .d_active.tab_drawer_heading:after{
6253            margin-top: -3px;
6254            transform: rotate(-135deg);
6255            -webkit-transform: rotate(-135deg);
6256        }
6257    }
6258</style>
6259
6260<script type="text/javascript">
6261    // If the page has no jquery
6262    // if(typeof jQuery == 'undefined'){
6263    //  console.log(456);
6264    //  var script = document.createElement('script');
6265    //  script.type = "text/javascript";
6266    //  script.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
6267    //  console.log(script);
6268    //  document.getElementsByTagName('head')[0].appendChild(script);
6269    // }
6270
6271    /* if in tab mode */
6272    $("body").on("click", ".tablinks", function(){
6273        var id = $(this).data("prod-desc-id");
6274
6275        // Get all elements with class="prod-desc-tab-content" and hide them
6276        $(".prod-desc-tab-content").hide();
6277
6278        // Get all elements with class="tablinks" and remove the class "active"
6279        $(".tablinks").removeClass("active");
6280
6281        // Show the current tab, and add an "active" class to the link that opened the tab
6282        $("#"+id+"_desc_tab_content").show();
6283        $(this).addClass("active");
6284
6285        // make mobile view(drawer mode) also in same tab
6286        $(".tab_drawer_heading").removeClass("d_active");
6287        $(".tab_drawer_heading[data-prod-desc-id='"+id+"']").addClass("d_active");
6288
6289    });
6290    
6291    /* if in drawer mode */
6292    $("body").on("click", ".tab_drawer_heading", function() {
6293        var id = $(this).data("prod-desc-id")
6294        var active = $(this).hasClass("d_active")
6295
6296        $(".prod-desc-tab-content").hide();
6297        $(".tab_drawer_heading").removeClass("d_active");
6298
6299        if(!active){
6300            $("#"+id+"_desc_tab_content").show();
6301            $(this).addClass("d_active");
6302            window.scroll({
6303                top: $(this).offset().top - 120,
6304                left: 0,
6305                behavior: 'smooth'
6306            });
6307        }
6308
6309        $(".tablinks").removeClass("active");
6310        $(".tablinks[data-prod-desc-id='"+id+"']").addClass("active");
6311    });
6312
6313    $(function(){
6314        var x = $(".product-description").find("h1, h2, h3, h4, h5, h6");
6315        var title = null;
6316        var body = null;
6317
6318        if(x.length > 1){
6319            $(".product-description").after("<link href='/assets/css/froala_style.min.css' rel='stylesheet' type='text/css'/><div class='product-description-tabs fr-view rte'><ul class='prod-desc-tab' style='margin: auto;'></ul><div class='prod-desc-tab-container'></div></div>");
6320            $(x).each(function(k, v){
6321                title = $(v).text();
6322
6323                if(k == 0){
6324                    body = $(x[0]).nextUntil(x[1]).clone();
6325                    $(".prod-desc-tab").append('<li class="tablinks active" data-prod-desc-id="'+k+'"><a>'+title+'</a></li>');
6326                    $(".prod-desc-tab-container").append('<h3 class="tab_drawer_heading d_active" data-prod-desc-id="'+k+'">'+title+'</h3><div id="'+k+'_desc_tab_content" class="prod-desc-tab-content" style="display:block"><h2>'+title+'</h2></div>');
6327                    $("#"+k+"_desc_tab_content h2").after(body);
6328                }
6329                else if(k == x.length){
6330                    body = $(x[k]).nextAll().clone();
6331                    $(".prod-desc-tab").append('<li class="tablinks" data-prod-desc-id="'+k+'"><a>'+title+'</a></li>');
6332                    $(".prod-desc-tab-container").append('<h3 class="tab_drawer_heading" data-prod-desc-id="'+k+'">'+title+'</h3><div id="'+k+'_desc_tab_content" class="prod-desc-tab-content" style="display:none"><h2>'+title+'</h2></div>');
6333                    $("#"+k+"_desc_tab_content h2").after(body);
6334                }
6335                else{
6336                    body = $(x[k]).nextUntil(x[k+1]).clone();
6337                    $(".prod-desc-tab").append('<li class="tablinks" data-prod-desc-id="'+k+'"><a>'+title+'</a></li>');
6338                    $(".prod-desc-tab-container").append('<h3 class="tab_drawer_heading" data-prod-desc-id="'+k+'">'+title+'</h3><div id="'+k+'_desc_tab_content" class="prod-desc-tab-content" style="display:none"><h2>'+title+'</h2></div>');
6339                    $("#"+k+"_desc_tab_content h2").after(body);
6340                }
6341            });
6342            $(".product-description").hide();
6343        }
6344
6345    });
6346</script>
6346
6347<!-- /Snippet -->
6348<script>
6349
6350  /*
6351
6352    ------
6353    Events
6354    ------
6355
6356    pages/viewed
6357
6358    customers/signup
6359
6360    customers/login
6361
6362    products/searched
6363
6364    collections/viewed
6365
6366    products/viewed
6367
6368    products/shared
6369
6370    wishlists/item_added
6371
6372    carts/items_added
6373
6374    carts/viewed
6375
6376    carts/item_removed
6377
6378    checkouts/initiated
6379
6380    checkouts/shipping_info_added
6381
6382    checkouts/payment_info_added
6383
6384    checkouts/completed
6385
6386    orders/placed
6387
6388    orders/purchased
6389
6390    payments/captured
6391
6392    payments/failed
6393
6394  */
6395
6396  window.__latest_cart = window.__latest_cart || null;
6397
6398  const _selector = document.querySelector.bind(document),
6399        _selectorAll = document.querySelectorAll.bind(document)
6400
6401  document.addEventListener('DOMContentLoaded', (event) => {
6402
6403    const default_currency = getCookie("currency")
6404    const customer_id = window.__st.cid
6405    const template    = window.__st.p
6406
6407    onPageView()
6408
6409    //-----------------------//
6410    //        Configs        //
6411    //-----------------------//
6412
6413    window.dataLayer = window.dataLayer || []
6414
6415    Array.prototype.last = Array.prototype.last || function() {
6416      return this[this.length - 1] || null
6417    }
6418
6419    Array.prototype.first = Array.prototype.first || function() {
6420      return this[0] || null
6421    }
6422
6423    //----------------------//
6424    //       Triggers       //
6425    //----------------------//
6426
6427    const XHR = window.XMLHttpRequest
6428
6429    function xhr() {
6430
6431      const xhr = new XHR()
6432
6433      xhr.addEventListener("readystatechange", function() {
6434
6435        if(xhr.readyState != 4) return
6436
6437        try {
6438
6439          const response_url = xhr.responseURL
6440
6441          if (response_url.includes("cart/add")) {
6442
6443            window.__latest_cart = JSON.parse(xhr.response)
6444
6445            onCartItemsAdded() // ok
6446
6447          }
6448
6449          if (response_url.includes("cart/remove_item_quantity")) {
6450
6451            window.__latest_cart = JSON.parse(xhr.response)
6452
6453            onCartItemRemoved() // ok
6454
6455          }
6456
6457          if (response_url.includes("new_cart?retrieve=true")) {
6458
6459            result = JSON.parse(xhr.response)
6460
6461            if (result.cart) {
6462              window.__latest_cart = result.cart
6463            }
6464
6465          }
6466
6467        } catch(e) {
6468
6469          console.error(e)
6470
6471        }
6472
6473      }, false);
6474
6475      return xhr
6476
6477    }
6478
6479    window.XMLHttpRequest = xhr
6480
6481    switch(template) {
6482
6483      case 'cart': onCartView() // ok
6484      break
6485      case 'product': onProductView() // ok
6486      break
6487      case 'collection': onCollectionView() // ok
6488      break
6489      case 'blog': onBlogView()
6490      break
6491      case 'article': onArticleView()
6492      break
6493      case 'payment_completed': onOrderPlace()
6494      break
6495      case 'payment_fail': onPaymentFail()
6496      break
6497
6498    }
6499
6500    // _selector('form[action="/checkout/payments"]').addEventListener("submit", onPaymentInfoAdded(_selector('form[action="/checkout/payments"]')))
6501    if (_selector('form[action="/checkout/detail"]'))                            _selector('form[action="/checkout/detail"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/detail"]'))})  // ok
6502    if (_selector('form[action="/checkout/shipping"]'))                          _selector('form[action="/checkout/shipping"]').addEventListener("submit", ()=>{onShippingInfoAdded(_selector('form[action="/checkout/shipping"]'))})  // ok
6503    if (_selector('form[action="/account/register"]'))                           _selector('form[action="/account/register"]').addEventListener("submit", onSignUp)  // ok
6504    if (_selector('form[action="/account/login"]'))                              _selector('form[action="/account/login"]').addEventListener("submit", onLogin)  // ok
6505    if (_selector('form[action="/search"]'))                                     _selector('form[action="/search"]').addEventListener("submit", onProductSearch()) // ok
6506    if (_selector('#line-login-btn'))                                            _selector('#line-login-btn').addEventListener('click', onLineLogin) // ok
6507    if (_selector('#PlaceOrder'))                                                _selector('#PlaceOrder').addEventListener("click", ()=>{onCheckoutComplete(_selector('form[action="/checkout/payments"]'))});  // ok
6508    if (_selector('#add_wishlist'))                                              _selector('#add_wishlist').addEventListener("click", onWishlistItemAdded) // ok
6509    if (_selectorAll('a[href="/account/logout"]'))                               _selectorAll('a[href="/account/logout"]').forEach(logoutButton => logoutButton.addEventListener("click", onLogout)) // ok
6510    if (_selector('.CartDrawerTrigger.cart-page-link'))                          _selector('.CartDrawerTrigger.cart-page-link').addEventListener("click", onCartView) // ok
6511    if (_selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link'))    _selector('.CartDrawerTrigger.cart-page-link.mobile-cart-page-link').addEventListener("click", onCartView) // ok
6512    if (_selectorAll('a[class^="share-"]'))                                      _selectorAll('a[class^="share-"]').forEach(shareButton => shareButton.addEventListener("click", ()=>{onProductShare(shareButton)}) ) // ok
6513    if (_selectorAll('[name$="checkout"]'))                                      _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
6514
6515    // For append elements
6516    const bodyMutationObserver = new MutationObserver(() => {
6517      if (_selector('#form__spc #PlaceOrder'))             _selector('#form__spc #PlaceOrder').addEventListener("click", onSinglePageCheckout) // ok
6518      if (_selectorAll('[name$="checkout"]'))              _selectorAll('[name$="checkout"]').forEach(checkoutButton => checkoutButton.addEventListener("click", onCheckoutInitiate))
6519    });
6520    bodyMutationObserver.observe(_selector("body"), {subtree: true, childList: true});
6521
6522    //------------------------------//
6523    //        Event handlers        //
6524    //------------------------------//
6525
6526    function onPageView() {
6527
6528      EasyStore.Event.dispatch('pages/viewed', {
6529        page: {
6530          type: template,
6531          title: document.title,
6532          description: _selector('meta[name=description]') ? _selector('meta[name=description]').getAttribute('content') : null,
6533          url: location.href,
6534        }
6535      })
6536
6537    }
6538
6539    function onSignUp() {
6540
6541      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
6542      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
6543
6544      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
6545
6546      let data = {}
6547
6548      if (email_regex.test(email_or_phone)) {
6549        data.method = 'email'
6550        data.email = email_or_phone
6551      }
6552
6553      if (phone_regex.test(email_or_phone)) {
6554        data.method = "phone"
6555        data.phone = email_or_phone
6556      }
6557
6558      if (!data.method) return
6559
6560      EasyStore.Event.dispatch('customers/signup', data)
6561
6562    }
6563
6564    function onLogin() {
6565
6566      const email_regex = new RegExp(/^[a-zA-Z0-9.!#$%&"*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/)
6567      const phone_regex = new RegExp(/^(\+?6?01)[0-46-9]-*[0-9]{7,8}$/)
6568
6569      const email_or_phone = _selector(`input[name="customer[email_or_phone]"]`).value.replace("+", "").replace(/\s+/, "")
6570
6571      let data = {}
6572
6573      if (email_regex.test(email_or_phone)) {
6574        data.method = 'email'
6575        data.email = email_or_phone
6576      }
6577
6578      if (phone_regex.test(email_or_phone)) {
6579        data.method = "phone"
6580        data.phone = email_or_phone
6581      }
6582
6583      if (!data.method) return
6584
6585      EasyStore.Event.dispatch('customers/login', data)
6586
6587    }
6588
6589    function onLineLogin() {
6590
6591      EasyStore.Event.dispatch('customers/login', { method: 'line' })
6592
6593    }
6594
6595    function onLogout() {
6596
6597      EasyStore.Event.dispatch('customers/logout', { customer_id })
6598
6599    }
6600
6601    function onBlogView() {
6602
6603      const blog = ""
6604
6605      EasyStore.Event.dispatch('blogs/viewed', { blog })
6606
6607    }
6608
6609    function onArticleView() {
6610
6611      const article = ""
6612
6613      EasyStore.Event.dispatch('articles/viewed', { article })
6614
6615    }
6616
6617    function onProductSearch() {
6618
6619      const query = _selector('input[name=q]').value
6620
6621      if (!query) return
6622
6623      EasyStore.Event.dispatch('products/searched', { query })
6624
6625    }
6626
6627    function onCollectionView() {
6628
6629      const collection = ""
6630
6631      EasyStore.Event.dispatch('collections/viewed', { collection })
6632
6633    }
6634
6635    function onProductView() {
6636
6637      const product = ""
6638
6639      EasyStore.Event.dispatch("products/viewed", { product })
6640
6641    }
6642
6643    function onProductShare(el) {
6644
6645      const product = ""
6646
6647      const channel = el.getAttribute("class").split("-").last()
6648
6649      EasyStore.Event.dispatch('products/shared', { product, channel })
6650
6651    }
6652
6653    function onWishlistItemAdded() {
6654
6655      let product  = ""
6656      const quantity = _selector("#Quantity").value
6657
6658      EasyStore.Event.dispatch('wishlists/item_added', { product })
6659
6660    }
6661
6662    async function onCartItemsAdded() {
6663
6664      const cart = await getCart()
6665
6666      if(cart && cart.items != undefined && cart.items.length > 0) {
6667
6668        EasyStore.Event.dispatch('carts/item_added', { cart })
6669
6670      }
6671
6672    }
6673
6674    async function onCartView() {
6675
6676      const cart = await getCart()
6677
6678      EasyStore.Event.dispatch('carts/viewed', { cart })
6679
6680    }
6681
6682    async function onCartItemRemoved() {
6683
6684      const cart = await getCart()
6685
6686      cart.items = []
6687
6688      if(cart) {
6689
6690        EasyStore.Event.dispatch('carts/item_removed', { cart })
6691
6692      }
6693
6694    }
6695
6696    async function onCheckoutInitiate() {
6697
6698      const cart = await getCart()
6699
6700      EasyStore.Event.dispatch('checkouts/initiated', { cart })
6701
6702    }
6703
6704    async function onShippingInfoAdded(form) {
6705      let checkout = getCheckout()
6706
6707      let form_data = {}
6708      new FormData(form).forEach((value, key) => form_data[key] = value)
6709
6710      let shipping_tier = null
6711
6712      if (form_data.type && form_data.type.startsWith("r_pickup")) {
6713        shipping_tier = `Pickup - ${form_data.pick_location}`
6714      }
6715
6716      if (form_data.s_id) {
6717        shipping_tier = _selector(`input[id='`+form_data.s_id+`']`).getAttribute("data-shipping-name")
6718      }
6719
6720      if (!shipping_tier) return
6721
6722      EasyStore.Event.dispatch('checkouts/shipping_info_added', { checkout, shipping_tier })
6723
6724    }
6725
6726    async function onPaymentInfoAdded(form) {
6727
6728      let checkout = getCheckout()
6729
6730      let payment_type = new FormData(form).get('payment_method')
6731
6732      EasyStore.Event.dispatch("checkouts/payment_info_added", { checkout, payment_type })
6733
6734    }
6735
6736    async function onOrderPlace() {
6737
6738      let cart_token  = getCookie("cart_js")
6739      let previous_cart_token = getCookie("previous_cart_ga4_js")
6740
6741      if (previous_cart_token && previous_cart_token == cart_token) {
6742        // Prevent duplicate purchase tracking
6743        return
6744      }
6745
6746      let order = getOrder()
6747
6748      EasyStore.Event.dispatch('orders/placed', { order })
6749
6750      if(order.is_manual_payment) {
6751
6752        EasyStore.Event.dispatch('orders/purchased', { order })
6753
6754      }
6755
6756      const last_transaction = order.transactions.last()
6757
6758      if (last_transaction.status) {
6759
6760        EasyStore.Event.dispatch('orders/purchased', { order })
6761        EasyStore.Event.dispatch('payments/captured', { order })
6762
6763      }
6764
6765    }
6766
6767    async function onPaymentFail() {
6768
6769      const order = getOrder()
6770
6771      EasyStore.Event.dispatch('payments/failed', { order })
6772
6773    }
6774
6775    async function onCheckoutComplete(form) {
6776
6777      onPaymentInfoAdded(form)
6778
6779      const checkout = getCheckout()
6780
6781      EasyStore.Event.dispatch('checkouts/completed', { checkout })
6782
6783    }
6784
6785    async function onSinglePageCheckout() {
6786
6787      // let checkout = $("[data-app-checkout]").data("app-checkout")
6788
6789      let checkout = getCheckout()
6790
6791      // const payment_type = _selector("#app_spc_payment_method").find(`[class*="label-content"]`).first().find("b").first().text()
6792      const payment_type = _selector("#app_spc_payment_method").getElementsByClassName('label-content')[0].getElementsByTagName('b')[0].innerHTML
6793
6794      const shipping_method = _selector("#delivery_method").value
6795
6796      let shipping_tier = null
6797      let app_spc_customer_info_label = _selector("#app_spc_customer_info").getElementsByClassName('label-content')
6798      if (shipping_method == "shipping") {
6799        shipping_tier = app_spc_customer_info_label[app_spc_customer_info_label.length - 1].getElementsByTagName('b')[0].innerHTML
6800      }
6801
6802      if (shipping_method == "pickup") {
6803        shipping_tier = app_spc_customer_info_label[0].innerHTML
6804      }
6805
6806      if (shipping_tier) {
6807
6808        EasyStore.Event.dispatch('checkouts/shipping_info_added', {
6809          checkout,
6810          shipping_tier,
6811        })
6812
6813      }
6814
6815      if (payment_type) {
6816
6817        EasyStore.Event.dispatch('checkouts/payment_info_added', {
6818          checkout,
6819          payment_type,
6820        })
6821
6822      }
6823
6824      EasyStore.Event.dispatch('checkouts/completed', { checkout })
6825
6826    }
6827
6828  })
6829
6830
6831  //-----------------------//
6832  //       Functions       //
6833  //-----------------------//
6834
6835  function getCookie(name) {
6836
6837    name += "="
6838
6839    decodedCookie = decodeURIComponent(document.cookie)
6840
6841    ca = decodedCookie.split(";")
6842
6843    for(i = 0; i < ca.length; i++) {
6844      c = ca[i]
6845      while (c.charAt(0) == " ") {
6846        c = c.substring(1)
6847      }
6848      if (c.indexOf(name) == 0) {
6849        return c.substring(name.length, c.length)
6850      }
6851    }
6852
6853    return ""
6854
6855  }
6856
6857  const parsePrice = price => {
6858    if(typeof price === 'string') {
6859      return parseFloat(price.split(',').join(''))
6860    }
6861
6862    return price
6863  }
6864
6865  const requestCart = async (method, data) => {
6866
6867  let response = await fetch('/cart.json', {method: 'GET',headers: {'Content-Type': 'application/json'}})
6868    result = await response.json()
6869
6870    return result.cart
6871
6872  }
6873  const getCart = async (latest = false) => {
6874
6875    let cart = window.__latest_cart
6876
6877    const cart_invalid = !cart || !cart.items || (cart.total_price > 0 && !cart.items.length)
6878
6879    if(latest || cart_invalid) {
6880      cart = await requestCart()
6881    }
6882
6883    cart.items = cart.items || []
6884
6885    return mapCart(cart)
6886
6887  }
6888
6889  const getCheckout = async () => {
6890    mapCheckout(window.__latest_cart || await requestCart())
6891  }
6892
6893  const getOrder = async () => {
6894    mapOrder(window.__latest_cart || await requestCart())
6895  }
6896
6897  //-----------------------//
6898  //        Mappers        //
6899  //-----------------------//
6900
6901  const fallbackAttribute = (object, attribute) => {
6902
6903    if(!Array.isArray(attribute)) {
6904      attribute = [attribute]
6905    }
6906
6907    let final_value = null
6908
6909    do {
6910
6911      final_value = object[attribute.shift()]
6912
6913    } while(!final_value && attribute.length)
6914
6915    return final_value
6916
6917  }
6918
6919  const map = (object, mapper) => {
6920
6921    const newObject = {}
6922
6923    for(const key in mapper) {
6924
6925      // Handle different keys between new and old format
6926      newObject[key] = fallbackAttribute(object, mapper[key])
6927
6928      // Cast price to float
6929      if(newObject[key] && ['price', 'amount', 'discount', 'discounts'].some(x => key.endsWith(x))) {
6930        newObject[key] = parsePrice(newObject[key])
6931      }
6932
6933      if(newObject[key] === undefined) {
6934        delete newObject[key]
6935      }
6936
6937    }
6938
6939    return newObject
6940
6941  }
6942
6943  const mapCart = cart => {
6944
6945    const oldCart = cart
6946
6947    const mapper = {
6948      id: 'id',
6949      currency: 'currency',
6950      item_count: 'item_count',
6951      items: 'items',
6952      total_price: 'total_price',
6953      latest_items: 'latest_items'
6954    }
6955
6956    cart = map(cart, mapper)
6957
6958    const discounts = (oldCart.storewide_discounts || []).concat((oldCart.voucher_discounts || []))
6959
6960    cart.discount_applications = discounts.map(discount => ({
6961      title: discount.voucher_code || null,
6962      value: parsePrice(discount.amount),
6963    }))
6964
6965    cart.original_total_price = cart.items.length
6966    ? cart.items
6967      .map(item => item.original_price)
6968      .reduce((sum, price) => sum + price)
6969    : 0
6970
6971    cart.total_discount = cart.discount_applications.length
6972    ? cart.discount_applications
6973      .map(discount => parsePrice(discount.value))
6974      .reduce((sum, value) => sum + value)
6975    : 0
6976
6977    cart.items = cart.items.map(item => mapLineItem(item))
6978
6979    return cart
6980
6981  }
6982
6983  const mapCheckout = checkout => {
6984
6985    const mapper = {
6986      note: 'note',
6987      attributes: 'note_attributes',
6988      billing_address: 'billing_address',
6989      currency: 'currency',
6990      customer_id: 'customer_id',
6991      discounts_amount: 'total_discount',
6992      id: 'id',
6993      line_items: 'order_item',
6994      order_number: 'order_number',
6995      shipping_address: 'shipping_address',
6996      shipping_price: 'shipping_tax',
6997      shipping_method: 'shipping_method_name',
6998      tax_price: 'total_tax',
6999    }
7000
7001    checkout = map(checkout, mapper)
7002
7003    checkout.requires_shipping = checkout.line_items.some(item => item.shipping_required)
7004
7005    checkout.line_items = checkout.line_items.map(item => mapLineItem(item))
7006
7007    return checkout
7008
7009  }
7010
7011  const mapOrder = order => {
7012
7013    const mapper = {
7014      attributes: 'note_attributes',
7015      billing_address: 'billing_address',
7016      cancelled: 'is_cancelled',
7017      cancelled_at: 'cancelled_at',
7018      created_at: 'created_at',
7019      customer_id: 'customer_id',
7020      // discount_applications: 'discount_applications',
7021      email: 'email',
7022      financial_status: 'financial_status',
7023      fulfillment_status: 'fulfillment_status',
7024      line_items: 'order_item',
7025      note: 'note',
7026      order_number: 'order_number',
7027      phone: 'phone',
7028      shipping_address: 'shipping_address',
7029      shipping_methods: 'shipping_methods',
7030      shipping_price: 'total_shipping',
7031      subtotal_price: 'subtotal_price',
7032      // tax_lines: 'tax_lines',
7033      tax_price: 'total_tax',
7034      total_discounts: 'total_discount',
7035      total_net_amount: 'total_amount_include_transaction',
7036      total_price: 'total_price',
7037      transactions: 'transaction_records',
7038      is_manual_payment: 'is_manual_payment',
7039    }
7040
7041    order.email = order.billing_address.email
7042    order.phone = order.billing_address.phone
7043    order.shipping_method = order.shipping_method_name
7044
7045    order = map(order, mapper)
7046
7047    order.line_items = order.line_items.map(item => mapLineItem(item))
7048    order.transactions = order.transactions.map(transaction => mapTransaction(transaction))
7049
7050    return order
7051
7052  }
7053
7054  const mapLineItem = line_item => {
7055
7056    const old_line_item = line_item
7057
7058    const mapper = {
7059      final_price: 'price',
7060      image: 'img_url',
7061      message: 'message',
7062      original_line_price: 'original_line_price',
7063      original_price: 'original_price',
7064      properties: 'properties',
7065      quantity: 'quantity',
7066      requires_shipping: 'shipping_required',
7067      sku: 'sku',
7068      taxable: 'taxable',
7069      title: 'product_name',
7070      product_name: 'product_name',
7071      url: 'url',
7072      product_id: 'product_id',
7073      variant_id: 'variant_id',
7074      id: ['id', 'i_id'],
7075    }
7076
7077    line_item = map(line_item, mapper)
7078
7079    line_item.product_id = line_item.product_id || (old_line_item.product && old_line_item.product.id) || null
7080    line_item.variant_id = line_item.variant_id || (old_line_item.variant && old_line_item.variant.id) || null
7081    line_item.image      = line_item.image || (old_line_item.image && old_line_item.image.url) || null
7082
7083    return line_item
7084
7085  }
7086
7087  const mapTransaction = transaction => {
7088
7089    const mapper = {
7090      amount: 'amount',
7091      created_at: 'created_at',
7092      gateway: 'gateway_type',
7093      id: 'id',
7094      status: 'status',
7095    }
7096
7097    transaction = map(transaction, mapper)
7098
7099    return transaction
7100
7101  }
7102
7103
7104</script>
7104
7105
7106</body>
7107</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.