PageSourceSearch

https://mastiff.ext.hp.com/gw/hpit/cs/mastiff/1.0/supportweb/HP_scraper.js

js hp.com collected 2026-09-24 08:27:21 UTC 542,093 bytes, 11,072 lines download raw bytes

1if (sessionStorage.getItem("mastiffdebug") === null) {
2    const onProd = window.location && window.location.hostname === "support.hp.com";
3    sessionStorage.setItem("mastiffdebug", "false");
4    sessionStorage.setItem("mastifflog", "false");
5}
6
7function isMastiffDebug() {
8    return sessionStorage.getItem("mastiffdebug") === "true";
9}
10
11function getMastiffUrl() {
12    return isMastiffDebug()
13        ? "https://mastiff-itg.ext.hp.com/gw/hpit/cs/mastiff.itg/1.0/MastiffService-1/getOffer"
14        : "https://mastiff.ext.hp.com/gw/hpit/cs/mastiff/1.0/MastiffService-1/getOffer";
15}
16
17var PAGE_CONFIG = {
18    warrantyresult_falcon: {
19        offerLocations: "primary,shop1,shop2,shop3,secondary",
20        positions: {
21            primary: {
22                placeholderSelector: "#warranty_spos_template3, #warranty_spos_template3_mobile",
23                containerSelector: "#mastiff-check-warranty-primary-offer"
24            },
25            secondary: {
26                placeholderSelector: "#warranty_spos_template4",
27                containerSelector: "#mastiff-check-warranty-secondary-offers"
28            },
29            shop1: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" },
30            shop2: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" },
31            shop3: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }
32        }
33    },
34    pdp_falcon: {
35        offerLocations: "primary,shop1,shop2,shop3,secondary",
36        positions: {
37            primary: { placeholderSelector: "#pdp_spos_template1, #pdp_spos_template1_mobile" },
38            secondary: { placeholderSelector: "#pdp_spos_template4" },
39            shop1: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" },
40            shop2: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" },
41            shop3: { placeholderSelector: "#pdp_spos_shoptab_template2", containerSelector: ".shop" }
42        }
43    },
44    warrantyresult_falcon: {
45        offerLocations: "primary,shop1,shop2,shop3,secondary",
46        positions: {
47            primary: {
48                placeholderSelector: "#warranty_spos_template3, #warranty_spos_template3_mobile",
49                containerSelector: "#mastiff-check-warranty-primary-offer"
50            },
51            secondary: {
52                placeholderSelector: "#warranty_spos_template4",
53                containerSelector: "#mastiff-check-warranty-secondary-offers"
54            },
55            shop1: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" },
56            shop2: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" },
57            shop3: { placeholderSelector: "#mastiff-check-warranty-secondary-offers", containerSelector: ".WRSecondarySlidercontainer" }
58        }
59    },
60    drivers_closure: {
61        offerLocations: "primary",
62        positions: { primary: { placeholderSelector: "#mastiff-diag-banner" } }
63    },
64    drivers_details: {
65        offerLocations: "primary,secondary",
66        positions: {
67            primary: { placeholderSelector: "#swd_spos_template6" },
68            secondary: { placeholderSelector: "#mastiff-diag-banner" }
69        }
70    },
71    document: {
72        offerLocations: "primary",
73        positions: { primary: { placeholderSelector: "#opt-mastiff-doc" } }
74    },
75    contact: {
76        offerLocations: "primary,secondary",
77        positions: {
78            primary: { placeholderSelector: "#contact_option_mastiff_tile_template" },
79            secondary: { placeholderSelector: "#contact_resource_mastiff_template" },
80            phone: { placeholderSelector: "#phone_fee_mastiff_tile_template" }
81        }
82    },
83    "contact-solution": {
84        // New Contact Solution pages expect a single primary placement only
85        offerLocations: "primary",
86        positions: {
87            primary: { placeholderSelector: "#mastiff-pfw-contact-solutions" }
88        }
89    },
90    "contact-hp": {
91        offerLocations: "primary,secondary",
92        positions: {
93            primary: { placeholderSelector: "#co_spos_template5" },
94            secondary: { placeholderSelector: "#contact_resource_mastiff_template" }
95        }
96    },
97    contact_closure: {
98        offerLocations: "primary,secondary",
99        positions: {
100            primary: { placeholderSelector: ".mastiff_template_container" },
101            secondary: { placeholderSelector: "#contact-summary-warranty-mastiff" }
102        }
103    },
104    "printer-setup": {
105        offerLocations: "primary,shop1,shop2,shop3,secondary",
106        positions: {
107            primary: { placeholderSelector: "#opt-mastiff-setup" },
108            secondary: { placeholderSelector: "#mastiffoffers" },
109            shop1: { placeholderSelector: "#mastiffoffers" },
110            shop2: { placeholderSelector: "#mastiffoffers" },
111            shop3: { placeholderSelector: "#mastiffoffers" }
112        }
113    },
114    repair: {
115        offerLocations: "primary",
116        positions: { primary: { placeholderSelector: "#mastiffoffers" } }
117    },
118    "hardware-diagnostics": {
119        offerLocations: "primary",
120        positions: { primary: { placeholderSelector: "#mastiffoffers" } }
121    },
122    service: {
123        offerLocations: "secondary",
124        positions: {
125            secondary: { placeholderSelector: "#mastiff_SDP_sticky_banner", containerSelector: "#sdp-mastiff
125-banner-container" }
126        }
127    },
128    home: {
129        offerLocations: "primary",
130        positions: { primary: { placeholderSelector: ".mastiff_template_container" } }
131    },
132    home_printer: {
133        offerLocations: "primary",
134        positions: { primary: { placeholderSelector: ".mastiff_template_container" } }
135    },
136    home_computer: {
137        offerLocations: "primary",
138        positions: { primary: { placeholderSelector: ".mastiff_template_container" } }
139    },
140    dashboard: {
141        offerLocations: "carousel",
142        positions: {
143            primary: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" },
144            secondary: { placeholderSelector: "#mastiffoffers" },
145            shop1: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" },
146            shop2: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" },
147            shop3: { placeholderSelector: "#dashboard_tile_mastiff_template", containerSelector: ".dashboardSlidercontainer" }
148        }
149    },
150    "help-printer": {
151        offerLocations: "primary,secondary",
152        positions: {
153            primary: { placeholderSelector: "#mastiff-diag-banner" },
154            secondary: { placeholderSelector: "#mastiff_diag_sticky_banner", containerSelector: "#diag-mastiff-banner-container" }
155        }
156    },
157    "help-computer": {
158        offerLocations: "primary,shop1,secondary",
159        positions: {
160            primary: { placeholderSelector: "#mastiff-diag-banner" },
161            secondary: { placeholderSelector: "#mastiff_diag_sticky_banner", containerSelector: "#diag-mastiff-banner-container" },
162            shop1: { placeholderSelector: "#mastiff-partstore" }
163        }
164    },
165    "help-windows": {
166        offerLocations: "secondary",
167        positions: {
168            secondary: { placeholderSelector: "#mastiff-sticky-banner", containerSelector: "#mastiff-sticky-banner" }
169        }
170    },
171    default: {
172        offerLocations: "primary,shop1,shop2,shop3,secondary",
173        positions: {
174            primary: { placeholderSelector: "#mastiffoffers" },
175            secondary: { placeholderSelector: "#mastiffoffers" },
176            shop1: { placeholderSelector: "#mastiffoffers" },
177            shop2: { placeholderSelector: "#mastiffoffers" },
178            shop3: { placeholderSelector: "#mastiffoffers" }
179        }
180    }
181};
182
183
184var PAGE_OFFER_MAP = [
185    {
186        pages: ["home", "home_printer", "home_computer"],
187        positions: {
188            primary: {
189                // fn: "showCarouselBanner",
190                placeholder: ".mastiff_template_container",
191                insert: "html",
192                required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"],
193                replacements: {
194                    "%LargeBannerImgPlaceholder%": "imageURL",
195                    "%LargeBannerTitleplaceholder%": "primaryText1",
196                    "%LargeBannerDescriptionplaceholder%": "primaryText2",
197                    "%LargeBannerCTAplaceholder%": "primaryButtonText"
198                },
199                hide: "none"
200            }
201        }
202    },
203    {
204        page: "contact_closure",
205        positions: {
206            primary: {
207                // fn: "showCarouselBanner",
208                placeholder: ".mastiff_template_container",
209                insert: "html",
210                required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"],
211                replacements: {
212                    "%LargeBannerImgPlaceholder%": "imageURL",
213                    "%LargeBannerTitleplaceholder%": "primaryText1",
214                    "%LargeBannerDescriptionplaceholder%": "primaryText2",
215                    "%LargeBannerCTAplaceholder%": "primaryButtonText"
216                },
217                hide: "none"
218            },
219            secondary: {
220                // fn: "showContactSummaryOffer",
221                placeholder: "#contact-summary-warranty-mastiff",
222                insert: "append",
223                required: ["html", "primaryButtonText", "storeURL"],
224                replacements: {
225                    "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText",
226                    "%simpleLinkTemplateURL%": "storeURL",
227                    "%simpleLinkTemplateId%": "divId"
228                },
229                hide: "$(\"#contact-summary-warranty-mastiff\").hide()"
230            }
231        }
232    },
233    {
234        page: "drivers_details",
235        positions: {
236            detailsCategory: {
237                // fn: "showSwdViewInStoreOffer",
238                placeholder: "#mastiff_view_in_store_SWD",
239                insert: "html",
240                required: ["html", "primaryButtonText", "storeURL"],
241                replacements: {
242                    "%simpleLinkTemplateImgURL%": "imageURL",
243                    "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText",
244                    "%simpleLinkTemplateId%": "divId"
245                },
246                hide: "none"
247            },
248            primary: {
249                // fn: "showDriverDetailsOffer",
250                placeholder: "#driversPageMastiffBannerTop",
251                insert: "html",
252                required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"],
253                replacements: {
254                    "%DriverTileOfferImgURLPlaceholder%": "imageURL",
255                    "%DriverTileOfferTitlePlaceholder%": "primaryText1",
256                    "%DriverTileOfferDescriptionPlaceholder%": "primaryText2",
257                    "%DriverTileOfferCTAPlaceholder%": "primaryButtonText",
258                    "%DriverTileOfferId%": "divId",
259                    "%secondaryContactHPOfferIdPlaceholder%": "divId"
260                },
261                hide: "none"
262            },
263            secondary: {
264                // fn: "showDriverDetailsOffer",
265                placeholder: "#driversPageMastiffBannerBot",
266                insert: "html",
267                required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"],
268                replacements: {
269                    "%DriverTileOfferImgURLPlaceholder%": "imageURL",
270                    "%DriverTileOfferTitlePlaceholder%": "primaryText1",
271                    "%DriverTileOfferDescriptionPlaceholder%": "primaryText2",
272                    "%DriverTileOfferCTAPlaceholder%": "primaryButtonText",
273                    "%DriverTileOfferId%": "divId",
274                    "%secondaryContactHPOfferIdPlaceholder%": "divId"
275                },
276                hide: "none"
277            },
278            shop1: {
279                placeholder: "#",
280                insert: "html",
281                required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"],
282                replacements: {
283                    "%DriverTileOfferImgURLPlaceholder%": "imageURL",
284                    "%DriverTileOfferTitlePlaceholder%": "primaryText1",
285                    "%DriverTileOfferDescriptionPlaceholder%": "primaryText2",
286                    "%DriverTileOfferCTAPlaceholder%": "primaryButtonText",
287                    "%DriverTileOfferId%": "divId",
288                    "%secondaryContactHPOfferIdPlaceholder%": "divId"
289                },
290                hide: "none"
291            }
292        }
293    },
294    {
295        page: "drivers_closure",
296        positions: {
297            primary: {
298                // fn: "showDriverClosurePrimaryOffer",
299                placeholder: "#swdClosurePageMastiffBanner",
300                insert: "html",
301                required: ["html", "primaryText1", "primaryText2", "primaryButtonText", "imageURL", "storeURL"],
302                replacements: {
303                    "%DriverTileOfferImgURLPlaceholder%": "imageURL",
304                    "%DriverTileOfferTitlePlaceholder%": "primaryText1",
305                    "%DriverTileOfferDescriptionPlaceholder%": "primaryText2",
306                    "%DriverTileOfferCTAPlaceholder%": "primaryButtonText",
307                    "%DriverTileOfferId%": "divId"
308                },
309                hide: "none"
310            }
311        }
312    },
313    {
314        page: "service",
315        positions: {
316            secondary: {
317                // fn: "showStickyBannerSecondaryOffer",
318                container: "#sdp-mastiff-banner-container",
319                placeholder: "#mastiff_SDP_sticky_banner",
320                insert: "html",
321                required: ["html", "primaryText1", "primaryButtonText", "storeURL"],
322                replacements: {
323                    "{title}": "primaryText1",
324                    "{cta}": "primaryButtonText",
325                    "%stickyFooterOfferId%": "divId"
326                },
327                hide: "hideContainer('#sdp-mastiff-banner-container','hide')"
328            }
329        }
330    },
331    {
332        pages: ["repair", "hardware-diagnostics"],
333        positions: {
334            "1r4ccontainer": {
335                // fn: "showHelpPageOffer",
336                placeholder: "#mastiff-offer-content",
337                insert: "html",
338                required: ["html", "primaryText1"],
339                replacements: {
340                    "{title}": "primaryText1",
341                    "{description}": "primaryText2",
342                    "%divId%": "divId"
343                },
344                hide: "none"
345            },
346            "1r4cTile": {
347                // fn: "showHelpPageOffer",
348                placeholder: "#DiagsRepairsDSPOSOffersContainer",
349                insert: "append",
350                required: ["html", "imageURL", "primaryText1", "primaryText2", "primaryButtonText", "storeURL"],
351                replacements: {
352                    "%falconContactHPImgURLPlaceholder%": "imageURL",
353                    "%falconContactHPOfferTitlePlaceholder%": "primaryText1",
354                    "%falconContactHPOfferDescriptionPlaceholder%": "primaryText2",
355                    "%falconContactHPOfferCTAPlaceholder%": "primaryButtonText",
356                    "%falconContactHPOfferIdPlaceholder%": "divId"
357                },
358                hide: "none"
359            }
360        }
361    },
362    {
363        pages: ["help-computer", "help-printer"],
364        positions: {
365            primary: {
366                // fn: "showHelpPrimaryOffer",
367                placeholder: "#mastiff-diag-banner",
368                insert: "html",
369                required: ["html", "storeURL", "primaryButtonText", "primaryText1", "primaryText2", "imageURL"],
370                replacements: {
371                    "%imageurlPlaceholder%": "imageURL",
372                    "%titlePlaceholder%": "primaryText1",
373                    "%descriptionPlaceholder%": "primaryText2",
374                    "%ctaPlaceholder%": "primaryButtonText",
375                    "%PrimaryDiagnosticsTabsTileOfferIdPlaceholder%": "divId"
376                },
377                hide: "hideContainer('#mastiff-diag-banner','hidden')"
378            },
379            secondary: {
380                // fn: "showStickyBannerSecondaryOffer",
381                container: "#diag-mastiff-banner-container",
382                placeholder: "#mastiff_diag_sticky_banner",
383                insert: "html",
384                required: ["html", "primaryText1", "primaryButtonText", "storeURL"],
385                replacements: {
386                    "{title}": "primaryText1",
387                    "{cta}": "primaryButtonText",
388                    "%stickyFooterOfferId%": "divId"
389                },
390                hide: "hideContainer('#diag-mastiff-banner-container','hide')"
391            },
392            shop1: {
393                placeholder: "#mastiff-partstore",
394                insert: "html",
395                required: ["html", "storeURL", "primaryButtonText"],
396                replacements: {
397                    "%simpleLinkTemplateCTAplaceholder%": "primaryButtonText",
398                    "%simpleLinkTemplateURL%": "storeURL",
399                    "%PromoTileId%": "divId"
400                },
401                hide: "hideContainer('#mastiff-partstore','hidden')"
402            },
403            owDiagsContainer: {
404                placeholder: ".warranty-container", //.warranty-container
405                insert: "html",
406                required: ["html", "primaryText1"],
407                replacements: {
408                    "{title}": "primaryText1"
409                },
410                hide: "hideContainer('.warranty-container','hidden')"
411            },
412            owDiags: {
413                placeholder: ".warranty-container .DiagsOOWSectionOffers",
414                insert: "append",
415                required: ["html", "storeURL", "primaryButtonText"],
416                replacements: {
417                    "{cta}": "primaryButtonText",
418                    "{imageurl}": "imageURL",
419                    "%simpleLinkTemplateId%": "divId"
420                },
421                hide: "none"
422            }
423        }
424    },
425    {
426        page: "document",
427        positions: {
428            primary: {
429                // fn: "showDocumentOffer",
430                placeholder: "#opt-mastiff-doc",
431                insert: "append",
432                required: ["html", "imageURL", "primaryText1", "primaryButtonText", "storeURL"],
433                replacements: {
434                    "%offerimageURLPlaceholder%": "imageURL",
435                    "%offerprimaryText1PlaceHolder%": "primaryText1",
436                    "%offerprimaryText2PlaceHolder%": "primaryText2",
437                    "%offerprimaryButtonTextPlaceHolder%": "primaryButtonText"
438                },
439                hide: "none"
440            }
441        }
442    },
443    {
444        page: "pdp_falcon",
445        positions: {
446            wtywidget: {
447                // fn: "",
448                placeholder: "#mastiff-extend-wty-pdp",
449                insert: "html",
450                required: ["html", "primaryButtonText", "storeURL"],
451                replacements: {
452                    "{imageurl}": "imageURL",
453                    "{cta}": "primaryButtonText",
454                    "%simpleLinkTemplateId%": "divId"
455                },
456                hide: "none",
457                templateReference: "swTemplate3"
458            }
459        }
460    },
461    {
462        page: "help-windows",
463        positions: {
464            secondary: {
465                container: "#mastiff-sticky-banner",
466                placeholder: "#mastiff-sticky-banner",
467                insert: "html",
468                required: ["html", "primaryText1", "primaryButtonText", "storeURL"],
469                replacements: {
470                    "{title}": "primaryText1",
471                    "{cta}": "primaryButtonText",
472                    "%stickyFooterOfferId%": "divId"
473                },
474                hide: "hideContainer('#mastiff-sticky-banner','hide')"
475            }
476        }
477    },
478    {
479        page: "contact-landing",
480        positions: {
481            "1r3ccontainer": {
482                placeholder: "#mastiff-quicklink-section",
483                insert: "html",
484                required: ["html", "primaryText1"],
485                replacements: {
486                    "{title}": "primaryText1",
487                    "{description}": "primaryText2",
488                    "%divId%": "divId"
489                },
490                hide: "none"
491            },
492            "1r3cTile": {
493                placeholder: "#contactEntryOffersContainer",
494                insert: "append",
495                required: ["html", "imageURL", "primaryText1", "primaryText2", "primaryButtonText", "storeURL"],
496                replacements: {
497                    "%OWEntryOfferImgURLPlaceholder%": "imageURL",
498                    "%OWEntryOfferTitlePlaceholder%": "primaryText1",
499                    "%OWEntryOfferDescriptionPlaceholder%": "primaryText2",
500                    "%OWEntryOfferCTAPlaceholder%": "primaryButtonText",
501                    "%falconContactHPOfferIdPlaceholder%": "divId"
502                },
503                hide: "none"
504            }
505        }
506    },
507];
508
509var offerResults = null;
510var accessoriesOfferResults = null;
511
512var reqObj = {};
513
514var pgName = pageName();
515
516var LeadOfferIndex = 1;
517var enableDashTile = false;
518
519var intentBasedLocationEmpty = true;
520var enablePromoTab = false;
521var enablepdpCarousel = false;
522var samePage = false;
523var deviceInfo = null;
524
525var intentPDPCategories = ["setup-user-guides", "tools-dignostics", "warranty-repair", "security-viruses", "ink-paper", "troubleshooting"];
526
527var promoTab = "<div id=\"promoContainer\"> <style> #promoContainer { border-top: 1px solid #dbdbdb; } .promoTitle { font-family: Forma DJR Micro; font-size: 24px; font-weight: 400; line-height: 32px; margin-top: 20px; } .promoOffers { margin-top: 26px; margin-bottom: 50px; display: flex; } @media screen and (min-width: 601px) and (max-width: 1158px) { .promoOffers { flex-direction: column; align-items: center; } .promoTiles { margin-top: 10px; } } @media screen and (max-width: 600px) { .promoOffers { flex-direction: column; align-items: center; margin-bottom: 30px; } .promoTitle { font-size: 14px !important; line-height: 20px !important; margin-top: 20px !important; } } </style> <h2 class=\"promoTitle\">Promotions & deals</h2> <div class=\"promoOffers\"> <div class=\"promoTiles\"> <div class=\"promoPrimaryTile\"></div> <div class=\"promoSecondaryTile\"></div> </div> </div> </div>";
528
529var promoShopOfferSliderDiv = "<div class=\"promoCarousel\"> <style> .promoCarousel { margin-right: 30px; margin-bottom: 30px; border-radius: 16px; background: #FFFFFF; box-shadow: 0 1px 4px 1px #21212133; position: relative; } .promoCarousel #navigation { position: absolute; display: flex; right: 15.57px; bottom: -20px; padding: 0px 10px; align-items: center; height: 56px; border-radius: 16px; background: #FFFFFF; box-shadow: 0 1px 4px 1px #21212133; } .promoCarousel .elipse { background: #0278AB; border-radius: 50%; cursor: pointer; margin: 0px 8px 0px 8px; width: 30px; height: 30px; position: relative; } .disabledElipse { background: #ADADAD; border-radius: 50%; margin: 0px 8px 0px 8px; width: 30px; height: 30px; position: relative; } .disabledElipse:focus { box-shadow: none}  .promoCarousel .elipse:hover { transition: 0.1s; background: #035C84; } .promoCarousel .elipse:active { transform: scale(0.9); } .promoCarousel .arrow { color: #FFF; width: 7.5px; height: 7.5px; position: absolute; top: 10.5px; } .promoCarousel .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 12px; } .promoCarousel .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 12px; } @media screen and (min-width: 601px) and (max-width: 1158px) { .promoCarousel { margin-right: 0px; } } @media screen and (max-width: 600px) { .promoCarousel { margin-right: 0px; margin-bottom: 56px; height: initial; } .promoCarousel #navigation { right: -5px; } } </style> <div id=navigation> <a tabindex=0 class=elipse id=SPOS_navLeft onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=0 class=elipse id=SPOS_navRight onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div>";
530var wtyShopOfferSliderDiv = "<div class=\"WRSecondarySlidercontainer\"> <style> #sposhrTag {position: relative; top: 35px; margin-bottom: 35px;} .WRSecondarySlidercontainer { min-height: 99px; display: flex; flex-direction: column; border-radius: 10px; } #navigation { display: flex; margin-left: 15.08px; order: 1; height: 0px; } .elipse { background: #FFF; border-radius: 50%; cursor: pointer; margin: 0px 7px 0px 7px; width: 40px; height: 40px; box-shadow: 0px 0px 10px 2px rgb(0 0 0 / 10%); position: relative; } .elipse:hover { transition: 0.1s; background: #165DBA; } .elipse:focus { transition: 0.1s; background: #165DBA; } .elipse:hover .arrow { color: #FFF; transition: 0.1s; } .elipse:focus .arrow { color: #FFF; transition: 0.1s; } .elipse:active { transform: scale(0.9); } .arrow { color: #165DBA; width: 10px; height: 10px; position: absolute; top: 14px; } .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 16px; } .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 16px; } @media screen and (max-width: 600px) { #navigation { margin-left: 17.08px; height: 30px; } .elipse{ top: 28.6px; } } </style> <div id=\"navigation\"> <a tabindex=\"0\" class=\"elipse\" id=\"navLeft\" onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=\"0\" class=\"elipse\" id=\"navRight\" onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div> <hr id=\"sposhrTag\" >";
531//var dashboardSliderDiv = ` <div class="dashboardSlidercontainer"> <style type="text/css"> .dashboardSlidercontainer .DashTempshowSlide { display: none; } .dashboardSlidercontainer { height: 242px; display: flex; justify-content: center; text-align: center; position: relative; } /* Navigation bar styles scoped to .dashboardSlidercontainer */ .dashboardSlidercontainer .dashboard-navigation { position: absolute; left: 0; right: 0; bottom: 10px; width: 100%; display: flex; justify-content: center; align-items: center; z-index: 1; gap: 20px; } .dashboardSlidercontainer .left-elipse, .dashboardSlidercontainer .right-elipse { border-radius: 50%; cursor: pointer; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; background: transparent; border: none; position: static; } .dashboardSlidercontainer .left, .dashboardSlidercontainer .right { width: 12px; height: 12px; box-shadow: -1px 1px 0 #0171AD; position: static; background: none; border: none; } .dashboardSlidercontainer .left { transform: rotate(45deg); } .dashboardSlidercontainer .right { transform: rotate(-135deg); } .dashboardSlidercontainer .nav-bullets { display: flex; gap: 8px; justify-content: center; align-items: center; } .dashboardSlidercontainer .nav-bulvar { width: 14px; height: 14px; border-radius: 50%; background: #D0CCCC; display: inline-block; cursor: pointer; transition: background 0.2s; } .dashboardSlidercontainer .nav-bullet-active { background: #0171AD; } .dashboardSlidercontainer .DashTempfade { animation-name: fade; animation-duration: 1.5s; z-index: 0; } @keyframes fade { from { opacity: .4; } to { opacity: 1; } } </style> <div class="dashboard-navigation"> <div class="left-elipse" onclick="nextSlide(-1)"> <div class="left"></div> </div> <div class="nav-bullets" id="nav-bullets"></div> <div class="right-elipse" onclick="nextSlide(1);"> <div class="right"></div> </div> </div> </div> `;
532var dashboardSliderDiv = `<div class="dashboardSlidercontainer"> <style type="text/css"> .DashTempshowSlide { display: none } .dashboardSlidercontainer { width: 100%; height: 242px; display: flex; justify-content: center; text-align: center; } .active { background-color: #717171; } .DashTempfade { -webkit-animation-name: fade; -webkit-animation-duration: 1.5s; animation-name: fade; animation-duration: 1.5s; } @-webkit-keyframes fade { from { opacity: .4 } to { opacity: 1 } } @keyframes fade { from { opacity: .4 } to { opacity: 1 } } #navigation { position: absolute; display: inline-flex; bottom: 19px; text-align: center; line-height: 0; display: flex; order: 1; height: 0px; } #nav-bullets {pointer-events: none; position: absolute; left: 0; right: 0; gap: 5px; margin: auto; bottom: 86px; display: flex; justify-content: center;} .nav-bullet { border-radius: 100%; width: 4px; height: 4px; opacity: 1; border: 1px solid #e3e0e0; } .nav-bullet-active { border-radius: 3px; width: 13px; background: #e3e0e0 0% 0% no-repeat padding-box; } .elipse { background: #FFF; border-radius: 50%; cursor: pointer; margin: 0px 7px 0px 7px; width: 40px; height: 40px; box-shadow: 0px 0px 10px 2px rgb(0 0 0 / 10%); position: relative; } .elipse:hover { transition: 0.1s; background: #0096d6; } .elipse:focus { transition: 0.1s; background: #0096d6; } .elipse:hover .arrow { color: #FFF; transition: 0.1s; } .elipse:focus .arrow { color: #FFF; transition: 0.1s; } .elipse:active { transform: scale(0.9); } .arrow { color: #0096d6; width: 10px; height: 10px; position: absolute; top: 14px; } .left { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(45deg); left: 16px; } .right { border-bottom: 2px solid; border-left: 2px solid; transform: scaleY(1.2) rotate(-135deg); right: 16px; } @media screen and (max-width: 600px) { .elipse { top: 28.6px; }} </style> <div id="navigation"> <a tabindex="0" class="elipse" id="navLeft" onclick="nextSlide(-1)"> <div class="arrow left"></div> </a> <div id="nav-bullets"> </div> <a tabindex="0" class="elipse" id="navRight" onclick="nextSlide(1)"> <div class="arrow right"></div> </a> </div> </div>`;
533
534async function standardRenderOffer(pageName, position, offerElement, targetPlaceholder, displayOnRender = true, addUrl = true) {
535    var divId = "";
536    divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
537
538    var LeadOffer = {};
539    LeadOffer.OfferID = divId;
540    //var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
541    LeadOffer.OfferClicked = "no";
542    LeadOffer.offerShown = "no";
543
544    const mapEntry = PAGE_OFFER_MAP.find(cfg => (cfg.page && cfg.page === pageName) || (cfg.pages && cfg.pages.includes(pageName)));
545    if (!mapEntry) {
546        LeadOffer.errorData = "No offer configuration found for page: " + pageName;
547        logToGlobalDataLayer(LeadOffer);
548        logInfo("No offer configuration found for page: " + pageName);
549        return Promise.resolve();
550    }
551
552    const posCfg = mapEntry.positions[position];
553    if (!posCfg) {
554        LeadOffer.errorData = "No offer configuration found for position: " + position + " on page: " + pageName;
555        logToGlobalDataLayer(LeadOffer);
556        logInfo("No offer configuration found for position: " + position + " on page: " + pageName);
557        return Promise.resolve();
558    }
559
560    LeadOffer.SPOStemplate = posCfg.templateReference || "";
561
562    const placeholder = targetPlaceholder || posCfg.placeholder;
563    const insert = posCfg.insert || "html";
564    const required = posCfg.required || [];
565    const replacements = posCfg.replacements || {};
566    const hideAction = posCfg.hide;
567
568    return waitForElement(placeholder, "", 5000).then(function () {
569        const missing = required.some(field => !isDefined(offerElement[field]));
570        if (!missing) {
571            var canInsert = (insert === "append" || insert === "prepe
571nd") || isContainerEmpty(placeholder);
572            if (canInsert) {
573                var html = offerElement.html;
574                Object.entries(replacements).forEach(([token, key]) => {
575                    var val = (key === "divId") ? divId : offerElement[key];
576                    html = html.replace(new RegExp(token, 'g'), val);
577                });
578
579                if (insert === "append") {
580                    $(placeholder).append(html);
581                } else if (insert === "prepend") {
582                    $(placeholder).prepend(html);
583                } else {
584                    $(placeholder).html(html);
585                }
586
587                if (displayOnRender) $(placeholder).removeClass("hidden").removeClass("hide").show();
588
589                allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
590                applyAccessibilityAttributes(divId, offerElement);
591                if (addUrl) addUrlAndClickEvent(divId, offerElement);
592                LeadOffer.offerShown = "yes";
593                logInfo(pageName + " offer HTML inserted", offerElement);
594                return true;
595            } else {
596                LeadOffer.errorData = pageName + " " + position + " Offer Location is not empty";
597                LeadOffer.offerShown = "no";
598            }
599            logToGlobalDataLayer(LeadOffer);
600            return false;
601        } else {
602            logInfo(pageName + " offer content not available");
603            LeadOffer.errorData = "No Content Available";
604            LeadOffer.offerShown = "no";
605            logToGlobalDataLayer(LeadOffer);
606            return false;
607        }
608    }).finally(() => {
609        if (hideAction && hideAction !== "none") {
610            try {
611                eval(hideAction);
612            } catch (e) {
613                logInfo("Hide action failed", e);
614            }
615        }
616    });
617}
618
619var offerNameForDecline = "";
620
621// ---------------- request payload builders
622// Builds the Sage/Sierra context value expected by Mastiff from supported URL parameters.
623function buildAdditionalUserData(queryParams) {
624    const allowedFields = [
625        "channel",
626        "intent",
627        "subscription",
628        "resolved",
629        "offerpromoted"
630    ];
631
632    return allowedFields
633        .filter(field => isDefined(queryParams[field]))
634        .map(field => `${field}:${queryParams[field]}`)
635        .join("|");
636}
637
638// BUILDERS: Dashboard payload builders
639function buildUserForDashboard(pgName) {
640    const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
641    return {
642        callerId: "supportweb",
643        sessionId: g.sessionId || "",
644        pageId: pgName,
645        HPID: "",
646        intent: "",
647        locale: g.Locale || "",
648        countryCode: g.CountryCode || "",
649        language: g.LanguageCode || "",
650        deviceType: "",
651        activeHealth: "",
652        isNewCustomer: "",
653        emailOffers: "",
654        gender: "",
655        smartFriend: "",
656        customerType: "",
657        documentId: ""
658    };
659}
660
661function pickDashboardDevice() {
662    const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
663    const list = g?.Dashboard?.Products || [];
664    const n = g?.Dashboard?.NoOfDevices || list.length || 0;
665    var match = null;
666    for (var i = 0; i < n; i++) {
667        const d = list[i];
668        if (!d) continue;
669        if (d.productLine == g?.Product?.productLineCode &&
670            d.productName == g?.Product?.productName &&
671            d.productNameOID == g?.Product?.productOID) {
672            match = d; break;
673        }
674    }
675
676    // try to match serial and model number if no match found yet
677    if (!isDefined(match)) {
678        waitForElement('#serial-number', '', 5000)
679        waitForElement('#model-number', '', 5000)
680        const sn = $('#serial-number').text() || $('#serial-number').val() || "";
681        const mn = $('#model-number').text() || $('#model-number').val() || "";
682        match = list.find(d => d.serialNumber == sn && d.productNumber == mn);
683    }
684    return match || {};
685}
686
687function buildProductForDashboard() {
688    const d = pickDashboardDevice();
689    var modelNumber = d.productNumber || "";
690    if (modelNumber && modelNumber.indexOf("#") > 0) {
691        modelNumber = modelNumber.substring(0, modelNumber.length - 4);
692    }
693    return {
694        modelNumber,
695        serialNumber: d.serialNumber || "",
696        partNumber: "",
697        productRegion: "",
698        productEndOfLifeCycle: "",
699        productEndOfSupportCycle: "",
700        productType: "",
701        productLine: d.productLine || "",
702        productSegment: "",
703        productCategory: "",
704        productSubCategory: "",
705        productSeries: d.productSeriesName || "",
706        productSeriesOid: d.productSeriesOID || "",
707        productSupportCategoryName: d.productName || "",
708        productName: d.productName || "",
709        productNameOid: d.productNameOID || "",
710        productReleasedate: "",
711        platform: `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}` || "",
712        includeHTML: "",
713        carePackEligible: "",
714        currentActiveCarePack: "",
715        instantInkEligible: "",
716        instantInkCapability: "",
717        inkLevel: "",
718        instantInkSubscriptionStatus: "",
719        loi: ""
720    };
721}
722
723// COMMON payload builders
724function buildUserCommon(pgName, segments, queryParams) {
725    const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
726    const user = {
727        callerId: "supportweb",
728        sessionId: g.sessionId || "",
729        pageId: pgName,
730        HPID: "",
731        intent: "",
732        locale: g.Locale || "",
733        countryCode: g.CountryCode || "",
734        language: g.LanguageCode || "",
735        deviceType: "",
736        activeHealth: "",
737        isNewCustomer: !samePage,
738        emailOffers: "",
739        gender: "",
740        smartFriend: "",
741        customerType: g?.Product?.audienceType || "",
742        documentId: (g?.Document?.documentID) || "",
743        additionalUserData: buildAdditionalUserData(queryParams)
744    };
745
746    const locSeg = segments[3] || "";
747    if (!isDefined(user.countryCode) && locSeg.length >= 2) user.countryCode = locSeg.substring(0, 2);
748    if (!isDefined(user.language) && locSeg.length >= 5) user.language = locSeg.substring(3);
749    if (!isDefined(user.locale)) user.locale = locSeg;
750
751    if (pgName === "pdp_falcon") {
752        user.intent = segments[5] || "";
753    } else if (pgName === "help-computer" || pgName === "help-printer") {
754        user.intent = (segments[6] ? segments[6].split("?")[0] : "");
755    } else if (pgName === "contact-solution") {
756        // Intent for contact-solution pages comes from segment index 6 (exclude query string)
757        user.intent = (segments[6] ? segments[6].split("?")[0] : "") + "_" + (segments[7] ? segments[7].split("?")[0] : "");
758    } else if (pgName === "help-windows") {
759        user.intent = (segments[5] ? segments[5].split("?")[0] : "");
760    }
761
762    if (!isDefined(user.documentId)) {
763        if (segments[4] == "document") user.documentId = segments[5] || "";
764        else if (segments[7] == "document") user.documentId = segments[8] || "";
765        else if (segments[9] == "document") user.documentId = segments[10] || "";
766    }
767
768    return user;
769}
770
771function buildWarrantyCommon(serialNumber) {
772    const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
773    var w = {
774        warrantyState: "",
775        warrantyStatus: "",
776        warrantyStatusDetail: "",
777        warrantyStatusCode: "",
778        warrantyCaption: "",
779        warrantyStartdate: "",
780        warrantyEnddate: "",
781        warrantyRemainingDays: "",
782        warrantyTypeCode: "",
783        warrantyProductTypeCode: "",
784        warrantyCoveragePeriod: ""
785    };
786
787    if (serialNumber === g?.EntitlementResults?.serialNumber) {
788        w = {
789            warrantyState: g?.EntitlementResults?.EntResults || "",
790            warrantyStatus: "",
791            warrantyStatusDetail: "",
792            warrantyStatusCode: "",
793            warrantyCaption: "",
794            warrantyStartdate: g?.EntitlementResults?.serviceObligationLineItemStartDate || "",
795            warrantyEnddate: g?.EntitlementResults?.serviceObligationLineItemEndDate || "",
796            warrantyRemainingDays: g?.EntitlementResults?.serviceObligationLineItemRemainingDays || "",
797            warrantyTypeCode: g?.EntitlementResults?.serviceObligationTypeCode || "",
798            warrantyProductTypeCode: g?.EntitlementResults?.serviceProductTypeCode || "",
799            warrantyCoveragePeriod: g?.EntitlementResults?.tierServiceObligationLineItemPeriodInMonths || ""
800        };
801
802        if (!isDefined(w.warrantyState)) {
803            const el = document.getElementById("warrantyStatus");
804            if (el) w.warrantyState = $("#warrantyStatus").val() || "";
805        }
806    }
807
808    return w;
809}
810
811function buildProductCommon(pgName, segments, queryParams) {
812    const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
813    const p = {
814        modelNumber: null,
815        serialNumber: null,
816        partNumber: "",
817        productRegion: "",
818        productEndOfLifeCycle: "",
819        productEndOfSupportCycle: "",
820        productType: "",
821        productLine: g?.Product?.productLineCode || "",
822        productSegment: "",
823        productCategory: "",
824        productSubCategory: "",
825        productSeries: g?.Product?.seriesName || "",
826        productSeriesOid: g?.Product?.seriesOid || "",
827        productSupportCategoryName: g?.Product?.supportCategoryName || "",
828        productName: g?.Product?.supportNameName || "",
829        productNameOid: g?.Product?.supportNameOid || "",
830        productReleasedate: g?.Product?.webReleaseDate || "",
831        platform: `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}` || "",
832        includeHTML: "",
833        carePackEligible: "",
834        currentActiveCarePack: "",
835        instantInkEligible: "",
836        instantInkCapability: "",
837        inkLevel: "",
838        instantInkSubscriptionStatus: "",
839        loi: ""
840    };
841
842    //From DOM Elements
843    const getVal = id => (document.getElementById(id) ? $("#" + id).val() : "");
844    if (!isDefined(p.modelNumber)) p.modelNumber = getVal("skuFromSession") || null;
845    if (!isDefined(p.serialNumber)) p.serialNumber = getVal("detectedSerialNo") || null;
846    if (!isDefined(p.serialNumber)) p.serialNumber = getVal("serialNumberFromSession") || null;
847    if (!isDefined(p.productSeries)) p.productSeries = getVal("seriesName") || p.productSeries;
848    if (!isDefined(p.productSeriesOid)) p.productSeriesOid = getVal("productSeriesId") || p.productSeriesOid;
849
850    // From URL
851    // productSeries
852    const setSeriesFromSeg = (idx) => {
853        if (!isDefined(p.productSeries) && isDefined(segments[idx]))
854            p.productSeries = segments[idx].replace(/-/g, " ");
855    };
856
857    if (pgName === "drivers_closure") setSeriesFromSeg(7);
858    else if (pgName === "drivers_details") setSeriesFromSeg(6);
859    else if (pgName === "drivers_closure") setSeriesFromSeg(7);
860    else if (pgName === "contact") setSeriesFromSeg(6);
861    else if (pgName === "pdp_falcon") setSeriesFromSeg(6);
862    else if (segments[4] !== "document" && segments[4] !== "help") setSeriesFromSeg(5);
863
864    // productSeriesOid
865    const setSeriesOidFromSeg = (idx) => {
866        if (!isDefined(p.productSeriesOid) && isDefined(segments[idx]))
867            p.productSeriesOid = segments[idx].replace(/-/g, " ");
868    };
869
870    if (pgName === "drivers_closure") setSeriesOidFromSeg(8);
871    else if (pgName === "contact") setSeriesOidFromSeg(7);
872    else if (pgName === "contact-solution") setSeriesOidFromSeg(1); // empty
873    else if (segments[4] !== "document" && segments[4] !== "help") setSeriesOidFromSeg(6);
874
875    // productNameOid
876    if (!isDefined(p.productNameOid)) {
877        var stringToBeParsed = "";
878
879        // if (pgName === "pdp_falcon" && isDefined(segments[6])) {
880        //     stringToBeParsed = segments.includes("model")
881        //         ? segments[segments.indexOf("model") + 1]
882        //         : (/^\d+$/.test(segments[6]) || segments[6].includes("?")) ? segments[6]
883        //             : (/^\d+$/.test(segments[7]) || segments[7]?.includes("?")) ? segments[7]
884        //                 : "";
885        // } else 
886        if (pgName === "drivers_details" && isDefined(segments[7])) {
887            stringToBeParsed = segments[7];
888        } else if (pgName === "drivers_closure") {
889            if (isDefined(segments[8])) {
890                stringToBeParsed = segments.includes("model")
891                    ? segments[segments.indexOf("model") + 1]
892                    : (/^\d+$/.test(segments[8]) || segments[8].includes("?")) ? segments[8]
893                        : (/^\d+$/.test(segments[10]) || segments[10]?.includes("?")) ? segments[10]
894                            : "";
895            }
896        } else if (pgName === "contact") {
897            stringToBeParsed = isDefined(segments[9]) ? segments[9] : "";
898        }
899
900        // fallback logic
901        if (!stringToBeParsed) {
902            if (pgName === "drivers_closure") {
903                stringToBeParsed = isDefined(segments[10]) ? segments[10] : "";
904            } else if (pgName === "contact") {
905                stringToBeParsed = isDefined(segments[9]) ? segments[9] : "";
906            } else if (pgName === "document" && segments[7] === "model") {
907                stringToBeParsed = isDefined(segments[8]) ? segments[8] : "";
908            } else if (typeof segments[8] !== "undefined") {
909                stringToBeParsed = isDefined(segments[8]) ? segments[8] : "";
910            } else {
911                stringToBeParsed = isDefined(segments[8]) ? segments[8] : "";
912            }
913        }
914
915        if (stringToBeParsed) {
916            p.productNameOid = stringToBeParsed.includes("?")
917                ? stringToBeParsed.substring(0, stringToBeParsed.indexOf("?"))
918                : stringToBeParsed.replace(/-/g, " ");
919        }
920    }
921
922
923    if (isDefined(stringToBeParsed)) {
924        p.productNameOid = stringToBeParsed.includes("?")
925            ? stringToBeParsed.substring(0, stringToBeParsed.indexOf("?"))
926            : stringToBeParsed.replace(/-/g, " ");
927    }
928    //FORCED and TO BE VERIFIED reset for help-computer page
929    if (pgName === "help-computer" && isDefined(p.productNameOid)) {
930        p.productNameOid = "";
931    }
932
933    //From Query Params
934    if (!isDefined(p.modelNumber) && isDefined(queryParams["sku"])) p.modelNumber = queryParams["sku"];
935    if (!isDefined(p.serialNumber) && isDefined(queryParams["serialnumber"])) p.serialNumber = queryParams["serialnumber"];
936
937    if (!isDefined(p.modelNumber)) {
938        p.modelNumber = g?.Product?.productNumber || "";
939        if (p.modelNumber && p.modelNumber.indexOf("#") > 0) {
940            p.modelNumber = p.modelNumber.substring(0, p.modelNumber.length - 4);
941        }
942    }
943    if (!isDefined(p.serialNumber)) {
944        p.serialNumber = g?.Product?.serialNumber || "";
945    }
946
947    p.productName = strOrEmpty(p.productName);
948    p.productNameOid = strOrEmpty(p.productNameOid);
949    p.modelNumber = strOrEmpty(p.modelNumber);
950    p.serialNumber = strOrEmpty(p.serialNumber);
951    p.productSeries = strOrEmpty(p.productSeries);
952    p.productSeriesOid = strOrEmpty(p.productSeriesOid);
953    return p;
954}
955
956// utility to ensure sessionId is set
957function ensureSessionId(reqObj, user) {
958    if (isDefined(user.sessionId)) return;
959    var mastiffSessionId = "";
960    try {
961        if (typeof localStorage === "undefined" || localStorage == null) {
962            mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10);
963        } else {
964            mastiffSessionId = localStorage.getItem("MastiffSessionId");
965            if (!isDefined(mastiffSessionId)) {
966                mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10);
967                localStorage.setItem("MastiffSessionId", mastiffSessionId);
968            }
969        }
970    } catch (e) {
971        mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10);
972    }
973    user.sessionId = mastiffSessionId;
974}
975
976// core request builder code
977function buildRequestPayload() {
978    const { segments, queryParams } = normalizeUrl();
979    const reqObj = {};
980    reqObj.requestId = createReqId();
981    reqObj.offerLocations = (PAGE_CONFIG[pgName] || PAGE_CONFIG.default).offerLocations;
982    // Force single primary location for contact-solution pages regardless of default logic
983    if (pgName === "contact-solution") {
984        reqObj.offerLocations = "primary";
985    }
986    reqObj.offerName = "";
987    reqObj.acceptanceLevel = "";
988
989    if (pgName === "dashboard") {
990        const user = buildUserForDashboard(pgName);
991        const product = buildProductForDashboard();
992        const warranty = buildWarrantyCommon(product.serialNumber);
993        product.warranty = warranty;
994        reqObj.product = product;
995        reqObj.user = user;
996        ensureSessionId(reqObj, reqObj.user);
997        return reqObj;
998    }
999
1000    const user = buildUserCommon(pgName, segments, queryParams);
1001    const product = buildProductCommon(pgName, segments, queryParams);
1002    const warranty = buildWarrantyCommon(product.serialNumber);
1003    product.warranty = warranty;
1004    reqObj.product = product;
1005    reqObj.user = user;
1006    ensureSessionId(reqObj, reqObj.user);
1007    return reqObj;
1008}
1009
1010// --------- core functions starts here ---------------
1011
1012// await this to ensure DOM is ready (DOMContentLoaded), but don't block if it's already ready
1013function domReady() {
1014    if (document.readyState === "complete") return Promise.resolve();
1015    return new Promise(resolve => {
1016        window.addEventListener("load", resolve, { once: true });
1017    });
1018}
1019
1020async function initiateMastiffCall() {
1021    if (window._mastiffCallInProgress) return;
1022    window._mastiffCallInProgress = true;
1023    try {
1024        await domReady();
1025
1026        deviceInfo = await getDeviceInfo();
1027        pgName = pageName();
1028
1029        if (pgName === "dashboard") {
1030            _quizReady = null;
1031            logInfo("[Dashboard Quiz] Reset Quiz Portal readiness for this Mastiff initiation.");
1032        }
1033        addSuppliesReporting();
1034        replaceMerchImages();
1035
1036        samePage = offerResults !== null && reqObj.user && reqObj.user.pageId === pgName;
1037        if (!samePage) {
1038            offerResults = null;
1039            reqObj = {};
1040        }
1041        LeadOfferIndex = 1;
1042        enableDashTile = false;
1043        slide_index = 1;
1044        navBulletAvailable = false;
1045        clearTimeout(myVarTimeout);
1046
1047        // pdp_falcon same-page: reprocess cached offers only, no new request
1048        if (samePage && pgName === 'pdp_falcon') {
1049            processOffers(offerResults, pgName);
1050
1051            if (accessoriesOfferResults && reqObj.user.intent === "product-specs") {
1052                await showAccListOffers(accessoriesOfferResults);
1053            } else if (!accessoriesOfferResults && reqObj.user.intent === "product-specs") {
1054                await safeExecute(() => sendPdpAccessoriesRequest(reqObj));
1055            }
1056            return;
1057        }
1058
1059        // drivers_details same-page: reprocess cached + send new request for version change
1060        if (samePage && pgName === 'drivers_details') {
1061            processOffers(offerResults, pgName);
1062        }
1063
1064
1065        await safeExecute(harvestData);
1066    } finally {
1067        window._mastiffCallInProgress = false;
1068    }
1069}
1070
1071async function beforeHarvestAjaxCall() {
1072    var quizSpinnerHtml = '<div class=sposQuizSpinner> <style>#mastiff-modal-cpc .sposQuizSpinner{display:none} .sposQuizSpinner { width: 100%; height: 250px; background: #fbfbfb; display: flex; justify-content: center; align-items: center; border-radius: 10px; margin-top: 20px; } .sposQuizSpinnerWheel { width: 50px; height: 50px; border: 8px solid #0096D6; border-top: 8px solid #fbfbfb; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> <div class=sposQuizSpinnerWheel></div></div>';
1073    var quizHtml = `<style>.quizPortalDiv { margin: 15px 0px; } .SPOSQuizDivider { height: 20px; border-bottom: 1px solid #E8E8E8; } /* Quiz container and header */ .CPConfiguratorContainer, .HUQConfiguratorContainer { font-family: "HPSimplifiedLight"; background: #fff; } .CPConfiguratorHeader { display: flex; align-items: center; margin-bottom: 13px; position: relative; height: 48px; padding-right: 68px; } .CPConfiguratorTitleDiv { display: flex; align-items: center; } .CPConfiguratorTitleIconDiv { width: 37px; height: auto; margin-right: 15px; } .CPConfiguratorTitleText { font-size: 16px; } /* close and reset buttons */ .CPConfiguratorTopButton { border-radius: 50%; width: 48px; height: 48px; display: flex; justify-content: center; align-items: center; cursor: pointer; position: absolute; right: 0px; } .CPConfiguratorCloseButton { background-color: #F3F8F3; } .HUQCloseButton { background-color: #FCF3F3 !important; } .CPConfiguratorTopButtonCloseImg { width: 12px; } .CPConfiguratorResetButton { background-color: #EFEFEF; display: none; } .CPConfiguratorTopButtonResetImg { width: 18px; margin-bottom: 2px; } /*Questions container */ .CPConfiguratorBody { border-radius: 10px; background-color: #fff; border: 11px solid #F3F8F3; padding: 11px; } .HUQBody { border: 11px solid #FCF3F3; } /*Questions */ .CPConfiguratorItem { border: 1px solid #EFEFEF; border-radius: 5px; border-left: 5px solid #d8d8d8; margin-bottom: 13px; padding-left: 15px; padding-right: 25px; padding-bottom: 12px; padding-top: 23px; } .CPConfiguratorItem-Two-column-layout { width: calc(50% - 7px); display: inline-block; vertical-align: top; } .CPConfiguratorItem-Two-column-layoutFirst { margin-right: 10px; } .CPConfiguratorQuestion { flex-wrap: wrap; margin-bottom: 22px; display: flex; align-items: center; flex-wrap: nowrap; }
1073 .CPConfiguratorQuestionIcon { border: 2.5px solid #d8d8d8; background-color: #d8d8d8; color: #E9F2E8; border-radius: 50%; height: 28px; min-width: 28px; margin-right: 10px; display: flex; align-items: center; justify-content: center; } .CPConfiguratorQuestionIconIndex { font-family: "HPSimplified"; font-size: 17px; color: #777777; } .CPConfiguratorQuestionText { font-size: 20px; line-height: 23px; color: #212121; font-family: "HPSimplified"; display: flex; align-items: center; } /* Active questions */ .CPConfiguratorItemActive { border-left: 5px solid #B7DAB5; } .CPConfiguratorQuestionIconActive { border: 2.5px solid #B7DAB5; background-color: #fff; } .CPConfiguratorQuestionIconImgActive { display: none; } /* Disabled questions */ .CPConfiguratorBodyDisabled { border: 11px solid #EFEFEF !important; } .CPConfiguratorQuestionIconDisabled { border: 2.5px solid #d8d8d8 !important; background-color: #fff !important; } .CPConfiguratorQuestionTextDisabled { color: #767676 !important; } .CPConfiguratorQuestionIconImgDisabled { display: none; } .CPConfiguratorItemActiveDisabled { border-left: 5px solid #f1f1f1 !important; } /*Answers container */ .CPConfiguratorAnswers { display: flex; flex-wrap: wrap; align-items: flex-start; align-content: flex-start; margin-left: 3px; width: 100%; } .CPConfiguratordurationRow, .CPConfiguratorlocationRow { width: calc(33% - 10px); margin-right: 10px; } .CPConfiguratortypeRow { width: 100%; margin-right: 10px; } .CPConfiguratorcoverageTypeRow { width: calc(33% - 10px); margin-right: 10px; } .CPConfiguratorfeatureRow { width: calc(50% - 20px); margin-right: 20px; } .CPConfiguratorfeaturesRow { width: 100%; margin-right: 20px; } /* Answsers */ .CPConfiguratorAnswer { display: flex; position: relative; flex-direction: row-reverse; justify-content: flex-end; align-items: flex-end; } .CPConfiguratorAnswerChild { padding-left: 15px; order: 999; width: 70%; } .CPConfiguratorAnswerSubChild { padding-left: 30px; } .CPConfiguratorAnswerfeature:hover, .CPConfiguratorAnswerfeature:focus, .CPConfiguratorAnswerfeature:focus-visible, .CPConfiguratorAnswerfeatures:hover, .CPConfiguratorAnswerfeatures:focus, .CPConfiguratorAnswerfeatures:focus-visible, .CPConfiguratorAnswerduration:hover, .CPConfiguratorAnswerduration:focus, .CPConfiguratorAnswerduration:focus-visible, .CPConfiguratorAnswerlocation:hover, .CPConfiguratorAnswerlocation:focus, .CPConfiguratorAnswerlocation:focus-visible, .CPConfiguratorAnswertype:hover, .CPConfiguratorAnswertype:focus, .CPConfiguratorAnswertype:focus-visible, .CPConfiguratorAnswercoverageType:hover, .CPConfiguratorAnswercoverageType:focus, .CPConfiguratorAnswercoverageType:focus-visible { outline: none; color: #000; .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked), .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked) { background-color: #E7E7E7 !important; box-shadow: 0 0 0 4px #E7E7E7, 0 0 0 4px #E7E7E7 !important; background-image: url(https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg); background-repeat: no-repeat; background-position: center; background-size: 90%; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked):focus, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked):focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:not(:checked):focus, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:not(:checked):focus-visible { box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F !important; } .CPConfiguratorAnswerdurationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"] { background-color: #E7E7E7; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; outline: none; } } .CPConfiguratorAnswerdurationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerdurationButton[type="radio"]:focus-visible, .CPConfiguratorAnswertypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswertypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswerlocationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerlocationButton[type="radio"]:focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeatureButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:focus-visible, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:focus-visible, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:focus-visible { background-color: #E7E7E7; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; outline: none; } .CPConfiguratorAnswerdurationButton[type="radio"]:checked, .CPConfiguratorAnswertypeButton[type="radio"]:checked, .CPConfiguratorAnswerlocationButton[type="radio"]:checked, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:checked { background-color: #165DBA !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #000000 !important; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:checked, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:checked { background-color: #165DBA !important; box-shadow: 0 0 0 4px #165DBA, 0 0 0 4px #000000 !important; background-image: url('https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg'); background-repeat: no-repeat; background-position: center; background-size: 90%; }
1073 .CPConfiguratorAnswercoverageType, .CPConfiguratorAnswerduration, .CPConfiguratorAnswerlocation, .CPConfiguratorAnswertype, .CPConfiguratorAnswerfeature, .CPConfiguratorAnswerfeatures { font-size: 16px; line-height: 22px; color: #000; display: flex; margin-bottom: 20px; cursor: pointer; align-items: flex-start; } .CPConfiguratorAnswerLabel>span:first-of-type { margin-top: -5px } .CPConfiguratorAnswerdurationButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswercoverageTypeButton[type="radio"] { border-radius: 50%; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"], .CPConfiguratorAnswercoverageTypeButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswerdurationButton[type="radio"] { appearance: none; cursor: pointer; min-width: 14px !important; height: 14px; background-color: #fff; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F; margin-right: 10px; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"] { border-radius: 2px; } .CPConfiguratorAnswercoverageType:focus-within, .CPConfiguratorAnswerduration:focus-within, .CPConfiguratorAnswerlocation:focus-within, .CPConfiguratorAnswertype:focus-within, .CPConfiguratorAnswerfeature:focus-within, .CPConfiguratorAnswerfeatures:focus-within { color: #000 !important; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"] { border-radius: 2px; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #8F8F8F !important; } /* Toggle answers */ .CPConfiguratorToggle input { display: none; } .CPConfiguratorSlider { max-width: 35px; width: 35px; margin-right: 7px; height: 20px; cursor: pointer; background-color: #ccc; border: 1px solid #8F8F8F; border-radius: 34px; top: 0; left: 0; right: 0; bottom: 0; transition: 0.2s; padding-top: 2px; padding-left: 3px; } .CPConfiguratorSliderCircle { height: 14px; width: 14px; background-color: white; transition: 0.2s; border-radius: 50%; } /* Toggle answers checked */ .CPConfiguratorToggle input:checked+.CPConfiguratorSlider { background-color: #165DBA; border: 1px solid #165DBA; } .CPConfiguratorToggle input:checked+.CPConfiguratorSlider .CPConfiguratorSliderCircle { margin-left: 14px; } /* Disabled answers */ .CPConfiguratorAnswercoverageTypeButton[type="radio"]:checked:disabled, .CPConfiguratorAnswertypeButton[type="radio"]:checked:disabled, .CPConfiguratorAnswerlocationButton[type="radio"]:checked:disabled, .CPConfiguratorAnswerdurationButton[type="radio"]:checked:disabled { cursor: default; background-color: #CCCCCC !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #CCCCCC !important; pointer-events: none; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:checked:disabled, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:checked:disabled { cursor: default; background-color: #CCCCCC !important; box-shadow: 0 0 0 4px #CCCCCC, 0 0 0 4px #CCCCCC !important; pointer-events: none; } .CPConfiguratorAnswerfeatureButton[type="checkbox"]:disabled, .CPConfiguratorAnswerfeaturesButton[type="checkbox"]:disabled, .CPConfiguratorAnswercoverageTypeButton[type="radio"]:disabled, .CPConfiguratorAnswertypeButton[type="radio"]:disabled, .CPConfiguratorAnswerlocationButton[type="radio"]:disabled, .CPConfiguratorAnswerdurationButton[type="radio"]:disabled { cursor: default; pointer-events: none; background-color: #ffffff !important; box-shadow: 0 0 0 3px #fff, 0 0 0 4px #CCCCCC !important; } .CPConfiguratorAnswerDisabled { color: #999999 !important; cursor: default; pointer-events: none; } /* Toggle disabled */ .CPConfiguratorToggle input:disabled+.CPConfiguratorSlider { transition: 0s; background-color: #F3F3F3; pointer-events: none; border: 1px solid #F3F3F3; } .CPConfiguratorToggle input:disabled+.CPConfiguratorSlider .CPConfiguratorSliderCircle { transition: 0s; background-color: #DADADA; } /* tooltips */ .CPConfiguratorAnswerTooltip { width: 15px; margin-left: 2px; }
1073 .CPConfiguratorAnswerTooltipDiv:hover~.CPConfiguratorAnswerTooltipBubble, .CPConfiguratorAnswerTooltipDiv:hover>.CPConfiguratorAnswerTooltipBubbleChip::after { display: flex !important; pointer-events: none; } .CPConfiguratorAnswerTooltipDiv:active, .CPConfiguratorAnswerTooltipDiv:focus {} .CPConfiguratorAnswerTooltipDiv { position: relative; height: 16px; display: ruby; margin-bottom: 25px; cursor: default; white-space: nowrap; pointer-events: auto; } .CPConfiguratorAnswerTooltipBubble { width: 103%; position: absolute; bottom: 44px; left: 0px; display: none; min-width: inherit; height: 500px; align-items: flex-end; min-width: 450px; } .CPConfiguratorAnswerTooltipBubbleChip::after { content: ""; position: absolute; border-width: 7px; z-index: 1001; top: -17px; left: -14px; border-style: solid; border-color: #fff transparent transparent transparent; display: none; } .CPConfiguratorAnswerTooltipBubbleChip { position: relative; right: 0px; display: inline-block; top: -2px; } .CPConfiguratorAnswerTooltipBubbleText { font-family: "HPSimplified"; font-size: 14px; line-height: 20px; text-align: left; color: #000; background: #fff; border-radius: 10px; z-index: 1000; box-shadow: 0 0 30px 10px #0000001a; padding: 15px 14px 15px 19px; } .CPConfiguratorResultSubmission { display: flex; justify-content: space-between; align-items: center; } .CPConfiguratorResultSubmissionTotal { font-size: 16px; color: #404040; margin-left: 4px; } .CPConfiguratorResultSubmissionButton { font-size: 16px; line-height: 35px; height: 45px; color: #fff; background-color: #CCCCCC; border-radius: 4px; padding: 6px 20px 6px 20px; font-family: "HPSimplified"; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; text-align: center; transition: 0.1s; pointer-events: none; } .CPConfiguratorResultSubmissionButtonActive { background-color: #165DBA; pointer-events: initial; } .CPConfiguratorResultSubmissionButtonActive:hover, .CPConfiguratorResultSubmissionButtonActive:focus, .CPConfiguratorResultSubmissionButtonActive:active, .CPConfiguratorResultSubmissionButton:focus-visible { background-color: #114284; outline: none; cursor: pointer; } /* offer */ .CPConfiguratorResultOffer { border-left: 5px solid #1C7A17; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09); border-radius: 5px; margin-top: 17px; margin-bottom: 5px; display: none; } .CPConfiguratorResultOfferImageDiv { background-color: #ffffff; width: 30%; padding: 26px; display: flex; align-items: center; justify-content: center; overflow: hidden; } .CPConfiguratorResultOfferImage {} .CPConfiguratorResultOfferText { background-color: #F3F8F3; padding: 17px 25px; width: 80%; } .CPConfiguratorResultOfferHeader { display: flex; align-items: center; justify-content: space-between; margin-bottom: 11px; } .CPConfiguratorResultOfferHeaderHeadline { display: flex; align-items: flex-start; } .CPConfiguratorResultOfferHeaderHeadlineIcon { margin-right: 7px; margin-top: 4px; } .CPConfiguratorResultOfferHeaderHeadlineText { color: #1C7A17; line-height: 26px; font-size: 20px; font-family: "HPSimplified"; } .CPConfiguratorResultOfferHeaderPrice { display: flex; font-size: 16px; } .HUQResultOfferHeaderPrice { display: flex; justify-content: center; margin: 15px 0px; } .HUQRecommendedForYouPrice { margin-bottom: 28px; } .CPConfiguratorResultOfferHeaderDiscountPrice { color: #7D7D7D; margin-right: 8px; text-decoration: line-through; } .CPConfiguratorResultOfferHeaderSalePrice { color: #7D7D7D; } .HUQConfiguratorContainer .CPConfiguratorResultOfferHeaderSalePrice { font-family: "HPSimplified"; color: #373737; } .CPConfiguratorResultOfferDescription { margin-bottom: 20px; font-size: 16px; line-height: 24px; } .CPConfiguratorResultOfferCTA { font-size: 16px; font-family: "HPSimplified"; line-height: 35px; color: #165DBA; background-color: #fff; border: 1px solid #165DBA; border-radius: 4px; padding: 6px 20px 6px 20px; width: max-content; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; cursor: pointer; text-align: center; transition: 0.1s; } .CPConfiguratorResultOfferCTA:hover, .CPConfiguratorResultOfferCTA:focus, .CPConfiguratorResultOfferCTA:focus-visible { border: 1px solid #165DBA; color: #fff; background-color: #165DBA; outline: none; } .CPConfiguratorResultOfferCTA:active { border: 1px solid #114284; color: #fff; background-color: #114284; outline: none; } /* spinner */ .CPConfiguratorSpinner { transition: 0.3s; } .skeleton { animation: skeleton-loading 0.8s linear infinite alternate; } @keyframes skeleton-loading { 0% { background-color: rgb(216, 221, 223); } 100% { background-color: rgb(240, 243, 245); } } .CPConfiguratorSpinnerBody { border-radius: 10px; background-color: #ffffff; border: 11px solid #f0f3f5; padding: 11px } .CPConfiguratorSpinnerHeader { margin-top: 20px; display: flex; align-items: center; height: 48px; position: relative; } .CPConfiguratorSpinnerHeaderIcon { min-width: 29px; height: 29px; border-radius: 50%; margin-right: 15px; }
1073 .CPConfiguratorSpinnerHeaderText { border-radius: 10px; height: 16px; width: 357px; } .CPConfiguratorSpinnerHeaderButton { width: 48px; height: 48px; position: absolute; right: 0; border-radius: 50%; } .CPConfiguratorItem-Two-column-layoutFirstSpinner { margin-right: 9px; } .CPConfiguratorSpinnerQuestion { display: flex; align-items: center; } .CPConfiguratorSpinnerQuestionIcon { min-width: 32px; height: 32px; border-radius: 50%; margin-right: 10px; } .CPConfiguratorSpinnerQuestionText { border-radius: 10px; height: 20px; width: 357px; } .CPConfiguratorSpinnerHzAnswer { align-items: center; width: 100%; } .CPConfiguratorSpinnerHzAnswerText { border-radius: 10px; height: 16px; width: 100%; margin-bottom: 26px; } .CPConfiguratorSpinnerSubmission { height: 47px; } .CPConfiguratorSpinnerSubmissionTotal { border-radius: 10px; height: 21px; width: 94px; } .CPConfiguratorResultSubmissionTotalPrice { font-family: "HPSimplified"; font-size: 18px; } .CPConfiguratorSpinnerSubmissionButton { border-radius: 5px; height: 47px; width: 108px; } .CPConfiguratorSpinnerHzAnswerTextMobile { display: none; } .CPConfiguratorResultOfferSectionHUQ { display: none; width: 100%; justify-content: space-between; margin-top: 13px; } .CPConfiguratorResultOfferSectionHUQOffer { border-top: 5px solid #BDD8BC; border-radius: 4px; width: calc(33.33% - 9px); display: flex; flex-direction: column; align-items: center; box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.09); padding-bottom: 20px; } .CPConfiguratorResultOfferSectionHUQOfferRecommended { border-top: 5px solid #8EBD8B; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(1), .CPConfiguratorResultOfferSectionHUQ> :nth-child(3) { margin-top: 13px; } .CPConfiguratorResultSubmissionButtonHUQRecommended { margin-top: 13px; } .CPConfiguratorResultOfferSectionHUQOfferHeader { background-color: #F3F8F3; width: 100%; text-align: center; padding: 14px 0px; display: flex; justify-content: center; } .CPConfiguratorResultOfferSectionHUQOfferHeaderImg { margin-right: 5px; min-width: 20px; max-height: 20px; } .CPConfiguratorResultOfferSectionHUQOfferImgDiv { margin-top: 20px; margin-bottom: 10px; display: flex; justify-content: center; align-items: center; height: 107px; } .CPConfiguratorResultOfferSectionHUQOfferImg { max-width: 125px; } .CPConfiguratorResultOfferSectionHUQOfferDescription { text-align: center; padding-left: 20px; padding-right: 20px; font-size: 14px; line-height: 20px; height: 80px; margin-bottom: 10px; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; color: #404040; } .CPConfiguratorResultSubmissionButtonHUQ { color: #165DBA; font-family: "HPSimplified"; cursor: pointer; display: flex; align-items: center; justify-content: center; } .diagsVRepairsCTAElipse { margin-right: 10px; background-color: #165dba; width: 25px; height: 25px; border-radius: 50%; position: relative; } .diagsVRepairsCTADivArrow { color: #fff; width: 5px; height: 5px; position: absolute; transform: scaleY(1.3) scaleX(0.85) rotate(-135deg); left: 9px; top: 9px; border-bottom: 2px solid; border-left: 2px solid; } .CPConfiguratorResultSubmissionButtonHUQ:hover, .CPConfiguratorResultSubmissionButtonHUQ:active, .CPConfiguratorResultSubmissionButtonHUQ:focus, .CPConfiguratorResultSubmissionButtonHUQ:focus-visible { color: #114284; outline: none; .diagsVRepairsCTAElipse { background-color: #114284; } } @media screen and (max-width: 792px) { .CPConfiguratorAnswerLabel>span:first-of-type { margin-top: -3px; } .CPConfiguratorQuestionText, .CPConfiguratorResultOfferHeaderHeadlineText { font-size: 16px !important; line-height: 20px; } .CPConfiguratorAnswerfeatureButton[type="checkbox"], .CPConfiguratorAnswerfeaturesButton[type="checkbox"], .CPConfiguratorAnswerlocationButton[type="radio"], .CPConfiguratorAnswertypeButton[type="radio"], .CPConfiguratorAnswerdurationButton[type="radio"] { min-width: 12px !important; height: 12px !important; margin-top: 4px; } .CPConfiguratorAnswercoverageType, .CPConfiguratorAnswerduration, .CPConfiguratorAnswertype, .CPConfiguratorAnswerfeature, .CPConfiguratorAnswerfeatures, .CPConfiguratorAnswerlocation, .CPConfiguratorTitleText, .CPConfiguratorResultOfferDescription, .CPConfiguratorResultSubmissionTotal { font-size: 14px !important; line-height: 20px !important; } .CPConfiguratorResultSubmissionTotal { width: 129px; display: flex; flex-direction: column; }
1073 .CPConfiguratorResultSubmissionTotalPrice { font-size: 16px; } .CPConfiguratorAnswerTooltip { margin-left: 4px; width: 12px; } .CPConfiguratorResultOfferHeaderPrice { font-size: 14px; } .CPConfiguratorResultSticky { position: sticky; bottom: 0px; background: white; padding: 10px; border-top: 1px solid #dfdfdf; margin: -11px; margin-top: 13px; box-shadow: rgba(149, 157, 165, 0.1) 0px -4px 10px; } .CPConfiguratorResultOfferHeaderHeadlineIcon { margin-top: 2px; } .CPConfiguratorResultOffer { overflow: hidden; } .CPConfiguratorResultOfferText { width: 100% !important; } .CPConfiguratorResultOfferHeader { flex-direction: column; align-items: flex-start !important; max-width: 100%; } .CPConfiguratorResultOfferHeaderHeadline { margin-bottom: 10px; } .CPConfiguratorResultOfferImageDiv { display: none !important; } .CPConfiguratorAnswerTooltipBubble { min-width: initial; width: 108%; left: -3%; } .CPConfiguratorAnswerTooltipBubbleText { max-width: 100%; } .CPConfiguratorAnswer { min-width: 100%; } .CPConfiguratorSpinnerSubmissionButton { display: none; } .CPConfiguratorSpinnerHzAnswerTextMobile { width: 51%; display: block; } .CPConfiguratorSpinnerQuestionText { border-radius: 10px; height: 20px; width: 110px; } .CPConfiguratorItem-Two-column-layout { width: initial; display: block; vertical-align: initial; } .CPConfiguratorItem-Two-column-layoutFirst, .CPConfiguratorItem-Two-column-layoutFirstSpinner { margin-right: 0px; } .CPConfiguratorQuestion { flex-wrap: wrap; margin-bottom: 22px; display: flex; align-items: center; flex-wrap: nowrap; } .CPConfiguratorResultOfferSectionHUQ { flex-direction: column; } .CPConfiguratorResultOfferSectionHUQOffer { width: initial; border-top: none; display: initial; border-left: 5px solid #BDD8BC; margin: 6.5px 0px; padding: 13px; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(1), .CPConfiguratorResultOfferSectionHUQ> :nth-child(3) { margin-top: 8px; } .CPConfiguratorResultOfferSectionHUQ> :nth-child(2) { order: -1; } .CPConfiguratorResultOfferSectionHUQOffercontentWrapper { display: flex; } .CPConfiguratorResultOfferSectionHUQOfferImgDiv { margin: 0px; margin-right: 13px; } .CPConfiguratorResultOfferSectionHUQOfferImg { width: 100px; } .CPConfiguratorResultSubmissionButtonHUQ { justify-content: flex-start; } .CPConfiguratorResultOfferSectionHUQOfferHeader { width: initial; max-width: fit-content; padding: 5px 15px; margin: auto; border-radius: 10px; margin-bottom: 10px; margin-top: 5px; } .CPConfiguratorResultOfferSectionHUQOfferDescription { text-align: left; padding: 0px; height: initial; max-height: 80px; } .CPConfiguratorSpinnerHzAnswerHUQ> :nth-child(2), .CPConfiguratorSpinnerHzAnswerHUQ> :nth-child(3) { display: none; } .HUQResultOfferHeaderPrice { justify-content: flex-start; } .HUQResultOfferHeaderPrice { margin-top: 5px; margin-bottom: 15px !important; } } @media screen and (max-width: 400px) { .CPConfiguratorAnswer { min-width: 100%; } .CPConfiguratorAnswerTooltipBubble { width: 109%; min-width: initial; } .CPConfiguratorResultOfferSectionHUQOfferImg { width: 90px; } } </style><div class="CPConfiguratorContainer quizPortalDiv"><div class="CPConfiguratorHeader"><div class="CPConfiguratorTitleDiv"><div class="CPConfiguratorTitleIconDiv"><img src="https://hp.widen.net/content/q2cfurljgw/png/CPC_CPIcon.png" class="CPConfiguratorTitleIcon" alt=""></div><div class="CPConfiguratorTitleText"></div></div><div class="CPConfiguratorCloseButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonCloseImg" src="https://hp.widen.net/content/bs9gwrpkho/png/CPC_xmark.png" alt=""></div><div class="CPConfiguratorResetButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div><div class="CPConfiguratorResetButton"></div></div><div class="CPConfiguratorBody"><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">1</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=CPConfiguratorAnswersduration></div></div><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">2</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div></div><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">3</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div></div><div class="CPConfiguratorResult CPConfiguratorResultSticky"><div class=CPConfiguratorResultSubmission><div class=CPConfiguratorResultSubmissionTotal><span class=CPConfiguratorResultSubmissionTotalText></span><span class="CPConfiguratorResultSubmissionTotalPrice incartPricePlaceholder"></span></div><div class=CPConfiguratorResultSubmissionButton tabindex=0></div></div><div class=CPConfiguratorResultOffer><div class=CPConfiguratorResultOfferImageDiv><img class=CPConfiguratorResultOfferImage src=https://hp.widen.net/content/nhkja006wg/png/CPC_CPImgimg.png alt=></div> <div class=CPConfiguratorResultOfferText><div class=CPConfiguratorResultOfferHeader><div class=CPConfiguratorResultOfferHeaderHeadline><div class=CPConfiguratorResultOfferHeaderHeadlineIcon><img src=https://hp.widen.net/content/mk7aaos2dh/png/CPC_Checkmark1.png alt=></div> <div class=CPConfiguratorResultOfferHeaderHeadlineText></div></div><div class=CPConfiguratorResultOfferHeaderPrice><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div></div><div class=CPConfiguratorResultOfferDescription></div><div class=CPConfiguratorResultOfferCTA tabindex=0></div></div></div></div></div><div class="SPOSQuizDivider"></div></div><div class="HUQConfiguratorContainer quizPortalDiv"><div class="preloadQuizImages" style="display: none"><img src=https://hp.widen.net/content/qybiqsn5op/svg/DSPOS_QUIZ_White_Checkmark.svg> <img src=https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png> <img src=https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png> </div><div class="CPConfiguratorHeader"><div class="CPConfiguratorTitleDiv"><div class="CPConfiguratorTitleIconDiv">
1073<img src="https://hp.widen.net/content/lb8570fxwi/svg/HardwareUpgradeQuizIcon.svg" class="CPConfiguratorTitleIcon" alt=""></div><div class="CPConfiguratorTitleText"></div></div><div class="CPConfiguratorCloseButton HUQCloseButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonCloseImg" src="https://hp.widen.net/content/bs9gwrpkho/png/CPC_xmark.png" alt=""></div><div class="CPConfiguratorResetButton CPConfiguratorTopButton"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div><div class="CPConfiguratorResetButton"></div></div><div class="CPConfiguratorBody HUQBody"><div class="CPConfiguratorItem"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">1</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=HUQAnswersLocation></div></div><div class="CPConfiguratorItem CPConfiguratorItem-Two-column-layout CPConfiguratorItem-Two-column-layoutFirst"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">2</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText">​</div></div><div class="CPConfiguratorAnswers" id=HUQAnswersType></div></div><div class="CPConfiguratorItem CPConfiguratorItem-Two-column-layout"><div class="CPConfiguratorQuestion"><div class="CPConfiguratorQuestionIcon"><div class="CPConfiguratorQuestionIconIndex">3</div><img class="CPConfiguratorQuestionIconImgActive" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt=""><img class="CPConfiguratorQuestionIconImgDisabled" src="https://hp.widen.net/content/9zkjffup3o/png/CPC_CheckmarkDisabled.png" alt=""></div><div class="CPConfiguratorQuestionText"></div></div><div class="CPConfiguratorAnswers" id=HUQAnswersFeatures></div></div><div class="CPConfiguratorResult CPConfiguratorResultSticky"><div class=CPConfiguratorResultSubmission><div class=CPConfiguratorResultSubmissionTotal></div><div class=CPConfiguratorResultSubmissionButton tabindex=0></div></div><div class=CPConfiguratorResultOffer><div class=CPConfiguratorResultOfferImageDiv><img class=CPConfiguratorResultOfferImage src=https://hp.widen.net/content/nhkja006wg/png/CPC_CPImgimg.png alt=></div> <div class=CPConfiguratorResultOfferText><div class=CPConfiguratorResultOfferHeader><div class=CPConfiguratorResultOfferHeaderHeadline><div class=CPConfiguratorResultOfferHeaderHeadlineIcon><img src=https://hp.widen.net/content/mk7aaos2dh/png/CPC_Checkmark1.png alt=></div> <div class=CPConfiguratorResultOfferHeaderHeadlineText></div></div><div class=CPConfiguratorResultOfferHeaderPrice><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div></div><div class=CPConfiguratorResultOfferDescription></div><div class=CPConfiguratorResultOfferCTA tabindex=0></div></div></div><div class=CPConfiguratorResultOfferSectionHUQ><div class=CPConfiguratorResultOfferSectionHUQOffer><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/fsq7hviqvc/png/HUQ_BudgetFriendly_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQBudgetFriendlyPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQBudgetFriendly" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div><div class="CPConfiguratorResultOfferSectionHUQOffer CPConfiguratorResultOfferSectionHUQOfferRecommended"><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/nvwc6kqvgd/png/HUQ_RecommendedForYou_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQRecommendedForYouPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQRecommended" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div><div class=CPConfiguratorResultOfferSectionHUQOffer><div class=CPConfiguratorResultOfferSectionHUQOfferHeader><img class=CPConfiguratorResultOfferSectionHUQOfferHeaderImg src=https://hp.widen.net/content/e6b8x6gxqo/png/HUQ_MostPopular_Icon.png><span class=CPConfiguratorResultOfferSectionHUQOfferHeaderText></span></div><div class=CPConfiguratorResultOfferSectionHUQOffercontentWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferImgDiv><img class=CPConfiguratorResultOfferSectionHUQOfferImg src=""></div><div class=textWrapper><div class=CPConfiguratorResultOfferSectionHUQOfferDescription></div><div class="HUQResultOfferHeaderPrice HUQMostPopularPrice"><div class="CPConfiguratorResultOfferHeaderDiscountPrice strikePricePlaceholder"></div><div class="CPConfiguratorResultOfferHeaderSalePrice incartPricePlaceholder"></div></div><div class="CPConfiguratorResultSubmissionButtonHUQ CPConfiguratorResultSubmissionButtonHUQMostPopular" tabindex=0><div class=diagsVRepairsCTAElipse><div class=diagsVRepairsCTADivArrow></div></div><span class=CPConfiguratorResultSubmissionButtonHUQText></span></div></div></div></div></div></div></div><div class="SPOSQuizDivider"></div></div>`
1074    var quizResetButton = '<div class="CPConfiguratorResetButton CPConfiguratorTopButton" style="display: none;    margin: 5px;"><img class="CPConfiguratorTopButtonResetImg" src="https://hp.widen.net/content/7iclbe1bz2/png/CPC_Reset.png" alt=""></div>'
1075    if (pgName == "warrantyresult_falcon") {
1076
1077        waitForElement("#mastiff-check-warranty-primary-offer").then(() => {
1078            $("#mastiff-check-warranty-primary-offer").html(quizSpinnerHtml);
1079            $("#mastiff-check-warranty-primary-offer").append(quizHtml);
1080            $(".quizPortalDiv").hide();
1081        });
1082        prepareInitialUi();
1083        handleQuizApiResponse(reqObj);
1084    } else if (pgName == "dashboard") {
1085        logInfo("[Dashboard Quiz] Starting the Quiz Portal request for the dashboard.");
1086        waitForElement("#mastiff-modal-cpc-content").then(() => {
1087            $("#mastiff-modal-cpc-content").html(quizSpinnerHtml);
1088            $("#mastiff-modal-cpc-content").append(quizHtml);
1089            $("#mastiff-modal-cpc-content .CPConfiguratorHeader").hide();
1090            $(".quizPortalDiv").hide();
1091        });
1092        prepareInitialUi();
1093        // insert reset button afetr .mastiff-modal-cpc-title
1094        waitForElement(".mastiff-modal-cpc-title").then(() => {
1095            $(".mastiff-modal-cpc-title").after(quizResetButton);
1096        });
1097        handleQuizApiResponse(reqObj);
1098    } else if (pgName == 'drivers_details') {
1099
1100        // Retrieval order for platform value:
1101        // 1. globalDataLayer.versionchange
1102        // 2. globalDataLayer.OSversionName
1103        // 3. sniffedOsData.versionName (from localStorage)
1104        // 4. os-device-name element text content with spaces replaced by underscores
1105        // 5. `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}`
1106        // 6. '' as fallback
1107
1108        const g = (typeof globalDataLayer !== "undefined") ? globalDataLayer : {};
1109        var driverDetailsSelectedOSVersion = "";
1110
1111        // Try globalDataLayer properties first
1112        if (isDefined(g.versionchange)) {
1113            driverDetailsSelectedOSVersion = g.versionchange;
1114            logInfo("Version change detected - using versionchange", driverDetailsSelectedOSVersion);
1115        } else if (isDefined(g.OSversionName)) {
1116            driverDetailsSelectedOSVersion = g.OSversionName;
1117            logInfo("Version change detected - using OSversionName", driverDetailsSelectedOSVersion);
1118        } else {
1119            // Try localStorage.sniffedOsData
1120            try {
1121                var sniffedOsData = JSON.parse(localStorage.getItem("sniffedOsData"));
1122                if (isDefined(sniffedOsData) && isDefined(sniffedOsData.versionName)) {
1123                    driverDetailsSelectedOSVersion = sniffedOsData.versionName;
1124                    logInfo("Using sniffedOsData.versionName", driverDetailsSelectedOSVersion);
1125                }
1126            } catch (e) {
1127                logInfo("Error parsing sniffedOsData from localStorage", e);
1128            }
1129
1130            // Try os-device-name element
1131            if (!isDefined(driverDetailsSelectedOSVersion)) {
1132                var osDeviceNameElement = document.querySelector(".os-device-name");
1133                if (osDeviceNameElement) {
1134                    driverDetailsSelectedOSVersion = osDeviceNameElement.textContent.trim().replace(/ /g, "_");
1135                    logInfo("Using os-device-name element", driverDetailsSelectedOSVersion);
1136                }
1137            }
1138
1139            // Try deviceInfo as final fallback
1140            if (!isDefined(driverDetailsSelectedOSVersion)) {
1141                driverDetailsSelectedOSVersion = `${deviceInfo.os}|${deviceInfo.browser}|${deviceInfo.deviceType}`;
1142                logInfo("Using deviceInfo fallback", driverDetailsSelectedOSVersion);
1143            }
1144        }
1145
1146        reqObj.product.platform = driverDetailsSelectedOSVersion || '';
1147    } else if (pgName == 'pdp_falcon') {
1148        if (reqObj.user.intent === "product-specs") {
1149            await safeExecute(() => sendPdpAccessoriesRequest(reqObj));
1150        }
1151    }
1152}
1153
1154async function sendPdpAccessoriesRequest(reqObj) {
1155    // this function will send an ajax api call same way we do for the main mastiff api call, 
1156    //but this will be for the accessories api call. 
1157    //The response will be processed in the processOffers function
1158    //same request id ands session id will be used for this api call as well.
1159    // same processoffer call on success 
1160
1161    if (accessoriesOfferResults) {
1162        await showAccListOffers(accessoriesOfferResults);
1163        return Promise.resolve();
1164    }
1165
1166    var accessoriesReqObj = JSON.parse(JSON.stringify(reqObj));
1167    accessoriesReqObj.user.pageId = "PDP_ACCESSORY";
1168    accessoriesReqObj.offerName = '';
1169    accessoriesReqObj.acceptanceLevel = '';
1170
1171    logInfo("PDP Accessories Request Object", accessoriesReqObj);
1172
1173    return new Promise((resolve, reject) => {
1174        $.ajax({
1175            url: getMastiffUrl(),
1176            method: "POST",
1177            async: true,
1178            data: encodeURIComponent(JSON.stringify(accessoriesReqObj)),
1179            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
1180            dataType: "json",
1181            timeout: 7000
1182        })
1183            .done(async function (result) {
1184                logInfo("PDP Accessories Offer API call successful", result);
1185                accessoriesOfferResults = result;
1186                try {
1187                    await showAccListOffers(accessoriesOfferResults);
1188                } catch (e) {
1189                    logInfo("processOffers failed for accessories request", e);
1190                    reject(e);
1191                    return;
1192                }
1193                resolve();
1194            })
1195            .fail(function (xhr, textStatus, errorThrown) {
1196                logInfo("PDP Accessories AJAX fail:", xhr && xhr.status, textStatus, errorThrown);
1197                resolve();
1198            });
1199    });
1200}
1201
1202function hideAllPlaceholders(checkIfEmpty = true) {
1203    if (pgName == "pdp_falcon") {
1204        //hideContainer("#mastiff_promotions_and_deals_PDP", "hide", checkIfEmpty);
1205        //hideContainer("#mastiff_view_in_store_PDP", "hide", checkIfEmpty);
1206    }
1207
1208    if (pgName == "document" && !checkIfEmpty) {
1209
1210    }
1211
1212    if (pgName === "service") {
1213        hideContainer("#sdp-mastiff-banner-container", "hide", checkIfEmpty);
1214    }
1215
1216    if (pgName === "contact") {
1217        Object.values(contactPageConfigs).forEach(cfg => {
1218            if (cfg.containerDivId) {
1219                waitForElement(`#${cfg.containerDivId}`, `.${cfg.parentClass}`)
1220                    .then(() => {
1221                        hideContainer(`#${cfg.containerDivId}`, "hide", checkIfEmpty);
1222                    })
1223                    .catch(() => { logInfo(`Element #${cfg.containerDivId} not found`); });
1224            }
1225        });
1226    }
1227
1228    if (pgName === "help-computer" || pgName === "help-printer") {
1229        hideContainer("#mastiff-diag-banner", "hidden", checkIfEmpty);
1230        hideContainer("#diag-mastiff-banner-container", "hide", checkIfEmpty);
1231        // New Shop1 placeholder for help-computer page
1232        hideContainer("#mastiff-partstore", "hidden", checkIfEmpty);
1233    }
1234
1235    if (pgName === "repair" || pgName === "hardware-diagnostics") {
1236        waitForElement("#mastiff-sticky-banner").then(() => {
1237            hideContainer("#mastiff-sticky-banner", "hide", checkIfEmpty);
1238        })
1239    }
1240
1241    if (pgName === "help-windows") {
1242        hideContainer("#mastiff-sticky-banner", "hide", checkIfEmpty);
1243    }
1244
1245    if (pgName.indexOf("home") > -1 && (isContainerEmpty(".mastiff_template_container") || !checkIfEmpty)) {
1246        window.isMastiffChecked = true;
1247        window.isMastiffRemoved = true;
1248    }
1249
1250    if (pgName === "dashboard") {
1251        hideContainer("#compatibleCartridgesTile", "hidden", checkIfEmpty);
1252        hideContainer("#dashboard_tile_instantink_print", "hide", checkIfEmpty);
1253        hideContainer("#dy-mastiff-warranty", "hidden", checkIfEmpty);
1254        hideContainer("#dashboard_tile_mastiff_template", "removeparent", checkIfEmpty);
1255    }
1256
1257    if (pgName === "warrantyresult_falcon") {
1258        if (!checkIfEmpty) removeQuizSpinner();
1259        waitForElement("#mastiff-dy-compatible-oow-section").then(() => {
1260            if (isContainerEmpty('#mastiff-check-warranty-primary-offer')) {
1261                if (!checkIfEmpty) $("#mastiff-dy-compatible-oow-section").addClass("hidden");
1262            }
1263        })
1264    }
1265}
1266
1267function harvestData() {
1268    const mastiffIntegrated = pageSupported(pgName);
1269    if (!mastiffIntegrated) return;
1270
1271    try {
1272        reqObj = buildRequestPayload();
1273    } catch (e) {
1274        logInfo("buildRequestPayload failed", e);
1275        hideAllPlaceholders(false);
1276        return;
1277    }
1278
1279    logInfo("Request Object", reqObj);
1280
1281    if (globalDataLayer.SPOSOffers == null) {
1282        globalDataLayer.SPOSOffers = {
1283            errorCode: "",
1284            requestId: reqObj.requestId,
1285            sessionId: reqObj.user.sessionId
1286        };
1287    } else {
1288        globalDataLayer.SPOSOffers.requestId = reqObj.requestId;
1289        globalDataLayer.SPOSOffers.sessionId = reqObj.user.sessionId;
1290    }
1291
1292    beforeHarvestAjaxCall();
1293
1294    // Wrapped in a promise (resolved via .always) so callers can await the full
1295    // request lifecycle instead of just the synchronous ajax kickoff.
1296    return new Promise((resolve) => {
1297        $.ajax({
1298            url: getMastiffUrl(),
1299            method: "POST",
1300            async: true,
1301            data: encodeURIComponent(JSON.stringify(reqObj)),
1302            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
1303            dataType: "json",
1304            timeout: 7000
1305        })
1306            .done(function (result) {
1307                logInfo("SPOS Offer API call successful", result);
1308                offerResults = result;
1309                try {
1310                    processOffers(offerResults, pgName);
1311                } catch (e) {
1312                    logInfo("processOffers failed", e);
1313                    hideAllPlaceholders(false);
1314                } finally {
1315                    // remove placeholders on success only if containers are empty
1316                    //hideAllPlaceholders(true);
1317                }
1318            })
1319            .fail(function (xhr, textStatus, errorThrown) {
1320                logInfo("AJAX fail:", xhr && xhr.status, textStatus, errorThrown);
1321                if (isDefined(globalDataLayer.SPOSOffers)) {
1322                    if (xhr && xhr.responseJSON) {
1323                        logInfo(xhr.responseJSON.errorCode + "-" + xhr.responseJSON.errorMessage);
1324                        globalDataLayer.SPOSOffers.errorCode = xhr.responseJSON.errorCode;
1325                    } else if (textStatus === "timeout") {
1326                        globalDataLayer.SPOSOffers.errorCode = "timeout";
1327                    } else if (xhr && xhr.status === 0) {
1328                        globalDataLayer.SPOSOffers.errorCode = "500";
1329                    } else {
1330                        globalDataLayer.SPOSOffers.errorCode = xhr ? xhr.status : "unknown";
1331                    }
1332                }
1333
1334                // remove placeholders on error path 
1335                hideAllPlaceholders(false);
1336            })
1337            .always(resolve);
1338    });
1339}
1340
1341async function processOffers(offerResults, pgName) {
1342    if (!offerResults || offerResults.offerCount <= 0) {
1343        if (isDefined(globalDataLayer.SPOSOffers)) {
1344            globalDataLayer.SPOSOffers.errorCode = "No Offers Available for this Profile/Device";
1345        }
1346        hideAllPlaceholders(false);
1347        return;
1348    }
1349
1350    const offers = offerResults.offers && Array.isArray(offerResults.offers.offer)
1351        ? offerResults.offers.offer
1352        : [];
1353
1354    // Start network checks in parallel without blocking offer rendering.
1355    prepareOfferImages(offers);
1356
1357    var enablePromoTab = false;
1358    var showWtyOffers = false;
1359    var quizInitiatorElement = null;
1360    var quizDiscardElement = null;
1361    var owDiagContainerOfferElement = null;
1362    // Track whether contact-solution offer already rendered (only 1 allowed)
1363    var contactSolutionRendered = false;
1364
1365    const isShop = (pos) => pos === "shop1" || pos === "shop2" || pos === "shop3";
1366    const lc = (s) => (typeof s === "string" ? s.toLowerCase() : "");
1367    const isWarrantyOwXOffer = (offer) => lc(offer?.category).startsWith("owx");
1368    const owxOffers = pgName === "warrantyresult_falcon"
1369        ? (offerResults.offers.offer || []).filter(isWarrantyOwXOffer)
1370        : [];
1371
1372    //pre process logic for specific pages 
1373    // it should be here as might process offers without going through harvestData
1374    if (pgName === "pdp_falcon") {
1375        const { segments: seg } = normalizeUrl();
1376        intentBasedLocationEmpty = true;
1377        if (isDefined(seg[5])) {
1378            reqObj.user.intent = segments[5];
1379        }
1380    }
1381
1382
1383    // main processing logic
1384    for (var i = 0; i < offerResults.offerCount; i++) {
1385        const element = offers[i];
1386        const pos = element.templatePosition;
1387
1388        switch (pgName) {
1389            case "home":
1390            case "home_printer":
1391            case "home_computer":
1392                if (pos === "primary") {
1393                    showCarouselBanner(element);
1394                }
1395                break;
1396
1397            case "drivers_details":
1398                if (lc(element.category).startsWith("details")) {
1399                    showSwdViewInStoreOffer(element);
1400                } else if (pos === "shop1") {
1401                    showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner-swd", "mastiff-sticky-banner-swd");
1402                } else {
1403                    showDriverDetailsOffer(element);
1404                }
1405                break;
1406
1407            case "drivers_closure":
1408                if (pos === "primary") showDriverClosurePrimaryOffer(element);
1409                break;
1410            //check later
1411            case "service":
1412                showStickyBannerSecondaryOffer(element, "sdp-mastiff
1412-banner-container", "mastiff_SDP_sticky_banner");
1413                break;
1414
1415            case "repair":
1416            case "hardware-diagnostics":
1417                if (lc(pos) === "primary") {
1418                    showHelpPageOffer(element);
1419                }
1420
1421                if (lc(pos) === "1r4ccontainer") {
1422                    const rendered = await standardRenderOffer(
1423                        pgName,
1424                        lc(pos),
1425                        element,
1426                        null,
1427                        false,
1428                        false
1429                    );
1430
1431                    if (rendered) {
1432                        if (isDefined(element.offerTitle)) {
1433                            $("#mastiff-offer-tab .msSubTitle, #mastiff-offer-tabMobile .msSubTitle")
1434                                .text(element.offerTitle);
1435                        }
1436
1437                        addUrlAndClickEvent("mastiff-offer-tab", element, false);
1438                        addUrlAndClickEvent("mastiff-offer-tabMobile", element, false);
1439                    }
1440                }
1441
1442                if (lc(pos) === "secondary")
1443                    showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner", "mastiff-sticky-banner");
1444                break;
1445
1446            case "help-computer":
1447                if (pos === "shop1") {
1448                    // New Shop1 rendering uses the generic standardRenderOffer logic & PAGE_OFFER_MAP config
1449                    standardRenderOffer(pgName, "shop1", element);
1450                }
1451            case "help-printer":
1452                if (pos === "primary") {
1453                    showHelpPrimaryOffer(element);
1454                } else if (pos === "secondary") {
1455                    //check later
1456                    showStickyBannerSecondaryOffer(element, "diag-mastiff-banner-container", "mastiff_diag_sticky_banner");
1457                }
1458                break;
1459
1460            case "help-windows":
1461                if (pos === "secondary") {
1462                    showStickyBannerSecondaryOffer(element, "mastiff-sticky-banner", "mastiff-sticky-banner");
1463                }
1464            case "document":
1465                if (pos === "primary") showDocumentOffer(element);
1466                if (pos === "secondary")
1467                    showStickyBannerSecondaryOffer(element, "document-mastiff-banner-container", "mastiff-smartfriend");
1468                break;
1469
1470            case "contact":
1471                waitForElementToDisappear(".select-country-modal", handleContactPageOffers, element);
1472                break;
1473
1474            case "contact-solution":
1475                // Render only the first valid primary offer
1476                if (!contactSolutionRendered && pos === "primary") {
1477                    contactSolutionRendered = renderContactSolutionOffer(element);
1478                }
1479                break;
1480
1481            case "contact_closure":
1482                if (pos === "primary") showCarouselBanner(element);
1483                if (pos === "secondary") showContactSummaryOffer(element);
1484                break;
1485
1486            case "contact-landing":
1487                if (lc(pos) === "1r3ccontainer") {
1488                    const rendered = await standardRenderOffer(
1489                        pgName,
1490                        lc(pos),
1491                        element,
1492                        null,
1493                        false,
1494                        false
1495                    );
1496
1497                    if (rendered) {
1498                        if (isDefined(element.offerTitle)) $("#mastiff-quicklink-title").text(element.offerTitle);
1499                        addUrlAndClickEvent("mastiff-quicklink-tile", element, false);
1500                    }
1501                }
1502                break;
1503
1504            case "warrantyresult_falcon":
1505                if (isWarrantyOwXOffer(element)) {
1506                    continue;
1507                }
1508                if (lc(element.name).includes("quizinitiator")) { quizInitiatorElement = element; continue; }
1509                if (lc(element.name).includes("quizdiscard")) { quizDiscardElement = element; continue; }
1510
1511                //render container offers based on offer category
1512                if (lc(element.category).startsWith("container ow experiment")) {
1513                    insertWarrantyOWContainerOffer(element);
1514                    continue;
1515                }
1516
1517                if (lc(element.category).startsWith("container regular")) {
1518                    insertWarrantyRegularContainerOffer(element);
1519                    continue;
1520                }
1521
1522                if (lc(element.category).startsWith("ow experiment")) {
1523                    element.OWTileOffer = true;
1524                }
1525
1526
1527                waitForQuizReady().then(() => {
1528                    if (quizReadyState.value === true || quizReadyState.value === false) {
1529                        if (pos === "primary" && (!element.OWTileOffer)) showWtyPrimaryOffer(element);
1530                        if (isShop(pos) && (!element.OWTileOffer)) showWtyOffers = true;
1531                    }
1532                });
1533
1534                if (pos === "secondary" && (!element.OWTileOffer)) showWtySecondaryOffer(element);
1535
1536                break;
1537
1538            case "pdp_falcon": {
1539                // Skip accList offers - handled in post-processing via showAccListOffers
1540                if (safeLower(element.name).includes("swcomp") || safeLower(element.name).includes("acclist") || safeLower(element.name).includes("accessorieslist")) break;
1541                const cat = lc(element.category);
1542                if (!isDefined(element.category)) {
1543                    enablePromoTab = true;
1544                } else {
1545                    if (cat.startsWith("details")) {
1546                        showViewInStoreOffer(element);
1547                    } else if (cat.startsWith("warranty widget")) {
1548                        standardRenderOffer(pgName, pos, element);
1549                    } else if (intentPDPCategories.some(category => cat.startsWith(category))) {
1550                        if (cat.includes(reqObj.user.intent)) {
1551                            handlePDPintentOffer(element);
1552                        }
1553                    } else {
1554                        element.category = null;
1555                        enablePromoTab = true;
1556                    }
1557                }
1558                break;
1559            }
1560
1561            case "printer-setup":
1562                printerSetupOffers();
1563                i = offerResults.offerCount;
1564                break;
1565
1566            case "dashboard":
1567                if (element.templatePosition == "primary" && element.category.toLowerCase().startsWith("dashboard t
1567ile")) {
1568                    element.ibOffer = true;
1569                    showSingleDashboardTileOffer(element);
1570                } else if (isDefined(element.category) && element.category.toLowerCase().startsWith("warranty dashboard")) {
1571                    element.ibOffer = true;
1572                } else if (isDefined(element.category) && element.category.toLowerCase().startsWith("cartridges tile")) {
1573                    element.ibOffer = true;
1574                    showCartidgesDashboardOffer(element);
1575                }
1576                break;
1577
1578            default:
1579                break;
1580        }
1581    }
1582
1583    //post process logic for specific pages
1584
1585    if (pgName === "dashboard") {
1586        await showDashboardTile();
1587
1588        waitForQuizReady().then(() => {
1589            var warrantyOffer = offerResults.offers.offer.find(o =>
1590                isDefined(o.category)
1591                && safeLower(o.category).startsWith("warranty dashboard")
1592                && safeLower(o.name) !== "cp_quizinitiator"
1593            );
1594            var quizInit = offerResults.offers.offer.find(element => safeLower(element.name) === "cp_quizinitiator");
1595
1596            logInfo("[Dashboard Quiz] render decision", {
1597                quizPortalReady: quizReadyState.value,
1598                quizInitiatorAvailable: Boolean(quizInit),
1599                quizInitiatorName: quizInit?.name || "none",
1600                warrantyFallbackAvailable: Boolean(warrantyOffer),
1601                warrantyFallbackName: warrantyOffer?.name || "none"
1602            });
1603
1604            if (quizReadyState.value === true) {
1605                if (quizInit) {
1606                    logInfo("[Dashboard Quiz] Quiz Portal is valid; rendering the quiz initiator.", quizInit.name);
1607                    $("#dy-mastiff-warranty").html("");
1608                    showWarrantyDashboardOffer(quizInit, false)
1609                        .then(divId => {
1610                            if (divId) bindDashboardQuizInitiator(quizInit);
1611                        });
1612                } else if (warrantyOffer) {
1613                    logInfo("[Dashboard Quiz] Quiz Portal is valid, but no initiator was returned; rendering the regular warranty fallback.", warrantyOffer.name);
1614                    $("#dy-mastiff-warranty").html("");
1615                    showWarrantyDashboardOffer(warrantyOffer, true);
1616                } else {
1617                    logInfo("[Dashboard Quiz] Quiz Portal is valid, but neither a quiz initiator nor a regular warranty fallback was returned; leaving the placement unchanged.");
1618                }
1619            } else if (quizReadyState.value === false) {
1620                if (warrantyOffer) {
1621                    logInfo("[Dashboard Quiz] Quiz Portal failed, was invali
1621d, or timed out; rendering the regular warranty fallback.", warrantyOffer.name);
1622                    $("#dy-mastiff-warranty").html("");
1623                    showWarrantyDashboardOffer(warrantyOffer, true);
1624                } else {
1625                    logInfo("[Dashboard Quiz] Quiz Portal failed, was invalid, or timed out, and no regular warranty fallback was returned; leaving the placement unchanged.");
1626                }
1627            } else {
1628                logInfo("[Dashboard Quiz] Quiz Portal readiness is unresolved; no warranty placement will be rendered yet.");
1629            }
1630        });
1631    }
1632
1633    if (pgName === "help-computer" || pgName === "help-printer") {
1634
1635        var owDiagContainerOffers = offerResults.offers.offer.filter(
1636            offer =>
1637                isDefined(offer.category)
1638                && lc(offer.category).startsWith("ow diagnostics - container")
1639        );
1640
1641        var owDiagoffers = offerResults.offers.offer.filter(function (o) {
1642            return (safeLower(o.templatePosition).startsWith("owdiags"))
1643                && !safeLower(o.templatePosition).includes("container");
1644        });
1645
1646        // Sort by numeric suffix after "_"; unnumbered go to the end
1647        var getPos = function (tp) {
1648            var match = (tp || "").match(/_(\d+)/);
1649            return match ? parseInt(match[1], 10) : Infinity;
1650        };
1651
1652        owDiagoffers.sort(function (a, b) {
1653            return getPos(a.templatePosition) - getPos(b.templatePosition);
1654        });
1655
1656        if (owDiagContainerOffers.length) {
1657            $(".warranty-container").html("");
1658
1659            standardRenderOffer(pgName, "owDiagsContainer", owDiagContainerOffers[0]).then(function () {
1660                for (var i = 0; i < owDiagoffers.length; i++) {
1661                    standardRenderOffer(pgName, "owDiags", owDiagoffers[i]);
1662                }
1663            });
1664        }
1665
1666    }
1667
1668    if (pgName === "pdp_falcon") {
1669        if (enablePromoTab && !samePage) showPromoTabOffer();
1670    }
1671
1672    if (pgName === "warrantyresult_falcon") {
1673
1674        if (owxOffers.length) {
1675            renderWarrantyNestedOwExperiment(owxOffers).then(function (renderResult) {
1676                if (renderResult.oneFullPathrendered) {
1677                    //remove hidden .from .mastiff-dy-oow-section
1678                    $("#mastiff-dy-oow-section").removeClass("hidden");
1679                }
1680            });
1681        }
1682
1683        //renderWarrantyOwTileOffers();
1684
1685        waitForQuizReady().then(() => {
1686            if (quizReadyState.value === true && quizInitiatorElement) {
1687                $(".WRPrimaryTile").hide();
1688                showWtyQuizInitiatorOffer(quizInitiatorElement).then(() => {
1689                    if (quizDiscardElement) appendQuizDiscardInsideInitiator(quizDiscardElement);
1690                });
1691            } else if (quizReadyState.value === false) {
1692                $(".WRPrimaryTile").show();
1693            }
1694            if (showWtyOffers) showWtyShopOffers();
1695            $(".quizPortalDiv").hide();
1696            $("#mastiff-check-warranty-secondary-offers").show();
1697            removeQuizSpinner();
1698        });
1699    }
1700
1701    if (pgName === "contact-landing") {
1702
1703        var offerTiles = offerResults.offers.offer.filter(element =>
1704            safeLower(element.templatePosition).startsWith("1r3ctile"));
1705
1706        offerTiles.sort(positionSortByUnderscoreOrder);
1707
1708        for (const element of offerTiles) {
1709            await standardRenderOffer(pgName, "1r3cTile", element);
1710        }
1711
1712        if ($("#contactEntryOffersContainer").children().length > 0) {
1713            $("#mastiff-quicklink-tile").removeClass("hidden");
1714        }
1715    }
1716
1717    if (pgName === "repair" || pgName === "hardware-diagnostics") {
1718
1719        var offerTiles = offerResults.offers.offer.filter(element =>
1720            safeLower(element.templatePosition).startsWith("1r4ctile"));
1721
1722        offerTiles.sort(positionSortByUnderscoreOrder);
1723
1724        for (const element of offerTiles) {
1725            await standardRenderOffer(pgName, "1r4cTile", element);
1726        }
1727
1728        if ($("#DiagsRepairsDSPOSOffersContainer").children().length > 0) {
1729            $("#mastiff-offer-tab").parent().removeClass("hidden");
1730        }
1731
1732    }
1733
1734    hideAllPlaceholders(true);
1735    SaveReqObjToSessionStorage();
1736}
1737
1738function resetRPMMastiffCall() {
1739    logInfo("Retired Product Modal Closed - Resetting reqObj ");
1740    var reqObjFSS = GetReqObjFromSessionStorage();
1741    if (reqObjFSS) {
1742        reqObj = reqObjFSS;
1743        pgName = reqObj.user.pageId;
1744    }
1745    if (pgName == 'dashboard') {
1746        sliderClassName = "DashTempshowSlide";
1747        navBulletAvailable = true;
1748        slide_index = 0;
1749    }
1750    if (!isDefined(offerResults)) {
1751        offerResults = JSON.parse(sessionStorage.getItem("offerResults")) || {};
1752    }
1753}
1754
1755function initiateRPMMastiffCall() {
1756    navBulletAvailable = false;
1757
1758    const rpmSposTitle = {
1759        "es": "Actualizaciones recomendadas",
1760        "pt": "Atualizações recomendadas",
1761        "fr": "Mises à niveau recommandées",
1762        "nl": "Aanbevolen upgrades",
1763        "bg": "Препоръчителни надстройки",
1764        "cs": "Doporučené upgrady",
1765        "hr": "Preporučene nadogradnje",
1766        "da": "Anbefalede opgraderinger",
1767        "de": "Empfohlene Upgrades",
1768        "et": "Soovitatud uuendused",
1769        "el": "Προτεινόμενες αναβαθμίσεις",
1770        "he": "שדרוגים מומלצים",
1771        "it": "Aggiornamenti consigliati",
1772        "kk": "Ұсынылатын жаңартулар",
1773        "lv": "Ieteicamie jauninājumi",
1774        "lt": "Rekomenduojami atnaujinimai",
1775        "hu": "Ajánlott frissítések",
1776        "ar": "الترقيات الموصى بها",
1777        "no": "Anbefalte oppgraderinger",
1778        "pl": "Zalecane ulepszenia",
1779        "ro": "Actualizări recomandate",
1780        "sr": "Препоручене надоградње",
1781        "sk": "Odporúčané aktualizácie",
1782        "sl": "Priporočene nadgradnje",
1783        "fi": "Suositellut päivitykset",
1784        "sv": "Rekommenderade uppgraderingar",
1785        "tr": "Önerilen Yükseltmeler",
1786        "uk": "Рекомендовані оновлення",
1787        "zh": "推荐升级",
1788        "id": "Peningkatan yang Disarankan",
1789        "ja": "推奨アップグレード",
1790        "ko": "추천 업그레이드",
1791        "ms": "Naik Taraf yang Disyorkan",
1792        "fil": "Inirerekomendang Mga Pag-upgrade",
1793        "th": "การอัปเกรดที่แนะนำ",
1794        "vi": "Nâng cấp được đề xuất"
1795    };
1796
1797    logInfo("Initiating Mastiff call for the Retired Product Modal...");
1798    reqObj = {};
1799
1800    if (!reqObj.user) {
1801        reqObj.user = {};
1802    }
1803    if (!reqObj.product) {
1804        reqObj.product = {};
1805    }
1806    if (!reqObj.product.warranty) {
1807        reqObj.product.warranty = {};
1808    }
1809    pgName = "retiredproductmodal";
1810
1811    reqObj.requestId = createReqId();
1812    reqObj.user.callerId = "supportweb";
1813    reqObj.user.pageId = pgName;
1814    reqObj.offerLocations = "primary,carousel";
1815
1816    if (typeof globalDataLayer !== "undefined") {
1817        reqObj.user.sessionId = globalDataLayer.sessionId;
1818
1819        if (reqObj.user.sessionId == null || reqObj.user.sessionId == "") {
1820            if (localStorage == null || typeof (localStorage) == "undefined") {
1821                var mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10);
1822            } else {
1823                var mastiffSessionId = localStorage.getItem('MastiffSessionId');
1824                if (mastiffSessionId == null || mastiffSessionId == "" || typeof (mastiffSessionId) == "undefined") {
1825                    mastiffSessionId = reqObj.requestId.substring(reqObj.requestId.length - 10);
1826                    localStorage.setItem('MastiffSessionId', mastiffSessionId);
1827                }
1828            }
1829            reqObj.user.sessionId = mastiffSessionId;
1830        }
1831        reqObj.user.locale = globalDataLayer.Locale;
1832        reqObj.user.countryCode = globalDataLayer.CountryCode;
1833        reqObj.user.language = globalDataLayer.LanguageCode;
1834        reqObj.product.modelNumber = globalDataLayer.Product?.productNumber || "";
1835        reqObj.product.serialNumber = globalDataLayer?.Product?.serialNumber || "";
1836        reqObj.product.productLine = globalDataLayer.Product?.productLineCode || "";
1837        reqObj.product.productSeries = globalDataLayer.Product?.seriesName || "";
1838        reqObj.product.productName = globalDataLayer.Product?.supportNameName || "";
1839        reqObj.product.productNameOid = globalDataLayer.Product?.supportNameO
1839id || "";
1840        reqObj.product.productSeriesOid = globalDataLayer.Product?.seriesOid || "";
1841        reqObj.product.platform = globalDataLayer.Product?.platformId || "";
1842        reqObj.product.productSupportCategoryName = globalDataLayer.Product?.supportCategoryName || "";
1843        reqObj.product.bigSeriesOid = globalDataLayer.Product?.bigSeriesOid || "";
1844    }
1845
1846    if (!globalDataLayer.SPOSOffers) {
1847        globalDataLayer.SPOSOffers = {
1848            errorCode: "",
1849            requestId: reqObj.requestId,
1850            sessionId: reqObj.user.sessionId
1851        };
1852    } else {
1853        globalDataLayer.SPOSOffers.requestId = reqObj.requestId;
1854        globalDataLayer.SPOSOffers.sessionId = reqObj.user.sessionId;
1855    }
1856
1857    function removeRetiredModalSpinner() {
1858        const spinner = document.querySelector("#retired-product-modal-spinner");
1859        if (spinner) {
1860            spinner.remove();
1861        }
1862
1863        const retiredProductModal = document.getElementById("mastiff_retired_product_spos");
1864        if (retiredProductModal) {
1865            retiredProductModal.innerHTML = "";
1866        }
1867    }
1868
1869    function renderRPMTitle() {
1870        var rpmTitleHtml = '<span style="font-family: HPSimplifiedRegular;font-size: 24px;font-weight: 400;line-height: 2.08;color: #333;text-align: center;box-sizing: border-box;">Recommended Upgrades</span>'
1871
1872        if (rpmSposTitle[reqObj.user.language] !== undefined) {
1873            rpmTitleHtml = rpmTitleHtml.replace(/Recommended Upgrades/, rpmSposTitle[reqObj.user.language])
1874        }
1875
1876        const container = document.getElementById("mastiff_retired_product_spos");
1877        container.insertAdjacentHTML("afterbegin", rpmTitleHtml);
1878    }
1879
1880    function hideRPMPlacement() {
1881        const container = document.getElementById("mastiff_retired_product_spos");
1882        if (container) {
1883            container.style.display = "none";
1884        }
1885    }
1886
1887    function renderPrimaryOffer(offerElement) {
1888        if (
1889            !offerElement.storeURL || offerElement.storeURL === "null" ||
1890            !offerElement.primaryButtonText || offerElement.primaryButtonText === "null" ||
1891            !offerElement.html || offerElement.html === "null"
1892        ) {
1893            hideRPMPlacement();
1894            return false;
1895        }
1896
1897        var offerId = "";
1898        offerId = `${offerElement.templatePosition}_${offerElement.name}`;
1899        var htmlTemplate = offerElement.html || "";
1900        htmlTemplate = htmlTemplate.replace("{cta}", offerElement.primaryButtonText);
1901        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", offerId);
1902
1903        const container = document.getElementById("mastiff_retired_product_spos");
1904        if (!container) {
1905            logInfo("No container found for primary retired product modal offer.");
1906            return false;
1907        }
1908
1909        container.insertAdjacentHTML("beforeend", htmlTemplate);
1910
1911        container.setAttribute("aria-label", offerElement.offerType);
1912        container.setAttribute("tabindex", "0");
1913
1914        if (reqObj.user.language === "ar" || reqObj.user.language === "he") {
1915            container.css("text-align", "right");
1916        }
1917
1918        addUrlAndClickEvent(`#${offerId}`, offerElement, /* openLinkInNewTab: */ true);
1919
1920        var sposGDLoffers = globalDataLayer.SPOSOffers;
1921        Object.keys(sposGDLoffers).forEach(function (key) {
1922            if (sposGDLoffers[key].OfferID === offerId) {
1923                sposGDLoffers[key].offerShown = "yes";
1924                sposGDLoffers[key].errorData = "";
1925                delete sposGDLoffers[key].errorData;
1926            }
1927        }
1928        );
1929
1930        return true;
1931    }
1932
1933
1934    function renderCarouselOffers(carouselOffers) {
1935        var slide_index = 1;
1936        sliderClassName = "rpmCarouselSlide";
1937        if (!carouselOffers || !carouselOffers.length) return;
1938
1939        const container = document.getElementById("mastiff_retired_product_spos");
1940        if (!container) {
1941            logInfo("No container found for retired product modal carousel offers.");
1942            hideRPMPlacement();
1943            return;
1944        }
1945
1946        var validOffers = carouselOffers.filter(o =>
1947            o.html && o.html !== "null" &&
1948            o.imageURL && o.imageURL !== "null" &&
1949            o.storeURL && o.storeURL !== "null" &&
1950            o.primaryButtonText && o.primaryButtonText !== "null"
1951        );
1952
1953        if (!validOffers.length) {
1954            logInfo("No valid carousel offers for retired product modal.");
1955            hideRPMPlacement();
1956            return;
1957        }
1958
1959        var carouselHtml = "<div class=\"RPMCarousel\"> <style> .RPMCarousel { border-radius: 16px; background: #FFFFFF; display: flex; flex-direction: column; } .RPMCarousel #navigation { margin-top: 20.75px; display: flex; align-items: center; height: 56px; border-radius: 16px; } .RPMCarousel .elipse { border: 1px solid #000; cursor: pointer; width: 38px; height: 38px; position: relative; } .disabledElipse:focus { box-shadow: none; width: 36px; height: 36px; border: 2px #0278AB; } .RPMCarousel .elipse:hover { background: #EBF9FF; } .RPMCarousel .elipse:active { background: #CAF3FF; } .RPMCarousel .arrow { color: #000; width: 9.5px; height: 9.5px; position: absolute; border-bottom: 1px solid; } .RPMCarousel .left { border-left: 1px solid; transform: scaleY(1.2) rotate(45deg); left: 17px; top: 13px; } #SPOS_navLeft{ margin-right: 20px; } .RPMCarousel .right { border-left: 1px solid; transform: scaleY(1.2) rotate(-135deg); right: 17px; top: 14px; } @media screen and (max-width: 600px) { .RPMCarousel #navigation { margin-top: 28px; } } </style> <div id=navigation> <a tabindex=0 class=elipse id=SPOS_navLeft onclick=\"nextSlide(-1)\"> <div class=\"arrow left\"></div> </a> <a tabindex=0 class=elipse id=SPOS_navRight onclick=\"nextSlide(1)\"> <div class=\"arrow right\"></div> </a> </div> </div>";
1960
1961        container.insertAdjacentHTML("beforeend", carouselHtml);
1962
1963        if (validOffers.length == 1) {
1964            const navigation = container.querySelector("#navigation");
1965            if (navigation) {
1966                navigation.style.display = "none";
1967            }
1968        }
1969
1970        const slidesWrapper = container.querySelector(".RPMCarousel");
1971
1972        validOffers.forEach((offer, index) => {
1973            var offerId = `${offer.templatePosition}_${offer.name}`;
1974            var slideHtml = offer.html || "";
1975
1976            slideHtml = slideHtml.replace("{cta}", offer.primaryButtonText);
1977            slideHtml = slideHtml.replace("{rpmOfferTitle}", offer.primaryText1 || "");
1978            slideHtml = slideHtml.replace("{rpmOfferDesc}", offer.primaryText2 || "");
1979            slideHtml = slideHtml.replace("{rpmOfferImageUrl}", offer.imageURL || "");
1980
1981            const slideMarkup = `
1982                <div class="rpmCarouselSlide" style="display:none" id="${offerId}">
1983                    ${slideHtml}
1984                </div>
1985            `;
1986
1987            slidesWrapper.insertAdjacentHTML("afterbegin", slideMarkup);
1988
1989            allocateRecEngPrices(offer.strikePrice, offer.incartPrice, offerId, offer.currency);
1990            if (offer.name.toLowerCase().indexOf("rec_") > -1) {
1991                $("#" + offerId + " #SmallBannerImgDiv").addClass("SmallBannerImgDivREC");
1992            }
1993
1994            const slideDiv = document.getElementById(offerId);
1995            slideDiv.setAttribute("aria-label", offer.offerType);
1996            slideDiv.setAttribute("tabindex", "0");
1997
1998            if (reqObj.user.language === "ar" || reqObj.user.language === "he") {
1999                slideDiv.css("text-align", "right");
2000            }
2001
2002            const ctaSel = `#${offerId} .SmallBannerCTADiv`;
2003            addUrlAndClickEvent(ctaSel, offer, true);
2004
2005            var sposGDLoffers = globalDataLayer.SPOSOffers;
2006            Object.keys(sposGDLoffers).forEach(function (key) {
2007                if (sposGDLoffers[key].OfferID === offerId) {
2008                    sposGDLoffers[key].offerShown = "yes";
2009                    sposGDLoffers[key].errorData = "";
2010                    delete sposGDLoffers[key].errorData;
2011                }
2012            }
2013            );
2014        });
2015
2016        displaySlides(slide_index);
2017    }
2018
2019
2020    $.ajax({
2021        url: getMastiffUrl(),
2022        method: "POST",
2023        async: true,
2024        data: encodeURIComponent(JSON.stringify(reqObj)),
2025        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
2026        success: function (result) {
2027            logInfo("Retired Product Modal - Mastiff response:");
2028            logInfo(result);
2029
2030            removeRetiredModalSpinner();
2031
2032            if (!result || !result.offerCount || !result.offers?.offer?.length) {
2033                logInfo("No offers returned for retired product modal.");
2034                globalDataLayer.SPOSOffers.errorCode = "No Offers for Retired Product";
2035                return;
2036            }
2037
2038            const allOffers = result.offers.offer;
2039            var primaryOffers = allOffers.filter(o => o.templatePosition === "primary");
2040            var carouselOffers = allOffers.filter(o => o.templatePosition === "carousel");
2041
2042            allOffers.forEach(offer => {
2043                var offerId = `${offer.templatePosition}_${offer.name}`;
2044                var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
2045                var LeadOffer = {};
2046                LeadOffer.OfferID = offerId;
2047                LeadOffer.OfferClicked = "no";
2048                LeadOffer.offerShown = "no";
2049                if (offer.templatePosition === "primary") {
2050                    LeadOffer.SPOStemplate = "2";
2051                } else if (offer.templatePosition === "carousel") {
2052                    LeadOffer.SPOStemplate = "24";
2053                }
2054
2055                logToGlobalDataLayer(LeadOffer);
2056            });
2057
2058            renderRPMTitle();
2059
2060            var displayedPrimary = false;
2061            for (var i = 0; i < primaryOffers.length; i++) {
2062                const isValid = renderPrimaryOffer(primaryOffers[i]);
2063                if (isValid) {
2064                    displayedPrimary = true;
2065                    break;
2066                }
2067            }
2068
2069            renderCarouselOffers(carouselOffers);
2070
2071            if ((typeof (globalDataLayer.SPOSOffers) !== "undefined") && (globalDataLayer.SPOSOffers !== null)) {
2072                if (!displayedPrimary && !carouselOffers.length) {
2073                    globalDataLayer.SPOSOffers.errorCode = "No valid primary or carousel offers";
2074                    hideRPMPlacement();
2075                }
2076            }
2077
2078        },
2079        error: function (XMLHttpRequest, textStatus, errorThrown) {
2080            logInfo("Retired Product Modal - Mastiff call error");
2081            logInfo(XMLHttpRequest.status);
2082            logInfo(textStatus);
2083            logInfo(errorThrown);
2084
2085            removeRetiredModalSpinner();
2086            hideRPMPlacement();
2087
2088            if (globalDataLayer.SPOSOffers) {
2089                if (XMLHttpRequest.responseJSON) {
2090                    globalDataLayer.SPOSOffers.errorCode = XMLHttpRequest.responseJSON.errorCode || "MastiffError";
2091                } else if (textStatus === "timeout") {
2092                    globalDataLayer.SPOSOffers.errorCode = "timeout";
2093                } else if (XMLHttpRequest.status === 0) {
2094                    globalDataLayer.SPOSOffers.errorCode = "500";
2095                } else {
2096                    globalDataLayer.SPOSOffers.errorCode = String(XMLHttpRequest.status);
2097                }
2098            }
2099        },
2100        timeout: 20000
2101    });
2102}
2103
2104// ---------- core functions ends here ----------------
2105
2106// ---------- helpers code starts here ----------------
2107
2108function getPlacementSelectors(page, position) {
2109    const cfg = PAGE_CONFIG[page] || PAGE_CONFIG.default || {};
2110    const pos = cfg.positions && cfg.positions[position];
2111    if (!pos) return {};
2112    const out = {};
2113    if (pos.placeholderSelector) {
2114        out.placeholder = pos.placeholderSelector;
2115    }
2116    if (pos.containerSelector) {
2117        out.container = pos.containerSelector;
2118    }
2119    return out;
2120}
2121
2122function hidePlacement(page, position) {
2123    const selObj = getPlacementSelectors(page, position);
2124    if (selObj.placeholder) {
2125        hideContainer(selObj.placeholder, "default", false);
2126    }
2127    if (selObj.container) {
2128        hideContainer(selObj.container, "default", false);
2129    }
2130}
2131
2132function safeExecute(fn) {
2133    try {
2134        const result = fn();
2135        if (result && typeof result.catch === "function") {
2136            return result.catch((err) => {
2137                logInfo(err);
2138            });
2139        }
2140        return result;
2141    } catch (err) {
2142        logInfo(err);
2143    }
2144}
2145
2146function normalizeUrl() {
2147    const href = String(window.location || "");
2148    const base = href.split("#")[0].split("?")[0];
2149    const segments = base.split("/");
2150    const query = href.includes("?") ? href.split("?")[1].split("#")[0] : "";
2151    const queryParams = {};
2152    if (query) {
2153        query.split("&").forEach(kv => {
2154            const [k, v] = kv.split("=");
2155            if (k) queryParams[k.toLowerCase()] = decodeURIComponent(v || "");
2156        });
2157    }
2158    window.segments = segments;
2159    return { href, base, segments, queryParams };
2160}
2161
2162function strOrEmpty(v) { return (v == null || v === "null") ? "" : String(v); }
2163function safeLower(v) { return (typeof v === "string") ? v.toLowerCase() : ""; }
2164
2165// For Level > 1, prefer order from templatePosition suffix "_n".
2166// Example: "level2tile_3" => 3, and values without "_n" render first.
2167function parsePositionUnderscoreOrder(templatePosition) {
2168    const pos = String(templatePosition || "");
2169    const match = pos.match(/_(\d+)(?!.*_\d+)/);
2170    return match ? Number(match[1]) : null;
2171};
2172
2173function positionSortByUnderscoreOrder(a, b) {
2174    const aOrder = parsePositionUnderscoreOrder(a.templatePosition);
2175    const bOrder = parsePositionUnderscoreOrder(b.templatePosition);
2176
2177    if (aOrder === null && bOrder === null) return positionSort(a, b);
2178    if (aOrder === null) return -1;
2179    if (bOrder === null) return 1;
2180    if (aOrder !== bOrder) return aOrder - bOrder;
2181    return positionSort(a, b);
2182};
2183
2184function positionSort(a, b) {
2185    const aNum = parseNumber(a.templatePosition);
2186    const bNum = parseNumber(b.templatePosition);
2187    if (aNum === null && bNum === null) return 0;
2188    if (aNum === null) return -1;
2189    if (bNum === null) return 1;
2190    return aNum - bNum;
2191};
2192
2193function parseNumber(value, fallback = null) {
2194    const match = value && String(value).match(/(\d+)/);
2195    return match ? Number(match[1]) : fallback;
2196};
2197
2198function isDefined(variableName) {
2199    return variableName !== undefined && variableName !== null && variableName !== '' && variableName !== 'null';
2200}
2201
2202var MASTIFF_IMAGE_FILLER_URL = "https://hp.widen.net/content/1dw15f0pxv/svg/Mastiff_Filler_Image.svg";
2203var MASTIFF_MERCH_IMAGE_FILLER_URL = "https://hp.widen.net/content/bataicjkf0/svg/-PDP-SuppliesList-FillerImg.svg";
2204//var MASTIFF_INK_PAPER_IMAGE_FILLER_URL = MASTIFF_IMAGE_FILLER_URL;
2205var MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS = 1000;
2206var MASTIFF_IMAGE_VALIDATION_CACHE = Object.create(null);
2207
2208function prepareOfferImages(offers) {
2209    offers.forEach(function (offer) {
2210        if (!offer) return;
2211
2212        var failureLogState = Object.create(null);
2213        prepareOfferImageValue(offer, "imageURL", offer.imageURL, failureLogState);
2214    });
2215}
2216
2217function prepareOfferImageValue(offer, fieldName, originalImageUrl, failureLogState) {
2218    var validation = validateOfferImageUrl(originalImageUrl, function (result) {
2219        applyOfferImageValidationResult(offer, fieldName, originalImageUrl, result, failureLogState);
2220    });
2221
2222    if (validation.status !== "pending") {
2223        applyOfferImageValidationResult(offer, fieldName, originalImageUrl, validation, failureLogState);
2224    } else if (fieldName !== "html" && typeof originalImageUrl === "string") {
2225        // Keep the original URL for immediate rendering. The async error callback
2226        // replaces rendered instances if the browser later rejects the image.
2227        offer[fieldName] = originalImageUrl.trim();
2228    }
2229}
2230
2231function applyOfferImageValidationResult(offer, fieldName, originalImageUrl, result, failureLogState) {
2232    if (result.status === "valid") {
2233        if (fieldName !== "html") offer[fieldName] = result.url;
2234        return;
2235    }
2236
2237    if (fieldName !== "html") offer[fieldName] = MASTIFF_IMAGE_FILLER_URL;
2238    offer.html = replaceOfferImageUrlInHtml(offer.html, originalImageUrl);
2239
2240    // This is needed for asynchronous failures because the offer may already be rendered.
2241    replaceRenderedImagesWithFiller(originalImageUrl, MASTIFF_IMAGE_FILLER_URL);
2242    logOfferImageFailure(offer, originalImageUrl, result.reason, failureLogState);
2243}
2244
2245function logOfferImageFailure(offer, imageReference, reason, failureLogState) {
2246    var logKey = String(imageReference || "missing") + "|" + reason;
2247    if (failureLogState[logKey]) return;
2248    failureLogState[logKey] = true;
2249
2250    logInfo(
2251        `[Image Validation] Failed image for offer "${offer.name || "unknown"}" ` +
2252        `(${offer.templatePosition || "unknown"}): ${reason}. ` +
2253        "Replaced the image reference with the filler image."
2254    );
2255
2256    if (typeof globalDataLayer !== "undefined" && globalDataLayer.SPOSOffers) {
2257        globalDataLayer.SPOSOffers.imageValidationFailures =
2258            (Number(globalDataLayer.SPOSOffers.imageValidationFailures) || 0) + 1;
2259    }
2260}
2261
2262function inspectOfferImageUrl(imageUrl) {
2263    if (!isDefined(imageUrl) || typeof imageUrl !== "string" || imageUrl.trim() === "") {
2264        return { reason: "image URL is missing or null" };
2265    }
2266
2267    var normalizedUrl = imageUrl.trim();
2268    if (normalizedUrl.toLowerCase() === "null") {
2269        return { reason: "image URL is missing or null" };
2270    }
2271
2272    var parsedUrl;
2273    try {
2274        parsedUrl = new URL(normalizedUrl);
2275    } catch (error) {
2276        return { reason: "image URL is malformed" };
2277    }
2278
2279    if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
2280        return { reason: "image URL uses an unsupported protocol" };
2281    }
2282
2283    return { normalizedUrl: normalizedUrl };
2284}
2285
2286function validateOfferImageUrl(imageUrl, onComplete) {
2287    var inspectedUrl = inspectOfferImageUrl(imageUrl);
2288    if (inspectedUrl.reason) {
2289        return { status: "failed", reason: inspectedUrl.reason, url: MASTIFF_IMAGE_FILLER_URL };
2290    }
2291
2292    var cacheKey = inspectedUrl.normalizedUrl;
2293    var cachedResult = MASTIFF_IMAGE_VALIDATION_CACHE[cacheKey];
2294    if (cachedResult) {
2295        if (cachedResult.status === "pending") cachedResult.callbacks.push(onComplete);
2296        return cachedResult;
2297    }
2298
2299    var pendingResult = { status: "pending", url: inspectedUrl.normalizedUrl, callbacks: [onComplete] };
2300    MASTIFF_IMAGE_VALIDATION_CACHE[cacheKey] = pendingResult;
2301
2302    var testImage;
2303    var settled = false;
2304    // Keep the check non-blocking. This is only a warning threshold; a slow
2305    // valid image must still be allowed to finish and reach onload/onerror.
2306    var timeoutId = window.setTimeout(function () {
2307        if (!settled) {
2308            logInfo("[Image Validation] Image check still pending after " + MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS + "ms");
2309        }
2310    }, MASTIFF_IMAGE_VALIDATION_TIMEOUT_MS);
2311
2312    function finish(result) {
2313        if (settled) return;
2314        settled = true;
2315        window.clearTimeout(timeoutId);
2316        if (testImage) {
2317            testImage.onload = null;
2318            testImage.onerror = null;
2319        }
2320
2321        var callbacks = pendingResult.callbacks.slice();
2322        pendingResult.status = result.status;
2323        pendingResult.reason = result.reason;
2324        pendingResult.url = result.url;
2325        delete pendingResult.callbacks;
2326        callbacks.forEach(function (callback) {
2327            if (typeof callback === "function") callback(result);
2328        });
2329    }
2330
2331    try {
2332        testImage = new Image();
2333        testImage.onload = function () {
2334            finish({ status: "valid", url: inspectedUrl.normalizedUrl });
2335        };
2336        testImage.onerror = function () {
2337            finish({
2338                status: "failed",
2339                reason: "image failed to load or is not a valid image",
2340                url: MASTIFF_IMAGE_FILLER_URL
2341            });
2342        };
2343        testImage.src = inspectedUrl.normalizedUrl;
2344    } catch (error) {
2345        finish({
2346            status: "failed",
2347            reason: "browser could not start image validation",
2348            url: MASTIFF_IMAGE_FILLER_URL
2349        });
2350    }
2351
2352    return pendingResult;
2353}
2354
2355function replaceOfferImageUrlInHtml(html, imageUrl) {
2356    if (typeof html !== "string") return html;
2357
2358    var brokenImageUrl = typeof imageUrl === "string" ? imageUrl.trim() : "";
2359    var replaceNullOrEmpty = !brokenImageUrl || brokenImageUrl.toLowerCase() === "null";
2360
2361    function replaceAttributeValue(value) {
2362        if (replaceNullOrEmpty && (value.trim() === "" || value.trim().toLowerCase() === "null")) {
2363            return MASTIFF_IMAGE_FILLER_URL;
2364        }
2365        if (brokenImageUrl && value.indexOf(brokenImageUrl) !== -1) {
2366            return value.split(brokenImageUrl).join(MASTIFF_IMAGE_FILLER_URL);
2367        }
2368        return value;
2369    }
2370
2371    html = replaceHtmlAttributeValue(html, "src", replaceAttributeValue);
2372    html = replaceHtmlAttributeValue(html, "srcset", replaceAttributeValue);
2373    html = replaceHtmlAttributeValue(html, "style", function (value) {
2374        if (!brokenImageUrl) return value;
2375        return value.split(brokenImageUrl).join(MASTIFF_IMAGE_FILLER_URL);
2376    });
2377
2378    if (brokenImageUrl) {
2379        var escapedImageUrl = brokenImageUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2380        html = html.replace(new RegExp("url\\(\\s*([\\\"']?)" + escapedImageUrl + "\\1\\s*\\)", "gi"), "url(" + MASTIFF_IMAGE_FILLER_URL + ")");
2381    }
2382
2383    return html;
2384}
2385
2386function replaceHtmlAttributeValue(html, attributeName, replaceValue) {
2387    var attributePattern = new RegExp("(\\b" + attributeName + "\\s*=\\s*)(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))", "gi");
2388    return html.replace(attributePattern, function (match, prefix, doubleQuotedValue, singleQuotedValue, unquotedValue) {
2389        var originalValue = doubleQuotedValue !== undefined
2390            ? doubleQuotedValue
2391            : (singleQuotedValue !== undefined ? singleQuotedValue : unquotedValue);
2392        var replacedValue = replaceValue(originalValue);
2393        if (replacedValue === originalValue) return match;
2394
2395        var quote = doubleQuotedValue !== undefined ? '"' : (singleQuotedValue !== undefined ? "'" : "");
2396        return prefix + quote + replacedValue + quote;
2397    });
2398}
2399
2400function replaceRenderedImagesWithFiller(imageUrl, fillerImageUrl, rootElement) {
2401    if (typeof document === "undefined" || !isDefined(imageUrl) || typeof imageUrl !== "string" ||
2402        typeof fillerImageUrl !== "string") return;
2403
2404    var normalizedUrl = imageUrl.trim();
2405    var normalizedFillerUrl = fillerImageUrl.trim();
2406    if (!normalizedUrl || normalizedUrl.toLowerCase() === "null" ||
2407        !normalizedFillerUrl || normalizedFillerUrl.toLowerCase() === "null") return;
2408
2409    var searchRoot = rootElement || document;
2410
2411    searchRoot.querySelectorAll("img, source").forEach(function (imageElement) {
2412        var attributeUrl = imageElement.getAttribute("src");
2413        if (attributeUrl === normalizedUrl || imageElement.src === normalizedUrl) {
2414            imageElement.setAttribute("src", normalizedFillerUrl);
2415        }
2416
2417        var srcset = imageElement.getAttribute("srcset");
2418        if (srcset && srcset.indexOf(normalizedUrl) !== -1) {
2419            imageElement.setAttribute("srcset", srcset.split(normalizedUrl).join(normalizedFillerUrl));
2420        }
2421    });
2422
2423    searchRoot.querySelectorAll("[style]").forEach(function (element) {
2424        var styleValue = element.getAttribute("style");
2425        if (styleValue && styleValue.indexOf(normalizedUrl) !== -1) {
2426            element.setAttribute("style", styleValue.split(normalizedUrl).join(normalizedFillerUrl));
2427        }
2428    });
2429
2430    searchRoot.querySelectorAll("style").forEach(function (styleElement) {
2431        if (styleElement.textContent && styleElement.textContent.indexOf(normalizedUrl) !== -1) {
2432            styleElement.textContent = styleElement.textContent.split(normalizedUrl).join(normalizedFillerUrl);
2433        }
2434    });
2435}
2436
2437// Returns true when a storeURL contains a phone number instead of a navigable URL.
2438// Phone numbers: start with 'tel:', or consist only of digits/spaces/dashes/parens/dots/plus
2439// and contain at least 7 digits. Standard URLs (http/https/www) always return false.
2440function isPhoneNumber(value) {
2441    if (!isDefined(value)) return false;
2442    if (/^tel:/i.test(value)) return true;
2443    if (/^https?:\/\//i.test(value) || /^www\./i.test(value)) return false;
2444    const stripped = value.trim();
2445    const digits = stripped.replace(/\D/g, '');
2446    if (digits.length < 7) return false;
2447    return /^[\+]?[\d][\d\s\-\.\(\)x]+$/.test(stripped);
2448}
2449
2450function offerClickEvent(acceptOfferReqObj, target, openLinkInNewTab = true) {
2451    // target can be an Element, an id, or any selector
2452    var el = target instanceof Element ? target : null;
2453    if (!el && typeof target === "string") {
2454        el = document.getElementById(target) || document.querySelector(target);
2455    }
2456    if (!el) {
2457        logInfo("offerClickEvent: element not found", target);
2458        return;
2459    }
2460
2461    // Derive URL; fall back to closest ancestor with data-store-url
2462    const url =
2463        el.getAttribute("data-store-url") ||
2464        el.closest("[data-store-url]")?.getAttribute("data-store-url");
2465
2466    if (!isDefined(url) && openLinkInNewTab) {
2467        logInfo("offerClickEvent: no URL found on element", target);
2468        //return;
2469    }
2470
2471    // Derive offer name; fall back to container id parsing
2472    const containerWithId = el.closest("[id]");
2473    const elementIdClicked = containerWithId ? containerWithId.id : (el.id || "");
2474    const offerName =
2475        el.getAttribute("data-offer-name") ||
2476        el.closest("[data-offer-name]")?.getAttribute("data-offer-name") ||
2477        (elementIdClicked ? elementIdClicked.replace(/^(?:Store_|SWD-)?SPOS_/, "").split("_").slice(1).join("_") : "");
2478
2479    if (!isDefined(offerName)) {
2480        logInfo("offerClickEvent: no offer name found on element", target);
2481        return;
2482    }
2483    logInfo("offerClickEvent: element clicked", elementIdClicked);
2484
2485    acceptOfferReqObj.offerName = offerName;
2486    acceptOfferReqObj.acceptanceLevel = "Accepted";
2487
2488    if (isDefined(globalDataLayer.SPOSOffers)) {
2489        for (property in globalDataLayer.SPOSOffers) {
2490            if (elementIdClicked === globalDataLayer.SPOSOffers[property].OfferID) {
2491                globalDataLayer.SPOSOffers[property].OfferClicked = "yes";
2492                break;
2493            }
2494        }
2495    }
2496
2497    $.ajax({
2498        url: getMastiffUrl(),
2499        method: "POST",
2500        async: true,
2501        data: encodeURIComponent(JSON.stringify(acceptOfferReqObj)),
2502        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
2503        success: function () {
2504            logInfo("Offer accepted Api call sent  " + offerName + " URL: " + url);
2505        },
2506        error: function (XMLHttpRequest, textStatus, errorThrown) {
2507            logInfo("ERROR in Offer accepted Api call for " + offerName);
2508            logInfo(XMLHttpRequest);
2509            logInfo(textStatus);
2510            logInfo(errorThrown);
2511        }
2512    });
2513
2514    if (url) {
2515        if (openLinkInNewTab) {
2516            window.open(url, "_blank", "noopener");
2517        }
2518    } else {
2519        logInfo("offerClickEvent: no URL found on element", elementIdClicked);
2520    }
2521}
2522
2523function replaceMerchImages() {
2524    if (pgName !== "pdp_falcon") return;
2525
2526    const { segments: seg } = normalizeUrl();
2527    if (!isDefined(seg[5]) || seg[5].toLowerCase() !== "ink-paper") return;
2528
2529    const merchImagePattern = /^https:\/\/www\.hp\.com\/[^?#]*\/shop\/Html\/Merch\/Images\/[^?#]+\.[^?#]+(?:[?#].*)?$/i;
2530
2531    waitForElement("#pdp .ink-paper", "#pdp").then(function (inkPaperRoot) {
2532        const checkedMerchUrls = new Set();
2533        const merchImages = inkPaperRoot.querySelectorAll("img");
2534
2535        merchImages.forEach(function (img) {
2536            const imageUrl = img.src;
2537            if (!merchImagePattern.test(imageUrl) || checkedMerchUrls.has(imageUrl)) return;
2538
2539            checkedMerchUrls.add(imageUrl);
2540            logInfo("[HP merch] image URL matched; replacing with filler:", imageUrl);
2541            replaceRenderedImagesWithFiller(imageUrl, MASTIFF_MERCH_IMAGE_FILLER_URL, inkPaperRoot);
2542        });
2543
2544        if (checkedMerchUrls.size) {
2545            logInfo(checkedMerchUrls.size, "[HP merch] images replaced with filler:", MASTIFF_MERCH_IMAGE_FILLER_URL);
2546        }
2547    }).catch(function (error) {
2548        logInfo("[HP merch] image replacement skipped: .ink-paper not found", error);
2549    });
2550}
2551
2552function addSuppliesReporting() {
2553    $('.ink-paper, .accessories-container')
2554        .off('click.mastiff', 'a')       // remove previous namespaced handlers
2555        .on('click.mastiff', 'a', function (e) {
2556            const $a = $(this);
2557
2558            // ensure link has expected Offer_id param
2559            const href = $a.attr('href') || '';
2560            const match = href.match(/Offer_id=MAS-([^_]+)_([^&]+)/);
2561            if (!match) return; // not a tracked shop link
2562
2563            // we matched - intercept navigation
2564            e.preventDefault();
2565
2566            const reqId = match[1];
2567            const offerName = match[2];
2568
2569            // build payload copy (safe-guard reqObj existence)
2570            const reqObjCopy = JSON.parse(JSON.stringify(window.reqObj || {}));
2571            reqObjCopy.offerName = offerName;
2572            reqObjCopy.acceptanceLevel = 'Accepted';
2573            reqObjCopy.requestId = reqId;
2574            reqObjCopy.user = reqObjCopy.user || {};
2575            reqObjCopy.user.callerId = 'SW_COMPATIBILITY';
2576            // choose pageId by id prefix
2577            const isSupplies = !!($a.attr('id') && $a.attr('id').startsWith('PDPsupplies_'));
2578            const isAccessory = !!($a.attr('id') && $a.attr('id').startsWith('View'));
2579
2580            reqObjCopy.user.pageId = isSupplies ? 'PDP_SUPPLIES' : isAccessory ? 'PDP_ACCESSORY' : 'PDP_FALCON';
2581
2582            // send to mastiff
2583            $.ajax({
2584                url: getMastiffUrl(),
2585                method: 'POST',
2586                async: true,
2587                data: encodeURIComponent(JSON.stringify(reqObjCopy)),
2588                contentType: 'application/x-www-form-urlencoded; charset=UTF-8'
2589            }).done(function () {
2590                logInfo('Offer accepted Api call sent: ' + offerName + ' URL: ' + getMastiffUrl());
2591            }).fail(function (jqXHR, textStatus, errorThrown) {
2592                logInfo('ERROR in Offer accepted Api call for ' + offerName);
2593                logInfo(jqXHR);
2594                logInfo(textStatus);
2595                logInfo(errorThrown);
2596            });
2597
2598            logInfo('Clicked shop link: ' + href + ', offer: ' + offerName + ', reqId: ' + reqId);
2599
2600            // open in new tab
2601            window.open(href, '_blank', 'noopener');
2602        });
2603}
2604
2605function createReqId() {
2606
2607    var timestamp = Date.now();
2608    var tsLength = String(timestamp).length;
2609    var randStrLen = 20 - parseInt(tsLength);
2610    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
2611    var charactersLength = characters.length;
2612    var result = "";
2613
2614    for (var i = 0; i < randStrLen; i++) {
2615        result += characters.charAt(Math.floor(Math.random() * charactersLength));
2616    }
2617
2618    return String(timestamp).concat(result);
2619}
2620
2621function getDeviceType() {
2622    var ua = navigator.userAgent;
2623    if (/(tablet|ipad|playbook|silk)|(android(?!.*mobi))/i.test(ua)) {
2624        return "tablet";
2625    }
2626    if (
2627        /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk-Accelerated|(hpw|web)OS|Opera M(obi|ini)/.test(
2628            ua
2629        )
2630    ) {
2631        return "mobile";
2632    }
2633    return "desktop";
2634}
2635
2636function pageName() {
2637    const { segments: segs } = normalizeUrl();
2638
2639    const s = (i) => (typeof segs[i] === "string" ? segs[i] : "");
2640    const has = (str, sub) => str && str.indexOf(sub) > -1;
2641    const starts = (str, sub) => str && str.startsWith(sub);
2642
2643    const p4 = s(4);
2644
2645    // no section -> home
2646    if (!p4) return "home";
2647
2648    // home variants
2649    if (p4 === "printer" || p4 === "computer") {
2650        // home_printer / home_computer
2651        return "home_" + p4;
2652    }
2653
2654    // drivers
2655    if (p4 === "drivers") {
2656        const p5 = s(5);
2657        const p6 = s(6);
2658        // check index 5 for "closure"
2659        if (has(p5, "closure")) {
2660            return "drivers_closure";
2661        } else {
2662            return "drivers_details";
2663        }
2664    }
2665
2666    // top-level document
2667    if (p4 === "document") {
2668        return "document";
2669    }
2670
2671    // help
2672    if (p4 === "help") {
2673        const p5 = s(5);
2674        //return help-repair
2675        if (has(p5, "repair")) return "repair";
2676        //same
2677        if (has(p5, "hp-pc-hardware-diagnostics")) return "hardware-diagnostics";
2678        // help-windows (e.g. /help/windows-10-support-center)
2679        if (has(p5, "windows")) return "help-windows";
2680        // e.g., help-computer, help-printer
2681        return "help-" + p5;
2682    }
2683
2684    // product (PDP or document under product)
2685    if (p4 === "product") {
2686        const p7 = s(7), p9 = s(9);
2687        if (p7 === "document" || p9 === "document") {
2688            return "document";
2689        }
2690        return "pdp_falcon";
2691    }
2692
2693    // contact (+ closure)
2694    if (p4 === "contact") {
2695        const p5 = s(5);
2696        if (p5 === "closure" || starts(p5, "closure")) {
2697            // contact_closure or contact_closure-*
2698            return "contact_" + p5;
2699        }
2700        if (p5 === "solution") {
2701            return "contact-solution";
2702        }
2703        if (!isDefined(p5)) {
2704            return "contact-landing";
2705        }
2706        return "contact";
2707    }
2708
2709    // printer-setup
2710    if (p4 === "printer-setup") {
2711        return "printer-setup";
2712    }
2713
2714    // warrantyresult
2715    if (p4 === "warrantyresult") {
2716        return "warrantyresult_falcon";
2717    }
2718
2719    // service
2720    if (p4 === "service") {
2721        return "service";
2722    }
2723
2724    // dashboard
2725    if (p4 === "dashboard") {
2726        return "dashboard";
2727    }
2728
2729    // default
2730    return p4;
2731}
2732
2733function pageSupported(name) {
2734    var supportedPageList = [
2735        "pdp_falcon",
2736        "drivers_closure",
2737        "drivers_details",
2738        "contact",
2739        "contact-solution",
2740        "warrantyresult_falcon",
2741        "service",
2742        "help-printer",
2743        "help-computer",
2744        "repair",
2745        "hardware-diagnostics",
2746        "home",
2747        "home_printer",
2748        "home_computer",
2749        "dashboard",
2750        "document",
2751        "contact_closure",
2752        "printer-setup",
2753        "help-windows",
2754        "contact-landing",
2755    ];
2756    return supportedPageList.indexOf(name) >= 0;
2757}
2758
2759function AcceptOffer(acceptOfferReqObj) {
2760
2761    $.ajax({
2762        url: getMastiffUrl(),
2763        method: "POST",
2764        async: true,
2765        data: encodeURIComponent(JSON.stringify(acceptOfferReqObj)),
2766        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
2767        success: function (result) {
2768
2769            logInfo("Response object - Offer accepted.");
2770        },
2771        error: function (XMLHttpRequest, textStatus, errorThrown) {
2772
2773            logInfo("ERROR");
2774
2775            logInfo(XMLHttpRequest);
2776            logInfo(textStatus);
2777            logInfo(errorThrown);
2778        }
2779    });
2780
2781}
2782
2783function offerDeclineEvent(declineOfferReqObj, offerName) {
2784
2785    declineOfferReqObj.offerName = offerName;
2786    declineOfferReqObj.acceptanceLevel = "Declined";
2787
2788    $.ajax({
2789        url: getMastiffUrl(),
2790        method: "POST",
2791        async: true,
2792        data: encodeURIComponent(JSON.stringify(declineOfferReqObj)),
2793        contentType: "application/x-www-form-urlencoded; charset=UTF-8",
2794        success: function (result) {
2795
2796            logInfo("Response object - Offer Declined.");
2797        },
2798        error: function (XMLHttpRequest, textStatus, errorThrown) {
2799
2800            logInfo("ERROR");
2801
2802            logInfo(XMLHttpRequest);
2803            logInfo(textStatus);
2804            logInfo(errorThrown);
2805        }
2806    });
2807}
2808
2809// Handles the click-to-reveal interaction for phone number offers (e.g. Asurion / HP Care Complete).
2810// On first click: updates the CTA text to show the phone number and fires an acceptance API call.
2811// Navigation is intentionally suppressed — the user dials manually after seeing the number.
2812// Handles the click-to-reveal interaction for phone number offers (e.g. Asurion / HP Care Complete).
2813// On first click: reads the pre-stripped phone number from data-phone (stamped by addUrlAndClickEvent),
2814// updates the CTA text, then delegates GDL tracking + acceptance API call to offerClickEvent.
2815// Navigation is intentionally suppressed — no offerElement closure needed.
2816function handlePhoneReveal($el, primaryButtonText) {
2817    const displayPhone = $el.attr("data-phone") || "";
2818
2819    logInfo("handlePhoneReveal: revealing phone number", displayPhone);
2820    // Find and replace the primaryButtonText value with the phone number
2821    if (primaryButtonText) {
2822        // Search through element text nodes and replace primaryButtonText with displayPhone
2823        const walker = document.createTreeWalker(
2824            $el[0],
2825            NodeFilter.SHOW_TEXT,
2826            null,
2827            false
2828        );
2829        let node;
2830        while (node = walker.nextNode()) {
2831            if (node.textContent.includes(primaryButtonText)) {
2832                logInfo("handlePhoneReveal: replacing primaryButtonText with phone number in text node.");
2833                node.textContent = node.textContent.replace(primaryButtonText, displayPhone);
2834                break;
2835            }
2836        }
2837    } else {
2838        // Fallback: if no primaryButtonText provided, just set based on any element that has a class name that contains cta or button
2839        const ctaElement = $el.find('[class*="cta"], [class*="button"]').first();
2840        if (ctaElement.length) {
2841            logInfo("handlePhoneReveal: no primaryButtonText provided, updating first CTA/button element text.");
2842            ctaElement.text(displayPhone);
2843        } else {
2844            loginfo("handlePhoneReveal: no primaryButtonText or CTA/button element found to update text.");
2845        }
2846    }
2847
2848    // Remove the click handler to prevent re-triggering on subsequent clicks
2849    $el.off(".offerClick");
2850
2851    // Delegate GDL tracking + acceptance API call to offerClickEvent.
2852    // Passing false for openLinkInNewTab suppresses window.open — no navigation occurs.
2853    offerClickEvent(reqObj, $el.get(0), false);
2854
2855    logInfo("Phone number revealed:", displayPhone);
2856}
2857
2858function addUrlAndClickEvent(divId, offerElement, openLinkInNewTab = true) {
2859    if (divId.charAt(0) !== '#' && divId.charAt(0) !== '.') {
2860        divId = "#" + divId;
2861    }
2862    const element = document.querySelector(
2863        divId.replace(/^#(\d)/, (_, d) => `#\\3${d} `)
2864    );
2865
2866    // convert to jQuery object
2867    const $el = $(element);
2868    if ($el.length === 0) {
2869        logInfo("addUrlAndClickEvent: element not found", divId);
2870        return;
2871    }
2872
2873    // Stash metadata on the element
2874    if (offerElement.storeURL) $el.attr("data-store-url", offerElement.storeURL);
2875
2876    if (offerElement.name) $el.attr("data-offer-name", offerElement.name);
2877
2878    // Avoid duplicate bindings if re-rendered
2879    //we pass the whole element clicked to the event handler
2880    //so that we can derive URL and offer name from data attributes or ancestors (when id is not set on cta)
2881    $el.off(".offerClick");
2882
2883    // Phone number in storeURL: stamp data-phone on the element and use click-to-reveal instead of navigation
2884    if (isPhoneNumber(offerElement.storeURL)) {
2885        $el.attr("data-phone", offerElement.storeURL.replace(/^tel:/i, "").replace(/[&?].*$/, "").trim());
2886        $el.on("click.offerClick", function (e) {
2887            e.preventDefault();
2888            handlePhoneReveal($(this), offerElement.primaryButtonText);
2889        });
2890        $el.on("keydown.offerClick", function (e) {
2891            const k = e.key || e.which;
2892            if (k === "Enter" || k === " " || k === 13 || k === 32) {
2893                e.preventDefault();
2894                handlePhoneReveal($(this), offerElement.primaryButtonText);
2895            }
2896        });
2897        return;
2898    }
2899
2900    $el.on("click.offerClick", function (e) {
2901        e.preventDefault();
2902        offerClickEvent(reqObj, this, openLinkInNewTab);
2903    });
2904
2905    $el.on("keydown.offerClick", function (e) {
2906        const k = e.key || e.which;
2907        if (k === "Enter" || k === " " || k === 13 || k === 32) {
2908            e.preventDefault();
2909            offerClickEvent(reqObj, this, openLinkInNewTab);
2910        }
2911    });
2912}
2913
2914function applyAccessibilityAttributes(selector, offerElement) {
2915
2916    if (selector.charAt(0) !== '#' && selector.charAt(0) !== '.') {
2917        selector = "#" + selector;
2918    }
2919
2920    // Cache the jQuery selector for the main element
2921    const element = document.querySelector(
2922        selector.replace(/^#(\d)/, (_, d) => `#\\3${d} `)
2923    );
2924
2925    // convert to jQuery object
2926    const $element = $(element);
2927    if (!$element) {
2928        logInfo(`Selector "${selector}" matched 0 elements.`);
2929        // treat "not found" as not empty
2930        return;
2931    }
2932
2933    // Set accessibility attributes on the main element
2934    $element.attr({
2935        "aria-label": offerElement.offerType,
2936        "tabindex": 0,
2937        "alt": offerElement.offerType
2938    });
2939
2940    // Set title attribute based on primaryButtonText, then primaryText1, then offerTitle, ensuring no HTML tags are included
2941    const htmlTagRegex = /<[^>]*>/;
2942    const titleText =
2943        (offerElement.primaryButtonText
2944            && !htmlTagRegex.test(offerElement.primaryButtonText) && isDefined(offerElement.primaryButtonText))
2945            ? offerElement.primaryButtonText
2946            : (isDefined(offerElement.primaryText1) && !htmlTagRegex.test(offerElement.primaryText1))
2947                ? offerElement.primaryText1
2948                : (isDefined(offerElement.primaryText2) && !htmlTagRegex.test(offerElement.primaryText2))
2949                    ? offerElement.primaryText2
2950                    : offerElement.offerType;
2951
2952    $element.attr("title", titleText);
2953
2954    if (reqObj.user.language === "ar" || reqObj.user.language === "he") {
2955        // Get parent directly rather than by class name
2956        $element.parent().css("text-align", "right");
2957    }
2958
2959    // Apply attributes to images if they exist
2960    if (isDefined(offerElement.imageURL)) {
2961        $element.find("img").attr({
2962            "title": titleText,
2963            "alt": offerElement.offerType
2964        });
2965    }
2966}
2967
2968function isContainerEmpty(selector) {
2969    const el = document.querySelector(selector);
2970    if (!el) {
2971        logInfo(`Selector "${selector}" matched 0 elements.`);
2972        // treat "not found" as not empty
2973        return false;
2974    }
2975    const text = (el.textContent || "").trim();
2976    const looksLoading = /loading|spinner|please wait/i.test(text);
2977    const havePlaceholder = /placeholder/i.test(text);
2978    const structurallyEmpty = el.children.length === 0 || text.length === 0;
2979    const isEmpty = $(el).is(":empty");
2980    return structurallyEmpty || looksLoading || havePlaceholder || isEmpty;
2981}
2982
2983function hideContainer(selector, method = "hide", onlyWhenEmpty = true) {
2984    logInfo(`hideContainer called with selector="${selector}", method="${method}", onlyWhenEmpty=${onlyWhenEmpty}`);
2985    //log callstack
2986    //logInfo(new Error().stack);
2987    const el = document.querySelector(selector);
2988    if (!el) {
2989        logInfo(`Selector "${selector}" matched 0 elements. No action taken.`);
2990        return;
2991    }
2992    const empty = isContainerEmpty(selector);
2993    logInfo(`Container "${selector}" empty status: ${empty}`);
2994    if ((onlyWhenEmpty && empty) || (!onlyWhenEmpty)) {
2995        // only hide if empty, or always hide
2996        if (!onlyWhenEmpty) logInfo(`Hiding container "${selector}" using method "${method}" regardless of content.`);
2997        if (onlyWhenEmpty && empty) logInfo(`Hiding container "${selector}" using method "${method}" because it is empty.`);
2998        switch (method) {
2999            case "remove":
3000                if (el) {
3001                    el.remove();
3002                    logInfo(`Element removed from DOM.`);
3003                }
3004                break;
3005            case "visibility":
3006                if (el) {
3007                    el.style.visibility = "hidden";
3008                    logInfo(`Element visibility set to hidden.`);
3009                }
3010                break;
3011            case "hidden":
3012                if (el) {
3013                    el.classList.add("hidden");
3014                    logInfo(`Element class 'hidden' added.`);
3015                }
3016                break;
3017            case "hide":
3018                if (el) {
3019                    $(el).hide();
3020                    logInfo(`Element hidden using jQuery.`);
3021                }
3022                break;
3023            case "removeparent":
3024                if (el && el.parentElement) {
3025                    el.parentElement.remove();
3026                    logInfo(`Parent element removed from DOM.`);
3027                }
3028                break;
3029            case "hideparent":
3030                if (el && el.parentElement) {
3031                    $(el.parentElement).hide();
3032                    logInfo(`Parent element hidden using jQuery.`);
3033                }
3034                break;
3035            default:
3036                if (el) el.style.display = "none";
3037                logInfo(`Element display set to none.`);
3038                break;
3039        }
3040    }
3041}
3042
3043function hideMastiffOfferPlacement() {
3044    var cfg = PAGE_CONFIG[pgName] || {};
3045    if (cfg.positions) {
3046        Object.keys(cfg.positions).forEach(function (pos) {
3047            hidePlacement(pgName, pos);
3048        });
3049    }
3050}
3051
3052function waitForElementToDisappear(selector, callback, callbackArg) {
3053    const targetElement = document.querySelector(selector);
3054
3055    if (!targetElement) {
3056        logInfo(`${selector} not found`);
3057        callback(callbackArg);
3058        return;
3059    }
3060
3061    logInfo(`waiting for ${selector} to disappear`);
3062
3063    const observer = new MutationObserver((mutationsList, observer) => {
3064        if (!document.querySelector(selector)) {
3065            logInfo(`${selector} removed`);
3066            observer.disconnect();
3067            callback(callbackArg);
3068        }
3069    });
3070
3071    observer.observe(targetElement.parentNode, { childList: true });
3072}
3073
3074function waitForElement(selector, parent, timeout = 30000) {
3075    logInfo("waiting for element", selector);
3076    return new Promise((resolve, reject) => {
3077        const element = document.querySelector(selector);
3078        if (element) {
3079            logInfo(selector, "element found using querySelector");
3080            resolve(element);
3081            return;
3082        }
3083
3084        const observer = new MutationObserver((mutations, obs) => {
3085            const element = document.querySelector(selector);
3086            if (element) {
3087                logInfo(selector, "element found using observer");
3088                resolve(element);
3089                obs.disconnect();
3090            }
3091        });
3092
3093        var parentNode = document.body;
3094        if (parent) {
3095            const parentElement = document.querySelector(parent);
3096            if (parentElement) {
3097                parentNode = parentElement;
3098            } else {
3099                logInfo(`Parent element "${parent}" not found. Defaulting to document.body`);
3100            }
3101        }
3102
3103        logInfo("observing", parentNode);
3104
3105        observer.observe(parentNode, {
3106            childList: true,
3107            subtree: true
3108        });
3109
3110        setTimeout(() => {
3111            observer.disconnect();
3112            logInfo("waited ", timeout, "ms for ", selector);
3113            reject(new Error("Observer timed out when waiting for element" + selector));
3114        }, timeout);
3115    });
3116}
3117
3118function sleep(milliseconds) {
3119    var date = Date.now();
3120    var currentDate = null;
3121    do {
3122        currentDate = Date.now();
3123    } while (currentDate - date < milliseconds);
3124}
3125
3126function logInfo(...args) {
3127    if (isMastiffDebug() || isForceLogOn()) console.info(...args);
3128}
3129
3130// add mastifflog as URL param to force logging #mastifflog=1
3131function isForceLogOn() {
3132    return sessionStorage.getItem("mastifflog") === "true";
3133}
3134
3135function logToGlobalDataLayer(LeadOffer) {
3136    if (typeof globalDataLayer !== "undefined" && globalDataLayer.SPOSOffers) {
3137        globalDataLayer.SPOSOffers[`LeadOffer${LeadOfferIndex}`] = LeadOffer;
3138        LeadOfferIndex++;
3139    }
3140}
3141
3142function SaveReqObjToSessionStorage() {
3143    sessionStorage.setItem("reqObj", JSON.stringify(reqObj));
3144    sessionStorage.setItem("offerResults", JSON.stringify(offerResults));
3145}
3146
3147function GetReqObjFromSessionStorage() {
3148    return JSON.parse(sessionStorage.getItem("reqObj")) || {};
3149}
3150
3151async function getDeviceInfo() {
3152    const ua = navigator.userAgent || "";
3153    const hasUAData = !!navigator.userAgentData;
3154
3155    // --- helpers ---
3156    const detectBrowserFromUA = (uaStr) => {
3157        if (/Edg\//i.test(uaStr)) return "Microsoft Edge";
3158        if (/OPR\//i.test(uaStr) || /Opera/i.test(uaStr)) return "Opera";
3159        if (/Chrome\//i.test(uaStr) && !/Chromium/i.test(uaStr)) return "Chrome";
3160        if (/Safari\//i.test(uaStr) && !/Chrome/i.test(uaStr)) return "Safari";
3161        if (/Firefox\//i.test(uaStr)) return "Firefox";
3162        if (/Chromium/i.test(uaStr)) return "Chromium";
3163        if (/MSIE|Trident/i.test(uaStr)) return "Internet Explorer";
3164        return "Unknown";
3165    };
3166
3167    const heuristicWin10vs11FromUA = (uaStr) => {
3168        // Both Win10/11 report Windows NT 10.0 in UA.
3169        if (/Windows 11/i.test(uaStr)) return "Windows 11";
3170        const m = uaStr.match(/(Chrome|Edg|Firefox)\/(\d+)/i);
3171        if (!m) return "Windows 10";
3172        const name = m[1].toLowerCase();
3173        const ver = parseInt(m[2], 10);
3174        if ((name === "chrome" || name === "edg") && ver >= 92) return "Windows 11";
3175        if (name === "firefox" && ver >= 90) return "Windows 11";
3176        return "Windows 10";
3177    };
3178
3179    const detectOSFromUAWithWinSplit = (uaStr) => {
3180        if (/Windows NT 10\.0/i.test(uaStr)) return heuristicWin10vs11FromUA(uaStr);
3181        if (/Windows NT 6\.3/i.test(uaStr)) return "Windows 8.1";
3182        if (/Windows NT 6\.2/i.test(uaStr)) return "Windows 8";
3183        if (/Windows NT 6\.1/i.test(uaStr)) return "Windows 7";
3184        if (/Windows NT 6\.0/i.test(uaStr)) return "Windows Vista";
3185        if (/Windows NT 5\.1/i.test(uaStr)) return "Windows XP";
3186        if (/Mac OS X 10[._]\d+/i.test(uaStr)) return "macOS";
3187        if (/Android/i.test(uaStr)) return "Android";
3188        if (/iPhone|iPad|iPod/i.test(uaStr)) return "iOS";
3189        if (/Linux/i.test(uaStr)) return "Linux";
3190        return "Unknown";
3191    };
3192
3193    const fallback = {
3194        browser: detectBrowserFromUA(ua),
3195        os: detectOSFromUAWithWinSplit(ua),
3196        deviceType: /Mobi|Android|iPhone|iPad|iPod/i.test(ua) ? "Mobile" : "Desktop"
3197    };
3198
3199    if (!hasUAData) return fallback;
3200
3201    try {
3202        // UA-CH (Chromium): get high-entropy values
3203        const uaData = navigator.userAgentData;
3204        const { brands, mobile, platform } = uaData;
3205        // Some browsers expose fullVersionList instead of brands in getHighEntropyValues
3206        const hi = await uaData.getHighEntropyValues([
3207            "platform",
3208            "platformVersion",
3209            "fullVersionList",
3210            "model"
3211        ]);
3212
3213        // --- Browser via UA-CH brands/fullVersionList ---
3214        const brandList = (hi.fullVersionList && Array.isArray(hi.fullVersionList))
3215            ? hi.fullVersionList
3216            : (brands || []);
3217
3218        const brandNames = brandList.map(b => (b.brand || b.brandName || ""));
3219
3220        var browser = "Unknown";
3221        if (brandNames.some(b => /Microsoft Edge/i.test(b))) browser = "Microsoft Edge";
3222        else if (brandNames.some(b => /Opera/i.test(b))) browser = "Opera";
3223        else if (brandNames.some(b => /Google Chrome/i.test(b))) browser = "Chrome";
3224        else if (brandNames.some(b => /^Chromium$/i.test(b))) browser = "Chromium";
3225        else {
3226            // Non-Chromium (Safari/Firefox) often won’t populate UA-CH; fallback to UA string
3227            browser = detectBrowserFromUA(ua);
3228        }
3229
3230        // --- Device Type from UA-CH (fallback UA) ---
3231        const deviceType = mobile ? "Mobile" : (/Mobi|Android|iPhone|iPad|iPod/i.test(ua) ? "Mobile" : "Desktop");
3232
3233        // --- OS with Win10/11 split using UA-CH platformVersion ---
3234        var os = "Unknown";
3235        const plat = (hi.platform || platform || "").toLowerCase();
3236
3237        if (plat === "windows") {
3238            // Windows mapping per Chromium UA-CH:
3239            // major platformVersion >= 13 -> Windows 11+, >0 -> Windows 10, 0/undefined -> older/unknown
3240            const major = parseInt((hi.platformVersion || "0").split(".")[0], 10);
3241            if (!isNaN(major)) {
3242                if (major >= 13) os = "Windows 11";
3243                else if (major > 0) os = "Windows 10";
3244                else os = "Windows (before Windows 10)";
3245            } else {
3246                // Fallback to UA heuristic if parsing failed
3247                os = detectOSFromUAWithWinSplit(ua);
3248            }
3249        } else if (plat === "mac" || plat === "macos") {
3250            os = "macOS";
3251        } else if (plat === "android") {
3252            os = "Android";
3253        } else if (plat === "ios") {
3254            os = "iOS";
3255        } else if (plat === "chrome os" || plat === "chromeos") {
3256            os = "Chrome OS";
3257        } else if (plat === "linux") {
3258            os = "Linux";
3259        } else {
3260            os = detectOSFromUAWithWinSplit(ua);
3261        }
3262
3263        return { browser, os, deviceType };
3264    } catch {
3265        return fallback;
3266    }
3267}
3268
3269// ------------------- helpers code ends here -------------------
3270
3271// ----------- Offer rendering code starts here ----------------
3272
3273function printerSetupOffers() {
3274    waitForElement("#opt-mastiff-setup")
3275    var primaryPositionElement = offerResults.offers.offer.filter(function (x) {
3276        return x.templatePosition === "primary";
3277    })[0];
3278    var secondaryPositionElement = offerResults.offers.offer.filter(function (x) {
3279        return x.templatePosition === "secondary";
3280    })[0];
3281    var shop1PositionElement = offerResults.offers.offer.filter(function (x) {
3282        return x.templatePosition === "shop1";
3283    })[0];
3284
3285    if (primaryPositionElement != null) {
3286        showpPrinterSetupOffer(primaryPositionElement);
3287    }
3288    if (secondaryPositionElement != null) {
3289        showpPrinterSetupOffer(secondaryPositionElement);
3290    }
3291    if (shop1PositionElement != null) {
3292        showpPrinterSetupOffer(shop1PositionElement);
3293    }
3294    $("#opt-mastiff-setup").css("margin-top", "20px");
3295}
3296
3297function showpPrinterSetupOffer(prnSetupOfferElement) {
3298    var divId = "";
3299    divId = divId.concat(prnSetupOfferElement.templatePosition, "_", prnSetupOfferElement.name);
3300
3301    var LeadOffer = {};
3302    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3303    LeadOffer.OfferID = divId;
3304    LeadOffer.OfferClicked = "no";
3305    LeadOffer.SPOStemplate = "12";
3306    if (
3307        isDefined(prnSetupOfferElement.html) &&
3308        isDefined(prnSetupOfferElement.primaryButtonText) &&
3309        isDefined(prnSetupOfferElement.storeURL)
3310    ) {
3311        var htmlTemplate = prnSetupOfferElement.html;
3312        var html = "";
3313        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", prnSetupOfferElement.primaryButtonText);
3314        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", prnSetupOfferElement.storeURL);
3315        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId);
3316
3317        $("#opt-mastiff-setup").append(htmlTemplate);
3318        $(".opt-mastiff-setup-box").removeClass("hidden");
3319
3320        LeadOffer.offerShown = "yes";
3321
3322
3323        applyAccessibilityAttributes(divId, prnSetupOfferElement);
3324
3325        $(".simpleLinkTemplateAnchor").css("font-family", "HPSimplified");
3326        $(".simpleLinkTemplateAnchor").css("font-size", "14px");
3327        $(".simpleLinkTemplateAnchor").css("line-height", "25px");
3328        $("#" + divId).css("margin-top", "10px");
3329
3330        addUrlAndClickEvent(divId, prnSetupOfferElement);
3331        logToGlobalDataLayer(LeadOffer);
3332    } else {
3333        LeadOffer.errorData = "No Content Available";
3334        LeadOffer.offerShown = "no";
3335        window.optRevertHpOffer();
3336        logToGlobalDataLayer(LeadOffer)
3337    }
3338}
3339
3340function showDocumentOffer(primaryOfferElement) {
3341    var divId = "";
3342    divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name);
3343
3344    var LeadOffer = {};
3345    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3346    LeadOffer.OfferID = divId;
3347    LeadOffer.OfferClicked = "no";
3348    LeadOffer.SPOStemplate = "9";
3349    if (
3350        isDefined(primaryOfferElement.html) &&
3351        isDefined(primaryOfferElement.imageURL) &&
3352        isDefined(primaryOfferElement.primaryText1) &&
3353        isDefined(primaryOfferElement.primaryButtonText) &&
3354        isDefined(primaryOfferElement.storeURL)
3355    ) {
3356        var htmlTemplate = primaryOfferElement.html;
3357        var html = "";
3358        html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>");
3359        if (isContainerEmpty("#opt-mastiff-doc")) {
3360            html = html.replace("%offerimageURLPlaceholder%", primaryOfferElement.imageURL || "");
3361            html = html.replace("%offerprimaryText1PlaceHolder%", primaryOfferElement.primaryText1 || "");
3362            html = html.replace("%offerprimaryText2PlaceHolder%", primaryOfferElement.primaryText2 || "");
3363            html = html.replace("%offerprimaryButtonTextPlaceHolder%", primaryOfferElement.primaryButtonText || "");
3364
3365            $("#opt-mastiff-doc").append(html);
3366            LeadOffer.offerShown = "yes";
3367
3368            applyAccessibilityAttributes(divId, primaryOfferElement);
3369            addUrlAndClickEvent(divId, primaryOfferElement);
3370
3371        } else {
3372            LeadOffer.errorData = "Document Offer Location is not empty";
3373            LeadOffer.offerShown = "no";
3374            window.optRevertHpOffer();
3375        }
3376        logToGlobalDataLayer(LeadOffer);
3377    } else {
3378        LeadOffer.errorData = "No Content Available";
3379        LeadOffer.offerShown = "no";
3380        window.optRevertHpOffer();
3381        logToGlobalDataLayer(LeadOffer);
3382    }
3383}
3384
3385function showHelpPageOffer(primaryOfferElement) {
3386    var divId = "";
3387    divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name);
3388
3389    var LeadOffer = {};
3390    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3391    LeadOffer.OfferID = divId;
3392    LeadOffer.OfferClicked = "no";
3393    LeadOffer.SPOStemplate = "15";
3394    if (
3395        isDefined(primaryOfferElement.html) &&
3396        isDefined(primaryOfferElement.imageURL) &&
3397        isDefined(primaryOfferElement.primaryText1) &&
3398        isDefined(primaryOfferElement.primaryButtonText) &&
3399        isDefined(primaryOfferElement.storeURL)
3400    ) {
3401        var htmlTemplate = primaryOfferElement.html;
3402        var html = "";
3403        html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>");
3404        if (isContainerEmpty("#mastiffoffers")) {
3405            html = html.replace("%DiagsVRepairsimageURLPlaceholder%", primaryOfferElement.imageURL);
3406            html = html.replace("%DiagsVRepairsText1PlaceHolder%", primaryOfferElement.primaryText1);
3407            html = html.replace("%DiagsVRepairsText2PlaceHolder%", primaryOfferElement.primaryText2);
3408            html = html.replace("%DiagsVRepairsButtonTextPlaceHolder%", primaryOfferElement.primaryButtonText);
3409
3410            $("#mastiffoffers").append(html);
3411            if (pgName === "repair") {
3412                document.getElementById('diagsVRepairsImg').classList.add('VRepairsImg');
3413                document.getElementById('diagsVRepairsText1').classList.add('VRepairsText1');
3414                document.getElementById('diagsVRepairsText2').classList.add('VRepairsText2');
3415                document.getElementById('diagsVRepairsCTADiv').classList.add('VRepairsCTADiv');
3416            }
3417            else if (pgName === "hardware-diagnostics") {
3418                document.getElementById('diagsVRepairsImg').classList.add('DiagsImg');
3419                document.getElementById('diagsVRepairsText1').classList.add('DiagsText1');
3420                document.getElementById('diagsVRepairsText2').classList.add('DiagsText2');
3421                document.getElementById('diagsVRepairsCTADiv').classList.add('DiagsCTADiv');
3422            }
3423            $('.mastiffoffersTile').removeClass('hidden');
3424
3425            LeadOffer.offerShown = "yes";
3426            applyAccessibilityAttributes(divId, primaryOfferElement);
3427            addUrlAndClickEvent(divId, primaryOfferElement);
3428        } else {
3429            LeadOffer.errorData = "Help Page Offer Location is not empty";
3430            LeadOffer.offerShown = "no";
3431        }
3432        logToGlobalDataLayer(LeadOffer);
3433    } else {
3434        LeadOffer.errorData = "No Content Available";
3435        LeadOffer.offerShown = "no";
3436        logToGlobalDataLayer(LeadOffer);
3437    }
3438}
3439
3440function showDriverClosurePrimaryOffer(offerElement) {
3441    var divId = "";
3442    divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name);
3443
3444    var LeadOffer = {};
3445    var GDLOfferName = "LeadOffer" + LeadOfferIndex;
3446    LeadOffer.OfferID = divId;
3447    LeadOffer.OfferClicked = "no";
3448    LeadOffer.SPOStemplate = "15";
3449
3450    if (
3451        isDefined(offerElement.html) &&
3452        isDefined(offerElement.primaryText1) &&
3453        isDefined(offerElement.primaryText2) &&
3454        isDefined(offerElement.primaryButtonText) &&
3455        isDefined(offerElement.imageURL) &&
3456        isDefined(offerElement.storeURL)
3457    ) {
3458        var htmlTemplate = offerElement.html;
3459
3460        if (isContainerEmpty("#swdClosurePageMastiffBanner")) {
3461            htmlTemplate = htmlTemplate.replace("%DriverTileOfferImgURLPlaceholder%", offerElement.imageURL);
3462            htmlTemplate = htmlTemplate.replace("%DriverTileOfferTitlePlaceholder%", offerElement.primaryText1);
3463            htmlTemplate = htmlTemplate.replace("%DriverTileOfferDescriptionPlaceholder%", offerElement.primaryText2);
3464            htmlTemplate = htmlTemplate.replace("%DriverTileOfferCTAPlaceholder%", offerElement.primaryButtonText);
3465            htmlTemplate = htmlTemplate.replace("%DriverTileOfferId%", divId);
3466
3467            $("#swdClosurePageMastiffBanner").html(htmlTemplate);
3468
3469            allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
3470
3471            $("#" + divId).css("margin-top", "50px");
3472            $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" });
3473
3474            applyAccessibilityAttributes(divId, offerElement);
3475
3476            LeadOffer.offerShown = "yes";
3477            addUrlAndClickEvent(divId, offerElement);
3478        } else {
3479            LeadOffer.errorData = "Primary1 Location is not empty";
3480            LeadOffer.offerShown = "no";
3481        }
3482        logToGlobalDataLayer(LeadOffer);
3483    } else {
3484        LeadOffer.errorData = "No Content Available";
3485        LeadOffer.offerShown = "no";
3486
3487        logToGlobalDataLayer(LeadOffer);
3488    }
3489}
3490
3491
3492async function showDashboardTile() {
3493    enableDashTile = false;
3494    await waitForElement("#dashboard_tile_mastiff_template").then(() => {
3495        // if dashboard_tile_mastiff_template container is empty then only proceed
3496        if (!isContainerEmpty("#dashboard_tile_mastiff_template")) {
3497            $("#dashboard_tile_mastiff_template").empty();
3498        }
3499
3500        var carouselOffers = offerResults.offers.offer.filter(function (x) {
3501            return x.templatePosition === "carousel" && !x.category.toLowerCase().includes("quiz")
3502        });
3503
3504        carouselOffers.forEach(function (offer) {
3505            DashboardTileContent(offer);
3506        });
3507
3508        if (enableDashTile) {
3509            var slides = $(".dashboardSlidercontainer .DashTempshowSlide");
3510            var navBullets = $("#nav-bullets");
3511            navBullets.empty();
3512            slides.each(function (idx) {
3513                navBullets.append(`<div class="nav-bullet"></div>`);
3514            });
3515            $('#nav-bullets').off('click').on('click', '.nav-bullet', function () {
3516                var idx = $(this).index() + 1;
3517                currentSlide(idx);
3518            });
3519
3520            if (document.getElementsByClassName("DashTempshowSlide").length == 1) {
3521                var navigationDiv = document.getElementsByClassName('dashboard-navigation')[0];
3522                if (navigationDiv) navigationDiv.style.visibility = "hidden";
3523            }
3524            sliderClassName = "DashTempshowSlide";
3525            navBulletAvailable = true;
3526            displaySlides(slide_index);
3527        } else {
3528            hideContainer("#dashboard_tile_mastiff_template", "removeparent", true);
3529        }
3530    })
3531        .catch((err) => {
3532            logInfo("Error waiting for dashboard tile container:", err);
3533        });
3534}
3535
3536function DashboardTileContent(offerElement) {
3537    var divId = "";
3538    divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
3539    var LeadOffer = {};
3540    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3541    LeadOffer.OfferID = divId;
3542    LeadOffer.OfferClicked = "no";
3543    LeadOffer.SPOStemplate = "8";
3544
3545    if (
3546        isDefined(offerElement.html) &&
3547        isDefined(offerElement.imageURL) &&
3548        isDefined(offerElement.primaryText1) &&
3549        isDefined(offerElement.primaryButtonText) &&
3550        isDefined(offerElement.storeURL)
3551    ) {
3552        var htmlTemplate = offerElement.html;
3553        if (!$(".dashboardSlidercontainer").length && isContainerEmpty("#dashboard_tile_mastiff_template")) {
3554            $("#dashboard_tile_mastiff_template").attr("tabindex", "0");
3555            $("#dashboard_tile_mastiff_template").append(dashboardSliderDiv);
3556        }
3557        enableDashTile = true;
3558        htmlTemplate = htmlTemplate.replace("%DashboardTileImgplaceholder%", offerElement.imageURL);
3559        htmlTemplate = htmlTemplate.replace("%DashboardTileTitleplaceholder%", offerElement.primaryText1);
3560        htmlTemplate = htmlTemplate.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2);
3561        htmlTemplate = htmlTemplate.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText);
3562        //htmlTemplate = htmlTemplate.replace("%dashboardTemplateTileLinkURL%", offerElement.storeURL || "");
3563        htmlTemplate = htmlTemplate.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)");
3564        htmlTemplate = htmlTemplate.replace("id=%DashboardTileCTAId%", "");
3565        htmlTemplate = htmlTemplate.replace("class=dashboardTemplate>", "class='dashboardTemplate DashTempshowSlide DashTempfade'>");
3566        htmlTemplate = htmlTemplate.replace("tabindex=0", "");
3567        htmlTemplate = htmlTemplate.replace('target=_blank', "tabindex=0");
3568
3569        //remove id from the htmlTemplate id="divId"
3570        htmlTemplate = htmlTemplate.replace("class='dashboardTemplate DashTempshowSlide DashTempfade'>", `id="${divId}" class='dashboardTemplate DashTempshowSlide DashTempfade'>`);
3571
3572        if (!isContainerEmpty(".dashboardSlidercontainer")) {
3573            $(".dashboardSlidercontainer").append(htmlTemplate);
3574            $("#nav-bullets").append("<div class=\"nav-bullet\" onclick=\"currentSlide(1)\"></div>");
3575        }
3576        LeadOffer.offerShown = "yes";
3577        applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, offerElement);
3578        addUrlAndClickEvent(divId, offerElement);
3579    } else {
3580        logInfo("Dashboard offer content not available");
3581        LeadOffer.errorData = "No Content Available";
3582        LeadOffer.offerShown = "no";
3583    }
3584
3585    logToGlobalDataLayer(LeadOffer);
3586}
3587function bindDashboardQuizInitiator(quizInitiator) {
3588    const $warrantyPlacement = $("#dy-mastiff-warranty");
3589    if (!$warrantyPlacement.length) return;
3590
3591    const showDashboardQuizModal = function () {
3592        logInfo("[Dashboard Quiz] Initiator selected; revealing the prepared Quiz Portal modal.");
3593        $("#mastiff-modal-cpc-content .sposQuizSpinner").remove();
3594        if (uiState.quiztype === "cpc") {
3595            $("#mastiff-modal-cpc-content .CPConfiguratorContainer").show();
3596        } else if (uiState.quiztype === "huq") {
3597            $("#mastiff-modal-cpc-content .HUQConfiguratorContainer").show();
3598        }
3599        $("#mastiff-modal-cpc, #mastiff-overlay").show();
3600    };
3601
3602    $warrantyPlacement
3603        .off(".dashboardQuiz")
3604        .on("click.dashboardQuiz", function (event) {
3605            event.preventDefault();
3606            showDashboardQuizModal();
3607        }).on("keydown.dashboardQuiz", function (event) {
3608            const key = event.key || event.which;
3609            if (key === "Enter" || key === " " || key === 13 || key === 32) {
3610                event.preventDefault();
3611                showDashboardQuizModal();
3612            }
3613        });
3614
3615    $(document).off("click.dashboardQuizDiscard", "#mastiff-modal-cpc-close, #mastiff-overlay")
3616        .on("click.dashboardQuizDiscard", "#mastiff-modal-cpc-close, #mastiff-overlay", function (event) {
3617            if (this.id === "mastiff-overlay" && event.target !== this) return;
3618
3619            logInfo("[Dashboard Quiz] Modal dismissed; sending the Quiz Portal discard report for the initiator.", quizInitiator.name);
3620            discardQuizPortalExperience(quizInitiator.name);
3621        });
3622}
3623
3624function showWarrantyDashboardOffer(offerElement, openLinkInNewTab) {
3625    const warrantyTileContainerId = "dy-mastiff-warranty";
3626
3627    return waitForElement("#" + warrantyTileContainerId).then(() => {
3628
3629        var divId = "";
3630        divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
3631
3632        var LeadOffer = {};
3633        var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3634        LeadOffer.OfferID = divId;
3635        LeadOffer.OfferClicked = "no";
3636        LeadOffer.SPOStemplate = "10";
3637
3638        if (isDefined(offerElement.primaryButtonText) &&
3639            isDefined(offerElement.storeURL) &&
3640            isDefined(offerElement.html)) {
3641            var renderedDivId = null;
3642            logInfo("Warranty dashboard offer content available");
3643            if (isContainerEmpty(`#${warrantyTileContainerId}`)) {
3644                //$("#" + warrantyTileContainerId).attr("tabindex", "0");
3645                var html = offerElement.html;
3646                html = html.replace(/{cta}/g, offerElement.primaryButtonText);
3647                html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)");
3648                html = html.replace("id=%DashboardTileCTAId%", "");
3649                html = html.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2);
3650                html = html.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText);
3651                html = html.replace("tabindex=0", "");
3652                html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='oldDashboardTemplate'`);
3653                html = html.replace('target=_blank', "tabindex=0");
3654
3655                $("#" + warrantyTileContainerId).html(html);
3656
3657                $("#" + warrantyTileContainerId).find(".oldDashboardTemplateTileHeader").remove();
3658                $("#" + warrantyTileContainerId).find(".oldDashboardTemplateDescContainer").remove();
3659
3660                $("#" + warrantyTileContainerId).removeClass("hidden");
3661                $("#" + warrantyTileContainerId).addClass("show");
3662                LeadOffer.offerShown = "yes";
3663
3664
3665                applyAccessibilityAttributes(`#${divId} .oldDashboardTemplateTileLink `, offerElement);
3666                addUrlAndClickEvent(divId, offerElement, openLinkInNewTab);
3667
3668                logInfo("Warranty dashboard offer HTML inserted", offerElement);
3669                renderedDivId = divId;
3670            } else {
3671                LeadOffer.errorData = "Warranty Dashboard Offer Location is not empty";
3672                LeadOffer.offerShown = "no";
3673            }
3674
3675            logToGlobalDataLayer(LeadOffer);
3676            return renderedDivId;
3677        } else {
3678            logInfo("Warranty dashboard offer content not available");
3679            LeadOffer.errorData = "No Content Available";
3680            LeadOffer.offerShown = "no";
3681            logToGlobalDataLayer(LeadOffer);
3682            return null;
3683        }
3684    }).catch((err) => {
3685        logInfo("Error waiting for warranty tile container:", err);
3686        return null;
3687    });
3688}
3689
3690function showSingleDashboardTileOffer(primaryOfferElement) {
3691    waitForElement("#dashboard_tile_instantink_print").then(() => {
3692        var divId = "";
3693        divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name);
3694
3695        var LeadOffer = {};
3696        var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3697        LeadOffer.OfferID = divId;
3698        LeadOffer.OfferClicked = "no";
3699        LeadOffer.SPOStemplate = "10";
3700
3701        if (
3702            isDefined(primaryOfferElement.html) &&
3703            isDefined(primaryOfferElement.primaryText1) &&
3704            isDefined(primaryOfferElement.primaryButtonText) &&
3705            isDefined(primaryOfferElement.imageURL) &&
3706            isDefined(primaryOfferElement.storeURL)
3707        ) {
3708
3709            logInfo("offer content available");
3710            if (isContainerEmpty("#dashboard_tile_instantink_print")) {
3711                $("#dashboard_tile_instantink_print").attr("tabindex", "0");
3712                var html = primaryOfferElement.html;
3713
3714                html = html.replace("%DashboardTileImgplaceholder%", primaryOfferElement.imageURL);
3715                html = html.replace("%DashboardTileTitleplaceholder%", primaryOfferElement.primaryText1);
3716                html = html.replace("%DashboardTileDescriptionplaceholder%", primaryOfferElement.primaryText2);
3717                html = html.replace("%DashboardTileCTAplaceholder%", primaryOfferElement.primaryButtonText);
3718                html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)");
3719                html = html.replace("tabindex=0", "");
3720                html = html.replace("id=%DashboardTileCTAId%", "");
3721                html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='dashboardTemplate'`);
3722                html = html.replace('target=_blank', "tabindex=0");
3723
3724                $("#dashboard_tile_instantink_print").show();
3725                $("#dashboard_tile_instantink_print").html(html);
3726                LeadOffer.offerShown = "yes";
3727
3728                applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, primaryOfferElement);
3729                addUrlAndClickEvent(divId, primaryOfferElement);
3730
3731                logInfo("Offer HTML inserted in ", primaryOfferElement);
3732            } else {
3733                LeadOffer.errorData = "SPOS Primary Offer Location is not empty";
3734                LeadOffer.offerShown = "no";
3735            }
3736            logToGlobalDataLayer(LeadOffer);
3737        } else {
3738            logInfo("offer content not available");
3739            LeadOffer.errorData = "No Content Available";
3740            LeadOffer.offerShown = "no";
3741            logToGlobalDataLayer(LeadOffer);
3742        }
3743
3744        hideContainer("#dashboard_tile_instantink_print");
3745    }).catch((err) => {
3746        logInfo("Error waiting for dashboard tile container:", err);
3747    });
3748}
3749
3750async function showCartidgesDashboardOffer(offerElement) {
3751    const cartidgesTileContainerId = "compatibleCartridgesTile";
3752
3753    await waitForElement("#" + cartidgesTileContainerId);
3754
3755    var divId = "";
3756    divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
3757
3758    var LeadOffer = {};
3759    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
3760    LeadOffer.OfferID = divId;
3761    LeadOffer.OfferClicked = "no";
3762    LeadOffer.SPOStemplate = "10";
3763
3764    if (
3765        isDefined(offerElement.imageURL) &&
3766        isDefined(offerElement.primaryText1) &&
3767        isDefined(offerElement.primaryButtonText) &&
3768        isDefined(offerElement.storeURL) &&
3769        isDefined(offerElement.html)
3770    ) {
3771        logInfo("Cartidges dashboard offer content available");
3772        if (isContainerEmpty(`#${cartidgesTileContainerId}`)) {
3773            $("#" + cartidgesTileContainerId).attr("tabindex", "0");
3774
3775            var html = offerElement.html;
3776
3777            html = html.replace("%DashboardTileImgplaceholder%", offerElement.imageURL);
3778            html = html.replace("%DashboardTileTitleplaceholder%", offerElement.primaryText1);
3779            html = html.replace("%DashboardTileDescriptionplaceholder%", offerElement.primaryText2);
3780            html = html.replace("%DashboardTileCTAplaceholder%", offerElement.primaryButtonText);
3781            html = html.replace("%dashboardTemplateTileLinkURL%", "javascript:void(0)");
3782            html = html.replace("tabindex=0", "");
3783            html = html.replace("id=%DashboardTileCTAId%", "");
3784            html = html.replace("class=oldDashboardTemplate", `id="${divId}" class='dashboardTemplate'`);
3785            html = html.replace('target=_blank', "tabindex=0");
3786
3787            $("#" + cartidgesTileContainerId).html(html).show();
3788            $("#" + cartidgesTileContainerId).removeClass("hidden");
3789
3790            LeadOffer.offerShown = "yes";
3791
3792            //applyAccessibilityAttributes(cartidgesTileContainerId, offerElement);
3793            applyAccessibilityAttributes(`#${divId} .dashboardTemplateTileLink`, offerElement);
3794
3795            addUrlAndClickEvent(divId, offerElement);
3796
3797            logInfo("Cartidges dashboard offer HTML inserted", offerElement);
3798        } else {
3799            LeadOffer.errorData = "Cartidges Dashboard Offer Location is not empty";
3800            LeadOffer.offerShown = "no";
3801        }
3802
3803        logToGlobalDataLayer(LeadOffer);
3804    } else {
3805        logInfo("Cartidges dashboard offer content not available");
3806        LeadOffer.errorData = "No Content Available";
3807        LeadOffer.offerShown = "no";
3808        logToGlobalDataLayer(LeadOffer);
3809    }
3810}
3811
3812var contactPageConfigs = {
3813    "primary-contact": {
3814        matchCondition: (offer) => !offer.category?.startsWith("phone-support") && offer.templatePosition === "primary",
3815        containerDivId: "contact_option_mastiff_tile_template",
3816        parentClass: "contact-options-container",
3817        templateNumber: "11",
3818        isValid: (offer) => (
3819            isDefined(offer.primaryText1) && isDefined(offer.primaryText2) &&
3820            isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText)
3821        ),
3822        renderTemplate: (offer, offerDivId) => {
3823            return offer.html
3824                .replace("%falconContactHPImgURLPlaceholder%", offer.imageURL)
3825                .replace("%falconContactHPOfferTitlePlaceholder%", offer.primaryText1)
3826                .replace("%falconContactHPOfferDescriptionPlaceholder%", offer.primaryText2)
3827                .replace("%falconContactHPOfferCTAPlaceholder%", offer.primaryButtonText)
3828                .replace("%falconContactHPOfferIdPlaceholder%", offerDivId);
3829        },
3830        adjustStyles: (containerDivId) => {
3831            if (!containerDivId) return;
3832            const container = $(`#${containerDivId}`).parent();
3833            if (container.hasClass("preffered-border-mastiff")) {
3834                $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivPreffered");
3835            } else {
3836                $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivNonPreffered");
3837            }
3838            $(".contactPageMastiffTemplateDescription").css("margin-bottom", `${$(".contactPageMastiffTemplateContainer").parent().height() - 325}px`);
3839        }
3840    },
3841    "secondary-contact": {
3842        matchCondition: (offer) => offer.templatePosition === "secondary",
3843        containerDivId: "contact_resource_mastiff_template",
3844        parentClass: "support-resource-cards",
3845        templateNumber: "11",
3846        isValid: (offer) => (
3847            isDefined(offer.primaryText1) && isDefined(offer.primaryText2) &&
3848            isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText)
3849        ),
3850        renderTemplate: (offer, offerDivId) => {
3851            return offer.html
3852                .replace("%imageurlPlaceholder%", offer.imageURL)
3853                .replace("%titlePlaceholder%", offer.primaryText1)
3854                .replace("%descriptionPlaceholder%", offer.primaryText2)
3855                .replace("%ctaPlaceholder%", offer.primaryButtonText)
3856                .replace("%secondaryContactHPOfferIdPlaceholder%", offerDivId);
3857        },
3858        adjustStyles: () => { }
3859    },
3860    "phone-support": {
3861        matchCondition: (offer) => offer.category?.startsWith("phone-support") && offer.templatePosition === "primary",
3862        containerDivId: "phone_fee_mastiff_tile_template",
3863        parentClass: "contact-options-container",
3864        templateNumber: "11",
3865        isValid: (offer) => (
3866            isDefined(offer.primaryText1) && isDefined(offer.primaryText2) &&
3867            isDefined(offer.imageURL) && isDefined(offer.storeURL) && isDefined(offer.primaryButtonText)
3868        ),
3869        renderTemplate: (offer, offerDivId) => {
3870            return offer.html
3871                .replace("%falconContactHPImgURLPlaceholder%", offer.imageURL)
3872                .replace("%falconContactHPOfferTitlePlaceholder%", offer.primaryText1)
3873                .replace("%falconContactHPOfferDescriptionPlaceholder%", offer.primaryText2)
3874                .replace("%falconContactHPOfferCTAPlaceholder%", offer.primaryButtonText)
3875                .replace("%falconContactHPOfferIdPlaceholder%", offerDivId);
3876        },
3877        adjustStyles: (containerDivId) => {
3878            if (!containerDivId) return;
3879            const container = $(`#${containerDivId}`).parent();
3880            if (container.hasClass("preffered-border-mastiff")) {
3881                $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivPreffered");
3882            } else {
3883                $(".contactPageMastiffTemplateTextDiv").addClass("contactPageMastiffTemplateTextDivNonPreffered");
3884            }
3885            $(".contactPageMastiffTemplateDescription").css("margin-bottom", `${$(".contactPageMastiffTemplateContainer").parent().height() - 325}px`);
3886        }
3887    },
3888    "warranty-widget": {
3889        matchCondition: (offer) => safeLower(offer.category).startsWith("warranty widget") && safeLower(offer.templatePosition) === "wtywidget",
3890        containerDivId: "mastiff-extend-wty-contact",
3891        parentClass: "device-details-container",
3892        templateNumber: "4",
3893        isValid: (offer) => (
3894            isDefined(offer.html)
3895            && isDefined(offer.storeURL)
3896            && isDefined(offer.primaryButtonText)
3897        ),
3898        renderTemplate: (offer, offerDivId) => {
3899            return offer.html
3900                .replace("{cta}", offer.primaryButtonText)
3901                .replace("{imageurl}", offer.imageURL)
3902                .replace("%simpleLinkTemplateId%", offerDivId)
3903        },
3904        adjustStyles: (containerDivId) => {
3905            if (!containerDivId) return;
3906            const $container = $(`#${containerDivId}`);
3907            if ($container.length > 0) {
3908                $container.children().first().css("margin-top", "0");
3909            }
3910
3911        }
3912    }
3913};
3914
3915function handleContactPageOffers(element) {
3916    const config = Object.values(contactPageConfigs).find(cfg => cfg.matchCondition(element));
3917    if (!config) {
3918        logInfo(`No valid configuration found for contact page offer: ${element.category}`);
3919        return;
3920    }
3921
3922    showOffer(element, config)
3923        .finally(() => {
3924            hideContainer(`#${config.containerDivId}`);
3925        });
3926
3927    async function showOffer(offer, config) {
3928        await waitForElement(`#${config.containerDivId}`, `.${config.parentClass}` || "", 5000);
3929
3930        const offerDivId = `SPOS_${offer.templatePosition}_${offer.name}`;
3931        var LeadOffer = {
3932            OfferID: offerDivId,
3933            OfferClicked: "no",
3934            offerShown: "no",
3935            SPOStemplate: config.templateNumber,
3936        };
3937
3938        if (!config.isValid(offer)) {
3939            logInfo(`Invalid offer content for offer ${offerDivId}`, offer);
3940            LeadOffer.errorData = "Invalid Offer Content";
3941            logToGlobalDataLayer(LeadOffer);
3942            return;
3943        }
3944
3945        const htmlTemplate = config.renderTemplate(offer, offerDivId);
3946
3947        if (!isContainerEmpty(`#${config.containerDivId}`)) {
3948            logInfo(`Skipping offer insertion due to non-empty container: ${config.containerDivId}`);
3949            LeadOffer.errorData = "Container not empty";
3950            logToGlobalDataLayer(LeadOffer);
3951            return;
3952        }
3953
3954        $(`#${config.containerDivId}`).html(htmlTemplate).show().removeClass("hidden");
3955        config.adjustStyles(config.containerDivId);
3956        applyAccessibilityAttributes(offerDivId, offer);
3957        addUrlAndClickEvent(offerDivId, offer);
3958        LeadOffer.offerShown = "yes";
3959        logInfo(`Offer HTML inserted in #${config.containerDivId}`, offer);
3960        logToGlobalDataLayer(LeadOffer);
3961    }
3962}
3963
3964// ---------------- Contact Solution Offer Rendering ----------------
3965function renderContactSolutionOffer(offerElement) {
3966    const divId = `${offerElement.templatePosition}_${offerElement.name}`;
3967
3968    var LeadOffer = {
3969        OfferID: divId,
3970        OfferClicked: "no",
3971        offerShown: "no",
3972        errorData: "",
3973        SPOStemplate: "33"
3974    };
3975
3976    // Validate required fields
3977    if (!(
3978        isDefined(offerElement.primaryText1) &&
3979        isDefined(offerElement.primaryText2) &&
3980        isDefined(offerElement.storeURL) &&
3981        isDefined(offerElement.imageURL) &&
3982        isDefined(offerElement.primaryButtonText)
3983    )) {
3984        LeadOffer.errorData = "Missing Required Fields";
3985        logInfo("Contact Solution offer missing required fields", offerElement);
3986        logToGlobalDataLayer(LeadOffer);
3987        return false;
3988    }
3989
3990    const containerSelector = "#mastiff-pfw-contact-solutions";
3991    return waitForElement(containerSelector, "", 10000)
3992        .then(() => {
3993            if (!isContainerEmpty(containerSelector)) {
3994                LeadOffer.errorData = "Container not empty";
3995                logToGlobalDataLayer(LeadOffer);
3996                logInfo("Contact Solution container not empty; skipping", containerSelector);
3997                return false;
3998            }
3999
4000            var templateHtml = offerElement.html || "";
4001            templateHtml = templateHtml.replace("%{divId}%", divId);
4002            templateHtml = templateHtml.replace("{title}", offerElement.primaryText1 || "");
4003            templateHtml = templateHtml.replace("{description}", offerElement.primaryText2 || "");
4004            templateHtml = templateHtml.replace("{cta}", offerElement.primaryButtonText || "");
4005            templateHtml = templateHtml.replace("{imageurl}", offerElement.imageURL || "");
4006
4007            $(containerSelector).html(templateHtml).removeClass("hidden").show();
4008
4009            // Accessibility
4010            applyAccessibilityAttributes(divId, offerElement);
4011            addUrlAndClickEvent("#" + divId + " .CDCOfferCTA", offerElement, true);
4012
4013            LeadOffer.offerShown = "yes";
4014            logToGlobalDataLayer(LeadOffer);
4015            logInfo("Contact Solution offer rendered", offerElement);
4016            return true;
4017        })
4018        .catch(err => {
4019            logInfo("Contact Solution container not found within timeout", err);
4020            return false;
4021        });
4022}
4023
4024async function showStickyBannerSecondaryOffer(offerElement, containerDivId, offerDivId) {
4025    await waitForElement("#" + containerDivId);
4026
4027    var divId = "";
4028    divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
4029
4030    var LeadOffer = {};
4031    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4032    LeadOffer.OfferID = divId;
4033    LeadOffer.OfferClicked = "no";
4034    LeadOffer.SPOStemplate = "22";
4035
4036    if (
4037        isDefined(offerElement.html) &&
4038        isDefined(offerElement.primaryText1) &&
4039        isDefined(offerElement.primaryButtonText) &&
4040        isDefined(offerElement.storeURL)
4041    ) {
4042
4043        logInfo("offer content available");
4044        if (isContainerEmpty(`#${containerDivId}`) || samePage) {
4045            var html = offerElement.html;
4046            html = html.replace("{title}", offerElement.primaryText1 || "");
4047            html = html.replace("{cta}", offerElement.primaryButtonText || "");
4048            html = html.replace("%stickyFooterOfferId%", divId);
4049
4050            $("#" + containerDivId).show();
4051            $("#" + containerDivId).removeClass('hidden');
4052            $("#" + offerDivId).show();
4053            $("#" + offerDivId).html(html);
4054            LeadOffer.offerShown = "yes";
4055            offerNameForDecline = offerElement.name;
4056
4057            applyAccessibilityAttributes(divId, offerElement);
4058            addUrlAndClickEvent(divId, offerElement);
4059        } else {
4060            LeadOffer.errorData = "SPOS Primary Offer Location is not empty";
4061            LeadOffer.offerShown = "no";
4062        }
4063        logToGlobalDataLayer(LeadOffer);
4064    } else {
4065        logInfo("offer content not available");
4066        LeadOffer.errorData = "No Content Available";
4067        LeadOffer.offerShown = "no";
4068        logToGlobalDataLayer(LeadOffer);
4069    }
4070
4071    hideContainer(`#${containerDivId}`, "hide");
4072}
4073
4074function hideStickyBannerSecondaryOffer_closeAction() {
4075    var offerDeclined = "";
4076    if (pgName === "document") {
4077        hideContainer("#document-mastiff-banner-container", "hide", false);
4078        offerDeclined = $("#document-mastiff-banner-container").find("[data-offer-name]").attr("data-offer-name");
4079    }
4080
4081    if (pgName === "service") {
4082        hideContainer("#sdp-mastiff-banner-container", "hide", false);
4083        offerDeclined = $("#sdp-mastiff-banner-container").find("[data-offer-name]").attr("data-offer-name");
4084    }
4085
4086    if (pgName === "help-windows") {
4087        hideContainer("#mastiff-sticky-banner", "hide", false);
4088        offerDeclined = $("#mastiff-sticky-banner").find("[data-offer-name]").attr("data-offer-name");
4089    }
4090
4091    if (pgName === "drivers_details") {
4092        hideContainer("#mastiff-sticky-banner-swd", "hide", false);
4093        offerDeclined = $("#mastiff-sticky-banner-swd").find("[data-offer-name]").attr("data-offer-name");
4094    }
4095
4096    if (pgName === "repair" || pgName === "hardware-diagnostics") {
4097        hideContainer("#mastiff-sticky-banner-swd", "hide", false);
4098        offerDeclined = $("#mastiff-sticky-banner-swd").find("[data-offer-name]").attr("data-offer-name");
4099    }
4100
4101    offerDeclineEvent(reqObj, offerDeclined);
4102}
4103
4104function hideServiceSecondaryOffer_closeAction() {
4105    hideContainer("#sdp-mastiff-banner-container", "hide", false);
4106    offerDeclineEvent(reqObj, offerNameForDecline);
4107}
4108
4109function showHelpPrimaryOffer(offerElement) {
4110    waitForElement("#mastiff-diag-banner", "", 5000).then(function () {
4111        var divId = "";
4112        divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
4113
4114        var LeadOffer = {};
4115        var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4116        LeadOffer.OfferID = divId;
4117        LeadOffer.OfferClicked = "no";
4118        LeadOffer.SPOStemplate = "15";
4119        if (isDefined(offerElement.html)
4120            && isDefined(offerElement.storeURL)
4121            && isDefined(offerElement.primaryButtonText)
4122            && isDefined(offerElement.primaryText1)
4123            && isDefined(offerElement.primaryText2)
4124            && isDefined(offerElement.imageURL)) {
4125
4126            if (isContainerEmpty("#mastiff-diag-banner")) {
4127                var html = offerElement.html;
4128                html = html.replace("%imageurlPlaceholder%", offerElement.imageURL);
4129                html = html.replace("%titlePlaceholder%", offerElement.primaryText1);
4130                html = html.replace("%descriptionPlaceholder%", offerElement.primaryText2);
4131                html = html.replace("%ctaPlaceholder%", offerElement.primaryButtonText);
4132                html = html.replace("%PrimaryDiagnosticsTabsTileOfferIdPlaceholder%", divId);
4133
4134                $("#mastiff-diag-banner").removeClass("hidden");
4135                $("#mastiff-diag-banner").html(html).show();
4136
4137                allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
4138                applyAccessibilityAttributes(divId, offerElement);
4139                addUrlAndClickEvent(divId, offerElement);
4140                LeadOffer.offerShown = "yes";
4141                logInfo("Help Primary offer HTML inserted", offerElement);
4142            } else {
4143                logInfo("Help Primary offer content location not empty");
4144                LeadOffer.errorData = "Help Primary Offer Location is not empty";
4145                LeadOffer.offerShown = "no";
4146            }
4147            logToGlobalDataLayer(LeadOffer);
4148        } else {
4149            logInfo("Help Primary offer content not available");
4150            LeadOffer.errorData = "No Content Available";
4151            LeadOffer.offerShown = "no";
4152            logToGlobalDataLayer(LeadOffer);
4153        }
4154    }).finally(() => {
4155        hideContainer("#mastiff-diag-banner", "hidden")
4156    });
4157}
4158
4159/**
4160 * Renders OW Diagnostics child offers into .oneRowThreeColumnsContainer under #mastiff-diag-banner.
4161 * Pulls offers whose templatePosition starts with "owDiags" from offerResults,
4162 * sorts by numeric suffix (owDiags_X), and delegates to standardRenderOffer.
4163 */
4164function renderOwDiagnosticsOffers(offerResults) {
4165    if (!offerResults || !offerResults.offers || !offerResults.offers.offer) return;
4166
4167}
4168
4169function handlePDPintentOffer(offerElement) {
4170    const pdpIntentCategoryConfigs = {
4171        "setup-user-guides": {
4172            matchCondition: (offer) => offer.category?.startsWith("setup-user-guides"),
4173            containerDivId: "mastiff_check_available_security_and_software_PDP_setup_user_guides",
4174            parentClass: "setup-user-guide-content",
4175            templateNumber: "2",
4176            renderTemplate: (offer, offerDivId) => {
4177                return offer.html
4178                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText)
4179                    .replace("%simpleButtonTemplateId%", offerDivId);
4180            },
4181            adjustStyles: (offerDivId) => {
4182                $("#" + offerDivId).css("margin-bottom", "2rem");
4183            },
4184        },
4185        "tools-dignostics": {
4186            matchCondition: (offer) => offer.category?.startsWith("tools-dignostics"),
4187            containerDivId: "mastiff_check_available_security_and_software_PDP_product-related-documents",
4188            parentClass: "tools-diagnostics-content",
4189            templateNumber: "2",
4190            renderTemplate: (offer, offerDivId) => {
4191                return offer.html
4192                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText)
4193                    .replace("%simpleButtonTemplateId%", offerDivId);
4194            },
4195            adjustStyles: (offerDivId) => {
4196                $("#" + offerDivId).css("margin-bottom", "2rem");
4197            },
4198        },
4199        "warranty-repair-double": {
4200            matchCondition: (offer) => offer.category?.startsWith("warranty-repair") && offer.category.indexOf("anonymous") === -1,
4201            containerDivId: "mastiff_explore_warranty_options_PDP",
4202            parentClass: "",
4203            templateNumber: offerElement.templatePosition === "shop2" ? "26" : "4",
4204            renderTemplate: (offer, offerDivId) => {
4205                if (offer.templatePosition === "shop2") {
4206                    return offer.html
4207                        .replace("{cta}", offer.primaryButtonText)
4208                        .replace("%PromoTileId%", offerDivId)
4209                        .replace("{imageurl}", offer.imageURL || "")
4210                } else {
4211                    return offer.html
4212                        .replace("{cta}", offer.primaryButtonText)
4213                        .replace("%simpleButtonTemplateId%", offerDivId)
4214                }
4215            },
4216            adjustStyles: (offerDivId) => {
4217
4218            },
4219            multipleOffersSupported: () => true,
4220            initContainer: (containerDivId, offer) => {
4221                const parentContainer = $("#mastiff_explore_warranty_options_PDP");
4222
4223                var customContainer = $(`#custom_warranty_options_container`);
4224                if (customContainer.length === 0) {
4225                    customContainer = $(`<div id="custom_warranty_options_container"> <style> #custom_warranty_options_container { display: flex; gap: 1rem; justify-content: flex-start; flex-wrap: wrap; } @media screen and (max-width: 600px) { #custom_warranty_options_container { flex-direction: column; } } </style> </div>`);
4226                    parentContainer.append(customContainer);
4227                }
4228
4229                const wrapperId = `WRP_${offer.templatePosition}_${offer.name}`;
4230                if (!document.getElementById(wrapperId)) {
4231                    const htmlWrapper = `<div class="intent-offer" id="${wrapperId}"></div>`;
4232                    if (offer.templatePosition === "shop2") {
4233                        customContainer.prepend(htmlWrapper);
4234                    } else {
4235                        customContainer.append(htmlWrapper);
4236                    }
4237                }
4238                customContainer.removeClass("hidden").show();
4239            },
4240            getTargetPlaceholder: (offer) => {
4241                return `WRP_${offer.templatePosition}_${offer.name}`;
4242            }
4243        },
4244
4245        "warranty-repair-anonymous": {
4246            matchCondition: (offer) => offer.category?.startsWith("warranty-repair") && offer.category.indexOf("anonymous") !== -1,
4247            containerDivId: "mastiff_check_available_security_and_software_PDP_warranty_and_repair",
4248            parentClass: "warranty-repair-content",
4249            templateNumber: "2",
4250            renderTemplate: (offer, offerDivId) => {
4251                return offer.html
4252                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText)
4253                    .replace("%simpleButtonTemplateId%", offerDivId);
4254            },
4255            adjustStyles: (offerDivId) => {
4256                $("#" + offerDivId).css("margin-bottom", "2rem");
4257            },
4258        },
4259        "security-viruses": {
4260            matchCondition: (offer) => offer.category?.startsWith("security-viruses"),
4261            containerDivId: "mastiff_check_available_security_and_software_PDP",
4262            parentClass: "parent",
4263            templateNumber: "2",
4264            renderTemplate: (offer, offerDivId) => {
4265                return offer.html
4266                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText)
4267                    .replace("%simpleButtonTemplateId%", offerDivId);
4268            },
4269            adjustStyles: (offerDivId) => {
4270                $("#" + offerDivId).css("margin-bottom", "2rem");
4271            },
4272        },
4273        "ink-paper": {
4274            matchCondition: (offer) => offer.category?.startsWith("ink-paper") && offer.templatePosition != "shop1",
4275            containerDivId: "mastiff_shop_cartridges_PDP",
4276            parentClass: "",
4277            templateNumber: "2",
4278            renderTemplate: (offer, offerDivId) => {
4279                return offer.html
4280                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText)
4281                    .replace("%simpleButtonTemplateId%", offerDivId);
4282            },
4283            adjustStyles: (offerDivId) => {
4284                $("#" + offerDivId).css("margin-bottom", "2rem");
4285            },
4286        },
4287        "ink-paper-multiple": {
4288            matchCondition: (offer) => offer.category?.startsWith("ink-paper") && offer.templatePosition === "shop1",
4289            containerDivId: "mastiff_shop_cartridges_PDP",
4290            parentClass: "",
4291            templateNumber: "23",
4292            renderTemplate: (offer, offerDivId) => {
4293                return offer.html
4294                    .replace("%{title}%", offer.primaryText1)
4295                    .replace("%{description}%", offer.primaryText2)
4296                    .replace("%{imageurl}%", offer.imageURL)
4297                    .replace("%{cta}%", offer.primaryButtonText)
4298                    .replace("%simpleButtonTemplateId%", offerDivId);
4299            },
4300            adjustStyles: (offerDivId) => {
4301                $("#" + offerDivId).css("display", "flex");
4302            },
4303            multipleOffersSupported: (offer) => offer.templatePosition === "shop1",
4304            initContainer: (containerDivId) => {
4305                const flexId = "InkPaperOffersFlexContainer";
4306                if (!document.getElementById(flexId)) {
4307                    const InkPaperContainer = `<div id=${flexId} class=InkPaperOffersContainer> <style> .InkPaperOffersContainer { display: flex; flex-wrap: wrap; } .InkPaperOfferTile { flex-direction: column; align-items: center; width: calc(49% - 18px); background: #fff; box-shadow: 0 1px 4px 1px #21212133; border-radius: 16px; margin: 1.5%; display: none; } .InkPaperOfferTile .troubleshootingOfferCTA { background-color: #0278AB !important; color: #fff !important; border: none; padding: 9px 21px !important; } .InkPaperOfferTile .troubleshootingOfferCTA:hover { background-color: #035C84 !important; border: none; color: #fff !important; } .InkPaperOfferTile .troubleshootingOfferCTA:active, .InkPaperOfferTile .troubleshootingOfferCTA:focus { background-color: #015985 !important; border: none; color: #fff !important; } @media screen and (max-width : 600px) { .InkPaperOffersContainer { flex-direction: column; } .InkPaperOfferTile { width: 100%; margin: 0px; margin-bottom: 10px; } } </style> </div>`;
4308                    $(`#${containerDivId}`).append(InkPaperContainer).removeClass("hidden").show();
4309                }
4310            },
4311            getTargetPlaceholder: (offer) => {
4312                const wrapperId = `WRP_${offer.templatePosition}_${offer.name}`;
4313                const container = $("#InkPaperOffersFlexContainer");
4314
4315                if (!document.getElementById(wrapperId)) {
4316                    const wrapper = `<div class="InkPaperOfferTile" id="${wrapperId}"></div>`;
4317                    container.append(wrapper);
4318                }
4319
4320                return wrapperId;
4321            }
4322        },
4323        "troubleshooting": {
4324            matchCondition: (offer) => offer.category?.startsWith("troubleshooting"),
4325            containerDivId: "Mastiff_Troubleshooting",
4326            parentClass: "",
4327            templateNumber: "2",
4328            renderTemplate: (offer, offerDivId) => {
4329                const containerSelector = `#${pdpIntentCategoryConfigs["troubleshooting"].containerDivId}`;
4330                const templateContainer = document.createElement("div");
4331                templateContainer.innerHTML = offer.html;
4332
4333                const templateDiv = templateContainer.querySelector(".troubleshootingOfferTemplate") || templateContainer.querySelector("div");
4334
4335                templateDiv.innerHTML = templateDiv.innerHTML
4336                    .replace("%simpleButtonTemplateId%", offerDivId)
4337                    .replace("%simpleButtonTemplateCTAPlaceholder%", offer.primaryButtonText);
4338
4339                waitForElement(containerSelector, ".option-details", 5000).then(() => {
4340                    const container = document.querySelector(containerSelector);
4341
4342                    const optionCard = document.querySelector(".option-card");
4343                    if (optionCard) {
4344                        const ngContentAttr = optionCard.getAttributeNames().find(name =>
4345                            name.startsWith("_ngcontent")
4346                        );
4347                        if (ngContentAttr) {
4348                            container.setAttribute(ngContentAttr, "");
4349                        }
4350                    }
4351
4352                    const redictionTxt = document.querySelector(".rediction-txt");
4353                    if (redictionTxt?.firstChild) {
4354                        const redictionTxtCopy = redictionTxt.cloneNode(true);
4355                        copyStyles(redictionTxt.firstChild, redictionTxtCopy.firstChild);
4356                        templateDiv.appendChild(redictionTxtCopy);
4357                    }
4358                });
4359
4360                return templateDiv;
4361            },
4362            adjustStyles: (offerDivId) => {
4363                $("#" + offerDivId).css("display", "flex");
4364            },
4365        },
4366    };
4367
4368    const categoryConfig = Object.values(pdpIntentCategoryConfigs).find(cfg => cfg.matchCondition(offerElement)) || null;
4369
4370    showIntentOffer(offerElement, categoryConfig);
4371
4372
4373    async function showIntentOffer(offerElement, categoryConfig) {
4374        const offerDivId = `SPOS_${offerElement.templatePosition}_${offerElement.name}`;
4375
4376        var LeadOffer = {};
4377        LeadOffer.OfferID = offerDivId;
4378        LeadOffer.OfferClicked = "no";
4379
4380        if (!offerElement || !categoryConfig) {
4381            logInfo(`Invalid offer or category config for category: ${offerElement.category}`);
4382            LeadOffer.errorData = "Invalid Offer or Category Config";
4383            LeadOffer.offerShown = "no";
4384            logToGlobalDataLayer(LeadOffer);
4385            hideIntentBasedOffer();
4386            return;
4387        }
4388
4389        const {
4390            containerDivId,
4391            parentClass,
4392            templateNumber,
4393            renderTemplate,
4394            adjustStyles,
4395            multipleOffersSupported,
4396            initContainer,
4397            getTargetPlaceholder
4398        } = categoryConfig;
4399
4400        LeadOffer.SPOStemplate = templateNumber;
4401
4402        var multipleOffers = typeof multipleOffersSupported === "function"
4403            ? multipleOffersSupported(offerElement)
4404            : multipleOffersSupported || false;
4405
4406        var targetContainerId = containerDivId;
4407
4408        if (!isDefined(offerElement.storeURL) || !isDefined(offerElement.primaryButtonText) || !isDefined(offerElement.html)) {
4409            logInfo(`Offer missing required fields for category: ${offerElement.category}`);
4410            LeadOffer.errorData = "No Content Available";
4411            LeadOffer.offerShown = "no";
4412            logToGlobalDataLayer(LeadOffer);
4413            hideIntentBasedOffer();
4414            return;
4415        }
4416
4417        try {
4418            await waitForElement(`#${targetContainerId}
4418`, ".option-details", 5000);
4419        } catch (error) {
4420            logInfo(error);
4421            LeadOffer.errorData = "Placeholder " + targetContainerId + " not found";
4422            LeadOffer.offerShown = "no";
4423            logToGlobalDataLayer(LeadOffer);
4424            hideIntentBasedOffer();
4425            return;
4426        }
4427
4428        if (multipleOffers) {
4429            if (typeof initContainer === "function") {
4430                initContainer(containerDivId, offerElement);
4431            }
4432
4433            if (typeof getTargetPlaceholder === "function") {
4434                const placeholder = getTargetPlaceholder(offerElement);
4435                if (!placeholder) {
4436                    LeadOffer.errorData = "No available ink-paper placeholders";
4437                    LeadOffer.offerShown = "no";
4438                    logToGlobalDataLayer(LeadOffer);
4439                    hideIntentBasedOffer();
4440                    return;
4441                }
4442                targetContainerId = placeholder;
4443            }
4444        }
4445
4446        if (intentBasedLocationEmpty || multipleOffers) {
4447            const htmlTemplate = renderTemplate(offerElement, offerDivId);
4448
4449            $(`#${targetContainerId}`).html(htmlTemplate).show();
4450
4451            adjustStyles(targetContainerId);
4452
4453            if (isDefined(parentClass) && parentClass !== "parent") {
4454                $(`.${parentClass}`).removeClass("hidden");
4455            }
4456
4457            $(`#${targetContainerId}`).removeClass("hidden");
4458
4459            applyAccessibilityAttributes(offerDivId, offerElement);
4460
4461            addUrlAndClickEvent(offerDivId, offerElement);
4462
4463            LeadOffer.offerShown = "yes";
4464            logInfo(`Offer rendered successfully for category: ${offerElement.category}`);
4465            if (!multipleOffers && document.getElementById(offerDivId)) {
4466                intentBasedLocationEmpty = false;
4467            }
4468        } else {
4469            logInfo("Intent Based Location is not empty", offerElement);
4470            LeadOffer.errorData = "Intent Based Location is not empty";
4471            LeadOffer.offerShown = "no";
4472            hideIntentBasedOffer();
4473        }
4474
4475        logToGlobalDataLayer(LeadOffer);
4476
4477        function hideIntentBasedOffer() {
4478            if (intentBasedLocationEmpty) {
4479                if (isDefined(parentClass)) {
4480                    if ((parentClass) === "parent") {
4481                        hideContainer(`#${targetContainerId}`, "hideparent", false);
4482                    } else {
4483                        $(`.${parentClass}`).hide();
4484                    }
4485                } else {
4486                    $(`#${targetContainerId}`).hide();
4487                }
4488            }
4489        }
4490
4491        if (!multipleOffers) hideIntentBasedOffer();
4492    }
4493}
4494
4495function copyStyles(sourceElement, targetElement) {
4496    const styles = getComputedStyle(sourceElement);
4497    for (const property in styles) {
4498        if (styles.hasOwnProperty(property)) {
4499            targetElement.style[property] = styles[property];
4500        }
4501    }
4502}
4503
4504function showPromoTabOffer() {
4505    waitForElement("#mastiff_promotions_and_deals_PDP", ".support-options");
4506
4507    if (offerResults.offerCount > 0) {
4508
4509        if (promoTitle[reqObj.user.language] !== undefined) {
4510            promoTab = promoTab.replace(/Promotions\s&\sdeals/, promoTitle[reqObj.user.language])
4511        }
4512        for (i = 0; i < offerResults.offerCount; i++) {
4513            var element = offerResults.offers.offer[i];
4514            if ((element.templatePosition === "primary" || element.templatePosition === "secondary") && !isDefined(element.category)) {
4515                var divId = "";
4516                divId = divId.concat("SPOS_", element.templatePosition, "_", element.name);
4517                var LeadOffer = {};
4518                var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4519                LeadOffer.OfferID = divId;
4520                LeadOffer.OfferClicked = "no";
4521                LeadOffer.SPOStemplate = "2";
4522
4523                if (
4524                    isDefined(element.html) &&
4525                    isDefined(element.primaryText1) &&
4526                    isDefined(element.primaryText2) &&
4527                    isDefined(element.primaryButtonText) &&
4528                    isDefined(element.storeURL)
4529                ) {
4530
4531                    var htmlTemplate = element.html;
4532                    if (element.templatePosition === "primary") {
4533
4534                        if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) {
4535                            $("#mastiff_promotions_and_deals_PDP").append(promoTab);
4536                        }
4537                        if (isContainerEmpty(".promoPrimaryTile")) {
4538                            htmlTemplate = htmlTemplate.replace("%PromoTileImgURLPlaceholder%", element.imageURL);
4539                            htmlTemplate = htmlTemplate.replace("%PromoTileTitlePlaceholder%", element.primaryText1);
4540                            htmlTemplate = htmlTemplate.replace("%PromoTileDescriptionPlaceholder%", element.primaryText2);
4541                            htmlTemplate = htmlTemplate.replace("%PromoTileCTAPlaceholder%", element.primaryButtonText);
4542                            htmlTemplate = htmlTemplate.replace("%PromoTileId%", divId);
4543                            $(".promoPrimaryTile").html(htmlTemplate);
4544
4545                            allocateRecEngPrices(element.strikePrice, element.incartPrice, divId, element.currency);
4546
4547                            LeadOffer.offerShown = "yes";
4548                            applyAccessibilityAttributes(divId, element);
4549                            addUrlAndClickEvent(divId, element);
4550                        } else {
4551                            LeadOffer.errorData = "Primary Location is not empty";
4552                            LeadOffer.offerShown = "no";
4553                        }
4554                        logToGlobalDataLayer(LeadOffer);
4555                    } else if (element.templatePosition === "secondary") {
4556                        if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) {
4557                            $("#mastiff_promotions_and_deals_PDP").append(promoTab);
4558                        }
4559                        if (isContainerEmpty(".promoSecondaryTile")) {
4560                            htmlTemplate = htmlTemplate.replace("%PromoTileImgURLPlaceholder%", element.imageURL);
4561                            htmlTemplate = htmlTemplate.replace("%PromoTileTitlePlaceholder%", element.primaryText1);
4562                            htmlTemplate = htmlTemplate.replace("%PromoTileDescriptionPlaceholder%", element.primaryText2);
4563                            htmlTemplate = htmlTemplate.replace("%PromoTileCTAPlaceholder%", element.primaryButtonText);
4564                            htmlTemplate = htmlTemplate.replace("%PromoTileId%", divId);
4565                            $(".promoSecondaryTile").html(htmlTemplate);
4566
4567                            allocateRecEngPrices(element.strikePrice, element.incartPrice, divId, element.currency);
4568
4569                            LeadOffer.offerShown = "yes";
4570
4571                            applyAccessibilityAttributes(divId, element);
4572                            addUrlAndClickEvent(divId, element);
4573                        } else {
4574                            LeadOffer.errorData = "Secondary Location is not empty";
4575                            LeadOffer.offerShown = "no";
4576                        }
4577
4578                        logToGlobalDataLayer(LeadOffer);
4579                    }
4580                }
4581                else {
4582                    LeadOffer.errorData = "No Content Available";
4583                    LeadOffer.offerShown = "no";
4584                    logToGlobalDataLayer(LeadOffer);
4585                }
4586            } else if (element.templatePosition === "shop1" || element.templatePosition === "shop2" || element.templatePosition === "shop3") {
4587                enablepdpCarousel = true;
4588            }
4589        }
4590
4591    }
4592    if (enablepdpCarousel) {
4593        showPromoShopOffers();
4594    }
4595
4596}
4597
4598function showPromoShopOffers() {
4599    enablepdpCarousel = false;
4600    var elements = offerResults.offers.offer;
4601    var shopPositions = ["shop1", "shop2", "shop3"];
4602    var sortedElements = elements.filter(element => shopPositions.includes(element.templatePosition) && element.category === null);
4603    sortedElements.sort((a, b) => shopPositions.indexOf(a.templatePosition) - shopPositions.indexOf(b.templatePosition));
4604
4605    if (isContainerEmpty(".promoCarouselOffer")) {
4606        for (i = 0; i < sortedElements.length; i++) {
4607            PromoShopOfferContent(sortedElements[i], "Missing");
4608        }
4609    } else {
4610        for (j = 1; j < 4; j++) {
4611            var getIndex = num => $(`div[id^="shop${num}"].promoCarouselOffer`).first().index('.promoCarouselOffer');
4612            var firstShopIndex = getIndex(j) > -1 ? getIndex(j) : j === 1 && (getIndex(2) > -1 || getIndex(3) > -1) ? 0 : j === 2 && getIndex(3) > -1 ? getIndex(3) : "Missing";
4613            var sortedShopElements = sortedElements.filter(sortedElement => (`shop${j}`).includes(sortedElement.templatePosition));
4614            for (i = 0; i < sortedShopElements.length; i++) {
4615                PromoShopOfferContent(sortedShopElements[i], (firstShopIndex !== "Missing" ? firstShopIndex + i : "Missing"));
4616            }
4617        }
4618    }
4619
4620    if ($(".promoCarousel").length) {
4621        if (document.getElementsByClassName("promoCarouselOffer").length === 1) {
4622            var navigationDiv = document.getElementById('navigation');
4623            navigationDiv.style.display = "none";
4624        }
4625        $("#SPOS_navLeft").keypress(function (event) {
4626            var code = event.keyCode || event.which;
4627            if (code === 13) {
4628                nextSlide(-1);
4629            }
4630        });
4631        $("#SPOS_navRight").keypress(function (event) {
4632            var code = event.keyCode || event.which;
4633            if (code === 13) {
4634                nextSlide(1);
4635            }
4636        });
4637        sliderClassName = "promoCarouselOffer";
4638        navBulletAvailable = false;
4639        displaySlides(slide_index);
4640    }
4641
4642}
4643
4644function PromoShopOfferContent(offerElement, firstIndex) {
4645    var divId = "";
4646    divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name);
4647    var LeadOffer = {};
4648    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4649    LeadOffer.OfferID = divId;
4650    LeadOffer.OfferClicked = "no";
4651    LeadOffer.SPOStemplate = "2";
4652
4653    if (
4654        isDefined(offerElement.html) &&
4655        isDefined(offerElement.primaryText1) &&
4656        isDefined(offerElement.primaryButtonText) &&
4657        isDefined(offerElement.storeURL) &&
4658        isDefined(offerElement.imageURL)
4659    ) {
4660        var htmlTemplate = offerElement.html;
4661        if (isContainerEmpty("#mastiff_promotions_and_deals_PDP")) {
4662            $("#mastiff_promotions_and_deals_PDP").append(promoTab);
4663        }
4664        enablePromoTab = true;
4665        if (!$('.promoCarousel').length || isContainerEmpty('.promoOffers')) {
4666            $(".promoOffers").prepend(promoShopOfferSliderDiv);
4667        }
4668
4669        htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferImgURLPlaceholder%", offerElement.imageURL || "");
4670        htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferTitlePlaceholder%", offerElement.primaryText1 || "");
4671        htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferDescriptionPlaceholder%", offerElement.primaryText2 || "");
4672        htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferCTAPlaceholder%", offerElement.primaryButtonText || "");
4673        htmlTemplate = htmlTemplate.replace("%PromoCarouselOfferId%", divId);
4674
4675        if (!isContainerEmpty('.promoCarousel')) {
4676            if (firstIndex !== "Missing") {
4677                $(htmlTemplate).insertBefore($('.promoCarouselOffer').eq(firstIndex));
4678            } else {
4679                $(".promoCarousel").append(htmlTemplate);
4680            }
4681        }
4682
4683        allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
4684
4685        $("#" + divId).find('a').attr({ title: offerElement.primaryButtonText, alt: offerElement.offerType });
4686        LeadOffer.offerShown = "yes";
4687        // To Be Reviewed
4688        //if (isDefined(offerElement.imageURL)) {
4689        //    $("#" + divId).attr('style', "color: #212121 !important");
4690        //} else {
4691        $("#" + divId).find('img').attr({ title: offerElement.primaryButtonText, alt: offerElement.offerType });
4692        //}
4693        if (reqObj.user.language === "ar" || reqObj.user.language === "he")
4694            $(".promoCarouselOffer").css("text-align", "right").eq();
4695        $("#" + divId).attr("aria-label", offerElement.offerType);
4696        $("#" + divId).attr("tabindex", 0);
4697        addUrlAndClickEvent(divId, offerElement);
4698    } else {
4699        LeadOffer.errorData = "No Content Available";
4700        LeadOffer.offerShown = "no";
4701    }
4702
4703    logToGlobalDataLayer(LeadOffer);
4704}
4705
4706var promoTitle = {
4707    "es": "Promociones y ofertas",
4708    "pt": "Promoções e ofertas",
4709    "fr": "Promotions et offres",
4710    "nl": "Promoties en deals",
4711    "bg": "Промоции и оферти",
4712    "cs": "Promoce a nabídky",
4713    "hr": "Promocije i ponude",
4714    "da": "Kampagner og tilbud",
4715    "de": "Aktionen & Angebote",
4716    "et": "Kampaaniad ja pakkumised",
4717    "el": "Προσφορές και εκπτώσεις",
4718    "he": "מבצעים והטבות",
4719    "it": "Promozioni e offerte",
4720    "kk": "Жарнамалар және дейінділер",
4721    "lv": "Akcijas un piedāvājumi",
4722    "lt": "Akcijos ir pasiūlymai",
4723    "hu": "Akciók és ajánlatok",
4724    "ar": "العروض والفرص",
4725    "no": "Kampanjer og tilbud",
4726    "pl": "Promocje i oferty",
4727    "ro": "Promoții și oferte",
4728    "sr": "Promocije i ponude",
4729    "sk": "Akcie a ponuky",
4730    "sl": "Promocije in ponudbe",
4731    "fi": "Tarjoukset ja diilit",
4732    "sv": "Kampanjer och erbjudanden",
4733    "tr": "Promosyonlar ve fırsatlar",
4734    "uk": "Акції та пропозиції",
4735    "zh": "促销和优惠",
4736    "id": "Promosi & deal",
4737    "ja": "プロモーション&お得な情報",
4738    "ko": "프로모션 및 거래",
4739    "ms": "Promosi & tawaran",
4740    "fil": "Promosyon at mga deal",
4741    "th": "โปรโมชั่นและดีล",
4742    "vi": "Khuyến mãi & Ưu đãi"
4743};
4744
4745function showViewInStoreOffer(offerElement) {
4746    var divId = "";
4747    divId = divId.concat("Store_SPOS_", offerElement.templatePosition, "_", offerElement.name);
4748
4749    var LeadOffer = {};
4750    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4751    LeadOffer.OfferID = divId;
4752    LeadOffer.OfferClicked = "no";
4753    LeadOffer.SPOStemplate = "15";
4754    if (
4755        isDefined(offerElement.html) &&
4756        isDefined(offerElement.primaryButtonText) &&
4757        isDefined(offerElement.storeURL)
4758    ) {
4759        var htmlTemplate = offerElement.html;
4760        if (isContainerEmpty("#mastiff_view_in_store_PDP")) {
4761            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateImgURL%", offerElement.imageURL || "");
4762            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", offerElement.primaryButtonText || "");
4763            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId);
4764
4765            $("#mastiff_view_in_store_PDP").html(htmlTemplate);
4766
4767            $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" });
4768
4769            LeadOffer.offerShown = "yes";
4770            applyAccessibilityAttributes(divId, offerElement);
4771            addUrlAndClickEvent(divId, offerElement);
4772
4773        } else {
4774            LeadOffer.errorData = "View In Store Location is not empty";
4775            LeadOffer.offerShown = "no";
4776        }
4777        logToGlobalDataLayer(LeadOffer);
4778    } else {
4779        LeadOffer.errorData = "No Content Available";
4780        LeadOffer.offerShown = "no";
4781
4782        logToGlobalDataLayer(LeadOffer);
4783    }
4784}
4785
4786function showCarouselBanner(primaryOfferElement) {
4787    var divId = "";
4788    divId = divId.concat(primaryOfferElement.templatePosition, "_", primaryOfferElement.name);
4789
4790    var LeadOffer = {};
4791    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4792    LeadOffer.OfferID = divId;
4793    LeadOffer.OfferClicked = "no";
4794    if (pgName.indexOf("home") > -1)
4795        LeadOffer.SPOStemplate = "7";
4796    else if (pgName === "contact_closure")
4797        LeadOffer.SPOStemplate = "11";
4798    if (
4799        isDefined(primaryOfferElement.html) &&
4800        isDefined(primaryOfferElement.imageURL) &&
4801        isDefined(primaryOfferElement.primaryText1) &&
4802        isDefined(primaryOfferElement.primaryButtonText) &&
4803        isDefined(primaryOfferElement.storeURL)
4804    ) {
4805        var htmlTemplate = primaryOfferElement.html;
4806        var html = "";
4807        html = html.concat("<div id=\"", divId, "\">", htmlTemplate, "</div>");
4808        if (isContainerEmpty('.mastiff_template_container')) {
4809            html = html.replace("%LargeBannerImgPlaceholder%", primaryOfferElement.imageURL || "");
4810            html = html.replace("%LargeBannerTitleplaceholder%", primaryOfferElement.primaryText1 || "");
4811            html = html.replace("%LargeBannerDescriptionplaceholder%", primaryOfferElement.primaryText2 || "");
4812            html = html.replace("%LargeBannerCTAplaceholder%", "\"" + (primaryOfferElement.primaryButtonText || "") + "\"");
4813            html = html.replace("%LargeBannerCTAplaceholder%", primaryOfferElement.primaryButtonText || "");
4814
4815            $(".mastiff_template_container").html(html);
4816
4817            LeadOffer.offerShown = "yes";
4818            if (reqObj.user.language === "ar" || reqObj.user.language === "he") {
4819                $("#LargeBannerContent").css("text-align", "left !important");
4820                $("#LargeBannerContent").css("float", "left");
4821                $("#LargeBannerContent").addClass("arabicContent");
4822            }
4823            $("#" + divId).attr("aria-label", primaryOfferElement.offerType);
4824            $("#LargeBannerTemplate").attr("tabindex", 0);
4825            $(".LargeBannerCTADiv").attr("tabindex", 0);
4826
4827            addUrlAndClickEvent(`#${divId} .LargeBannerCTADiv`, primaryOfferElement, /* openLinkInNewTab: */ true);
4828            applyAccessibilityAttributes(`#${divId} .LargeBannerCTADiv`, primaryOfferElement);
4829
4830            logInfo("Carousel Banner - Offer displayed successfully", ".mastiff_template_container");
4831        } else {
4832            LeadOffer.errorData = "Large banner Location is not empty";
4833            LeadOffer.offerShown = "no";
4834        }
4835        logToGlobalDataLayer(LeadOffer);
4836
4837    } else {
4838        LeadOffer.errorData = "No Content Available";
4839        LeadOffer.offerShown = "no";
4840        logToGlobalDataLayer(LeadOffer);
4841    }
4842}
4843
4844function showContactSummaryOffer(contactSumOfferElement) {
4845    var divId = "";
4846    divId = divId.concat(contactSumOfferElement.templatePosition, "_", contactSumOfferElement.name);
4847
4848    var LeadOffer = {};
4849    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4850    LeadOffer.OfferID = divId;
4851    LeadOffer.OfferClicked = "no";
4852    LeadOffer.SPOStemplate = "16";
4853    if (
4854        isDefined(contactSumOfferElement.html) &&
4855        isDefined(contactSumOfferElement.primaryButtonText) &&
4856        isDefined(contactSumOfferElement.storeURL)
4857    ) {
4858        var htmlTemplate = contactSumOfferElement.html;
4859        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", contactSumOfferElement.primaryButtonText);
4860        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", contactSumOfferElement.storeURL);
4861        htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId);
4862
4863        $("#contact-summary-warranty-mastiff").append(htmlTemplate);
4864        LeadOffer.offerShown = "yes";
4865        applyAccessibilityAttributes(divId, contactSumOfferElement);
4866        addUrlAndClickEvent(divId, contactSumOfferElement);
4867        logToGlobalDataLayer(LeadOffer);
4868    } else {
4869        LeadOffer.errorData = "No Content Available";
4870        LeadOffer.offerShown = "no";
4871        $("#contact-summary-warranty-mastiff").hide();
4872        logToGlobalDataLayer(LeadOffer);
4873    }
4874}
4875
4876async function showWtyPrimaryOffer(wtyPrimaryOfferElement) {
4877    await waitForElement("#mastiff-check-warranty-primary-offer");
4878
4879    var divId = "";
4880    divId = divId.concat(wtyPrimaryOfferElement.templatePosition, "_", wtyPrimaryOfferElement.name);
4881
4882    var LeadOffer = {};
4883    LeadOffer.OfferID = divId;
4884    LeadOffer.OfferClicked = "no";
4885    LeadOffer.SPOStemplate = "13";
4886
4887    if (
4888        isDefined(wtyPrimaryOfferElement.html) &&
4889        isDefined(wtyPrimaryOfferElement.primaryText1) &&
4890        isDefined(wtyPrimaryOfferElement.primaryButtonText) &&
4891        isDefined(wtyPrimaryOfferElement.storeURL)
4892    ) {
4893        var htmlTemplate = wtyPrimaryOfferElement.html;
4894        if (isContainerEmpty("#mastiff-check-warranty-primary-offer")) {
4895            htmlTemplate = htmlTemplate.replace("%WRPrimaryTileTitleplaceholder%", wtyPrimaryOfferElement.primaryText1 || "");
4896            htmlTemplate = htmlTemplate.replace("%WRPrimaryTileDescriptionplaceholder%", wtyPrimaryOfferElement.primaryText2 || "");
4897            htmlTemplate = htmlTemplate.replace("%WRPrimaryTileCTAplaceholder%", wtyPrimaryOfferElement.primaryButtonText || "");
4898            htmlTemplate = htmlTemplate.replace("%WRPrimaryTileCTAId%", divId);
4899
4900            $("#mastiff-check-warranty-primary-offer").append(htmlTemplate);
4901            $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden");
4902
4903            $(".WRPrimaryTile").css("margin-top", "20px");
4904            LeadOffer.offerShown = "yes";
4905
4906            applyAccessibilityAttributes(divId, wtyPrimaryOfferElement);
4907
4908            addUrlAndClickEvent(divId, wtyPrimaryOfferElement);
4909        } else {
4910            LeadOffer.errorData = "Primary Location is not empty";
4911            LeadOffer.offerShown = "no";
4912        }
4913        logToGlobalDataLayer(LeadOffer);
4914
4915    } else {
4916        LeadOffer.errorData = "No Content Available";
4917        LeadOffer.offerShown = "no";
4918        logToGlobalDataLayer(LeadOffer);
4919    }
4920}
4921
4922async function showWtySecondaryOffer(wtySecondaryOfferElement) {
4923
4924    await waitForElement("#warrantyoptions", ".warranty-details");
4925
4926    var divId = "";
4927    divId = divId.concat(wtySecondaryOfferElement.templatePosition, "_", wtySecondaryOfferElement.name);
4928
4929    var LeadOffer = {};
4930    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
4931    LeadOffer.OfferID = divId;
4932    LeadOffer.OfferClicked = "no";
4933    LeadOffer.SPOStemplate = "15";
4934    if (
4935        isDefined(wtySecondaryOfferElement.html) &&
4936        isDefined(wtySecondaryOfferElement.primaryButtonText) &&
4937        isDefined(wtySecondaryOfferElement.storeURL)
4938    ) {
4939        var htmlTemplate = wtySecondaryOfferElement.html;
4940        var html = "";
4941        if (isContainerEmpty("#warrantyoptions")) {
4942            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", wtySecondaryOfferElement.primaryButtonText);
4943            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateURL%", wtySecondaryOfferElement.storeURL);
4944            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId);
4945
4946            $("#warrantyoptions").append(htmlTemplate);
4947            $(".simpleLinkTemplate").css("margin-top", "20px");
4948            LeadOffer.offerShown = "yes";
4949            applyAccessibilityAttributes(divId, wtySecondaryOfferElement);
4950            addUrlAndClickEvent(divId, wtySecondaryOfferElement);
4951        } else {
4952            LeadOffer.errorData = "Secondary Location is not empty";
4953            LeadOffer.offerShown = "no";
4954        }
4955        logToGlobalDataLayer(LeadOffer);
4956    } else {
4957        LeadOffer.errorData = "No Content Available";
4958        LeadOffer.offerShown = "no";
4959        //window.optRevertHpOffer();
4960        logToGlobalDataLayer(LeadOffer);
4961    }
4962
4963
4964}
4965
4966function showWtyShopOffers() {
4967    waitForElement("#mastiff-check-warranty-secondary-offers");
4968    var shop1PositionElement = offerResults.offers.offer.filter(function (x) {
4969        return x.templatePosition === "shop1" && !x.OWTileOffer;
4970    })[0];
4971    var shop2PositionElement = offerResults.offers.offer.filter(function (x) {
4972        return x.templatePosition === "shop2" && !x.OWTileOffer;
4973    })[0];
4974    var shop3PositionElement = offerResults.offers.offer.filter(function (x) {
4975        return x.templatePosition === "shop3" && !x.OWTileOffer;
4976    })[0];
4977
4978    if (shop1PositionElement != null) {
4979        wtyShopOfferContent(shop1PositionElement);
4980    }
4981    if (shop2PositionElement != null) {
4982        wtyShopOfferContent(shop2PositionElement);
4983    }
4984    if (shop3PositionElement != null) {
4985        wtyShopOfferContent(shop3PositionElement);
4986    }
4987
4988
4989    if (document.getElementsByClassName("WRSecondaryTile").length == 1) {
4990        var navigationDiv = document.getElementById('navigation');
4991        navigationDiv.style.display = "none";
4992    }
4993
4994    $(".WRSecondarySlidercontainer").css("margin-top", "20px");
4995    $(".WRSecondarySlidercontainer").css("margin-bottom", "20px");
4996    $("#navLeft").keypress(function (event) {
4997        var code = event.keyCode || event.which;
4998        if (code == 13) {
4999            nextSlide(-1);
5000        }
5001    });
5002    $("#navRight").keypress(function (event) {
5003        var code = event.keyCode || event.which;
5004        if (code == 13) {
5005            nextSlide(1);
5006        }
5007    });
5008    sliderClassName = "WRSecondaryTile";
5009    navBulletAvailable = false;
5010    displaySlides(slide_index);
5011
5012}
5013
5014function wtyShopOfferContent(offerElement) {
5015    var divId = "";
5016    divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
5017    var LeadOffer = {};
5018    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
5019    LeadOffer.OfferID = divId;
5020    LeadOffer.OfferClicked = "no";
5021    LeadOffer.SPOStemplate = "14";
5022    if (
5023        isDefined(offerElement.html) &&
5024        isDefined(offerElement.primaryText1) &&
5025        isDefined(offerElement.primaryButtonText) &&
5026        isDefined(offerElement.storeURL)
5027    ) {
5028        var htmlTemplate = offerElement.html;
5029        if (isContainerEmpty("#mastiff-check-warranty-secondary-offers")) {
5030            $("#mastiff-check-warranty-secondary-offers").append(wtyShopOfferSliderDiv);
5031            $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden");
5032        }
5033        htmlTemplate = htmlTemplate.replace("%WRSecondaryTileTitleplaceholder%", offerElement.primaryText1 || "");
5034        htmlTemplate = htmlTemplate.replace("%WRSecondaryTileDescriptionplaceholder%", offerElement.primaryText2 || "");
5035        htmlTemplate = htmlTemplate.replace("%WRSecondaryTileCTAplaceholder%", offerElement.primaryButtonText || "");
5036        htmlTemplate = htmlTemplate.replace("%WRSecondaryTileCTAId%", divId);
5037
5038        $(".WRSecondarySlidercontainer").append(htmlTemplate);
5039
5040        allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
5041
5042        LeadOffer.offerShown = "yes";
5043
5044        applyAccessibilityAttributes(divId, offerElement);
5045        addUrlAndClickEvent(divId, offerElement);
5046    } else {
5047        LeadOffer.errorData = "No Content Available";
5048        LeadOffer.offerShown = "no";
5049    }
5050
5051    logToGlobalDataLayer(LeadOffer);
5052}
5053
5054async function showWtyQuizInitiatorOffer(offerElement) {
5055    await waitForElement("#mastiff-check-warranty-primary-offer");
5056
5057    const divId = `${offerElement.templatePosition}_${offerElement.name}`;
5058
5059    const LeadOffer = {
5060        OfferID: divId,
5061        OfferClicked: "no",
5062        SPOStemplate: "27"
5063    };
5064    const GDLOfferName = "LeadOffer" + LeadOfferIndex;
5065
5066    const hasValidContent =
5067        isDefined(offerElement.primaryText1) &&
5068        isDefined(offerElement.primaryText2) &&
5069        isDefined(offerElement.primaryButtonText) &&
5070        isDefined(offerElement.storeURL);
5071
5072    if (hasValidContent) {
5073        const title = offerElement.primaryText1 || "";
5074        const description = offerElement.primaryText2 || "";
5075        const cta = offerElement.primaryButtonText || "";
5076
5077        var htmlTemplate = offerElement.html;
5078        htmlTemplate = htmlTemplate.replace("{title}", title);
5079        htmlTemplate = htmlTemplate.replace("{description}", description);
5080        htmlTemplate = htmlTemplate.replace("{cta}", cta);
5081        htmlTemplate = htmlTemplate.replace("%sposQuizInitiatorCTATwoId%", divId);
5082        $("#mastiff-check-warranty-primary-offer").append(htmlTemplate);
5083        $("#mastiff-check-warranty-primary-offer").css("margin-top", "20px");
5084        $('.WRPrimaryTile').hide();
5085
5086        applyAccessibilityAttributes(divId, offerElement);
5087
5088        $("#" + divId).keypress(function (e) {
5089            var code = e.keyCode || e.which;
5090            if (code === 13) {
5091                $('.sposQuizInitiatorContainer').hide();
5092                $("#mastiff-check-warranty-secondary-offers").hide();
5093
5094                if (uiState.quiztype.toLowerCase() === "huq") {
5095                    $(".HUQConfiguratorContainer").show();
5096                } else if (uiState.quiztype.toLowerCase() === "cpc") {
5097                    $(".CPConfiguratorContainer").show();
5098                }
5099            }
5100        });
5101
5102        $("#" + divId).click(function () {
5103            $('.sposQuizInitiatorContainer').hide();
5104            $("#mastiff-check-warranty-secondary-offers").hide();
5105
5106            if (uiState.quiztype.toLowerCase() === "huq") {
5107                $(".HUQConfiguratorContainer").show();
5108            } else if (uiState.quiztype.toLowerCase() === "cpc") {
5109                $(".CPConfiguratorContainer").show();
5110            }
5111        });
5112
5113
5114        addUrlAndClickEvent(divId, offerElement, false);
5115
5116        LeadOffer.offerShown = "yes";
5117    } else {
5118        LeadOffer.errorData = "No Content Available";
5119        LeadOffer.offerShown = "no";
5120    }
5121
5122    logToGlobalDataLayer(LeadOffer);
5123
5124    return Promise.resolve();
5125}
5126
5127function appendQuizDiscardInsideInitiator(discardElement) {
5128    const divId = `${discardElement.templatePosition}_${discardElement.name}`;
5129
5130    const LeadOffer = {
5131        OfferID: divId,
5132        OfferClicked: "no",
5133        SPOStemplate: "29"
5134    };
5135    const GDLOfferName = "LeadOffer" + LeadOfferIndex;
5136
5137    const hasValidContent =
5138        isDefined(discardElement.primaryButtonText) &&
5139        isDefined(discardElement.storeURL);
5140
5141    if (hasValidContent) {
5142        const cta = discardElement.primaryButtonText || "";
5143
5144        var htmlTemplate = discardElement.html;
5145
5146        htmlTemplate = htmlTemplate.replace("{cta}", cta);
5147        htmlTemplate = htmlTemplate.replace("%sposQuizInitiatorDeclineOfferCTAId%", divId);
5148
5149        $("#sposQuizDeclineOfferDiv").html(htmlTemplate);
5150
5151        applyAccessibilityAttributes(divId, discardElement);
5152
5153        $("#" + divId).keypress(function (e) {
5154            var code = e.keyCode || e.which;
5155            if (code === 13) {
5156                offerDeclineEvent(reqObj, discardElement.name);
5157                $('.sposQuizInitiatorContainer').hide();
5158                $('.WRPrimaryTile').show();
5159
5160            }
5161        });
5162
5163        $("#" + divId).click(function () {
5164            offerDeclineEvent(reqObj, discardElement.name);
5165            $('.sposQuizInitiatorContainer').hide();
5166            $('.WRPrimaryTile').show();
5167        });
5168
5169
5170        LeadOffer.offerShown = "yes";
5171    } else {
5172        LeadOffer.errorData = "No Content Available";
5173        LeadOffer.offerShown = "no";
5174    }
5175
5176    logToGlobalDataLayer(LeadOffer);
5177}
5178
5179async function insertWarrantyOWContainerOffer(offerElement) {
5180    //wait for mastiff-dy-oow-section
5181    await waitForElement("#mastiff-dy-oow-section");
5182    var divId = "";
5183    divId = divId.concat("DY-OOW_", offerElement.templatePosition, "_", offerElement.name);
5184    var LeadOffer = {};
5185    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
5186    LeadOffer.OfferID = divId;
5187
5188    LeadOffer.OfferClicked = "no";
5189    LeadOffer.SPOStemplate = "31";
5190    //clickSelector is mastiff-dy-oow-section .accordion .accordion-button
5191    var clickSelector = "#mastiff-dy-oow-section .accordion .accordion-button";
5192    //addUrlAndClickEvent(clickSelector, offerElement, false);
5193
5194    var $el = $(clickSelector);
5195    if (offerElement.name) $el.attr("data-offer-name", offerElement.name);
5196
5197    // only send click when it's not active
5198    $(clickSelector).click(function () {
5199        if ($(this).hasClass("active")) {
5200            offerClickEvent(reqObj, this, false);
5201        }
5202    });
5203
5204
5205    if (isDefined(offerElement.primaryText1)) {
5206        //insert it in mastiff-dy-oow-section-title
5207        $("#mastiff-dy-oow-section-title").text(offerElement.primaryText1);
5208    }
5209
5210    if (isDefined(offerElement.primaryText2)) {
5211        //insert it in mastiff-dy-oow-section-subtitle
5212        $("#mastiff-dy-oow-section-subtitle").text(offerElement.primaryText2);
5213    }
5214
5215    if (isDefined(offerElement.html)) {
5216        var htmlContainer = offerElement.html;
5217        // insert in mastiff-dy-oow-tiles
5218        if (isContainerEmpty("#mastiff-dy-oow-tiles")) {
5219            $("#mastiff-dy-oow-tiles").html(htmlContainer);
5220            LeadOffer.offerShown = "yes";
5221            logInfo("DY OOW Container - Offers container inserted successfully", "#mastiff-dy-oow-tiles");
5222        } else {
5223            logInfo("DY OOW Container - Placement location is not empty", "#mastiff-dy-oow-tiles");
5224            LeadOffer.errorData = "OOW Container Location is not empty";
5225            LeadOffer.offerShown = "no";
5226        }
5227        logToGlobalDataLayer(LeadOffer);
5228    } else {
5229        logInfo("DY OOW Container - Missing mandatory fields", "#mastiff-dy-oow-tiles");
5230        LeadOffer.errorData = "No html container Available";
5231        LeadOffer.offerShown = "no";
5232        logToGlobalDataLayer(LeadOffer);
5233    }
5234}
5235
5236async function insertWarrantyRegularContainerOffer(offerElement) {
5237    //wait for mastiff-dy-oow-section
5238    await waitForElement("#mastiff-dy-compatible-oow-section");
5239    var divId = "";
5240    divId = divId.concat("DY-COMP-OOW_", offerElement.templatePosition, "_", offerElement.name);
5241    var LeadOffer = {};
5242    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
5243    LeadOffer.OfferID = divId;
5244
5245    LeadOffer.OfferClicked = "no";
5246    LeadOffer.SPOStemplate = "26";
5247    //clickSelector is mastiff-dy-compatible-oow-section .accordion .accordion-button
5248    var clickSelector = "#mastiff-dy-compatible-oow-section .accordion .accordion-button";
5249    //addUrlAndClickEvent(clickSelector, offerElement, false);
5250
5251    var $el = $(clickSelector);
5252    if (offerElement.name) $el.attr("data-offer-name", offerElement.name);
5253
5254    // only send click when it's not active
5255    $(clickSelector).click(function () {
5256        if ($(this).hasClass("active")) {
5257            offerClickEvent(reqObj, this, false);
5258        }
5259    });
5260
5261    if (isDefined(offerElement.primaryText1)) {
5262        //insert it in mastiff-dy-compatible-oow-section-title
5263        $("#mastiff-dy-compatible-section-title").text(offerElement.primaryText1);
5264    }
5265
5266    if (isDefined(offerElement.html)) {
5267        var htmlContainer = offerElement.html;
5268        // insert container in mastiff-dy-compatible-tiles
5269        if (isContainerEmpty("#mastiff-dy-compatible-tiles")) {
5270            $("#mastiff-dy-compatible-tiles").html(htmlContainer);
5271            $("#mastiff-dy-compatible-oow-section").show().removeClass("hidden");
5272
5273            LeadOffer.offerShown = "yes";
5274            logInfo("DY Comp OOW Container - Offers container inserted successfully", "#mastiff-dy-compatible-tiles");
5275        } else {
5276            logInfo("DY comp OOW Container - Placement location is not empty", "#mastiff-dy-compatible-tiles");
5277            LeadOffer.errorData = "Comp OOW Container Location is not empty";
5278            LeadOffer.offerShown = "no";
5279        }
5280        logToGlobalDataLayer(LeadOffer);
5281    } else {
5282        logInfo("DY Comp OOW Container - Missing mandatory fields", "#mastiff-dy-compatible-tiles");
5283        LeadOffer.errorData = "No html container Available";
5284        LeadOffer.offerShown = "no";
5285        logToGlobalDataLayer(LeadOffer);
5286    }
5287}
5288
5289/**
5290 * OWX Nested Experience Renderer (FINAL)
5291 * Update: Tab number is extracted from offer.category (NOT templatePosition).
5292 *
5293 * Expected behavior covered:
5294 * 1) OWExperiment_ib_Container inserts #SPOSOWEntryTiles under #mastiff-dy-oow-section (handled elsewhere: insertWarrantyOWContainerOffer)
5295 * 2) OWX_Navigation_Container_Shell is inserted under #SPOSOWEntryTiles but kept hidden
5296 * 3) Level0 offers are grouped in one wrapper (shown first). Order by templatePosition Level0Tab_{order}
5297 * 4) Clicking Level0 nested -> show shell, focus correct tab + show correct level containers
5298 * 5) Level1 grouped by Level1 containers
5299 * 6) Level2 grouped/filtered by tile_{n} relationship to its parent Level1 selection
5300 * 7) Back button hides shell and shows Level0 tiles
5301 */
5302async function renderWarrantyNestedOwExperiment(offerElements) {
5303    const owOffers = (offerElements || []).filter((offer) => safeLower(offer?.category).startsWith("owx"));
5304    const handled = new Set();
5305    if (!owOffers.length) return handled;
5306
5307    const LEVEL0_SELECTOR = "#SPOSOWEntryTiles";
5308    const EXPERIENCE_SELECTOR = "#mastiff-dy-oow-tiles";
5309
5310    // -------------------------
5311    // Helpers
5312    // -------------------------
5313
5314    const isActivationKey = (key) => key === "Enter" || key === " " || key === 13 || key === 32;
5315    const bindActivationKeyToClick = ($element, namespace) => {
5316        $element.off(`keydown.${namespace}`).on(`keydown.${namespace}`, function (e) {
5317            const k = e.key || e.which;
5318            if (!isActivationKey(k)) return;
5319            e.preventDefault();
5320            $(this).trigger("click");
5321        });
5322    };
5323
5324    //  TAB NUMBER: from CATEGORY
5325    // Category examples supported:
5326    // "OWX Tab1 - Level0 - Nested"
5327    // "OWX Tab2 - Level1 - Tiles - nested"
5328    // "OWX Tab3 - Level1 - Container"
5329    const parseTabNumberFromCategory = (category) => {
5330        const match = category && String(category).match(/tab\s*([0-9]+)/i);
5331        return match ? Number(match[1]) : 0;
5332    };
5333
5334    const parseLevelNumber = (category, templatePosition) => {
5335        const cat = String(category || "");
5336        const pos = String(templatePosition || "");
5337        const match = cat.match(/level\s*([0-9]+)/i);
5338        if (match) return Number(match[1]);
5339
5340        // fallback: some payloads may encode in templatePosition
5341        const posMatch = pos.match(/level\s*([0-9]+)/i);
5342        if (posMatch) return Number(posMatch[1]);
5343
5344        // special: level0tab_* is level 0
5345        if (pos.match(/level0tab/i)) return 0;
5346
5347        return 0;
5348    };
5349
5350    // Order for Level0 tiles: templatePosition like "level0tab_3" or "Level0Tab-2"
5351    const parseLevel0Order = (templatePosition) => {
5352        const match = templatePosition && String(templatePosition).match(/level0tab[_-]?([0-9]+)/i);
5353        return match ? Number(match[1]) : null;
5354    };
5355
5356    // tile key extraction: "tile_1", "tile-2", "tile2"
5357    const parseTileKey = (value) => {
5358        const v = String(value || "");
5359        const match = v.match(/tile[_\s-]?(\d+)/i);
5360        return match ? `tile_${match[1]}`.toLowerCase() : null;
5361    };
5362
5363    const isContainerPosition = (templatePosition) => safeLower(templatePosition || "").includes("container");
5364    const isTilePosition = (templatePosition) => safeLower(templatePosition || "").includes("tile");
5365    const isContainerCategory = (category) => safeLower(category || "").includes("container");
5366    const isOptionCategory = (category) => {
5367        const c = safeLower(category || "");
5368        return c.includes("option") || c.includes("tile");
5369    };
5370    const isContainerOffer = (offer) => isContainerPosition(offer?.templatePosition) || isContainerCategory(offer?.category);
5371    const isTileOffer = (offer) => isTilePosition(offer?.templatePosition) || isOptionCategory(offer?.category);
5372
5373    const containerSelectorCache = new Map();
5374
5375    const containerSelectorForPosition = (templatePosition) => {
5376        const key = templatePosition || "";
5377        if (containerSelectorCache.has(key)) return containerSelectorCache.get(key);
5378        const pos = safeLower(key);
5379        var selector = null;
5380        if (pos.includes("1r3c")) selector = ".oneRowThreeColumnsContainer";
5381        else if (pos.includes("2r3c")) selector = ".TwoRowsThreeColumnsContainer";
5382        else if (pos.includes("3r2c")) selector = ".ThreeRowsTwoColumnsContainer";
5383        containerSelectorCache.set(key, selector);
5384        return selector;
5385    };
5386
5387    const buildOwTileHtml = (offer, divId) => {
5388
5389        const requiredFields = {
5390            "level0tab": ["primaryText1", "primaryButtonText", "imageURL"],
5391            "3r2ctile": ["primaryText2"],
5392            "2r3ctile": ["primaryText1", "imageURL"],
5393            "1r3ctile": ["primaryText1", "primaryButtonText", "imageURL"]
5394        }
5395
5396        var templateKey = offer.templatePosition.toLowerCase().replace(/_\d+$/, "");
5397        var offerRequiredFields = requiredFields[templateKey] || [];
5398        var hasAllFields = offerRequiredFields.every(field => isDefined(offer[field]));
5399
5400        const isContainer = isContainerCategory(offer.category) || isContainerPosition(offer.templatePosition);
5401
5402        // required fields apply only to non-container offers
5403        const missingRequired = !isContainer && !hasAllFields;
5404
5405        if (missingRequired) {
5406            logInfo(`OWX Nested Experience: Missing required fields for offer ${offer.name} with    
5407templatePosition ${offer.templatePosition}`);
5408            return null;
5409        }
5410
5411        var html = offer.html;
5412        html = html.replace("%OWEntryOfferTitlePlaceholder%", offer.primaryText1 || "");
5413        html = html.replace("%OWEntryOfferDescriptionPlaceholder%", offer.primaryText2 || "");
5414        html = html.replace("%OWEntryOfferCTAPlaceholder%", offer.primaryButtonText || "");
5415        html = html.replace("%OWEntryOfferImgURLPlaceholder%", offer.imageURL || "''");
5416        html = html.replace("%falconContactHPOfferIdPlaceholder%", divId);
5417
5418        html = html.replace("%imageurl%", offer.imageURL || "''");
5419        if (isDefined(offer.offerTitle))
5420            html = html.replace("%description%", offer.offerTitle);
5421        else
5422            html = html.replace("%description%", offer.offerSubTitle);
5423        return html;
5424    };
5425
5426    // -------------------------
5427    // Find roots
5428    // -------------------------
5429    // Level 0 offers go to #SPOSOWEntryTiles
5430    var sposContainer;
5431    try {
5432        sposContainer = await waitForElement(LEVEL0_SELECTOR);
5433    } catch (e) {
5434        logInfo(`OWX nested experience: ${LEVEL0_SELECTOR} not found`);
5435        return handled;
5436    }
5437    const $level0Root = $(sposContainer);
5438
5439    // Nested experience shell goes to #mastiff-dy-oow-tiles
5440    var tileContainer;
5441    try {
5442        tileContainer = await waitForElement(EXPERIENCE_SELECTOR);
5443    } catch (e) {
5444        logInfo(`OWX nested experience: ${EXPERIENCE_SELECTOR} not found`);
5445        return handled;
5446    }
5447    const $experienceParent = $(tileContainer);
5448
5449    // -------------------------
5450    // Identify shell + build model (tabs/levels)
5451    // -------------------------
5452    const tabs = new Map();
5453
5454    // shell offer (level0container in templatePosition)
5455    const level0ContainerOffer = owOffers.find((offer) => safeLower(offer.templatePosition || "").includes("level0container"));
5456
5457    // add offers to model
5458    owOffers.forEach((offer) => {
5459        handled.add(offer.name);
5460
5461        const rawCategory = offer.category || "";
5462        const category = safeLower(rawCategory);
5463        const templatePosition = offer.templatePosition || "";
5464        const lowerTemplatePosition = safeLower(templatePosition);
5465        const isShell = lowerTemplatePosition.includes("level0container");
5466        if (isShell) return;
5467
5468        const tabNumber = parseTabNumberFromCategory(category);
5469        const levelNumber = parseLevelNumber(category, templatePosition);
5470        const isNested = category.includes("nested");
5471        // Hidden offers ("Nested - Hidden") build the tab model at Level0 but are never
5472        // rendered as visible tiles. They only require primaryText1 (tab label).
5473        const isHiddenNested = isNested && category.includes("hidden");
5474
5475        // Optimized: tileKey extracted purely from offer.category (matching groups)
5476        const tileKey = parseTileKey(rawCategory);
5477        const level0Order = parseLevel0Order(templatePosition);
5478
5479        if (!tabs.has(tabNumber)) {
5480            tabs.set(tabNumber, {
5481                tabNumber,
5482                tabOffer: null,       // a representative offer for analytics / title fallback
5483                levels: new Map(),    // Map<levelNumber, Array<{offer,isNested,tileKey}>>
5484                level0Order: null,    // ordering for Level0 tiles
5485                tabTitle: ""          // title shown in nav items
5486            });
5487        }
5488
5489        const tabData = tabs.get(tabNumber);
5490        if (!tabData.levels.has(levelNumber)) tabData.levels.set(levelNumber, []);
5491        tabData.levels.get(levelNumber).push({ offer, isNested, isHiddenNested, tileKey });
5492
5493        if (level0Order !== null) tabData.level0Order = level0Order;
5494
5495        // Tab title preference:
5496        // - If we find a level1 container with primaryText1, use it
5497        // - Else fallback to tab offer (level0) title/name
5498        if (levelNumber === 1 && isContainerPosition(templatePosition) && isDefined(offer.primaryText1)) {
5499            tabData.tabTitle = offer.primaryText1;
5500        }
5501
5502        if (!tabData.tabOffer || levelNumber === 0) {
5503            tabData.tabOffer = offer;
5504            if (!tabData.tabTitle) {
5505                tabData.tabTitle = offer.primaryText1 || offer.name || `Tab ${tabNumber}`;
5506            }
5507        }
5508    });
5509
5510    const tabKeys = Array.from(tabs.keys()).sort((a, b) => {
5511        const aOrder = tabs.get(a)?.level0Order;
5512        const bOrder = tabs.get(b)?.level0Order;
5513        if (aOrder != null && bOrder != null) return aOrder - bOrder;
5514        if (aOrder != null) return -1;
5515        if (bOrder != null) return 1;
5516        return a - b;
5517    });
5518    if (!tabKeys.length) return handled;
5519
5520    const sortedLevelsForTabCache = new Map();
5521    const getSortedLevelsForTab = (tabNumber) => {
5522        if (sortedLevelsForTabCache.has(tabNumber)) return sortedLevelsForTabCache.get(tabNumber);
5523        const tabData = tabs.get(tabNumber);
5524        const levels = tabData ? Array.from(tabData.levels.keys()).sort((a, b) => a - b) : [];
5525        sortedLevelsForTabCache.set(tabNumber, levels);
5526        return levels;
5527    };
5528    const getNextLevelForTab = (tabNumber, level) => {
5529        const levels = getSortedLevelsForTab(tabNumber);
5530        for (var i = 0; i < levels.length; i++) {
5531            if (levels[i] > level) return levels[i];
5532        }
5533        return undefined;
5534    };
5535    const getPreviousLevelForTab = (tabNumber, level) => {
5536        const levels = getSortedLevelsForTab(tabNumber);
5537        for (var i = levels.length - 1; i >= 0; i--) {
5538            if (levels[i] < level) return levels[i];
5539        }
5540        return level;
5541    };
5542
5543    const hasValidChildrenMemo = new Map();
5544    const hasValidChildren = (tabNumber, currentLevel, parentKey) => {
5545        const memoKey = `${tabNumber}|${currentLevel}|${safeLower(parentKey || "")}`;
5546        if (hasValidChildrenMemo.has(memoKey)) return hasValidChildrenMemo.get(memoKey);
5547
5548        const nextLevel = getNextLevelForTab(tabNumber, currentLevel);
5549        if (typeof nextLevel === "undefined") {
5550            hasValidChildrenMemo.set(memoKey, false);
5551            return false;
5552        }
5553
5554        const allNext = tabs.get(tabNumber).levels.get(nextLevel) || [];
5555        // For Level 1 (nextLevel=1), we assume all items in the tab are L1 roots unless filtered otherwise.
5556        // For Level > 1, we must match the parent's tileKey.
5557        const candidates = (nextLevel > 1)
5558            ? allNext.filter(c => safeLower(c.tileKey) === safeLower(parentKey))
5559            : allNext;
5560
5561        if (!candidates.length) {
5562            hasValidChildrenMemo.set(memoKey, false);
5563            return false;
5564        }
5565
5566        const result = candidates.some(c => {
5567            // Containers are structural only, never count as valid leaves
5568            if (isContainerOffer(c.offer)) return false;
5569            if (!c.isNested) {
5570                // Leaf tile: verify it would actually render (html, storeURL, required fields)
5571                if (!isDefined(c.offer.html)) return false;
5572                if (!isDefined(c.offer.storeURL)) return false;
5573                return buildOwTileHtml(c.offer, '_validationCheck') !== null;
5574            }
5575            // Nested: recursively check for valid children
5576            return hasValidChildren(tabNumber, nextLevel, c.tileKey);
5577        });
5578        hasValidChildrenMemo.set(memoKey, result);
5579        return result;
5580    };
5581
5582    // Filter out tabs with no renderable Level 0 offers to prevent
5583    // empty shell containers and orphaned tab navigation items.
5584    for (var i = tabKeys.length - 1; i >= 0; i--) {
5585        const tn = tabKeys[i];
5586        const td = tabs.get(tn);
5587        const l0 = td ? (td.levels.get(0) || []) : [];
5588        const hasRenderable = l0.some(({ offer, isNested, isHiddenNested, tileKey }) => {
5589            // Hidden offers have no html/storeURL; only primaryText1 is required.
5590            if (isHiddenNested) return isDefined(offer.primaryText1) && hasValidChildren(tn, 0, tileKey);
5591            if (!isDefined(offer.html)) return false;
5592            if (isNested) return hasValidChildren(tn, 0, tileKey);
5593            return buildOwTileHtml(offer, '_validationCheck') !== null;
5594        });
5595        if (!hasRenderable) {
5596            // Tab0 without a complete nested path: keep it if at least one other tab
5597            // has valid children — Tab0 will act as a visual entry tile and redirect
5598            // on click to the first valid tab. If no other tab survives, Tab0 is removed too.
5599            const tab0Survives = tn === 0 && tabKeys.length > 1 && l0.some(({ offer }) => isDefined(offer.html));
5600            if (!tab0Survives) tabKeys.splice(i, 1);
5601        }
5602    }
5603    if (!tabKeys.length) return handled;
5604
5605    // -------------------------
5606    // Reset and create experience root
5607    // -------------------------
5608    $experienceParent.find(".OWEntryNestedExperienceRoot").remove();
5609
5610    const $experienceRoot = $("<div class='OWEntryNestedExperienceRoot'></div>");
5611    $experienceParent.append($experienceRoot);
5612
5613    // Level 0 offers are inserted directly into #SPOSOWEntryTiles ($level0Root), no wrapper needed.
5614
5615    //  Shell inserted under #SPOSOWEntryTiles but hidden initially
5616    var $level0Shell = $("<div class='OWEntryNestedContainer OWEntryNestedLevel0Shell'></div>");
5617    if (level0ContainerOffer && isDefined(level0ContainerOffer.html)) {
5618        // replace {title} placeholder if exists with level0ContainerOffer.primaryText1
5619        const level0ShellHtml = level0ContainerOffer.html.replace("{title}", level0ContainerOffer.primaryText1 || "");
5620        $level0Shell = $(level0ShellHtml);
5621    }
5622    $level0Shell.addClass("OWEntryNestedLevel0Shell");
5623
5624    $experienceRoot.append($level0Shell);
5625
5626    // -------------------------
5627    // Build navigation items (tabs) inside shell
5628    // -------------------------
5629    const navItemsHtml = tabKeys
5630        .filter((tabNumber) => {
5631            const td = tabs.get(tabNumber);
5632            const l0 = td ? (td.levels.get(0) || []) : [];
5633            return l0.some(({ isNested, tileKey }) => isNested && hasValidChildren(tabNumber, 0, tileKey));
5634        })
5635        .map((tabNumber) => {
5636            const tabData = tabs.get(tabNumber);
5637            const title = tabData?.tabTitle || `Tab ${tabNumber}`;
5638            const offerName = tabData?.tabOffer?.name || "";
5639            return `<div class="OWEntryNavigationItem" data-tab="${tabNumber}" data-offer-name="${offerName}" tabindex="0" role="button" aria-label="${title}">
5640                <div class="OWEntryNavigationItemElipse"></div>${title}
5641              </div>`;
5642        })
5643        .join("");
5644
5645    const $navContainers = $level0Shell.find(".OWEntryNavigationItems");
5646    if ($navContainers.length) {
5647        $navContainers.each(function () {
5648            $(this).html(navItemsHtml);
5649        });
5650    } else {
5651        $level0Shell.prepend(`<div class="OWEntryNavigationItems">${navItemsHtml}</div>`);
5652    }
5653
5654    const $shellContainersRoot = $level0Shell.find(".OWEntryNestedContainers").first().length
5655        ? $level0Shell.find(".OWEntryNestedContainers").first()
5656        : $level0Shell;
5657    const $navItems = $experienceRoot.find(".OWEntryNavigationItem");
5658    const levelElementByTabLevel = new Map();
5659
5660    // -------------------------
5661    // Render levels (L1+ only) inside shell per tab
5662    // -------------------------
5663    tabKeys.forEach((tabNumber) => {
5664        const tabData = tabs.get(tabNumber);
5665        const $tabContainer = $("<div class='OWEntryNestedTab'></div>").attr("data-tab", tabNumber);
5666        $shellContainersRoot.append($tabContainer);
5667
5668        const levelKeys = Array.from(tabData.levels.keys()).sort((a, b) => a - b);
5669        levelKeys.forEach((level) => {
5670            if (level === 0) return; // L0 is outside (level0Group)
5671
5672            const $levelWrapper = $("<div class='OWEntryNestedLevel'></div>")
5673                .attr("data-tab", tabNumber)
5674                .attr("data-level", level);
5675            $tabContainer.append($levelWrapper);
5676
5677            const levelEntries = tabData.levels.get(level) || [];
5678            const sorted = levelEntries.slice().sort((a, b) => {
5679                return level >= 1
5680                    ? positionSortByUnderscoreOrder(a.offer, b.offer)
5681                    : positionSort(a.offer, b.offer);
5682            });
5683
5684            const containers = sorted.filter(({ offer }) => isContainerOffer(offer));
5685            const tiles = sorted.filter(({ offer }) => isTileOffer(offer));
5686
5687            // 5) Container & Tile Placement
5688            // Level 1: Containers appended to level wrapper. Tiles inside containers.
5689            // Level > 1: TileGroups appended to level wrapper. Containers inside Groups. Tiles inside Containers inside Groups.
5690
5691            const level1ContainerInstances = [];
5692            const levelNContainerOffers = []; // Store offers to instantiate on demand
5693            const levelNContainerByTileKey = new Map();
5694            const tileGroupCache = new Map();
5695            const tileGroupContainerCache = new Map();
5696            const level1MatchedContainerBySelector = new Map();
5697
5698            const resolveLevel1TargetContainer = (containerSelector) => {
5699                if (!level1ContainerInstances.length) return null;
5700                if (!containerSelector) return level1ContainerInstances[0];
5701                if (level1MatchedContainerBySelector.has(containerSelector)) {
5702                    return level1MatchedContainerBySelector.get(containerSelector);
5703                }
5704
5705                var $matched = null;
5706                for (var i = 0; i < level1ContainerInstances.length; i++) {
5707                    const $candidate = level1ContainerInstances[i].find(containerSelector).first();
5708                    if ($candidate.length) {
5709                        $matched = $candidate;
5710                        break;
5711                    }
5712                }
5713                if (!$matched || !$matched.length) $matched = level1ContainerInstances[0];
5714                level1MatchedContainerBySelector.set(containerSelector, $matched);
5715                return $matched;
5716            };
5717
5718            if (level === 1) {
5719                containers.forEach(({ offer, tileKey }) => {
5720                    if (!isDefined(offer.html)) return;
5721                    const $container = $(offer.html);
5722                    if (tileKey) $container.attr("data-tile-key", tileKey);
5723                    level1ContainerInstances.push($container);
5724                    $levelWrapper.append($container);
5725                });
5726            } else {
5727                containers.forEach(({ offer, tileKey }) => {
5728                    if (!isDefined(offer.html)) return;
5729                    const containerData = { offer, lowerHtml: safeLower(offer.html) };
5730                    levelNContainerOffers.push(containerData);
5731                    if (tileKey && !levelNContainerByTileKey.has(tileKey)) {
5732                        levelNContainerByTileKey.set(tileKey, containerData);
5733                    }
5734                });
5735            }
5736
5737            tiles.forEach(({ offer, isNested, tileKey }, tileIndex) => {
5738                // Validate nested paths: if it's nested but leads to nowhere, don't show it.
5739                if (isNested && !hasValidChildren(tabNumber, level, tileKey)) return;
5740
5741                // Nested tiles can ignore storeURL. Link tiles must have storeURL.
5742                const requiresStoreUrl = !isNested;
5743                const hasRequired = isDefined(offer.html) && (!requiresStoreUrl || isDefined(offer.storeURL));
5744                if (!hasRequired) return;
5745
5746                const tileId = `OWX_${tabNumber}_${level}_${tileIndex}`;
5747                const tileHtml = buildOwTileHtml(offer, tileId);
5748                if (!isDefined(tileHtml)) return;
5749
5750                const $tile = $(tileHtml);
5751                const $tileRoot = $tile.first();
5752                if (!$tileRoot.length) return;
5753
5754                $tileRoot.attr("id", tileId);
5755                $tileRoot.attr("data-offer-name", offer.name || "");
5756                $tileRoot.attr("data-experience", isNested ? "nested" : "link");
5757                if (tileKey) $tileRoot.attr("data-tile-key", tileKey);
5758                if (offer.storeURL) $tileRoot.attr("data-store-url", offer.storeURL);
5759
5760                const containerSelector = containerSelectorForPosition(offer.templatePosition);
5761
5762                // Placement Logic
5763                if (level > 1 && tileKey) {
5764                    // Structure: $levelWrapper -> .OWEntryNestedTileGroup -> Container -> Tile
5765                    var $tileGroup = tileGroupCache.get(tileKey);
5766                    if (!$tileGroup || !$tileGroup.length) {
5767                        $tileGroup = $(`<div class="OWEntryNestedTileGroup" data-tile-key="${tileKey}"></div>`);
5768                        $levelWrapper.append($tileGroup);
5769                        tileGroupCache.set(tileKey, $tileGroup);
5770                    }
5771
5772                    // Match container offer by tab+level+tileKey (tab+level scope is already active in this loop)
5773                    var $targetContainer = tileGroupContainerCache.get(tileKey) || null;
5774                    if (!$targetContainer || !$targetContainer.length) {
5775                        var chosenContainerData = levelNContainerByTileKey.get(tileKey) || null;
5776
5777                        if (!chosenContainerData && levelNContainerOffers.length) {
5778                            // fallback to selector-compatible container when explicit tile match is missing
5779                            if (containerSelector) {
5780                                const selName = containerSelector.replace(".", "");
5781                                const lowerSelectorName = safeLower(selName);
5782                                chosenContainerData = levelNContainerOffers.find((o) => o.lowerHtml.includes(lowerSelectorName));
5783                            }
5784                            if (!chosenContainerData) chosenContainerData = levelNContainerOffers[0];
5785                        }
5786
5787                        if (chosenContainerData) {
5788                            const $newContainer = $(chosenContainerData.offer.html);
5789                            if (tileKey) $newContainer.attr("data-tile-key", tileKey);
5790                            $tileGroup.append($newContainer);
5791
5792                            // prefer container selector within inserted HTML if present
5793                            if (containerSelector) {
5794                                $targetContainer = $newContainer.find(containerSelector).first();
5795                                if (!$targetContainer.length && $newContainer.is(containerSelector)) {
5796                                    $targetContainer = $newContainer;
5797                                }
5798                            }
5799                            if (!$targetContainer || !$targetContainer.length) {
5800                                $targetContainer = $newContainer;
5801                            }
5802                        } else {
5803                            $targetContainer = $tileGroup;
5804                        }
5805
5806                        tileGroupContainerCache.set(tileKey, $targetContainer);
5807                    }
5808
5809                    $targetContainer.append($tile);
5810
5811                } else {
5812                    // Level 1 logic (or fallback for L>1 without tileKey): LevelWrapper -> Container -> Tile
5813                    // Note: For Level 1, containers are ALREADY in $levelWrapper.
5814
5815                    var $targetContainer = containerSelector ? $levelWrapper.find(containerSelector).first() : $levelWrapper;
5816
5817                    if (level === 1 && level1ContainerInstances.length) {
5818                        var $matched = resolveLevel1TargetContainer(containerSelector);
5819                        if ($matched && $matched.length) $targetContainer = $matched;
5820                    }
5821                    else if (level > 1 && !tileKey) {
5822                        // Edge case: Level > 1 but no tileKey -> append to wrapper directly 
5823                        // (We didn't instantiate containers for L>1 outside groups)
5824                        $targetContainer = $levelWrapper;
5825                    }
5826
5827                    $targetContainer.append($tile);
5828
5829                    // 6) Level2+ related to parent by tileKey (tile_1 / tile_2...) - LEGACY LOGIC REMOVED/HANDLED ABOVE
5830                    // We incorporated grouping into the placement logic for L>1 above.
5831                }
5832
5833                // a11y + pricing placeholders
5834                applyAccessibilityAttributes(`#${tileId}`, offer);
5835                allocateRecEngPrices(offer.strikePrice, offer.incartPrice, tileId, offer.currency);
5836
5837                // Determine the key to use for navigation.
5838                // Rely on tile matching groups by offer category only.
5839                // Identifiers propagate down; L(N) tile with key 'X' opens L(N+1) group 'X'.
5840                const nextNavigationKey = tileKey;
5841
5842                // click behavior
5843                if (isNested) {
5844                    $tileRoot.off(".owxNested").on("click.owxNested", function (e) {
5845                        e.preventDefault();
5846                        offerClickEvent(reqObj, this, false);
5847
5848                        const nextLevel = getNextLevelForTab(tabNumber, level);
5849                        if (typeof nextLevel === "number") {
5850                            navigationStack.push({ tabNumber: lastActiveTab, level: lastActiveLevel, tileKey: lastActiveTileKey });
5851                            activateTabLevel(tabNumber, nextLevel, nextNavigationKey || null);
5852                        }
5853                    });
5854                    bindActivationKeyToClick($tileRoot, "owxNestedKey");
5855                } else {
5856                    $tileRoot.off(".owxLink");
5857                    addUrlAndClickEvent(tileId, offer);
5858                }
5859            });
5860
5861            levelElementByTabLevel.set(`${tabNumber}|${level}`, $levelWrapper);
5862        });
5863    });
5864
5865    // -------------------------
5866    // Render Level0 tiles (outside shell)
5867    // -------------------------
5868    const level0Offers = [];
5869    tabKeys.forEach((tabNumber) => {
5870        const tabData = tabs.get(tabNumber);
5871        const list = tabData.levels.get(0) || [];
5872        list.forEach((entry) => level0Offers.push({ tabNumber, ...entry }));
5873    });
5874
5875    // Order Level0 tiles strictly by Level0Tab_{order} from templatePosition (fallback: tab number)
5876    level0Offers.sort((a, b) => {
5877        const aOrder = parseLevel0Order(a.offer?.templatePosition);
5878        const bOrder = parseLevel0Order(b.offer?.templatePosition);
5879        if (aOrder != null && bOrder != null) return aOrder - bOrder;
5880        if (aOrder != null) return -1;
5881        if (bOrder != null) return 1;
5882        return a.tabNumber - b.tabNumber;
5883    });
5884
5885    // -------------------------
5886    // Navigation state + show/hide
5887    // -------------------------
5888    const navigationStack = [];
5889    var lastActiveTab = tabKeys[0];
5890    var lastActiveLevel = 0;
5891    var lastActiveTileKey = null;
5892
5893    const showLevel0View = () => {
5894        $level0Root.show();
5895        $experienceRoot.hide();
5896    };
5897
5898    const showNestedView = () => {
5899        $level0Root.hide();
5900        $experienceRoot.show();
5901        //normalizeHeightsOnce();
5902    };
5903
5904    function activateTabLevel(tabNumber, levelNumber, tileKey = null) {
5905        lastActiveTab = tabNumber;
5906        lastActiveLevel = levelNumber;
5907        lastActiveTileKey = levelNumber > 1 ? tileKey : null;
5908
5909        $shellContainersRoot.find(".OWEntryNestedLevel").hide();
5910        const activeKey = `${tabNumber}|${levelNumber}`;
5911        const $activeLevel = levelElementByTabLevel.get(activeKey)
5912            || $shellContainersRoot.find(`.OWEntryNestedLevel[data-tab="${tabNumber}"][data-level="${levelNumber}"]`);
5913        $activeLevel.show();
5914
5915        $navItems.removeClass("OWEntryNavigationItemActive");
5916        $navItems.filter(`[data-tab="${tabNumber}"]`).addClass("OWEntryNavigationItemActive");
5917
5918        // if level>1 and tileKey provided, show only the matching tile group
5919        if (tileKey && levelNumber > 1) {
5920            $activeLevel.find("[data-tile-key]").hide();
5921            $activeLevel.find(`[data-tile-key="${tileKey}"]`).show();
5922        } else {
5923            $activeLevel.find("[data-tile-key]").show();
5924        }
5925    }
5926
5927    // Create Level0 tiles UI (grouped)
5928    level0Offers.forEach(({ offer, tileKey, tabNumber, isNested, isHiddenNested }, index) => {
5929        // Hidden offers are structural only - they define tab content but never appear as Level0 tiles.
5930        if (isHiddenNested) return;
5931        // Tab0 without a fulfilled happy path is kept at Level0 (redirects to first valid tab on click).
5932        if (isNested && tabNumber !== 0 && !hasValidChildren(tabNumber, 0, tileKey)) return;
5933
5934        const tileId = `OWX_Level0_${tabNumber}_${index}`;
5935        const tileHtml = buildOwTileHtml(offer, tileId);
5936        if (!tileHtml) return;
5937
5938        const $tile = $(tileHtml);
5939        const $tileRoot = $tile.first();
5940        if (!$tileRoot.length) return;
5941
5942        $tileRoot.attr("id", tileId);
5943        $tileRoot.attr("data-offer-name", offer.name || "");
5944        $tileRoot.attr("data-tab", tabNumber);
5945        if (tileKey) $tileRoot.attr("data-tile-key", tileKey);
5946        $level0Root.append($tile);
5947
5948        applyAccessibilityAttributes(`#${tileId}`, offer);
5949
5950        if (!isNested) {
5951            // Non-nested Level0 uses only addUrlAndClickEvent for click + key activation + reporting.
5952            addUrlAndClickEvent(tileId, offer);
5953            return;
5954        }
5955
5956        $tileRoot.off(".owxLevel0").on("click.owxLevel0", function (e) {
5957            e.preventDefault();
5958
5959            // Only nested Level0 tiles should enter the shell.
5960            // If a Level0 tile is not nested, it can behave as a link (storeURL).
5961            const isNested = safeLower(offer.category || "").includes("nested");
5962            offerClickEvent(reqObj, this, false);
5963
5964            // Tab0 with no fulfilled nested path: redirect to the first tab with valid children
5965            // (i.e. the first tab that will appear in the navigation bar).
5966            if (isNested && tabNumber === 0 && !hasValidChildren(tabNumber, 0, tileKey)) {
5967                const firstValidTab = tabKeys.find(tn => {
5968                    if (tn === 0) return false;
5969                    const td = tabs.get(tn);
5970                    const l0items = td ? (td.levels.get(0) || []) : [];
5971                    return l0items.some(({ isNested: iN, tileKey: tk }) => iN && hasValidChildren(tn, 0, tk));
5972                });
5973                if (firstValidTab !== undefined) {
5974                    navigationStack.length = 0;
5975                    showNestedView();
5976                    activateTabLevel(firstValidTab, getNextLevelForTab(firstValidTab, 0) ?? 1, null);
5977                }
5978                return;
5979            }
5980
5981            navigationStack.length = 0;
5982            showNestedView();
5983            // Use this tile's own tab when it is still a valid tab (backward-compat with
5984            // multiple "Nested" L0 tiles). Fall back to tabKeys[0] only for the single-entry
5985            // scenario where the entry tile's tab was filtered out (e.g. no tab number -> Tab0).
5986            const entryTab = tabKeys.indexOf(tabNumber) !== -1 ? tabNumber : tabKeys[0];
5987            activateTabLevel(entryTab, getNextLevelForTab(entryTab, 0) ?? 1, null);
5988        });
5989        bindActivationKeyToClick($tileRoot, "owxLevel0Key");
5990    });
5991
5992    // -------------------------
5993    // Tab click -> open nested shell and show L1 for that tab
5994    // -------------------------
5995    $experienceRoot.on("click", ".OWEntryNavigationItem", function (e) {
5996        e.preventDefault();
5997        const tabNumber = Number($(this).attr("data-tab"));
5998        if (!Number.isFinite(tabNumber)) return;
5999
6000        offerClickEvent(reqObj, this, false);
6001        const tabData = tabs.get(tabNumber);
6002        if (!tabData) return;
6003
6004        navigationStack.length = 0;
6005        showNestedView();
6006        activateTabLevel(tabNumber, getNextLevelForTab(tabNumber, 0) ?? 1, null);
6007    });
6008
6009    $experienceRoot.on("keydown", ".OWEntryNavigationItem", function (e) {
6010        const k = e.key || e.which;
6011        if (!isActivationKey(k)) return;
6012        e.preventDefault();
6013        $(this).trigger("click");
6014    });
6015
6016    // -------------------------
6017    // Back button: pop stack OR go to previous level OR return to Level0 tiles
6018    // -------------------------
6019    $experienceRoot.on("click", ".OWEntryNavigationBarReturnButton, .OWEntryNavigationBarElipse, .OWEntryNavigationBarReturn", function (e) {
6020        e.preventDefault();
6021        e.stopPropagation();
6022        // only send reporting if we can derive an offer name (avoid spurious reports for pure navigation)
6023        const $btn = $(this);
6024        const offerName = $btn.attr('data-offer-name') || $btn.closest('[data-offer-name]').attr('data-offer-name');
6025        if (isDefined(offerName)) {
6026            offerClickEvent(reqObj, this, false);
6027        } else {
6028            logInfo('OWX back nav clicked - no offerName, skipping reporting');
6029        }
6030
6031        const previous = navigationStack.pop();
6032        if (previous) {
6033            const previousTileKey = previous.level > 1 ? (previous.tileKey || null) : null;
6034            activateTabLevel(previous.tabNumber, previous.level, previousTileKey);
6035            return;
6036        }
6037
6038        const prevLevel = getPreviousLevelForTab(lastActiveTab, lastActiveLevel);
6039        if (prevLevel <= 0) {
6040            // 7) Hide shell and show Level0 tiles
6041            showLevel0View();
6042            return;
6043        }
6044
6045        const prevTileKey = prevLevel > 1 ? (lastActiveTileKey || null) : null;
6046        activateTabLevel(lastActiveTab, prevLevel, prevTileKey);
6047    });
6048
6049    // -------------------------
6050    // Normalize heights for all levels (same level index => same min-height)
6051    // Deferred to first show of the nested view: at that point all ancestors are
6052    // guaranteed to be in the live render tree so outerHeight() returns real values.
6053    // -------------------------
6054    let heightsNormalized = false;
6055    const normalizeHeightsOnce = () => {
6056        if (heightsNormalized) return;
6057        heightsNormalized = true;
6058
6059        const $levels = $shellContainersRoot.find(".OWEntryNestedLevel");
6060        $levels.css({ display: "block", visibility: "hidden" });
6061
6062        const levelHeights = {};
6063        $levels.each(function () {
6064            const lvl = $(this).attr("data-level");
6065            const h = $(this).outerHeight(true);
6066            levelHeights[lvl] = Math.max(levelHeights[lvl] || 0, h);
6067        });
6068
6069        $levels.each(function () {
6070            const lvl = $(this).attr("data-level");
6071            const h = levelHeights[lvl];
6072            if (h) $(this).css("min-height", h);
6073        });
6074
6075        $levels.css({ display: "none", visibility: "" });
6076    };
6077
6078    // Calculate oneFullPathrendered:
6079    // Check if there is at least one tab where the *highest level* contains a "leaf" offer (not nested, not container).
6080    // This indicates a full path is rendered/ready for that tab.
6081    var oneFullPathrendered = false;
6082    for (const [tabNumber, data] of tabs.entries()) {
6083        const levels = getSortedLevelsForTab(tabNumber);
6084        if (levels.length === 0) continue;
6085
6086        const maxLevel = levels[levels.length - 1];
6087        const entries = data.levels.get(maxLevel) || [];
6088
6089        const hasLeaf = entries.some(({ offer, isNested }) => {
6090            const isContainer = isContainerPosition(offer.templatePosition);
6091            return !isNested && !isContainer;
6092        });
6093
6094        if (hasLeaf) {
6095            oneFullPathrendered = true;
6096            break;
6097        }
6098    }
6099    handled.oneFullPathrendered = oneFullPathrendered;
6100
6101    // initial view
6102    showLevel0View();
6103    return handled;
6104}
6105
6106function renderWarrantyOwTileOffers() {
6107    var warrantyTileOffers = offerResults.offers.offer.filter(function (x) {
6108        return x.OWTileOffer === true;
6109    });
6110
6111
6112    // order offer based on x.templatePosition (primary, secondary, shop1, shop2)
6113    warrantyTileOffers.sort(function (a, b) {
6114        var positionOrder = { "primary": 1, "secondary": 2, "shop1": 3, "shop2": 4, "shop3": 5 };
6115        return positionOrder[a.templatePosition] - positionOrder[b.templatePosition];
6116    });
6117
6118    waitForElement("#SPOSOWEntryTiles").then(() => {
6119        var anyInserted = false;
6120        warrantyTileOffers.forEach(function (offerElement) {
6121            var offerInserted = insertWarrantyOWContainerOffer(offerElement);
6122            if (offerInserted) {
6123                anyInserted = true;
6124            }
6125        });
6126        if (anyInserted) {
6127            // remove hidden from mastiff-dy-oow-section
6128            $("#mastiff-dy-oow-section").removeClass("hidden");
6129        }
6130    });
6131
6132    function insertWarrantyOWContainerOffer(offerElement) {
6133        var divId = "";
6134        divId = divId.concat(offerElement.templatePosition, "_", offerElement.name);
6135        var LeadOffer = {};
6136        var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
6137        LeadOffer.OfferID = divId;
6138        LeadOffer.OfferClicked = "no";
6139        LeadOffer.SPOStemplate = "32";
6140
6141        if (isDefined(offerElement.html)
6142            && isDefined(offerElement.primaryText1)
6143            && isDefined(offerElement.primaryText2)
6144            && isDefined(offerElement.primaryButtonText)
6145            && isDefined(offerElement.storeURL)
6146            && isDefined(offerElement.imageURL)
6147        ) {
6148            var htmlTemplate = offerElement.html;
6149
6150            //replace placeholders
6151            htmlTemplate = htmlTemplate.replace("%OWEntryOfferTitlePlaceholder%", offerElement.primaryText1);
6152            htmlTemplate = htmlTemplate.replace("%OWEntryOfferDescriptionPlaceholder%", offerElement.primaryText2);
6153            htmlTemplate = htmlTemplate.replace("%OWEntryOfferCTAPlaceholder%", offerElement.primaryButtonText);
6154            htmlTemplate = htmlTemplate.replace("%OWEntryOfferImgURLPlaceholder%", offerElement.imageURL);
6155            htmlTemplate = htmlTemplate.replace("%falconContactHPOfferIdPlaceholder%", divId);
6156
6157            $("#mastiff-dy-oow-tiles").append(htmlTemplate);
6158
6159            LeadOffer.offerShown = "yes";
6160
6161            applyAccessibilityAttributes(divId, offerElement);
6162            addUrlAndClickEvent(divId, offerElement);
6163            logInfo("DY OOW Tile Offer - Offer displayed successfully", "#mastiff-dy-oow-tiles");
6164            return true;
6165
6166            // } else {
6167            //     logInfo("DY OOW Tile Offer - Placement location is not empty", "#mastiff-dy-oow-tiles");
6168            // }
6169        } else {
6170            logInfo("DY OOW Tile Offer - Missing mandatory fields", "#mastiff-dy-oow-tiles");
6171        }
6172        return false;
6173    }
6174}
6175
6176function showSwdViewInStoreOffer(offerElement) {
6177    var divId = "";
6178    divId = divId.concat("SWD-SPOS_", offerElement.templatePosition, "_", offerElement.name);
6179
6180    var LeadOffer = {};
6181    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
6182    LeadOffer.OfferID = divId;
6183    LeadOffer.OfferClicked = "no";
6184    LeadOffer.SPOStemplate = "15";
6185    if (
6186        isDefined(offerElement.html) &&
6187        isDefined(offerElement.primaryButtonText) &&
6188        isDefined(offerElement.storeURL)
6189    ) {
6190        var htmlTemplate = offerElement.html;
6191        if (isContainerEmpty("#mastiff_view_in_store_SWD")) {
6192            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateImgURL%", offerElement.imageURL);
6193            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateCTAplaceholder%", offerElement.primaryButtonText);
6194            htmlTemplate = htmlTemplate.replace("%simpleLinkTemplateId%", divId);
6195
6196            $("#mastiff_view_in_store_SWD").html(htmlTemplate);
6197            $("#mastiff_view_in_store_SWD").removeClass("hidden");
6198
6199            $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" });
6200
6201            applyAccessibilityAttributes(divId, offerElement);
6202            addUrlAndClickEvent(divId, offerElement);
6203            LeadOffer.offerShown = "yes";
6204            logInfo("SWD View In Store Offer - Offer displayed successfully", "#mastiff_view_in_store_SWD");
6205        } else {
6206            logInfo("SWD View In Store Offer - Placement location is not empty");
6207            LeadOffer.errorData = "View In Store Location is not empty";
6208            LeadOffer.offerShown = "no";
6209        }
6210        logToGlobalDataLayer(LeadOffer);
6211
6212    } else {
6213        logInfo("SWD View In Store Offer - Missing mandatory fields");
6214        LeadOffer.errorData = "No Content Available";
6215        LeadOffer.offerShown = "no";
6216
6217        logToGlobalDataLayer(LeadOffer);
6218
6219    }
6220}
6221
6222function showDriverDetailsOffer(offerElement) {
6223    var divId = "";
6224    divId = divId.concat("SPOS_", offerElement.templatePosition, "_", offerElement.name);
6225
6226    var placeholderToinsertAt = "";
6227    if (offerElement.templatePosition === "primary") {
6228        placeholderToinsertAt = "#driversPageMastiffBannerTop";
6229    } else if (offerElement.templatePosition === "secondary") {
6230        placeholderToinsertAt = "#driversPageMastiffBannerBot";
6231    }
6232
6233    var LeadOffer = {};
6234    var GDLOfferName = "LeadOffer" + (LeadOfferIndex);
6235    LeadOffer.OfferID = divId;
6236    LeadOffer.OfferClicked = "no";
6237    LeadOffer.SPOStemplate = "15";
6238
6239    if (
6240        isDefined(offerElement.html) &&
6241        isDefined(offerElement.primaryText1) &&
6242        isDefined(offerElement.primaryText2) &&
6243        isDefined(offerElement.primaryButtonText) &&
6244        isDefined(offerElement.imageURL) &&
6245        isDefined(offerElement.storeURL)
6246    ) {
6247        var htmlTemplate = offerElement.html;
6248        if (isContainerEmpty(placeholderToinsertAt)) {
6249            htmlTemplate = htmlTemplate.replace("%DriverTileOfferImgURLPlaceholder%", offerElement.imageURL);
6250            htmlTemplate = htmlTemplate.replace("%DriverTileOfferTitlePlaceholder%", offerElement.primaryText1);
6251            htmlTemplate = htmlTemplate.replace("%DriverTileOfferDescriptionPlaceholder%", offerElement.primaryText2);
6252            htmlTemplate = htmlTemplate.replace("%DriverTileOfferCTAPlaceholder%", offerElement.primaryButtonText);
6253            htmlTemplate = htmlTemplate.replace("%DriverTileOfferId%", divId);
6254            htmlTemplate = htmlTemplate.replace("%secondaryContactHPOfferIdPlaceholder%", divId);
6255
6256            $(placeholderToinsertAt).html(htmlTemplate).css({ 'display': 'block', 'padding-bottom': '0px' });
6257
6258            allocateRecEngPrices(offerElement.strikePrice, offerElement.incartPrice, divId, offerElement.currency);
6259
6260            $("#" + divId).css({ "font-size": "14px", "text-decoration": "none" });
6261            applyAccessibilityAttributes(divId, offerElement);
6262
6263            addUrlAndClickEvent(divId, offerElement);
6264            LeadOffer.offerShown = "yes";
6265            logInfo("Driver Details Offer - Offer displayed successfully", placeholderToinsertAt);
6266        } else {
6267            logInfo("Driver Details Offer - Placement location is not empty", placeholderToinsertAt);
6268            LeadOffer.errorData = "Offer Location is not empty";
6269            LeadOffer.offerShown = "no";
6270        }
6271        logToGlobalDataLayer(LeadOffer);
6272    } else {
6273        logInfo("Driver Details Offer - Missing mandatory fields");
6274        LeadOffer.errorData = "No Content Available";
6275        LeadOffer.offerShown = "no";
6276
6277        logToGlobalDataLayer(LeadOffer);
6278    }
6279}
6280
6281// ----------- Accessories Navigation Experiment -----------------
6282async function showAccListOffers(accessoriesOffers) {
6283    // Normalize the API payload (or a legacy offer array) and retain only accessory-list offers.
6284    // This keeps response flattening in one place and avoids repeating it at every call site.
6285    var rawOffers = Array.isArray(accessoriesOffers)
6286        ? accessoriesOffers
6287        : accessoriesOffers && accessoriesOffers.offers
6288            ? accessoriesOffers.offers.offer
6289            : [];
6290    var accListOffers = [];
6291    var flattenOffers = function (offers) {
6292        if (Array.isArray(offers)) {
6293            offers.forEach(flattenOffers);
6294            return;
6295        }
6296
6297        if (offers &&
6298            (safeLower(offers.name).includes("swcomp") ||
6299                safeLower(offers.name).includes("acclist") ||
6300                safeLower(offers.name).includes("accessorieslist")) &&
6301            isDefined(offers.html)) {
6302            accListOffers.push(offers);
6303        }
6304    };
6305
6306    flattenOffers(rawOffers);
6307
6308    if (!accListOffers || !accListOffers.length) return;
6309
6310    var containerSelector = "#mastiff-pdp-accessories";
6311
6312    logInfo("AccList: starting render -", accListOffers.length, "offers");
6313
6314    // -- local helpers ----------------------------------------------------------
6315
6316    var parseFamilyKey = function (cat) { var m = (cat || "").match(/family(\d+)/i); return m ? "family" + m[1].toLowerCase() : null; };
6317    var parseCategoryKey = function (cat) { var m = (cat || "").match(/category(\d+)/i); return m ? "category" + m[1].toLowerCase() : null; };
6318    var parseOrderNum = function (key) { var m = (key || "").match(/\d+$/); return m ? parseInt(m[0], 10) : 0; };
6319    var lp = function (o) { return safeLower(o.templatePosition || ""); };
6320    var makeDivId = function (o) { return o.templatePosition + "_" + o.name; };
6321    var replaceDivId = function (html, id) { return (html || "").replace(/%divId%/g, id); };
6322
6323    // LeadOffer factory + status helpers (mirrors GDL pattern used throughout the file)
6324    var makeLeadOffer = function (divId, t) { return { OfferID: divId, OfferClicked: "no", offerShown: "no", SPOStemplate: t }; };
6325    var failLeadOffer = function (lo, reason) { lo.offerShown = "no"; lo.errorData = reason; logInfo("AccList [skip]", lo.OfferID, "-", reason); logToGlobalDataLayer(lo); };
6326    var doneLeadOffer = function (lo) { lo.offerShown = "yes"; logToGlobalDataLayer(lo); };
6327
6328    // bind Enter/Space -> click (mirrors bindActivationKeyToClick in renderWarrantyNestedOwExperiment)
6329    var bindActivation = function ($el, ns) {
6330        $el.off("keydown." + ns).on("keydown." + ns, function (e) {
6331            var k = e.key || e.which;
6332            if (k === "Enter" || k === " " || k === 13 || k === 32) { e.preventDefault(); $(this).trigger("click"); }
6333        });
6334    };
6335
6336    var sortByFamily = function (a, b) { return parseOrderNum(parseFamilyKey(a.category)) - parseOrderNum(parseFamilyKey(b.category)); };
6337    var sortByCategory = function (a, b) { return parseOrderNum(parseCategoryKey(a.category)) - parseOrderNum(parseCategoryKey(b.category)); };
6338
6339    // -- per-templatePosition required fields + HTML token replacements ---------
6340    // required: fields that must be isDefined() before the offer is rendered.
6341    // replacements: { %token% : "offerFieldName" } applied (globally) after %divId% substitution.
6342    // Token naming convention mirrors existing codebase patterns (e.g. %OWEntryOffer*Placeholder%).
6343    var accTemplateConfig = {
6344        "level0container": {
6345            required: ["html"],
6346            replacements: {
6347                "%title%": "primaryText1"
6348            }
6349        },
6350        "level0tile": {
6351            required: ["html", "imageURL", "primaryText1"],
6352            replacements: {
6353                "{title}": "primaryText1",
6354                "{imageurl}": "imageURL"
6355            }
6356        },
6357        "familycontainer": {
6358            required: ["html", "primaryText1"],
6359            replacements: {
6360                "{title}": "primaryText1"
6361            }
6362        },
6363        "categorycontainer": {
6364            required: ["html", "primaryText1"],
6365            replacements: {
6366                "{title}": "primaryText1"
6367            }
6368        },
6369        "accessorycard": {
6370            required: ["html", "imageURL", "storeURL", "primaryButtonText"],
6371            replacements: {
6372                "{title}": "primaryText1",
6373                "%imageurl%": "imageURL",
6374                "%description%": "primaryText2",
6375                "{cta}": "primaryButtonText"
6376            }
6377        }
6378    };
6379
6380    // escapeRegex: make a literal string safe for use inside RegExp (token chars like % are safe, but included for robustness)
6381    var escapeRegex = function (s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); };
6382
6383    // isOfferValid: check all required fields for the given templatePosition
6384    var isOfferValid = function (offer, pos) {
6385        var cfg = accTemplateConfig[pos] || { required: ["html"], replacements: {} };
6386        return cfg.required.every(function (f) { return isDefined(offer[f]); });
6387    };
6388
6389    // applyTemplate: replace %divId% + all config tokens in the offer html
6390    var applyTemplate = function (offer, pos) {
6391        var cfg = accTemplateConfig[pos] || { required: ["html"], replacements: {} };
6392        var html = replaceDivId(offer.html || "", makeDivId(offer));
6393        Object.keys(cfg.replacements).forEach(function (token) {
6394            html = html.replace(new RegExp(escapeRegex(token), "g"), offer[cfg.replacements[token]] || "");
6395        });
6396        return html;
6397    };
6398
6399    // -- partition offers by templatePosition ----------------------------------
6400
6401    var level0ContainerOffer = accListOffers.find(function (o) { return lp(o) === "level0container"; });
6402    var level0TileOffers = accListOffers.filter(function (o) { return lp(o) === "level0tile"; });
6403    var familyContainerOffers = accListOffers.filter(function (o) { return lp(o) === "familycontainer"; });
6404    var categoryContainerOffers = accListOffers.filter(function (o) { return lp(o) === "categorycontainer"; });
6405    var accessoryCardOffers = accListOffers.filter(function (o) { return lp(o) === "accessorycard"; });
6406
6407    logInfo("AccList: partitioned - container:", !!level0ContainerOffer,
6408        "| tiles:", level0TileOffers.length, "| families:", familyContainerOffers.length,
6409        "| categories:", categoryContainerOffers.length, "| cards:", accessoryCardOffers.length);
6410
6411    // familyHasRenderableCards: pure look-ahead - returns true when the given familyKey
6412    // has at least one valid categorycontainer that itself contains at least one valid
6413    // accessorycard. No DOM or GDL side effects. Used to pre-filter level0 tiles.
6414    var familyHasRenderableCards = function (familyKey) {
6415        if (!familyKey) return false;
6416        return categoryContainerOffers.some(function (cat) {
6417            if (parseFamilyKey(cat.category) !== familyKey || !isOfferValid(cat, "categorycontainer")) return false;
6418            var catKey = parseCategoryKey(cat.category);
6419            return accessoryCardOffers.some(function (card) {
6420                return parseFamilyKey(card.category) === familyKey &&
6421                    parseCategoryKey(card.category) === catKey &&
6422                    isOfferValid(card, "accessorycard");
6423            });
6424        });
6425    };
6426
6427    if (!level0ContainerOffer || !isOfferValid(level0ContainerOffer, "level0container")) {
6428        logInfo("AccList: no valid level0container - aborting");
6429        return;
6430    }
6431
6432    // -- wait for page placeholder ---------------------------------------------
6433
6434    var containerLo = makeLeadOffer(makeDivId(level0ContainerOffer), "45");
6435    try {
6436        await waitForElement(containerSelector, "", 5000);
6437    } catch (e) {
6438        failLeadOffer(containerLo, "Placeholder not found: " + containerSelector);
6439        return;
6440    }
6441
6442    if (!isContainerEmpty(containerSelector)) {
6443        logInfo("AccList: container not empty - skipping double-render");
6444        return;
6445    }
6446
6447    // -- insert level0container (hidden until full path confirmed) -------------
6448    // Mirrors renderWarrantyNestedOwExperiment: build DOM first, reveal only after oneFullPathRendered check
6449
6450    var level0ContainerId = containerLo.OfferID;
6451    $(containerSelector).html(applyTemplate(level0ContainerOffer, "level0container")).removeClass("hidden");
6452    // intentionally NOT calling .show() here - deferred to end of function
6453    doneLeadOffer(containerLo);
6454    logInfo("AccList: level0container built (hidden pending full-path check)", level0ContainerId);
6455
6456    var oneFullPathRendered = false;
6457
6458    // -- level0 tile menu ------------------------------------------------------
6459
6460    level0TileOffers.slice().sort(sortByFamily).forEach(function (offer) {
6461        var divId = makeDivId(offer), familyKey = parseFamilyKey(offer.category);
6462        var lo = makeLeadOffer(divId, "47");
6463        if (!isOfferValid(offer, "level0tile")) { failLeadOffer(lo, "Missing required fields"); return; }
6464        if (!familyHasRenderableCards(familyKey)) { failLeadOffer(lo, "No renderable content for family"); return; }
6465
6466        var $tile = $(applyTemplate(offer, "level0tile"));
6467        if (familyKey) $tile.attr("data-acc-family", familyKey);
6468        $tile.attr("data-offer-name", offer.name || "");
6469        $("#menuOffersContainer").append($tile);
6470        applyAccessibilityAttributes(divId, offer);
6471
6472        $tile.off(".accListNav").on("click.accListNav", function (e) {
6473            e.preventDefault();
6474            offerClickEvent(reqObj, this, false);
6475            var fk = $tile.attr("data-acc-family");
6476            if (fk) {
6477                logInfo("AccList: navigating to family", fk);
6478                $("#menuOffersContainer").hide();
6479                $("#" + level0ContainerId).children("[data-acc-family='" + fk + "']").show();
6480            }
6481        });
6482        bindActivation($tile, "accListNav");
6483        doneLeadOffer(lo);
6484    });
6485
6486    // -- family containers (hidden) + nested sub-structure --------------------
6487
6488    familyContainerOffers.slice().sort(sortByFamily).forEach(function (familyOffer) {
6489        var familyDivId = makeDivId(familyOffer), familyKey = parseFamilyKey(familyOffer.category);
6490        var familyLo = makeLeadOffer(familyDivId, "48");
6491        if (!isOfferValid(familyOffer, "familycontainer")) { failLeadOffer(familyLo, "Missing required fields"); return; }
6492
6493        var $familyDiv = $(applyTemplate(familyOffer, "familycontainer"));
6494        if (familyKey) $familyDiv.attr("data-acc-family", familyKey);
6495        $familyDiv.hide();
6496        // DOM append deferred - $familyDiv is only inserted when ≥1 category has renderable cards
6497
6498        // back button: .menuCategoryTitle -> return to level0 tile view
6499        var $backBtn = $familyDiv.find(".menuCategoryTitle");
6500        $backBtn.off(".accListBack").on("click.accListBack", function (e) {
6501            e.preventDefault();
6502            logInfo("AccList: back -> level0 from family", familyKey);
6503            $familyDiv.hide();
6504            $("#menuOffersContainer").show();
6505        });
6506        bindActivation($backBtn, "accListBack");
6507
6508        // -- category containers for this family -------------------------------
6509
6510        var familyHasCard = false;
6511        var pendingFamilyBindings = [];
6512
6513        categoryContainerOffers
6514            .filter(function (c) { return parseFamilyKey(c.category) === familyKey; })
6515            .sort(sortByCategory)
6516            .forEach(function (catOffer) {
6517                var catDivId = makeDivId(catOffer), catKey = parseCategoryKey(catOffer.category);
6518                var catLo = makeLeadOffer(catDivId, "49");
6519                if (!isOfferValid(catOffer, "categorycontainer")) { failLeadOffer(catLo, "Missing required fields"); return; }
6520
6521                var $catDiv = $(applyTemplate(catOffer, "categorycontainer"));
6522                if (catKey) $catDiv.attr("data-acc-category", catKey);
6523                // DOM append deferred - $catDiv is only inserted when ≥1 card renders below
6524
6525                // -- accessory cards for this family + category -----------------
6526
6527                var catHasCard = false;
6528
6529                accessoryCardOffers
6530                    .filter(function (card) {
6531                        return parseFamilyKey(card.category) === familyKey && parseCategoryKey(card.category) === catKey;
6532                    })
6533                    .forEach(function (cardOffer) {
6534                        var cardDivId = makeDivId(cardOffer);
6535                        var cardLo = makeLeadOffer(cardDivId, "44");
6536
6537                        // require html + storeURL + primaryButtonText - validated by accTemplateConfig["accessorycard"].required
6538                        if (!isOfferValid(cardOffer, "accessorycard")) {
6539                            failLeadOffer(cardLo, "Missing required fields");
6540                            return;
6541                        }
6542
6543                        var cardOfferForTemplate = Object.assign({}, cardOffer, {
6544                            primaryText1: (cardOffer.name || "").endsWith("_01") ? cardOffer.primaryText1 : ""
6545                        });
6546                        $catDiv.find("#menuSubCategoryOffers").append(applyTemplate(cardOfferForTemplate, "accessorycard"));
6547
6548                        // defer DOM-dependent calls until $familyDiv is in the live document
6549                        pendingFamilyBindings.push({ cardOffer: cardOffer, cardDivId: cardDivId, cardLo: cardLo });
6550                        catHasCard = true;
6551                    });
6552
6553                if (catHasCard) {
6554                    $familyDiv.find("#menuSubCategoriesContainer").append($catDiv);
6555                    logInfo("AccList: categoryContainer appended", catDivId, "| category:", catKey);
6556                    familyHasCard = true;
6557                    doneLeadOffer(catLo);
6558                } else {
6559                    failLeadOffer(catLo, "No valid cards for category");
6560                }
6561            });
6562
6563        if (familyHasCard) {
6564            $("#" + level0ContainerId).append($familyDiv);
6565            // $familyDiv is now in the live DOM - safe to query cards by id
6566            pendingFamilyBindings.forEach(function (item) {
6567                allocateRecEngPrices(item.cardOffer.strikePrice, item.cardOffer.incartPrice, item.cardDivId, item.cardOffer.currency);
6568                applyAccessibilityAttributes(item.cardDivId, item.cardOffer);
6569                addUrlAndClickEvent(item.cardDivId, item.cardOffer);
6570                doneLeadOffer(item.cardLo);
6571                logInfo("AccList: accessoryCard rendered", item.cardDivId);
6572            });
6573            logInfo("AccList: familyContainer appended (hidden)", familyDivId, "| family:", familyKey);
6574            oneFullPathRendered = true;
6575            doneLeadOffer(familyLo);
6576        } else {
6577            failLeadOffer(familyLo, "No valid cards for family");
6578        }
6579    });
6580
6581    // -- deferred reveal (same pattern as renderWarrantyNestedOwExperiment) ----
6582    // Only show #mastiff-pdp-accessories when at least one full path
6583    // (level0container -> family -> category -> accessoryCard) is confirmed rendered.
6584
6585    if (oneFullPathRendered) {
6586        $(containerSelector).removeClass("hidden");
6587        logInfo("AccList: accessories navigation visible - full path confirmed", containerSelector);
6588    } else {
6589        $(containerSelector).addClass("hidden");
6590        logInfo("AccList: no fully accessible card found - keeping", containerSelector, "hidden");
6591    }
6592}
6593// ----------- Offer rendering code ends here ----------------
6594
6595// --------------- slider code starts here -----------------
6596var slide_index = 1;
6597var myVarTimeout;
6598var sliderClassName = "";
6599var navBulletAvailable = false;
6600
6601function nextSlide(n) {
6602    displaySlides(slide_index += n);
6603}
6604
6605function currentSlide(n) {
6606    displaySlides(slide_index = n);
6607}
6608
6609function displaySlides(n) {
6610    clearTimeout(myVarTimeout);
6611    var i;
6612    var slides = document.getElementsByClassName(sliderClassName);
6613    if (navBulletAvailable) {
6614        var bullets = document.querySelectorAll(".nav-bullet");
6615    }
6616
6617    if (n > slides.length) { slide_index = 1 }
6618    if (n < 1) { slide_index = slides.length }
6619    for (i = 0; i < slides.length; i++) {
6620        slides[i].style.display = "none";
6621        if (navBulletAvailable) {
6622            bullets[i].classList.remove("nav-bullet-active");
6623        }
6624    }
6625
6626    if (slides[slide_index - 1]) {
6627        slides[slide_index - 1].style.display = "block";
6628    }
6629    if (navBulletAvailable && bullets[slide_index - 1]) {
6630        bullets[slide_index - 1].className += " nav-bullet-active";
6631    }
6632    myVarTimeout = setTimeout(showSlidesAuto, 5000);
6633}
6634
6635function showSlidesAuto() {
6636    clearTimeout(myVarTimeout);
6637    var i;
6638    var slides = document.getElementsByClassName(sliderClassName);
6639    if (navBulletAvailable) {
6640        var bullets = document.querySelectorAll(".nav-bullet");
6641    }
6642
6643    for (i = 0; i < slides.length; i++) {
6644        slides[i].style.display = "none";
6645    }
6646    if (navBulletAvailable) {
6647        for (i = 0; i < bullets.length; i++) {
6648            bullets[i].classList.remove("nav-bullet-active");
6649        }
6650    }
6651    slide_index++;
6652    if (slide_index > slides.length) { slide_index = 1 }
6653
6654    if (slides[slide_index - 1]) {
6655        slides[slide_index - 1].style.display = "block";
6656    }
6657
6658    if (navBulletAvailable && bullets[slide_index - 1]) {
6659        bullets[slide_index - 1].className += " nav-bullet-active";
6660    }
6661    myVarTimeout = setTimeout(showSlidesAuto, 5000);
6662}
6663
6664
6665// --------------- slider code ends here -----------------
6666
6667// --------------- RecEng Price Allocation code starts here -----------------
6668function allocateRecEngPrices(strikePraw, inCartPraw, divId, currency) {
6669    const $root = $("#" + (divId || ""));
6670    const $strikeDiv = $root.find(".strikePricePlaceholder");
6671    const $inCartDiv = $root.find(".incartPricePlaceholder");
6672    const $discountDiv = $root.find(".discountPercentage");
6673
6674    var locale = `${reqObj?.user?.language}-${reqObj?.user?.countryCode}`
6675        .toLowerCase();
6676
6677    locale = /^[a-z]{2}-[a-z]{2}$/.test(locale) ? locale : 'en-us';
6678
6679    const toNum = v => (v == null ? NaN : Number(v));
6680    const a = toNum(strikePraw), b = toNum(inCartPraw);
6681
6682    if ((Number.isNaN(a) && Number.isNaN(b)) || !$root.length || !isDefined(currency)) {
6683        $strikeDiv.hide(); $inCartDiv.hide(); $discountDiv.hide(); return;
6684    }
6685
6686    // determine raw strike (higher) and incart (lower)
6687    var strikeRaw = Number.isFinite(strikePraw) ? strikePraw : 0;
6688    var inCartRaw = Number.isFinite(inCartPraw) ? inCartPraw : 0;
6689    if (strikeRaw < inCartRaw && strikeRaw > 0) {
6690        [strikeRaw, inCartRaw] = [inCartRaw, strikeRaw];
6691    }
6692
6693    // identical prices => no strike price
6694    if (strikeRaw === inCartRaw) strikeRaw = 0;
6695
6696    // formatter that shows no decimals for whole numbers, 2 decimals otherwise
6697    const fmt = (value) => {
6698        if (!Number.isFinite(value) || value === 0) return null;
6699        const isInt = Number.isInteger(value);
6700        return new Intl.NumberFormat(locale, {
6701            style: "currency",
6702            currency,
6703            minimumFractionDigits: isInt ? 0 : 2,
6704            maximumFractionDigits: isInt ? 0 : 2
6705        }).format(value);
6706    };
6707
6708    const strikeFmt = fmt(strikeRaw);
6709    const inCartFmt = fmt(inCartRaw);
6710
6711    // render or hide
6712    if (strikeFmt && $strikeDiv.length)
6713        $strikeDiv.html(strikeFmt).show();
6714    else
6715        $strikeDiv.hide();
6716
6717    if (inCartFmt && $inCartDiv.length)
6718        $inCartDiv.html(inCartFmt).show();
6719    else
6720        $inCartDiv.hide();
6721
6722    // discount: only shown when strike exists and >10%
6723    if ($discountDiv.length) {
6724        if (strikeRaw > 0) {
6725            const discount = Math.round(((strikeRaw - inCartRaw) / strikeRaw) * 100);
6726            discount > 10 ? $discountDiv.html(discount + "%").show() : $discountDiv.hide();
6727        } else {
6728            $discountDiv.hide();
6729        }
6730    }
6731}
6732
6733// --------------- RecEng Price Allocation code ends here -----------------
6734
6735// --------------- Quiz Code Starts Here -----------------
6736
6737var _quizReady = null;
6738var quizReadyWatchers = [];
6739
6740var quizReadyState = new Proxy({}, {
6741    set(target, prop, value) {
6742        if (prop === "value") {
6743            _quizReady = value;
6744            logInfo(`[quizReadyState] value set to:`, value);
6745            quizReadyWatchers.forEach((cb, idx) => {
6746                logInfo(`[quizReadyState] firing watcher #${idx + 1}`);
6747                cb();
6748            });
6749            quizReadyWatchers.length = 0;
6750        }
6751        return true;
6752    },
6753    get(target, prop) {
6754        if (prop === "value") return _quizReady;
6755    }
6756});
6757
6758function waitForQuizReady() {
6759    const ready = quizReadyState.value;
6760    if (ready === true || ready === false) {
6761        logInfo("[waitForQuizReady] quizReady is known:", ready);
6762        return Promise.resolve();
6763    }
6764
6765    return new Promise((resolve) => {
6766        logInfo("[waitForQuizReady] quizReady is pending, adding to watchers");
6767        quizReadyWatchers.push(() => {
6768            logInfo("[waitForQuizReady] watcher fired, value is now:", quizReadyState.value);
6769            resolve();
6770        });
6771    });
6772}
6773
6774function handleQuizApiResponse(swReqObj) {
6775    handleApiResponse(swReqObj).then((response) => {
6776        const dashboardHuqQuiz = pgName === "dashboard" && uiState.quiztype === "huq";
6777        quizReadyState.value = response === true && !dashboardHuqQuiz;
6778
6779        if (dashboardHuqQuiz) {
6780            logInfo("[Dashboard Quiz] HUQ is not supported on the dashboard; marking Quiz Portal as unavailable.");
6781        }
6782    }).finally(() => {
6783        if (uiState.quiztype === "cpc") {
6784            $('.CPConfiguratorContainer').hide();
6785        } else if (uiState.quiztype === "huq") {
6786            $('.HUQConfiguratorContainer').hide();
6787        }
6788    });
6789}
6790
6791async function handleApiResponse(swReqObj) {
6792    try {
6793        structuredData = await getApiResponseStructuredData(swReqObj).catch((error) => {
6794            return false;
6795        });
6796
6797        const offerName = structuredData.name?.toLowerCase() || '';
6798        uiState.offerName = structuredData.name;
6799        uiState.quiztype = offerName.includes("cpc") ? "cpc" : (offerName.includes("huq") ? "huq" : null);
6800
6801        if (!uiState.quiztype) {
6802            console.error("No valid offer name found in the API response.");
6803            return false;
6804        }
6805
6806        uiState.quizCurrency = CPChardcodedContent.quizBodyContent.footer.currencies?.[quizReqOb
6806j.user.countryCode];
6807
6808        if (structuredData.products.length === 0) {
6809            console.error("No valid products found in the API response.");
6810            $('.CPConfiguratorContainer').hide();
6811            $('.HUQConfiguratorContainer').hide();
6812            return false;
6813        }
6814
6815        if (offerName.includes("cpc")) {
6816            handleCPCScenario(structuredData);
6817            return true;
6818        } else if (offerName.includes("huq")) {
6819            handleHUQScenario(structuredData);
6820            return true;
6821        } else {
6822            console.error("Unknown scenario: ", structuredData.name);
6823            return false;
6824        }
6825
6826
6827    } catch (error) {
6828        console.error("Failed to handle API response:", error);
6829    } finally {
6830        $('.HUQonfiguratorSpinner').hide();
6831        $('.CPConfiguratorSpinner').hide();
6832    }
6833}
6834
6835async function getApiResponseStructuredData(requestObject) {
6836    quizReqObj = JSON.parse(JSON.stringify(requestObject));
6837    setReqId();
6838    setMastiffSessionId();
6839    quizReqObj.user.callerId = "quizportal";
6840    quizReqObj.user.pageId = "supportweb"; //should be changed later to supportweb
6841    //quizReqObj.product.modelNumber = "7Z8K5PC";
6842    //quizReqObj.product.warranty.warrantyState = "IW";
6843
6844
6845    try {
6846        var responseData;
6847
6848
6849        if (isMastiffDebug() && window.location.protocol === "file:") {
6850            responseData = await sendDemoPostRequest(sku, warranty);
6851        } else {
6852            responseData = await sendPostRequest(apiUrl, quizReqObj);
6853        }
6854        const structuredData = extractOffers(responseData);
6855
6856        if (!structuredData) {
6857            throw new Error("Empty or malformed offer data.");
6858        }
6859
6860        logInfo("Structured Offers:", structuredData);
6861
6862        return structuredData;
6863
6864    } catch (error) {
6865        console.error('Failed to fetch or process offers:', error);
6866    }
6867}
6868
6869function removeQuizSpinner() {
6870    return waitForElement(".sposQuizSpinner")
6871        .then(spinner => { spinner?.remove(); })
6872        .catch(() => { });
6873}
6874
6875function discardQuizPortalExperience(offerName) {
6876    uiState.status = "Abondoned";
6877    if (offerName) uiState.offerName = offerName;
6878
6879    sendReportingRequest(uiState);
6880    uiState.reportAlreadySent = true;
6881
6882    uiState.results = [];
6883    uiState.acceptedSKU = "";
6884    uiState.q1 = "";
6885    uiState.q2 = "";
6886    uiState.q3 = [];
6887    uiState.total = "";
6888    uiState.userInteracted = false;
6889    uiState.matchedDirectSelection = undefined;
6890    uiState.relaxationIteration = undefined;
6891}
6892
6893$(document).on("click", ".CPConfiguratorCloseButton", function () {
6894    $(".quizPortalDiv").hide();
6895    $('.WRPrimaryTile').show();
6896    $("#mastiff-check-warranty-secondary-offers").show();
6897
6898    discardQuizPortalExperience();
6899});
6900
6901var apiUrl = getMastiffUrl();
6902
6903var cvgTypeTooltips = {};
6904var matchedCarePack = undefined;
6905var quizSubmitted = false;
6906var analyzedCarepacks = {};
6907
6908var answerClicked = 0;
6909var cvgTypeClicked = false;
6910
6911var checkboxType = {
6912    format: "",
6913    state: "",
6914    location: "",
6915    style: "",
6916    dependenciesIDs: "",
6917    exclusionsIDs: ""
6918};
6919
6920var quizReqObj = {
6921    requestId: "",
6922    offerLocations: "primary,shop1,shop2,shop3,secondary",
6923    offerName: "",
6924    acceptanceLevel: "",
6925    consent: "",
6926    user: {
6927        callerId: "quizportal",
6928        sessionId: "",
6929        pageId: "supportweb",
6930        intent: "",
6931        locale: "us-en",
6932        countryCode: "us",
6933        language: "en",
6934    },
6935    product: {
6936        carePackEligible: "",
6937        modelNumber: "",
6938        serialNumber: "",
6939        warranty: {
6940            warrantyState: "",
6941            warrantyStartdate: "",
6942            warrantyEnddate: "",
6943
6944        }
6945    }
6946};
6947
6948var availableCarepacks = [];
6949var resultHUQOffers;
6950var structuredData = {};
6951var uiState = {};
6952
6953var pendingReportTimeoutId = null;
6954var REPORT_DELAY_MS = 60 * 1000 * 15;
6955
6956
6957async function prepareInitialUi(warranty = null) {
6958    uiState.userInteracted = false;
6959    uiState.reportAlreadySent = false;
6960
6961    $(document).on('click', '.CPConfiguratorContainer, .HUQConfiguratorContainer', function () {
6962        if (quizSubmitted) return;
6963
6964        uiState.userInteracted = true;
6965        uiState.status = "Not Completed";
6966    });
6967
6968    await sendPendingReport();
6969
6970    $('.CPConfiguratorContainer').hide();
6971    $('.HUQConfiguratorContainer').hide();
6972    $('.CPConfiguratorSpinner').hide();
6973    $('.HUQonfiguratorSpinner').hide();
6974
6975    if (warranty === "PW" || warranty === "IW") {
6976        $('.CPConfiguratorSpinner').show();
6977    }
6978
6979    if (warranty === "OW") {
6980        $('.HUQonfiguratorSpinner').show();
6981    }
6982
6983
6984}
6985
6986$(document).on("click", ".CPConfiguratorStartButton", function () {
6987    $('.CPConfiguratorSpinner').show();
6988    (async () => { const structuredData = await CPC_API.getApiReesponseStructuredData(); })();
6989    const analyzedCarepacks = analyzeCarepacks(availableCarepacks.products);
6990    displayAnswers(analyzedCarepacks);
6991    $('.CPConfiguratorSpinner').hide();
6992    $('.CPConfiguratorContainer').show();
6993});
6994
6995$(document).on("click", ".CPConfiguratorAnswerLabel", function () {
6996    if (Date.now() - answerClicked < 100) return;
6997    if (uiState.quiztype === "cpc") {
6998        if ($(this).find('input[type="radio"]:disabled').length === 0 && $(this).find('input[type="checkbox"]:disabled').length === 0) {
6999            var $answeredQuestion;
7000
7001            if ($(this).hasClass('CPConfiguratorAnswerduration')) {
7002                $(this).find('input[type="radio"]').prop('checked', true);
7003                $answeredQuestion = $('.CPConfiguratorItem').eq(0);
7004                $('.CPConfiguratorItem').eq(1).find('.CPConfiguratorAnswers').hide();
7005                const displayedCoverageTypes = `#CPConfiguratorAnswerscoverageType__${$(this).attr('id')}`;
7006                $(displayedCoverageTypes).css('display', 'flex');
7007
7008                if (answerClicked) {
7009                    $(displayedCoverageTypes).find('input[type="radio"]').first().prop('checked', true).trigger('change')
7010                    $answeredQuestion = $('.CPConfiguratorItem:lt(2)');
7011                }
7012                $('.CPConfiguratorItem').eq(2).find('.CPConfiguratorAnswers').hide();
7013                $(`#CPConfiguratorAnswersfeature__${$(displayedCoverageTypes).find('input[type="radio"]').first().closest('label').attr('id')}`).css('display', 'flex');
7014                adjustQuestion($('.CPConfiguratorItem').eq(1), 'unchecked');
7015
7016            }
7017            if ($(this).hasClass('CPConfiguratorAnswercoverageType')) {
7018                $(this).find('input[type="radio"]').prop('checked', true);
7019                $answeredQuestion = $('.CPConfiguratorItem').eq(1);
7020                $('.CPConfiguratorItem').eq(2).find('.CPConfiguratorAnswers').hide();
7021                $(`#CPConfiguratorAnswersfeature__${$(this).attr('id')}`).css('display', 'flex');
7022            }
7023            setTimeout(() => {
7024                if ($(this).hasClass('CPConfiguratorAnswerfeature')) {
7025                    $answeredQuestion = $('.CPConfiguratorItem').eq(2);
7026                }
7027                const thirdQuestion = $('.CPConfiguratorItem').eq(2),
7028                    secondQuestionSelected = $('#CPConfiguratorAnswerscoverageType__' + $($('input[name="duration"]:checked')).closest('label').attr('id')).find('input[type="radio"]:checked').length !== 0,
7029                    thirdQuestionEmpty = $('#CPConfiguratorAnswersfeature__' + $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').attr('id')).find('input[type="checkbox"]').length === 0,
7030                    thirdQuestionSelected = $('#CPConfiguratorAnswersfeature__' + $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').attr('id')).find('input[type="checkbox"]:checked').length > 0;
7031
7032                if (secondQuestionSelected) {
7033                    adjustQuestion(thirdQuestion, thirdQuestionEmpty ? 'disabled:checked' : thirdQuestionSelected ? 'checked' : 'unchecked');
7034                    cvgTypeClicked = true;
7035                }
7036
7037                var isChecked = ($(this).closest('.CPConfiguratorAnswers').find('input[type="checkbox"]:checked').length > 0 || $(this).closest('.CPConfiguratorAnswers').find('input[type="radio"]:checked').length > 0);
7038                if (isChecked) {
7039                    adjustQuestion($answeredQuestion, 'checked');
7040                } else {
7041                    $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive');
7042                    adjustQuestion($answeredQuestion, 'unchecked');
7043                }
7044                if ($(this).hasClass('CPConfiguratorAnswerfeature') || ($(this).hasClass('CPConfiguratorAnswercoverageType')) || $(this).hasClass('CPConfiguratorAnswerduration')) {
7045                    var currentID = $(this).hasClass('CPConfiguratorAnswerfeature') ? `#${$(this).closest('.CPConfiguratorAnswers').attr('id')}` : $(this).hasClass('CPConfiguratorAnswercoverageType') ? `#CPConfiguratorAnswersfeature__${$(this).attr('id')}` : $(this).hasClass('CPConfiguratorAnswerduration') ? `#CPConfiguratorAnswersfeature__${$(`#CPConfiguratorAnswerscoverageType__${$(this).attr('id')}`).find('input[type="radio"]').first().closest('label').attr('id')}` : "";
7046                    if ($(currentID).find('div.CPCnoAddonNotif').length == 0) {
7047                        $(`${currentID} > div`).each(function () {
7048                            const deps = $(this).data('dependencies');
7049
7050                            const allChecked = deps
7051                                .split(' ')
7052                                .map(id => id.trim())
7053                                .filter(id => id.length > 0)
7054                                .every(id => $('#' + id).find('input[type="checkbox"]').prop('checked'));
7055
7056                            const excls = $(this).data('exclusions');
7057
7058                            const anyExcl = excls
7059                                .split(' ')
7060                                .map(id => id.trim())
7061                                .filter(id => id.length > 0)
7062                                .some(id => $('#' + id).find('input[type="checkbox"]').prop('checked'));
7063
7064                            var selectedDuration = $('input[name="duration"]:checked').closest('label').text().trim(),
7065                                selectedcoverageType = $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(),
7066                                selectedFeatures = $(`input[name=${selectedcoverageType.replace(/\s+/g, '_')}__${selectedDuration.replace(/\s+/g, '_')}]:checked`).map(function () { return $(this).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(); }).get();
7067
7068                            if (!$(this).find('input[type="checkbox"]:checked').length)
7069                                selectedFeatures.push(($(this).find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim()));
7070
7071                            var isAddon = availableCarepacks.products.some(carePack =>
7072                                carePack.answers?.q1 === selectedDuration &&
7073                                carePack.answers?.q2 === selectedcoverageType &&
7074                                Array.isArray(carePack.answers?.q3) &&
7075                                selectedFeatures.length === carePack.answers.q3.length &&
7076                                selectedFeatures.every(f => carePack.answers.q3.includes(f))
7077                            );
7078
7079
7080                            if (allChecked && !anyExcl && isAddon || $(this).hasClass('CPConfiguratorAnswerChild') && !anyExcl && isAddon || $(this).hasClass('CPConfiguratorAnswerStandalone') && !anyExcl && isAddon) {
7081                                $(this).find('input:checkbox:disabled').each(function () {
7082                                    if ($(this).hasClass('CPConfiguratorAnswerHasRootParents') || $(this).hasClass('CPConfiguratorAnswerStandalone')) {
7083                                        $(this).prop('disabled', false);
7084                                    }
7085                                    $(this).find('label').removeClass('CPConfiguratorAnswerDisabled');
7086
7087                                })
7088                                if (!$(this).hasClass('CPConfiguratorAnswerStandalone')) {
7089                                    $(this).find('input:checkbox:disabled').prop('checked', true);
7090                                    $(this).find('input:checkbox:not(:disabled)').prop('disabled', false);
7091                                } else {
7092                                    $(this).find('input:checkbox:disabled').prop('disabled', false);
7093                                    $(this).find('label').removeClass('CPConfiguratorAnswerDisabled');
7094
7095                                }
7096                            } else if (anyExcl || !isAddon) {
7097                                $(this).find('label').addClass('CPConfiguratorAnswerDisabled');
7098
7099                                $(this).find('input:checkbox:disabled').prop('checked', false);
7100                                $(this).find('input:checkbox:not(:disabled)').prop('disabled', true);
7101                                $(this).find('input:checkbox:not(:disabled):checked').prop('disabled', true).prop('checked', false);
7102                            } else if (!allChecked) {
7103                                $(this).find('input:checkbox:disabled').prop('checked', false);
7104                                $(this).find('input:checkbox:not(:disabled):not(:checked)').prop('disabled', true);
7105
7106                                $(this).find('input:checkbox:not(:disabled):not(:checked)').each(function () {
7107                                    if ($(this).hasClass('CPConfiguratorAnswerHasRootParents')) {
7108                                        $(this).prop('disabled', true);
7109                                    }
7110                                });
7111                            }
7112                        });
7113                    }
7114                }
7115                captureSelectedElements();
7116                if (matchedCarePack !== undefined) {
7117                    allocateQuizPrices(matchedCarePack.strikePrice, matchedCarePack.incartPrice, ".CPConfiguratorResultSubmissionTotal");
7118                    $('.CPConfiguratorResultSubmissionButton').addClass('CPConfiguratorResultSubmissionButtonActive');
7119                } else {
7120                    $('.CPConfiguratorResultSubmissionTotalPrice').html(uiState.quizCurrency.replace("%price%", '0'));
7121                    $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive');
7122                }
7123
7124            }, 0);
7125
7126        }
7127    } else if (uiState.quiztype === "huq") {
7128        const answerClasses = ['location', 'type', 'features'];
7129        const questionIndexes = [3, 4, 5];
7130
7131        if (answerClicked === 0) {
7132            answerClasses.forEach((answerClass, index) => {
7133                if ($(this).hasClass('CPConfiguratorAnswer' + answerClass)) {
7134                    const $answeredQuestion = $('.CPConfiguratorItem').eq(questionIndexes[index]);
7135                    adjustQuestion($answeredQuestion, 'checked');
7136                }
7137            });
7138            setTimeout(captureSelectedElements, 0);
7139        } else {
7140            setTimeout(() => {
7141                answerClasses.forEach((answerClass, index) => {
7142                    const $answeredQuestion = $('.CPConfiguratorItem').eq(questionIndexes[index]);
7143                    if ($(this).hasClass('CPConfiguratorAnswer' + answerClass)) {
7144                        if (answerClass === 'features') {
7145                            const isChecked = $('input[name="features"]:checked').length > 0;
7146                            adjustQuestion($answeredQuestion, isChecked ? 'checked' : 'unchecked');
7147                        } else {
7148                            adjustQuestion($answeredQuestion, 'checked');
7149                        }
7150                    }
7151                });
7152
7153                captureSelectedElements();
7154
7155                const allAnswered = answerClasses.every(
7156                    name => $('input[name="' + name + '"]:checked').length > 0
7157                );
7158                $('.CPConfiguratorResultSubmissionButton').toggleClass(
7159                    'CPConfiguratorResultSubmissionButtonActive',
7160                    allAnswered
7161                );
7162            }, 0);
7163        }
7164
7165
7166    }
7167    answerClicked = Date.now();
7168});
7169
7170$(document).on("click", ".CPConfiguratorResultSubmissionButtonActive", function () {
7171    logInfo("submit clicked");
7172    cvgTypeClicked = false;
7173    $('.CPConfiguratorBody').addClass('CPConfiguratorBodyDisabled');
7174    $('.CPConfiguratorResultSubmission').hide();
7175    $('.CPConfiguratorCloseButton').hide();
7176    $('.CPConfiguratorResetButton').css('display', 'flex');
7177    adjustQuestion($('.CPConfiguratorItem'), 'disabled:checked');
7178
7179    quizSubmitted = true;
7180    uiState.status = "Completed";
7181
7182    if (uiState.quiztype === "cpc") {
7183        allocateQuizPrices(matchedCarePack.strikePrice, matchedCarePack.incartPrice, ".CPConfiguratorResultOfferHeaderPrice");
7184        $('.CPConfiguratorResultOfferDescription').text(matchedCarePack.skuName);
7185        uiState.results.push(matchedCarePack.productSKU);
7186        uiState.offerResults.push(matchedCarePack);
7187
7188        $('.CPConfiguratorResultOfferCTA')
7189            .off('click')
7190            .on('click', function () {
7191                uiState.acceptedSKU = matchedCarePack.productSKU;
7192                sendReportingRequest(uiState);
7193                uiState.reportAlreadySent = true;
7194                window.open(matchedCarePack.storeURL, '_blank');
7195            });
7196
7197        $('.CPConfiguratorResultOffer').css('display', 'flex');
7198    }
7199
7200    if (uiState.quiztype === "huq") {
7201        const offerTypes = [
7202            { key: 'budgetFriendly', pricesWrapper: '.HUQBudgetFriendlyPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQBudgetFriendly' },
7203            { key: 'recommended', pricesWrapper: '.HUQRecommendedForYouPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQRecommended' },
7204            { key: 'mostPopular', pricesWrapper: '.HUQMostPopularPrice', CTA: '.CPConfiguratorResultSubmissionButtonHUQMostPopular' }
7205        ];
7206
7207        resultHUQOffers = getRecommendedProductSet(structuredData.products, uiState);
7208
7209        offerTypes.forEach((offerType, index) => {
7210            const offer = resultHUQOffers[offerType.key];
7211            uiState.results.push(offerType.key + "_" + offer.productSKU);
7212            uiState.offerResults.push(offer);
7213            $('.CPConfiguratorResultOfferSectionHUQOfferImg').eq(index).attr('src', offer.imageURL);
7214            $('.CPConfiguratorResultOfferSectionHUQOfferDescription').eq(index).text(offer.skuName);
7215            allocateQuizPrices(offer.strikePrice, offer.incartPrice, offerType.pricesWrapper);
7216
7217            $(offerType.CTA)
7218                .off('click')
7219                .attr('id', offer.productSKU)
7220                .on('click', () => {
7221                    uiState.acceptedSKU = $(offerType.CTA).attr('id');
7222                    sendReportingRequest(uiState);
7223                    uiState.reportAlreadySent = true;
7224                    window.open(offer.storeURL, '_blank');
7225                });
7226        });
7227
7228        $('.CPConfiguratorResultOfferSectionHUQ').css('display', 'flex');
7229    }
7230
7231    $('.CPConfiguratorResult').removeClass('CPConfiguratorResultSticky');
7232    $('.CPConfiguratorBody')[0]?.scrollIntoView({ behavior: 'smooth', block: 'end' });
7233});
7234
7235
7236$(document).on("click", ".CPConfiguratorResetButton", function () {
7237    logInfo("reset clicked")
7238    if (uiState.quiztype === "cpc") {
7239        $('.CPConfiguratorResultOffer').hide();
7240        adjustQuestion($('.CPConfiguratorItem').eq(0), 'unchecked');
7241        adjustQuestion($('.CPConfiguratorItem:gt(0):lt(3)'), 'disabled:unchecked')
7242        $('.CPConfiguratorResultSubmissionTotalPrice').html(uiState.quizCurrency.replace("%price%", '0'));
7243        $('.CPConfiguratorAnswerActive').prop('checked', false);
7244
7245    }
7246    if (uiState.quiztype === "huq") {
7247        $('.CPConfiguratorResultOfferSectionHUQ').hide();
7248        $('.CPConfiguratorResultOfferSectionHUQOfferImg').attr("src", "");
7249
7250        adjustQuestion($('.CPConfiguratorItem').eq(3), 'unchecked');
7251        adjustQuestion($('.CPConfiguratorItem').eq(4), 'unchecked');
7252        adjustQuestion($('.CPConfiguratorItem').eq(5), 'unchecked');
7253        $('.CPConfiguratorAnswerActive').prop('checked', false);
7254        $('input[name="location"]').prop('checked', false);
7255        $(`input[name="type"]`).prop('checked', false);
7256        $(`input[name="features"]`).prop('checked', false);
7257    }
7258
7259    $('.CPConfiguratorResultSubmission').css('display', 'flex');
7260    $('.CPConfiguratorBody').removeClass('CPConfiguratorBodyDisabled');
7261
7262
7263    $('.CPConfiguratorResultSubmissionButton').removeClass('CPConfiguratorResultSubmissionButtonActive');
7264    $('.CPConfiguratorCloseButton').css('display', 'flex');
7265    $('.CPConfiguratorResetButton').hide();
7266    $('.CPConfiguratorResult').addClass('CPConfiguratorResultSticky');
7267    answerClicked = 0;
7268    quizSubmitted = false;
7269    cvgTypeClicked = false;
7270
7271    if (!uiState.reportAlreadySent) {
7272        sendReportingRequest(uiState);
7273    }
7274
7275    uiState.results = [];
7276    uiState.acceptedSKU = "";
7277    uiState.q1 = "";
7278    uiState.q2 = "";
7279    uiState.q3 = [];
7280    uiState.total = "";
7281    uiState.userInteracted = false;
7282    uiState.reportAlreadySent = false;
7283    uiState.matchedDirectSelection = undefined;
7284    uiState.relaxationIteration = undefined;
7285
7286});
7287
7288
7289document.addEventListener("visibilitychange", () => {
7290    if (document.visibilityState === "hidden") {
7291        if (uiState.userInteracted && !uiState.reportAlreadySent && !pendingReportTimeoutId) {
7292            pendingReportTimeoutId = setTimeout(() => {
7293                sendReportingRequest(uiState);
7294                uiState.reportAlreadySent = true;
7295                pendingReportTimeoutId = null;
7296            }, REPORT_DELAY_MS);
7297        }
7298    }
7299});
7300
7301window.addEventListener("beforeunload", () => {
7302    if (uiState.userInteracted && !uiState.reportAlreadySent) {
7303        localStorage.setItem("quiz_lastState", JSON.stringify(uiState));
7304    }
7305    _quizReady = null;
7306    quizReadyState.value = null;
7307});
7308
7309function adjustQuestion(selectedQuestions, status) {
7310    const locate = selectedQuestions.find.bind(selectedQuestions);
7311    const icon = locate('.CPConfiguratorQuestionIcon');
7312    const text = locate('.CPConfiguratorQuestionText');
7313    const index = locate('.CPConfiguratorQuestionIconIndex');
7314    const imgActive = locate('.CPConfiguratorQuestionIconImgActive');
7315    const imgDisabled = locate('.CPConfiguratorQuestionIconImgDisabled');
7316    const inputs = quizSubmitted || !cvgTypeClicked ? locate('.CPConfiguratorAnswerActive') : locate('.CPConfiguratorAnswer').not('.CPConfiguratorAnswerStandalone:has(input[disabled])').find('.CPConfiguratorAnswerActive');
7317    const labels = quizSubmitted || !cvgTypeClicked ? locate('.CPConfiguratorAnswerLabelActive') : locate('.CPConfiguratorAnswer').not('.CPConfiguratorAnswerStandalone:has(input[disabled])').find('.CPConfiguratorAnswerLabelActive');
7318    if (status === "disabled:checked") {
7319        imgActive.hide();
7320        imgDisabled.show();
7321        icon.addClass('CPConfiguratorQuestionIconDisabled');
7322        selectedQuestions.removeClass('CPConfiguratorItemActive').addClass('CPConfiguratorItemActiveDisabled');;
7323        text.addClass('CPConfiguratorQuestionTextDisabled');
7324        index.hide();
7325        if (!cvgTypeClicked)
7326            inputs.prop('disabled', true);
7327        labels.addClass('CPConfiguratorAnswerDisabled');
7328    } else if (status === "checked") {
7329        selectedQuestions.addClass('CPConfiguratorItemActive').removeClass('CPConfiguratorItemActiveDisabled');
7330        icon.addClass('CPConfiguratorQuestionIconActive').removeClass('CPConfiguratorQuestionIconDisabled');
7331        index.hide();
7332        imgActive.show();
7333        imgDisabled.hide();
7334        inputs.prop('disabled', false);
7335        labels.removeClass('CPConfiguratorAnswerDisabled');
7336
7337    } else if (status === "unchecked") {
7338        icon.removeClass('CPConfiguratorQuestionIconDisabled CPConfiguratorQuestionIconActive');
7339        text.removeClass('CPConfiguratorQuestionTextDisabled');
7340        imgActive.hide();
7341        selectedQuestions.removeClass('CPConfiguratorItemActive CPConfiguratorItemActiveDisabled');
7342        index.show();
7343        imgDisabled.hide();
7344        inputs.prop('disabled', false);
7345        labels.removeClass('CPConfiguratorAnswerDisabled');
7346
7347    } else if (status === "disabled:unchecked") {
7348        imgActive.hide();
7349        imgDisabled.hide();
7350        icon.removeClass('CPConfiguratorQuestionIconActive').addClass('CPConfiguratorQuestionIconDisabled');
7351        selectedQuestions.removeClass('CPConfiguratorItemActive').addClass('CPConfiguratorItemActiveDisabled');
7352        text.addClass('CPConfiguratorQuestionTextDisabled');
7353        index.show();
7354        inputs.prop('disabled', true);
7355        labels.addClass('CPConfiguratorAnswerDisabled');
7356    }
7357};
7358
7359function captureSelectedElements() {
7360    if (uiState.quiztype === "cpc") {
7361        var selectedDuration = $('input[name="duration"]:checked').closest('label').text().trim(),
7362            selectedcoverageType = $(`input[name="${$('input[name="duration"]:checked').closest('label').attr('id')}"]:checked`).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(),
7363            selectedFeatures = $(`input[name=${selectedcoverageType.replace(/\s+/g, '_')}__${selectedDuration.replace(/\s+/g, '_')}]:checked`).map(function () { return $(this).closest('label').find('span:first').contents().filter((_, el) => el.nodeType === 3).first().text().trim(); }).get();
7364        matchedCarePack = availableCarepacks.products.find(carePack =>
7365            carePack.answers?.q1 === selectedDuration &&
7366            carePack.answers?.q2 === selectedcoverageType &&
7367            Array.isArray(carePack.answers?.q3) &&
7368            selectedFeatures.length === carePack.answers.q3.length &&
7369            selectedFeatures.every(f => carePack.answers.q3.includes(f))
7370        );
7371        const features = analyzedCarepacks[selectedDuration][selectedcoverageType],
7372            total = Object.values(features ?? {})?.[0]?.total ?? "";
7373
7374
7375        uiState = {
7376            ...uiState,
7377            q1: selectedDuration || "",
7378            q2: selectedcoverageType || "",
7379            q3: selectedFeatures.map(feature => {
7380                const freq = features[feature]?.frequency ?? 1;
7381                return `${feature}_${freq}`;
7382            }) || [],
7383            total: total,
7384            results: [],
7385            offerResults: [],
7386            acceptedSKU: ""
7387        }
7388    };
7389    if (uiState.quiztype === "huq") {
7390        var selectedLocationId = $('input[name="location"]:checked').closest('label').attr('id') || "";
7391        var selectedTypeId = $('input[name="type"]:checked').closest('label').attr('id') || "";
7392        var selectedFeatureIds = $('input[name="features"]:checked').map(function () {
7393            return $(this).closest('label').attr('id');
7394        }).get();
7395
7396        uiState = {
7397            ...uiState,
7398            q1: selectedLocationId,
7399            q2: selectedTypeId,
7400            q3: selectedFeatureIds,
7401            results: [],
7402            offerResults: [],
7403            acceptedSKU: ""
7404        }
7405    }
7406
7407};
7408
7409function displayHUQAnswers(q1, q2, q3) {
7410    const hardcodedAnswers = HUQhardcodedContent.quizBodyContent.answers;
7411    const countryCode = quizReqObj.user.countryCode;
7412
7413    [
7414        { answers: q1, category: 'location', type: 'radio', wrapper: 'HUQAnswersLocation' },
7415        { answers: q2, category: 'type', type: 'radio', wrapper: 'HUQAnswersType' },
7416        { answers: q3, category: 'features', type: 'checkbox', wrapper: 'HUQAnswersFeatures' },
7417    ].forEach(({ answers, category, type, wrapper }) =>
7418        answers.forEach(answer =>
7419            displayAnswer(category, (hardcodedAnswers[answer]?.[countryCode]) || answer, type, wrapper, answer, category)
7420        )
7421    );
7422
7423    $('.CPConfiguratorItem input:not(:disabled)').addClass('CPConfiguratorAnswerActive')
7424        .closest('label').addClass('CPConfiguratorAnswerLabelActive');
7425
7426    $('.HUQConfiguratorContainer').show();
7427}
7428
7429
7430function displayAnswers(analyzedCarepacks) {
7431    const durations = Object.keys(analyzedCarepacks);
7432    durations.forEach(duration => {
7433        var coverageTypes = Object.keys(analyzedCarepacks[duration]),
7434
7435            durationWrapper = 'CPConfiguratorAnswersduration',
7436            coverageTypesWrapper = `CPConfiguratorAnswerscoverageType__${duration.replace(/\s+/g, '_')}`;
7437        $($('.CPConfiguratorItem')[1]).append(`<div id="${coverageTypesWrapper}" class="CPConfiguratorAnswers"></div>`);
7438        displayAnswer('duration', duration, "radio", durationWrapper, duration, 'duration');
7439
7440        coverageTypes.forEach(coverageType => {
7441            var featuresWrapper = `CPConfiguratorAnswersfeature__${coverageType.replace(/\s+/g, '_')}__${duration.replace(/\s+/g, '_')}`;
7442
7443            $($('.CPConfiguratorItem')[2]).append(`<div id="${featuresWrapper}" class="CPConfiguratorAnswers"></div>`);
7444            displayAnswer('coverageType', coverageType, "radio", coverageTypesWrapper, coverageType + "__" + duration, duration);
7445            const features = Object.keys(analyzedCarepacks[duration][coverageType]);
7446            if (features.length === 0) $("#" + featuresWrapper).append('<style> .CPCnoAddonNotif { font-size: 16px; line-height: 22px; color: #767676; display: flex; margin-bottom: 20px; } </style> <div class=CPCnoAddonNotif>No additional selections are required for this option.</div>')
7447
7448            features.forEach(feature => {
7449                const featureData = analyzedCarepacks[duration][coverageType][feature];
7450                if (featureData.dependencies.length === 0 && featureData.exclusions.length === 0 && featureData.standalone) {
7451                    featureData.commonFeature = true;
7452                }
7453            });
7454            features.forEach(feature => {
7455
7456                const featureData = analyzedCarepacks[duration][coverageType][feature];
7457                const frequency = featureData.frequency, dependencies = featureData.dependencies, exclusions = featureData.exclusions, standalone = featureData.standalone;
7458
7459                checkboxType.format = "toggle";
7460                exclusions.forEach((exclusion) => {
7461                    checkboxType.exclusionsIDs += (exclusion + "__" + coverageType + "__" + duration).replace(/\s+/g, '_') + ' ';
7462                })
7463
7464                var dependancyTree = {
7465                    rootParents: [],
7466                    directParents: [],
7467                    dependantSiblings: [],
7468                    independantSiblings: []
7469                }
7470                dependencies.forEach((dependency, index) => {
7471                    if ((analyzedCarepacks[duration][coverageType][dependencies[index]].dependencies.length === 0)) {
7472                        dependancyTree.rootParents.push(dependency);
7473                    } else if (!analyzedCarepacks[duration][coverageType][dependencies[index]].dependencies.includes(feature)) {
7474                        dependancyTree.directParents.push(dependency);
7475                    } else {
7476                        dependancyTree.dependantSiblings.push(dependency);
7477                    }
7478                    dependancyTree.independantSiblings = features.filter(x => !exclusions.includes(x) && !dependencies.includes(x) && x !== feature);
7479
7480                    checkboxType.dependenciesIDs += (dependency + "__" + coverageType + "__" + duration).replace(/\s+/g, '_') + ' ';
7481                });
7482
7483                if (frequency === 1 && dependencies.length === 0 && exclusions.length === 0 && !standalone) {
7484
7485                    checkboxType.format = "toggle";
7486                    checkboxType.state = "checked disabled";
7487
7488                } else if (dependencies.length === 0 && exclusions.length === 0 && standalone) {
7489
7490                    checkboxType.format = features.length > 1 ? "checkbox" : "toggle";
7491
7492                } else if (dependencies.length === 0 && exclusions.length !== 0) {
7493                    if (dependancyTree.independantSiblings.length === 0) {
7494
7495                        checkboxType.style = "CPConfiguratorAnswerStandalone";
7496                    }
7497
7498                }
7499                else {
7500                    if (dependancyTree.independantSiblings.length > 0 && dependancyTree.dependantSiblings.length === 0) {
7501                        checkboxType.format = "checkbox";
7502
7503                    } else if (dependancyTree.dependantSiblings.length === 0) {
7504                        checkboxType.format = "toggle";
7505                    } else if (dependancyTree.dependantSiblings.length > 0) {
7506                        checkboxType.format = "toggle";
7507                    }
7508                    var siblingDisplayed = false;
7509
7510                    dependancyTree.dependantSiblings.forEach(dependantSibling => {
7511                        siblingDisplayed = ($("#" + (dependantSibling + "__" + coverageType + "__" + duration).replace(/\s+/g, '_'))).length > 0;
7512                    });
7513
7514                    if (dependancyTree.directParents.length !== 0 || siblingDisplayed) {
7515                        checkboxType.style = "CPConfiguratorAnswerSubChild";
7516                        checkboxType.state = "disabled"
7517                    } else if (dependancyTree.rootParents.length !== 0) {
7518                        checkboxType.style = "CPConfiguratorAnswerChild";
7519
7520                        if ($("#" + (dependancyTree.rootParents[0] + "__" + coverageType + "__" + duration).replace(/\s+/g, '_')).find('input[type="checkbox"]:disabled:not(:checked)').length === 0)
7521                            checkboxType.style = "CPConfiguratorAnswerChild CPConfiguratorAnswerHasRootParents";
7522
7523                    }
7524
7525                }
7526                displayAnswer('feature', feature, 'checkbox', featuresWrapper, feature + "__" + coverageType + "__" + duration, coverageType + "__" + duration, checkboxType);
7527                checkboxType = {
7528                    format: "",
7529                    state: "",
7530                    location: "",
7531                    style: "",
7532                    dependenciesIDs: "",
7533                    exclusionsIDs: ""
7534                };
7535            });
7536
7537        });
7538        $('.CPConfiguratorContainer').show();
7539
7540        $('.CPConfiguratorItem').find('.CPConfiguratorAnswer input:not(:disabled)').addClass('CPConfiguratorAnswerActive').closest('label').addClass('CPConfiguratorAnswerLabelActive');
7541        adjustQuestion($('.CPConfiguratorItem:gt(0):lt(3)'), 'disabled:unchecked')
7542
7543    });
7544    $('.CPConfiguratorAnswer:not(:has(label.CPConfiguratorToggle))').each(function () {
7545        $(this).appendTo($(this).parent());
7546    });
7547};
7548
7549function displayAnswer(answerType, answerValue, inputType, wrapperID, answerID, inputName, checkboxType = { format: "", state: "", location: "", style: "", dependenciesIDs: "", exclusionsIDs: "" }) {
7550    if (uiState.quiztype === "cpc") {
7551        var tooltipContent = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.summary || (wrapperID.includes("coverageType") ? cvgTypeTooltips[answerValue] : ''),
7552            tooltipBenefits = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.benefits,
7553            idealForText = CPChardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerValue]?.idealFor || "",
7554            idealForPrefix = isDefined(idealForText) ? CPChardcodedContent?.tooltipsContent?.prefix?.[quizReqObj.user.countryCode] : "",
7555            tooltipIdealFor = idealForText !== "" ? '<div style="height: 10px"></div><span style="color:#418d3c">' + idealForPrefix + '</span>' + idealForText : "",
7556            benefitsDiv = tooltipBenefits !== undefined ? ('<br><div style="height: 10px"></div>' + tooltipBenefits.map(benefit => `<img class="" src="https://hp.widen.net/content/th8nrqkmot/png/CPC_Checkmark.png" alt="" style="display: inline; width:12.5px; margin-right: 5px">${benefit}<br>`).join('')) : "";
7557    } else if (uiState.quiztype === "huq") {
7558        var tooltipContent = HUQhardcodedContent?.tooltipsContent?.text?.[quizReqObj.user.countryCode]?.[answerID]?.summary || '', tooltipBenefits = "", benefitsDiv = "", tooltipIdealFor = "";
7559    }
7560    var tooltipdiv = tooltipContent ? `<span class=CPConfiguratorAnswerTooltipDiv><img class=CPConfiguratorAnswerTooltip src=https://hp.widen.net/content/w27rpukk05/svg/CPC_toolTip.svg><div class=CPConfiguratorAnswerTooltipBubbleChip></div></span><div class=CPConfiguratorAnswerTooltipBubble><div class=CPConfiguratorAnswerTooltipBubbleText>${tooltipContent + benefitsDiv + tooltipIdealFor}</div></div>` : '',
7561        answerDiv = `<div data-dependencies="${checkboxType.dependenciesIDs}" data-exclusions="${checkboxType.exclusionsIDs}" class="${checkboxType.style} CPConfiguratorAnswer CPConfigurator${answerType}Row"><label id="${answerID.replace(/\s+/g, '_')}" class="${checkboxType.format === "toggle" ? 'CPConfiguratorToggle' : ""} ${checkboxType.state === "disabled" || checkboxType.state === "checked disabled" ? 'CPConfiguratorAnswerDisabled' : ""} CPConfiguratorAnswerLabel CPConfiguratorAnswer${answerType}"><input ${checkboxType.state} class=CPConfiguratorAnswer${answerType}Button tabindex=0 type="${inputType}" name="${inputName.replace(/\s+/g, '_')}" />${checkboxType.format === "toggle" ? '<div class="CPConfiguratorSlider"> <div class="CPConfiguratorSliderCircle"></div></div>' : ""}<span>${answerValue}&nbsp;${tooltipdiv}</span></label></div>`;
7562    $("#" + wrapperID).append(answerDiv);
7563};
7564
7565function allocateQuizPrices(strikePrice, incartPrice, priceWrapper) {
7566    const strikeDiv = $(priceWrapper).find(".strikePricePlaceholder"),
7567        incartDiv = $(priceWrapper).find(".incartPricePlaceholder"),
7568        discountDiv = $(priceWrapper).find(".discountPercentage");
7569    if ((strikePrice || incartPrice) && strikePrice !== 0 && incartPrice !== 0) {
7570        const f = p => Number.isInteger(p) ? p : p.toFixed(2),
7571            s0 = Math.max(strikePrice, incartPrice),
7572            i0 = Math.min(strikePrice, incartPrice),
7573            s = f(s0) == f(i0) ? 0 : f(s0),
7574            i = f(i0);
7575        s && strikeDiv.length ? strikeDiv.html(uiState.quizCurrency.replace("%price%", s)) : strikeDiv.hide();
7576        i && incartDiv.length ? incartDiv.html(uiState.quizCurrency.replace("%price%", i)) : incartDiv.hide();
7577        discountDiv.length && s ? Math.round(((s - i) / s) * 100) > 10 ? discountDiv.html(Math.round(((s - i) / s) * 100) + "%") : discountDiv.hide() : 0;
7578    } else strikeDiv.hide(), incartDiv.hide(), discountDiv.hide();
7579};
7580
7581function equalizeAnswersHeight() {
7582    $('#mastiff-modal-cpc').show();
7583    $('#mastiff-check-warranty-primary-offer').show();
7584    $('#mastiff-check-warranty-primary-offer').css('visibility', 'hidden');
7585
7586    if (uiState.quiztype === "cpc") {
7587        [2, 1].forEach(index => {
7588            const $answerWrappers = $('.CPConfiguratorItem').eq(index).find('.CPConfiguratorAnswers');
7589            $answerWrappers.show()
7590            $answerWrappers.height(Math.max(...$answerWrappers.map((_, wrapper) => $(wrapper).outerHeight()).get())).hide().eq(0).show();
7591        });
7592    }
7593    if (uiState.quiztype === "huq" && $(window).width() > 539) {
7594        const items = [4, 5];
7595        const matchHeights = (selector) => {
7596            const elements = items.map(i => $('.CPConfiguratorItem').eq(i).find(selector));
7597            const maxHeight = Math.max(...elements.map(el => el.height()));
7598            elements.forEach(el => el.height(maxHeight));
7599        };
7600        matchHeights('.CPConfiguratorAnswers');
7601        matchHeights('.CPConfiguratorQuestionText');
7602    }
7603    $('#mastiff-check-warranty-primary-offer').css('visibility', 'visible');
7604    $('#mastiff-modal-cpc').hide();
7605
7606};
7607
7608function displayQuizHardcodedContent() {
7609    const countryCode = quizReqObj.user.countryCode,
7610        currentQuizContent = uiState.quiztype === "cpc" ? CPChardcodedContent : uiState.quiztype === "huq" ? HUQhardcodedContent : "",
7611        quizContent = currentQuizContent.quizBodyContent,
7612        offerContent = currentQuizContent.offerContent,
7613        { header: offerHeader, cta: offerCTA } = offerContent,
7614        { header: quizHeader, questions: { first: firstQuestion, second: secondQuestion, third: thirdQuestion },
7615            footer: { totalPrice, cta: quizCTA, currencies } } = quizContent;
7616
7617    const headerText = quizHeader[countryCode],
7618        firstQuestionText = firstQuestion[countryCode],
7619        secondQuestionText = secondQuestion[countryCode],
7620        thirdQuestionText = thirdQuestion[countryCode],
7621        quizCTAText = quizCTA[countryCode],
7622        offerCTAText = offerCTA[countryCode],
7623        quizCurrency = currencies[countryCode];
7624
7625    if (uiState.quiztype === "cpc") {
7626        var totalPriceText = totalPrice[countryCode],
7627            offerHeaderText = offerHeader[countryCode],
7628            quizContainer = ".CPConfiguratorContainer";
7629        $('.CPConfiguratorResultSubmissionTotalText').text(totalPriceText);
7630        $('.CPConfiguratorResultSubmissionTotalPrice').html(quizCurrency.replace("%price%", '0'));
7631        $('.CPConfiguratorResultOfferHeaderHeadlineText').text(offerHeaderText);
7632        $('.CPConfiguratorResultOfferCTA').text(offerCTAText);
7633    }
7634    if (uiState.quiztype === "huq") {
7635        var recommendedText = offerHeader.recommended[countryCode],
7636            mostPopularText = offerHeader.mostPopular[countryCode],
7637            budgetFriendlyText = offerHeader.budgetFriendly[countryCode],
7638            quizContainer = ".HUQConfiguratorContainer";
7639        $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(0).text(budgetFriendlyText);
7640        $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(1).text(recommendedText);
7641        $('.CPConfiguratorResultOfferSectionHUQOfferHeaderText').eq(2).text(mostPopularText);
7642        $('.CPConfiguratorResultSubmissionButtonHUQText').text(offerCTAText);
7643    }
7644    $(`${quizContainer} .CPConfiguratorTitleText`).text(headerText);
7645    $(`${quizContainer} .CPConfiguratorQuestionText`).eq(0).text(firstQuestionText);
7646    $(`${quizContainer} .CPConfiguratorQuestionText`).eq(1).text(secondQuestionText);
7647    $(`${quizContainer} .CPConfiguratorQuestionText`).eq(2).text(thirdQuestionText);
7648    $(`${quizContainer} .CPConfiguratorResultSubmissionButton`).text(quizCTAText);
7649    equalizeAnswersHeight()
7650
7651};
7652
7653function analyzeCarepacks(availableCarepacks) {
7654    const result = {};
7655    const coverageMap = {};
7656
7657    availableCarepacks.sort((a, b) => parseInt(a.answers.q1) - parseInt(b.answers.q1));
7658
7659    for (const pack of availableCarepacks) {
7660        const { answers = {}, primaryText2 } = pack;
7661        const duration = answers.q1;
7662        const coverageType = answers.q2;
7663        const features = Array.isArray(answers.q3) ? answers.q3 : [];
7664
7665        (result[duration] ??= {})[coverageType] ??= [];
7666        result[duration][coverageType].push(features);
7667
7668        if (!coverageMap[coverageType] || features.length < (coverageMap[coverageType].features?.length ?? 0)) {
7669            coverageMap[coverageType] = { primaryText2, features };
7670        }
7671    }
7672
7673    cvgTypeTooltips = Object.fromEntries(
7674        Object.entries(coverageMap).map(([k, v]) => [k, v.primaryText2])
7675    );
7676
7677    for (const duration in result) {
7678        for (const coverageType in result[duration]) {
7679            const allFeatureSets = result[duration][coverageType];
7680            var total = allFeatureSets.length;
7681
7682            const frequencyMap = {};
7683            const coOccurMap = {};
7684            var standalone = false;
7685
7686            allFeatureSets.forEach(set => {
7687                if (set.length === 0)
7688                    standalone = true;
7689                set.forEach(f => {
7690                    frequencyMap[f] = (frequencyMap[f] || 0) + 1;
7691                    if (!coOccurMap[f]) coOccurMap[f] = {};
7692
7693                    set.forEach(other => {
7694                        if (f !== other) {
7695                            coOccurMap[f][other] = (coOccurMap[f][other] || 0) + 1;
7696                        }
7697                    });
7698                });
7699            });
7700            var realTotal = total;
7701            if (standalone) total--;
7702
7703            const finalFeatures = {};
7704            const allFeatures = Object.keys(frequencyMap);
7705
7706            for (const feature of allFeatures) {
7707                const freq = frequencyMap[feature] / total;
7708                const coMap = coOccurMap[feature] || {};
7709                const dependency = Object.entries(coMap)
7710                    .filter(([_, count]) => count === frequencyMap[feature])
7711                    .map(([f]) => f);
7712                const exclusions = allFeatures.filter(f => f !== feature && !(coMap[f] > 0));
7713
7714                finalFeatures[feature] = {
7715                    frequency: +freq.toFixed(2),
7716                    dependencies: dependency.length ? dependency : [],
7717                    exclusions: exclusions.length ? exclusions : [],
7718                    standalone: standalone,
7719                    total: realTotal
7720                };
7721            }
7722            standalone = false;
7723
7724            result[duration][coverageType] = finalFeatures;
7725        }
7726    }
7727
7728
7729    return result;
7730};
7731
7732
7733function handleCPCScenario(data) {
7734    $('.CPConfiguratorSpinner').show();
7735    $('.CPConfiguratorContainer').show();
7736
7737    availableCarepacks = data;
7738    analyzedCarepacks = analyzeCarepacks(data.products);
7739    logInfo("Analyzed CPC Carepacks:", analyzedCarepacks);
7740
7741    displayAnswers(analyzedCarepacks);
7742    displayQuizHardcodedContent();
7743}
7744
7745function handleHUQScenario(data) {
7746    logInfo("Handling HUQ scenario");
7747
7748    const q1Set = new Set();
7749    const q2Set = new Set();
7750    const q3Set = new Set();
7751
7752    data.products.forEach(product => {
7753        q1Set.add(product.answers.q1);
7754        q2Set.add(product.answers.q2);
7755        (product.answers.q3 || []).forEach(feature => q3Set.add(feature));
7756    });
7757
7758    const uniqueQ1 = Array.from(q1Set);
7759    const uniqueQ2 = Array.from(q2Set);
7760    const uniqueQ3 = Array.from(q3Set);
7761
7762    logInfo("Unique Q1:", uniqueQ1);
7763    logInfo("Unique Q2:", uniqueQ2);
7764    logInfo("Unique Q3 (features):", uniqueQ3);
7765
7766    const randomFeatures = getRandomFeatures(data.products, 5);
7767    displayHUQAnswers(uniqueQ1, uniqueQ2, randomFeatures);
7768    displayQuizHardcodedContent()
7769
7770}
7771
7772async function sendPendingReport() {
7773    const savedState = localStorage.getItem("quiz_lastState");
7774    const currentSessionId = localStorage.getItem("MastiffSessionId");
7775
7776    if (savedState) {
7777        try {
7778            const restoredState = JSON.parse(savedState);
7779
7780            if (!restoredState?.sessionId || restoredState.sessionId !== currentSessionId) {
7781                localStorage.removeItem("quiz_lastState");
7782                return;
7783            }
7784
7785            if (restoredState?.reportAlreadySent) {
7786                localStorage.removeItem("quiz_lastState");
7787                return;
7788            }
7789
7790            const originalRequestId = quizReqObj.requestId;
7791            const originalSessionId = quizReqObj.user.sessionId;
7792
7793            await sendReportingRequest(restoredState, true);
7794
7795            quizReqObj.requestId = originalRequestId;
7796            quizReqObj.user.sessionId = originalSessionId;
7797
7798        } catch (error) {
7799            console.error("Failed to send pending report or parse state. Will retry next load.", error);
7800            return;
7801        }
7802        localStorage.removeItem("quiz_lastState");
7803    }
7804}
7805function setReqId() {
7806    var timestamp = Date.now();
7807    var tsLength = String(timestamp).length;
7808    var randStrLen = 20 - parseInt(tsLength);
7809    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
7810    var charactersLength = characters.length;
7811    var result = "";
7812
7813    for (var i = 0; i < randStrLen; i++) {
7814        result += characters.charAt(Math.floor(Math.random() * charactersLength));
7815    }
7816    var reqId = String(timestamp).concat(result);
7817    quizReqObj.requestId = reqId;
7818    uiState.requestId = reqId;
7819}
7820
7821function setMastiffSessionId() {
7822    if (localStorage == null || typeof (localStorage) == "undefined") {
7823        quizReqObj.user.sessionId = quizReqObj.requestId.substring(quizReqObj.requestId.length - 10);
7824    } else {
7825        var mastiffSessionId = localStorage.getItem('MastiffSessionId');
7826        if (mastiffSessionId == null || mastiffSessionId == "" || typeof (mastiffSessionId) == "undefined") {
7827            mastiffSessionId = quizReqObj.requestId.substring(quizReqObj.requestId.length - 10);
7828            localStorage.setItem('MastiffSessionId', mastiffSessionId);
7829        }
7830        quizReqObj.user.sessionId = mastiffSessionId;
7831    }
7832    uiState.sessionId = quizReqObj.user.sessionId;
7833}
7834
7835function parseDelimitedString(str = "", listKeys = []) {
7836    const result = {};
7837
7838    str.split('|').forEach(pair => {
7839        const [key, value] = pair.split(':');
7840        if (!value || value === 'null') return;
7841
7842        const cleanKey = key.trim();
7843        const cleanValue = value.trim();
7844
7845        if (listKeys.includes(cleanKey)) {
7846            result[cleanKey] = cleanValue.split(/[,;]\s*/).map(v => v.trim());
7847        } else {
7848            result[cleanKey] = cleanValue;
7849        }
7850    });
7851
7852    return result;
7853}
7854
7855var getRandomFeatures = (data, count = 5) => {
7856    const allFeatures = Array.from(
7857        new Set(
7858            data.flatMap(item => item.filters?.features || [])
7859                .map(f => featureCategoryMap[f.trim()])
7860                .filter(Boolean)
7861        )
7862    );
7863    for (var i = allFeatures.length - 1; i > 0; i--) {
7864        const j = Math.floor(Math.random() * (i + 1));
7865        [allFeatures[i], allFeatures[j]] = [allFeatures[j], allFeatures[i]];
7866    }
7867    return allFeatures.slice(0, count);
7868};
7869
7870
7871var getTopFeatures = (data, topN = 5) =>
7872    Object.entries(extractFeatureCounts(data))
7873        .sort(([, a], [, b]) => b - a)
7874        .slice(0, topN)
7875        .map(([feature]) => feature);
7876
7877
7878var extractFeatureCounts = (data) =>
7879    data.flatMap(item => item.filters?.features || [])
7880        .map(f => featureCategoryMap[f.trim()])
7881        .filter(Boolean)
7882        .reduce((countMap, category) => {
7883            countMap[category] = (countMap[category] || 0) + 1;
7884            return countMap;
7885        }, {});
7886
7887function normalizeQ3(q3List) {
7888    return q3List
7889        .map(f => featureCategoryMap[f.trim()])
7890        .filter(Boolean);
7891}
7892
7893function getRecommendedProductSet(products, selectedAnswers) {
7894    const enrich = product => {
7895        const discount = (product.strikePrice && product.incartPrice)
7896            ? Math.max(0, ((product.strikePrice - product.incartPrice) / product.strikePrice) * 100)
7897            : 0;
7898        return { ...product, discount };
7899    };
7900
7901    const shuffle = array => {
7902        const arr = [...array];
7903        for (var i = arr.length - 1; i > 0; i--) {
7904            const j = Math.floor(Math.random() * (i + 1));
7905            [arr[i], arr[j]] = [arr[j], arr[i]];
7906        }
7907        return arr;
7908    };
7909
7910    const relaxQ3 = (products, selectedQ1, selectedQ2, relaxedQ3) => {
7911
7912        if (!isDefined(uiState.relaxationIteration)) {
7913            uiState.relaxationIteration = 0;
7914        }
7915        const featureFreq = extractFeatureCounts(products);
7916        relaxedQ3.sort((a, b) => (featureFreq[a] || 0) - (featureFreq[b] || 0));
7917        logInfo("Sorted Q3 by rarity:", relaxedQ3);
7918
7919        for (var i = 0; i <= relaxedQ3.length; i++) {
7920            const subset = relaxedQ3.slice(i);
7921            const matched = products.filter(p =>
7922                p.answers.q1 === selectedQ1 &&
7923                p.answers.q2 === selectedQ2 &&
7924                subset.every(f => p.answers.q3.includes(f))
7925            );
7926            logInfo(`Relax Q3 step ${i}: ${subset.join(', ')} -> ${matched.length} matches`);
7927            if (uiState.relaxationIteration === 0) {
7928                uiState.matchedDirectSelection = matched.length;
7929            }
7930            if (matched.length > 0) {
7931                return matched;
7932            } else {
7933                uiState.relaxationIteration++;
7934            }
7935        }
7936        return [];
7937    };
7938
7939    const getFallbackPool = (excludeSKUs, conditionFn) =>
7940        products.filter(p =>
7941            !excludeSKUs.has(p.productSKU) &&
7942            conditionFn(p)
7943        );
7944
7945    const pickThree = enrichedPool => {
7946        const budgetFriendly = enrichedPool.sort((a, b) => a.incartPrice - b.incartPrice)[0];
7947        const recommended = shuffle(enrichedPool.filter(p => p.productSKU !== budgetFriendly?.productSKU))[0];
7948        const mostPopular = enrichedPool
7949            .filter(p => p.productSKU !== recommended?.productSKU && p.productSKU !== budgetFriendly?.productSKU)
7950            .sort((a, b) => b.discount - a.discount)[0];
7951
7952        var finalSet = {
7953            recommended,
7954            mostPopular,
7955            budgetFriendly
7956        };
7957
7958        const selectedSKUs = new Set(Object.values(finalSet).filter(
7958Boolean).map(p => p.productSKU));
7959        for (const p of enrichedPool) {
7960            if (!selectedSKUs.has(p.productSKU)) {
7961                if (!finalSet.recommended) finalSet.recommended = p;
7962                else if (!finalSet.mostPopular) finalSet.mostPopular = p;
7963                else if (!finalSet.budgetFriendly) finalSet.budgetFriendly = p;
7964                if (Object.values(finalSet).filter(Boolean).length === 3) break;
7965            }
7966        }
7967
7968        return finalSet;
7969    };
7970
7971    const { q1, q2 } = selectedAnswers;
7972    const relaxedQ3 = [...(selectedAnswers.q3 || [])].map(f => f.replace(/_/g, ' '));
7973    var matchedByQ123 = relaxQ3(products, q1, q2, relaxedQ3);
7974
7975    if (matchedByQ123.length > 0) {
7976        logInfo(`(${matchedByQ123.length} matched products)`);
7977        var enrichedPool = matchedByQ123.map(enrich);
7978
7979        if (matchedByQ123.length < 3) {
7980            const excludeSKUs = new Set(matchedByQ123.map(p => p.productSKU));
7981
7982            var relaxedFallback = relaxQ3(products.filter(p => !excludeSKUs.has(p.productSKU)), q1, q2, relaxedQ3);
7983            if (relaxedFallback.length) {
7984                enrichedPool = enrichedPool.concat(relaxedFallback.map(enrich));
7985            }
7986
7987            if (enrichedPool.length < 3) {
7988                const q1q2 = getFallbackPool(excludeSKUs, p => p.answers.q1 === q1 && p.answers.q2 === q2);
7989                enrichedPool = enrichedPool.concat(q1q2.map(enrich));
7990            }
7991
7992            if (enrichedPool.length < 3) {
7993                const q1Only = getFallbackPool(excludeSKUs, p => p.answers.q1 === q1);
7994                enrichedPool = enrichedPool.concat(q1Only.map(enrich));
7995            }
7996        }
7997
7998        const result = pickThree(enrichedPool);
7999        logInfo("Final recommendations:", result);
8000        return result;
8001    }
8002
8003    logInfo("No matches. Fallback initiated.");
8004    var candidates = products.filter(p => p.answers.q1 === q1 && p.answers.q2 === q2);
8005    if (candidates.length < 3) {
8006        candidates = products.filter(p => p.answers.q1 === q1);
8007    }
8008    if (candidates.length < 3) {
8009        candidates = [...products];
8010    }
8011
8012    const enrichedFallback = candidates.map(enrich);
8013    const result = pickThree(enrichedFallback);
8014    logInfo("Final fallback recommendations:", result);
8015    return result;
8016}
8017
8018function testRecommendationEngine(products, iterations = 250) {
8019    const errors = [];
8020    const rolesSeen = new Set();
8021
8022    const normalizedProducts = products.map(p => ({
8023        ...p,
8024        answers: {
8025            ...p.answers,
8026            q3: (p.answers.q3 || [])
8027                .map(f => featureCategoryMap[f.trim()] || f.trim())
8028                .filter(Boolean)
8029        }
8030    }));
8031
8032    function getMatchLevel(product, selected) {
8033        const a = product.answers;
8034        if (!a?.q1 || !a?.q2) return 'invalid';
8035
8036        const matchQ1 = a.q1 === selected.q1;
8037        const matchQ2 = a.q2 === selected.q2;
8038        const matchQ3 = selected.q3.every(f => a.q3?.includes(f));
8039
8040        if (matchQ1 && matchQ2 && matchQ3) return "Q1+Q2+Q3";
8041        if (matchQ1 && matchQ2) return "Q1+Q2";
8042        if (matchQ1) return "Q1 only";
8043        return "No match";
8044    }
8045
8046    for (var i = 0; i < iterations; i++) {
8047        const randomProduct = normalizedProducts[Math.floor(Math.random() * normalizedProducts.length)];
8048        if (!randomProduct?.answers) continue;
8049
8050        const selectedAnswers = {
8051            q1: randomProduct.answers.q1,
8052            q2: randomProduct.answers.q2,
8053            q3: [...new Set(randomProduct.answers.q3 || [])]
8054        };
8055
8056        const result = getRecommendedProductSet(products, selectedAnswers);
8057        const { recommended, mostPopular, budgetFriendly } = result;
8058
8059        const assigned = [recommended?.productSKU, mostPopular?.productSKU, budgetFriendly?.productSKU];
8060        const uniqueAssigned = [...new Set(assigned)];
8061
8062        const matchLevels = {
8063            recommended: getMatchLevel(recommended, selectedAnswers),
8064            mostPopular: getMatchLevel(mostPopular, selectedAnswers),
8065            budgetFriendly: getMatchLevel(budgetFriendly, selectedAnswers)
8066        };
8067
8068        logInfo(`Test ${i + 1}:`);
8069        logInfo("Selected Answers:", selectedAnswers);
8070        logInfo(`-> Recommended:     ${recommended?.productSKU} [${matchLevels.recommended}]`);
8071        logInfo(`-> Most Popular:    ${mostPopular?.productSKU} [${matchLevels.mostPopular}]`);
8072        logInfo(`-> Budget Friendly: ${budgetFriendly?.productSKU} [${matchLevels.budgetFriendly}]`);
8073        logInfo("*** Unique roles:", uniqueAssigned.length === 3 ? "PASS" : "X FAIL");
8074        logInfo("--------------------------------------------------");
8075
8076        if (uniqueAssigned.length !== 3) {
8077            errors.push({
8078                test: i + 1,
8079                selectedAnswers,
8080                recommended: recommended?.productSKU,
8081                mostPopular: mostPopular?.productSKU,
8082                budgetFriendly: budgetFriendly?.productSKU
8083            });
8084        }
8085
8086        rolesSeen.add(recommended?.productSKU);
8087        rolesSeen.add(mostPopular?.productSKU);
8088        rolesSeen.add(budgetFriendly?.productSKU);
8089    }
8090
8091    logInfo(`-> ${iterations} tests complete. Distinct products used: ${rolesSeen.size}`);
8092    if (errors.length > 0) {
8093        console.warn(`:( ${errors.length} tests failed due to duplicate role assignments:`);
8094        console.table(errors);
8095    } else {
8096        logInfo("YUH all tests passed with unique role assignments.");
8097    }
8098}
8099
8100var deviceUseCriteriaMap = {
8101    setLocation: {
8102        id: "setLocation",
8103        name: "Set location (Desktop)",
8104        formFactor: ["All-in-one", "microtower", "mini", "small form factor", 'tower']
8105    },
8106    onTheGo: {
8107        id: "onTheGo",
8108        name: "On the go (Laptop)",
8109        formFactor: ["Convertible", "Mobile workstation", "Mobile thin client", "standard laptop"]
8110    }
8111}
8112
8113var deviceCriteriaMap = {
8114    entertainment: {
8115        id: "entertainment",
8116        name: "Entertainment & Personal",
8117        usage: ["Everyday computing", "Safe and simple"],
8118        processors: ["Intel Core i3", "Intel Core 3", "AMD Ryzen 3"],
8119        memory: { min: 4, max: 8 },
8120        storage: 64
8121    },
8122    creativeTechnical: {
8123        id: "creativeTechnical",
8124        name: "Creative & Technical",
8125        usage: ["Performance computing"],
8126        processors: ["Intel Core i7", "Intel Core i9", "Intel Core Ultra 7", "Intel Core Ultra 9", "AMD Ryzen 7", "AMD Ryzen 9"],
8127        memory: { min: 16, max: null },
8128        storage: 512
8129    },
8130    education: {
8131        id: "education",
8132        name: "Education & Hobbies",
8133        usage: ["Premium computing"],
8134        processors: ["Intel Core i5", "Intel Core 5", "Intel Core Ultra 5", "AMD Ryzen 5"],
8135        memory: { min: 8, max: 16 },
8136        storage: 256
8137    },
8138    gaming: {
8139        id: "gaming",
8140        name: "Gaming",
8141        usage: ["Gaming"],
8142        processors: ["Intel Core i7", "Intel Core i9", "Intel Core Ultra 7", "Intel Core Ultra 9", "AMD Ryzen 5", "AMD Ryzen 7"],
8143        memory: { min: 16, max: null },
8144        storage: 512
8145    },
8146    business: {
8147        id: "business",
8148        name: "Business & Professional",
8149        usage: ["Premium computing", "Business professional", "Mission critical", "Proven productivity"],
8150        processors: ["Intel Core i5", "Intel Core 5", "AMD Ryzen 5", "Intel Core i7", "Intel Core Ultra 7", "AMD Ryzen 7"],
8151        memory: { min: 16, max: null },
8152        storage: 256
8153    }
8154};
8155
8156var featureCategoryMap = {
8157    "Large Display": "Large display",
8158    "Lightweight and Slim": "Lightweight and slim",
8159    "touch": "Touchscreen",
8160    "Touch screen": "Touchscreen",
8161    "Touchscreen display": "Touchscreen",
8162    "Fingerprint Reader": "Fingerprint Sensor",
8163    "Fingerprint sensor": "Fingerprint Sensor",
8164    "HP FingerPrint Sensor": "Fingerprint Sensor",
8165    "Integrated fingerprint reader": "Fingerprint Sensor",
8166    "HP Wolf Pro Security Edition (1 year)": "HP Wolf Pro Security",
8167    "HP Wolf Pro Security Edition (3 years)": "HP Wolf Pro Security",
8168    "HP Wolf Security Pro Edition": "HP Wolf Pro Security",
8169    "HP 510 Black Wireless Keyboard and mouse combo": "Wireless keyboard and mouse",
8170    "HP 510 White Wireless Keyboard and mouse combo": "Wireless keyboard and mouse",
8171    "HP 510SP Black Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse",
8172    "HP 510SP White Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse",
8173    "HP 655 Wireless  Keyboard and mouse combo": "Wireless keyboard and mouse",
8174    "HP 655 Wireless Keyboard and mouse combo": "Wireless keyboard and mouse",
8175    "HP 710 Black Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse",
8176    "HP 710 White Wireless Keyboard and Mouse Combo": "Wireless keyboard and mouse",
8177    "HP 720 White Touchpad Integrated Bluetooth Keyboard": "Wireless keyboard and mouse",
8178    "HP 915 Wireless Keyboard and mouse combo": "Wireless keyboard and mouse",
8179    "HP Wireless Business Slim Keyboard and mouse combo": "Wireless keyboard and mouse",
8180    "USB black wireless keyboard and mouse combo": "Wireless keyboard and mouse",
8181    "USB nightfall black wireless keyboard and mouse combo": "Wireless keyboard and mouse",
8182    "USB white wireless keyboard and mouse combo": "Wireless keyboard and mouse",
8183    "Wi-Fi 6": "Faster Wi-Fi",
8184    "Wi-Fi 6E": "Faster Wi-Fi",
8185    "Wi-Fi 7": "Faster Wi-Fi",
8186    "Wi-Fi CERTIFIED 6ƒ?›": "Faster Wi-Fi",
8187    "Wireless (WiFi)": "Faster Wi-Fi",
8188    "ENERGY STAR certified": "ENERGY STAR Certified",
8189    "ENERGY STAR qualified": "ENERGY STAR Certified",
8190    "ENERGY STAR® certified": "ENERGY STAR Certified",
8191    "Full HD": "Full HD",
8192    "three-sided micro-edge": "Three-sided micro-edge display",
8193    "Touchscreen": "Touchscreen",
8194    "HP Premium Collaboration Keyboard – spill-resistant keyboard with numeric keypad": "Spill-resistant",
8195    "HP Premium Collaboration Keyboard – spill-resistant": "Spill-resistant",
8196    "HP Premium Keyboard – spill-resistant keyboard": "Spill-resistant",
8197    "HP Premium Keyboard – spill resistant": "Spill-resistant",
8198    "Spill-resistant keyboard": "Spill-resistant",
8199    "Full-size keyboard": "Full-size keyboard",
8200    "Full-size keyboard with numeric keypad": "Full-size keyboard",
8201    "backlit": "Backlit keyboard",
8202    "Backlit keyboard": "Backlit keyboard",
8203    "dragon red backlit": "Backlit keyboard",
8204    "RGB backlit": "Backlit keyboard",
8205    "2 Super Speed USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8206    "2 SuperSpeed Type-A USB 5Gbps signaling rate (1 charging)": "Multiple USB ports",
8207    "2 SuperSpeed USB 10Gbps signaling rate": "Multiple USB ports",
8208    "2 SuperSpeed USB 5Gbps signaling rate": "Multiple USB ports",
8209    "2 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports",
8210    "2 SuperSpeed USB Type-A 10Gbps signaling rate (1 fast charging)": "Multiple USB ports",
8211    "2 SuperSpeed USB Type-A 10Gbps signaling rate (charging)": "Multiple USB ports",
8212    "2 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8213    "2 SuperSpeed USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports",
8214    "2 SuperSpeed USB Type-A 5Gbps signaling rate (1 fast charging)": "Multiple USB ports",
8215    "2 SuperSpeed USB Type-A 5Gbps signaling rate (Charging 1.2)": "Multiple USB ports",
8216    "2 SuperSpeed USB Type-A 5Gbps signaling rate (charging)": "Multiple USB ports",
8217    "2 SuperSpeed USB Type-C® 20Gbps signaling rate": "Multiple USB ports",
8218    "2 SuperSpeed USB Type-C® 20Gbps signaling rate (USB Power Delivery)": "Multiple USB ports",
8219    "2 Thunderbolt™ 4 with USB Type-C® 40Gbps signaling rate": "Multiple USB ports",
8220    "2 Thunderbolt™ 4 with USB4™ Type-C® 40Gbps signaling rate": "Multiple USB ports",
8221    "2 USB 2.0": "Multiple USB ports",
8222    "2 USB 2.0 (1 charging)": "Multiple USB ports",
8223    "2 USB 2.0 Type-A": "Multiple USB ports",
8224    "2 USB 3.0": "Multiple USB ports",
8225    "2 USB 3.0 (1 charging)": "Multiple USB ports",
8226    "2 USB 3.1 Gen 1": "Multiple USB ports",
8227    "2 USB 3.1 Gen 1 (1 charging)": "Multiple USB ports",
8228    "2 USB 3.1 Gen 1 (charging)": "Multiple USB ports",
8229    "2 USB 3.1 Gen 1 (Data transfer only)": "Multiple USB ports",
8230    "2 USB 3.1 Gen 1 (Sleep and Charge support)": "Multiple USB ports",
8231    "2 USB 3.1 Gen 1 Type-A (Data Transfer Only)": "Multiple USB ports",
8232    "2 USB 3.1 Gen 2": "Multiple USB ports",
8233    "2 USB 3.1 Type A": "Multiple USB ports",
8234    "2 USB 3.1 Type-C®": "Multiple USB ports",
8235    "2 USB Type-A 10Gbps signaling rate": "Multiple USB ports",
8236    "2 USB Type-A 480Mbps signaling rate": "Multiple USB ports",
8237    "2 USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8238    "2 USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports",
8239    "2 USB Type-C (Alt mode)": "Multiple USB ports",
8240    "2 USB Type-C 20Gbps signaling rate (USB Power Delivery)": "Multiple USB ports",
8241    "3 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports",
8242    "3 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8243    "3 USB 2.0 Type-A": "Multiple USB ports",
8244    "3 USB Type-A 480 Mbps signaling rate": "Multiple USB ports",
8245    "3 USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8246    "4 SuperSpeed USB 10Gbps signaling rate": "Multiple USB ports",
8247    "4 SuperSpeed USB 5Gbps signaling rate (1 fast charging)": "Multiple USB ports",
8248    "4 SuperSpeed USB Type-A 10Gbps signaling rate": "Multiple USB ports",
8249    "4 SuperSpeed USB Type-A 10Gbps signaling rate (1 charging)": "Multiple USB ports",
8250    "4 SuperSpeed USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8251    "4 SuperSpeed USB Type-A 5Gbps signaling rate (1 Charging)": "Multiple USB ports",
8252    "4 USB 2.0 Type-A": "Multiple USB ports",
8253    "4 USB 3.1 (1 charging)": "Multiple USB ports",
8254    "4 USB 3.1 Gen 1": "Multiple USB ports",
8255    "4 USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8256    "4 USB Type-A 5Gbps signaling rate (1 charging)": "Multiple USB ports",
8257    "6 USB 3.1 Gen 1": "Multiple USB ports",
8258    "6 USB Type-A 5Gbps signaling rate": "Multiple USB ports",
8259    "OLED": "OLED",
8260    "10% post-consumer recycled plastic": "Recycled material",
8261    "10% post-industrial recycled metal": "Recycled material",
8262    "10% recycled metal": "Recycled material",
8263    "100% recycled polyester in speaker and pocket fabric": "Recycled material",
8264    "15% post-consumer recycled plastic": "Recycled material",
8265    "2% post-consumer recycled plastic": "Recycled material",
8266    "20% post-consumer recycled plastic": "Recycled material",
8267    "20% recycled metal": "Recycled material",
8268    "25% recycled metal": "Recycled material",
8269    "30% post-consumer recycled plastic": "Recycled material",
8270    "30% recycled metal": "Recycled material",
8271    "35% post-consumer recycled plastic": "Recycled material",
8272    "40% post-consumer recycled plastic": "Recycled material",
8273    "45% post-consumer recycled plastic": "Recycled material",
8274    "45% recycled metal": "Recycled material",
8275    "5% post-consumer recycled plastic": "Recycled material",
8276    "50% post-consumer recycled plastic": "Recycled material",
8277    "50% recycled metal": "Recycled material",
8278    "55% post-consumer recycled plastic": "Recycled material",
8279    "58% post-consumer recycled plastic": "Recycled material",
8280    "60% post-consumer recycled plastic": "Recycled material",
8281    "65% recycled metal": "Recycled material",
8282    "75% post-consumer recycled plastic": "Recycled material",
8283    "Contains recycled metal": "Recycled material",
8284    "Keyboard keycaps and scissors contain post-consumer recycled plastic": "Recycled material",
8285    "Keyboard keycaps made with post-consumer recycled plastic": "Recycled material",
8286    "LDPE bag contains 30% recycled plastic": "Recycled material",
8287    "Molded paper pulp cushion inside box is 100% sustainably sourced and recyclable": "Recycled material",
8288    "Outside box and corrugated cushions are 100% sustainably sourced and recyclable": "Recycled material",
8289    "Plastic cushion inserts contain 80% recycled content": "Recycled material",
8290    "Recycled fabric": "Recycled material",
8291    "Recycled fabric in speaker grill": "Recycled material",
8292    "Recycled Plastic cushions": "Recycled material",
8293};
8294
8295function getAnswers(transformedOffer, offerName) {
8296    const answers = {
8297        q1: null,
8298        q2: null,
8299        q3: []
8300    };
8301
8302    try {
8303        const filters = transformedOffer.filters || {};
8304
8305        if (offerName.toLowerCase().includes("cpc")) {
8306            answers.q1 = filters.filter_term_cp || null;
8307            answers.q2 = filters.filter_supptype_cp_01 || null;
8308            answers.q3 = filters.filter_supptype_cp_05 || []
8309
8310        } else if (offerName.toLowerCase().includes("huq")) {
8311            if (!isDefined(filters.appearance) ||
8312                !isDefined(filters.usage) ||
8313                !isDefined(filters.processor) ||
8314                !isDefined(filters.memory) ||
8315                !isDefined(filters.drives)) {
8316                return null;
8317            }
8318
8319            answers.q1 = Object.values(deviceUseCriteriaMap).find(useCriteria =>
8320                useCriteria.formFactor.some(formFactor =>
8321                    formFactor.toLowerCase() === filters.appearance.toLowerCase()
8322                )
8323            )?.id || null;
8324
8325            if (!answers.q1) {
8326                console.error("No matching device use criteria for:", filters.appearance);
8327            }
8328
8329            answers.q2 = Object.values(deviceCriteriaMap).find(criteria =>
8330                criteria.usage.some(usage =>
8331                    usage.toLowerCase() === filters.usage.toLowerCase()
8332                ) &&
8333                criteria.processors.some(processor =>
8334                    processor.toLowerCase() === filters.processor.toLowerCase()
8335                ) &&
8336                (filters.memory >= criteria.memory.min &&
8337                    (criteria.memory.max === null || filters.memory <= criteria.memory.max)) &&
8338                filters.drives >= criteria.storage
8339            )?.id || null;
8340
8341            if (!answers.q2) {
8342                answers.q2 = Object.values(deviceCriteriaMap).find(criteria =>
8343                    criteria.processors.some(processor =>
8344                        processor.toLowerCase() === filters.processor.toLowerCase()
8345                    ) &&
8346                    (filters.memory >= criteria.memory.min &&
8347                        (criteria.memory.max === null || filters.memory <= criteria.memory.max)) &&
8348                    filters.drives >= criteria.storage
8349                )?.id || null;
8350            }
8351
8352            if (!answers.q2) {
8353                answers.q2 = Object.values(deviceCriteriaMap).find(criteria =>
8354                    criteria.usage.some(usage =>
8355                        usage.toLowerCase() === filters.usage.toLowerCase()
8356                    )
8357                )?.id || null;
8358            }
8359
8360            if (!answers.q2) {
8361                console.error("No matching device criteria for HUQ:", filters);
8362            }
8363
8364            const rawFeatures = filters.features || [];
8365            answers.q3 = rawFeatures
8366                .map(f => featureCategoryMap[f.trim()])
8367                .filter(Boolean);
8368
8369        } else {
8370            console.error("Unknown offer name:", offerName);
8371            return null;
8372        }
8373
8374    } catch (error) {
8375        console.error("Error while preparing answers:", error, transformedOffer);
8376        return null;
8377    }
8378
8379    return answers;
8380}
8381
8382function transformOffer(offer) {
8383    const categoryData = parseDelimitedString(offer.category, ['filter_supptype_cp_05', 'Ports', 'Features']);
8384    const descriptionData = parseDelimitedString(offer.primaryText2);
8385
8386    const cleanedExtended = (descriptionData.proddes_overview_extended || "").replace(/\[\d+\]/g, '');
8387    const cleanedExtendedShort = (descriptionData.proddes_overview_short || "").replace(/\[\d+\]/g, '');
8388
8389    const cleanedCoverage = categoryData.filter_supptype_cp_01
8390        ? categoryData.filter_supptype_cp_01.replace(/w\//gi, "with ").replace(/\//g, "with ")
8391        : null;
8392
8393    const trackingId = 'Offer_id=MAS-' + quizReqObj.requestId + '_' + (offer.productSKU) + '_' + (offer.name);
8394    var trackedStoreURL = offer.storeURL;
8395    if (trackedStoreURL && trackedStoreURL.lastIndexOf("?") > -1) {
8396        trackedStoreURL += "&" + trackingId;
8397    } else if (trackedStoreURL) {
8398        trackedStoreURL += "?" + trackingId;
8399    } else {
8400        trackedStoreURL = null;
8401    }
8402
8403    const filters = {
8404        appearance: categoryData.Appearance || null,
8405        usage: categoryData.Usage || null,
8406        processor: categoryData.Processor || null,
8407        memory: categoryData.Memory || null,
8408        drives: categoryData.Drives || null,
8409        screenSize: categoryData.ScreenSize || null,
8410        features: categoryData.Features || [],
8411        ports: categoryData.Ports || null,
8412        weight: categoryData.Weight || null,
8413        filter_term_cp: categoryData.filter_term_cp || null,
8414        filter_supptype_cp_01: cleanedCoverage,
8415        filter_supptype_cp_05: categoryData.filter_supptype_cp_05 || []
8416    };
8417
8418    const extraFeatures = [];
8419
8420    if (isDefined(filters.screenSize) && parseFloat(filters.screenSize) >= 15) {
8421        extraFeatures.push("Large Display");
8422    }
8423
8424    if (isDefined(filters.weight) && parseFloat(filters.weight) <= 1.4) {
8425        extraFeatures.push("Lightweight and Slim");
8426    }
8427
8428    filters.features = [...new Set([...filters.features, ...extraFeatures])];
8429
8430    return {
8431        productSKU: offer.productSKU || null,
8432        skuName: offer.primaryText1 || "",
8433        skuDesciption: cleanedExtended || "",
8434        skuDesciptionShort: cleanedExtendedShort || "",
8435        storeURL: trackedStoreURL || null,
8436        imageURL: offer.imageURL || null,
8437        incartPrice: offer.incartPrice || null,
8438        strikePrice: offer.strikePrice || null,
8439        filters
8440    };
8441}
8442
8443function extractOffers(apiResponse) {
8444    if (!apiResponse?.offers?.offer?.length) {
8445        if (Array.isArray(apiResponse?.offers) && apiResponse.offers.length === 1 && apiResponse.offers[0]?.offer?.length) {
8446            apiResponse.offers = apiResponse.offers[0];
8447        } else {
8448            return [];
8449        }
8450    }
8451
8452    const products = [];
8453    var offerName = null;
8454
8455    if (apiResponse.offers.offer.length === 1 && !isDefined(apiResponse.offers.offer[0].offerTitle)) {
8456        console.warn("Only one offer found and no offerTitle defined. Exiting.");
8457        if (!offerName && isDefined(apiResponse.offers.offer[0].name)) {
8458            offerName = apiResponse.offers.offer[0].name;
8459        }
8460        return {
8461            name: offerName,
8462            products: products,
8463        };
8464    }
8465
8466    for (const item of apiResponse.offers.offer) {
8467        const transformedOffer = transformOffer(item);
8468
8469        if (!offerName && isDefined(item.name)) {
8470            offerName = item.name;
8471        }
8472        transformedOffer.answers = getAnswers(transformedOffer, offerName);
8473
8474        if (isDefined(transformedOffer.answers) && isDefined(transformedOffer.answers.q1) && isDefined(transformedOffer.answers.q2)) {
8475            products.push(transformedOffer);
8476        } else {
8477
8478
8479        }
8480
8481    }
8482
8483    return {
8484        name: offerName,
8485        products: products,
8486    };
8487}
8488async function sendPostRequest(endpoint, payload) {
8489    return new Promise((resolve, reject) => {
8490        $.ajax({
8491            url: endpoint,
8492            method: "POST",
8493            async: true,
8494            data: encodeURIComponent(JSON.stringify(payload)),
8495            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
8496            timeout: 7000,
8497            success: function (result) {
8498                logInfo("API Response:", result);
8499                resolve(result);
8500            },
8501            error: function (XMLHttpRequest, textStatus, errorThrown) {
8502                console.error("API Error:", XMLHttpRequest, textStatus, errorThrown);
8503                reject({ XMLHttpRequest, textStatus, errorThrown });
8504            }
8505        });
8506    });
8507}
8508async function sendDemoPostRequest(sku, warranty) {
8509    if (!isMastiffDebug() && window.location.protocol !== "file:") {
8510        console.error("Debug mode is OFF, cannot send demo request.");
8511        return null;
8512    }
8513
8514    logInfo("Debug mode is ON");
8515
8516    await new Promise((resolve, reject) => {
8517        const script = document.createElement('script');
8518        script.src = "hardCodedData.js";
8519
8520        script.onload = () => {
8521            logInfo("Hardcoded data loaded successfully.");
8522            resolve();
8523        };
8524
8525        script.onerror = () => {
8526            console.error("Failed to load hardcoded data.");
8527            reject(new Error("Failed to load hardcoded data."));
8528        };
8529
8530        document.head.appendChild(script);
8531    });
8532
8533    if (typeof liveDemoResponseData === 'undefined' || !Array.isArray(liveDemoResponseData)) {
8534        console.error("liveDemoResponseData is not defined or is not an array.");
8535        return null;
8536    }
8537
8538    const filteredResponse = liveDemoResponseData.filter(
8539        item => item.SKU === sku && item.WarrantyState === warranty
8540    );
8541
8542    return filteredResponse.length > 0 ? filteredResponse[0] : null;
8543}
8544function stringifyReportingContext(context = {}) {
8545    logInfo("Reporting context:", context);
8546    const q1 = context.q1 || "";
8547    const q2 = context.q2 || "";
8548    const q3 = Array.isArray(context.q3) ? context.q3.join(";") : "";
8549    const results = context.results || "";
8550    const status = context.status || "";
8551    const sku = context.acceptedSKU || "";
8552    const totalProducts = context.total || 0;
8553    const matchedDirectSelection = context.matchedDirectSelection || null;
8554    const relaxationIteration = context.relaxationIteration || null;
8555
8556    var reportingString = `Q1:${q1}|Q2:${q2}|Q3:${q3}|Results:${results}|Status:${status}|SKUAccepted:${sku}|TotalQ3:${totalProducts}|matchedDirectSelection:${matchedDirectSelection}|relaxationIteration:${relaxationIteration}`;
8557
8558    reportingString = reportingString.replaceAll("&", "and");
8559    logInfo("Reporting string:", reportingString);
8560    return reportingString;
8561}
8562
8563async function sendReportingRequest(context, pendingReqId = false) {
8564    const originalRequestId = quizReqObj.requestId;
8565    const originalSessionId = quizReqObj.user.sessionId;
8566
8567    if (pendingReqId) {
8568        quizReqObj.requestId = context.requestId;
8569        quizReqObj.user.sessionId = context.sessionId || quizReqObj.user.sessionId;
8570    }
8571
8572    const reportingString = encodeURIComponent(stringifyReportingContext(context));
8573    quizReqObj.offerName = context.offerName || "";
8574    quizReqObj.experienceResults = reportingString;
8575    quizReqObj.acceptanceLevel = "Accepted";
8576
8577    try {
8578        const response = await sendPostRequest(apiUrl, quizReqObj);
8579        return response;
8580    } catch (error) {
8581        throw error;
8582    } finally {
8583        quizReqObj.requestId = originalRequestId;
8584        quizReqObj.user.sessionId = originalSessionId;
8585        quizReqObj.offerName = "";
8586        quizReqObj.experienceResults = "";
8587        quizReqObj.acceptanceLevel = "";
8588    }
8589}
8590
8591var CPChardcodedContent = {
8592    tooltipsContent: {
8593        text: {
8594            "us": {
8595                "Active Care": {
8596                    summary: 'HP Active Care leverages devices telemetry to identify, prevent, resolve employee device issues from anywhere, and includes:',
8597                    benefits: ["Automated device health monitoring", "Predictive analytics & insights", "End user alerts & automated ticketing", "Next business day response", "24x7 remote support", "Onsite support from an HP expert", "Priority access to parts & HP service experts"],
8598                    idealFor: "Mobile business users who divide their time between their office, travel and working remotely."
8599                },
8600                "Onsite repair": {
8601                    summary: "Onsite Service makes an HP authorized representative available at the customers' premises to begin hardware maintenance service , and includes:",
8602                    benefits: ["Remote diagnosis and phone support", "Onsite hardware support", "Freight costs paid by HP for returning the defective product",],
8603                    idealFor: "Mobile business users who divide their time between their office, travel and working remotely."
8604                },
8605                "Exchange": {
8606                    summary: 'Exchange provides a replacement product or part to be delivered free of freight charges to your location, and includes:',
8607                    benefits: ["Remote diagnosis and phone support", "Replacements for defective products or parts", "Freight costs paid by HP for returning the defective product",],
8608                    idealFor: "Mobile business users who divide their time between their office, travel and working remotely."
8609                },
8610                "Pickup and return": {
8611                    summary: "Pickup and Return provides access to an HP authorized courier to pick-up the faulty unit, repair, and return the operational unit, if the issue cannot be resolved remotely and includes:",
8612                    benefits: ["Remote diagnosis and phone support", "lower-cost alternative to onsite support", "Repair at an HP center (materials & parts included)", "Flexible shipping to HP center", "Return shipping of repaired unit", "3–5 business-day turnaround (location-dependent) "],
8613                    idealFor: "Customers seeking reliable, cost-effective repair with included parts and flexible shipping, without the need for on-site support."
8614                },
8615                "Accidental damage protection": {
8616                    summary: 'Accidental Damage Protection allows the customer to avoid out-of-pocket repair or replacement costs caused by accidents such as drops, spills or electrical surges. Refer to local datasheet for detailed coverage.',
8617                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8618                }, "HP SmartFriend": {
8619                    summary: "SmartFriend connects you with SmartFriend agents who will help you solve a wide range of technical issues that may arise with your PCs and tablets, and includes:",
8620                    benefits: ["Virus removal and PC security assistance", "Software installation, configuration & troubleshooting", "“How-to” assistance", "Wi-Fi network connectivity assistance and troubleshooting"],
8621                    idealFor: "Mobile business users who divide their time between their office, travel and working remotely."
8622                },
8623                "Defective media retention": {
8624                    summary: 'Defective Media Retention provides a replacement drive while allowing customers to keep their malfunctioning drive on which their sensitive data is stored.',
8625                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8626                },
8627                "Device life extension": {
8628                    summary: 'HP Device Life Extension Service enables organizations to send PCs from their existing fleets to be optimized for performance and returned to the customer, giving devices a performance boost and allowing customers to use their devices for longer.',
8629                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8630                },
8631                "PC Solution": {
8632                    summary: 'Add repair or replace coverage on up to six peripherals when you purchase your commercial HP device.',
8633                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8634                },
8635                "Travel coverage": {
8636                    summary: 'Provides next-business-day onsite service in any of the covered (80) countries/regions for customers who travel internationally.',
8637                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8638                },
8639                "Computer tracing": {
8640                    summary: 'If your device is lost, or worse, stolen, we can lock your device, track it, and work with the authorities to help recover it. We can even wipe your hard drive so your private data stays private.',
8641                    idealFor: "High-risk environments, ADP helps minimize downtime and repair expenses."
8642                },
8643            },
8644            "es": {},
8645            "pt": {},
8646            "fr": {},
8647            "nl": {},
8648            "bg": {},
8649            "cs": {},
8650            "hr": {},
8651            "da": {},
8652            "de": {},
8653            "et": {},
8654            "el": {},
8655            "he": {},
8656            "it": {},
8657            "kk": {},
8658            "lv": {},
8659            "lt": {},
8660            "hu": {},
8661            "ar": {},
8662            "no": {},
8663            "pl": {},
8664            "ro": {},
8665            "sr": {},
8666            "sk": {},
8667            "sl": {},
8668            "fi": {},
8669            "sv": {},
8670            "tr": {},
8671            "uk": {},
8672            "zh": {},
8673            "id": {},
8674            "ja": {},
8675            "ko": {},
8676            "ms": {},
8677            "fil": {},
8678            "th": {},
8679            "vi": {}
8680        }, prefix: {
8681            "us": "Ideal for: ",
8682            "es": "Ideal para: ",
8683            "pt": "Ideal para: ",
8684            "fr": "Idéal pour : ",
8685            "nl": "Ideaal voor: ",
8686            "bg": "Подходящ за: ",
8687            "cs": "Ideální pro: ",
8688            "hr": "Idealno za: ",
8689            "da": "Ideel til: ",
8690            "de": "Ideal für: ",
8691            "et": "Ideaalne: ",
8692            "el": "Ιδανικό για: ",
8693            "he": "אידיאלי עבור: ",
8694            "it": "Ideale per: ",
8695            "kk": "Үшін қолайлы: ",
8696            "lv": "Ideāli piemērots: ",
8697            "lt": "Idealiai tinka: ",
8698            "hu": "Ideális erre: ",
8699            "ar": "مثالي لـ: ",
8700            "no": "Ideell for: ",
8701            "pl": "Idealne dla: ",
8702            "ro": "Ideal pentru: ",
8703            "sr": "Идеално за: ",
8704            "sk": "Ideálne pre: ",
8705            "sl": "Idealno za: ",
8706            "fi": "Ihanteellinen: ",
8707            "sv": "Perfekt för: ",
8708            "tr": "İdeal olan: ",
8709            "uk": "Ідеально для: ",
8710            "zh": "适用于:",
8711            "id": "Ideal untuk: ",
8712            "ja": "〜に最適:",
8713            "ko": "이상적임: ",
8714            "ms": "Sesuai untuk: ",
8715            "fil": "Mainam para sa: ",
8716            "th": "เหมาะสำหรับ: ",
8717            "vi": "Lý tưởng cho: "
8718        }
8719    },
8720    quizEntryContent: {
8721        header: {
8722            "us": "Extend your Warranty",
8723            "es": "Extiende tu garantía",
8724            "pt": "Estenda sua garantia",
8725            "fr": "Prolongez votre garantie",
8726            "nl": "Verleng je garantie",
8727            "bg": "Разширете гаранцията си",
8728            "cs": "Prodloužit záruku",
8729            "hr": "Produžite jamstvo",
8730            "da": "Forlæng din garanti",
8731            "de": "Verlängern Sie Ihre Garantie",
8732            "et": "Pikenda oma garantiiaeg",
8733            "el": "Επεκτείνετε την εγγύησή σας",
8734            "he": "הרחב את האחריות שלך",
8735            "it": "Estendi la tua garanzia",
8736            "kk": "Гарантияңызды ұзартуға болады",
8737            "lv": "Pagariniet savu garantiju",
8738            "lt": "Išplėskite savo garantiją",
8739            "hu": "Hosszabbítsa meg a garanciát",
8740            "ar": "مدد ضمانتك",
8741            "no": "Forleng garantien din",
8742            "pl": "Rozszerz swoją gwarancję",
8743            "ro": "Extindeți garanția",
8744            "sr": "Proširite garanciju",
8745            "sk": "Predĺžte svoju záruku",
8746            "sl": "Podaljšajte svojo garancijo",
8747            "fi": "Pidennä takuuta",
8748            "sv": "Förläng din garanti",
8749            "tr": "Garanti sürenizi uzatın",
8750            "uk": "Продовжіть свою гарантію",
8751            "zh": "延长您的保修期",
8752            "id": "Perpanjang garansi Anda",
8753            "ja": "保証を延長する",
8754            "ko": "보증 연장",
8755            "ms": "Panjang jaminan anda",
8756            "fil": "Palawigin ang iyong garantiya",
8757            "th": "ขยายการรับประกันของคุณ",
8758            "vi": "Gia hạn bảo hành của bạn"
8759        },
8760        description: {
8761            "us": "Answer 3 questions to build your coverage plan.",
8762            "es": "Responde 3 preguntas para crear tu plan de cobertura",
8763            "pt": "Responda a 3 perguntas para criar seu plano de cobertura",
8764            "fr": "Répondez à 3 questions pour créer votre plan de couverture",
8765            "nl": "Beantwoord 3 vragen om je dekking plan te maken",
8766            "bg": "Отговорете на 3 въпроса, за да създадете план за покритие",
8767            "cs": "Odpovězte na 3 otázky a vytvořte svůj plán krytí",
8768            "hr": "Odgovorite na 3 pitanja kako biste izradili svoj plan pokrivanja",
8769            "da": "Svar på 3 spørgsmål for at opbygge din dækning plan",
8770            "de": "Beantworten Sie 3 Fragen, um Ihren Deckungsplan zu erstellen",
8771            "et": "Vastake 3 küsimusele, et koostada oma katteplaan",
8772            "el": "Απαντήστε σε 3 ερωτήσεις για να δημιουργήσετε το σχέδιο κάλυψης",
8773            "he": "ענה על 3 שאלות כדי ליצור את תכנית הכיסוי שלך",
8774            "it": "Rispondi a 3 domande per creare il tuo piano di copertura",
8775            "kk": "Қамту жоспарын құру үшін 3 сұраққа жауап беріңіз",
8776            "lv": "Atbildiet uz 3 jautājumiem, lai izveidotu savu seguma plānu",
8777            "lt": "Atsakykite į 3 klausimus, kad sukurtumėte savo aprėpties planą",
8778            "hu": "Válaszoljon 3 kérdésre a fedezeti terv létrehozásához",
8779            "ar": "أجب على 3 أسئلة لبناء اشتراك التغطية الخاص بك",
8780            "no": "Svar på 3 spørsmål for å lage ditt dekning plan",
8781            "pl": "Odpowiedz na 3 pytania, aby stworzyć swój plan pokrycia",
8782            "ro": "Răspundeți la 3 întrebări pentru a construi planul de acoperire",
8783            "sr": "Odgovorite na 3 pitanja kako biste izgradili svoj plan pokrivanja",
8784            "sk": "Odpovedzte na 3 otázky a vytvorte si svoj plán pokrytia",
8785            "sl": "Odgovorite na 3 vprašanja, da sestavite svoj načrt kritja",
8786            "fi": "Vastaa 3 kysymykseen rakentaaksesi kattavussuunnitelmasi",
8787            "sv": "Svara på 3 frågor för att bygga din täckningsplan",
8788            "tr": "Kapsama planınızı oluşturmak için 3 soruyu yanıtlayın",
8789            "uk": "Відповідайте на 3 запитання, щоб створити свій план покриття",
8790            "zh": "回答 3 个问题以构建您的保障计划",
8791            "id": "Jawab 3 pertanyaan untuk membangun rencana perlindungan Anda",
8792            "ja": "カバレッジプランを作成するために3つの質問に答えてください",
8793            "ko": "보장 계획을 작성하려면 3개의 질문에 답하세요",
8794            "ms": "Jawab 3 soalan untuk membina pelan perlindungan anda",
8795            "fil": "Sagot ang 3 tanong upang buuin ang iyong plano ng proteksyon",
8796            "th": "ตอบคำถาม 3 ข้อเพื่อสร้างแผนการคุ้มครองของคุณ",
8797            "vi": "Trả lời 3 câu hỏi để xây dựng kế hoạch bảo hiểm của bạn"
8798        },
8799        cta: {
8800            "us": "Get started",
8801            "es": "Comenzar",
8802            "pt": "Começar",
8803            "fr": "Commencer",
8804            "nl": "Begin",
8805            "bg": "Започнете",
8806            "cs": "Začít",
8807            "hr": "Započnite",
8808            "da": "Kom godt i gang",
8809            "de": "Loslegen",
8810            "et": "Alusta",
8811            "el": "Ξεκινήστε",
8812            "he": "התחל",
8813            "it": "Inizia",
8814            "kk": "Бастау",
8815            "lv": "Sākt",
8816            "lt": "Pradėti",
8817            "hu": "Kezdjen",
8818            "ar": "ابدأ",
8819            "no": "Kom i gang",
8820            "pl": "Zacznij",
8821            "ro": "Începe",
8822            "sr": "Počnite",
8823            "sk": "Začnite",
8824            "sl": "Začnite",
8825            "fi": "Aloita",
8826            "sv": "Kom igång",
8827            "tr": "Başlayın",
8828            "uk": "Почати",
8829            "zh": "开始",
8830            "id": "Mulai",
8831            "ja": "始める",
8832            "ko": "시작하기",
8833            "ms": "Mula",
8834            "fil": "Magsimula",
8835            "th": "เริ่มต้น",
8836            "vi": "Bắt đầu"
8837        }
8838    },
8839    quizBodyContent: {
8840        header: {
8841            "us": "Your plan will unlock after you select your coverage needs",
8842            "es": "Tu plan se desbloqueará después de seleccionar tus necesidades de cobertura",
8843            "pt": "Seu plano será desbloqueado após você selecionar suas necessidades de cobertura",
8844            "fr": "Votre plan se débloquera après avoir sélectionné vos besoins en couverture",
8845            "nl": "Je plan wordt ontgrendeld nadat je je dekkingsbehoeften hebt geselecteerd",
8846            "bg": "Вашият план ще се отключи след като изберете вашите нужди от покритие",
8847            "cs": "Váš plán se odemkne, jakmile vyberete své potřeby krytí",
8848            "hr": "Vaš plan bit će otključan nakon što odaberete svoje potrebe pokrivenosti",
8849            "da": "Din plan vil blive låst op, når du har valgt dine dækningbehov",
8850            "de": "Ihr Plan wird freigeschaltet, nachdem Sie Ihre Deckungsbedürfnisse ausgewählt haben",
8851            "et": "Teie plaan avatakse pärast seda, kui olete valinud oma kattevajadused",
8852            "el": "Το σχέδιο σας θα ξεκλειδώσει αφού επιλέξετε τις ανάγκες κάλυψης",
8853            "he": "התוכנית שלך תפתח לאחר שתבחר את צרכי הכיסוי שלך",
8854            "it": "Il tuo piano si sbloccherà dopo aver selezionato le tue esigenze di copertura",
8855            "kk": "Жоспарыңыз жапқыш қажеттіліктеріңізді таңдағаннан кейін ашылады",
8856            "lv": "Jūsu plāns tiks atbloķēts pēc tam, kad izvēlēsieties savas seguma vajadzības",
8857            "lt": "Jūsų planas bus atrakintas, kai pasirinksite savo aprėpties poreikius",
8858            "hu": "A terved feloldódik, miután kiválasztottad a fedezeti igényeidet",
8859            "ar": "سيتم تفعيل اشتراكك بعد تحديد احتياجاتك من التغطية",
8860            "no": "Planen din vil bli låst opp etter at du har valgt dine dekningbehov",
8861            "pl": "Twój plan zostanie odblokowany po wybraniu potrzeb pokrycia",
8862            "ro": "Planul tău se va debloca după ce îți selectezi nevoile de acoperire",
8863            "sr": "Vaš plan će biti otključan nakon što odaberete svoje potrebe pokrivanja",
8864            "sk": "Váš plán sa odomkne po výbere vašich potrieb pokrytia",
8865            "sl": "Vaš načrt se bo odklenil, ko izberete svoje potrebe po kritju",
8866            "fi": "Suunnitelmasi avautuu, kun ovar valinnut kattavuustarpeesi",
8867            "sv": "Din plan låses upp efter att du har valt dina täckningsbehov",
8868            "tr": "Planınız, kapsama ihtiyaçlarınızı seçtikten sonra açılacaktır",
8869            "uk": "Ваш план буде розблоковано після вибору ваших потреб у покритті",
8870            "zh": "在选择您的保障需求后,您的计划将解锁",
8871            "id": "Rencana Anda akan terbuka setelah Anda memilih kebutuhan perlindungan Anda",
8872            "ja": "カバレッジのニーズを選択した後、プランがアンロックされます",
8873            "ko": "보장 요구 사항을 선택한 후 플랜이 잠금 해제됩니다",
8874            "ms": "Pelan anda akan dibuka selepas anda memilih keperluan perlindungan anda",
8875            "fil": "Bubukas ang iyong plano pagkatapos mong piliin ang iyong mga pangangailangan sa proteksyon",
8876            "th": "แผนของคุณจะถูกปลดล็อกหลังจากที่คุณเลือกความต้องการการคุ้มครองของคุณ",
8877            "vi": "Kế hoạch của bạn sẽ được mở khóa sau khi bạn chọn các nhu cầu bảo hiểm của mình"
8878        },
8879        questions: {
8880            first: {
8881                "us": "How much additional coverage do you need?",
8882                "es": "¿Cuánta cobertura adicional necesitas?",
8883                "pt": "De quanta cobertura adicional você precisa?",
8884                "fr": "De combien de couverture supplémentaire avez-vous besoin ?",
8885                "nl": "Hoeveel extra dekking heeft u nodig?",
8886                "bg": "От колко допълнително покритие се нуждаете?",
8887                "cs": "Kolik dalšího krytí potřebujete?",
8888                "hr": "Koliko dodatne pokrivenosti trebate?",
8889                "da": "Hvor meget ekstra dækning har du brug for?",
8890                "de": "Wie viel zusätzliche Deckung benötigen Sie?",
8891                "et": "Kui palju lisakatet vajate?",
8892                "el": "Πόση επιπλέον κάλυψη χρειάζεστε;",
8893                "he": "כמה כיסוי נוסף אתה צריך?",
8894                "it": "Di quanta copertura aggiuntiva hai bisogno?",
8895                "kk": "Қосымша қанша қамту қажет?",
8896                "lv": "Cik daudz papildu seguma jums nepieciešams?",
8897                "lt": "Kiek papildomos apsaugos jums reikia?",
8898                "hu": "Mennyi további fedezetre van szüksége?",
8899                "ar": "كم من التغطية الإضافية تحتاج؟",
8900                "no": "Hvor mye ekstra dekning trenger du?",
8901                "pl": "Ile dodatkowego pokrycia potrzebujesz?",
8902                "ro": "De câtă acoperire suplimentară ai nevoie?",
8903                "sr": "Колико додатног покрића вам је потребно?",
8904                "sk": "Koľko dodatočného krytia potrebujete?",
8905                "sl": "Koliko dodatnega kritja potrebujete?",
8906                "fi": "Kuinka paljon lisäsuojaa tarvitset?",
8907                "sv": "Hur mycket extra täckning behöver du?",
8908                "tr": "Ne kadar ek kapsamaya ihtiyacınız var?",
8909                "uk": "Скільки додаткового покриття вам потрібно?",
8910                "zh": "您需要多少额外的保障?",
8911                "id": "Berapa banyak pertanggungan tambahan yang Anda butuhkan?",
8912                "ja": "どれくらいの追加補償が必要ですか?",
8913                "ko": "추가 보장이 얼마나 필요하십니까?",
8914                "ms": "Berapakah perlindungan tambahan yang anda perlukan?",
8915                "fil": "Gaano karaming karagdagang saklaw ang kailangan mo?",
8916                "th": "คุณต้องการความคุ้มครองเพิ่มเติมเท่าใด?",
8917                "vi": "Bạn cần bao nhiêu bảo hiểm bổ sung?"
8918            }
8919            ,
8920            second: {
8921                "us": "Pick your coverage type",
8922                "es": "Elige tu tipo de cobertura",
8923                "pt": "Escolha seu tipo de cobertura",
8924                "fr": "Choisissez votre type de couverture",
8925                "nl": "Kies uw dekkingssoort",
8926                "bg": "Изберете вида на покритието си",
8927                "cs": "Vyberte typ krytí",
8928                "hr": "Odaberite vrstu pokrića",
8929                "da": "Vælg din dækningsstype",
8930                "de": "Wählen Sie Ihren Versicherungstyp",
8931                "et": "Valige oma katte tüüp",
8932                "el": "Επιλέξτε τον τύπο κάλυψης σας",
8933                "he": "בחר את סוג הכיסוי שלך",
8934                "it": "Scegli il tuo tipo di copertura",
8935                "kk": "Сақтандыру түрін таңдаңыз",
8936                "lv": "Izvēlieties savu seguma veidu",
8937                "lt": "Pasirinkite savo draudimo tipą",
8938                "hu": "Válassza ki a fedezet típusát",
8939                "ar": "اختر نوع التغطية الخاص بك",
8940                "no": "Velg din dekningstype",
8941                "pl": "Wybierz swój typ ubezpieczenia",
8942                "ro": "Alegeți tipul de acoperire",
8943                "sr": "Изаберите тип покрића",
8944                "sk": "Vyberte typ krytia",
8945                "sl": "Izberite vrsto kritja",
8946                "fi": "Valitse vakuutustyyppisi",
8947                "sv": "Välj din täckningstyp",
8948                "tr": "Kapsama türünüzü seçin",
8949                "uk": "Виберіть тип покриття",
8950                "zh": "选择您的保障类型",
8951                "id": "Pilih jenis pertanggungan Anda",
8952                "ja": "補償タイプを選択してください",
8953                "ko": "보장 유형을 선택하세요",
8954                "ms": "Pilih jenis perlindungan anda",
8955                "fil": "Piliin ang uri ng saklaw mo",
8956                "th": "เลือกประเภทความคุ้มครองของคุณ",
8957                "vi": "Chọn loại bảo hiểm của bạn"
8958            }
8959            ,
8960            third: {
8961                "us": "Configure your protection options",
8962                "es": "Selecciona y configura tu opción de protección",
8963                "pt": "Selecione e configure sua opção de proteção",
8964                "fr": "Sélectionnez et configurez votre option de protection",
8965                "nl": "Selecteer en configureer uw beschermingsoptie",
8966                "bg": "Изберете и конфигурирайте вашата опция за защита",
8967                "cs": "Vyberte a nakonfigurujte svou možnost ochrany",
8968                "hr": "Odaberite i konfigurirajte svoju opciju zaštite",
8969                "da": "Vælg og konfigurer din beskyttelsesmulighed",
8970                "de": "Wählen und konfigurieren Sie Ihre Schutzoption",
8971                "et": "Valige ja seadistage oma kaitsevalik",
8972                "el": "Επιλέξτε και διαμορφώστε την επιλογή προστασίας σας",
8973                "he": "בחר והגדר את אפשרות ההגנה שלך",
8974                "it": "Seleziona e configura la tua opzione di protezione",
8975                "kk": "Қорғау опцияңызды таңдаңыз және баптаңыз",
8976                "lv": "Izvēlieties un konfigurējiet savu aizsardzības opciju",
8977                "lt": "Pasirinkite ir sukonfigūruokite savo apsaugos parinktį",
8978                "hu": "Válassza ki és konfigurálja a védelmi lehetőségét",
8979                "ar": "اختر وقم بتكوين خيار الحماية الخاص بك",
8980                "no": "Velg og konfigurer ditt beskyttelsesalternativ",
8981                "pl": "Wybierz i skonfiguruj swoją opcję ochrony",
8982                "ro": "Selectați și configurați opțiunea dvs. de protecție",
8983                "sr": "Изаберите и конфигуришите своју опцију заштите",
8984                "sk": "Vyberte a nakonfigurujte svoju možnosť ochrany",
8985                "sl": "Izberite in konfigurirajte svojo možnost zaščite",
8986                "fi": "Valitse ja määritä suojausvaihtoehtosi",
8987                "sv": "Välj och konfigurera ditt skyddsalternativ",
8988                "tr": "Koruma seçeneğinizi seçin ve yapılandırın",
8989                "uk": "Виберіть і налаштуйте свій варіант захисту",
8990                "zh": "选择并配置您的保护选项",
8991                "id": "Pilih dan konfigurasikan opsi perlindungan Anda",
8992                "ja": "保護オプションを選択して構成してください",
8993                "ko": "보호 옵션을 선택하고 구성하세요",
8994                "ms": "Pilih dan konfigurasikan pilihan perlindungan anda",
8995                "fil": "Piliin at i-configure ang iyong opsyon sa proteksyon",
8996                "th": "เลือกและกำหนดค่าตัวเลือกการป้องกันของคุณ",
8997                "vi": "Chọn và cấu hình tùy chọn bảo vệ của bạn"
8998            }
8999        },
9000        footer: {
9001            totalPrice: {
9002                "us": "Total: ",
9003                "es": "Total: ",
9004                "pt": "Total: ",
9005                "fr": "Total: ",
9006                "nl": "Totaal: ",
9007                "bg": "Общо: ",
9008                "cs": "Celkem: ",
9009                "hr": "Ukupno: ",
9010                "da": "I alt: ",
9011                "de": "Gesamt: ",
9012                "et": "Kokku: ",
9013                "el": "Σύνολο: ",
9014                "he": " :סה\"כ",
9015                "it": "Totale: ",
9016                "kk": "Жалпы: ",
9017                "lv": "Kopā: ",
9018                "lt": "IÅ¡ viso: ",
9019                "hu": "Összesen: ",
9020                "ar": " :الإجمالي",
9021                "no": "Totalt: ",
9022                "pl": "Razem: ",
9023                "ro": "Total: ",
9024                "sr": "Укупно: ",
9025                "sk": "Spolu: ",
9026                "sl": "Skupaj: ",
9027                "fi": "Yhteensä: ",
9028                "sv": "Totalt: ",
9029                "tr": "Toplam: ",
9030                "uk": "Разом: ",
9031                "zh": "总计: ",
9032                "id": "Total: ",
9033                "ja": "合計: ",
9034                "ko": "합계: ",
9035                "ms": "Jumlah: ",
9036                "fil": "Kabuuan: ",
9037                "th": "รวม: ",
9038                "vi": "Tổng cộng: "
9039            },
9040            cta: {
9041                "us": "View & purchase plan",
9042                "es": "Ver y comprar plan",
9043                "pt": "Visualizar e comprar plano",
9044                "fr": "Voir et acheter le plan",
9045                "nl": "Plan bekijken en kopen",
9046                "bg": "Преглед и закупуване на план",
9047                "cs": "Zobrazit a zakoupit plán",
9048                "hr": "Pregledaj i kupi plan",
9049                "da": "Se og køb plan",
9050                "de": "Plan anzeigen und kaufen",
9051                "et": "Vaata ja osta plaan",
9052                "el": "Προβολή και αγορά πλάνου",
9053                "he": "צפה ורכוש תוכנית",
9054                "it": "Visualizza e acquista il piano",
9055                "kk": "Жоспарды қарау және сатып алу",
9056                "lv": "Skatīt un iegādāties plānu",
9057                "lt": "Peržiūrėti ir įsigyti planą",
9058                "hu": "Terv megtekintése és vásárlása",
9059                "ar": "عرض وشراء الاشتراك",
9060                "no": "Se og kjøp plan",
9061                "pl": "Zobacz i kup plan",
9062                "ro": "Vizualizează și cumpără planul",
9063                "sr": "Прегледај и купи план",
9064                "sk": "Zobraziť a zakúpiť plán",
9065                "sl": "Ogled in nakup načrta",
9066                "fi": "Näytä ja osta suunnitelma",
9067                "sv": "Visa och köp plan",
9068                "tr": "Planı görüntüle ve satın al",
9069                "uk": "Переглянути та придбати план",
9070                "zh": "查看并购买计划",
9071                "id": "Lihat dan beli paket",
9072                "ja": "プランを表示して購入",
9073                "ko": "계획 보기 및 구매",
9074                "ms": "Lihat dan beli pelan",
9075                "fil": "Tingnan at bilhin ang plano",
9076                "th": "ดูและซื้อแผน",
9077                "vi": "Xem và mua gói"
9078            },
9079            currencies: {
9080                "us": '&#36;%price%',
9081                "de": '&#128;%price%',
9082                "ch": 'fr. %price%',
9083                "se": '%price% kr',
9084                "gb": '£%price%',
9085                "au": '$%price%',
9086                "ca": '$%price%',
9087                "cl": '$%price%',
9088                "in": '₹ %price%',
9089                "ar": '$ %price%',
9090                "my": 'RM %price%',
9091                "mx": '$%price%',
9092                "sg": '$%price%',
9093                "pe": 'S/.%price%',
9094                "hk": 'HK$ %price%',
9095                "kr": '₩ %price%',
9096                "za": 'R %price%',
9097                "vn": '%price% ₫',
9098                "tw": '元 %price%',
9099                "tr": '%price% ₺',
9100                "th": '%price% ฿',
9101                "sa": '%price% ï·¼',
9102                "ru": '%price% ₽',
9103                "ro": '%price% RON',
9104                "pl": '%price% zł',
9105                "ph": '₱ %price%',
9106                "nz": '%price%',
9107                "no": 'kr %price%',
9108                "ma": '%price% .د.م.',
9109                "kp": '₩ %price%',
9110                "jp": 'Â¥ %price%',
9111                "il": '₪ %price%',
9112                "id": 'Rp %price%',
9113                "hu": '%price% Ft',
9114                "hr": '€ %price%',
9115                "dk": 'kr. %price%',
9116                "cz": '%price% Kč',
9117                "cn": 'Â¥ %price%',
9118                "br": 'R$ %price%',
9119                "bg": '%price% лв',
9120                "an": '€ %price%'
9121            }
9122        }
9123    },
9124    offerContent: {
9125        header: {
9126            "us": "Recommended Coverage Plan",
9127            "es": "Plan de cobertura recomendado",
9128            "pt": "Plano de cobertura recomendado",
9129            "fr": "Plan de couverture recommandé",
9130            "nl": "Aanbevolen dekking plan",
9131            "bg": "Препоръчителен план за покритие",
9132            "cs": "Doporučený plán krytí",
9133            "hr": "Preporučeni plan pokrivanja",
9134            "da": "Anbefavar dækning plan",
9135            "de": "Empfohlener Deckungsplan",
9136            "et": "Soovitatud katteplaan",
9137            "el": "Προτεινόμενο σχέδιο κάλυψης",
9138            "he": "תכנית כיסוי מומלצת",
9139            "it": "Piano di copertura consigliato",
9140            "kk": "Ұсынылатын қамту жоспары",
9141            "lv": "Ieteicamais seguma plāns",
9142            "lt": "Rekomenduojamas aprėpties planas",
9143            "hu": "Ajánlott fedezeti terv",
9144            "ar": "اشتراك التغطية الموصى به",
9145            "no": "Anbefalt dekning plan",
9146            "pl": "Zalecany plan pokrycia",
9147            "ro": "Plan de acoperire recomandat",
9148            "sr": "Preporučeni plan pokrivanja",
9149            "sk": "Odporúčaný plán pokrytia",
9150            "sl": "Priporočeni načrt kritja",
9151            "fi": "Suositeltu kattavuussuunnitelma",
9152            "sv": "Rekommenderad täckningsplan",
9153            "tr": "Önerilen Kapsam Planı",
9154            "uk": "Рекомендований план покриття",
9155            "zh": "推荐保障计划",
9156            "id": "Rencana Perlindungan yang Disarankan",
9157            "ja": "推奨保険プラン",
9158            "ko": "추천 보장 플랜",
9159            "ms": "Pelan Perlindungan yang Disyorkan",
9160            "fil": "Inirerekomendang Plano ng Proteksyon",
9161            "th": "แผนการคุ้มครองที่แนะนำ",
9162            "vi": "Kế hoạch bảo hiểm được đề xuất"
9163        },
9164        cta: {
9165            "us": "Shop now",
9166            "es": "Compra ahora",
9167            "pt": "Compre agora",
9168            "fr": "Achetez maintenant",
9169            "nl": "Koop nu",
9170            "bg": "Купи сега",
9171            "cs": "Kup nyní",
9172            "hr": "Kupite sada",
9173            "da": "Køb nu",
9174            "de": "Jetzt kaufen",
9175            "et": "Osta nüüd",
9176            "el": "Αγοράστε τώρα",
9177            "he": "קנה עכשיו",
9178            "it": "Acquista ora",
9179            "kk": "Қазір сатып алыңыз",
9180            "lv": "Pērc tagad",
9181            "lt": "Pirkite dabar",
9182            "hu": "Vásároljon most",
9183            "ar": "اشترِ الآن",
9184            "no": "Kjøp nå",
9185            "pl": "Kup teraz",
9186            "ro": "Cumpără acum",
9187            "sr": "Kupite sada",
9188            "sk": "Kúp teraz",
9189            "sl": "Kupite zdaj",
9190            "fi": "Osta nyt",
9191            "sv": "Köp nu",
9192            "tr": "Hemen satın al",
9193            "uk": "Купити зараз",
9194            "zh": "立即购买",
9195            "id": "Beli sekarang",
9196            "ja": "今すぐ購入",
9197            "ko": "지금 구매",
9198            "ms": "Beli sekarang",
9199            "fil": "Bumili ngayon",
9200            "th": "ซื้อเลย",
9201            "vi": "Mua ngay"
9202        }
9203    }
9204};
9205
9206var HUQhardcodedContent = {
9207    tooltipsContent: {
9208        text: {
9209            "us": {
9210                "entertainment": {
9211                    summary: 'Best for streaming, browsing, email, and social media.',
9212                    benefits: [""],
9213                    idealFor: ""
9214                },
9215                "education": {
9216                    summary: 'Best for creative, photo editing, creating documents, and more.​',
9217                    benefits: [""],
9218                    idealFor: ""
9219                },
9220                "creativeTechnical": {
9221                    summary: 'Best for word processing, spreadsheets, presentations,  and video calls...',
9222                    benefits: [""],
9223                    idealFor: ""
9224                },
9225                "business": {
9226                    summary: 'Best for photo, video, and sound editing, large files, and more.​',
9227                    benefits: [""],
9228                    idealFor: ""
9229                },
9230                "gaming": {
9231                    summary: 'Best for avid gamers.​',
9232                    benefits: [""],
9233                    idealFor: ""
9234                }
9235            },
9236
9237
9238            "es": {
9239                "entertainment": {
9240                    summary: "Ideal para streaming, navegación, correo electrónico y redes sociales.",
9241                    benefits: [""],
9242                    idealFor: ""
9243                },
9244                "education": {
9245                    summary: "Ideal para actividades creativas, edición de fotos, creación de documentos y más.",
9246                    benefits: [""],
9247                    idealFor: ""
9248                },
9249                "creativeTechnical": {
9250                    summary: "Ideal para procesamiento de texto, hojas de cálculo, presentaciones y videollamadas...",
9251                    benefits: [""],
9252                    idealFor: ""
9253                },
9254                "business": {
9255                    summary: "Ideal para edición de fotos, videos y audio, archivos grandes y más.",
9256                    benefits: [""],
9257                    idealFor: ""
9258                },
9259                "gaming": {
9260                    summary: "Ideal para jugadores entusiastas.",
9261                    benefits: [""],
9262                    idealFor: ""
9263                }
9264            },
9265            "pt": {
9266                "entertainment": {
9267                    summary: "Ideal para streaming, navegação, email e redes sociais.",
9268                    benefits: [""],
9269                    idealFor: ""
9270                },
9271                "education": {
9272                    summary: "Ideal para atividades criativas, edição de fotos, criação de documentos e mais.",
9273                    benefits: [""],
9274                    idealFor: ""
9275                },
9276                "creativeTechnical": {
9277                    summary: "Ideal para processamento de texto, planilhas, apresentações e videochamadas...",
9278                    benefits: [""],
9279                    idealFor: ""
9280                },
9281                "business": {
9282                    summary: "Ideal para edição de fotos, vídeos e áudio, arquivos grandes e mais.",
9283                    benefits: [""],
9284                    idealFor: ""
9285                },
9286                "gaming": {
9287                    summary: "Ideal para jogadores apaixonados.",
9288                    benefits: [""],
9289                    idealFor: ""
9290                }
9291            },
9292            "fr": {
9293                "entertainment": {
9294                    summary: "Idéal pour le streaming, la navigation, les emails et les réseaux sociaux.",
9295                    benefits: [""],
9296                    idealFor: ""
9297                },
9298                "education": {
9299                    summary: "Idéal pour les activités créatives, la retouche photo, la création de documents et plus.",
9300                    benefits: [""],
9301                    idealFor: ""
9302                },
9303                "creativeTechnical": {
9304                    summary: "Idéal pour le traitement de texte, les tableur
9304s, les présentations et les appels vidéo...",
9305                    benefits: [""],
9306                    idealFor: ""
9307                },
9308                "business": {
9309                    summary: "Idéal pour la retouche photo, vidéo, audio, fichiers volumineux et plus.",
9310                    benefits: [""],
9311                    idealFor: ""
9312                },
9313                "gaming": {
9314                    summary: "Idéal pour les joueurs passionnés.",
9315                    benefits: [""],
9316                    idealFor: ""
9317                }
9318            },
9319            "nl": {
9320                "entertainment": {
9321                    summary: "Geschikt voor streaming, surfen, e-mail en sociale media.",
9322                    benefits: [""],
9323                    idealFor: ""
9324                },
9325                "education": {
9326                    summary: "Geschikt voor creatieve activiteiten, fotobewerking, documenten maken en meer.",
9327                    benefits: [""],
9328                    idealFor: ""
9329                },
9330                "creativeTechnical": {
9331                    summary: "Geschikt voor tekstverwerking, spreadsheets, presentaties en videogesprekken...",
9332                    benefits: [""],
9333                    idealFor: ""
9334                },
9335                "business": {
9336                    summary: "Geschikt voor foto-, video- en geluidsbewerking, grote bestanden en meer.",
9337                    benefits: [""],
9338                    idealFor: ""
9339                },
9340                "gaming": {
9341                    summary: "Geschikt voor fanatieke gamers.",
9342                    benefits: [""],
9343                    idealFor: ""
9344                }
9345            },
9346            "bg": {
9347                "entertainment": {
9348                    summary: "Подходящ за стрийминг, сърфиране, електронна поща и социални мрежи.",
9349                    benefits: [""],
9350                    idealFor: ""
9351                },
9352                "education": {
9353                    summary: "Подходящ за творчески дейности, редактиране на снимки, създаване на документи и др.",
9354                    benefits: [""],
9355                    idealFor: ""
9356                },
9357                "creativeTechnical": {
9358                    summary: "Подходящ за текстообработка, електронни таблици, презентации и видео разговори...",
9359                    benefits: [""],
9360                    idealFor: ""
9361                },
9362                "business": {
9363                    summary: "Подходящ за редактиране на снимки, видео и звук, големи файлове и др.",
9364                    benefits: [""],
9365                    idealFor: ""
9366                },
9367                "gaming": {
9368                    summary: "Подходящ за запалени геймъри.",
9369                    benefits: [""],
9370                    idealFor: ""
9371                }
9372            },
9373            "cs": {
9374                "entertainment": {
9375                    summary: "Vhodné pro streamování, prohlížení, e-mail a sociální sítě.",
9376                    benefits: [""],
9377                    idealFor: ""
9378                },
9379                "education": {
9380                    summary: "Vhodné pro kreativní činnosti, úpravu fotografií, tvorbu dokumentů a další.",
9381                    benefits: [""],
9382                    idealFor: ""
9383                },
9384                "creativeTechnical": {
9385                    summary: "Vhodné pro zpracování textu, tabulky, prezentace a videohovory...",
9386                    benefits: [""],
9387                    idealFor: ""
9388                },
9389                "business": {
9390                    summary: "Vhodné pro úpravu fotografií, videa a zvuku, velké soubory a další.",
9391                    benefits: [""],
9392                    idealFor: ""
9393                },
9394                "gaming": {
9395                    summary: "Vhodné pro vášnivé hráče.",
9396                    benefits: [""],
9397                    idealFor: ""
9398                }
9399            },
9400            "hr": {
9401                "entertainment": {
9402                    summary: "Najbolje za streaming, pregledavanje, e-poštu i društvene mreže.",
9403                    benefits: [""],
9404                    idealFor: ""
9405                },
9406                "education": {
9407                    summary: "Najbolje za kreativne aktivnosti, uređivanje fotografija, izradu dokumenata i još mnogo toga.",
9408                    benefits: [""],
9409                    idealFor: ""
9410                },
9411                "creativeTechnical": {
9412                    summary: "Najbolje za obradu teksta, tablice, prezentacije i video pozive...",
9413                    benefits: [""],
9414                    idealFor: ""
9415                },
9416                "business": {
9417                    summary: "Najbolje za uređivanje fotografija, video i zvuka, velike datoteke i još mnogo toga.",
9418                    benefits: [""],
9419                    idealFor: ""
9420                },
9421                "gaming": {
9422                    summary: "Najbolje za strastvene igrače.",
9423                    benefits: [""],
9424                    idealFor: ""
9425                }
9426            },
9427            "da": {
9428                "entertainment": {
9429                    summary: "Bedst til streaming, browsing, e-mail og sociale medier.",
9430                    benefits: [""],
9431                    idealFor: ""
9432                },
9433                "education": {
9434                    summary: "Bedst til kreative aktiviteter, fotoredigering, oprettelse af dokumenter og mere.",
9435                    benefits: [""],
9436                    idealFor: ""
9437                },
9438                "creativeTechnical": {
9439                    summary: "Bedst til tekstbehandling, regneark, præsentationer og videoopkald...",
9440                    benefits: [""],
9441                    idealFor: ""
9442                },
9443                "business": {
9444                    summary: "Bedst til foto-, video- og lydredigering, store filer og mere.",
9445                    benefits: [""],
9446                    idealFor: ""
9447                },
9448                "gaming": {
9449                    summary: "Bedst til ivrige gamere.",
9450                    benefits: [""],
9451                    idealFor: ""
9452                }
9453            },
9454            "de": {
9455                "entertainment": {
9456                    summary: "Ideal zum Streaming, Surfen, E-Mail und sozialen Medien.",
9457                    benefits: [""],
9458                    idealFor: ""
9459                },
9460                "education": {
9461                    summary: "Ideal für kreative Tätigkeiten, Fotobearbeitung, Dokumentenerstellung und mehr.",
9462                    benefits: [""],
9463                    idealFor: ""
9464                },
9465                "creativeTechnical": {
9466                    summary: "Ideal für Textverarbeitung, Tabellenkalkulationen, Präsentationen und Videoanrufe...",
9467                    benefits: [""],
9468                    idealFor: ""
9469                },
9470                "business": {
9471                    summary: "Ideal für Foto-, Video- und Tonbearbeitung, große Dateien und mehr.",
9472                    benefits: [""],
9473                    idealFor: ""
9474                },
9475                "gaming": {
9476                    summary: "Ideal für leidenschaftliche Gamer.",
9477                    benefits: [""],
9478                    idealFor: ""
9479                }
9480            },
9481            "et": {
9482                "entertainment": {
9483                    summary: "Parim voogedastuseks, sirvimiseks, e-postiks ja sotsiaalmeediaks.",
9484                    benefits: [""],
9485                    idealFor: ""
9486                },
9487                "education": {
9488                    summary: "Parim loominguliseks tööks, fototöötluseks, dokumentide loomiseks ja muuks.",
9489                    benefits: [""],
9490                    idealFor: ""
9491                },
9492                "creativeTechnical": {
9493                    summary: "Parim tekstiredigeerimiseks, tabelarvutuseks, esitluste ja videokõnede jaoks...",
9494                    benefits: [""],
9495                    idealFor: ""
9496                },
9497                "business": {
9498                    summary: "Parim fotode, videote ja heli redigeerimiseks, suurte failide töötlemiseks ja muuks.",
9499                    benefits: [""],
9500                    idealFor: ""
9501                },
9502                "gaming": {
9503                    summary: "Parim aktiivsetele mänguritele.",
9504                    benefits: [""],
9505                    idealFor: ""
9506                }
9507            },
9508            "el": {
9509                "entertainment": {
9510                    summary: "Καλύτερο για streaming, περιήγηση, email και κοινωνικά δίκτυα.",
9511                    benefits: [""],
9512                    idealFor: ""
9513                },
9514                "education": {
9515                    summary: "Καλύτερο για δημιουργικές δραστηριότητες, επεξεργασία φωτογραφιών, δημιουργία εγγράφων και άλλα.",
9516                    benefits: [""],
9517                    idealFor: ""
9518                },
9519                "creativeTechnical": {
9520                    summary: "Καλύτερο για επεξεργασία κειμένου, υπολογιστικά φύλλα, παρουσιάσεις και βιντεοκλήσεις...",
9521                    benefits: [""],
9522                    idealFor: ""
9523                },
9524                "business": {
9525                    summary: "Καλύτερο για επεξεργασία φωτογραφιών, βίντεο και ήχου, μεγάλα αρχεία και άλλα.",
9526                    benefits: [""],
9527                    idealFor: ""
9528                },
9529                "gaming": {
9530                    summary: "Καλύτερο για ενθουσιώδεις παίκτες.",
9531                    benefits: [""],
9532                    idealFor: ""
9533                }
9534            },
9535            "he": {
9536                "entertainment": {
9537                    summary: "הכי מתאים לסטרימינג, גלישה, דואר אלקטרוני ורשתות חברתיות.",
9538                    benefits: [""],
9539                    idealFor: ""
9540                },
9541                "education": {
9542                    summary: "הכי מתאים לפעילויות יצירתיות, עריכת תמונות, יצירת מסמכים ועוד.",
9543                    benefits: [""],
9544                    idealFor: ""
9545                },
9546                "creativeTechnical": {
9547                    summary: "הכי מתאים לעיבוד תמלילים, גיליונות אלקטרוניים, מצגות ושיחות וידאו...",
9548                    benefits: [""],
9549                    idealFor: ""
9550                },
9551                "business": {
9552                    summary: "הכי מתאים לעריכת תמונות, וידאו, סאונד, קבצים גדולים ועוד.",
9553                    benefits: [""],
9554                    idealFor: ""
9555                },
9556                "gaming": {
9557                    summary: "הכי מתאים לשחקנים נלהבים.",
9558                    benefits: [""],
9559                    idealFor: ""
9560                }
9561            },
9562            "it": {
9563                "entertainment": {
9564                    summary: "Ideale per streaming, navigazione, email e social media.",
9565                    benefits: [""],
9566                    idealFor: ""
9567                },
9568                "education": {
9569                    summary: "Ideale per attività creative, fotoritocco, creazione di documenti e altro.",
9570                    benefits: [""],
9571                    idealFor: ""
9572                },
9573                "creativeTechnical": {
9574                    summary: "Ideale per elaborazione testi, fogli di calcolo, presentazioni e videochiamate...",
9575                    benefits: [""],
9576                    idealFor: ""
9577                },
9578                "business": {
9579                    summary: "Ideale per fotoritocco, video, audio, file di grandi dimensioni e altro.",
9580                    benefits: [""],
9581                    idealFor: ""
9582                },
9583                "gaming": {
9584                    summary: "Ideale per giocatori appassionati.",
9585                    benefits: [""],
9586                    idealFor: ""
9587                }
9588            },
9589            "kk": {
9590                "entertainment": {
9591                    summary: "Ағынды видео көру, браузинг, электрондық пошта және әлеуметтік желілер үшін ең қолайлы.",
9592                    benefits: [""],
9593                    idealFor: ""
9594                },
9595                "education": {
9596                    summary: "Шығармашылық, фотосуреттерді өңдеу, құжаттар жасау және тағы басқалар үшін ең қолайлы.",
9597                    benefits: [""],
9598                    idealFor: ""
9599                },
9600                "creativeTechnical": {
9601                    summary: "Мәтіндік құжаттар, кестелер, презентациялар және бейнеконференциялар үшін ең қолайлы...",
9602                    benefits: [""],
9603                    idealFor: ""
9604                },
9605                "business": {
9606                    summary: "Фотосуреттерді, видеоны және дыбысты өңдеу, үлкен файлдар және тағы басқалар үшін ең қолайлы.",
9607                    benefits: [""],
9608                    idealFor: ""
9609                },
9610                "gaming": {
9611                    summary: "Ойын сүйер қауымға ең қолайлы.",
9612                    benefits: [""],
9613                    idealFor: ""
9614                }
9615            },
9616            "lv": {
9617                "entertainment": {
9618                    summary: "Vislabāk piemērots straumēšanai, pārlūkošanai, e-pastam un sociālajiem tīkliem.",
9619                    benefits: [""],
9620                    idealFor: ""
9621                },
9622                "education": {
9623                    summary: "Vislabāk piemērots radošām aktivitātēm, foto rediģēšanai, dokumentu veidošanai un citām darbībām.",
9624                    benefits: [""],
9625                    idealFor: ""
9626                },
9627                "creativeTechnical": {
9628                    summary: "Vislabāk piemērots teksta apstrādei, izklājlapām, prezentācijām un videozvaniem...",
9629                    benefits: [""],
9630                    idealFor: ""
9631                },
9632                "business": {
9633                    summary: "Vislabāk piemērots foto, video un skaņas rediģēšanai, lieliem failiem un citām vajadzībām.",
9634                    benefits: [""],
9635                    idealFor: ""
9636                },
9637                "gaming": {
9638                    summary: "Vislabāk piemērots entuziastiskiem spēlētājiem.",
9639                    benefits: [""],
9640                    idealFor: ""
9641                }
9642            },
9643            "lt": {
9644                "entertainment": {
9645                    summary: "Geriausia transliacijai, naršymui, el. paštui ir socialiniams tinklams.",
9646                    benefits: [""],
9647                    idealFor: ""
9648                },
9649                "education": {
9650                    summary: "Geriausia kūrybai, nuotraukų redagavimui, dokumentų kūrimui ir pan.",
9651                    benefits: [""],
9652                    idealFor: ""
9653                },
9654                "creativeTechnical": {
9655                    summary: "Geriausia tekstų redagavimui, lentelėms, pristatymams ir vaizdo skambučiams...",
9656                    benefits: [""],
9657                    idealFor: ""
9658                },
9659                "business": {
9660                    summary: "Geriausia nuotraukų, vaizdo ir garso redagavimui, dideliems failams ir daugiau.",
9661                    benefits: [""],
9662                    idealFor: ""
9663                },
9664                "gaming": {
9665                    summary: "Geriausia aistringiems žaidėjams.",
9666                    benefits: [""],
9667                    idealFor: ""
9668                }
9669            },
9670            "hu": {
9671                "entertainment": {
9672                    summary: "Legjobb streaminghez, böngészéshez, e-mailhez és közösségi médiához.",
9673                    benefits: [""],
9674                    idealFor: ""
9675                },
9676                "education": {
9677                    summary: "Legjobb kreatív tevékenységekhez, fényképszerkesztéshez, dokumentumkészítéshez és még sok máshoz.",
9678                    benefits: [""],
9679                    idealFor: ""
9680                },
9681                "creativeTechnical": {
9682                    summary: "Legjobb szövegszerkesztéshez, táblázatokhoz, prezentációkhoz és videóhívásokhoz...",
9683                    benefits: [""],
9684                    idealFor: ""
9685                },
9686                "business": {
9687                    summary: "Legjobb fénykép-, videó- és hangszerkesztéshez, nagy fájlokhoz és még sok máshoz.",
9688                    benefits: [""],
9689                    idealFor: ""
9690                },
9691                "gaming": {
9692                    summary: "Legjobb lelkes játékosoknak.",
9693                    benefits: [""],
9694                    idealFor: ""
9695                }
9696            },
9697            "ar": {
9698                "entertainment": {
9699                    summary: "أفضل للبث، التصفح، البريد الإلكتروني ووسائل التواصل الاجتماعي.",
9700                    benefits: [""],
9701                    idealFor: ""
9702                },
9703                "education": {
9704                    summary: "أفضل للأنشطة الإبداعية، تحرير الصور، إنشاء المستندات والمزيد.",
9705                    benefits: [""],
9706                    idealFor: ""
9707                },
9708                "creativeTechnical": {
9709                    summary: "أفضل لمعالجة النصوص، جداول البيانات، العروض التقديمية والمكالمات الفيديو...",
9710                    benefits: [""],
9711                    idealFor: ""
9712                },
9713                "business": {
9714                    summary: "أفضل لتحرير الصور، الفيديو، الصوت، الملفات الكبيرة والمزيد.",
9715                    benefits: [""],
9716                    idealFor: ""
9717                },
9718                "gaming": {
9719                    summary: "أفضل للاعبين المتحمسين.",
9720                    benefits: [""],
9721                    idealFor: ""
9722                }
9723            },
9724            "no": {
9725                "entertainment": {
9726                    summary: "Best for streaming, surfing, e-mail and social media.",
9727                    benefits: [""],
9728                    idealFor: ""
9729                },
9730                "education": {
9731                    summary: "Best for creative activities, photo editing, document creation and more.",
9732                    benefits: [""],
9733                    idealFor: ""
9734                },
9735                "creativeTechnical": {
9736                    summary: "Best for word processing, spreadsheets, presentations and video calls...",
9737                    benefits: [""],
9738                    idealFor: ""
9739                },
9740                "business": {
9741                    summary: "Best for photo, video and sound editing, large files and more.",
9742                    benefits: [""],
9743                    idealFor: ""
9744                },
9745                "gaming": {
9746                    summary: "Best for avid gamers.",
9747                    benefits: [""],
9748                    idealFor: ""
9749                }
9750            },
9751            "pl": {
9752                "entertainment": {
9753                    summary: "Najlepsze do streamingu, przeglądania, e-maila i mediów społecznościowych.",
9754                    benefits: [""],
9755                    idealFor: ""
9756                },
9757                "education": {
9758                    summary: "Najlepsze do działań kreatywnych, edycji zdjęć, tworzenia dokumentów i innych.",
9759                    benefits: [""],
9760                    idealFor: ""
9761                },
9762                "creativeTechnical": {
9763                    summary: "Najlepsze do edycji tekstu, arkuszy kalkulacyjnych, prezentacji i rozmów wideo...",
9764                    benefits: [""],
9765                    idealFor: ""
9766                },
9767                "business": {
9768                    summary: "Najlepsze do edycji zdjęć, wideo, dźwięku, dużych plików i innych.",
9769                    benefits: [""],
9770                    idealFor: ""
9771                },
9772                "gaming": {
9773                    summary: "Najlepsze dla zapalonych graczy.",
9774                    benefits: [""],
9775                    idealFor: ""
9776                }
9777            },
9778            "ro": {
9779                "entertainment": {
9780                    summary: "Ideal pentru streaming, navigare, email și social media.",
9781                    benefits: [""],
9782                    idealFor: ""
9783                },
9784                "education": {
9785                    summary: "Ideal pentru activități creative, editare foto, creare de documente și altele.",
9786                    benefits: [""],
9787                    idealFor: ""
9788                },
9789                "creativeTechnical": {
9790                    summary: "Ideal pentru procesare text, foi de calcul, prezentări și apeluri video...",
9791                    benefits: [""],
9792                    idealFor: ""
9793                },
9794                "business": {
9795                    summary: "Ideal pentru editare foto, video și sunet, fișiere mari și altele.",
9796                    benefits: [""],
9797                    idealFor: ""
9798                },
9799                "gaming": {
9800                    summary: "Ideal pentru jucători pasionați.",
9801                    benefits: [""],
9802                    idealFor: ""
9803                }
9804            },
9805            "sr": {
9806                "entertainment": {
9807                    summary: "Najbolje za striming, pretraživanje, e-poštu i društvene mreže.",
9808                    benefits: [""],
9809                    idealFor: ""
9810                },
9811                "education": {
9812                    summary: "Najbolje za kreativne aktivnosti, uređivanje fotografija, pravljenje dokumenata i još mnogo toga.",
9813                    benefits: [""],
9814                    idealFor: ""
9815                },
9816                "creativeTechnical": {
9817                    summary: "Najbolje za obradu teksta, tabele, prezentacije i video pozive...",
9818                    benefits: [""],
9819                    idealFor: ""
9820                },
9821                "business": {
9822                    summary: "Najbolje za uređivanje fotografija, videa, zvuka, velikih fajlova i još mnogo toga.",
9823                    benefits: [""],
9824                    idealFor: ""
9825                },
9826                "gaming": {
9827                    summary: "Najbolje za strastvene gejmere.",
9828                    benefits: [""],
9829                    idealFor: ""
9830                }
9831            },
9832            "sk": {
9833                "entertainment": {
9834                    summary: "Najlepšie na streamovanie, prehliadanie, e-maily a sociálne siete.",
9835                    benefits: [""],
9836                    idealFor: ""
9837                },
9838                "education": {
9839                    summary: "Najlepšie na tvorivé aktivity, úpravu fotiek, tvorbu dokumentov a ďalšie.",
9840                    benefits: [""],
9841                    idealFor: ""
9842                },
9843                "creativeTechnical": {
9844                    summary: "Najlepšie na spracovanie textov, tabuľky, prezentácie a videohovory...",
9845                    benefits: [""],
9846                    idealFor: ""
9847                },
9848                "business": {
9849                    summary: "Najlepšie na úpravu fotiek, videí a zvukov, veľkých súborov a ďalšie.",
9850                    benefits: [""],
9851                    idealFor: ""
9852                },
9853                "gaming": {
9854                    summary: "Najlepšie pre zapálených hráčov.",
9855                    benefits: [""],
9856                    idealFor: ""
9857                }
9858            },
9859            "sl": {
9860                "entertainment": {
9861                    summary: "Najbolje za pretakanje, brskanje, e-pošto in družbena omrežja.",
9862                    benefits: [""],
9863                    idealFor: ""
9864                },
9865                "education": {
9866                    summary: "Najbolje za ustvarjalne dejavnosti, urejanje fotografij, ustvarjanje dokumentov in drugo.",
9867                    benefits: [""],
9868                    idealFor: ""
9869                },
9870                "creativeTechnical": {
9871                    summary: "Najbolje za urejanje besedil, preglednic, predstavitev in video klice...",
9872                    benefits: [""],
9873                    idealFor: ""
9874                },
9875                "business": {
9876                    summary: "Najbolje za urejanje fotografij, videov in zvoka, velike datoteke in drugo.",
9877                    benefits: [""],
9878                    idealFor: ""
9879                },
9880                "gaming": {
9881                    summary: "Najbolje za strastne igralce.",
9882                    benefits: [""],
9883                    idealFor: ""
9884                }
9885            },
9886            "fi": {
9887                "entertainment": {
9888                    summary: "Paras suoratoistoon, selaamiseen, sähköpostiin ja sosiaaliseen mediaan.",
9889                    benefits: [""],
9890                    idealFor: ""
9891                },
9892                "education": {
9893                    summary: "Paras luovaan toimintaan, valokuvien muokkaamiseen, asiakirjojen luomiseen ja muuhun.",
9894                    benefits: [""],
9895                    idealFor: ""
9896                },
9897                "creativeTechnical": {
9898                    summary: "Paras tekstinkäsittelyyn, taulukoihin, esityksiin ja videopuheluihin...",
9899                    benefits: [""],
9900                    idealFor: ""
9901                },
9902                "business": {
9903                    summary: "Paras valokuvien, videoiden ja äänen muokkaukseen, suuriin tiedostoihin ja muuhun.",
9904                    benefits: [""],
9905                    idealFor: ""
9906                },
9907                "gaming": {
9908                    summary: "Paras innokkaille pelaajille.",
9909                    benefits: [""],
9910                    idealFor: ""
9911                }
9912            },
9913            "sv": {
9914                "entertainment": {
9915                    summary: "Bäst för streaming, surfning, e-post och sociala medier.",
9916                    benefits: [""],
9917                    idealFor: ""
9918                },
9919                "education": {
9920                    summary: "Bäst för kreativa aktiviteter, fotoredigering, dokumentskapande och mer.",
9921                    benefits: [""],
9922                    idealFor: ""
9923                },
9924                "creativeTechnical": {
9925                    summary: "Bäst för ordbehandling, kalkylblad, presentationer och videosamtal...",
9926                    benefits: [""],
9927                    idealFor: ""
9928                },
9929                "business": {
9930                    summary: "Bäst för foto-, video- och ljudredigering, stora filer och mer.",
9931                    benefits: [""],
9932                    idealFor: ""
9933                },
9934                "gaming": {
9935                    summary: "Bäst för hängivna spelare.",
9936                    benefits: [""],
9937                    idealFor: ""
9938                }
9939            },
9940            "tr": {
9941                "entertainment": {
9942                    summary: "Akış, gezinme, e-posta ve sosyal medya için en iyisi.",
9943                    benefits: [""],
9944                    idealFor: ""
9945                },
9946                "education": {
9947                    summary: "Yaratıcı aktiviteler, fotoğraf düzenleme, belge oluşturma ve daha fazlası için en iyisi.",
9948                    benefits: [""],
9949                    idealFor: ""
9950                },
9951                "creativeTechnical": {
9952                    summary: "Kelime işlem, hesap tabloları, sunumlar ve video aramaları için en iyisi...",
9953                    benefits: [""],
9954                    idealFor: ""
9955                },
9956                "business": {
9957                    summary: "Fotoğraf, video ve ses düzenleme, büyük dosyalar ve daha fazlası için en iyisi.",
9958                    benefits: [""],
9959                    idealFor: ""
9960                },
9961                "gaming": {
9962                    summary: "Tutkulu oyuncular için en iyisi.",
9963                    benefits: [""],
9964                    idealFor: ""
9965                }
9966            },
9967            "uk": {
9968                "entertainment": {
9969                    summary: "Найкраще для потокового перегляду, перегляду веб-сторінок, електронної пошти та соціальних мереж.",
9970                    benefits: [""],
9971                    idealFor: ""
9972                },
9973                "education": {
9974                    summary: "Найкраще для творчих завдань, редагування фото, створення документів та іншого.",
9975                    benefits: [""],
9976                    idealFor: ""
9977                },
9978                "creativeTechnical": {
9979                    summary: "Найкраще для обробки текстів, електронних таблиць, презентацій і відеодзвінків...",
9980                    benefits: [""],
9981                    idealFor: ""
9982                },
9983                "business": {
9984                    summary: "Найкраще для редагування фото, відео, звуку, великих файлів та іншого.",
9985                    benefits: [""],
9986                    idealFor: ""
9987                },
9988                "gaming": {
9989                    summary: "Найкраще для завзятих гравців.",
9990                    benefits: [""],
9991                    idealFor: ""
9992                }
9993            },
9994            "zh": {
9995                "entertainment": {
9996                    summary: "最适合流媒体、浏览、电子邮件和社交媒体。",
9997                    benefits: [""],
9998                    idealFor: ""
9999                },
10000                "education": {
10001                    summary: "最适合创意活动、照片编辑、创建文档等。",
10002                    benefits: [""],
10003                    idealFor: ""
10004                },
10005                "creativeTechnical": {
10006                    summary: "最适合文字处理、电子表格、演示文稿和视频通话...",
10007                    benefits: [""],
10008                    idealFor: ""
10009                },
10010                "business": {
10011                    summary: "最适合照片、视频和音频编辑,大文件等。",
10012                    benefits: [""],
10013                    idealFor: ""
10014                },
10015                "gaming": {
10016                    summary: "最适合狂热玩家。",
10017                    benefits: [""],
10018                    idealFor: ""
10019                }
10020            }
10021
10022            ,
10023            "id": {
10024                "entertainment": {
10025                    summary: "Terbaik untuk streaming, browsing, email, dan media s
10025osial.",
10026                    benefits: [""],
10027                    idealFor: ""
10028                },
10029                "education": {
10030                    summary: "Terbaik untuk kreativitas, pengeditan foto, membuat dokumen, dan lainnya.",
10031                    benefits: [""],
10032                    idealFor: ""
10033                },
10034                "creativeTechnical": {
10035                    summary: "Terbaik untuk pengolahan kata, spreadsheet, presentasi, dan panggilan video.",
10036                    benefits: [""],
10037                    idealFor: ""
10038                },
10039                "business": {
10040                    summary: "Terbaik untuk pengeditan foto, video, suara, file besar, dan lainnya.",
10041                    benefits: [""],
10042                    idealFor: ""
10043                },
10044                "gaming": {
10045                    summary: "Terbaik untuk para gamer berat.",
10046                    benefits: [""],
10047                    idealFor: ""
10048                }
10049            },
10050            "ja": {
10051                "entertainment": {
10052                    summary: "ストリーミング、ブラウジング、メール、ソーシャルメディアに最適です。",
10053                    benefits: [""],
10054                    idealFor: ""
10055                },
10056                "education": {
10057                    summary: "クリエイティブ、写真編集、ドキュメント作成などに最適です。",
10058                    benefits: [""],
10059                    idealFor: ""
10060                },
10061                "creativeTechnical": {
10062                    summary: "ワードプロセッシング、スプレッドシート、プレゼンテーション、ビデオ通話に最適です。",
10063                    benefits: [""],
10064                    idealFor: ""
10065                },
10066                "business": {
10067                    summary: "写真、ビデオ、音声編集、大容量ファイルなどに最適です。",
10068                    benefits: [""],
10069                    idealFor: ""
10070                },
10071                "gaming": {
10072                    summary: "熱心なゲーマーに最適です。",
10073                    benefits: [""],
10074                    idealFor: ""
10075                }
10076            },
10077            "ko": {
10078                "entertainment": {
10079                    summary: "스트리밍, 브라우징, 이메일 및 소셜 미디어에 가장 적합합니다.",
10080                    benefits: [""],
10081                    idealFor: ""
10082                },
10083                "education": {
10084                    summary: "창작, 사진 편집, 문서 작성 등에 가장 적합합니다.",
10085                    benefits: [""],
10086                    idealFor: ""
10087                },
10088                "creativeTechnical": {
10089                    summary: "워드 프로세싱, 스프레드시트, 프레젠테이션 및 화상 통화에 가장 적합합니다.",
10090                    benefits: [""],
10091                    idealFor: ""
10092                },
10093                "business": {
10094                    summary: "사진, 비디오, 사운드 편집, 대용량 파일 등에 가장 적합합니다.",
10095                    benefits: [""],
10096                    idealFor: ""
10097                },
10098                "gaming": {
10099                    summary: "열성 게이머에게 가장 적합합니다.",
10100                    benefits: [""],
10101                    idealFor: ""
10102                }
10103            },
10104            "ms": {
10105                "entertainment": {
10106                    summary: "Terbaik untuk penstriman, pelayaran, emel, dan media sosial.",
10107                    benefits: [""],
10108                    idealFor: ""
10109                },
10110                "education": {
10111                    summary: "Terbaik untuk kreativiti, penyuntingan foto, membuat dokumen, dan lain-lain.",
10112                    benefits: [""],
10113                    idealFor: ""
10114                },
10115                "creativeTechnical": {
10116                    summary: "Terbaik untuk pemprosesan kata, hamparan, pembentangan, dan panggilan video.",
10117                    benefits: [""],
10118                    idealFor: ""
10119                },
10120                "business": {
10121                    summary: "Terbaik untuk penyuntingan foto, video, bunyi, fail besar, dan lain-lain.",
10122                    benefits: [""],
10123                    idealFor: ""
10124                },
10125                "gaming": {
10126                    summary: "Terbaik untuk pemain tegar.",
10127                    benefits: [""],
10128                    idealFor: ""
10129                }
10130            },
10131            "fil": {
10132                "entertainment": {
10133                    summary: "Pinakamainam para sa streaming, pag-browse, email, at social media.",
10134                    benefits: [""],
10135                    idealFor: ""
10136                },
10137                "education": {
10138                    summary: "Pinakamainam para sa malikhaing gawain, pag-edit ng larawan, paggawa ng dokumento, at iba pa.",
10139                    benefits: [""],
10140                    idealFor: ""
10141                },
10142                "creativeTechnical": {
10143                    summary: "Pinakamainam para sa word processing, spreadsheets, presentasyon, at video calls.",
10144                    benefits: [""],
10145                    idealFor: ""
10146                },
10147                "business": {
10148                    summary: "Pinakamainam para sa pag-edit ng larawan, video, tunog, malalaking file, at iba pa.",
10149                    benefits: [""],
10150                    idealFor: ""
10151                },
10152                "gaming": {
10153                    summary: "Pinakamainam para sa mga mahilig maglaro.",
10154                    benefits: [""],
10155                    idealFor: ""
10156                }
10157            },
10158            "th": {
10159                "entertainment": {
10160                    summary: "เหมาะสำหรับการสตรีมมิ่ง, การท่องเว็บ, อีเมล และโซเชียลมีเดีย",
10161                    benefits: [""],
10162                    idealFor: ""
10163                },
10164                "education": {
10165                    summary: "เหมาะสำหรับงานสร้างสรรค์, การแก้ไขภาพถ่าย, การสร้างเอกสาร และอื่นๆ",
10166                    benefits: [""],
10167                    idealFor: ""
10168                },
10169                "creativeTechnical": {
10170                    summary: "เหมาะสำหรับการประมวลผลคำ, สเปรดชีต, การนำเสนอ และการโทรวิดีโอ",
10171                    benefits: [""],
10172                    idealFor: ""
10173                },
10174                "business": {
10175                    summary: "เหมาะสำหรับการแก้ไขภาพ, วิดีโอ, เสียง, ไฟล์ขนาดใหญ่ และอื่นๆ",
10176                    benefits: [""],
10177                    idealFor: ""
10178                },
10179                "gaming": {
10180                    summary: "เหมาะสำหรับนักเล่นเกมตัวยง",
10181                    benefits: [""],
10182                    idealFor: ""
10183                }
10184            },
10185            "vi": {
10186                "entertainment": {
10187                    summary: "Tốt nhất cho phát trực tuyến, duyệt web, email và mạng xã hội.",
10188                    benefits: [""],
10189                    idealFor: ""
10190                },
10191                "education": {
10192                    summary: "Tốt nhất cho sáng tạo, chỉnh sửa ảnh, tạo tài liệu và nhiều hơn nữa.",
10193                    benefits: [""],
10194                    idealFor: ""
10195                },
10196                "creativeTechnical": {
10197                    summary: "Tốt nhất cho xử lý văn bản, bảng tính, thuyết trình và gọi video.",
10198                    benefits: [""],
10199                    idealFor: ""
10200                },
10201                "business": {
10202                    summary: "Tốt nhất cho chỉnh sửa ảnh, video, âm thanh, file lớn và nhiều hơn nữa.",
10203                    benefits: [""],
10204                    idealFor: ""
10205                },
10206                "gaming": {
10207                    summary: "Tốt nhất cho game thủ nhiệt huyết.",
10208                    benefits: [""],
10209                    idealFor: ""
10210                }
10211            }
10212
10213        },
10214        prefix: {
10215            "us": "Ideal for: ",
10216            "es": "Ideal para: ",
10217            "pt": "Ideal para: ",
10218            "fr": "Idéal pour : ",
10219            "nl": "Ideaal voor: ",
10220            "bg": "Подходящ за: ",
10221            "cs": "Ideální pro: ",
10222            "hr": "Idealno za: ",
10223            "da": "Ideel til: ",
10224            "de": "Ideal für: ",
10225            "et": "Ideaalne: ",
10226            "el": "Ιδανικό για: ",
10227            "he": "אידיאלי עבור: ",
10228            "it": "Ideale per: ",
10229            "kk": "Үшін қолайлы: ",
10230            "lv": "Ideāli piemērots: ",
10231            "lt": "Idealiai tinka: ",
10232            "hu": "Ideális erre: ",
10233            "ar": "مثالي لـ: ",
10234            "no": "Ideell for: ",
10235            "pl": "Idealne dla: ",
10236            "ro": "Ideal pentru: ",
10237            "sr": "Идеално за: ",
10238            "sk": "Ideálne pre: ",
10239            "sl": "Idealno za: ",
10240            "fi": "Ihanteellinen: ",
10241            "sv": "Perfekt för: ",
10242            "tr": "İdeal olan: ",
10243            "uk": "Ідеально для: ",
10244            "zh": "适用于:",
10245            "id": "Ideal untuk: ",
10246            "ja": "〜に最適:",
10247            "ko": "이상적임: ",
10248            "ms": "Sesuai untuk: ",
10249            "fil": "Mainam para sa: ",
10250            "th": "เหมาะสำหรับ: ",
10251            "vi": "Lý tưởng cho: "
10252        }
10253    },
10254    quizEntryContent: {
10255        header: {
10256            "us": "var HP Recommend a new PC for you",
10257            "es": "Deja que HP te recomiende un nuevo PC",
10258            "pt": "Deixe a HP recomendar um novo PC para você",
10259            "fr": "Laissez HP vous recommander un nouveau PC",
10260            "nl": "Laat HP een nieuwe pc voor je aanbevelen",
10261            "bg": "Нека HP ви препоръча нов компютър",
10262            "cs": "Nechte HP doporučit nový počítač pro vás",
10263            "hr": "Neka HP preporuči novo računalo za vas",
10264            "da": "Lad HP anbefale en ny pc til dig",
10265            "de": "Lassen Sie HP einen neuen PC für Sie empfehlen",
10266            "et": "Lase HP-l soovitada sulle uus arvuti",
10267            "el": "Αφήστε την HP να σας προτείνει έναν νέο υπολογιστή",
10268            "he": "תן ל-HP להמליץ על מחשב חדש עבורך",
10269            "it": "Lascia che HP ti consigli un nuovo PC",
10270            "kk": "HP сізге жаңа ДК ұсынсын",
10271            "lv": "Ļaujiet HP ieteikt jums jaunu datoru",
10272            "lt": "Leiskite HP rekomenduoti jums naują kompiuterį",
10273            "hu": "Hagyja, hogy a HP új számítógépet ajánljon Önnek",
10274            "ar": "دع HP توصي بجهاز كمبيوتر جديد لك",
10275            "no": "La HP anbefale en ny PC for deg",
10276            "pl": "Pozwól HP polecić nowy komputer dla Ciebie",
10277            "ro": "Permiteți HP să vă recomande un nou PC",
10278            "sr": "Neka HP preporuči novi računar za vas",
10279            "sk": "Nechajte HP odporučiť vám nový počítač",
10280            "sl": "Naj HP priporoči nov računalnik za vas",
10281            "fi": "Anna HP:n suositella sinulle uutta tietokonetta",
10282            "sv": "Låt HP rekommendera en ny dator för dig",
10283            "tr": "HP'nin size yeni bir bilgisayar önermesine izin verin",
10284            "uk": "Дозвольте HP рекомендувати вам новий ПК",
10285            "zh": "让 HP 为您推荐一台新电脑",
10286            "id": "Biarkan HP merekomendasikan PC baru untuk Anda",
10287            "ja": "HP に新しい PC をおすすめさせましょう",
10288            "ko": "HP가 새로운 PC를 추천해 드리겠습니다",
10289            "ms": "Biarkan HP mencadangkan PC baharu untuk anda",
10290            "fil": "Hayaan ang HP na magrekomenda ng bagong PC para sa iyo",
10291            "th": "ให้ HP แนะนำพีซีใหม่สำหรับคุณ",
10292            "vi": "Hãy để HP đề xuất cho bạn một máy tính mới"
10293        },
10294        description: {
10295            "us": "Answer 3 questions and var HP find it for you.",
10296            "es": "Responde 3 preguntas y deja que HP lo encuentre por ti.",
10297            "pt": "Responda a 3 perguntas e deixe a HP encontrá-lo para você.",
10298            "fr": "Répondez à 3 questions et laissez HP le trouver pour vous.",
10299            "nl": "Beantwoord 3 vragen en laat HP het voor je vinden.",
10300            "bg": "Отговорете на 3 въпроса и оставете HP да го намери за вас.",
10301            "cs": "Odpovězte na 3 otázky a nechte HP to najít za vás.",
10302            "hr": "Odgovorite na 3 pitanja i neka HP to pronađe za vas.",
10303            "da": "Besvar 3 spørgsmål, og lad HP finde det for dig.",
10304            "de": "Beantworten Sie 3 Fragen und lassen Sie HP es für Sie finden.",
10305            "et": "Vasta 3 küsimusele ja lase HP-l see sinu jaoks leida.",
10306            "el": "Απαντήστε σε 3 ερωτήσεις και αφήστε την HP να το βρει για εσάς.",
10307            "he": "ענה על 3 שאלות ותן ל-HP למצוא את זה עבורך.",
10308            "it": "Rispondi a 3 domande e lascia che HP lo trovi per te.",
10309            "kk": "3 сұраққа жауап беріңіз, HP оны сіз үшін тапсын.",
10310            "lv": "Atbildiet uz 3 jautājumiem un ļaujiet HP to atrast jums.",
10311            "lt": "Atsakykite į 3 klausimus ir leiskite HP tai rasti jums.",
10312            "hu": "Válaszoljon 3 kérdésre, és hagyja, hogy a HP megtalálja azt Önnek.",
10313            "ar": "أجب عن 3 أسئلة ودع HP يجدها لك.",
10314            "no": "Svar på 3 spørsmål, og la HP finne det for deg.",
10315            "pl": "Odpowiedz na 3 pytania i pozwól HP znaleźć to dla Ciebie.",
10316            "ro": "Răspundeți la 3 întrebări și lăsați HP să o găsească pentru dvs.",
10317            "sr": "Odgovorite na 3 pitanja i neka HP to pronađe za vas.",
10318            "sk": "Odpovedzte na 3 otázky a nechajte HP, aby to našla za vás.",
10319            "sl": "Odgovorite na 3 vprašanja in dovolite, da HP to najde za vas.",
10320            "fi": "Vastaa 3 kysymykseen ja anna HP:n löytää se sinulle.",
10321            "sv": "Svara på 3 frågor och låt HP hitta det åt dig.",
10322            "tr": "3 soruyu yanıtlayın ve HP'nin sizin için bulmasına izin verin.",
10323            "uk": "Відповідайте на 3 запитання, і дозвольте HP знайти це для вас.",
10324            "zh": "回答3个问题,让HP为您找到它。",
10325            "id": "Jawab 3 pertanyaan dan biarkan HP menemukannya untuk Anda.",
10326            "ja": "3つの質問に答えて、HPにそれを見つけてもらいましょう。",
10327            "ko": "3개의 질문에 답하고 HP가 그것을 찾아드리게 하세요.",
10328            "ms": "Jawab 3 soalan dan biarkan HP mencarinya untuk anda.",
10329            "fil": "Sagutin ang 3 tanong at hayaan ang HP na hanapin ito para sa iyo.",
10330            "th": "ตอบคำถาม 3 ข้อ แล้วให้ HP ค้นหาสิ่งนั้นให้คุณ",
10331            "vi": "Trả lời 3 câu hỏi và để HP tìm nó cho bạn."
10332        },
10333        cta: {
10334            "us": "Get started",
10335            "es": "Comenzar",
10336            "pt": "Começar",
10337            "fr": "Commencer",
10338            "nl": "Begin",
10339            "bg": "Започнете",
10340            "cs": "Začít",
10341            "hr": "Započnite",
10342            "da": "Kom godt i gang",
10343            "de": "Loslegen",
10344            "et": "Alusta",
10345            "el": "Ξεκινήστε",
10346            "he": "התחל",
10347            "it": "Inizia",
10348            "kk": "Бастау",
10349            "lv": "Sākt",
10350            "lt": "Pradėti",
10351            "hu": "Kezdjen",
10352            "ar": "ابدأ",
10353            "no": "Kom i gang",
10354            "pl": "Zacznij",
10355            "ro": "Începe",
10356            "sr": "Počnite",
10357            "sk": "Začnite",
10358            "sl": "Začnite",
10359            "fi": "Aloita",
10360            "sv": "Kom igång",
10361            "tr": "Başlayın",
10362            "uk": "Почати",
10363            "zh": "开始",
10364            "id": "Mulai",
10365            "ja": "始める",
10366            "ko": "시작하기",
10367            "ms": "Mula",
10368            "fil": "Magsimula",
10369            "th": "เริ่มต้น",
10370            "vi": "Bắt đầu"
10371        }
10372    },
10373    quizBodyContent: {
10374        header: {
10375            "us": "Answer these questions to discover the ideal device for you",
10376            "es": "Responde estas preguntas para descubrir el dispositivo ideal para ti",
10377            "pt": "Responda a estas perguntas para descobrir o dispositivo ideal para você",
10378            "fr": "Répondez à ces questions pour découvrir l'appareil idéal pour vous",
10379            "nl": "Beantwoord deze vragen om het ideale apparaat voor jou te ontdekken",
10380            "bg": "Отговорете на тези въпроси, за да откриете идеалното устройство за вас",
10381            "cs": "Odpovězte na tyto otázky a objevte ideální zařízení pro vás",
10382            "hr": "Odgovorite na ova pitanja kako biste otkrili idealni uređaj za vas",
10383            "da": "Besvar disse spørgsmål for at finde den ideelle enhed til dig",
10384            "de": "Beantworten Sie diese Fragen, um das ideale Gerät für Sie zu finden",
10385            "et": "Vasta nendele küsimustele, et leida endale ideaalne seade",
10386            "el": "Απαντήστε σε αυτές τις ερωτήσεις για να ανακαλύψετε τη ιδανική συσκευή για εσάς",
10387            "he": "ענה על השאלות האלה כדי לגלות את המכשיר האידיאלי עבורך",
10388            "it": "Rispondi a queste domande per scoprire il dispositivo ideale per te",
10389            "kk": "Сізге арналған идеалды құрылғыны табу үшін осы сұрақтарға жауап беріңіз",
10390            "lv": "Atbildiet uz šiem jautājumiem, lai atklātu jums ideālo ierīci",
10391            "lt": "Atsakykite į šiuos klausimus, kad atrastumėte jums idealiausią įrenginį",
10392            "hu": "Válaszoljon ezekre a kérdésekre, hogy megtalálja az Ön számára ideális eszközt",
10393            "ar": "أجب عن هذه الأسئلة لاكتشاف الجهاز المثالي لك",
10394            "no": "Svar på disse spørsmålene for å finne den ideelle enheten for deg",
10395            "pl": "Odpowiedz na te pytania, aby odkryć idealne urządzenie dla siebie",
10396            "ro": "Răspundeți la aceste întrebări pentru a descoperi dispozitivul ideal pentru dvs.",
10397            "sr": "Odgovorite na ova pitanja kako biste otkrili idealan uređaj za vas",
10398            "sk": "Odpovedzte na tieto otázky, aby ste objavili ideálne zariadenie pre vás",
10399            "sl": "Odgovorite na ta vprašanja, da odkrijete idealno napravo za vas",
10400            "fi": "Vastaa näihin kysymyksiin löytääksesi sinulle ihanteellisen laitteen",
10401            "sv": "Svara på dessa frågor för att upptäcka den idealiska enheten för dig",
10402            "tr": "Senin için ideal cihazı keşfetmek için bu soruları yanıtla",
10403            "uk": "Відповідайте на ці запитання, щоб знайти ідеальний пристрій для себе",
10404            "zh": "回答这些问题,发现适合您的理想设备",
10405            "id": "Jawab pertanyaan-pertanyaan ini untuk menemukan perangkat ideal untuk Anda",
10406            "ja": "これらの質問に答えて、あなたに最適なデバイスを見つけましょう",
10407            "ko": "이 질문에 답하여 당신에게 이상적인 장치를 찾아보세요",
10408            "ms": "Jawab soalan-soalan ini untuk menemui peranti yang sesuai untuk anda",
10409            "fil": "Sagutin ang mga tanong na ito upang matuklasan ang perpektong device para sa iyo",
10410            "th": "ตอบคำถามเหล่านี้เพื่อค้นหาอุปกรณ์ที่เหมาะสมสำหรับคุณ",
10411            "vi": "Trả lời những câu hỏi này để khám phá thiết bị lý tưởng cho bạn"
10412        },
10413        questions: {
10414            first: {
10415                "us": "Where will the device primarily be used?",
10416                "es": "¿Dónde se utilizará principalmente el dispositivo?",
10417                "pt": "Onde o dispositivo será usado principalmente?",
10418                "fr": "Où l'appareil sera-t-il principalement utilisé ?",
10419                "nl": "Waar zal het apparaat voornamelijk worden gebruikt?",
10420                "bg": "Къде основно ще се използва устройството?",
10421                "cs": "Kde bude zařízení primárně používáno?",
10422                "hr": "Gdje će se uređaj prvenstveno koristiti?",
10423                "da": "Hvor vil enheden primært blive brugt?",
10424                "de": "Wo wird das Gerät hauptsächlich verwendet?",
10425                "et": "Kus seadet peamiselt kasutatakse?",
10426                "el": "Πού θα χρησιμοποιείται κυρίως η συσκευή;",
10427                "he": "היכן ייעשה שימוש עיקרי במכשיר?",
10428                "it": "Dove verrà utilizzato principalmente il dispositivo?",
10429                "kk": "Құрылғы негізінен қай жерде қолданылады?",
10430                "lv": "Kur ierīce galvenokārt tiks izmantota?",
10431                "lt": "Kur prietaisas bus daugiausia naudojamas?",
10432                "hu": "Hol fogják elsősorban használni az eszközt?",
10433                "ar": "أين سيتم استخدام الجهاز بشكل أساسي؟",
10434                "no": "Hvor vil enheten hovedsakelig bli brukt?",
10435                "pl": "Gdzie urządzenie będzie głównie używane?",
10436                "ro": "Unde va fi utilizat în principal dispozitivul?",
10437                "sr": "Gde će se uređaj prvenstveno koristiti?",
10438                "sk": "Kde sa bude zariadenie primárne používať?",
10439                "sl": "Kje bo naprava večinoma uporabljena?",
10440                "fi": "Missä laitetta käytetään pääasiassa?",
10441                "sv": "Var kommer enheten främst att användas?",
10442                "tr": "Cihaz ağırlıklı olarak nerede kullanılacak?",
10443                "uk": "Де пристрій буде переважно використовуватися?",
10444                "zh": "该设备主要将在何处使用?",
10445                "id": "Di mana perangkat akan digunakan terutama?",
10446                "ja": "デバイスは主にどこで使用されますか?",
10447                "ko": "기기는 주로 어디에서 사용될 예정입니까?",
10448                "ms": "Di manakah peranti akan digunakan terutamanya?",
10449                "fil": "Saan pangunahing gagamitin ang device?",
10450                "th": "อุปกรณ์จะถูกใช้งานหลัก ๆ ที่ไหน?",
10451                "vi": "Thiết bị sẽ chủ yếu được sử dụng ở đâu?"
10452            },
10453            second: {
10454                "us": "How will the device be used?",
10455                "es": "¿Cómo se utilizará el dispositivo?",
10456                "pt": "Como o dispositivo será usado?",
10457                "fr": "Comment l'appareil sera-t-il utilisé ?",
10458                "nl": "Hoe zal het apparaat worden gebruikt?",
10459                "bg": "Как ще се използва устройството?",
10460                "cs": "Jak bude zařízení používáno?",
10461                "hr": "Kako će se uređaj koristiti?",
10462                "da": "Hvordan vil enheden blive brugt?",
10463                "de": "Wie wird das Gerät verwendet?",
10464                "et": "Kuidas seadet kasutatakse?",
10465                "el": "Πώς θα χρησιμοποιηθεί η συσκευή;",
10466                "he": "כיצד ייעשה שימוש במכשיר?",
10467                "it": "Come verrà utilizzato il dispositivo?",
10468                "kk": "Құрылғы қалай пайдаланылады?",
10469                "lv": "Kā ierīce tiks izmantota?",
10470                "lt": "Kaip bus naudojamas įrenginys?",
10471                "hu": "Hogyan fogják használni az eszközt?",
10472                "ar": "كيف سيتم استخدام الجهاز؟",
10473                "no": "Hvordan vil enheten bli brukt?",
10474                "pl": "Jak będzie używane urządzenie?",
10475                "ro": "Cum va fi utilizat dispozitivul?",
10476                "sr": "Kako će se uređaj koristiti?",
10477                "sk": "Ako sa bude zariadenie používať?",
10478                "sl": "Kako bo naprava uporabljena?",
10479                "fi": "Kuinka laitetta käytetään?",
10480                "sv": "Hur kommer enheten att användas?",
10481                "tr": "Cihaz nasıl kullanılacak?",
10482                "uk": "Як буде використовуватися пристрій?",
10483                "zh": "该设备将如何使用?",
10484                "id": "Bagaimana perangkat akan digunakan?",
10485                "ja": "デバイスはどのように使用されますか?",
10486                "ko": "기기는 어떻게 사용될 예정입니까?",
10487                "ms": "Bagaimanakah peranti akan digunakan?",
10488                "fil": "Paano gagamitin ang device?",
10489                "th": "อุปกรณ์จะถูกใช้งานอย่างไร?",
10490                "vi": "Thiết bị sẽ được sử dụng như thế nào?"
10491            }
10492
10493            ,
10494            third: {
10495                "us": "What features matter most to you?",
10496                "es": "¿Qué características son más importantes para ti?",
10497                "pt": "Quais recursos são mais importantes para você?",
10498                "fr": "Quelles fonctionnalités sont les plus importantes pour vous ?",
10499                "nl": "Welke functies zijn voor jou het belangrijkst?",
10500                "bg": "Кои функции са най-важни за вас?",
10501                "cs": "Na kterých funkcích vám nejvíce záleží?",
10502                "hr": "Koje su vam značajke najvažnije?",
10503                "da": "Hvilke funktioner er vigtigst for dig?",
10504                "de": "Welche Funktionen sind für Sie am wichtigsten?",
10505                "et": "Millised funktsioonid on teie jaoks kõige olulisemad?",
10506                "el": "Ποιες λειτουργίες έχουν μεγαλύτερη σημασία για εσάς;",
10507                "he": "אילו תכונות חשובות לך ביותר?",
10508                "it": "Quali funzionalità sono più importanti per te?",
10509                "kk": "Сіз үшін қандай мүмкіндіктер ең маңызды?",
10510                "lv": "Kuras funkcijas jums ir visnozīmīgākās?",
10511                "lt": "Kurios funkcijos jums yra svarbiausios?",
10512                "hu": "Mely funkciók a legfontosabbak az Ön számára?",
10513                "ar": "ما هي الميزات الأكثر أهمية بالنسبة لك؟",
10514                "no": "Hvilke funksjoner er viktigst for deg?",
10515                "pl": "Które funkcje są dla Ciebie najważniejsze?",
10516                "ro": "Care caracteristici sunt cele mai importante pentru tine?",
10517                "sr": "Koje su funkcije najvažnije za vas?",
10518                "sk": "Na ktorých funkciách vám najviac záleží?",
10519                "sl": "Katere funkcije so vam najpomembnejše?",
10520                "fi": "Mitkä ominaisuudet ovat sinulle tärkeimpiä?",
10521                "sv": "Vilka funktioner är viktigast för dig?",
10522                "tr": "Sizin için en önemli özellikler nelerdir?",
10523                "uk": "Які функції для вас найважливіші?",
10524                "zh": "哪些功能对您最重要?",
10525                "id": "Fitur apa yang paling penting bagi Anda?",
10526                "ja": "どの機能が最も重要ですか?",
10527                "ko": "어떤 기능이 가장 중요합니까?",
10528                "ms": "Apakah ciri-ciri yang paling penting bagi anda?",
10529                "fil": "Aling mga tampok ang pinakamahalaga sa iyo?",
10530                "th": "คุณสมบัติใดที่สำคัญที่สุดสำหรับคุณ?",
10531                "vi": "Những tính năng nào quan trọng nhất đối với bạn?"
10532            }
10533        },
10534        answers: {
10535            setLocation: {
10536                "CAP": "Set location (Desktop)",
10537                "us": "Set location (Desktop)",
10538                "es": "Establecer ubicación (Escritorio)",
10539                "pt": "Definir local (Computador)",
10540                "fr": "Définir l’emplacement (Bureau)",
10541                "nl": "Locatie instellen (Desktop)",
10542                "bg": "Задаване на местоположение (Настолен)",
10543                "cs": "Nastavit polohu (Stolní PC)",
10544                "hr": "Postavi lokaciju (Stolno računalo)",
10545                "da": "Angiv placering (Stationær)",
10546                "de": "Standort festlegen (PC)",
10547                "et": "Määra asukoht (Lauaarvuti)",
10548                "el": "Ορισμός τοποθεσίας (Σταθερός)",
10549                "he": "הגדר מיקום (נייח)",
10550                "it": "Imposta posizione (Fisso)",
10551                "kk": "Орналасуды орнату (Үстелдік)",
10552                "lv": "Iestatīt atrašanās vietu (Galddators)",
10553                "lt": "Nustatyti vietą (Stacionarus)",
10554                "hu": "Hely beállítása (Asztali gép)",
10555                "ar": "تعيين الموقع (جهاز مكتبي)",
10556                "no": "Angi plassering (Stasjonær)",
10557                "pl": "Ustaw lokalizację (Stacjonarny)",
10558                "ro": "Setează locația (Desktop)",
10559                "sr": "Podesi lokaciju (Stoni računar)",
10560                "sk": "Nastaviť polohu (Stolný PC)",
10561                "sl": "Nastavi lokacijo (Namizni)",
10562                "fi": "Aseta sijainti (Pöytäkone)",
10563                "sv": "Ange plats (Stationär)",
10564                "tr": "Konum ayarla (Masaüstü)",
10565                "uk": "Встановити місцезнаходження (Настільний)",
10566                "zh": "设置位置(台式机)",
10567                "id": "Atur lokasi (PC Meja)",
10568                "ja": "場所を設定(デスクトップ)",
10569                "ko": "위치 설정 (데스크탑)",
10570                "ms": "Tetapkan lokasi (Komputer Meja)",
10571                "fil": "Itakda ang lokasyon (Desktop)",
10572                "th": "ตั้งค่าตำแหน่ง (เดสก์ท็อป)",
10573                "vi": "Đặt vị trí (Máy bàn)"
10574            }
10575            ,
10576            onTheGo: {
10577                "CAP": "On the go (Laptop)",
10578                "us": "On the go (Laptop)",
10579                "es": "En movimiento (portátil)",
10580                "pt": "Em movimento (notebook)",
10581                "fr": "En déplacement (portable)",
10582                "nl": "Onderweg (laptop)",
10583                "bg": "В движение (лаптоп)",
10584                "cs": "Na cestách (notebook)",
10585                "hr": "U pokretu (laptop)",
10586                "da": "På farten (bærbar)",
10587                "de": "Unterwegs (laptop)",
10588                "et": "Liikvel olles (sülearvuti)",
10589                "el": "Εν κινήσει (laptop)",
10590                "he": "תוך כדי תנועה (נייד)",
10591                "it": "In movimento (portatile)",
10592                "kk": "Жолда (ноутбук)",
10593                "lv": "Ceļā (portatīvais)",
10594                "lt": "Kelyje (nešiojamas)",
10595                "hu": "Útközben (laptop)",
10596                "ar": "أثناء التنقل (لابتوب)",
10597                "no": "På farten (bærbar)",
10598                "pl": "W drodze (laptop)",
10599                "ro": "În mișcare (laptop)",
10600                "sr": "U pokretu (laptop)",
10601                "sk": "Na cestách (notebook)",
10602                "sl": "Na poti (prenosnik)",
10603                "fi": "Liikkeellä (kannettava)",
10604                "sv": "På språng (bärbar)",
10605                "tr": "Hareket halinde (dizüstü)",
10606                "uk": "У дорозі (ноутбук)",
10607                "zh": "移动中(笔记本)",
10608                "id": "Sedang bepergian (laptop)",
10609                "ja": "外出先で(ノートpc)",
10610                "ko": "이동 중 (노트북)",
10611                "ms": "Semasa bergerak (komputer riba)",
10612                "fil": "Habang nasa biyahe (laptop)",
10613                "th": "ระหว่างเดินทาง (แล็ปท็อป)",
10614                "vi": "Khi di chuyển (laptop)"
10615            }
10616            ,
10617            entertainment: {
10618                "CAP": "Entertainment & Personal",
10619                "us": "Entertainment & Personal",
10620                "es": "Entretenimiento y uso personal",
10621                "pt": "Entretenimento e uso pessoal",
10622                "fr": "Divertissement et usage personnel",
10623                "nl": "Amusement en persoonlijk gebruik",
10624                "bg": "Развлечение и лично ползване",
10625                "cs": "Zábava a osobní použití",
10626                "hr": "Zabava i osobna upotreba",
10627                "da": "Underholdning og personlig brug",
10628                "de": "Unterhaltung und persönliche Nutzung",
10629                "et": "Meelelahutus ja isiklik kasutus",
10630                "el": "Ψυχαγωγία και προσωπική χρήση",
10631                "he": "בידור ושימוש אישי",
10632                "it": "Intrattenimento e uso personale",
10633                "kk": "Ойын-сауық және жеке пайдалану",
10634                "lv": "Izklaide un personīga lietošana",
10635                "lt": "Pramogoms ir asmeniniam naudojimui",
10636                "hu": "Szórakozás és személyes használat",
10637                "ar": "ترفيه واستخدام شخصي",
10638                "no": "Underholdning og personlig bruk",
10639                "pl": "Rozrywka i użytki osobiste",
10640                "ro": "Divertisment și uz personal",
10641                "sr": "Zabava i lična upotreba",
10642                "sk": "Zábava a osobné použitie",
10643                "sl": "Zabava in osebna raba",
10644                "fi": "Viihde ja henkilökohtainen käyttö",
10645                "sv": "Underhållning och personligt bruk",
10646                "tr": "Eğlence ve kişisel kullanım",
10647                "uk": "Розваги та особисте використання",
10648                "zh": "娱乐和个人使用",
10649                "id": "Hiburan dan penggunaan pribadi",
10650                "ja": "エンタメ・個人利用",
10651                "ko": "엔터테인먼트 및 개인용",
10652                "ms": "Hiburan & penggunaan peribadi",
10653                "fil": "Aliwan at personal na gamit",
10654                "th": "ความบันเทิงและการใช้งานส่วนตัว",
10655                "vi": "Giải trí và sử dụng cá nhân"
10656            }
10657            ,
10658            education: {
10659                "CAP": "Education & Hobbies",
10660                "us": "Education & Hobbies",
10661                "es": "Educación y pasatiempos",
10662                "pt": "Educação e hobbies",
10663                "fr": "Éducation et loisirs",
10664                "nl": "Onderwijs en hobby's",
10665                "bg": "Образование и хобита",
10666                "cs": "Vzdělání a koníčky",
10667                "hr": "Obrazovanje i hobiji",
10668                "da": "Uddannelse og hobbyer",
10669                "de": "Bildung und Hobbys",
10670                "et": "Haridus ja hobid",
10671                "el": "Εκπαίδευση και χόμπι",
10672                "he": "חינוך ותחביבים",
10673                "it": "Istruzione e hobby",
10674                "kk": "Білім және хобби",
10675                "lv": "Izglītība un hobiji",
10676                "lt": "Švietimas ir pomėgiai",
10677                "hu": "Oktatás és hobbi",
10678                "ar": "تعليم وهوايات",
10679                "no": "Utdanning og hobbyer",
10680                "pl": "Edukacja i hobby",
10681                "ro": "Educație și hobby-uri",
10682                "sr": "Obrazovanje i hobiji",
10683                "sk": "Vzdelanie a záľuby",
10684                "sl": "Izobraževanje in hobiji",
10685                "fi": "Koulutus ja harrastukset",
10686                "sv": "Utbildning och hobbyer",
10687                "tr": "Eğitim ve hobiler",
10688                "uk": "Освіта та хобі",
10689                "zh": "教育和爱好",
10690                "id": "Pendidikan dan hobi",
10691                "ja": "教育・趣味",
10692                "ko": "교육 및 취미",
10693                "ms": "Pendidikan & hobi",
10694                "fil": "Edukasyon at libangan",
10695                "th": "การศึกษาและงานอดิเรก",
10696                "vi": "Giáo dục và sở thích"
10697            }
10698            ,
10699            creativeTechnical: {
10700                "CAP": "Creative & Technical",
10701                "us": "Creative & Technical",
10702                "es": "Uso creativo y técnico",
10703                "pt": "Uso criativo e técnico",
10704                "fr": "Utilisation créative et technique",
10705                "nl": "Creatief en technisch gebruik",
10706                "bg": "Креативна и техническа употреба",
10707                "cs": "Kreativní a technické použití",
10708                "hr": "Kreativna i tehnička upotreba",
10709                "da": "Kreativ og teknisk brug",
10710                "de": "Kreative und technische Nutzung",
10711                "et": "Loominguline ja tehniline kasutus",
10712                "el": "Δημιουργική και τεχνική χρήση",
10713                "he": "שימוש יצירתי וטכני",
10714                "it": "Uso creativo e tecnico",
10715                "kk": "Шығармашылық және техникалық қолдану",
10716                "lv": "Radoša un tehniska lietošana",
10717                "lt": "Kūrybinis ir techninis naudojimas",
10718                "hu": "Kreatív és technikai használat",
10719                "ar": "استخدام إبداعي وتقني",
10720                "no": "Kreativ og teknisk bruk",
10721                "pl": "Użytek kreatywny i techniczny",
10722                "ro": "Utilizare creativă și tehnică",
10723                "sr": "Kreativna i tehnička upotreba",
10724                "sk": "Kreatívne a technické použitie",
10725                "sl": "Kreativna in tehnična uporaba",
10726                "fi": "Luova ja tekninen käyttö",
10727                "sv": "Kreativ och teknisk användning",
10728                "tr": "Yaratıcı ve teknik kullanım",
10729                "uk": "Креативне та технічне використання",
10730                "zh": "创意与技术用途",
10731                "id": "Penggunaan kreatif dan teknis",
10732                "ja": "クリエイティブ・技術用途",
10733                "ko": "창의적 및 기술적 사용",
10734                "ms": "Penggunaan kreatif & teknikal",
10735                "fil": "Malikhain at teknikal na gamit",
10736                "th": "ใช้งานเชิงสร้างสรรค์และเทคนิค",
10737                "vi": "Sử dụng sáng tạo & kỹ thuật"
10738            }
10739            ,
10740            business: {
10741                "CAP": "Business & Professional",
10742                "us": "Business & Professional",
10743                "es": "Uso empresarial y profesional",
10744                "pt": "Uso empresarial e profissional",
10745                "fr": "Usage professionnel et d'affaires",
10746                "nl": "Zakelijk en professioneel gebruik",
10747                "bg": "Бизнес и професионална употреба",
10748                "cs": "Obchodní a profesionální použití",
10749                "hr": "Poslovna i profesionalna upotreba",
10750                "da": "Forretnings- og professionel brug",
10751                "de": "Geschäftliche und professionelle Nutzung",
10752                "et": "Äri- ja professionaalne kasutus",
10753                "el": "Επαγγελματική και επιχειρηματική χρήση",
10754                "he": "שימוש עסקי ומקצועי",
10755                "it": "Uso aziendale e professionale",
10756                "kk": "Іскерлік және кәсіби қолдану",
10757                "lv": "Biznesa un profesionāla lietošana",
10758                "lt": "Versliniam ir profesiniam naudojimui",
10759                "hu": "Üzleti és professzionális használat",
10760                "ar": "استخدام تجاري واحترافي",
10761                "no": "Forretnings- og profesjonell bruk",
10762                "pl": "Użytek biznesowy i profesjonalny",
10763                "ro": "Utilizare profesională și de afaceri",
10764                "sr": "Poslovna i profesionalna upotreba",
10765                "sk": "Obchodné a profesionálne použitie",
10766                "sl": "Poslovna in strokovna uporaba",
10767                "fi": "Liike- ja ammattikäyttö",
10768                "sv": "Affärs- och yrkesanvändning",
10769                "tr": "İş ve profesyonel kullanım",
10770                "uk": "Бізнес та професійне використання",
10771                "zh": "商务与专业用途",
10772                "id": "Penggunaan bisnis dan profesional",
10773                "ja": "ビジネス・プロ用途",
10774                "ko": "업무 및 전문가용",
10775                "ms": "Penggunaan perniagaan & profesional",
10776                "fil": "Paggamit sa negosyo at propesyonal",
10777                "th": "ใช้งานทางธุรกิจและมืออาชีพ",
10778                "vi": "Sử dụng cho kinh doanh & chuyên nghiệp"
10779            }
10780            ,
10781            gaming: {
10782                "CAP": "Gaming",
10783                "us": "Gaming",
10784                "es": "Juegos",
10785                "pt": "Jogos",
10786                "fr": "Jeux vidéo",
10787                "nl": "Gamen",
10788                "bg": "Игри",
10789                "cs": "Hraní her",
10790                "hr": "Igranje",
10791                "da": "Spil",
10792                "de": "Gaming",
10793                "et": "Mängimine",
10794                "el": "Παιχνίδια",
10795                "he": "גיימינג",
10796                "it": "Gaming",
10797                "kk": "Ойын",
10798                "lv": "Spēlēšana",
10799                "lt": "Žaidimai",
10800                "hu": "Játék",
10801                "ar": "ألعاب",
10802                "no": "Spilling",
10803                "pl": "Gry",
10804                "ro": "Gaming",
10805                "sr": "Igranje",
10806                "sk": "Hranie hier",
10807                "sl": "Igranje iger",
10808                "fi": "Pelaaminen",
10809                "sv": "Spel",
10810                "tr": "Oyun",
10811                "uk": "Ігри",
10812                "zh": "游戏",
10813                "id": "Gaming",
10814                "ja": "ゲーム",
10815                "ko": "게임",
10816                "ms": "Permainan",
10817                "fil": "Paglalaro",
10818                "th": "การเล่นเกม",
10819                "vi": "Chơi game"
10820            }
10821        },
10822        footer: {
10823            cta: {
10824                "us": "Submit",
10825                "es": "Enviar",
10826                "pt": "Enviar",
10827                "fr": "Soumettre",
10828                "nl": "Indienen",
10829                "bg": "Изпращане",
10830                "cs": "Odeslat",
10831                "hr": "Pošalji",
10832                "da": "Indsend",
10833                "de": "Einreichen",
10834                "et": "Esita",
10835                "el": "Υποβολή",
10836                "he": "שלח",
10837                "it": "Invia",
10838                "kk": "Жіберу",
10839                "lv": "Iesniegt",
10840                "lt": "Pateikti",
10841                "hu": "Beküldés",
10842                "ar": "إرسال",
10843                "no": "Send inn",
10844                "pl": "Prześlij",
10845                "ro": "Trimite",
10846                "sr": "Pošalji",
10847                "sk": "Odoslať",
10848                "sl": "Pošlji",
10849                "fi": "Lähetä",
10850                "sv": "Skicka in",
10851                "tr": "Gönder",
10852                "uk": "Надіслати",
10853                "zh": "提交",
10854                "id": "Kirim",
10855                "ja": "送信",
10856                "ko": "제출",
10857                "ms": "Hantar",
10858                "fil": "Isumite",
10859                "th": "ส่ง",
10860                "vi": "Gá»­i"
10861            },
10862            currencies: {
10863                "us": '&#36;%price%',
10864                "de": '&#128;%price%',
10865                "ch": 'fr. %price%',
10866                "se": '%price% kr',
10867                "gb": '£%price%',
10868                "au": '$%price%',
10869                "ca": '$%price%',
10870                "cl": '$%price%',
10871                "in": '₹ %price%',
10872                "ar": '$ %price%',
10873                "my": 'RM %price%',
10874                "mx": '$%price%',
10875                "sg": '$%price%',
10876                "pe": 'S/.%price%',
10877                "hk": 'HK$ %price%',
10878                "kr": '₩ %price%',
10879                "za": 'R %price%',
10880                "vn": '%price% ₫',
10881                "tw": '元 %price%',
10882                "tr": '%price% ₺',
10883                "th": '%price% ฿',
10884                "sa": '%price% ï·¼',
10885                "ru": '%price% ₽',
10886                "ro": '%price% RON',
10887                "pl": '%price% zł',
10888                "ph": '₱ %price%',
10889                "nz": '%price%',
10890                "no": 'kr %price%',
10891                "ma": '%price% .د.م.',
10892                "kp": '₩ %price%',
10893                "jp": 'Â¥ %price%',
10894                "il": '₪ %price%',
10895                "id": 'Rp %price%',
10896                "hu": '%price% Ft',
10897                "hr": '€ %price%',
10898                "dk": 'kr. %price%',
10899                "cz": '%price% Kč',
10900                "cn": 'Â¥ %price%',
10901                "br": 'R$ %price%',
10902                "bg": '%price% лв',
10903                "an": '€ %price%'
10904            }
10905        }
10906    },
10907    offerContent: {
10908        header: {
10909            budgetFriendly: {
10910                "us": "Budget friendly",
10911                "es": "Económico",
10912                "pt": "Econômico",
10913                "fr": "Économique",
10914                "nl": "Budgetvriendelijk",
10915                "bg": "Изгоден",
10916                "cs": "Cenově dostupný",
10917                "hr": "Pristupačan",
10918                "da": "Budgetvenlig",
10919                "de": "Preiswert",
10920                "et": "Soodsate hindadega",
10921                "el": "Οικονομικό",
10922                "he": "ידידותי לתקציב",
10923                "it": "Economico",
10924                "kk": "Бюджетке қолайлы",
10925                "lv": "Budžetam draudzīgs",
10926                "lt": "Biudžetui palankus",
10927                "hu": "Költségbarát",
10928                "ar": "صديق للميزانية",
10929                "no": "Budsjettvennlig",
10930                "pl": "Przystępny cenowo",
10931                "ro": "Accesibil",
10932                "sr": "Pristupačan",
10933                "sk": "Cenovo dostupný",
10934                "sl": "Cenovno ugoden",
10935                "fi": "Edullinen",
10936                "sv": "Budgetvänlig",
10937                "tr": "Bütçe dostu",
10938                "uk": "Доступний за ціною",
10939                "zh": "经济实惠",
10940                "id": "Ramah anggaran",
10941                "ja": "予算に優しい",
10942                "ko": "예산 친화적",
10943                "ms": "Mesra bajet",
10944                "fil": "Abot-kayang halaga",
10945                "th": "เป็นมิตรกับงบประมาณ",
10946                "vi": "Phù hợp ngân sách"
10947            },
10948            recommended: {
10949                "us": "Recommended for you",
10950                "es": "Recomendado para ti",
10951                "pt": "Recomendado para você",
10952                "fr": "Recommandé pour vous",
10953                "nl": "Aanbevolen voor jou",
10954                "bg": "Препоръчано за вас",
10955                "cs": "Doporučeno pro vás",
10956                "hr": "Preporučeno za vas",
10957                "da": "Anbefavar til dig",
10958                "de": "Empfohlen für Sie",
10959                "et": "Soovitatav teile",
10960                "el": "Προτείνεται για εσάς",
10961                "he": "מומלץ עבורך",
10962                "it": "Consigliato per te",
10963                "kk": "Сізге ұсынылады",
10964                "lv": "Ieteicams jums",
10965                "lt": "Rekomenduojama jums",
10966                "hu": "Ajánlott önnek",
10967                "ar": "موصى به لك",
10968                "no": "Anbefalt for deg",
10969                "pl": "Polecane dla Ciebie",
10970                "ro": "Recomandat pentru tine",
10971                "sr": "Preporučeno za vas",
10972                "sk": "Odporúčané pre vás",
10973                "sl": "Priporočeno za vas",
10974                "fi": "Suositeltu sinulle",
10975                "sv": "Rekommenderat för dig",
10976                "tr": "Sizin için önerilen",
10977                "uk": "Рекомендовано для вас",
10978                "zh": "为您推荐",
10979                "id": "Direkomendasikan untuk Anda",
10980                "ja": "あなたにおすすめ",
10981                "ko": "당신을 위한 추천",
10982                "ms": "Disyorkan untuk anda",
10983                "fil": "Inirerekomenda para sa iyo",
10984                "th": "แนะนำสำหรับคุณ",
10985                "vi": "Được đề xuất cho bạn"
10986            }
10987            ,
10988            mostPopular: {
10989                "us": "Most popular",
10990                "es": "Más popular",
10991                "pt": "Mais popular",
10992                "fr": "Le plus populaire",
10993                "nl": "Meest populair",
10994                "bg": "Най-популярен",
10995                "cs": "Nejoblíbenější",
10996                "hr": "Najpopularnije",
10997                "da": "Mest populær",
10998                "de": "Am beliebtesten",
10999                "et": "Kõige populaarsem",
11000                "el": "Πιο δημοφιλές",
11001                "he": "הכי פופולרי",
11002                "it": "Più popolare",
11003                "kk": "Ең танымал",
11004                "lv": "Vispopulārākais",
11005                "lt": "Populiariausias",
11006                "hu": "Legnépszerűbb",
11007                "ar": "الأكثر شعبية",
11008                "no": "Mest populær",
11009                "pl": "Najpopularniejsze",
11010                "ro": "Cel mai popular",
11011                "sr": "Најпопуларнији",
11012                "sk": "Najpopulárnejší",
11013                "sl": "Najbolj priljubljeno",
11014                "fi": "Suosituin",
11015                "sv": "Mest populär",
11016                "tr": "En popüler",
11017                "uk": "Найпопулярніший",
11018                "zh": "最受欢迎",
11019                "id": "Paling populer",
11020                "ja": "最も人気のある",
11021                "ko": "가장 인기 있는",
11022                "ms": "Paling popular",
11023                "fil": "Pinakapopular",
11024                "th": "ที่นิยมที่สุด",
11025                "vi": "Phổ biến nhất"
11026            }
11027
11028        },
11029        cta: {
11030            "us": "Shop now",
11031            "es": "Compra ahora",
11032            "pt": "Compre agora",
11033            "fr": "Achetez maintenant",
11034            "nl": "Koop nu",
11035            "bg": "Купи сега",
11036            "cs": "Kup nyní",
11037            "hr": "Kupite sada",
11038            "da": "Køb nu",
11039            "de": "Jetzt kaufen",
11040            "et": "Osta nüüd",
11041            "el": "Αγοράστε τώρα",
11042            "he": "קנה עכשיו",
11043            "it": "Acquista ora",
11044            "kk": "Қазір сатып алыңыз",
11045            "lv": "Pērc tagad",
11046            "lt": "Pirkite dabar",
11047            "hu": "Vásároljon most",
11048            "ar": "اشترِ الآن",
11049            "no": "Kjøp nå",
11050            "pl": "Kup teraz",
11051            "ro": "Cumpără acum",
11052            "sr": "Kupite sada",
11053            "sk": "Kúp teraz",
11054            "sl": "Kupite zdaj",
11055            "fi": "Osta nyt",
11056            "sv": "Köp nu",
11057            "tr": "Hemen satın al",
11058            "uk": "Купити зараз",
11059            "zh": "立即购买",
11060            "id": "Beli sekarang",
11061            "ja": "今すぐ購入",
11062            "ko": "지금 구매",
11063            "ms": "Beli sekarang",
11064            "fil": "Bumili ngayon",
11065            "th": "ซื้อเลย",
11066            "vi": "Mua ngay"
11067        }
11068    }
11069};
11070
11071// --------------- Quiz Code ends Here -----------------
11072initiateMastiffCall();

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.