    <!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="theme-color" content="#c9a961">
<title>Pusat Dana Kaget &amp; Bagi Rezeki Online | Promo &amp; Cashback | KlikDana</title>

<link rel="icon" id="pageFavicon" href="https://media-splash.com/assets/img/favicon-lp-klikdanacom-1777365177.png">
<link rel="shortcut icon" href="https://media-splash.com/assets/img/favicon-lp-klikdanacom-1777365177.png">

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-WN33KL9Q');</script>
<!-- End Google Tag Manager -->

<style>
*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{height:100%}
body{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  background:#0f0f0f;
  color:#fff;
  min-height:100vh;
  overflow-x:hidden;
}
.app{max-width:480px;margin:0 auto;min-height:100vh;background:#141414;position:relative}

/* ---------- BRAND BAR (logo center, juga dipakai di detail page) ---------- */
.brand-bar{
  background:#fff;
  padding:14px 18px;
  display:flex;
  align-items:center;
  justify-content:center;
  border-bottom:1px solid #f1f1f1;
  position:relative;
  min-height:62px;
}
.brand-logo{
  max-height:34px;
  max-width:180px;
  width:auto;
  height:auto;
  display:block;
  object-fit:contain;
}

/* ---------- HERO (title + sub_title — gradient gold/coklat sesuai theme) ---------- */
.hero{
  background:linear-gradient(135deg,#c9a961 0%,#e6c77e 50%,#a88842 100%);
  background-size:cover;
  background-position:center;
  background-repeat:no-repeat;
  padding:28px 22px 26px;
  text-align:center;
  color:#1a1a1a;
  position:relative;
  overflow:hidden;
  box-shadow:0 4px 20px rgba(0,0,0,.4);
}
.hero.has-bg-image{
  color:#fff;
}
.hero.has-bg-image::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.25) 0%,rgba(0,0,0,.55) 100%);
  pointer-events:none;
  z-index:0;
}
.hero::before{
  content:"";
  position:absolute;
  inset:0;
  background:repeating-linear-gradient(135deg,transparent 0,transparent 22px,rgba(255,255,255,.08) 22px,rgba(255,255,255,.08) 44px);
  pointer-events:none;
}
.hero.has-bg-image::before{
  display:none;
}
.hero.has-bg-image .hero-title{
  text-shadow:0 2px 8px rgba(0,0,0,.6);
}
.hero.has-bg-image .hero-sub{
  color:rgba(255,255,255,.92);
  text-shadow:0 1px 4px rgba(0,0,0,.5);
}
.hero-title{
  font-size:20px;
  font-weight:900;
  line-height:1.25;
  letter-spacing:.3px;
  margin:0 0 10px;
  text-shadow:0 2px 0 rgba(255,255,255,.25);
  position:relative;
  z-index:1;
}
.hero-sub{
  font-size:13px;
  font-weight:600;
  line-height:1.5;
  color:rgba(0,0,0,.72);
  margin:0 auto;
  max-width:380px;
  position:relative;
  z-index:1;
}

/* ---------- HEADER (detail page) ---------- */
.header{
  background:linear-gradient(135deg,#c9a961 0%,#e6c77e 50%,#a88842 100%);
  padding:24px 54px 22px;
  text-align:center;
  position:relative;
  box-shadow:0 4px 20px rgba(0,0,0,.4);
}
.header h1{
  font-size:20px;
  font-weight:900;
  letter-spacing:.5px;
  color:#1a1a1a;
  text-shadow:0 2px 0 rgba(255,255,255,.25);
  line-height:1.2;
}
.back-btn{
  position:absolute;
  left:12px;
  top:50%;
  transform:translateY(-50%);
  width:38px;
  height:38px;
  border-radius:50%;
  background:#1a1a1a;
  border:none;
  color:#fff;
  font-size:20px;
  display:none;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  line-height:1;
  box-shadow:0 2px 6px rgba(0,0,0,.15);
  z-index:2;
}
.back-btn:active{background:#000}

/* ---------- INTRO ---------- */
.intro{padding:20px 18px 4px}
.intro-card{
  background:linear-gradient(135deg,#1e1e1e 0%,#262626 100%);
  border:1px solid #2e2e2e;
  border-radius:12px;
  padding:16px;
  position:relative;
  overflow:hidden;
}
.intro-card::before{
  content:"";
  position:absolute;
  top:-30px;right:-30px;
  width:100px;height:100px;
  background:radial-gradient(circle,rgba(201,169,97,.25) 0%,transparent 70%);
}
.intro-title{
  font-size:14px;
  font-weight:900;
  color:#c9a961;
  letter-spacing:1px;
  margin-bottom:6px;
  position:relative;
}
.intro-text{
  font-size:12.5px;
  line-height:1.55;
  color:#ccc;
  position:relative;
}
.intro-text b{color:#e6c77e;font-weight:800}

/* ---------- HERO SLIDER (Voucher Card Style) ---------- */
.hero-slider-wrap{
  margin:14px 16px 4px;
  user-select:none;
  -webkit-user-select:none;
}
.hero-slider{
  position:relative;
  border-radius:12px;
  overflow:hidden;
  box-shadow:0 4px 14px rgba(0,0,0,.25),0 0 0 1px rgba(255,255,255,.05);
  background:#fff;
}
.hero-slider-track{
  display:flex;
  transition:transform .45s cubic-bezier(.25,.8,.45,1);
  will-change:transform;
}
.hero-slide{
  flex:0 0 100%;
  min-width:100%;
  position:relative;
  display:flex;
  align-items:stretch;
  min-height:140px;
  background:#fff;
}
.hero-slide-img-wrap{
  flex:0 0 38%;
  max-width:38%;
  position:relative;
  background:#fff;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:14px 12px;
  border-right:1px dashed #e5e5e5;
}
.hero-slide-img-wrap img{
  display:block;
  max-width:100%;
  max-height:100%;
  width:auto;
  height:auto;
  object-fit:contain;
}
.hero-slide-body{
  flex:1;
  padding:12px 14px;
  display:flex;
  flex-direction:column;
  background:#fff;
  min-width:0;
  position:relative;
}
.hero-slide-tags{
  display:flex;
  align-items:center;
  justify-content:flex-end;
  margin-bottom:6px;
  gap:8px;
}
.hero-slide-tag-kode{
  font-size:11px;
  font-weight:800;
  color:#e63946;
  letter-spacing:.4px;
  white-space:nowrap;
}
.hero-slide-brand{
  font-size:11px;
  color:#888;
  font-weight:500;
  text-align:right;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.hero-slide-title{
  font-size:18px;
  font-weight:900;
  color:#1a1a1a;
  letter-spacing:.2px;
  line-height:1.2;
  margin-bottom:5px;
  display:-webkit-box;
  -webkit-line-clamp:1;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
.hero-slide-desc{
  font-size:12px;
  color:#555;
  line-height:1.4;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
}
.hero-slide-expiry{
  font-size:10.5px;
  color:#999;
  margin-top:auto;
  padding-top:8px;
  border-top:1px dashed #eee;
}
.hero-slide-expiry b{color:#666;font-weight:600}

/* Style varian: banner (image top + label, like Teknologi card) */
.hero-slide--banner{
  flex-direction:column;
  padding:0;
  min-height:auto;
}
.hero-slide-banner-img{
  position:relative;
  line-height:0;
  background:#f5f5f5;
  width:100%;
}
.hero-slide-banner-img img{
  display:block;
  width:100%;
  height:auto;
  aspect-ratio:16/9;
  object-fit:cover;
}
.hero-slide-banner-label{
  position:absolute;
  top:0;
  left:0;
  right:0;
  padding:10px 16px;
  background:rgba(60,60,60,.78);
  backdrop-filter:blur(4px);
  color:#fff;
  font-weight:700;
  font-size:13px;
  letter-spacing:.5px;
  text-transform:uppercase;
  text-align:left;
}
.hero-slide-banner-foot{
  position:relative;
  display:flex;
  align-items:center;
  justify-content:space-around;
  gap:10px;
  padding:18px 18px;
  background:#fff;
  flex-wrap:wrap;
  min-height:64px;
}
.hero-slide-banner-foot::before{
  content:"";
  position:absolute;
  top:0;left:16px;right:16px;
  height:1px;
  background:linear-gradient(90deg,transparent 0%,#e5e5e5 50%,transparent 100%);
}
.hero-slide-banner-foot img{
  display:block;
  max-height:30px;
  max-width:95px;
  object-fit:contain;
  filter:grayscale(10%);
  opacity:.95;
  transition:filter .2s,opacity .2s;
}
.hero-slide-banner-foot img:hover{
  filter:grayscale(0);
  opacity:1;
}
.hero-slide-banner-foot-desc{
  flex:1;
  font-size:13px;
  color:#444;
  line-height:1.5;
  text-align:center;
  font-weight:500;
  display:-webkit-box;
  -webkit-line-clamp:2;
  -webkit-box-orient:vertical;
  overflow:hidden;
  letter-spacing:.2px;
}

.hero-dots{
  display:flex;
  justify-content:center;
  gap:6px;
  margin-top:10px;
}
.hero-dot{
  width:6px;height:6px;
  border-radius:50%;
  background:rgba(255,255,255,.25);
  transition:all .25s ease;
  cursor:pointer;
  border:none;
  padding:0;
}
.hero-dot.active{
  width:20px;
  border-radius:3px;
  background:#c9a961;
  box-shadow:0 0 8px rgba(201,169,97,.5);
}
.hero-empty{display:none}
.hero-slider-wrap + .hero-slider-wrap{margin-top:14px}
#heroSliderContainerBottom{
  margin-top:18px;
  padding-bottom:8px;
  position:relative;
}
#heroSliderContainerBottom:empty{display:none}
#heroSliderContainerBottom::after{
  content:"";
  position:absolute;
  top:0;right:0;bottom:8px;
  width:36px;
  background:linear-gradient(to right,transparent 0%,#141414 80%);
  pointer-events:none;
  z-index:2;
  opacity:0;
  transition:opacity .25s ease;
}
#heroSliderContainerBottom.has-overflow::after{opacity:1}
.hero-cat-label{
  font-size:11px;
  font-weight:800;
  color:#c9a961;
  letter-spacing:1.2px;
  text-transform:uppercase;
  padding:0 4px 8px;
}

/* ---------- COUPON SHORTCUTS (bottom container) ---------- */
.pill-list{
  display:flex;
  flex-wrap:nowrap;
  gap:14px;
  padding:14px 16px 18px;
  overflow-x:auto;
  overflow-y:hidden;
  -webkit-overflow-scrolling:touch;
  scroll-behavior:smooth;
  scroll-snap-type:x proximity;
  scrollbar-width:none;
  user-select:none;
  -webkit-user-select:none;
  cursor:grab;
}
.pill-list.is-dragging{cursor:grabbing}
.pill-list::-webkit-scrollbar{display:none}
.pill{
  flex:0 0 auto;
  scroll-snap-align:start;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:6px;
  padding:10px 22px;
  min-width:140px;
  border-radius:999px;
  font-size:13px;
  font-weight:700;
  letter-spacing:.4px;
  text-transform:uppercase;
  font-family:inherit;
  border:1.5px solid rgba(201,169,97,.3);
  background:linear-gradient(135deg,#1f1f1f 0%,#2a2a2a 100%);
  color:#e6c77e;
  cursor:pointer;
  white-space:nowrap;
  transition:all .25s cubic-bezier(.25,.8,.45,1);
}
.pill:active{transform:scale(.96)}
.pill:hover{
  transform:translateY(-2px);
  border-color:rgba(201,169,97,.7);
  background:linear-gradient(135deg,#2a2418 0%,#3a3020 100%);
  color:#ffd86b;
  box-shadow:0 6px 16px rgba(201,169,97,.18);
}
.pill--disabled{
  opacity:.4;
  cursor:not-allowed;
  filter:grayscale(50%);
}
.pill--disabled:hover{
  transform:none;
  border-color:rgba(201,169,97,.15);
  background:linear-gradient(135deg,#1f1f1f 0%,#2a2a2a 100%);
  color:#888;
  box-shadow:none;
}
.pill-count{
  background:rgba(201,169,97,.18);
  color:#ffd86b;
  font-size:10px;
  padding:2px 8px;
  border-radius:999px;
  font-weight:800;
  min-width:20px;
  text-align:center;
  line-height:1.4;
}

/* ---------- COUPON BOTTOM SHEET ---------- */
.coupon-sheet{
  position:fixed;
  inset:0;
  z-index:9999;
  display:none;
  pointer-events:none;
}
.coupon-sheet.is-open{
  display:block;
  pointer-events:auto;
}
.coupon-sheet-overlay{
  position:absolute;
  inset:0;
  background:rgba(0,0,0,.65);
  backdrop-filter:blur(2px);
  opacity:0;
  transition:opacity .3s ease;
}
.coupon-sheet.is-open .coupon-sheet-overlay{opacity:1}
.coupon-sheet-content{
  position:absolute;
  left:0;right:0;bottom:0;
  max-width:480px;
  margin:0 auto;
  background:linear-gradient(180deg,#1a1a1a 0%,#141414 100%);
  border-radius:20px 20px 0 0;
  padding:18px 18px 24px;
  transform:translateY(100%);
  transition:transform .35s cubic-bezier(.25,.8,.45,1);
  max-height:75vh;
  overflow-y:auto;
  box-shadow:0 -8px 30px rgba(0,0,0,.5);
}
.coupon-sheet.is-open .coupon-sheet-content{transform:translateY(0)}
.coupon-sheet-handle{
  width:42px;
  height:4px;
  background:rgba(255,255,255,.18);
  border-radius:999px;
  margin:0 auto 14px;
}
.coupon-sheet-header{
  display:flex;
  align-items:center;
  justify-content:space-between;
  padding-bottom:14px;
  border-bottom:1px solid rgba(201,169,97,.15);
  margin-bottom:14px;
}
.coupon-sheet-title{
  font-size:14px;
  font-weight:800;
  color:#ffd86b;
  text-transform:uppercase;
  letter-spacing:.6px;
}
.coupon-sheet-close{
  background:rgba(255,255,255,.06);
  border:none;
  color:#cfcfcf;
  font-size:18px;
  line-height:1;
  cursor:pointer;
  width:28px;
  height:28px;
  border-radius:50%;
  display:flex;
  align-items:center;
  justify-content:center;
  transition:all .2s ease;
}
.coupon-sheet-close:hover{background:rgba(255,255,255,.12);color:#fff}
.coupon-sheet-list{
  display:flex;
  flex-direction:column;
  gap:8px;
}
.coupon-sheet-item{
  display:flex;
  align-items:center;
  gap:12px;
  padding:10px 12px;
  background:linear-gradient(135deg,#1f1f1f 0%,#2a2a2a 100%);
  border:1.5px solid rgba(201,169,97,.2);
  border-radius:12px;
  color:#e8e8e8;
  font-size:13.5px;
  font-weight:600;
  cursor:pointer;
  text-align:left;
  width:100%;
  font-family:inherit;
  transition:all .2s ease;
}
.coupon-sheet-item:hover{
  border-color:rgba(201,169,97,.6);
  background:linear-gradient(135deg,#2a2418 0%,#3a3020 100%);
  transform:translateX(2px);
}
.coupon-sheet-item:active{transform:scale(.98)}
.coupon-sheet-thumb{
  width:48px;
  height:48px;
  border-radius:8px;
  background:#0f0f0f;
  flex-shrink:0;
  overflow:hidden;
  display:flex;
  align-items:center;
  justify-content:center;
}
.coupon-sheet-thumb img{
  width:100%;
  height:100%;
  object-fit:cover;
}
.coupon-sheet-thumb-fallback{
  font-size:18px;
  font-weight:900;
  color:#c9a961;
}
.coupon-sheet-item-name{
  flex:1;
  min-width:0;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.coupon-sheet-item-arrow{
  color:#c9a961;
  font-size:14px;
  flex-shrink:0;
}
.coupon-sheet-item--inactive{
  opacity:.45;
  filter:grayscale(60%);
  cursor:not-allowed;
}
.coupon-sheet-item--inactive:hover{
  border-color:rgba(201,169,97,.2);
  background:linear-gradient(135deg,#1f1f1f 0%,#2a2a2a 100%);
  transform:none;
}
.coupon-sheet-item--inactive .coupon-sheet-item-arrow{
  display:none;
}
.coupon-sheet-item-badge{
  font-size:10px;
  font-weight:800;
  letter-spacing:.5px;
  padding:3px 8px;
  border-radius:999px;
  background:rgba(255,255,255,.08);
  color:#888;
  text-transform:uppercase;
  flex-shrink:0;
}
.coupon-sheet-empty{
  text-align:center;
  padding:24px 12px;
  color:#888;
  font-size:13px;
}

/* ---------- COUPON LIST ---------- */
.coupons{padding:16px 16px 8px;display:flex;flex-direction:column;gap:14px}

.coupon{
  position:relative;
  border-radius:14px;
  overflow:hidden;
  box-shadow:0 6px 20px rgba(0,0,0,.4);
  cursor:pointer;
  line-height:0;
  isolation:isolate;
}
.coupon img{
  display:block;
  width:100%;
  height:auto;
}
.coupon.pressable:active{animation:bounce .38s cubic-bezier(.25,.8,.45,1)}
@keyframes bounce{
  0%{transform:scale(1)}
  35%{transform:scale(.93)}
  65%{transform:scale(1.025)}
  100%{transform:scale(1)}
}
.coupon.disabled{cursor:not-allowed}
.coupon.disabled .overlay-dim{
  position:absolute;
  inset:0;
  background:rgba(0,0,0,.58);
  border-radius:14px;
  z-index:2;
  pointer-events:none;
}

/* ---------- PAGE TRANSITIONS ---------- */
.page{display:none}
.page.active{display:block;animation:fade .25s ease}
@keyframes fade{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ---------- DETAIL PAGE ---------- */
.detail-wrap{padding:26px 22px 10px;text-align:center}
.selamat{
  font-size:36px;
  font-weight:900;
  letter-spacing:2px;
  background:linear-gradient(135deg,#ffd86b 0%,#c9a961 50%,#ffecb0 100%);
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  text-shadow:0 2px 10px rgba(201,169,97,.35);
  margin-bottom:4px;
}
.detail-desc{
  font-size:14px;
  color:#ddd;
  letter-spacing:1.5px;
  font-weight:600;
  margin-bottom:20px;
}

.barcode-card{
  background:#fff;
  border-radius:18px;
  padding:18px;
  margin:0 auto 16px;
  max-width:260px;
  box-shadow:0 10px 30px rgba(201,169,97,.25),0 0 0 4px rgba(201,169,97,.2);
  display:flex;
  align-items:center;
  justify-content:center;
}
.qr-img{
  width:100%;
  max-width:220px;
  height:auto;
  display:block;
}

.quota-info{
  display:inline-flex;
  align-items:center;
  gap:8px;
  background:#1e1e1e;
  border:1px solid #2e2e2e;
  padding:8px 14px;
  border-radius:30px;
  font-size:12px;
  color:#ccc;
  font-weight:600;
  margin-bottom:16px;
  letter-spacing:.5px;
}
.quota-info .dot{width:8px;height:8px;border-radius:50%;background:#25c253;box-shadow:0 0 6px #25c253}
.quota-info.low .dot{background:#f7a623;box-shadow:0 0 6px #f7a623}
.quota-info.empty .dot{background:#e63946;box-shadow:0 0 6px #e63946}
.quota-info.empty{border-color:#7a1f27;background:#2a1215;color:#ffd0d4}
.quota-info b{color:#fff;font-weight:800}
.quota-info.empty b{color:#ff5864}

.claim-btn{
  display:block;
  width:100%;
  max-width:320px;
  margin:0 auto 22px;
  background:linear-gradient(135deg,#c9a961 0%,#e6c77e 50%,#a88842 100%);
  color:#1a1a1a;
  border:none;
  padding:16px;
  font-size:17px;
  font-weight:900;
  letter-spacing:2px;
  border-radius:50px;
  cursor:pointer;
  box-shadow:0 8px 22px rgba(201,169,97,.4);
  transition:transform .1s ease;
}
.claim-btn:active{transform:scale(.97)}
.claim-btn.inactive{
  background:linear-gradient(135deg,#3a3a3a 0%,#555 100%);
  color:#aaa;
  cursor:not-allowed;
  box-shadow:none;
  letter-spacing:1.5px;
}
.claim-btn.inactive:active{transform:none}

.claim-again{
  font-size:12px;
  letter-spacing:2px;
  color:#aaa;
  margin-bottom:10px;
  font-weight:600;
}
.countdown{display:flex;justify-content:center;gap:10px}
.cd-box{
  background:#1e1e1e;
  border:1px solid #2e2e2e;
  border-radius:10px;
  padding:12px 10px 8px;
  min-width:64px;
  text-align:center;
  transition:all .2s ease;
}
.cd-num{font-size:24px;font-weight:900;color:#c9a961;letter-spacing:1px}
.cd-label{font-size:10px;color:#888;letter-spacing:1.5px;margin-top:2px;text-transform:uppercase}
.countdown.red .cd-box{border-color:#7a1f27;background:#2a1215}
.countdown.red .cd-num{color:#ff5864}

/* ---------- FOOTER ---------- */
.footer{
  padding:22px 22px 28px;
  border-top:1px solid #222;
  margin-top:22px;
  background:#0f0f0f;
}
.footer-title{
  font-size:13px;
  font-weight:900;
  color:#c9a961;
  letter-spacing:1.5px;
  margin-bottom:10px;
}
.footer ul{list-style:none;padding:0}
.footer li{
  font-size:12px;
  line-height:1.55;
  color:#bbb;
  padding:5px 0 5px 18px;
  position:relative;
}
.footer li::before{
  content:"•";
  position:absolute;
  left:4px;top:4px;
  color:#c9a961;
  font-weight:900;
  font-size:16px;
  line-height:1;
}

/* ---------- RESPONSIVE ---------- */
@media (max-width:360px){
  .coupon-title-big{font-size:21px}
  .coupon-subtitle{font-size:12.5px}
  .coupon-cta{font-size:12.5px;padding:8px 10px;letter-spacing:1px}
  .brand-logo-box{width:62px;height:62px}
  .coupon-desc{font-size:9px}
  .header h1{font-size:17px}
  .selamat{font-size:30px}
  .hero-title{font-size:17px}
  .hero-sub{font-size:11.5px}
  .brand-logo{max-height:30px}
}
</style>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WN33KL9Q"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

<div class="app">

  
  <!-- ================= LIST PAGE ================= -->
  <section id="page-list" class="page active">
    <div class="brand-bar" id="brandBar" style="">
      <img class="brand-logo" id="brandLogo" src="https://media-splash.com/assets/img/logo-lp-klikdanacom-1777361999.png" alt="Logo" onerror="document.getElementById('brandBar').style.display='none'">
    </div>

    <div class="hero has-bg-image"
          style="background-image:url('https://media-splash.com/assets/img/bg-lp-klikdanacom-1777972243.jpg');" >
      <h1 class="hero-title" id="heroTitle">Pusat Dana Kaget &amp; Bagi Rezeki Online | Promo &amp; Cashback | KlikDana</h1>
      <p class="hero-sub" id="heroSub">Mau promo + dana cuma-cuma? 😎
KlikDana punya semuanya
voucher, diskon, bonus, cashback &amp; cuan gratis. Tinggal klik, gas! 🚀</p>
    </div>

    <div id="heroSliderContainer" aria-label="Promo Slider"></div>

    <div class="coupons" id="coupons"></div>

    <div id="heroSliderContainerBottom" aria-label="Promo Slider Bottom"></div>
  </section>

  <!-- ================= DETAIL PAGE ================= -->
  <section id="page-detail" class="page">
    <div class="brand-bar">
      <button class="back-btn" id="backBtn" aria-label="Back">&#8592;</button>
            <img class="brand-logo" id="brandLogoDetail" src="https://media-splash.com/assets/img/logo-lp-klikdanacom-1777361999.png" alt="Logo" onerror="this.style.display='none'">
          </div>

    <div class="detail-wrap">
      <div class="selamat" id="selamatText"></div>
      <div class="detail-desc" id="detailDesc"></div>

      <div class="barcode-card">
        <img class="qr-img" id="qrImg" src="https://media-splash.com/assets/img/barcode-dana.jpg" alt="QR Code" onerror="this.style.display='none'">
      </div>

      <div class="quota-info" id="quotaInfo">
        <span class="dot"></span>
        <span id="quotaText">Tersedia untuk 100 orang tercepat hari ini</span>
      </div>

      <button class="claim-btn" id="claimBtn">KLAIM</button>

      <div class="claim-again">KLAIM LAGI DALAM:</div>
      <div class="countdown" id="countdown">
        <div class="cd-box"><div class="cd-num" id="cdH">00</div><div class="cd-label">JAM</div></div>
        <div class="cd-box"><div class="cd-num" id="cdM">00</div><div class="cd-label">MENIT</div></div>
        <div class="cd-box"><div class="cd-num" id="cdS">00</div><div class="cd-label">DETIK</div></div>
      </div>
    </div>

    <footer class="footer">
      <div class="footer-title">KETENTUAN</div>
      <ul id="snkList">
        <li>Pengguna wajib memiliki akun DANA yang aktif.</li>
        <li>Klaim hanya dapat dilakukan maksimal 1 (satu) kali dalam periode 24 jam.</li>
        <li>Setiap klaim akan melalui proses verifikasi sebelum saldo dikirimkan.</li>
      </ul>
    </footer>
  </section>

</div>

<script>
/* ======================= CONFIG ======================= */
/* Kuota di-load dari /api/quota (file quota.json di server).
 * Default awal ada di server (index.blade.php: $quotaDefaults). */
let QUOTA = { total: 100, remaining: 100 };

async function fetchQuota(){
  try{
    const r = await fetch("/api/quota", {cache:"no-store"});
    if(r.ok){ QUOTA = await r.json(); }
  }catch(e){}
  return QUOTA;
}
async function claimQuota(){
  try{
    const r = await fetch("/api/quota/claim", {method:"POST", cache:"no-store"});
    if(r.ok){ QUOTA = await r.json(); }
  }catch(e){}
  return QUOTA;
}

/* ======================= DATA (dari API /api/coupon/list) ======================= */
const RAW_COUPONS          = [{"start_date":"2026-04-24 14:16:00","end_date":"2026-06-01 14:16:00","open_time":"07:59:00","close_time":"23:59:00","is_active":1,"position":1,"url_target":"https:\/\/tinyurl.com\/klikdana1","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-dana-1777965295.jpg","logo_url":null,"header":"SELAMAT!!","sub_header":"Klaim dana kaget untuk 100 orang tercepat!","custom_text":"Tinggal Dikit, Claim Sekarang Ya!","cta_text":"KLAIM DISINI","snk_text":"1. Wajib punya akun DANA yang masih aktif ya.\r\n2. Klaim cuma bisa 1x dalam 24 jam.\r\n3. Kuota tiap hari terbatas, jadi siapa cepat dia dapat.\r\n4. Nominal yang didapat bisa beda-beda tiap hari.\r\n\r\n\ud83d\udd25 Tes hokimu sekarang!","notes":null,"hostname":"klikdana.com","name":"DANA","slug":"dana","title":"Pusat Dana Kaget \u0026 Bagi Rezeki Online","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-dana-kaget-1777021851.png","brand_slug":"vegas88","category":"E Wallet","category_slug":"e-wallet"},{"start_date":"2026-05-05 12:48:00","end_date":"2026-09-05 12:48:00","open_time":null,"close_time":null,"is_active":1,"position":2,"url_target":"https:\/\/tinyurl.com\/klikgopay1","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-gopay-1777965312.jpg","logo_url":null,"header":"SELAMAT!!","sub_header":"Kesempatan dapetin GoPay hinggga jutaan rupiah!","custom_text":"Buruan sebelum kehabisan, kuotanya terbatas!","cta_text":"AMBIL SEKARANG","snk_text":"Wajib punya akun GoPay yang masih aktif.\r\nKlaim hanya bisa 1x dalam 24 jam.\r\nKuota harian terbatas \u2014 siapa cepat dia dapat!\r\nNominal saldo yang diterima bisa berbeda setiap hari.\r\n\r\n\ud83d\udd25 Uji keberuntunganmu sekarang juga!","notes":null,"hostname":null,"name":"GOPAY","slug":"gopay","title":"Gopay Bagi Bagi","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-gopay-1777959714.png","brand_slug":"vegas88","category":"E Wallet","category_slug":"e-wallet"},{"start_date":"2026-04-24 14:17:00","end_date":"2026-06-01 14:17:00","open_time":null,"close_time":null,"is_active":1,"position":2,"url_target":"https:\/\/shopee.co.id\/m\/new-user-gift","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-shopee-1777271307.webp","logo_url":null,"header":"SELAMAT!!","sub_header":"VOUCHER SPESIAL UNTUKMU","custom_text":"Tanpa Minimum Belanja","cta_text":"PAKAI SEKARANG","snk_text":"HADIAH SPESIAL SHOPEE UNTUK PENGGUNA BARU\r\nMasa Berlaku: 21 Hari","notes":null,"hostname":"klikdana.com","name":"SHOPEE","slug":"shopee","title":"GRATIS ONGKIR SHOPEE","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-gratis-ongkir-1777021832.png","brand_slug":"vegas88","category":"Shop","category_slug":"shop"},{"start_date":"2026-04-27 09:22:00","end_date":"2026-06-27 09:22:00","open_time":null,"close_time":null,"is_active":1,"position":3,"url_target":"https:\/\/www.codashop.com\/","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-codashop-1777256597.png","logo_url":null,"header":"SELAMAT!!","sub_header":"Potongan hingga 90% untuk top up Free Fire","custom_text":"Tidak perlu kode!","cta_text":"KUNJUNGI DISINI","snk_text":"Buat pemain Free Fire, lagi ada promo di Codashop diskon sampai 90% hari ini. Cocok buat top up diamond murah\u2014buruan sebelum habis!","notes":null,"hostname":"klikdana.com","name":"CODASHOP","slug":"codashop","title":"DISCOUNT 90%","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-codashop-1777256482.png","brand_slug":"vegas88","category":"Game","category_slug":"game"},{"start_date":"2026-04-27 14:20:00","end_date":"2026-06-30 14:20:00","open_time":null,"close_time":null,"is_active":1,"position":4,"url_target":"https:\/\/www.lapakgaming.com\/id-id\/coins-rewards","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-lapakgaming-1777274427.png","logo_url":null,"header":"TUKARKAN SEGERA!!","sub_header":"Lapakgaming Coins Rewards","custom_text":"kesempatan untuk memenangkan hadiah seru!","cta_text":"TUKAR DISINI","snk_text":"Setiap beli 1 produk di Lapakgaming, kamu dapat 1 tiket undian. Makin banyak beli, makin besar peluang menang\u2014diundi tiap hari \u0026 diumumin Senin\u2013Jumat.","notes":null,"hostname":"klikdana.com","name":"LAPAKGAMING","slug":"lapakgaming","title":"Lapakgaming Coins Rewards","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-lapakgaming-1777274267.png","brand_slug":"vegas88","category":"Game","category_slug":"game"},{"start_date":"2026-05-01 14:18:00","end_date":"2026-05-03 14:21:00","open_time":null,"close_time":null,"is_active":0,"position":5,"url_target":"https:\/\/www.gojek.com\/en-id","url_qr":"https:\/\/media-splash.com\/assets\/img\/qr-goweekend-1777527726.png","logo_url":null,"header":"PROMO WEEKEND","sub_header":"WARA-WIRI WEEKEND PASTI TENANG PAKAI KODE GOWEEKEND","custom_text":"Perjalanan naik GoCar dan GoRide jadi lebih hemat dengan kode promo: GOWEEKEND","cta_text":"KLAIM DISINI","snk_text":"1x voucher diskon Rp12.000 untuk layanan GoCar berlaku untuk semua metode pembayaran\r\n3x voucher diskon Rp6.000 untuk layanan GoCar berlaku untuk semua metode pembayaran\r\n2x voucher diskon Rp5.000 untuk layanan GoRide berlaku untuk semua metode pembayaran","notes":null,"hostname":"klikdana.com","name":"GOWEEKEND","slug":"goweekend","title":"GOWEEKEND","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-goweekend-1777021838.png","brand_slug":"vegas88","category":"Travel","category_slug":"travel"},{"start_date":"2026-04-24 14:14:00","end_date":"2026-04-25 18:17:00","open_time":null,"close_time":null,"is_active":0,"position":6,"url_target":null,"url_qr":null,"logo_url":null,"header":null,"sub_header":null,"custom_text":null,"cta_text":null,"snk_text":null,"notes":null,"hostname":"klikdana.com","name":"CASHBACK","slug":"cashback","title":"CASHBACK TRAVELOKA","description":null,"image":"https:\/\/media-splash.com\/assets\/img\/coupon-cashback-1777021858.png","brand_slug":"vegas88","category":"Travel","category_slug":"travel"}];
const RAW_SLIDERS          = [{"hostname":"klikdana.com","start_date":null,"end_date":null,"custom_text":"Siapa Cepat Dia Dapat!","open_time":null,"close_time":null,"is_active":1,"notes":null,"name":"GOPAY","slug":"gopay","title":"Lagi Ada Hadiah GoPay Nih!","description":"Saldo hingga jutaan rupiah siap diklaim.","image":"https:\/\/media-splash.com\/assets\/img\/slider-gopay-1777964420.webp","view_name":"Lagi Ada Hadiah GoPay Nih!","brand_slug":"vegas88","category":null,"category_slug":null},{"hostname":"klikdana.com","start_date":null,"end_date":null,"custom_text":"Claim Sekarang Juga ~!","open_time":null,"close_time":null,"is_active":1,"notes":null,"name":"DANA","slug":"dana","title":"Rezeki lagi lewat!","description":"Ada bonus spesial dari DANA hingga Rp1.000.000","image":"https:\/\/media-splash.com\/assets\/img\/slider-dana-1777964330.webp","view_name":"Rezeki lagi lewat!","brand_slug":"vegas88","category":null,"category_slug":null}];
const RAW_COUPON_CATEGORIES = [{"name":"E Wallet","slug":"e-wallet","coupons":[{"name":"DANA","slug":"dana","image":"https:\/\/media-splash.com\/assets\/img\/coupon-dana-kaget-1777021851.png","is_active":1},{"name":"GOPAY","slug":"gopay","image":"https:\/\/media-splash.com\/assets\/img\/coupon-gopay-1777959714.png","is_active":1}]},{"name":"Game","slug":"game","coupons":[{"name":"CODASHOP","slug":"codashop","image":"https:\/\/media-splash.com\/assets\/img\/coupon-codashop-1777256482.png","is_active":1},{"name":"LAPAKGAMING","slug":"lapakgaming","image":"https:\/\/media-splash.com\/assets\/img\/coupon-lapakgaming-1777274267.png","is_active":1}]},{"name":"Shop","slug":"shop","coupons":[{"name":"SHOPEE","slug":"shopee","image":"https:\/\/media-splash.com\/assets\/img\/coupon-gratis-ongkir-1777021832.png","is_active":1}]},{"name":"Travel","slug":"travel","coupons":[{"name":"GOWEEKEND","slug":"goweekend","image":"https:\/\/media-splash.com\/assets\/img\/coupon-goweekend-1777021838.png","is_active":0},{"name":"CASHBACK","slug":"cashback","image":"https:\/\/media-splash.com\/assets\/img\/coupon-cashback-1777021858.png","is_active":0}]}];

function deriveStatus(c){
  const now = new Date();

  if(!c.is_active) return 'INACTIVE';
  if(c.start_date && new Date(c.start_date.replace(' ','T')) > now) return 'COMING_SOON';
  if(c.end_date && new Date(c.end_date.replace(' ','T')) < now) return 'EXPIRED';

  // Quota tracking opsional — kalau API tidak return quota_total/claimed_count/remaining,
  // anggap unlimited (skip OUT_OF_QUOTA check).
  const hasQuotaInfo = typeof c.remaining === 'number'
    || c.quota_total != null
    || c.claimed_count != null;
  if (hasQuotaInfo) {
    const remaining = typeof c.remaining === 'number'
      ? c.remaining
      : Math.max(0, (Number(c.quota_total)||0) - (Number(c.claimed_count)||0));
    if(remaining <= 0) return 'OUT_OF_QUOTA';
  }

  if(c.open_time && c.close_time){
    const pad = n => String(n).padStart(2,'0');
    const today = `${now.getFullYear()}-${pad(now.getMonth()+1)}-${pad(now.getDate())}`;
    const open  = new Date(`${today}T${c.open_time}`);
    const close = new Date(`${today}T${c.close_time}`);
    if(now < open || now > close) return 'CLOSED';
  }

  return 'AVAILABLE';
}

const COUPONS = (Array.isArray(RAW_COUPONS) ? RAW_COUPONS : []).map(c => ({
  slug:       c.slug,
  status:     deriveStatus(c),
  image:      c.image,
  alt:        c.title || c.name || c.slug,
  claimUrl:   c.url_target || c.claim_url || '',
  urlQr:      c.url_qr || '',
  configId:   c.config_id,
  position:   c.position != null ? Number(c.position) : 9999,
  quotaTotal: c.quota_total,
  claimedCount: c.claimed_count,
  remaining:  typeof c.remaining === 'number'
    ? c.remaining
    : (c.quota_total != null || c.claimed_count != null
        ? Math.max(0, (Number(c.quota_total)||0) - (Number(c.claimed_count)||0))
        : null),
  openTime:   c.open_time,
  closeTime:  c.close_time,
  endDate:    c.end_date,
  startDate:  c.start_date,
  header:     c.header,
  subHeader:  c.sub_header,
  customText: c.custom_text,
  ctaText:    c.cta_text,
  snkText:    c.snk_text,
  category: c.category
})).sort((a, b) => a.position - b.position);

/* ======================= RENDER LIST ======================= */
function renderCoupons(){
  const wrap = document.getElementById("coupons");
  wrap.innerHTML = "";
  COUPONS.forEach(c=>{
    const clickable = c.status === "AVAILABLE";
    const dimmed = !clickable;
    const el = document.createElement("div");
    el.className = "coupon" + (clickable ? " pressable" : " disabled");

    el.innerHTML = `
      <img src="${c.image}" alt="${c.alt || ''}">
      ${dimmed ? '<div class="overlay-dim"></div>' : ''}
    `;

    if(clickable){
      el.addEventListener("click", ()=>{
        setTimeout(()=>navigate(c.slug), 200);
      });
    }
    wrap.appendChild(el);
  });
}

/* ======================= ROUTING ======================= */
function navigate(slug){
  if(slug){
    history.pushState({slug}, "", "/" + slug);
  } else {
    history.pushState({}, "", "/");
  }
  applyRoute();
}

function applyRoute(){
  const path = location.pathname || "/";
  const m = path.match(/^\/([a-z0-9-]+)\/?$/i);
  if(m){
    const slug = m[1];
    const c = COUPONS.find(x=>x.slug===slug);
    if(c && c.status==="AVAILABLE"){
      showDetail(c);
      return;
    }
  }
  showList();
}

function hideAllPages(){
  document.getElementById("page-list").classList.remove("active");
  document.getElementById("page-detail").classList.remove("active");
}

function showList(){
  hideAllPages();
  document.getElementById("page-list").classList.add("active");
  stopCountdown();
  window.scrollTo(0,0);
}

function renderQuotaState(c){
  const quotaText = document.getElementById("quotaText");
  const claim     = document.getElementById("claimBtn");

  // Custom text dari API (replace seluruh teks "Tersedia untuk X orang...")
  if (quotaText) {
    quotaText.textContent = (c && c.customText)
      ? c.customText
      : "Tersedia untuk 100 orang tercepat hari ini";
  }

  if (!claim) return;

  const ctaLabel = (c && c.ctaText) ? c.ctaText : "KLAIM";
  claim.textContent = ctaLabel;
  claim.classList.remove("inactive");
  claim.disabled = false;
  claim.onclick = function(){
    if (!c.claimUrl) { alert('URL target belum di-set di admin panel.'); return; }
    claim.disabled = true;
    claim.textContent = "MEMPROSES...";
    if (window.dataLayer) window.dataLayer.push({ event: "klaim_click", brand: c.slug });
    window.location.href = c.claimUrl;
  };
}

function renderSnkList(snkText){
  const ul = document.getElementById("snkList");
  if (!ul) return;
  const defaults = [
    "Pengguna wajib memiliki akun DANA yang aktif.",
    "Klaim hanya dapat dilakukan maksimal 1 (satu) kali dalam periode 24 jam.",
    "Setiap klaim akan melalui proses verifikasi sebelum saldo dikirimkan."
  ];
  ul.innerHTML = "";
  const items = (snkText && String(snkText).trim().length)
    ? String(snkText).split(/\r?\n/).map(s => s.replace(/^[-•*]\s*/, '').trim()).filter(Boolean)
    : defaults;
  items.forEach(text => {
    const li = document.createElement("li");
    li.textContent = text;
    ul.appendChild(li);
  });
}

async function showDetail(c){
  hideAllPages();
  document.getElementById("page-detail").classList.add("active");
  document.getElementById("backBtn").style.display = "flex";

  // Set QR image dari API (url_qr). Fallback ke default kalau kosong.
  const qrImg = document.getElementById("qrImg");
  if (qrImg) {
    qrImg.style.display = "";
    qrImg.src = c.urlQr || "https://media-splash.com/assets/img/barcode-dana.jpg";
  }

  // Header & sub-header dari API (fallback ke teks default)
  const selamatEl = document.getElementById("selamatText");
  if (selamatEl) selamatEl.textContent = c.header || "";

  const detailDescEl = document.getElementById("detailDesc");
  if (detailDescEl) detailDescEl.textContent = c.subHeader || "";

  // Render list ketentuan (S&K) dari snk_text
  renderSnkList(c.snkText);

  renderQuotaState(c);
  startCountdown(c);
  window.scrollTo(0,0);
}

document.getElementById("backBtn").addEventListener("click", ()=>{
  history.back();
});

window.addEventListener("popstate", applyRoute);

/* ======================= COUNTDOWN (pake open_time/close_time dari API) ======================= */
let cdTimer = null;
let cdCurrentCoupon = null;

function parseHMS(str){
  if (!str) return null;
  const parts = String(str).split(':').map(Number);
  return { h: parts[0]||0, m: parts[1]||0, s: parts[2]||0 };
}

function computeTarget(c){
  const now = new Date();
  const openT  = c ? parseHMS(c.openTime)  : null;
  const closeT = c ? parseHMS(c.closeTime) : null;

  // Kalau ada open_time + close_time
  if (openT && closeT) {
    const openToday  = new Date(now); openToday.setHours(openT.h,  openT.m,  openT.s,  0);
    const closeToday = new Date(now); closeToday.setHours(closeT.h, closeT.m, closeT.s, 0);

    if (now >= openToday && now <= closeToday) {
      return closeToday; // masih buka → countdown ke tutup
    }
    // Di luar window → ke next open_time
    const nextOpen = new Date(openToday);
    if (now > openToday) nextOpen.setDate(nextOpen.getDate() + 1);
    return nextOpen;
  }

  // Fallback: 08:00 next
  const t = new Date(now);
  t.setHours(8, 0, 0, 0);
  if (now >= t) t.setDate(t.getDate()+1);
  return t;
}

function tick(){
  const target = computeTarget(cdCurrentCoupon);
  const diff = Math.max(0, target - new Date());
  const h = Math.floor(diff/3600000);
  const m = Math.floor((diff%3600000)/60000);
  const s = Math.floor((diff%60000)/1000);
  const elH = document.getElementById("cdH");
  const elM = document.getElementById("cdM");
  const elS = document.getElementById("cdS");
  if (elH) elH.textContent = String(h).padStart(2,"0");
  if (elM) elM.textContent = String(m).padStart(2,"0");
  if (elS) elS.textContent = String(s).padStart(2,"0");
}

function startCountdown(c){
  stopCountdown();
  cdCurrentCoupon = c || null;
  tick();
  cdTimer = setInterval(tick, 1000);
}
function stopCountdown(){
  if(cdTimer){ clearInterval(cdTimer); cdTimer=null; }
}

/* ======================= HERO SLIDER ======================= */
function fmtSliderDate(d){
  if(!d) return '';
  const m = String(d).match(/^(\d{4})-(\d{2})-(\d{2})/);
  if(!m) return '';
  return `${m[3]}/${m[2]}/${m[1]}`;
}

function parseSliderLogos(desc){
  if(!desc) return [];
  // Format: "logos:url1,url2,url3" → array of urls
  const m = String(desc).match(/logos:\s*(.+)/i);
  if(!m) return [];
  return m[1].split(',').map(s => s.trim()).filter(Boolean);
}

const SLIDERS = (Array.isArray(RAW_SLIDERS) ? RAW_SLIDERS : [])
  .filter(s => s && s.image)
  .map(s => ({
    image:       s.image,
    title:       s.title || s.name || '',
    description: s.description || '',
    slug:        s.slug || '',
    brand:       s.brand_slug || s.brand_name || '',
    hostname:    s.hostname || '',
    category:    s.category || s.category_slug || 'KODE',
    expiry:      s.custom_text || '',
    viewName:    (s.view_name || '').toLowerCase(),
    logos:       parseSliderLogos(s.description)
  }));

const SLIDER_INSTANCES = [];

/* ======================= COUPON BOTTOM SHEET ======================= */
let couponSheetEl = null;
function ensureCouponSheet(){
  if(couponSheetEl) return couponSheetEl;
  const wrap = document.createElement('div');
  wrap.className = 'coupon-sheet';
  wrap.innerHTML = `
    <div class="coupon-sheet-overlay"></div>
    <div class="coupon-sheet-content">
      <div class="coupon-sheet-handle"></div>
      <div class="coupon-sheet-header">
        <div class="coupon-sheet-title" id="couponSheetTitle"></div>
        <button type="button" class="coupon-sheet-close" aria-label="Close">×</button>
      </div>
      <div class="coupon-sheet-list" id="couponSheetList"></div>
    </div>
  `;
  document.body.appendChild(wrap);
  wrap.querySelector('.coupon-sheet-overlay').addEventListener('click', closeCouponSheet);
  wrap.querySelector('.coupon-sheet-close').addEventListener('click', closeCouponSheet);
  document.addEventListener('keydown', e => {
    if(e.key === 'Escape') closeCouponSheet();
  });
  couponSheetEl = wrap;
  return wrap;
}
function openCouponSheet(cat, allCoupons){
  const sheet = ensureCouponSheet();
  sheet.querySelector('#couponSheetTitle').textContent = cat.name || '';
  const list = sheet.querySelector('#couponSheetList');

  if(!allCoupons || !allCoupons.length){
    list.innerHTML = `<div class="coupon-sheet-empty">Belum ada coupon di kategori ini.</div>`;
  } else {
    // Sort: active coupons di atas, inactive di bawah
    const sorted = allCoupons.slice().sort((a, b) => {
      const aActive = isCouponClickable(a) ? 0 : 1;
      const bActive = isCouponClickable(b) ? 0 : 1;
      return aActive - bActive;
    });

    list.innerHTML = sorted.map(cp => {
      const slug      = (cp.slug || '').replace(/"/g,'&quot;');
      const name      = (cp.name || cp.title || cp.slug || '').replace(/"/g,'&quot;');
      const image     = cp.image || '';
      const initial   = (cp.name || cp.slug || '?').charAt(0).toUpperCase();
      const clickable = isCouponClickable(cp);
      const itemCls   = 'coupon-sheet-item' + (clickable ? '' : ' coupon-sheet-item--inactive');
      const thumbHtml = image
        ? `<img src="${image}" alt="${name}" loading="lazy" onerror="this.parentNode.innerHTML='<span class=&quot;coupon-sheet-thumb-fallback&quot;>${initial}</span>'">`
        : `<span class="coupon-sheet-thumb-fallback">${initial}</span>`;
      const tail = clickable
        ? `<span class="coupon-sheet-item-arrow">›</span>`
        : `<span class="coupon-sheet-item-badge">Tidak Aktif</span>`;
      return `
        <button type="button" class="${itemCls}" data-coupon-slug="${slug}" ${clickable ? '' : 'disabled aria-disabled="true"'}>
          <span class="coupon-sheet-thumb">${thumbHtml}</span>
          <span class="coupon-sheet-item-name">${name}</span>
          ${tail}
        </button>
      `;
    }).join('');

    list.querySelectorAll('.coupon-sheet-item').forEach(item => {
      if(item.classList.contains('coupon-sheet-item--inactive')) return;
      item.addEventListener('click', () => {
        const slug = item.dataset.couponSlug;
        const c = COUPONS.find(x => x.slug === slug && x.status === 'AVAILABLE');
        if(!c) return;
        closeCouponSheet();
        setTimeout(()=> navigate(c.slug), 200);
      });
    });
  }

  sheet.classList.add('is-open');
  document.body.style.overflow = 'hidden';
}

// Coupon dianggap clickable kalau ada di COUPONS dengan status AVAILABLE.
// Cek `is_active` dari API juga (yang baru ditambah di /api/coupon/category/list).
function isCouponClickable(cp){
  if(cp && cp.is_active === 0) return false;
  return COUPONS.some(c => c.slug === cp.slug && c.status === 'AVAILABLE');
}
function closeCouponSheet(){
  if(!couponSheetEl) return;
  couponSheetEl.classList.remove('is-open');
  document.body.style.overflow = '';
}

// Kategori yang otomatis di-render di BOTTOM container + force banner template.
// Tambah/hapus sesuai kebutuhan (case-insensitive).
const BOTTOM_CATEGORIES = ['TOPUP', 'TOP UP', 'TOP-UP'];

function isBottomCategory(cat){
  if(!cat) return false;
  const norm = String(cat).toUpperCase().trim();
  return BOTTOM_CATEGORIES.map(c=>c.toUpperCase()).includes(norm);
}

function renderSlideHtml(s){
  const safeAlt  = (s.title || '').replace(/"/g,'&quot;');
  const safeSlug = (s.slug || '').replace(/"/g,'&quot;');

  // === VARIAN: banner (image full + label, brand logos / description optional) ===
  // Auto-pakai banner kalau view_name = 'banner' ATAU category termasuk BOTTOM_CATEGORIES
  if(s.viewName === 'banner' || isBottomCategory(s.category)){
    let footHtml = '';
    if(s.logos && s.logos.length){
      footHtml = `<div class="hero-slide-banner-foot">${s.logos.map(u => `<img src="${u}" alt="" onerror="this.style.display='none'">`).join('')}</div>`;
    } else if(s.description && !/^logos:/i.test(s.description)){
      footHtml = `<div class="hero-slide-banner-foot"><div class="hero-slide-banner-foot-desc">${s.description}</div></div>`;
    }
    return `
      <div class="hero-slide hero-slide--banner" data-slider-slug="${safeSlug}">
        <div class="hero-slide-banner-img">
          <img src="${s.image}" alt="${safeAlt}" loading="lazy" onerror="this.style.display='none'">
          ${s.category ? `<div class="hero-slide-banner-label">${s.category}</div>` : ''}
        </div>
        ${footHtml}
      </div>
    `;
  }

  // === DEFAULT: voucher card (Domino's style) ===
  return `
    <div class="hero-slide" data-slider-slug="${safeSlug}">
      <div class="hero-slide-img-wrap">
        <img src="${s.image}" alt="${safeAlt}" loading="lazy" onerror="this.style.display='none'">
      </div>
      <div class="hero-slide-body">
        <div class="hero-slide-tags">
          ${s.hostname ? `<span class="hero-slide-brand">${s.hostname}</span>` : (s.brand ? `<span class="hero-slide-brand">${s.brand}</span>` : '')}
        </div>
        ${s.title ? `<div class="hero-slide-title">${s.title}</div>` : ''}
        ${s.description ? `<div class="hero-slide-desc">${s.description}</div>` : ''}
        ${s.expiry ? `<div class="hero-slide-expiry"><b>${s.expiry}</b></div>` : ''}
      </div>
    </div>
  `;
}

// Cari coupon yang available berdasarkan slug slider
function handleSliderClick(sliderSlug){
  if(!sliderSlug) return;
  const coupon = (typeof COUPONS !== 'undefined' ? COUPONS : []).find(
    c => c.slug === sliderSlug && c.status === 'AVAILABLE'
  );
  if(!coupon) return;
  setTimeout(()=> navigate(coupon.slug), 150);
}

function initSliderInstance(trackEl, dotsEl, items){
  const state = { index:0, timer:null, intervalMs:4500, startX:0, endX:0, dragging:false };

  trackEl.innerHTML = items.map(s => renderSlideHtml(s)).join('');
  dotsEl.innerHTML  = items.map((_,i)=>`<button type="button" class="hero-dot${i===0?' active':''}" data-i="${i}" aria-label="Slide ${i+1}"></button>`).join('');

  function go(i){
    if(!items.length) return;
    const n = items.length;
    state.index = ((i % n) + n) % n;
    trackEl.style.transform = `translateX(-${state.index * 100}%)`;
    dotsEl.querySelectorAll('.hero-dot').forEach((d,idx)=>{
      d.classList.toggle('active', idx === state.index);
    });
  }
  function start(){
    stop();
    if(items.length <= 1) return;
    state.timer = setInterval(()=> go(state.index + 1), state.intervalMs);
  }
  function stop(){
    if(state.timer){ clearInterval(state.timer); state.timer = null; }
  }

  // Dots click
  dotsEl.querySelectorAll('.hero-dot').forEach(d=>{
    d.addEventListener('click', ()=>{ go(Number(d.dataset.i)); start(); });
  });

  // Helper: handle tap (drag pendek = klik) → navigate ke coupon dengan slug match
  function handleTap(targetEl){
    if(!targetEl) return;
    const slideEl = targetEl.closest && targetEl.closest('.hero-slide');
    if(!slideEl) return;
    const slug = slideEl.dataset.sliderSlug;
    if(slug) handleSliderClick(slug);
  }

  // Touch (mobile)
  trackEl.addEventListener('touchstart', e => {
    state.dragging = true;
    state.startX = e.touches[0].clientX;
    state.endX   = state.startX;
    state.target = e.target;
    stop();
  }, {passive:true});
  trackEl.addEventListener('touchmove', e => {
    if(!state.dragging) return;
    state.endX = e.touches[0].clientX;
  }, {passive:true});
  trackEl.addEventListener('touchend', () => {
    if(!state.dragging) return;
    state.dragging = false;
    const delta = state.endX - state.startX;
    if(Math.abs(delta) > 40){
      if(delta < 0) go(state.index + 1);
      else          go(state.index - 1);
    } else if(Math.abs(delta) < 8){
      // Tap (no swipe) → trigger click navigation
      handleTap(state.target);
    }
    state.target = null;
    start();
  });

  // Mouse drag (desktop)
  trackEl.style.cursor = 'pointer';
  trackEl.addEventListener('mousedown', e => {
    state.dragging = true;
    state.startX = e.clientX;
    state.endX   = state.startX;
    state.target = e.target;
    trackEl.style.cursor = 'grabbing';
    stop();
    e.preventDefault();
  });
  window.addEventListener('mousemove', e => {
    if(!state.dragging) return;
    state.endX = e.clientX;
  });
  window.addEventListener('mouseup', () => {
    if(!state.dragging) return;
    state.dragging = false;
    trackEl.style.cursor = 'pointer';
    const delta = state.endX - state.startX;
    if(Math.abs(delta) > 40){
      if(delta < 0) go(state.index + 1);
      else          go(state.index - 1);
    } else if(Math.abs(delta) < 5){
      // Click (no drag) → trigger navigation
      handleTap(state.target);
    }
    state.target = null;
    start();
  });

  go(0);
  start();
  SLIDER_INSTANCES.push({ start, stop });
}

function renderHeroSliders(){
  const containerTop    = document.getElementById('heroSliderContainer');
  const containerBottom = document.getElementById('heroSliderContainerBottom');
  if(!containerTop && !containerBottom) return;

  if(containerTop)    containerTop.innerHTML = '';
  if(containerBottom) containerBottom.innerHTML = '';

  if(!SLIDERS.length) return;

  // Group by category
  const groupsRaw = {};
  SLIDERS.forEach(s => {
    const cat = (s.category || 'OTHER');
    if(!groupsRaw[cat]) groupsRaw[cat] = [];
    groupsRaw[cat].push(s);
  });

  // Sort categories alphabetically
  const sortedCats = Object.keys(groupsRaw).sort((a,b)=> a.localeCompare(b));

  // Pisahin TOP vs BOTTOM categories
  const topCats = [];
  const bottomCats = [];
  sortedCats.forEach(cat => {
    const items = groupsRaw[cat];
    const isBottom = isBottomCategory(cat) || items.some(s => s.viewName === 'banner');
    if(isBottom) bottomCats.push(cat);
    else        topCats.push(cat);
  });

  // === TOP: carousel voucher card per kategori ===
  let idx = 0;
  for(const cat of topCats){
    const items = groupsRaw[cat];
    if(!containerTop) continue;

    const trackId = `heroTrack${idx}`;
    const dotsId  = `heroDots${idx}`;

    const wrap = document.createElement('div');
    wrap.className = 'hero-slider-wrap';
    wrap.id = `heroSlider${idx}`;
    wrap.dataset.cat = cat;
    wrap.innerHTML = `
      <div class="hero-slider">
        <div class="hero-slider-track" id="${trackId}"></div>
      </div>
      <div class="hero-dots" id="${dotsId}"></div>
    `;
    containerTop.appendChild(wrap);

    initSliderInstance(
      document.getElementById(trackId),
      document.getElementById(dotsId),
      items
    );
    idx++;
  }

  // === BOTTOM: pill per category dari /api/coupon/category/list ===
  // Click pill → buka bottom sheet dengan SEMUA coupon (active + inactive).
  // Inactive ditampilkan grayed-out tapi tetap visible.
  if(containerBottom){
    const cats = Array.isArray(RAW_COUPON_CATEGORIES) ? RAW_COUPON_CATEGORIES : [];

    // Helper: hitung coupon active per category (untuk badge counter)
    function countActiveCoupons(cat){
      return (cat.coupons || []).filter(cp => isCouponClickable(cp)).length;
    }

    const pillsHtml = [];
    cats.forEach(cat => {
      const total = (cat.coupons || []).length;
      const activeCount = countActiveCoupons(cat);
      const slug = (cat.slug || '').replace(/"/g,'&quot;');
      const name = (cat.name || cat.slug || '').replace(/"/g,'&quot;');
      const disabled = total === 0 ? ' pill--disabled' : '';
      const countBadge = total > 0 ? `<span class="pill-count">${activeCount}</span>` : '';
      pillsHtml.push(
        `<button type="button" class="pill${disabled}" data-cat-slug="${slug}"${total === 0 ? ' disabled' : ''} title="${name}">${name}${countBadge}</button>`
      );
    });

    if(pillsHtml.length){
      containerBottom.innerHTML = `<div class="pill-list" id="pillList">${pillsHtml.join('')}</div>`;

      const pillList = document.getElementById('pillList');

      // Toggle fade indicator kalau overflow + on-scroll
      function updateOverflow(){
        const hasOverflow = pillList.scrollWidth > pillList.clientWidth + 2;
        const atEnd = pillList.scrollLeft + pillList.clientWidth >= pillList.scrollWidth - 2;
        if(hasOverflow && !atEnd){
          containerBottom.classList.add('has-overflow');
        } else {
          containerBottom.classList.remove('has-overflow');
        }
      }
      pillList.addEventListener('scroll', updateOverflow);
      window.addEventListener('resize', updateOverflow);
      requestAnimationFrame(updateOverflow);
      setTimeout(updateOverflow, 300);

      // Drag-to-scroll desktop (mouse) — touch sudah handled native browser
      const drag = { active:false, startX:0, scrollLeft:0, moved:0 };

      pillList.addEventListener('mousedown', e => {
        drag.active = true;
        drag.startX = e.clientX;
        drag.scrollLeft = pillList.scrollLeft;
        drag.moved = 0;
        pillList.classList.add('is-dragging');
      });
      window.addEventListener('mousemove', e => {
        if(!drag.active) return;
        e.preventDefault();
        const walk = (e.clientX - drag.startX) * 1.2;
        drag.moved = Math.abs(walk);
        pillList.scrollLeft = drag.scrollLeft - walk;
      });
      window.addEventListener('mouseup', () => {
        if(!drag.active) return;
        drag.active = false;
        pillList.classList.remove('is-dragging');
      });

      // Click pill → open bottom sheet (skip kalau habis drag)
      pillList.querySelectorAll('.pill[data-cat-slug]').forEach(btn => {
        btn.addEventListener('click', () => {
          if(drag.moved > 5){ drag.moved = 0; return; }
          const catSlug = btn.dataset.catSlug;
          if(!catSlug) return;
          const cat = cats.find(c => c.slug === catSlug);
          if(!cat) return;
          openCouponSheet(cat, cat.coupons || []);
        });
      });
    } else {
      containerBottom.innerHTML = '';
    }
  }

  /* ============================================================
   * === BOTTOM (LEGACY): banner carousel per kategori ===
   * Uncomment block ini & comment block "BOTTOM: pill row" di atas
   * kalau mau pake banner card style (image + label + logos).
   *
   * let idxBottom = 1000;
   * for(const cat of bottomCats){
   *   const items = groupsRaw[cat];
   *   if(!containerBottom) continue;
   *
   *   const trackId = `heroTrack${idxBottom}`;
   *   const dotsId  = `heroDots${idxBottom}`;
   *
   *   const wrap = document.createElement('div');
   *   wrap.className = 'hero-slider-wrap';
   *   wrap.id = `heroSlider${idxBottom}`;
   *   wrap.dataset.cat = cat;
   *   wrap.innerHTML = `
   *     <div class="hero-cat-label">${cat}</div>
   *     <div class="hero-slider">
   *       <div class="hero-slider-track" id="${trackId}"></div>
   *     </div>
   *     <div class="hero-dots" id="${dotsId}"></div>
   *   `;
   *   containerBottom.appendChild(wrap);
   *
   *   initSliderInstance(
   *     document.getElementById(trackId),
   *     document.getElementById(dotsId),
   *     items
   *   );
   *   idxBottom++;
   * }
   * ============================================================ */
}

document.addEventListener('visibilitychange', ()=>{
  SLIDER_INSTANCES.forEach(inst => {
    if(document.hidden) inst.stop();
    else                inst.start();
  });
});

/* ======================= INIT ======================= */
renderHeroSliders();
renderCoupons();
applyRoute();
</script>
</body>
</html>
