Er trad een fout op tijdens de verwerking van de sjabloon.
The following has evaluated to null or missing:
==> qstringmap["ecdma-lc"]  [in template "10154#10192#19541382" at line 45, column 15]

----
Tip: It's the final [] step that caused this error, not those before it.
----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign lc = qstringmap["ecdma-lc"]?f...  [in template "10154#10192#19541382" at line 45, column 1]
----
1<#--  
2public product selector version of rewards calc only has google anyltics(ga()) on rewards calculate button. elan version has all ga() calls. 
3--> 
4<#-- ecdma-lc=01133  ecdma-lc=04851(Diffrent card art for consumer and business) ecdma-lc=17329(Business cards only) --> 
5<#assign utilServ = (serviceLocator.findService("com.elan.crc.utilites.service.CRCRemoteServiceService"))! /> 
6 
7 
8<#--<#assign url = request.attributes.CURRENT_URL > --> 
9<#assign url = themeDisplay.getURLCurrent() >  
10 
11<#assign qstringmap = httpUtil.getParameterMap(httpUtil.getQueryString(url))> 
12 
13<#-- What enviroment we are in QA UAT PROD --> 
14<#assign host = request["scheme"] + "://" + themeDisplay.getServerName()> 
15<#-- Enviroment used for dynamic Learn More and No Annual Fee links href="${environment}/11t3/${productURL}?ecdma-lc=${lc}${ecidExt}" --> 
16<#-- Defaults to enviroment for Prod --> 
17<#assign environment = "https://creditcardlearnmore.com"> 
18<#assign oadURL_TC = 'https://online1.elancard.com/oad/terms.controller' > 
19<#if host?contains("uat")> 
20    <#assign oadURL_TC = 'https://uat-online1.elancard.com/oad/terms.controller' > 
21</#if> 
22 
23<#if host?contains("admin.") && !host?contains("uat-admin.")> 
24  <#assign environment = "http://admin.creditcardlearnmore.com"> 
25<#elseif host?contains("admin-lr7crc.uat.")> 
26  <#assign environment = host + "/web/creditcardlearnmore"> 
27<#elseif host?contains("lr7crc.uat.")> 
28  <#assign environment = host + "/web/creditcardlearnmore"> 
29<#elseif host?contains("admin-lr7crc.herodigital")> 
30  <#assign environment = host + "/web/creditcardlearnmore"> 
31<#elseif host?contains("admin-lr7crc.qa")> 
32  <#assign environment = host + "/web/creditcardlearnmore"> 
33</#if> 
34 
35<#-- ecid has something to do with tracking. Used for the Learn More links --> 
36<#if qstringmap["ecid"]?has_content> 
37    <#assign ecidExt="&ecid="+qstringmap["ecid"]?first> 
38    <#assign campaignId = qstringmap["ecid"]?first > 
39<#else> 
40    <#assign ecidExt=""> 
41    <#assign campaignId = "" > 
42</#if> 
43 
44<#-- retrieves location code(lc) from query params and sets prefix --> 
45<#assign lc = qstringmap["ecdma-lc"]?first>  
46<#assign prefix = "00000" > 
47<#assign lcWithPrefix = prefix + lc > 
48<#assign withPrefixLength = lcWithPrefix?length > 
49<#assign startHere = withPrefixLength - 5> 
50<#assign lc = lcWithPrefix?substring(startHere)> 
51 
52<#-- using lc gets partner name, pbu, and subbu --> 
53<#assign clientProfileService = serviceLocator.findService('com.elan.crc.user.service.CrcClientProfileLocalService') > 
54<#assign clientProfileList = clientProfileService.findByLocationCode(lc)> 
55<#if clientProfileList?first?has_content> 
56  <#assign clientProfile = clientProfileList?first> 
57  <#assign partnerName = clientProfile.getMarketingNameLong()> 
58  <#assign pbu = clientProfile.getPbu()> 
59  <#assign subbu = clientProfile.getSUBBRANDBUNBR()> 
60  <#-- logoFileName path --> 
61  <#assign logoFileName = clientProfile.getLogoBFormat1()?replace(".", "-")?replace("-([^-]*)$", ".$1", "r")?lower_case> 
62 
63  <#-- gets cards for finical institution(fi) --> 
64  <#assign fiCardsData = (utilServ.makeCall('crcTier3GetPbuData','0&'+ pbu +'&'+subbu))!>  
65</#if> 
66 
67 
68<#assign cdnCardArtUrl = (propsUtil.get('rackspace.cdn.cardart.url'))!> 
69<#-- Prod cdnLogoUrl--> 
70<#assign cdnLogoUrl = (propsUtil.get('rackspace.cdn.web.url'))!> 
71<#assign panoUrl = getterUtil.getString(propsUtil.get('pano.url'), 'https://www.mycardapply.com')> 
72 
73 <#assign crcRewardsCalculatorLocalService = serviceLocator.findService('com.elan.crc.quicklink.service.CrcRewardsCalculatorLocalService') > 
74 <#assign rewardsList = 
75    crcRewardsCalculatorLocalService.getCrcRewardsCalculators(-1,-1)> 
76     
77 
78<#-- BUILD REWARDS LOOKUP MAP (offerType → reward) --> 
79 
80<#assign rewardsByOfferType = {}> 
81 
82<#if rewardsList?has_content> 
83  <#list rewardsList as reward> 
84    <#assign rewardsByOfferType = 
85      rewardsByOfferType + { 
86        reward.getOfferType()?string : reward 
87
88
89  </#list> 
90</#if> 
91 
92<#-- WEB CONTENT LOOKUP (offerType → child fields) --> 
93<#-- Parent: Numberh6rv (offerType) --> 
94 
95<#assign wcByOfferType = {}> 
96 
97<#if Numberh6rv.getSiblings()?has_content> 
98  <#list Numberh6rv.getSiblings() as wcItem> 
99 
100    <#assign offerTypeKey = wcItem.getData()?string /> 
101 
102    <#assign textTitle = "" /> 
103    <#if wcItem.Text13zu?? && wcItem.Text13zu.getData()?has_content> 
104      <#assign textTitle = wcItem.Text13zu.getData() /> 
105    </#if> 
106 
107    <#assign childTextHtml = "" /> 
108     <#if wcItem.HTMLbl7t?? && wcItem.HTMLbl7t.getData()?has_content> 
109      <#assign childTextHtml = wcItem.HTMLbl7t.getData() /> 
110    </#if> 
111     
112    <#assign childText = "" /> 
113     <#if wcItem.annualFeeText?? && wcItem.annualFeeText.getData()?has_content> 
114      <#assign childText = wcItem.annualFeeText.getData() /> 
115    </#if> 
116     
117    <#assign wcByOfferType = wcByOfferType + {  
118      offerTypeKey : {  
119        "text" : textTitle,  
120        "textHtml" : childTextHtml,  
121        "childText" : childText 
122      }  
123    }> 
124 
125 
126  </#list> 
127</#if> 
128 
129<#-- COMBINED LIST --> 
130 
131<#assign combinedList = []> 
132<#if fiCardsData?has_content> 
133  <#list fiCardsData as fib> 
134    <#assign offerKey = fib.offerType?string /> 
135     <#assign offerId = fib.offerId?string /> 
136    <#assign reward = rewardsByOfferType[offerKey]! /> 
137    <#assign wcData = wcByOfferType[offerKey]! /> 
138    <#-- Include only when reward exists --> 
139    <#if reward?has_content> 
140      <#assign combinedList = combinedList + [{ 
141        "offerType" : offerKey, 
142        "offerId"   : offerId, 
143        "card"      : fib, 
144        "reward"    : reward, 
145        "wc"        : wcData    
146      }]> 
147    </#if> 
148 
149  </#list> 
150</#if> 
151 
152<#-- STEP 3: OPTIONAL SORT (BY CARD ORDER) --> 
153<#--  
154<#if combinedList?has_content> 
155  <#assign combinedList = combinedList?sort_by("card.cardOrder")> 
156</#if> 
157--> 
158 
159<div class="container re_header"> 
160    <!-- Logo Section --> 
161    <div class="row mybenifit_header"> 
162        <div class="header-bar"> 
163         <div class="header-left"> 
164            <#if (backArrow.getData())?? && backArrow.getData() != ""> 
165                	<img class="d-none" alt="${backArrow.getAttribute("alt")}" data-fileentryid="${backArrow.getAttribute("fileEntryId")}" src="${backArrow.getData()}" /> 
166            </#if> 
167            <img 
168                class="re_cdn_logo" src="${cdnLogoUrl!''}/${logoFileName!''}" 
169                alt="elan-logo" loading="eager"/>   
170         </div> 
171         
172          <!-- Right section --> 
173         <div class="header-right d-none card_reset_btn" id="resettext"onclick="setCardType('ALL', this)"> 
174                <#if (resetIcon.getData())?? && resetIcon.getData() != ""> 
175                	<img alt="${resetIcon.getAttribute("alt")}" data-fileentryid="${resetIcon.getAttribute("fileEntryId")}" src="${resetIcon.getData()}" /> 
176                </#if> 
177            <div class="reset-text">Reset</div> 
178         </div> 
179        </div>  
180        
181            <h1 class="re_cdn_titl" id="title1"> 
182            <#if (title.getData())??> 
183            	${title.getData()} 
184            </#if> 
185            </h1> 
186            <p class="re_cdn_sub_titl" id="des1"> 
187            <#if (description.getData())??> 
188            	${description.getData()} 
189            </#if></p>  
190            <h1 class="re_cdn_titl" id="title2"> 
191            <#if (consumerCardTitle.getData())??> 
192            	${consumerCardTitle.getData()} 
193            </#if></h1> 
194            <p class="re_cdn_sub_titl" id="des2"> 
195            <#if (consumerCardDes.getData())??> 
196            	${consumerCardDes.getData()} 
197            </#if></p>  
198            <h1 class="re_cdn_titl" id="title3"> 
199            <#if (consumerCategoryTitle.getData())??> 
200            	${consumerCategoryTitle.getData()} 
201            </#if></h1> 
202            <p class="re_cdn_sub_titl" id="des3"> 
203            <#if (consumerEveryDayDes.getData())??> 
204            	${consumerEveryDayDes.getData()} 
205            </#if></p>  
206            <p class="re_cdn_sub_titl" id="des4"> 
207            <#if (consumerTravelDes.getData())??> 
208            	${consumerTravelDes.getData()} 
209            </#if></p>  
210    </div> 
211        <!-- Cards Section --> 
212     
213        <div class="row re_card_sec mt-4" id="reCardSec"> 
214     
215    	  <div class="re_card" id="re_card_cosumer" onclick="setCardType('CONSUMER', this)"> 
216    		<img class="re_card_icon" src="${consumerCardImage.getData()}" /> 
217    		<h2 class="re_card_title">Consumer Credit Cards</h2> 
218    	  </div> 
219     
220    	  <div class="re_card" id="re_card_consumer_business" onclick="setCardType('BUSINESS', this)"> 
221    		<img class="re_card_icon" src="${businessCardImage.getData()}" /> 
222    		<h2 class="re_card_title">Business Credit Cards</h2> 
223    	  </div> 
224          <div class="plus-symbol d-none" id="plussymbol"> 
225
226          </div> 
227    	  <div class="re_card d-none" id="re_card_everyday" onclick="setCardType('EVERYDAY', this)"> 
228    		<#if (consumerEveryDayImg.getData())?? && consumerEveryDayImg.getData() != ""> 
229      	    <img class="re_card_icon" alt="${consumerEveryDayImg.getAttribute("alt")}" data-fileentryid="${consumerEveryDayImg.getAttribute("fileEntryId")}" src="${consumerEveryDayImg.getData()}" /> 
230            </#if> 
231    		<h2 class="re_card_title">Everyday Spend</h2> 
232    	  </div> 
233    	   
234    	  <div class="re_card d-none" id="re_card_travel" onclick="setCardType('TRAVEL', this)"> 
235    		<#if (consumerTravelImg.getData())?? && consumerTravelImg.getData() != ""> 
236    	    <img class="re_card_icon" alt="${consumerTravelImg.getAttribute("alt")}" data-fileentryid="${consumerTravelImg.getAttribute("fileEntryId")}" src="${consumerTravelImg.getData()}" /> 
237            </#if> 
238    		<h2 class="re_card_title">Travel</h2> 
239    	  </div> 
240    	  
241        </div> 
242	 
243 
244</div> 
245 
246<div class="car_sec"> 
247    <div class="section-header"> 
248      <div class="section-title" id="cardCount"> 
249         All Cards (${combinedList?has_content?then(combinedList?size, 0)} Cards) 
250      </div> 
251    </div> 
252     
253    <section class="carousel-section" role="region" aria-label="Cards carousel"> 
254 
255      <!-- ADD rcarousel-inner class --> 
256      <div class="card-list rcarousel-inner" id="carouselInner"></div> 
257    </section> 
258</div> 
259 
260<div class="frame_sec d-none" id="framesec"> 
261    <div class="section-aerrow"> 
262        <div class="carousel-indicator"> 
263            <button class="indicator-arrow" id="iframePrev" 
264                    onclick="changeIframe(-1)" aria-label="Previous calculator"> 
265              &#8592; 
266            </button> 
267             
268            <div class="indicator-count" id="indicatorCount"></div> 
269             
270            <button class="indicator-arrow" id="iframeNext" 
271                    onclick="changeIframe(1)" aria-label="Next calculator"> 
272              &#8594; 
273            </button> 
274 
275        </div> 
276 
277    </div> 
278     
279    <div class="iframe-wrapper d-none" id="iframeWrapper"></div> 
280 
281 
282    
283    <div class="section-footer"> 
284      <div class="section-footer-title" id="section-footer-title" onclick="scrollToTop()"> 
285        ↑ Back to top  
286      </div> 
287    </div> 
288</div> 
289 
290<style> 
291.indicator-arrow:disabled { 
292  opacity: 0.4; 
293  cursor: not-allowed; 
294  pointer-events: none; 
295
296 
297.indicator-count { 
298  min-width: 60px; 
299  text-align: center; 
300  font-family: Arial, sans-serif; 
301  font-size: 14px; 
302  font-weight: 700; 
303  color: #ffffff; /* arrow bar is black */ 
304
305.iframe-wrapper { 
306  width: 100%; 
307  height: 100%; 
308  padding: 0 8px; 
309  background: #ffffff; 
310 
311  display: inline-flex; 
312  justify-content: center; 
313  align-items: center; 
314  gap: 8px; 
315  box-sizing: border-box; 
316
317 
318.iframe-content { 
319  flex: 1 1 0; 
320  width: 100%; 
321  max-width: 736px; 
322  height: 558.9px; 
323 
324  border: 0; 
325
326 
327/* ===== HEADER WRAPPER ===== */ 
328.mybenifit_header{ 
329    width: 700px; 
330    margin: auto; 
331
332 
333.header-bar { 
334  display: flex; 
335  flex-direction: row;           
336  justify-content: space-between; 
337  align-items: center; 
338  max-width: 700px; 
339  width: 100%; 
340  height: auto;                  
341  min-height: 40px; 
342  position: relative; 
343
344 
345/* ===== LEFT SECTION ===== */ 
346.header-left { 
347  width: 300px; 
348  display: flex; 
349  align-items: center; 
350  gap: 16px; 
351
352/* ===== RIGHT SECTION ===== */ 
353.header-right { 
354  display: flex; 
355  align-items: center; 
356  justify-content: center; 
357  gap: 8px; 
358
359 
360 
361/* Reset text */ 
362.card_reset_btn{ 
363  cursor: pointer; 
364
365.reset-text { 
366  color: var(--Core-Black, #000000); 
367  font-family: Arial, sans-serif; 
368  font-size: 14px; 
369  font-weight: 700; 
370  text-align: center; 
371
372 
373.re_header { 
374  max-width: 752px; 
375  width: 100%; 
376  background: #E6E6E6; 
377  padding: 24px; 
378  box-sizing: border-box; 
379
380.re_car_sec{ 
381  height: 62px; 
382  background: #000000; 
383  border-top: 1px solid #D7D7D7; 
384  box-sizing: border-box; 
385
386 
387.re_cdn_logo { 
388  width: 162px; 
389  height: 62px; 
390
391/*.re_cdn_logo.consumer-logo { 
392  width: 104px; 
393  height: 40px; 
394}*/ 
395.reset-link { 
396  margin-left: auto;   /* pushes to right corner */ 
397  cursor: pointer; 
398  font-weight: 700; 
399  margin-right:50px; 
400
401 
402.re_cdn_titl{ 
403  font: 400 34px/52px Arial, sans-serif; 
404  color: #000; 
405
406 
407.re_cdn_sub_titl { 
408  max-width: 702px; 
409  width: 100%; 
410  font-family: Arial, sans-serif; 
411  font-weight: 400; 
412  font-size: 14px; 
413  line-height: 22px; 
414  letter-spacing: 0; 
415  color: #000000; 
416
417 
418 
419.re_card_sec{ 
420  display: flex; 
421  justify-content: center; 
422  align-items: center; 
423  gap: 16px; 
424  height: 100px; 
425
426 
427.re_card { 
428  box-sizing: border-box; 
429  display: flex; 
430  flex-direction: column; 
431  align-items: center; 
432  width: 100%; 
433  max-width: 200px; 
434  height: 100px; 
435  padding: 12px; 
436  background: #FFFFFF; 
437  border: 1px solid #969798; 
438  cursor: pointer; 
439
440 
441.plus-symbol { 
442    color: var(--Core-Elan-Dark-Blue, #084BB7); 
443    text-align: center; 
444    font-family: Arial, sans-serif; 
445    font-size: 20px; 
446    font-weight: 700; 
447    line-height: normal; 
448
449 
450.re_card.active { 
451  background: var(--Core-Elan-Dark-Blue, #084BB7); 
452 
453
454.re_card.active .re_card_title { 
455  color: #ffffff; /* or whatever color you want */ 
456
457.re_card_sec.consumer-active { 
458  gap: 8px; 
459
460.re_card.active .re_card_icon { 
461  filter: brightness(0) invert(1); 
462
463 
464.re_card_icon{ 
465  width: 32px; 
466  height: 32px; 
467  position: relative; 
468  top: 2.08px; 
469
470.re_card_title{ 
471  width: 85px; 
472  height: 32px; 
473  font-family: Arial, sans-serif; 
474  font-weight: 700; 
475  font-size: 14px !important; 
476  line-height: 1 !important; 
477  text-align: center; 
478  color: #084BB7; 
479
480 
481</style> 
482 
483<style> 
484.car_sec{ 
485  max-width: 754px; 
486  width: 100%; 
487 /* min-height: 705px; */ 
488  box-sizing: border-box; 
489
490.section-header { 
491  box-sizing: border-box; 
492  width: 100%; 
493  max-width: 754px; 
494  height: 62px; 
495  background: #000000; 
496  border: 1px solid #D7D7D7; 
497  display: flex; 
498  align-items: center; 
499  padding: 0 16px; 
500  justify-content: center; 
501
502 
503.section-title { 
504  font-family: Arial, sans-serif; 
505  font-weight: 700; 
506  font-size: 18px; 
507  line-height: 22px; 
508  color: #FFFFFF; 
509
510.section-footer{ 
511  box-sizing: border-box; 
512  width: 100%; 
513  max-width: 754px; 
514  height: 62px; 
515  background: var(--Core-Dark-Gray, #969798); 
516  border: 1px solid #D7D7D7; 
517  display: flex; 
518  align-items: center; 
519  padding: 0 16px; 
520
521.carousel-section { 
522  position: relative; 
523  overflow: hidden; 
524  max-width: 750px; 
525  width: 100%; 
526 /* min-height: 643px; */ 
527  display: flex; 
528  flex-direction: column; 
529  gap: 16px; 
530  padding: 24px 0; 
531  background: var(--Core-White, #FFFFFF); 
532  box-sizing: border-box; 
533
534 
535.card-list { 
536  display: flex !important; 
537  flex-wrap: wrap !important; 
538  justify-content: center; 
539  gap: 16px; 
540  transform: none !important; 
541  transition: none !important; 
542
543 
544/*.rcard { 
545  flex: 0 0 calc(33.333% - 16px); 
546  max-width: calc(33.333% - 16px); 
547  display: flex; 
548  justify-content: center; 
549}*/ 
550 
551 
552.cal-card { 
553  max-width: 210px; 
554  width: 100%; 
555  border: 1px solid #FFFFFF; 
556  box-sizing: border-box; 
557  position: relative; 
558  font-family: Arial, sans-serif; 
559
560 
561/* ===== IMAGE ===== */ 
562.cal-card-image { 
563  width: 100%; 
564  display: flex; 
565  justify-content: center; 
566  position: absolute; 
567  z-index: 2; 
568
569 
570.cal-card-image img { 
571  width: 171.875px; 
572  height: 110px; 
573  object-fit: contain; 
574
575 
576 
577/* ===== BODY ===== */ 
578 
579.cal-card-body { 
580  margin-top: 101px; 
581  width: 100%; 
582  background: #CECACA; 
583  border-radius: 12px; 
584  box-sizing: border-box; 
585  padding: 16px; 
586  color:#00000; 
587
588 
589 
590/* ===== TITLE ===== */ 
591.cal-card-title { 
592  height: 44px; 
593  font-family: Arial, sans-serif; 
594  font-weight: 700; 
595  font-size: 18px; 
596  line-height: 21.6px; 
597  letter-spacing: 0; 
598  text-align: center; 
599  display: flex; 
600  align-items: center; 
601  justify-content: center; 
602
603 
604 
605/* ===== DIVIDER ===== */ 
606 
607.cal-divider, .cal-card-divider { 
608  width: 162px; 
609  margin: 16px auto; 
610  border-bottom: 1px solid #000000; 
611
612 
613/* ===== DETAILS ===== */ 
614  .cal-card-details { 
615  width: 162px; 
616  height: 75px; 
617  display: flex; 
618  flex-direction: column; 
619  gap: 12px; 
620
621 
622/* Frame */ 
623.cal-card-detail-row { 
624  width: 100%; 
625  min-height: 44px; 
626  display: flex; 
627  gap: 8px; 
628  box-sizing: border-box; 
629
630 
631.multiplier { 
632  min-width: 21px; 
633  font-family: Arial, sans-serif; 
634  font-weight: 700; 
635  font-size: 14px; 
636  line-height: 22px; 
637  white-space: nowrap; 
638
639.description { 
640  font-family: Arial, sans-serif; 
641  font-weight: 400; 
642  font-size: 14px; 
643  line-height: 22px; 
644  text-align: center; 
645
646 
647/* ===== FEE ===== */ 
648.cal-fee { 
649  font-family: Arial, sans-serif; 
650  font-weight: 400; 
651  font-size: 14px; 
652  line-height: 22px; 
653  text-decoration: underline; 
654  text-align: center; 
655  color : #000 !important; 
656
657 
658 
659/* ===== ACTIONS ===== */ 
660.cal-actions { 
661  display: flex; 
662  justify-content: center; 
663  margin-top: auto; 
664
665 
666/* ===== BUTTON ===== */ 
667.cal-btn-primary { 
668  color:var(--Core-Elan-Dark-Blue, #084BB7) !important; 
669  width: 150px; 
670  height: 44px; 
671  color: #000; 
672  cursor: pointer; 
673  display: flex; 
674  align-items: center; 
675  justify-content: center; 
676  border: 2px solid var(--Core-Elan-Dark-Blue, #084BB7) !important; 
677  background: var(--Core-White, #FFF) !important; 
678
679 
680.cal-btn-text { 
681    text-shadow: none !important; 
682    font-family: Arial, sans-serif; 
683    font-size: 14px; 
684    font-style: normal; 
685    font-weight: 700; 
686    line-height: 22.5px; 
687    text-transform: capitalize; 
688
689.frame_sec{ 
690  max-width: 754px; 
691  width: 100%; 
692  box-sizing: border-box; 
693
694 
695.frame-section-header { 
696  box-sizing: border-box; 
697  width: 100%; 
698  max-width: 754px; 
699  height: 62px; 
700  background: #000000; 
701  border: 1px solid #D7D7D7; 
702  display: flex; 
703  align-items: center; 
704  justify-content: center; 
705
706 
707.frame-title { 
708  font-family: Arial, sans-serif; 
709  font-weight: 700; 
710  font-size: 18px; 
711  line-height: 22px; 
712  color: #FFFFFF; 
713
714.section-footer-title { 
715    color: var(--Core-Black, #000000); 
716    text-align: center; 
717    font-family: Arial, sans-serif; 
718    font-size: 18px; 
719    font-style: normal; 
720    font-weight: 700; 
721    line-height: 22px; 
722    max-width: 737.203px; 
723    flex-shrink: 0; 
724	margin: auto; 
725    cursor: pointer; 
726
727 
728/* Arrows */ 
729.section-aerrow { 
730  box-sizing: border-box; 
731  width: 100%; 
732  max-width: 754px; 
733  height: 62px; 
734  background: #000000; 
735  border: 1px solid #D7D7D7; 
736  display: flex; 
737  padding: 0 16px; 
738  align-items: center; 
739  justify-content: center; 
740
741.carousel-arrow { 
742  position: absolute; 
743  top: 50%; 
744  transform: translateY(-50%); 
745  background: #ffffff; 
746  border: 1px solid #ccc; 
747  width: 36px; 
748  height: 36px; 
749  border-radius: 50%; 
750  cursor: pointer; 
751  font-size: 22px; 
752  line-height: 34px; 
753  text-align: center; 
754  z-index: 5; 
755
756 
757.carousel-arrow.left { 
758  left: 10px; 
759
760 
761.carousel-arrow.right { 
762  right: 10px; 
763
764 
765.carousel-arrow:hover { 
766  background: #084BB7; 
767  color: #fff; 
768
769.carousel-indicator { 
770  display: flex; 
771  align-items: center; 
772  gap: 14px; 
773
774 
775.indicator-arrow { 
776  border: none; 
777  font-size: 22px; 
778  cursor: pointer; 
779  background: #000 !important; 
780  color: #fff; 
781
782 
783.indicator-arrow:hover { 
784  color: #084BB7; 
785  color: #fff; 
786
787 
788.indicator-dots { 
789  display: flex; 
790  gap: 8px; 
791
792 
793.indicator-dot { 
794  width: 10px; 
795  height: 10px; 
796  border-radius: 50%; 
797  background: #d0d0d0; 
798  cursor: pointer; 
799
800 
801.indicator-dot.active { 
802  background: #084BB7; 
803
804 
805.rcard.is-focused { 
806  outline: none; 
807  box-shadow: none; 
808  border: none; 
809
810 
811.rcard.is-focused .cal-card-body { 
812  color:#fff; 
813  background:var(--Core-Elan-Dark-Blue, #084BB7) 
814
815.rcard.is-focused .cal-fee { 
816  color:#fff !important; 
817
818.rcard.is-focused .cal-divider, .rcard.is-focused .cal-card-divider { 
819 border-bottom: 1px solid var(--Core-Elan-Dark-Blue, #fff) 
820
821 
822 
823/* This Style is for  */ 
824 
825.re_header, 
826.car_sec, 
827.section-header, 
828.carousel-section, 
829.frame_sec, 
830.section-aerrow, 
831.section-footer { 
832  max-width: 100% !important; 
833  width: 100% !important; 
834
835 
836.header-bar { 
837  max-width: 100% !important; 
838
839 
840.container { 
841  max-width: 100% !important; 
842
843 
844 
845 
846 
847 
848</style> 
849 
850<script> 
851const cardsData = [ 
852  <#if combinedList?has_content> 
853    <#list combinedList as item> 
854
855      offerType: "${item.offerType}", 
856      offerId: "${item.offerId}", 
857      title: "${item.reward.getCardName()?js_string!''}", 
858      groupName: 
859        "${item.reward.getGroupName()?upper_case?contains('BUSINESS')?then('BUSINESS','CONSUMER')}", 
860      category: 
861        "${item.reward.getCategory()?upper_case?contains('EVERYDAY')?then('EVERYDAY','TRAVEL')}", 
862      imageUrl: "${cdnCardArtUrl}/${item.card.filename}.png", 
863      wcTextHtml: "${item.wc?has_content?then(item.wc.textHtml?js_string,'')}", 
864     wcChildText: "${item.wc?has_content?then(item.wc.childText?js_string,'')}" 
865    }<#if item_has_next>,</#if> 
866    </#list> 
867  </#if> 
868]; 
869 
870 
871/* ========================================================= 
872   INIT 
873========================================================= */ 
874 
875document.addEventListener('DOMContentLoaded', () => { 
876  applyInitialCardMixUI(); 
877  renderCarousel(); 
878  autoSelectFirstCard();    
879  updateIframeCounter(); 
880  isInitialLoad = false; 
881}); 
882 
883 
884function setCardType(type, el) { 
885 
886  if ( 
887    (type === 'CONSUMER' || type === 'BUSINESS') && 
888    el.classList.contains('disabled') 
889  ) { 
890    return; 
891
892 
893    if (type === 'ALL') { 
894      resetUIToDefault(); 
895      return; 
896
897 
898  // Consumer / Business 
899  if (type === 'CONSUMER' || type === 'BUSINESS') { 
900    activeCardType = type; 
901    activeCategory = 'ALL'; 
902
903 
904  // Category only under Consumer 
905  if ( 
906    (type === 'EVERYDAY' || type === 'TRAVEL') && 
907    activeCardType === 'CONSUMER' 
908  ) { 
909    activeCategory = type; 
910
911 
912    // Active UI 
913    // Remove active only when switching main types 
914    if (type === 'CONSUMER' || type === 'BUSINESS') { 
915      document.querySelectorAll('.re_card') 
916        .forEach(card => card.classList.remove('active')); 
917
918     
919    // Always activate clicked card 
920    el.classList.add('active'); 
921     
922    // Keep CONSUMER active when selecting sub-categories 
923    if (type === 'EVERYDAY' || type === 'TRAVEL') { 
924      const consumerCard = document.getElementById('re_card_cosumer'); 
925      if (consumerCard) { 
926        consumerCard.classList.add('active'); 
927
928
929 
930 
931  // Disable logic 
932  if (type === 'CONSUMER') { 
933    handleConsumerSubCard(); 
934    el.classList.add('disabled');  
935
936 
937  if (type === 'BUSINESS') { 
938    document.getElementById('re_card_everyday')?.classList.remove('active'); 
939    document.getElementById('re_card_travel')?.classList.remove('active'); 
940    el.classList.add('disabled'); 
941
942 
943  if (type === 'EVERYDAY') handleEveryDayCard(); 
944  if (type === 'TRAVEL') handleTravelCard(); 
945   
946  currentIframeIndex = 0; 
947  currentPage = 0; 
948  renderCarousel(); 
949  autoSelectFirstCard();  
950  updateIframeCounter(); 
951   
952
953 
954 
955function handleConsumerSubCard() { 
956  $("#re_card_consumer_business").hide(); 
957  $("#re_card_everyday,#re_card_travel,#plussymbol").removeClass("d-none"); 
958 
959  $("#title2,#des2").removeClass("d-none"); 
960  $("#title1,#des1").addClass("d-none"); 
961  const cardContainer = document.querySelector('.re_card_sec'); 
962  cardContainer?.classList.add('consumer-active'); 
963   $("#resettext").removeClass("d-none"); 
964  document.querySelector('.re_cdn_logo')?.classList.add('consumer-logo'); 
965 
966
967function handleEveryDayCard() { 
968  document.getElementById('re_card_travel')?.classList.remove('active'); 
969  $("#resettext").removeClass("d-none"); 
970  $("#title3,#des3").removeClass("d-none"); 
971  $("#title2,#des2,#des4").addClass("d-none"); 
972
973function handleTravelCard() { 
974  document.getElementById('re_card_everyday')?.classList.remove('active'); 
975  $("#resettext").removeClass("d-none"); 
976  $("#title3,#des4").removeClass("d-none"); 
977  $("#title2,#des2,#des3").addClass("d-none"); 
978
979 
980 
981function applyInitialCardMixUI() { 
982 
983  const groupSet = new Set(cardsData.map(card => card.groupName)); 
984  $("#reCardSec").removeClass("d-none"); 
985  // First hide everything (safe – already hidden, no flicker) 
986  $("#title1,#title2,#title3,#des1,#des2,#des3,#des4,#framesec,#resettext") 
987    .addClass("d-none"); 
988 
989  // BOTH Consumer + Business 
990  if (groupSet.size > 1) { 
991    $("#title1,#des1").removeClass("d-none"); 
992
993 
994  // ONLY Consumer 
995  else if (groupSet.has('CONSUMER')) { 
996    activeCardType = 'CONSUMER'; 
997    activeCategory = 'ALL'; 
998    $("#title2,#des2").removeClass("d-none"); 
999	$("#re_card_everyday,#re_card_travel").removeClass("d-none"); 
1000    $("#re_card_cosumer,#re_card_consumer_business").addClass("d-none"); 
1001
1002 
1003  // ONLY Business 
1004  else if (groupSet.has('BUSINESS')) { 
1005    $("#title1,#des1").removeClass("d-none"); 
1006    $("#reCardSec").addClass("d-none"); 
1007
1008
1009 
1010 
1011 
1012function resetUIToDefault() { 
1013 
1014  //  Reset filter logic 
1015  activeCardType = 'ALL'; 
1016  activeCategory = 'ALL'; 
1017 
1018  //  Reset card buttons 
1019  document.querySelectorAll('.re_card').forEach(card => { 
1020    card.classList.remove('active'); 
1021    card.classList.remove('disabled'); 
1022  }); 
1023 
1024  //  Restore card button visibility 
1025  $("#re_card_consumer_business").show(); 
1026  $("#re_card_everyday,#re_card_travel,#plussymbol").addClass("d-none"); 
1027  document.querySelector('.re_card_sec')?.classList.remove('consumer-active'); 
1028  document.querySelector('.re_cdn_logo')?.classList.remove('consumer-logo'); 
1029   
1030  document.querySelectorAll('.rcard') 
1031  .forEach(card => card.classList.remove('is-focused')); 
1032 
1033   
1034  currentIframeIndex = 0; 
1035  //  Apply data-based hiding (ONLY what is needed) 
1036  applyInitialCardMixUI(); 
1037 
1038  //  Reset carousel state 
1039  currentPage = 0; 
1040  
1041 
1042  // Re-render 
1043  renderCarousel(); 
1044  autoSelectFirstCard();  
1045
1046 
1047 
1048 
1049/* ========================================================= 
1050   GLOBAL STATE 
1051========================================================= */ 
1052const PAGE_SIZE = 3; 
1053let activeCardType = 'ALL'; 
1054let activeCategory = 'ALL'; 
1055let currentPage = 0; 
1056let isInitialLoad = true; 
1057let currentIframeIndex = 0; 
1058let allowAutoScroll = true; 
1059const panoUrl = "${panoUrl}"; 
1060 
1061 
1062 
1063 
1064 
1065 
1066 
1067 
1068 
1069/* ========================================================= 
1070   FILTER + COUNT 
1071========================================================= */ 
1072 
1073function updateCardCount(count, type) { 
1074  const el = document.getElementById('cardCount'); 
1075  if (!el) return; 
1076 
1077  let label = 'All Cards'; 
1078  if (type === 'CONSUMER') label = 'Consumer Cards'; 
1079  if (type === 'BUSINESS') label = 'Business Cards'; 
1080 
1081  // reeMarker-safe 
1082  el.textContent = `${r"${label}"} (${r"${count}"} Cards)`; 
1083
1084 
1085 
1086 
1087function getFilteredCards() { 
1088  return cardsData.filter(card => { 
1089 
1090    // Filter by Consumer / Business 
1091    if (activeCardType !== 'ALL' && card.groupName !== activeCardType) { 
1092      return false; 
1093
1094 
1095    // Category filter ONLY when Consumer is selected 
1096    if (activeCardType === 'CONSUMER' && activeCategory !== 'ALL') { 
1097      return card.category === activeCategory; 
1098
1099 
1100    // Business ignores category 
1101    return true; 
1102  }); 
1103
1104 
1105 
1106/* ========================================================= 
1107   CAROUSEL RENDER 
1108========================================================= */ 
1109function renderCarousel() { 
1110  const container = document.getElementById('carouselInner'); 
1111  if (!container) return; 
1112 
1113  const filteredCards = getFilteredCards(); 
1114 
1115 
1116   
1117  if (!filteredCards.length) { 
1118  container.innerHTML = '<p style="padding:20px">No cards available</p>'; 
1119  updateCardCount(0, activeCardType); 
1120  return; 
1121
1122 
1123 
1124  updateCardCount(filteredCards.length, activeCardType); 
1125 
1126    const start = currentPage * PAGE_SIZE; 
1127    const end = start + PAGE_SIZE; 
1128    const pageCards = filteredCards.slice(start, end); 
1129     
1130    container.innerHTML = pageCards.map(card => ` 
1131        <div class="rcard" 
1132             tabindex="0" 
1133             data-offer-type="${r"${card.offerType}"}" 
1134             onclick="showCalculator( 
1135               panoUrl + '/calculators/${r"${card.offerType}"}', 
1136               '${r"${card.title}"}' 
1137             )"> 
1138         
1139          <div class="cal-card"> 
1140            <div class="cal-card-image"> 
1141              <img src="${r"${card.imageUrl}"}" alt="Card Image"> 
1142            </div> 
1143         
1144            <div class="cal-card-body"> 
1145              <h3 class="cal-card-title">${r"${card.title}"}</h3> 
1146              <div class="cal-divider"></div> 
1147         
1148              <div class="cal-card-details"> 
1149                <a class="cal-fee" 
1150                   href="${oadURL_TC}?step=display&amp;offerId=${r"${card.offerId}"}&amp;locationCode=${lc}" 
1151                   target="_blank" 
1152                   onclick="event.stopPropagation();"> 
1153                   ${r"${card.wcChildText}"} 
1154                </a> 
1155              </div> 
1156            </div> 
1157          </div> 
1158        </div> 
1159    `).join(''); 
1160     
1161  
1162
1163 
1164/* ========================================================= 
1165   FILTER BUTTON HANDLER 
1166========================================================= */ 
1167 
1168 
1169 
1170 
1171/* ========================================================= 
1172   CAROUSEL CORE 
1173========================================================= */ 
1174function getCards() { 
1175  return document.querySelectorAll('.rcard'); 
1176
1177 
1178 
1179 
1180  
1181function showCalculator(url, title) { 
1182  console.log("[CAL URL]",url); 
1183  const filteredCards = getFilteredCards(); 
1184 
1185  const index = filteredCards.findIndex( 
1186    card => url.includes(card.offerType) 
1187  ); 
1188 
1189  if (index !== -1) { 
1190    currentIframeIndex = index; 
1191    highlightCard(filteredCards[index].offerType); 
1192
1193 
1194  const wrapper = document.getElementById('iframeWrapper'); 
1195  const titleEl = document.getElementById('frametitle'); 
1196 
1197  if (titleEl) { 
1198    titleEl.textContent = title + ' Rewards Calculator'; 
1199
1200 
1201  wrapper.innerHTML = ''; 
1202 
1203  const iframe = document.createElement('iframe'); 
1204  iframe.src = url; 
1205  iframe.className = 'iframe-content'; 
1206  iframe.loading = 'lazy'; 
1207 
1208  wrapper.appendChild(iframe); 
1209 
1210  $("#framesec,#iframeWrapper").removeClass("d-none"); 
1211 
1212  // scroll only when allowed 
1213  if (allowAutoScroll) { 
1214    wrapper.scrollIntoView({ behavior: 'smooth' }); 
1215
1216 
1217  updateIframeCounter(); 
1218
1219 
1220 
1221function scrollToTop() { 
1222  $('html, body').animate({ scrollTop: 0 }, 'slow'); 
1223
1224 
1225 
1226function changeIframe(direction) { 
1227  const filteredCards = getFilteredCards(); 
1228  const total = filteredCards.length; 
1229  if (!total) return; 
1230 
1231  const nextIndex = currentIframeIndex + direction; 
1232 
1233  // stop at bounds 
1234  if (nextIndex < 0 || nextIndex >= total) return; 
1235 
1236  currentIframeIndex = nextIndex; 
1237 
1238  // derive page from index 
1239  const requiredPage = Math.floor(currentIframeIndex / PAGE_SIZE); 
1240 
1241  // switch page ONLY if needed 
1242  if (requiredPage !== currentPage) { 
1243    currentPage = requiredPage; 
1244 
1245    // prevent auto-select + scroll during re-render 
1246    allowAutoScroll = false; 
1247    renderCarousel(); 
1248    allowAutoScroll = true; 
1249
1250 
1251  const card = filteredCards[currentIframeIndex]; 
1252 
1253  // highlight selected card 
1254  highlightCard(card.offerType); 
1255 
1256  // load iframe (user action → scroll allowed) 
1257  const url = panoUrl+'/calculators/' + card.offerType; 
1258 
1259  showCalculator(url, card.title); 
1260 
1261  updateIframeCounter(); 
1262
1263 
1264 
1265 
1266 
1267 
1268function updateIframeCounter() { 
1269  const counterEl = document.getElementById('indicatorCount'); 
1270  const prevBtn = document.getElementById('iframePrev'); 
1271  const nextBtn = document.getElementById('iframeNext'); 
1272 
1273  if (!counterEl || !prevBtn || !nextBtn) return; 
1274 
1275  const filteredCards = getFilteredCards(); 
1276  const total = filteredCards.length; 
1277 
1278  if (!total) { 
1279    counterEl.textContent = ''; 
1280    prevBtn.disabled = true; 
1281    nextBtn.disabled = true; 
1282    return; 
1283
1284 
1285  // ARD-BASED COUNT (this is what you want) 
1286  counterEl.textContent = 
1287    (currentIframeIndex + 1) + ' of ' + total; 
1288 
1289  // isable arrows at first / last card 
1290  prevBtn.disabled = currentIframeIndex === 0; 
1291  nextBtn.disabled = currentIframeIndex === total - 1; 
1292
1293 
1294 
1295 
1296function highlightCard(offerType) { 
1297  document.querySelectorAll('.rcard').forEach(card => { 
1298    if (card.dataset.offerType === offerType) { 
1299      card.classList.add('is-focused'); 
1300    } else { 
1301      card.classList.remove('is-focused'); 
1302
1303  }); 
1304
1305 
1306function autoSelectFirstCard() { 
1307  const filteredCards = getFilteredCards(); 
1308  if (!filteredCards.length) return; 
1309 
1310  const firstCard = filteredCards[0]; 
1311 
1312  currentIframeIndex = 0; 
1313 
1314  // disable scroll for auto select 
1315  allowAutoScroll = false; 
1316 
1317  highlightCard(firstCard.offerType); 
1318 
1319  const url = panoUrl+'/calculators/' + firstCard.offerType; 
1320 
1321  showCalculator(url, firstCard.title); 
1322 
1323  // re-enable scroll for user actions 
1324  allowAutoScroll = true; 
1325
1326 
1327</script>