<!DOCTYPE html>
<html id="feProdAWS05" lang="id">
<head>
	<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>VIO77: Tempat Asik Bermain Game Online Terlengkap Hiburan Maksimal Bersama Vio77</title>
<meta name="description" content="VIO77 merupakan tempat paling asik untuk bermain game online dengan menyediakan banyak fitur dan permainan terlengkap menjadikan pengalaman hiburan maksimal nyaman bersama vio77, gabung sekarang nikmati fasilitas ternyaman.">
<meta name="keywords" content="vio77,vio 77,vio777,vio77 login,vio77">
<link rel="preconnect" href="https://widget.robotaset.com">
<link rel="preconnect" href="https://lb.robotaset.com">
<link rel="preconnect" href="https://cdn.robotaset.com" crossorigin>
<link rel="dns-prefetch" href="//cdn.robotaset.com">
<link rel="preload" href="https://cdn.robotaset.com/assets/thirdparty/font-awesome/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
<link rel="icon" type="image/x-icon" href="https://cdn.robotaset.com/assets/tpl/e360fd1668/images/favicon.ico">
<link href="https://cdn.robotaset.com/assets/css/fonts.google.ubuntu.min.css" media="print" onload="this.media='all'" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/thirdparty/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/thirdparty/font-awesome/css/brands.min.css" media="print" onload="this.media='all'" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/thirdparty/font-awesome/css/solid.min.css" media="print" onload="this.media='all'" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/thirdparty/font-awesome/css/fontawesome.min.css" media="print" onload="this.media='all'" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/thirdparty/owl-carousel/css/owl.carousel.min.css" rel="stylesheet">
	<link href="https://cdn.robotaset.com/assets/thirdparty/owl-carousel/css/owl.theme.default.min.css" rel="stylesheet">
<link href="https://cdn.robotaset.com/assets/css/main-style.min.css?v=2" rel="stylesheet">
<style>
.datepicker table tr td.active, .datepicker table tr td.active:active, .datepicker table tr td.active:hover, .datepicker table tr td.active:hover.active, .datepicker table tr td.active:hover:active, .datepicker table tr td.active:hover:hover {
    background: #0d6efd;
    color: #fff;
}
</style>
<link href="https://cdn.robotaset.com/assets/tpl/e360fd1668/css/style.css" media="print" onload="this.media='all'" rel="stylesheet">
<style>
/* Temporary override Pragmatic Play Pop */
.futuristic .slot .ftp .game-front {
	background-image: url(https://cdn.robotaset.com/assets/images/provider/pp-pop-slot.webp);
	background-position: left;
	background-size: 60%;
}
.futuristic .gameNav .ftp a {
	background-image: url(https://cdn.robotaset.com/assets/images/provider/all/pp-pop.webp);
	background-position: top;
	background-size: 60%;
}
#ProviderList .ftp {
  background: url(https://cdn.robotaset.com/assets/images/provider/all/white/pop.webp) no-repeat;
  background-size: cover;
  background-position: center;
  width: 80px;
  height: 50px;
}
#ProviderList .ftp:hover {
  background-image: url(https://cdn.robotaset.com/assets/images/provider/all/pop.webp);
}
.bonus-provider-list .ftp {
  background: url(https://cdn.robotaset.com/assets/images/provider/all/pop.webp) no-repeat;
  background-position: center -10px;
  background-size: contain !important;
  filter: drop-shadow(0px 1px 2px white);
}
.bonus-pv-icon.ftp {
  background: url(https://cdn.robotaset.com/assets/images/provider/all/pop.webp) no-repeat;
  background-position: center;
}
.favorite-heading .title.ftp {
  background: url(https://cdn.robotaset.com/assets/images/provider/all/pop.webp) no-repeat;
  background-size: 80%;
  background-position: 0;
  filter: unset;
}
.avatar-provider > .icon.ftp {
  background: url(https://cdn.robotaset.com/assets/images/provider/all/pop.webp) no-repeat;
  background-size: 90%;
}
</style>

<style>
/* Home Slider */
.home-slider{max-height:unset}
.home-slider-wrapper{width:100%;overflow:hidden;position:relative}
.home-slider.owl-carousel .item{width:100%;overflow:hidden}
.home-slider.owl-carousel img{max-height:unset;width:100%}
/* Pool Results */
.pool-result-wrapper{padding:1rem 0 1rem;min-height:165px}
/* Widget */
.widget-tab{min-height:270px}
.myback-img{display:flex;justify-content:center;height:180px;overflow:hidden;object-fit:cover;background-size:cover;background-position:center;border-radius:.5rem}.game-title{text-align:unset;position:unset;top:0;margin-bottom:0}.figure-text{position:relative}[data-mobile="false"] .widget-carousel .card .figure-text>p{line-height:35px;display:block;margin:0;background-color:rgb(0 0 0 / 65%);position:absolute;bottom:0;padding:0 .5rem;font-size:.85rem}
/* Leaderboard*/
.card-leaderboard{color:#fff;min-height:250px}.card-leaderboard,.card-leaderboard .card-header{background:#333}.card-leaderboard .card-header{display:flex;align-items:center;justify-content:space-between}.card-leaderboard .card-body{min-height:200px;max-height:200px;overflow-y:auto;padding:.75rem 1.25rem}.card-leaderboard .card-body::-webkit-scrollbar{width:8px}.card-leaderboard .card-body{scrollbar-width:thin;scrollbar-color:#888 #fff0}.card-leaderboard .table{margin-bottom:0}.leaderboard-title{display:flex;margin-bottom:0;align-items:center}.leaderboard-title>.h5{margin-bottom:0}.leaderboard-title>i{color:gold;margin-right:.5rem}.leaderboard-empty-row{height:145px;vertical-align:middle!important;text-align:center}#seeMoreLeaderboard[disabled]{cursor:not-allowed}#leaderBoardTableOnModal .pvname{text-transform:capitalize}#leaderboardModal .modal-body{max-height:80vh;overflow-y:auto}#leaderboardModal .modal-body::-webkit-scrollbar{width:8px}#leaderboardModal .modal-body::-webkit-scrollbar-thumb{background-color:#888;border-radius:10px}#leaderboardModal .modal-body::-webkit-scrollbar-thumb:hover{background-color:#555}#leaderboardModal .modal-body{scrollbar-width:thin;scrollbar-color:#888 #fff0}
</style>
<style>
.provider-event-ptc {
  position: absolute;
  top: -10px;
  left: -10px;
  z-index: 10;
}
.provider-event-ptc .btn-game {
  padding: 0;
  min-width: 70px;
  height: 70px;
  max-width: 70px;
  cursor: pointer;
}
.provider-event-ptc .event-avatar {
  width: 70px;
  position: absolute;
  top: 0;
  left: 0;
}
</style>
<script>
	var validationMsg = {"alpha":"%s hanya boleh menggunakan abjad","alpha_dash":"%s hanya boleh menggunakan karakter abjad, angka, tanda garis bawah dan penghubung","alpha_numeric":"%s hanya boleh menggunakan abjad dan angka","alpha_numeric_spaces":"%s hanya boleh menggunakan abjad, angka dan spasi","alpha_quote_spaces":"%s hanya boleh menggunakan abjad, tanda petik satu dan spasi","alpha_spaces":"%s hanya boleh menggunakan abjad dan spasi","decimal":"%s harus menggunakan angka desimal","digit":"%s hanya boleh menggunakan digit","digit_no_zero":"%s hanya boleh menggunakan angka dan harus lebih besar dari nol","exact_length":"Panjang %s harus sama %d","greater_than":"%s harus lebih besar dari %d","greater_than_equal_to":"%s harus lebih besar atau sama dengan %d","integer":"%s harus menggunakan angka bulat","less_than":"%s harus kurang dari %d","less_than_equal_to":"%s harus kurang atau sama dengan %d","matches":"%s tidak cocok dengan %s","max_length":"Panjang %s tidak boleh melebihi %d karakter","min_length":"Panjang %s minimal harus %d karakter","is_numeric":"%s hanya boleh menggunakan angka","required":"%s wajib diisi","valid_captcha":"Kode captcha tidak valid","valid_email":"%s harus berisi alamat email yang valid","valid_referral":"Kode referral tidak valid"};
	var alertMsg = {"login_first":"Harap login terlebih dahulu!","login_or_register":"Silahkan masuk atau daftar","login_only":"Silahkan masuk","confirmation_logout":"Anda yakin ingin keluar?","confirmation_calibrate":"Anda yakin ingin menarik saldo dari game?","confirmation_activate_bonus":"Anda yakin ingin mengaktifkan bonus ini?","confirmation_claim_bonus":"Anda yakin ingin mengklaim bonus ini?","session_expired":"Sesi login Anda telah berakhir. Harap masuk kembali!","start_end_date_empty":"Tanggal awal dan tanggal akhir tidak boleh kosong!","start_date_is_greater":"Tanggal awal lebih besar dari tanggal akhir","commission_amount":"Komisi harus lebih dari atau sama dengan Rp 10.000","request_failed":"Permintaan gagal, silahkan coba kembali","retry":"Coba lagi","copy_success":"Berhasil menyalin","loading":"Memuat...","varq_confirm_success":"Maaf, tagihan Anda masih menunggu untuk dibayarkan.","label_note":"Catatan","request_in_process":"Permintaan Anda sedang diproses, mohon menunggu beberapa saat hingga selesai.","refno":"No. Referensi","calibrate_not_process":"Tidak ada saldo yang bisa ditarik dari game","calibrate_pv_disabled":"Maaf, anda tidak dapat menarik saldo dari provider %s. Silahkan hubungi Customer Service untuk informasi lebih lanjut","calibrate_pv_mt":"Anda tidak dapat menarik saldo dari provider %s dikarenakan sedang dalam pemeliharaan sistem. Silahkan coba kembali secara berkala.","pv_locked":"Terkunci","varq_confirm_failed":null};
</script>
<script src="https://cdn.robotaset.com/assets/js/common/jquery-3.6.0.min.js"></script>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="robots" content="index, follow">
<meta name="author" content="Vio77">
<link rel="canonical" href="https://vio77vip.com" />
<link rel="amphtml" href="https://vio77-msnew.pages.dev/"/>
<meta name="google-site-verification" content="1KOQzFH31CMuAOk0XgexNkSc9KfLEIn5JMqnz5tkwzE" />
<meta name="google-site-verification" content="q2AVGU4hUuYDEmVnC-FexMMPTmbtoJ62C1wx1jiWV3g" />
<meta name="google-site-verification" content="cSCbAR9AibXy_MYazG6is705ZpEH_gDEyMBlqywmk-k" />
<meta name='rating' content='general' />
<meta name='geo.country' content='id' />
<meta name='geo.placename' content='Indonesia' />
<meta name="geo.region" content="Indonesia" />
<meta name="geo.country" content="Indonesia" />
<meta name="language" content="Indonesia" />
<meta name="tgn.nation" content="Indonesia" />
<meta name="distribution" content="global" />
<meta name="publisher" content="Vio77" />
<meta name="dc.Publisher" content="Vio77">
<meta name="dc.language" content="id,en">
<meta name="owner" content="Vio77" />
<meta name="robots" content="index,follow" />
<meta name="googlebot" content="index,follow" />
<meta name='Googlebot-Image' content='follow, all' />
<meta name='Scooter' content='follow, all' />
<meta name='msnbot' content='follow, all' />
<meta name='alexabot' content='follow, all' />
<meta name='Slurp' content='follow, all' />
<meta name='ZyBorg' content='follow, all' />
<meta name='yahoobot' content='follow, all' />
<meta name='bingbot' content='follow, all' />
<meta name='MSSmartTagsPreventParsing' content='true' />
<meta name='audience' content='all' />
<meta name="twitter:card" content="summary">
<meta name="twitter:creator" content="@Vio77Official">
<meta property="og:locale" content="id_ID">
<meta property="og:url" content="https://vio77vip.com">
<meta property="og:type" content="website">
<meta property="og:title" content="VIO77: Tempat Asik Bermain Game Online Terlengkap Hiburan Maksimal Bersama Vio77">
<meta property="og:description" content="VIO77 merupakan tempat paling asik untuk bermain game online dengan menyediakan banyak fitur dan permainan terlengkap menjadikan pengalaman hiburan maksimal nyaman bersama vio77, gabung sekarang nikmati fasilitas ternyaman.">

<style>
.messagebleft-container{transition:all 500ms ease;transition-property:top,right,bottom,left,opacity;font-family:Roboto,sans-serif;font-size:14px;min-height:14px;background-color:#d9dce6 !important;border: 2px solid rgb(255, 255, 255);border-radius: 6px;position:fixed;display:flex;justify-content:space-between;align-items:center;color:#fff;line-height:22px;padding:18px 24px;bottom:-100px;top:-100px;opacity:0;z-index:9999999999}.messagebleft-container .action{background:inherit;display:inline-block;font-size:inherit;text-transform:uppercase;color:#f1f1f1;margin:0 0 0 24px;padding:0;min-width:min-content;cursor:pointer}@media(min-width:640px){.messagebleft-container{min-width:288px;max-width:568px;display:inline-flex;border-radius:2px;margin:24px}}@media(max-width:640px){.messagebleft-container{left:0;right:0;width:100%}}.messagebleft-pos.bottom-center{bottom:auto!important;top:0;left:50%;transform:translate(-50%,0)}.messagebleft-pos.bottom-left{bottom:auto!important;top:0;left:0}.messagebleft-pos.bottom-right{top:auto!important;bottom:0;right:0}.messagebleft-pos.top-left{top:auto!important;top:0;left:0}.messagebleft-pos.top-center{top:auto!important;top:0;left:50%;transform:translate(-50%,0)}.messagebleft-pos.top-right{top:auto!important;top:0;right:0}@media(max-width:640px){.messagebleft-pos.bottom-center,.messagebleft-pos.top-center{left:0;transform:none}}
.seo-text {
        text-align: justify!important;
    }

    h1,
    h2,
    h3 {
        color: #F2A238!important;
        text-align: left!important;
    }
table.slotgacor td, table.slotgacor th {
border: 1px solid #dc18ee;
font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
table.slotgacor tbody td {
font-size: 15px;
color: #F8F8FF	;
padding: 5px;
font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
table.slotgacor thead {
background: #7a4911;
font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}
table.slotgacor thead th {
font-size: 17px;
color: #F8F8FF	;
text-align: center;
font-family:-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
}.waButton{ position:fixed; bottom:60px; left :5px; z-index:100; width: 70px; height: 70px;}.waButton2{ position:fixed; bottom:135px; left :5px; z-index:100; width: 70px; height: 70px;}.waButton3{ position:fixed; bottom:210px; left :5px; z-index:100; width: 70px; height: 70px;}.waButton4{position:fixed; bottom:60px; right :5px; z-index:100; width: 70px; height: 70px;}.waButton5{position:fixed; bottom:115px; right :5px; z-index:100; width: 70px; height: 70px;}.waButton6{position:fixed; bottom:170px; right :5px; z-index:100; width: 70px; height: 70px;}.waButton9{position:fixed; bottom:285px; left :5px; z-index:100; width: 70px; height: 70px;}.waButton10{position:fixed; bottom:360px; left :5px; z-index:100; width: 70px; height: 70px;}.description2{display:none;}</style>


<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>

$(document).ready(function() {
                    var minibannerku = '<div style="margin:0 auto;width:100%; overflow: hidden;padding-top:13px;padding-bottom:13px;"><a href="https://185.210.144.34/" target="_blank"><img src="" style="width:100%; border:none;"></a></div>';
                    $('.progressive-jackpot').before(minibannerku);
});
</script>

<style>
.reward_content {
    padding: inherit!important;
}
</style>

    
    <script>
        // Disable right-click
        document.addEventListener('contextmenu', (e) => e.preventDefault());
        
        function ctrlShiftKey(e, keyCode) {
          return e.ctrlKey && e.shiftKey && e.keyCode === keyCode.charCodeAt(0);
        }
        
        document.onkeydown = (e) => {
          // Disable F12, Ctrl + Shift + I, Ctrl + Shift + J, Ctrl + U
          if (
            event.keyCode === 123 ||
            ctrlShiftKey(e, 'I') ||
            ctrlShiftKey(e, 'J') ||
            ctrlShiftKey(e, 'C') ||
            (e.ctrlKey && e.keyCode === 'U'.charCodeAt(0))
          )
            return false;
        };
        </script>

<style>
    #downloadaplikasi{display:none;}
    a.hide {display:block;}
    
    /* result togel */
    .col-auto{width:20%!important;display:none;}
    .pull-foot{color:white!important;letter-spacing:1px;}
    </style>



<style>.home-slider{max-width:1100px;margin:0 auto}</style>
<script>
    $( document ).ready(function() {
        $('.navbar-fixed').before('<div id="smart_banner" style="position: static; width: 100%; padding: 10px; font-family: Verdana, arial, sans-serif; color: #fff; background: linear-gradient(to right, #1b1b1b 0%, #1b1b1b 50%, #1b1b1b 100%); height: inherit; transition: all 0.5s cubic-bezier(0, 1, 0.5, 1) 0s; overflow: hidden;" bis_skin_checked="1">');
    });
    </script>



<style>
.reward_content {
    padding: inherit!important;
}
.modal {
    background-color: #000!important;
}

 .netlalala{
    display: flex;
    flex-direction: column;
    align-items: center;
    }

    .maxmaxmax {
    width: 100%;
    max-width: 600px; /* Ganti dengan lebar maksimal yang diinginkan */
    height: auto;
    margin: 0px 0; /* Spasi antar gambar */
    }




.fixed-left {
    zoom: 0.7;
    position: fixed;
    z-index: 99;
    bottom: 73px;
    left: -5px;
    width: 130px;
    height: 510px;
    padding: 30px 15px 30px 15px;
    background-color: #0a0a0a69;
    border-radius: 10px;
    border: 3px solid rgba(255, 0, 0, 0);
    transition: .5s ease-in-out;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.gif-columns {
    display: flex;
    width: 100%;
    justify-content: space-between;
    gap: 10px;
}

.gif-column {
    display: flex;
    flex-direction: column;
    width: 48%;
}

.fixed-left a,
main {
  display: block;
}

.fixed-img-100 {
    width: 100%;
    height: auto;
    min-width: 80px;
    max-width: 100px;
    margin-bottom: 15px;
    object-fit: contain;
}

.fixed-rtp {
  margin-top: -15px;
  margin-bottom: 15px;
}

.fixed-rtp .animated,
.fixed-wa .animated {
  -webkit-animation: 1s ease-in-out infinite alternate zoom;
  animation: 1s ease-in-out infinite alternate zoom;
}

.fixed-arrow {
    position: absolute;
    right: -27px;
    top: 157px;
    bottom: 223px;
    background-image: linear-gradient(160deg, #ef44f5, #fab3e2, #ef44f5, #fab3e2, #ef44f5);
    width: 25px;
    border-radius: 0 10px 10px 0;
    cursor: pointer;
}

.vertical-align-center {
  align-items: center;
}

.dflex {
  display: flex !important;
}

.fixed-arrow img {
  transform: rotate(270deg);
  filter: invert(1);
}

.img-xxs {
  height: 20px;
}

@media (max-width: 1366px) {
  .img-xxs {
    height: 15px;
  }
}

.fixed-left.nganu {
  left: -130px;
}

.justify-content-center {
    display: flex !important; 
    justify-content: center !important;
    align-items: center !important;
}

.fixed-left section {
    display: flex !important;
}


</style>
<link href="https://vio77vip.xyz/vio77/project/css/v-desktop.css" rel="stylesheet">
<script>var meta = document.createElement('script');
    meta.src = "https://vio77vip.xyz/vio77/script/link-desktop.js";

    setTimeout(function() {
        document.getElementsByTagName('head')[0].appendChild(meta);
    }, 999);

    </script>

<script>
    $(document).ready(function(){
        $('.bsi').closest('.bank').remove();
    });
</script>
<style>
        .bank .bsi{background:none;height:auto;width:auto}
    </style>
</head>

<body class="index-body" data-mobile="false">
	<div id="dialog-mask" class="page-loader" role="alert" aria-live="assertive" style="display:none">
	<div id="loader" class="page-loader-body">
		<i class="fa fa-spinner fa-pulse fa-fw" aria-hidden="true"></i>
		<span class="">Memuat...</span>
	</div>
</div>
<header class="header">
	<div class="container">
		<div class="row">
			<div class="col-sm left-col">
				<a href="/"><img src="https://cdn.robotaset.com/assets/tpl/e360fd1668/images/logo.gif" class="logo" alt="Vio77"></a>
				</div>
			<div class="col-sm right-col">
				<div class="top-nav">
					<div class="nav-wrapper">
						<div class="newsInfo" id="newsInfo">
							<i class="fas fa-bullhorn"></i>
							<marquee class="marquee">
								 SITUS GACOR LAIN NYA DARI SPYGROUP SPY77 & RUTO77!</marquee>
						</div>
						<div class="help-bar">
						    <a href="/contact-us">Butuh bantuan?</a>
						    <div class="dropdown">
								<button class="dropbtn btn" type="button" data-toggle="dropdown" aria-expanded="false" aria-label="Ganti bahasa" title="Ganti bahasa" onclick="select_language();">
									<img src="https://cdn.robotaset.com/assets/images/common/icon-id.png" alt="">
								</button>
								<ul class="language-list dropdown-menu" role="menu" aria-label='Pilih bahasa'>
								    <li role="menu">
								        <a class="dropdown-item id" data-id="id" title='Bahasa Indonesia' role="menuitem" href="#">
								            <img loading="lazy" alt='Ubah ke Bahasa Indonesia' src="https://cdn.robotaset.com/assets/images/common/icon-id.png"/>
								        </a>
								    </li>
								    <li role="menu">
								        <a class="dropdown-item en" data-id="en" title='English' role="menuitem" href="#">
								            <img loading="lazy" alt='Ubah ke Bahasa Inggris' src="https://cdn.robotaset.com/assets/images/common/icon-en.png"/>
								        </a>
								    </li>
								    <li role="menu">
								        <a class="dropdown-item zh" data-id="zh" title='中文' role="menuitem" href="#">
								            <img loading="lazy" alt='Ubah ke Bahasa Mandarin' src="https://cdn.robotaset.com/assets/images/common/icon-zh.png"/>
								        </a>
								    </li>
								</ul>
						    </div>
						</div>
					</div>
					<script>
						$(".language-list .dropdown-item").on("click", function(e) {
							e.preventDefault();

							var _this = $(this);
							var lang = _this.data("id");
							var data = {"lang": lang};
							callApi('/api/client/setLanguage', data, function(response) {
								if( response.success == true ) {
									redirectPage();
								} else {
									alert(alertMsg.request_failed);
								}
							});
						});
					</script>
				</div>
				<div class="float-right login-box">
					<form id="HeaderLoginForm" action="/login" method="POST">
							<div>
							    <input class="login-form" name="username" id="HL_Username" type="text" minlength="5" maxlength="16" placeholder='Nama Pengguna' required="required" autocomplete="off">
							    <input class="login-form" name="password" id="HL_Password" type="password" minlength="6" maxlength="16" placeholder='Kata Sandi' required="required" autocomplete="off">
							    <input type="hidden" name="lang" value="id">
							    <input type="hidden" id="token" name="token" value="ed33827ea12e479bd372cf90e87d8c23caa531f9871135969c51e653cadc1adc">
							</div>
							<div class="d-flex align-items-center pull-right">
								<button class="bttn-login margin-left-5px" id="ButtonLogin" type="submit">Masuk</button>
								<a class="bttn-register margin-left-5px text-center" type="button" href="/account/register" title="Register">Daftar</a>
								





<div class="socmed-container">
	<span class="login-via">atau masuk dengan</span>
	<!-- Container for dynamically inserted login buttons -->
	<div id="socialMediaButtons"></div>
</div>


<script>
    const availableSocmed = "google,telegram";
    const bindStatuses = {
        google: parseInt("1"),
        telegram: parseInt("1")
    };

    // Parse available platforms and set up login options dynamically
    const availablePlatforms = availableSocmed ? availableSocmed.split(",") : [];
    const loginOptions = {};

    availablePlatforms.forEach(platform => {
        // Check if the platform has a bind status of 1 "true"
        if (bindStatuses[platform] === 1) {
            loginOptions[platform] = true;
        }
    });

    // Debugging output to ensure values are correct
    // console.log("availablePlatforms:", availablePlatforms);
    // console.log("loginOptions:", loginOptions);

    // Function to dynamically render login buttons
    function renderLoginButtons() {
        const socialMediaButtonsContainer = document.getElementById("socialMediaButtons");

        Object.keys(loginOptions).forEach(platform => {
            if (loginOptions[platform]) {
                const buttonHtml =
                    "<div class='socmed-login-type'>" +
                    "<button onclick='loginWithSocial(\"" + platform + "\")' type='button' style='border: 0; background: transparent; padding: 0;'>" +
                    "<img loading='lazy' src='https://cdn.robotaset.com/assets/images/social-media/" + platform + "-login-rounded-btn.png' width='24' height='24' alt='" + platform + "'>" +
                    "</button>" +
                    "</div>";

				socialMediaButtonsContainer.insertAdjacentHTML("beforeend", buttonHtml);
            }
        });
    }

    // Call the function to render login buttons on page load
    renderLoginButtons();

</script>



    <script>
        function loginWithSocial(platform) {
            const url = "/v2/api/account/login/"+platform+"?d="+baseUrl();
            // console.log(url)
            window.location.href = url;
        }
    </script>


</div>
						</form>
					</div>
			</div>
		</div>
	</div>
</header>










<nav class="navbar futuristic">
	<div class="container">
		<ul id="gameListMenu">
			<li class="home">
                <a href="/">
                    <i class="icon_home"></i>
                    <strong class="nav_name">Beranda</strong>
                </a>
            </li>
			
				
					
					
					
					
					
	
					<li class="sports">
					    <a href="/game-group/sports">
					    	<i class="icon_sports"></i>
					        <strong class="nav_name ">Sports</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
													
														
													
													
												
											

							                <li class="game  sbo">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/sbo/1?portofolio=sbosb" class="game-front-type" data-url="/game/sbo/1?portofolio=sbosb" data-provider="sbo">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											

							                <li class="game  cmd">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/play/cmd" class="game-front-type" data-url="/play/cmd" data-provider="cmd">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											

							                <li class="game  sba">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/play/sba" class="game-front-type" data-url="/play/sba" data-provider="sba">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											

							                <li class="game  sng">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/play/sng" class="game-front-type" data-url="/play/sng" data-provider="sng">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
				
					
					
					
					
					
	
					<li class="casino">
					    <a href="/game-group/casino">
					    	<i class="icon_casino"></i>
					        <strong class="nav_name ">Casino</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pgr">
								                
								                	<span class="label-new">Promo</span>
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pgr/2" class="game-front-type" data-url="/game/pgr/2" data-provider="pgr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ggs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                	<span class="label-new label-new-top-right blink">Baru</span>
									                
									                
									                
									                	<img loading="lazy" src="https://cdn.robotaset.com/assets/images/provider/new-tag.png" alt="new-tag.png" class="lobby-icon game-front-tag">
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ggs/2" class="game-front-type" data-url="/game/ggs/2" data-provider="ggs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ptc">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ptc/2" class="game-front-type" data-url="/game/ptc/2" data-provider="ptc">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub wm">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/wm/2" class="game-front-type" data-url="/game/wm/2" data-provider="wm">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub sbc">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/sbc/2" class="game-front-type" data-url="/game/sbc/2" data-provider="sbc">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mcg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mcg/2" class="game-front-type" data-url="/game/mcg/2" data-provider="mcg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub gpi">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/gpi/2" class="game-front-type" data-url="/game/gpi/2" data-provider="gpi">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub prt">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/prt/2" class="game-front-type" data-url="/game/prt/2" data-provider="prt">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub plk">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/plk/2" class="game-front-type" data-url="/game/plk/2" data-provider="plk">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub bgg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/bgg/2" class="game-front-type" data-url="/game/bgg/2" data-provider="bgg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ttg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ttg/2" class="game-front-type" data-url="/game/ttg/2" data-provider="ttg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub bpt">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/bpt/2" class="game-front-type" data-url="/game/bpt/2" data-provider="bpt">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jli">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jli/2" class="game-front-type" data-url="/game/jli/2" data-provider="jli">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub sag">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/sag/2" class="game-front-type" data-url="/game/sag/2" data-provider="sag">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ori">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ori/2" class="game-front-type" data-url="/game/ori/2" data-provider="ori">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mrb">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mrb/2" class="game-front-type" data-url="/game/mrb/2" data-provider="mrb">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub eai">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/eai/2" class="game-front-type" data-url="/game/eai/2" data-provider="eai">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
					    
					        
					        
					        
					
					        <li class="btn-game" data-url="/play/ftp/vs10swtbnz" style="position:relative;">
					            <img src="https://cdn.robotaset.com/assets/images/common/tag/promo.gif" style="position:absolute;z-index:1;left:0;width:35px;top:5;">
					            
					            <a href="#" aria-label='Main Sekarang - Sweet Bonanza POP' title='Main Sekarang - Sweet Bonanza POP'>
					                <i class="icon_scatter" aria-hidden="true"></i>
					                <strong class="nav_name">Sweet Bonanza POP</strong>
					            </a>
					            <script>
					                if( $('.icon_scatter').length == 1 ) {
					                    $('.icon_scatter').css({
					                        'background-position': 'center 15px',
					                        'background-image': 'url(https://cdn.robotaset.com/assets/images/provider/pp-pop-slot2.gif?d=1)',
					                        'background-repeat': 'no-repeat',
					                        'background-size': '90%'
					                    });
					
					                    // For !important, you need to use plain JavaScript since jQuery's .css() doesn't support !important
					                    $('.icon_scatter').each(function() {
					                        this.style.setProperty('background-image', 'url(https://cdn.robotaset.com/assets/images/provider/pp-pop-slot2.gif?d=1)', 'important');
					                        this.setAttribute('role', 'img');
					                        this.setAttribute('aria-label', 'Sweet Bonanza POP');
					                    });
					
					                    $('.navbar > .container').css({'max-width':'1400px'});
					                }
					            </script>
					        </li>
					    
					
				
			
				
					
					
					
					
					
	
					<li class="slot">
					    <a href="/game-group/slot">
					    	<i class="icon_slot"></i>
					        <strong class="nav_name ">Slot</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pgr">
								                
								                	<span class="label-new">Promo</span>
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                	<img loading="lazy" src="https://cdn.robotaset.com/assets/images/provider/pgr-no1.png" alt="pgr-no1.png" class="lobby-icon game-front-tag">
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pgr/3" class="game-front-type" data-url="/game/pgr/3" data-provider="pgr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ggs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                	<span class="label-new label-new-top-right blink">Baru</span>
									                
									                
									                
									                	<img loading="lazy" src="https://cdn.robotaset.com/assets/images/provider/new-tag.png" alt="new-tag.png" class="lobby-icon game-front-tag">
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ggs/3" class="game-front-type" data-url="/game/ggs/3" data-provider="ggs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pgs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                	<img loading="lazy" src="https://cdn.robotaset.com/assets/images/provider/best-tag.png" alt="best-tag.png" class="lobby-icon game-front-tag">
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pgs/3" class="game-front-type" data-url="/game/pgs/3" data-provider="pgs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ftp">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ftp/3" class="game-front-type" data-url="/game/ftp/3" data-provider="ftp">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub aag">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/aag/3" class="game-front-type" data-url="/game/aag/3" data-provider="aag">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ptc">
								                
							                	<div class="icon-menu-wrapper">
													
													
													    
													    
													    

													    <div class="provider-event-ptc">
													    	<span class="btn-game" data-id="gpas_gtr10k_pop" data-url="/play/ptc/gpas_gtr10k_pop">
														        <img class="event-avatar" src="https://cdn.robotaset.com/assets/images/provider/ptc-event.webp" alt="Gold Trio 10000">
													    	</span>
													    </div>
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ptc/3" class="game-front-type" data-url="/game/ptc/3" data-provider="ptc">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ptg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ptg/3" class="game-front-type" data-url="/game/ptg/3" data-provider="ptg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub fvg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/fvg/3" class="game-front-type" data-url="/game/fvg/3" data-provider="fvg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mcg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mcg/3" class="game-front-type" data-url="/game/mcg/3" data-provider="mcg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jli">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jli/3" class="game-front-type" data-url="/game/jli/3" data-provider="jli">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub adv">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/adv/3" class="game-front-type" data-url="/game/adv/3" data-provider="adv">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ttg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ttg/3" class="game-front-type" data-url="/game/ttg/3" data-provider="ttg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub spd">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/spd/3" class="game-front-type" data-url="/game/spd/3" data-provider="spd">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub hb">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/hb/3" class="game-front-type" data-url="/game/hb/3" data-provider="hb">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jkr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jkr/3" class="game-front-type" data-url="/game/jkr/3" data-provider="jkr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pst">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pst/3" class="game-front-type" data-url="/game/pst/3" data-provider="pst">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub cqn">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/cqn/3" class="game-front-type" data-url="/game/cqn/3" data-provider="cqn">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub bng">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/bng/3" class="game-front-type" data-url="/game/bng/3" data-provider="bng">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub sll">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/sll/3" class="game-front-type" data-url="/game/sll/3" data-provider="sll">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mmg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mmg/3" class="game-front-type" data-url="/game/mmg/3" data-provider="mmg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub fch">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/fch/3" class="game-front-type" data-url="/game/fch/3" data-provider="fch">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub evo">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/evo/3" class="game-front-type" data-url="/game/evo/3" data-provider="evo">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub bpt">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/bpt/3" class="game-front-type" data-url="/game/bpt/3" data-provider="bpt">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ygg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ygg/3" class="game-front-type" data-url="/game/ygg/3" data-provider="ygg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub dgs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/dgs/3" class="game-front-type" data-url="/game/dgs/3" data-provider="dgs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub hsg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/hsg/3" class="game-front-type" data-url="/game/hsg/3" data-provider="hsg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mll">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mll/3" class="game-front-type" data-url="/game/mll/3" data-provider="mll">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub plk">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/plk/3" class="game-front-type" data-url="/game/plk/3" data-provider="plk">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ygr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ygr/3" class="game-front-type" data-url="/game/ygr/3" data-provider="ygr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
				
					
					
					
					
					
	
					<li class="lottery">
					    <a href="/game-group/lottery">
					    	<i class="icon_lottery"></i>
					        <strong class="nav_name blink">Togel</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ifd">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ifd/5" class="game-front-type" data-url="/game/ifd/5" data-provider="ifd">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pgr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pgr/5" class="game-front-type" data-url="/game/pgr/5" data-provider="pgr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub eai">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/eai/5" class="game-front-type" data-url="/game/eai/5" data-provider="eai">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
				
			
				
			
				
					
					
					
					
					
	
					<li class="cock_fighting">
					    <a href="/game-group/cock_fighting">
					    	<i class="icon_cock_fighting"></i>
					        <strong class="nav_name ">Sabung Ayam</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											

							                <li class="game  wsl">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/play/wsl" class="game-front-type" data-url="/play/wsl" data-provider="wsl">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											

							                <li class="game  awc">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/play/awc" class="game-front-type" data-url="/play/awc" data-provider="awc">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
				
					
					
					
					
					
	
					<li class="games">
					    <a href="/game-group/games">
					    	<i class="icon_games"></i>
					        <strong class="nav_name ">Games</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub pgr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/pgr/8" class="game-front-type" data-url="/game/pgr/8" data-provider="pgr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ggs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                	<span class="label-new label-new-top-right blink">Baru</span>
									                
									                
									                
									                	<img loading="lazy" src="https://cdn.robotaset.com/assets/images/provider/new-tag.png" alt="new-tag.png" class="lobby-icon game-front-tag">
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ggs/8" class="game-front-type" data-url="/game/ggs/8" data-provider="ggs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ttg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ttg/8" class="game-front-type" data-url="/game/ttg/8" data-provider="ttg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
													
													
												
											

							                <li class="game sub sbo">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/sbo/8?portofolio=sbovg" class="game-front-type" data-url="/game/sbo/8?portofolio=sbovg" data-provider="sbo">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub plk">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/plk/8" class="game-front-type" data-url="/game/plk/8" data-provider="plk">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jkr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jkr/8" class="game-front-type" data-url="/game/jkr/8" data-provider="jkr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub dgs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/dgs/8" class="game-front-type" data-url="/game/dgs/8" data-provider="dgs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mll">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mll/8" class="game-front-type" data-url="/game/mll/8" data-provider="mll">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub hsg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/hsg/8" class="game-front-type" data-url="/game/hsg/8" data-provider="hsg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub fch">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/fch/8" class="game-front-type" data-url="/game/fch/8" data-provider="fch">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jli">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jli/8" class="game-front-type" data-url="/game/jli/8" data-provider="jli">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mmg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mmg/8" class="game-front-type" data-url="/game/mmg/8" data-provider="mmg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
				
					
					
					
					
					
	
					<li class="tembak_ikan">
					    <a href="/game-group/tembak_ikan">
					    	<i class="icon_tembak_ikan"></i>
					        <strong class="nav_name ">Tembak Ikan</strong>
					    </a>
					    <div class="subnavbar" data-item="ckGame">
					        <div class="main_width container">
					            <ul class="gameNav clearfix">
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub spd">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/spd/4" class="game-front-type" data-url="/game/spd/4" data-provider="spd">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jkr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jkr/4" class="game-front-type" data-url="/game/jkr/4" data-provider="jkr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub ygr">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/ygr/4" class="game-front-type" data-url="/game/ygr/4" data-provider="ygr">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub mcg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/mcg/4" class="game-front-type" data-url="/game/mcg/4" data-provider="mcg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub jli">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/jli/4" class="game-front-type" data-url="/game/jli/4" data-provider="jli">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub dgs">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/dgs/4" class="game-front-type" data-url="/game/dgs/4" data-provider="dgs">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub hsg">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/hsg/4" class="game-front-type" data-url="/game/hsg/4" data-provider="hsg">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
										
											
											
											

											
											
											
												
												
											

							                <li class="game sub fch">
								                
							                	<div class="icon-menu-wrapper">
													
													
									                
									                
									                
									                
									                
							                		<div class="game-front"></div>
								                    <a data-href="/game/fch/4" class="game-front-type" data-url="/game/fch/4" data-provider="fch">
								                    	<span>Main Sekarang</span>
								                    </a>
							                	</div>
							                </li>
										
									
					            </ul>
					        </div>
					    </div>
					</li>
					
				
			
			<li>
                <a href="/promotion">
                    <i class="icon_promo"></i>
                    <strong class="nav_name">Promosi</strong>
                </a>
            </li>
			<li class="referral">
			    <a href="/referral">
			        <i class="icon_referral" aria-hidden="true"></i>
			        <strong class="nav_name">Referral</strong>
			    </a>
			</li>
			
		</ul>
	</div>
</nav>
<div class="home-slider-wrapper">
        <div class="home-slider owl-carousel owl-theme">
                <div class="item">
                        <a href="/promotion/cashback-100" aria-label="CASHBACK 100%"><img fetchpriority="high" decoding="async" src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/main-cashback-100-vio.jpg" alt="CASHBACK 100%">
                        </a></div>
                <div class="item">
                        <a href="/promotion/super-scatter" aria-label="SUPER SCATTER"><img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/main-super-scatter-vio.jpg" alt="SUPER SCATTER">
                        </a></div>
                <div class="item">
                        <a href="/promotion/event-gg-soft-vio77" aria-label="BONUS GGSOFT"><img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/bonus-gg-soft.jpg" alt="BONUS GGSOFT">
                        </a></div>
                <div class="item">
                        <a href="https://t.ly/pintuspy" aria-label="PARTNERSHIP"><img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/OFFICIAL-PS.jpg" alt="PARTNERSHIP">
                        </a></div>
                <div class="item">
                        <img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/VIP.jpg" alt="AKUN VIP PRO">
                        </div>
                <div class="item">
                        <img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/MOBILE-APK.jpg" alt="APK">
                        </div>
                <div class="item">
                        <img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/mahjong-wins-3.jpg" alt="BONUS SCATTER MAHJONG 3">
                        </div>
                <div class="item">
                        <a href="https://t.ly/pintuspy" aria-label="QRIS"><img decoding="async" class="owl-lazy" data-src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/qris.jpg" alt="QRIS">
                        </a></div>
                </div>
    </div>
    <script>
        $(document).ready(function() {
            var owl = $('.home-slider');
            owl.owlCarousel({
                items: 1,
                lazyLoad: true,
                nav: true,
                loop: true,
                margin: 10,
                autoplay: true,
                autoplayTimeout: 8000,
                autoHeight: true
            });
            owl.find('.owl-dot').each(function (index) {
                const slideNumber = index + 1;
                $(this).attr('aria-label', 'Ke slide ' + slideNumber);
                // Optional: Tambahkan aria-current ke tombol aktif
                if ($(this).hasClass('active')) {
                    $(this).attr('aria-current', 'true');
                }
            });
        })
    </script>
<section id="poolnumberresult" class="py-xxl-4 pool-result-wrapper">
    <div class="container">
        <div class="pool-list-results owl-carousel owl-theme" id="latestPool"></div>
    </div>

    <div class="modal fade" id="poolHistoryModal" tabindex="-1" role="dialog" aria-hidden="true" style="display:none">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Hasil Keluaran</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <section class="bg-dark-transparent">
                        <div class="container">
                            <div class="rounded py-1">
                                <div>
                                    <span class="text-warning text-uppercase" id="mdlPoolCode"></span>
                                </div>
                                <table class="table table-dark" id="mdlPoolHistory">
                                    <thead>
                                        <tr>
                                            <th scope="col" style="text-transform: capitalize;">Hari</th>
                                            <th scope="col">Tanggal</th>
                                            <th scope="col">Periode</th>
                                            <th scope="col">Hasil</th>
                                        </tr>
                                    </thead>
                                    <tbody></tbody>
                                </table>
                            </div>
                        </div>
                    </section>
                </div>
            </div>
        </div>
    </div>
	
	<script>
		var POOL_DATA = [];
		function poolLatestNumber(data) {
		    $.each(data, function (i, row) {
		        var $latestPool = $(document).find("#latestPool");
		        var poolName = row.label === "sg" ? "Singapore" : row.label;
		        $latestPool.append(
		            '<div class="item"><div class="px-xxl-1">' +
		                '<a class="box-pull" href="#" data-toggle="modal" data-target="#poolHistoryModal" data-poolcd="' +
		                row.label +
		                '">' +
		                '<div class="text-center">' +
		                '<div class="pull-head pt-1 text-uppercase">' +
		                "<span>" +
		                poolName +
		                "</span>" +
		                "</div>" +
		                '<div class="pull-body d-flex align-items-center justify-content-center"><span class="blink">' +
		                row.number +
		                "</span></div>" +
		                '<div class="pull-foot text-dark px-1">' +
		                row.day +
		                ", " +
		                row.humanDate +
		                "</div>" +
		                "</div>" +
		                "</a>" +
		                "</div></div>"
		        );
		    });
		}
		
		function poolHistoryNumber(data) {
		    var $tbody = $(document).find("#mdlPoolHistory tbody");
		    $.each(data, function (i, row) {
		        $tbody.append("<tr>" + "<td>" + row.day + "</td>" + "<td>" + row.humanDate + "</td>" + "<td>" + row.shift + "</td>" + "<td>" + row.number + "</td>" + "</tr>");
		    });
		}
		
		$(function () {
		    var lang = "id";
		    var poolApi = "https://widget.robotaset.com";
		    var agentCode = "0tnG3roIM3vxATE7NHCj7A==";
		
		    $.ajax({
		        async: true,
 		        url: poolApi + "/pool/latest?lang=" + lang + "&code="+agentCode,
		        type: "GET",
		        contentType: "json",
		    }).then(function (data) {
		    	POOL_DATA = data;
		        poolLatestNumber(data);
		        renderCarousel();
		        //$('.pool-list-results').find('.owl-nav').removeClass('disabled');
		    });

			// modal
		    $("#poolHistoryModal").on("show.bs.modal", function (event) {
		        var button = $(event.relatedTarget);
		        var poolCode = button.data("poolcd");
		        var poolText = poolCode == 'sg' ? 'Singapore' : poolCode;
		        var modal = $(this);
		        modal.find("#mdlPoolCode").text(poolText);
		        var $tbody = $(document).find("#mdlPoolHistory tbody");
		        $tbody.empty();
		
		        $.ajax({
		            async: true,
		            url: poolApi + "/pool/history?pool=" + poolCode + "&lang=" + lang,
		        }).then(function (data) {
		            poolHistoryNumber(data);
		        });

		        
		    })

		    

			// carousel
			function renderCarousel() {
				var poolRes = $(".pool-list-results");
				var activeItem = $('#poolnumberresult').find('.owl-item.active').length;
				var responsiveConfig = {
					200: {items: 2, loop: POOL_DATA.length > 2 ? true : false},
					300: {items: 2, loop: POOL_DATA.length > 2 ? true : false},
					400: {items: 3, loop: POOL_DATA.length > 3 ? true : false},
					500: {items: 3, loop: POOL_DATA.length > 3 ? true : false},
					600: {items: 4, loop: POOL_DATA.length > 4 ? true : false},
					700: {items: 5, loop: POOL_DATA.length > 5 ? true : false},
					800: {items: 6, loop: POOL_DATA.length > 6 ? true : false},
					900: {items: 7, loop: POOL_DATA.length > 7 ? true : false},
					1000: {items: 7, loop: POOL_DATA.length > 7 ? true : false}
				};
				poolRes.owlCarousel({
					nav: false,
					lazyLoad: true,
					dots: true,
					margin: 8,
					items: 7,
					autoplay: true,
					autoplayTimeout: 10000,
					responsiveClass: true,
					responsive: responsiveConfig
				});
			}
		});
	</script>
</section><main class="middle middle-index">
    <div class="container">
        <div class="progressive-jackpot">
            <p class="h2">Progressive Jackpot</p>
            <div class="jackpot-wrapper">
                <img loading="lazy" fetchpriority="high" src="https://cdn.robotaset.com/assets/tpl/e360fd1668/images/progressive-jackpot.gif" alt="Progressive Jackpot">
                <span id="jackpot" data-value="17936259943.42">17.936.259.943,42</span>
            </div>
        </div>

        <div class="mini-banner owl-carousel owl-theme">
            <div class="item box-middle">
                            <a href="https://vio77luck.com" aria-label="Banner Left"><img loading="lazy" src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/data-bank.jpg" alt="Banner Left"></a></div>
                <div class="item box-middle">
                            <img loading="lazy" src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/EXTRASPIN.jpg" alt="Banner Center"></div>
                <div class="item box-middle">
                            <img loading="lazy" src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/RTP.jpg" alt="Banner Right"></div>
                </div>
        <script>
            $(document).ready(function () {
                var owl = $('.mini-banner');
                owl.owlCarousel({
                    items: 3,
                    lazyLoad: true,
                    nav: false,
                    loop: false,
                    mouseDrag: false
                });
            })
        </script>
        <div class="row">
            <div id="SupportedBank">
                <div class="col-2 bank" role="img" aria-label="">
                    <div class="qris"></div>
                </div>
                <div class="col-2 bank">
                        <div class="bca"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="mandiri"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="cimb"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="bni"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="bri"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="danamon"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="permata"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="ovo"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="gopay"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="xl"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="simpati"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="dana"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="panin"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="linkaja"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="sakuku"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="bsi"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="tri"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="jenius"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="neo"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="jago"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="sinarmas"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="allo"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="indosat"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="blu"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="seabank"><span class="indicator on"></span></div>
                    </div>
                <div class="col-2 bank">
                        <div class="ocbc"><span class="indicator on"></span></div>
                    </div>
                </div>
        </div>
    </div>
</main>
<footer class="footer">
	<div class="container">
		<div class="wrap-provider-list">
			<ul id="ProviderList"></ul>
			<script>
				var a = [{"idgmfr":1,"gmfrnm":"Sports","gmfricon":"sports","pvls":[{"id":16,"pvnm":"SBO","pvst":1,"pvsub":1,"pvicon":"sbo","pvcode":"SBO","pvmtfrom":"20-07-2020 07:45:00","pvmtto":"31-07-2026 12:50:00","ism":1,"portofolio":"sbosb"},{"id":21,"pvnm":"Cmd","pvst":1,"pvsub":0,"pvicon":"cmd","pvcode":"CMD","pvmtfrom":"20-08-2021 12:15:00","pvmtto":"20-08-2021 15:00:00","ism":1,"portofolio":"cmd"},{"id":175,"pvnm":"Saba sports","pvst":1,"pvsub":0,"pvicon":"sba","pvcode":"SBA","pvmtfrom":"20-08-2020 10:00:00","pvmtto":"13-08-2026 19:00:00","ism":1,"portofolio":"sba"},{"id":446,"pvnm":"3sing sport","pvst":1,"pvsub":0,"pvicon":"sng","pvcode":"SNG","pvmtfrom":"13-08-2026 12:00:00","pvmtto":"13-08-2026 15:00:00","ism":1,"portofolio":"sngsport"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":3},{"idgmfr":2,"gmfrnm":"Casino","gmfricon":"casino","pvls":[{"id":4,"pvnm":"Pragmatic Play","pvst":1,"pvsub":1,"pvicon":"pgr","pvcode":"PGR","pvmtfrom":"20-07-2020 23:00:00","pvmtto":"20-05-2001 09:00:00","ism":1,"portofolio":"lvc"},{"id":1075,"pvnm":"GG Soft","pvst":1,"pvsub":1,"pvicon":"ggs","pvcode":"GGS","pvmtfrom":"20-07-2010 04:00:00","pvmtto":"20-07-2010 04:55:00","ism":1,"portofolio":"ggscasino"},{"id":710,"pvnm":"Playtech","pvst":1,"pvsub":1,"pvicon":"ptc","pvcode":"PTC","pvmtfrom":"22-01-2026 13:30:00","pvmtto":"07-06-2026 02:00:00","ism":1,"portofolio":"ptclc"},{"id":10,"pvnm":"Wanmei","pvst":1,"pvsub":1,"pvicon":"wm","pvcode":"WM","pvmtfrom":"10-08-2026 09:00:00","pvmtto":"10-08-2026 12:30:00","ism":1,"portofolio":"livecasino"},{"id":27,"pvnm":"Sexy baccarat","pvst":1,"pvsub":1,"pvicon":"sbc","pvcode":"SBC","pvmtfrom":"12-08-2026 08:00:00","pvmtto":"19-08-2026 08:00:00","ism":1,"portofolio":"sbc"},{"id":137,"pvnm":"Micro gaming","pvst":1,"pvsub":1,"pvicon":"mcg","pvcode":"MCG","pvmtfrom":"20-08-2026 10:50:00","pvmtto":"20-08-2026 12:00:00","ism":1,"portofolio":"mcgnlc"},{"id":6,"pvnm":"Gameplay","pvst":1,"pvsub":1,"pvicon":"gpi","pvcode":"GPI","pvmtfrom":"20-07-2020 04:00:00","pvmtto":"20-07-2022 23:00:00","ism":1,"portofolio":"lc"},{"id":171,"pvnm":"Pretty gaming","pvst":1,"pvsub":1,"pvicon":"prt","pvcode":"PRT","pvmtfrom":"26-02-2024 23:00:00","pvmtto":"27-03-2025 22:00:00","ism":1,"portofolio":"prtlive"},{"id":743,"pvnm":"Mini.game","pvst":1,"pvsub":1,"pvicon":"plk","pvcode":"PLK","pvmtfrom":"20-07-2026 09:00:00","pvmtto":"20-07-2026 11:00:00","ism":1,"portofolio":"plkgm"},{"id":103,"pvnm":"Big gaming","pvst":1,"pvsub":1,"pvicon":"bgg","pvcode":"BGG","pvmtfrom":"18-08-2026 03:00:00","pvmtto":"18-08-2026 04:00:00","ism":1,"portofolio":"bgglive"},{"id":97,"pvnm":"Top trend game","pvst":1,"pvsub":1,"pvicon":"ttg","pvcode":"TTG","pvmtfrom":"20-10-2020 18:00:00","pvmtto":"11-11-2028 23:00:00","ism":1,"portofolio":"swinttlivettg"},{"id":380,"pvnm":"Bigpot gaming ","pvst":1,"pvsub":1,"pvicon":"bpt","pvcode":"BPT","pvmtfrom":"20-07-2020 05:00:00","pvmtto":"20-07-2019 03:00:00","ism":1,"portofolio":"bptlc"},{"id":314,"pvnm":"Jili gaming","pvst":1,"pvsub":1,"pvicon":"jli","pvcode":"JLI","pvmtfrom":"11-11-2025 11:30:00","pvmtto":"12-08-2026 11:25:00","ism":1,"portofolio":"jlilc"},{"id":1042,"pvnm":"SA Gaming","pvst":1,"pvsub":1,"pvicon":"sag","pvcode":"SAG","pvmtfrom":"27-05-2026 19:00:00","pvmtto":"27-05-2026 20:30:00","ism":1,"portofolio":"saglc"},{"id":62,"pvnm":"Oriental gaming","pvst":1,"pvsub":1,"pvicon":"ori","pvcode":"ORI","pvmtfrom":"11-08-2026 12:00:00","pvmtto":"11-08-2026 15:00:00","ism":1,"portofolio":"neworilc"},{"id":1108,"pvnm":"MarbleX","pvst":1,"pvsub":1,"pvicon":"mrb","pvcode":"MRB","pvmtfrom":"11-08-2025 20:00:00","pvmtto":"26-08-2026 13:50:00","ism":1,"portofolio":"mrbslot"},{"id":1141,"pvnm":"EEAI","pvst":1,"pvsub":1,"pvicon":"EAI","pvcode":"EAI","pvmtfrom":"-","pvmtto":"-","ism":1,"portofolio":"eairoul"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":2},{"idgmfr":3,"gmfrnm":"Slot","gmfricon":"slot","pvls":[{"id":4,"pvnm":"Pragmatic Play","pvst":1,"pvsub":1,"pvicon":"pgr","pvcode":"PGR","pvmtfrom":"20-07-2020 23:00:00","pvmtto":"20-05-2001 09:00:00","ism":1,"portofolio":"vs"},{"id":1075,"pvnm":"GG Soft","pvst":1,"pvsub":1,"pvicon":"ggs","pvcode":"GGS","pvmtfrom":"20-07-2010 04:00:00","pvmtto":"20-07-2010 04:55:00","ism":1,"portofolio":"ggsslot"},{"id":26,"pvnm":"Pg soft","pvst":1,"pvsub":1,"pvicon":"pgs","pvcode":"PGS","pvmtfrom":"20-03-2020 00:00:00","pvmtto":"11-08-2026 14:10:00","ism":1,"portofolio":"pgs"},{"id":842,"pvnm":"Pragmatic Play POP","pvst":1,"pvsub":1,"pvicon":"ftp","pvcode":"FTP","pvmtfrom":"-","pvmtto":"09-09-2025 08:00:00","ism":1,"portofolio":"ftpslot"},{"id":1174,"pvnm":"AA Gaming","pvst":1,"pvsub":1,"pvicon":"AAG","pvcode":"AAG","pvmtfrom":"-","pvmtto":"-","ism":1,"portofolio":"aagslot"},{"id":710,"pvnm":"Playtech","pvst":1,"pvsub":1,"pvicon":"ptc","pvcode":"PTC","pvmtfrom":"22-01-2026 13:30:00","pvmtto":"07-06-2026 02:00:00","ism":1,"portofolio":"ptcslot"},{"id":545,"pvnm":"Pt games","pvst":1,"pvsub":1,"pvicon":"ptg","pvcode":"PTG","pvmtfrom":"20-11-2001 00:00:00","pvmtto":"20-12-2030 00:00:00","ism":1,"portofolio":"ptgslot"},{"id":875,"pvnm":"5g","pvst":1,"pvsub":1,"pvicon":"fvg","pvcode":"FVG","pvmtfrom":"20-07-2008 05:00:00","pvmtto":"08-07-2026 12:00:00","ism":1,"portofolio":"fvgslot"},{"id":137,"pvnm":"Micro gaming","pvst":1,"pvsub":1,"pvicon":"mcg","pvcode":"MCG","pvmtfrom":"20-08-2026 10:50:00","pvmtto":"20-08-2026 12:00:00","ism":1,"portofolio":"mcgslot"},{"id":314,"pvnm":"Jili gaming","pvst":1,"pvsub":1,"pvicon":"jli","pvcode":"JLI","pvmtfrom":"11-11-2025 11:30:00","pvmtto":"12-08-2026 11:25:00","ism":1,"portofolio":"jlislot"},{"id":248,"pvnm":"Advantplay","pvst":1,"pvsub":1,"pvicon":"adv","pvcode":"ADV","pvmtfrom":"21-08-2025 13:00:00","pvmtto":"21-08-2025 14:00:00","ism":1,"portofolio":"advslot"},{"id":97,"pvnm":"Top trend game","pvst":1,"pvsub":1,"pvicon":"ttg","pvcode":"TTG","pvmtfrom":"20-10-2020 18:00:00","pvmtto":"11-11-2028 23:00:00","ism":1,"portofolio":"ttgslot"},{"id":15,"pvnm":"Spade gaming","pvst":1,"pvsub":1,"pvicon":"spd","pvcode":"SPD","pvmtfrom":"20-05-2019 08:30:00","pvmtto":"21-07-2026 11:00:00","ism":1,"portofolio":"slt"},{"id":8,"pvnm":"Habanero","pvst":1,"pvsub":1,"pvicon":"hb","pvcode":"HB","pvmtfrom":"12-06-2024 03:50:00","pvmtto":"12-06-2024 10:00:00","ism":1,"portofolio":"11"},{"id":18,"pvnm":"Joker","pvst":1,"pvsub":1,"pvicon":"jkr","pvcode":"JKR","pvmtfrom":"20-01-2015 04:00:00","pvmtto":"31-12-2026 23:55:55","ism":1,"portofolio":"slt"},{"id":61,"pvnm":"Playstar gaming","pvst":1,"pvsub":1,"pvicon":"pst","pvcode":"PST","pvmtfrom":"03-08-2026 09:00:00","pvmtto":"03-08-2026 11:00:00","ism":1,"portofolio":"pstslot"},{"id":102,"pvnm":"Cq9","pvst":1,"pvsub":1,"pvicon":"cqn","pvcode":"CQN","pvmtfrom":"20-07-2029 03:00:00","pvmtto":"29-07-2026 09:15:00","ism":1,"portofolio":"cqnslot"},{"id":138,"pvnm":"Bng","pvst":1,"pvsub":1,"pvicon":"bng","pvcode":"BNG","pvmtfrom":"20-02-2021 05:35:00","pvmtto":"18-06-2026 17:45:00","ism":1,"portofolio":"bngslot"},{"id":136,"pvnm":"Slot88","pvst":1,"pvsub":1,"pvicon":"sll","pvcode":"SLL","pvmtfrom":"08-04-2025 12:51:00","pvmtto":"31-01-2035 13:00:00","ism":1,"portofolio":"sllslot"},{"id":176,"pvnm":"Mimi gaming","pvst":1,"pvsub":1,"pvicon":"mmg","pvcode":"MMG","pvmtfrom":"01-05-2025 08:00:00","pvmtto":"01-05-2025 09:00:00","ism":1,"portofolio":"mmgslot"},{"id":181,"pvnm":"Fachai","pvst":1,"pvsub":1,"pvicon":"fch","pvcode":"FCH","pvmtfrom":"27-01-2026 02:00:00","pvmtto":"20-05-2026 05:15:00","ism":1,"portofolio":"fchslot"},{"id":347,"pvnm":"No limit city","pvst":1,"pvsub":1,"pvicon":"evo","pvcode":"EVO","pvmtfrom":"20-04-2009 11:52:00","pvmtto":"10-04-2026 17:15:00","ism":1,"portofolio":"evoslot"},{"id":380,"pvnm":"Bigpot gaming ","pvst":1,"pvsub":1,"pvicon":"bpt","pvcode":"BPT","pvmtfrom":"20-07-2020 05:00:00","pvmtto":"20-07-2019 03:00:00","ism":1,"portofolio":"bptslot"},{"id":215,"pvnm":"Yggdrasil gaming","pvst":1,"pvsub":1,"pvicon":"ygg","pvcode":"YGG","pvmtfrom":"30-07-2026 05:00:00","pvmtto":"30-07-2026 08:30:00","ism":1,"portofolio":"yggslot"},{"id":413,"pvnm":"Dragoon soft","pvst":1,"pvsub":1,"pvicon":"dgs","pvcode":"DGS","pvmtfrom":"23-07-2026 08:00:00","pvmtto":"23-07-2026 11:00:00","ism":1,"portofolio":"dgsslot"},{"id":611,"pvnm":"Hacksaw gaming","pvst":1,"pvsub":1,"pvicon":"hsg","pvcode":"HSG","pvmtfrom":"20-07-2004 22:00:00","pvmtto":"26-01-2026 20:30:00","ism":1,"portofolio":"hsgslot"},{"id":677,"pvnm":"Mega888","pvst":1,"pvsub":1,"pvicon":"mll","pvcode":"MLL","pvmtfrom":"26-01-2026 14:30:00","pvmtto":"28-05-2026 03:20:00","ism":1,"portofolio":"mllslot"},{"id":743,"pvnm":"Mini.game","pvst":1,"pvsub":1,"pvicon":"plk","pvcode":"PLK","pvmtfrom":"20-07-2026 09:00:00","pvmtto":"20-07-2026 11:00:00","ism":1,"portofolio":"plkgm"},{"id":1207,"pvnm":"YGR Gaming","pvst":1,"pvsub":1,"pvicon":"YGR","pvcode":"YGR","pvmtfrom":"-","pvmtto":"-","ism":1,"portofolio":"ygrslot"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":1},{"idgmfr":5,"gmfrnm":"Togel","gmfricon":"lottery","pvls":[{"id":179,"pvnm":"Infini4d","pvst":1,"pvsub":1,"pvicon":"ifd","pvcode":"IFD","pvmtfrom":"20-04-2020 01:00:00","pvmtto":"12-06-2026 19:30:00","ism":1,"portofolio":"DEF"},{"id":4,"pvnm":"Pragmatic Play","pvst":1,"pvsub":1,"pvicon":"pgr","pvcode":"PGR","pvmtfrom":"20-07-2020 23:00:00","pvmtto":"20-05-2001 09:00:00","ism":1,"portofolio":"sc"},{"id":1141,"pvnm":"EEAI","pvst":1,"pvsub":1,"pvicon":"EAI","pvcode":"EAI","pvmtfrom":"-","pvmtto":"-","ism":1,"portofolio":"eailuck"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":0},{"idgmfr":6,"gmfrnm":"Poker","gmfricon":"poker","pvls":[],"hideFromMobile":true,"gameGroupDisabled":false,"ordering":6},{"idgmfr":7,"gmfrnm":"Racing","gmfricon":"racing","pvls":[],"hideFromMobile":true,"gameGroupDisabled":false,"ordering":6},{"idgmfr":9,"gmfrnm":"Sabung Ayam","gmfricon":"cock_fighting","pvls":[{"id":645,"pvnm":"Ws168","pvst":1,"pvsub":0,"pvicon":"wsl","pvcode":"WSL","pvmtfrom":"10-08-2026 03:00:00","pvmtto":"10-08-2026 04:30:00","ism":1,"portofolio":"ws168"},{"id":28,"pvnm":"Sv388","pvst":1,"pvsub":0,"pvicon":"awc","pvcode":"AWC","pvmtfrom":"30-07-2026 07:45:00","pvmtto":"30-07-2026 08:00:00","ism":1,"portofolio":"awc"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":4},{"idgmfr":8,"gmfrnm":"Games","gmfricon":"games","pvls":[{"id":4,"pvnm":"Pragmatic Play","pvst":1,"pvsub":1,"pvicon":"pgr","pvcode":"PGR","pvmtfrom":"20-07-2020 23:00:00","pvmtto":"20-05-2001 09:00:00","ism":1,"portofolio":"pl"},{"id":1075,"pvnm":"GG Soft","pvst":1,"pvsub":1,"pvicon":"ggs","pvcode":"GGS","pvmtfrom":"20-07-2010 04:00:00","pvmtto":"20-07-2010 04:55:00","ism":1,"portofolio":"ggsgames"},{"id":97,"pvnm":"Top trend game","pvst":1,"pvsub":1,"pvicon":"ttg","pvcode":"TTG","pvmtfrom":"20-10-2020 18:00:00","pvmtto":"11-11-2028 23:00:00","ism":1,"portofolio":"ttgcard"},{"id":16,"pvnm":"SBO","pvst":1,"pvsub":1,"pvicon":"sbo","pvcode":"SBO","pvmtfrom":"20-07-2020 07:45:00","pvmtto":"31-07-2026 12:50:00","ism":1,"portofolio":"sbovg"},{"id":743,"pvnm":"Mini.game","pvst":1,"pvsub":1,"pvicon":"plk","pvcode":"PLK","pvmtfrom":"20-07-2026 09:00:00","pvmtto":"20-07-2026 11:00:00","ism":1,"portofolio":"plkgm"},{"id":18,"pvnm":"Joker","pvst":1,"pvsub":1,"pvicon":"jkr","pvcode":"JKR","pvmtfrom":"20-01-2015 04:00:00","pvmtto":"31-12-2026 23:55:55","ism":1,"portofolio":"bingo"},{"id":413,"pvnm":"Dragoon soft","pvst":1,"pvsub":1,"pvicon":"dgs","pvcode":"DGS","pvmtfrom":"23-07-2026 08:00:00","pvmtto":"23-07-2026 11:00:00","ism":1,"portofolio":"dgsgames"},{"id":677,"pvnm":"Mega888","pvst":1,"pvsub":1,"pvicon":"mll","pvcode":"MLL","pvmtfrom":"26-01-2026 14:30:00","pvmtto":"28-05-2026 03:20:00","ism":1,"portofolio":"mllgames"},{"id":611,"pvnm":"Hacksaw gaming","pvst":1,"pvsub":1,"pvicon":"hsg","pvcode":"HSG","pvmtfrom":"20-07-2004 22:00:00","pvmtto":"26-01-2026 20:30:00","ism":1,"portofolio":"hsggames"},{"id":181,"pvnm":"Fachai","pvst":1,"pvsub":1,"pvicon":"fch","pvcode":"FCH","pvmtfrom":"27-01-2026 02:00:00","pvmtto":"20-05-2026 05:15:00","ism":1,"portofolio":"fchspecgames"},{"id":314,"pvnm":"Jili gaming","pvst":1,"pvsub":1,"pvicon":"jli","pvcode":"JLI","pvmtfrom":"11-11-2025 11:30:00","pvmtto":"12-08-2026 11:25:00","ism":1,"portofolio":"jligames"},{"id":176,"pvnm":"Mimi gaming","pvst":1,"pvsub":1,"pvicon":"mmg","pvcode":"MMG","pvmtfrom":"01-05-2025 08:00:00","pvmtto":"01-05-2025 09:00:00","ism":1,"portofolio":"mmggame"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":5},{"idgmfr":4,"gmfrnm":"Tembak Ikan","gmfricon":"tembak_ikan","pvls":[{"id":15,"pvnm":"Spade gaming","pvst":1,"pvsub":1,"pvicon":"spd","pvcode":"SPD","pvmtfrom":"20-05-2019 08:30:00","pvmtto":"21-07-2026 11:00:00","ism":1,"portofolio":"fishinggame"},{"id":18,"pvnm":"Joker","pvst":1,"pvsub":1,"pvicon":"jkr","pvcode":"JKR","pvmtfrom":"20-01-2015 04:00:00","pvmtto":"31-12-2026 23:55:55","ism":1,"portofolio":"fhs"},{"id":1207,"pvnm":"YGR Gaming","pvst":1,"pvsub":1,"pvicon":"YGR","pvcode":"YGR","pvmtfrom":"-","pvmtto":"-","ism":1,"portofolio":"fishygr"},{"id":137,"pvnm":"Micro gaming","pvst":1,"pvsub":1,"pvicon":"mcg","pvcode":"MCG","pvmtfrom":"20-08-2026 10:50:00","pvmtto":"20-08-2026 12:00:00","ism":1,"portofolio":"mcgfish"},{"id":314,"pvnm":"Jili gaming","pvst":1,"pvsub":1,"pvicon":"jli","pvcode":"JLI","pvmtfrom":"11-11-2025 11:30:00","pvmtto":"12-08-2026 11:25:00","ism":1,"portofolio":"jlifishing"},{"id":413,"pvnm":"Dragoon soft","pvst":1,"pvsub":1,"pvicon":"dgs","pvcode":"DGS","pvmtfrom":"23-07-2026 08:00:00","pvmtto":"23-07-2026 11:00:00","ism":1,"portofolio":"dgsfish"},{"id":611,"pvnm":"Hacksaw gaming","pvst":1,"pvsub":1,"pvicon":"hsg","pvcode":"HSG","pvmtfrom":"20-07-2004 22:00:00","pvmtto":"26-01-2026 20:30:00","ism":1,"portofolio":"hsgbingo"},{"id":181,"pvnm":"Fachai","pvst":1,"pvsub":1,"pvicon":"fch","pvcode":"FCH","pvmtfrom":"27-01-2026 02:00:00","pvmtto":"20-05-2026 05:15:00","ism":1,"portofolio":"fchfish"}],"hideFromMobile":false,"gameGroupDisabled":false,"ordering":6}];
				var d = $("#ProviderList");
				
				for(var b = 0; b < a.length; b++) {
					var e = a[b];
					
					var pvls = e.pvls;
					if( pvls.length > 0 ) {
						for(var c = 0; c < pvls.length; c++) {
							var f = pvls[c];
							var g = $('li[data-provider="'+ f.id +'"]');
							
							if( g.length == 0 ) {
								var icon = f.pvicon;
								var sub  = f.pvsub;
								var pvcd = f.pvcode.toLowerCase();
								var hassub = sub == 1 ? "sub" : "";
								var url  = sub == 1 ? "/game/" + pvcd + "/" + e.idgmfr : "/play/" + pvcd;
								if( pvcd == "pgr" ) {
									url  = "/game/" + pvcd + "/3";
								}

								
								d.append('<li class="provider '+ hassub +'" data-provider="'+ f.id +'"><a href="'+ url +'" class="'+ icon.toLowerCase() +'" aria-label="'+ f.pvnm +'"></a></li>');
							}
						}
					}
				}

				var _a = d.find("li");
				var _bbnp = [];
				_a.each(function(k, i) {
					var a = $(i).find("a").attr("class");
					if( a == "bbp" || a == "bbn" ) {
						_bbnp.unshift(i);
						$(i).remove();
					}
				});
				_bbnp.forEach((entry) => {
					d.prepend(entry);
				});

				$(document).on('click', '.provider a', function() {
					var target = $(this).attr("data-url");
	
					
						if( $(this).closest("li").hasClass("sub") ) {
							location.href = target;
						} else {
							do_login(target);
							return false;
						}
					
				});
			</script>
		</div>

		<div class="_seo_footer">
						<div class="_seo_footer">
						<script>
$(document).ready(function() {
    // Select the home-slider div and remove specific classes
    $('.home-slider').removeClass('owl-carousel owl-theme owl-loaded owl-drag').html(`
        <div class="netlalala">
            <a href="https://jali.me/linkpastivio" target="_blank">
                <img src="https://barangtupunyokito.sgp1.cdn.digitaloceanspaces.com/vio77/ms/akses-cepat-vio1.jpg" alt="Gambar 4" class="maxmaxmax">
            </a>
            <a href="https://jali.me/spygroup" target="_blank">
                <img src="https://barangtupunyokito.sgp1.cdn.digitaloceanspaces.com/vio77/ms/vio-partnership-co.jpg" alt="Gambar 1" class="maxmaxmax">
            </a>
            <a href="/promotion/event-balap-turnover" target="_blank">
                <img src="https://barangtupunyokito.sgp1.cdn.digitaloceanspaces.com/vio77/ms/promo-win-to-juni-vio.jpg" alt="Gambar 2" class="maxmaxmax">
            </a>
            <a href="/promotion/event-balap-turnover" target="_blank">
                <img src="https://barangtupunyokito.sgp1.cdn.digitaloceanspaces.com/vio77/ms/balap-to-JULI-vio.jpg" alt="Gambar 2" class="maxmaxmax">
            </a>
            <a href="/promotion/cashback-100" target="_blank">
                <img src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/promo-banner-vio77-cashback-100-gg-soft.jpg" alt="Gambar 2" class="maxmaxmax">
            </a>
            <a href="/promotion/upgrade-member-vip-vio77" target="_blank">
                <img src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/vip.jpg" alt="Gambar 3" class="maxmaxmax">
            </a>
            <a href="" target="_blank">
                <img src="https://77group.sgp1.cdn.digitaloceanspaces.com/vio77/new/qris.jpg" alt="Gambar 5" class="maxmaxmax">
            </a>
        </div>
    `);

    // Check if data-mobile is true
    if ($('body').data('mobile') === true) {
        // Move .home-slider after .game-front-menu
        $('.home-slider').insertAfter('.game-front-menu');
        $('.home-slider').addClass('mt-10');
    }
});
</script>


  <script>
$(document).ready(function () {
  $(".fixed-arrow").click(function () {
    $(".fixed-left").toggleClass("nganu");
  });
});



</script>


</div>
				<div class="support-footer">
			<div class="row clearfix">
				<div class="col-6">
					<section aria-labelledby="license" class="license heading mb-2">
						<h3 id="license" class="mb-3">Lisensi</h3>
						<div class="license">
							<a href="https://www.pagcor.ph/index.php" target="_blank" rel="noopener noreferrer nofollow" title="PAGCOR - Official website" aria-label="PAGCOR - Official website">
								<span role="img" class="pagcor"></span>
							</a>
							<a href="https://www.gamblingcommission.gov.uk/public-and-players/public-register" target="_blank" rel="noopener noreferrer nofollow" title="Gambling Commission - Public Register" aria-label="Gambling Commission - Public Register">
								<span role="img" class="gambling-commission"></span>
							</a>
							<a href="https://itechlabs.com" target="_blank" rel="noopener noreferrer nofollow" title="iTech Labs - Official site" aria-label="iTech Labs - Official site">
								<span role="img" class="itech-labs"></span>
							</a>
							<a href="https://gaminglabs.com" target="_blank" rel="noopener noreferrer nofollow" title="Gaming Labs International - Global Gaming Testing &amp; Certification" aria-label="Gaming Labs International - Global Gaming Testing &amp; Certification">
								<span role="img" class="gaming-labs-certified"></span>
							</a>
							<a href="https://bmm.com" target="_blank" rel="noopener noreferrer nofollow" title="bmm testlabs - Official webiste" aria-label="bmm testlabs - Official webiste">
								<span role="img" class="bmm-testlabs"></span>
							</a>
							<a href="https://www.mga.org.mt" target="_blank" rel="noopener noreferrer nofollow" title="Malta Gaming Authority - Official site" aria-label="Malta Gaming Authority - Official site">
								<span role="img" class="mga"></span>
							</a>
							</div>
					</section>
					<section aria-labelledby="responsible-gaming" class="responsible-gaming heading mb-4">
						<h3 id="responsible-gaming" class="mb-3">Tanggung Jawab Bermain</h3>
						<img loading="lazy" src="https://cdn.robotaset.com/assets/images/common/icon-responsible-game-horizontal-white.png" alt='Logo program permainan bertanggung jawab'>
					</section>
				</div>
				<div class="col-3" aria-labelledby="games-heading">
	<h3 id="games-heading" class="mb-3">Kategori Permainan</h3>
	<ul class="footer-links">
		<li><a href="/game-group/sports" title="Kategori Permainan Sports" aria-label="Kategori Permainan Sports">Sports</a></li>
			<li><a href="/game-group/casino" title="Kategori Permainan Casino" aria-label="Kategori Permainan Casino">Casino</a></li>
			<li><a href="/game-group/slot" title="Kategori Permainan Slot" aria-label="Kategori Permainan Slot">Slot</a></li>
			<li><a href="/game-group/lottery" title="Kategori Permainan Togel" aria-label="Kategori Permainan Togel">Togel</a></li>
			<li><a href="/game-group/cock_fighting" title="Kategori Permainan Sabung Ayam" aria-label="Kategori Permainan Sabung Ayam">Sabung Ayam</a></li>
			<li><a href="/game-group/games" title="Kategori Permainan Games" aria-label="Kategori Permainan Games">Games</a></li>
			<li><a href="/game-group/tembak_ikan" title="Kategori Permainan Tembak Ikan" aria-label="Kategori Permainan Tembak Ikan">Tembak Ikan</a></li>
			</ul>
</div>

<div class="col-3" aria-labelledby="info-heading">
	<h3 id="info-heading" class="mb-3">Informasi</h3>
	<ul class="footer-links">
		<li><a href="/about-us" title="Tentang Kami" aria-label="Tentang Kami">Tentang Kami</a></li>
		<li><a href="/contact-us" title="Hubungi Kami" aria-label="Hubungi Kami">Hubungi Kami</a></li>
	</ul>
</div></div>
		</div>

		<div class="text-center" style="margin:20px auto;">
		  		<img loading="lazy" src="https://cdn.robotaset.com/assets/images/common/infini88.png" alt="infini88.png" height="45">
	  		</div>
  		<div class="text-center rules-agreement mt-4 mb-4">
  			<div class="rules-agreement-logo"></div>
	  		</div>
	</div>
	<div class="container">
	<p class="copyright">Hak Cipta &copy; 2026 &nbsp;<span class="brand-name">Vio77</span>. Semua hak dilindungi.</p>
</div>
</footer>
<script>
	var jpEl = $("#jackpot");
	setInterval(function() {
		var newJp = new Date().getTime() / 100;
		jpEl.attr("data-value", newJp);
		jpEl.text(formatCurrency(newJp, null, 2));
	}, 600);
</script>
<script>window.__balanceScope = "";</script>

<script src="https://cdn.robotaset.com/assets/js/common/axios.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/js/common/popper.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/js/common/bootstrap.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/js/common/ajaxcall.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/js/common/format-number.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/thirdparty/owl-carousel/owl.carousel.min.js"></script>
	<script src="https://cdn.robotaset.com/assets/js/common/app.min.js"></script>
<script>
(function (window) {
    'use strict';

    var SCHEMA_VERSION = 1;
    var PREFIX = 'bal.v1.';
    var memberScope = String('' || '').replace(/[^A-Za-z0-9]/g, '');
    var storageKey = memberScope ? PREFIX + memberScope : null;
    // This JSP also runs on anonymous pages. Never preserve member data once SSR
    // confirms that no member is authenticated.
    var serverAuthenticated = false;
    var authInvalidated = !serverAuthenticated;
    var sessionCleanupApplied = false;
    var pending = {};
    var sequences = {};
    var subscribers = [];
    var providerListPromise = null;
    var providerListRequest = null;
    var providerListRequestVersion = 0;
    var logoutInProgress = false;
    var providerListAuthUnavailable = false;
    var PROVIDER_LIST_KEY = 'listPv';
    var PROVIDER_LIST_SCOPE_KEY = 'bal.meta.listPvScope';
    var FAVORITES_KEY = 'listFavorite';
    var PROVIDER_LOCKED_CODE = 19175;
    var PROVIDER_LOCKED_LABEL = 'Terkunci';
    var PROVIDER_MAINTENANCE_CODE = 9004;
    var PROVIDER_MAINTENANCE_LABEL = 'Pemeliharaan';
    // Locked-provider state is intentionally session/page scoped, not persisted in localStorage.
    // The authoritative persistent state lives in user_data.disabledProvider (Spring Session/Redis).
    var lockedProviders = {};
    // Page-scoped only: reload picks up the authoritative maintenance window again.
    var maintenanceProviders = {};
    var initialDisabledProviderRaw = String('' || '').trim();
    if (initialDisabledProviderRaw.toLowerCase() === 'null' || initialDisabledProviderRaw.toLowerCase() === 'undefined') {
        initialDisabledProviderRaw = '';
    }

    // Keep the native Storage methods before installing the legacy bridge below.
    // app.js / toto.js still contain direct sessionStorage wallet reads in LIVE PROD.
    // For this JSP-only POC those reads are virtualized to balanceCache/localStorage;
    // no balance object is persisted back into sessionStorage.
    var nativeStorageGetItem = Storage.prototype.getItem;
    var nativeStorageSetItem = Storage.prototype.setItem;
    var nativeStorageRemoveItem = Storage.prototype.removeItem;
    var nativeObjectKeys = Object.keys;

    window.__balanceScope = memberScope;

    function debug(reason, code) {
        if (window.__balanceCacheDebug === true && window.console && console.debug) {
            console.debug('[BalanceCache]', reason, code || '');
        }
    }

    function normalizeCode(code) {
        return String(code || '').trim().toUpperCase();
    }

    function isMemberStorageKey(key) {
        key = String(key || '');
        return key.indexOf(PREFIX) === 0 || key === PROVIDER_LIST_KEY
            || key === PROVIDER_LIST_SCOPE_KEY || key === FAVORITES_KEY;
    }

    function canUseMemberCache() {
        return serverAuthenticated && !authInvalidated
            && !logoutInProgress && !providerListAuthUnavailable;
    }

    function safeParse(raw) {
        if (!raw) return null;
        try { return JSON.parse(raw); } catch (e) { return null; }
    }

    function emptyEnvelope() {
        return {
            schemaVersion: SCHEMA_VERSION,
            memberScope: memberScope,
            wallets: {}
        };
    }

    function readEnvelope() {
        if (!storageKey) return emptyEnvelope();
        var env = safeParse(localStorage.getItem(storageKey));
        if (!env || env.schemaVersion !== SCHEMA_VERSION || env.memberScope !== memberScope || !env.wallets || typeof env.wallets !== 'object') {
            return emptyEnvelope();
        }
        // V6 POC briefly persisted providerStates; do not carry it forward.
        if (Object.prototype.hasOwnProperty.call(env, 'providerStates')) delete env.providerStates;
        return env;
    }

    function writeEnvelope(env) {
        if (!storageKey || !canUseMemberCache()) {
            debug('write_skipped_no_scope');
            return false;
        }
        env.schemaVersion = SCHEMA_VERSION;
        env.memberScope = memberScope;
        if (!env.wallets || typeof env.wallets !== 'object') env.wallets = {};
        if (Object.prototype.hasOwnProperty.call(env, 'providerStates')) delete env.providerStates;
        try {
            localStorage.setItem(storageKey, JSON.stringify(env));
            notify();
            return true;
        } catch (e) {
            debug('storage_write_failed');
            return false;
        }
    }

    function getProviderState(code) {
        code = normalizeCode(code);
        if (!code) return null;
        var state = lockedProviders[code];
        return state ? {
            status: 'LOCKED',
            messageCode: Number(state.messageCode || PROVIDER_LOCKED_CODE),
            updatedAt: Number(state.updatedAt || 0)
        } : null;
    }

    function isProviderLocked(code) {
        code = normalizeCode(code);
        return !!(code && lockedProviders[code]);
    }

    function replaceProviderStatusNode(h5, label, preferredTag, status) {
        if (!h5) return;
        var next = h5.nextElementSibling;
        var tag = preferredTag || (next && next.tagName && next.tagName.toLowerCase() === 'p' ? 'p' : 'span');
        var node = document.createElement(tag);
        status = status || 'LOCKED';
        node.className = status === 'MAINTENANCE' ? 'provider-maintenance-label' : 'provider-locked-label';
        node.setAttribute('data-provider-state', status);
        node.textContent = label;
        if (next) {
            next.parentNode.replaceChild(node, next);
        } else if (h5.parentNode) {
            h5.parentNode.appendChild(node);
        }
    }

    function disableTransferProvider(code) {
        var desktopSelectors = [
            '#TransferFrom li[data-value="' + code + '"]',
            '#TransferTo li[data-value="' + code + '"]'
        ];
        document.querySelectorAll(desktopSelectors.join(',')).forEach(function (item) {
            item.classList.add('disabled');
            item.setAttribute('aria-disabled', 'true');
            if (item.classList.contains('selected')) {
                var root = item.closest('#TransferFrom, #TransferTo');
                item.classList.remove('selected');
                if (root) {
                    var first = root.querySelector('li[data-value=""]');
                    if (first) {
                        first.classList.add('selected');
                        var chosen = root.querySelector('.chosen');
                        if (chosen) chosen.textContent = first.textContent;
                    }
                    var walletBox = root.id === 'TransferFrom'
                        ? document.getElementById('FromWallet')
                        : document.getElementById('ToWallet');
                    if (walletBox) walletBox.textContent = '0.00';
                }
            }
        });

        document.querySelectorAll('#TransferFrom option[value="' + code + '"], #TransferTo option[value="' + code + '"]').forEach(function (option) {
            option.disabled = true;
            option.setAttribute('aria-disabled', 'true');
            if (option.selected && option.parentElement) {
                var select = option.parentElement;
                select.value = '';
                try {
                    select.dispatchEvent(new Event('change', { bubbles: true }));
                } catch (e) {
                    var evt = document.createEvent('Event');
                    evt.initEvent('change', true, true);
                    select.dispatchEvent(evt);
                }
            }
        });
    }

    function renderProviderLocked(code) {
        code = normalizeCode(code);
        if (!code) return;
        var label = PROVIDER_LOCKED_LABEL || 'Locked';

        // Desktop Transfer side wallet list.
        document.querySelectorAll('#ProviderBalance h5[data-id]').forEach(function (h5) {
            if (normalizeCode(h5.getAttribute('data-id')) === code) {
                replaceProviderStatusNode(h5, label, 'span');
            }
        });

        // Mobile Balance list (shared by Infini88 / Infinitoto).
        document.querySelectorAll('#balance h5[data-id]').forEach(function (h5) {
            if (normalizeCode(h5.getAttribute('data-id')) === code) {
                replaceProviderStatusNode(h5, label, 'p');
            }
        });

        // Desktop header balance popup for both templates.
        var wallet = document.getElementById('game-balance-' + code.toLowerCase());
        if (wallet) {
            wallet.textContent = label;
            wallet.classList.remove('game-wallet');
            wallet.classList.add('provider-locked-label');
            wallet.setAttribute('data-provider-state', 'LOCKED');
        }
        document.querySelectorAll('.calibrate[data-id]').forEach(function (control) {
            if (normalizeCode(control.getAttribute('data-id')) === code) {
                control.style.display = 'none';
                control.setAttribute('aria-disabled', 'true');
            }
        });

        disableTransferProvider(code);
    }

    function isProviderMaintenance(code) {
        code = normalizeCode(code);
        return !!(code && maintenanceProviders[code]);
    }

    function renderProviderMaintenance(code) {
        code = normalizeCode(code);
        if (!code) return;
        var label = PROVIDER_MAINTENANCE_LABEL || 'Maintenance';

        document.querySelectorAll('#ProviderBalance h5[data-id]').forEach(function (h5) {
            if (normalizeCode(h5.getAttribute('data-id')) === code) {
                replaceProviderStatusNode(h5, label, 'span', 'MAINTENANCE');
            }
        });
        document.querySelectorAll('#balance h5[data-id]').forEach(function (h5) {
            if (normalizeCode(h5.getAttribute('data-id')) === code) {
                replaceProviderStatusNode(h5, label, 'p', 'MAINTENANCE');
            }
        });

        var wallet = document.getElementById('game-balance-' + code.toLowerCase());
        if (wallet) {
            wallet.textContent = label;
            wallet.classList.remove('game-wallet');
            wallet.classList.add('provider-maintenance-label');
            wallet.setAttribute('data-provider-state', 'MAINTENANCE');
            wallet.setAttribute('data-provider-code', code);
        }
        document.querySelectorAll('.calibrate[data-id]').forEach(function (control) {
            if (normalizeCode(control.getAttribute('data-id')) === code) {
                control.style.display = 'none';
                control.setAttribute('aria-disabled', 'true');
            }
        });
        disableTransferProvider(code);
    }

    function markProviderMaintenance(code) {
        code = normalizeCode(code);
        if (!code || code === 'MAIN') return false;
        maintenanceProviders[code] = { updatedAt: Date.now() };
        // Never count a stale numeric wallet in TOTAL, even if its TTL is valid.
        invalidate(code, 'maintenance');
        renderProviderMaintenance(code);
        // Legacy success callbacks may still attempt to display Retry immediately afterward.
        setTimeout(function () { renderProviderMaintenance(code); }, 0);
        try {
            window.dispatchEvent(new CustomEvent('balancecache:providermaintenance', {
                detail: { providerCode: code, messageCode: PROVIDER_MAINTENANCE_CODE }
            }));
        } catch (e) { /* CustomEvent compatibility is non-critical */ }
        return true;
    }

    function lockProvider(code, messageCode) {
        code = normalizeCode(code);
        if (!code) return false;

        // A locked provider must never keep a stale numeric balance.
        // Persist only the balance envelope; the LOCKED state itself stays in memory.
        if (storageKey) {
            var env = readEnvelope();
            delete env.wallets[code];
            writeEnvelope(env);
        }

        lockedProviders[code] = {
            messageCode: Number(messageCode || PROVIDER_LOCKED_CODE),
            updatedAt: Date.now()
        };

        renderProviderLocked(code);
        // Legacy callbacks may run after the response bridge and write Retry/0.
        setTimeout(function () {
            // An authoritative MAIN refresh may have removed the lock meanwhile.
            if (isProviderLocked(code)) renderProviderLocked(code);
        }, 0);
        try {
            window.dispatchEvent(new CustomEvent('balancecache:providerlocked', {
                detail: { providerCode: code, messageCode: Number(messageCode || PROVIDER_LOCKED_CODE) }
            }));
        } catch (e) { /* CustomEvent compatibility is non-critical */ }
        return true;
    }

    // Explicit, authoritative unlock. Call ONLY after a successful MAIN response
    // containing disabledProviders; neither TTL expiry nor a generic API error
    // is evidence that AGENT removed the lock.
    function unlockProvider(code) {
        code = normalizeCode(code);
        if (!code || !isProviderLocked(code)) return false;
        delete lockedProviders[code];
        // A prior lock discarded the cached provider wallet. Never restore that
        // old balance: only a new, authenticated balance request can refill it.
        invalidate(code, 'provider_unlocked_requires_refresh');

        // The popup's game page can contain a desktop header wallet. Return it
        // to the retry/check-all path, without touching /bank/transfer controls.
        var wallet = document.getElementById('game-balance-' + code.toLowerCase());
        if (wallet && wallet.getAttribute('data-provider-state') === 'LOCKED'
                && !isProviderMaintenance(code)) {
            wallet.classList.remove('provider-locked-label');
            wallet.classList.add('game-wallet');
            wallet.removeAttribute('data-provider-state');
            setHeaderProviderRetry(code);
        }
        try {
            window.dispatchEvent(new CustomEvent('balancecache:providerunlocked', {
                detail: { providerCode: code }
            }));
        } catch (e) { /* CustomEvent compatibility is non-critical */ }
        return true;
    }

    function responseProviderCode(resp, payload) {
        var code = resp && resp.data && (resp.data.disabledPv || resp.data.pvcd || resp.data.pvcode);
        if (!code && payload && typeof payload === 'object') code = payload.pvcd || payload.pvcode || payload.transferTo;
        if (!code && typeof payload === 'string') {
            var parsed = safeParse(payload);
            if (parsed) code = parsed.pvcd || parsed.pvcode || parsed.transferTo;
            if (!code && typeof URLSearchParams === 'function') {
                // jQuery.ajax can submit x-www-form-urlencoded rather than JSON.
                try {
                    var params = new URLSearchParams(payload);
                    code = params.get('pvcd') || params.get('pvcode') || params.get('transferTo');
                } catch (e) { /* malformed request payload */ }
            }
        }
        return normalizeCode(code);
    }

    function handleProviderResponse(resp, payload) {
        if (!resp) return false;
        if (Number(resp.code) === 14000) {
            expireMemberSession('api_session_expired');
            return true;
        }
        var code = responseProviderCode(resp, payload);
        if (!code) return false;
        if (Number(resp.code) === PROVIDER_LOCKED_CODE) {
            lockProvider(code, PROVIDER_LOCKED_CODE);
            return true;
        }
        if (Number(resp.code) === PROVIDER_MAINTENANCE_CODE) {
            markProviderMaintenance(code);
            return true;
        }
        return false;
    }

    function validWallet(obj) {
        return obj && typeof obj === 'object' && obj.balance !== undefined && obj.balance !== null && obj.ts !== undefined && obj.ts !== null;
    }

    function cloneWallet(obj) {
        return {
            balance: obj.balance,
            ts: Number(obj.ts),
            hasTransfer: Number(obj.hasTransfer || 0),
            revision: Number(obj.revision || 0),
            updatedAt: Number(obj.updatedAt || Date.now())
        };
    }

    function get(code) {
        code = normalizeCode(code);
        if (!code || !storageKey || !canUseMemberCache()) return null;
        var wallet = readEnvelope().wallets[code];
        return validWallet(wallet) ? cloneWallet(wallet) : null;
    }

    function getUsable(code) {
        if (isProviderLocked(code) || isProviderMaintenance(code)) return null;
        var wallet = get(code);
        if (!wallet) return null;
        if (!Number.isFinite(wallet.ts) || wallet.ts <= Date.now()) return null;
        if (Number(wallet.hasTransfer) === 1) return null;
        return wallet;
    }

    function setWallet(code, obj, seq) {
        code = normalizeCode(code);
        if (!code || !validWallet(obj) || !storageKey) return false;
        if (isProviderLocked(code) || isProviderMaintenance(code)) return false;
        if (seq !== undefined && seq !== null && Number(seq) < Number(sequences[code] || 0)) {
            debug('stale_sequence_discarded', code);
            return false;
        }

        var env = readEnvelope();
        var existing = env.wallets[code];
        var incomingTs = Number(obj.ts);
        if (!Number.isFinite(incomingTs)) return false;
        if (existing && Number(existing.ts) > incomingTs) {
            debug('stale_timestamp_discarded', code);
            return false;
        }

        env.wallets[code] = {
            balance: obj.balance,
            ts: incomingTs,
            hasTransfer: Number(obj.hasTransfer || 0),
            revision: Number(obj.revision || seq || 0),
            updatedAt: Date.now()
        };
        return writeEnvelope(env);
    }

    function setFromListBalance(listBalance, seq) {
        if (!canUseMemberCache()) return false;
        // Persist the whole response in one localStorage write. Provider balance
        // 0 is a valid authoritative value and MUST be cached just like any
        // positive balance. A batch merge also prevents rapid parallel provider
        // responses from repeatedly rebuilding the envelope one wallet at a time.
        if (!Array.isArray(listBalance) || !storageKey) return false;

        var env = readEnvelope();
        var changed = false;
        var batchUpdatedAt = Date.now();

        listBalance.forEach(function (row) {
            if (!row || typeof row !== 'object') return;

            nativeObjectKeys(row).forEach(function (rawCode) {
                var code = normalizeCode(rawCode);
                var obj = row[rawCode];
                if (!code || !validWallet(obj)) return;
                if (isProviderLocked(code) || isProviderMaintenance(code)) return;

                // Only reject by sequence when the caller explicitly supplied
                // one for this request. Equal/undefined sequence is valid.
                if (seq !== undefined && seq !== null &&
                    Number(seq) < Number(sequences[code] || 0)) {
                    debug('stale_sequence_discarded', code);
                    return;
                }

                var incomingTs = Number(obj.ts);
                if (!Number.isFinite(incomingTs)) {
                    debug('invalid_timestamp_discarded', code);
                    return;
                }

                var existing = env.wallets[code];
                if (existing && Number(existing.ts) > incomingTs) {
                    debug('stale_timestamp_discarded', code);
                    return;
                }

                var next = {
                    // Do not use a truthy check here: numeric 0 and string "0"
                    // are legitimate balances returned by the backend.
                    balance: obj.balance,
                    ts: incomingTs,
                    hasTransfer: Number(obj.hasTransfer || 0),
                    revision: Number(obj.revision || seq || 0),
                    updatedAt: batchUpdatedAt
                };

                // Avoid an unnecessary localStorage write when an automatic API
                // bridge and the page's explicit setFromListBalance() both see
                // the same response.
                if (existing &&
                    existing.balance === next.balance &&
                    Number(existing.ts) === next.ts &&
                    Number(existing.hasTransfer || 0) === next.hasTransfer &&
                    Number(existing.revision || 0) === next.revision) {
                    return;
                }

                env.wallets[code] = next;
                changed = true;
            });
        });

        return changed ? writeEnvelope(env) : true;
    }

    function ingestApiResponse(resp, seq) {
        if (resp && Number(resp.code) === 14000) {
            expireMemberSession('balance_api_session_expired');
            return false;
        }
        if (!canUseMemberCache() || !resp || resp.success !== true || !resp.data) return false;
        if (!Array.isArray(resp.data.listBalance)) return false;
        return setFromListBalance(resp.data.listBalance, seq);
    }

    function invalidate(code, reason) {
        code = normalizeCode(code);
        if (!code || !storageKey) return false;
        var env = readEnvelope();
        if (!Object.prototype.hasOwnProperty.call(env.wallets, code)) return true;
        delete env.wallets[code];
        debug('invalidated:' + (reason || 'manual'), code);
        return writeEnvelope(env);
    }

    function total() {
        var env = readEnvelope();
        var amount = 0;
        var known = 0;
        var unknown = 0;
        Object.keys(env.wallets).forEach(function (code) {
            var wallet = getUsable(code);
            if (!wallet) {
                unknown++;
                return;
            }
            var n = Number(wallet.balance);
            if (Number.isFinite(n)) {
                amount += n;
                known++;
            } else {
                unknown++;
            }
        });
        return { amount: amount, known: known, unknown: unknown };
    }

    function beginRequest(code, force) {
        code = normalizeCode(code);
        if (!code) return null;
        if (pending[code] && !force) return null;
        sequences[code] = Number(sequences[code] || 0) + 1;
        pending[code] = sequences[code];
        return sequences[code];
    }

    function endRequest(code, seq) {
        code = normalizeCode(code);
        if (!code) return;
        if (seq === undefined || seq === null || pending[code] === seq) delete pending[code];
    }

    function isRequestCurrent(code, seq) {
        code = normalizeCode(code);
        return !!code && Number(seq) === Number(sequences[code] || 0);
    }

    function clearCurrentMember() {
        if (!storageKey) return;
        localStorage.removeItem(storageKey);
        notify();
    }

    function clearAllMembers() {
        var keys = [];
        for (var i = 0; i < localStorage.length; i++) {
            var key = localStorage.key(i);
            if (key && key.indexOf(PREFIX) === 0) keys.push(key);
        }
        keys.forEach(function (key) { nativeStorageRemoveItem.call(localStorage, key); });
        // listPv is shared by old scripts; its scope marker and favorites must
        // be purged with wallet caches to prevent the next member seeing them.
        [PROVIDER_LIST_KEY, PROVIDER_LIST_SCOPE_KEY, FAVORITES_KEY].forEach(function (key) {
            nativeStorageRemoveItem.call(localStorage, key);
        });
        notify();
    }

    function normalizeProviderList(list) {
        if (!Array.isArray(list)) return [];
        var result = [];
        list.forEach(function (code) {
            code = normalizeCode(code);
            if (code && result.indexOf(code) === -1) result.push(code);
        });
        return result;
    }

    function readProviderList() {
        if (!canUseMemberCache()) return null;
        var raw = nativeStorageGetItem.call(localStorage, PROVIDER_LIST_KEY);
        if (raw === null) return null;
        var list = safeParse(raw);
        return Array.isArray(list) ? normalizeProviderList(list) : null;
    }

    function writeProviderList(list) {
        var normalized = normalizeProviderList(list);
        if (!canUseMemberCache()) return [];
        nativeStorageSetItem.call(localStorage, PROVIDER_LIST_KEY, JSON.stringify(normalized));
        if (memberScope) {
            nativeStorageSetItem.call(localStorage, PROVIDER_LIST_SCOPE_KEY, memberScope);
        }
        return normalized;
    }

    function providerListMatchesScope() {
        if (!memberScope) return false;
        return nativeStorageGetItem.call(localStorage, PROVIDER_LIST_SCOPE_KEY) === memberScope;
    }

    function isLogoutApiUrl(url) {
        return /\/api\/account\/logout(?:[?#]|$)/i.test(String(url || ''));
    }

    function isProviderListApiUrl(url) {
        return /\/api\/wallet\/calibrate\/list(?:[?#]|$)/i.test(String(url || ''));
    }

    function beginMemberLogout() {
        if (logoutInProgress) return;
        logoutInProgress = true;
        providerListRequestVersion++;
        // Stop the optional background provider-list preload as soon as the
        // confirmed logout API request starts (not when the confirmation opens).
        if (providerListRequest && typeof providerListRequest.abort === 'function') {
            try { providerListRequest.abort(); } catch (e) { /* already completed */ }
        }
        providerListRequest = null;
        providerListPromise = null;
        debug('provider_list_stopped_for_logout');
    }

    function expireMemberSession(reason) {
        if (sessionCleanupApplied) return;
        // Block all pending/late provider and wallet writes BEFORE deleting keys.
        beginMemberLogout();
        authInvalidated = true;
        providerListAuthUnavailable = true;
        sessionCleanupApplied = true;
        clearAllMembers();
        purgeLegacySessionBalances();
        debug('member_storage_cleared:' + (reason || 'session_ended'));
    }

    function restoreProviderListAfterFailedLogout() {
        // If the server explicitly rejected logout, keep the page usable.
        // A cancelled confirmation never reaches beginMemberLogout().
        logoutInProgress = false;
        debug('logout_failed_provider_list_resumed');
    }

    function acceptProviderListResponse(resp, version) {
        if (resp && Number(resp.code) === 14000) {
            expireMemberSession('provider_list_session_expired');
            return null;
        }
        if (logoutInProgress || version !== providerListRequestVersion) return null;
        if (!resp || resp.success !== true || !resp.data || !Array.isArray(resp.data.listPv)) {
            // An expired session must not overwrite a valid listPv with [].
            // A background refresh must not trigger the global 14000 alert.
            return null;
        }
        return writeProviderList(resp.data.listPv);
    }

    function requestProviderList(version) {
        // Deliberately avoid callApi3 here: its global error handling can display
        // SESSION_NOT_FOUND (14000) for a background request after logout.
        var url = window.location.origin + '/api/wallet/calibrate/list';
        if (window.fetch) {
            var controller = typeof window.AbortController === 'function'
                ? new window.AbortController() : null;
            var request = controller ? { abort: function () { controller.abort(); } } : null;
            var options = { credentials: 'same-origin', cache: 'no-store' };
            if (controller) options.signal = controller.signal;
            providerListRequest = request;
            return window.fetch(url, options).then(function (response) {
                if (!response.ok) return null;
                return response.json();
            }).then(function (resp) {
                return acceptProviderListResponse(resp, version);
            }, function () {
                // Network failures or an intentional abort are silent for preload.
                return null;
            }).then(function (list) {
                if (providerListRequest === request) providerListRequest = null;
                return list;
            });
        }

        // XHR fallback for browsers without fetch; also bypasses global
        // callApi3 error handlers and can be aborted on logout.
        return new Promise(function (resolve) {
            var xhr = new XMLHttpRequest();
            var completed = false;
            function finish(list) {
                if (completed) return;
                completed = true;
                if (providerListRequest === xhr) providerListRequest = null;
                resolve(list);
            }
            providerListRequest = xhr;
            xhr.open('GET', url, true);
            xhr.withCredentials = true;
            xhr.onreadystatechange = function () {
                if (xhr.readyState !== 4) return;
                var resp = xhr.status >= 200 && xhr.status < 300
                    ? safeParse(xhr.responseText) : null;
                finish(acceptProviderListResponse(resp, version));
            };
            xhr.onerror = function () { finish(null); };
            xhr.onabort = function () { finish(null); };
            try { xhr.send(); } catch (e) { finish(null); }
        });
    }

    function ensureProviderList(force) {
        if (!storageKey || !canUseMemberCache()) return Promise.resolve([]);

        var current = readProviderList();
        if (!force && providerListMatchesScope() && current !== null) {
            return Promise.resolve(current);
        }

        if (providerListPromise) return providerListPromise;

        var version = providerListRequestVersion;
        providerListPromise = requestProviderList(version).then(function (list) {
            if (version === providerListRequestVersion) providerListPromise = null;
            if (logoutInProgress || version !== providerListRequestVersion) return [];
            // Preserve a previous valid provider list when the background
            // refresh fails; never persist a failed API response as [].
            return list !== null ? list : (current || []);
        }, function () {
            if (version === providerListRequestVersion) providerListPromise = null;
            return logoutInProgress ? [] : (current || []);
        });
        return providerListPromise;
    }

    function parseProviderList() {
        return readProviderList() || [];
    }

    function isLegacyWalletKey(key) {
        var code = normalizeCode(key);
        if (!code) return false;
        if (code === 'MAIN') return true;

        var env = readEnvelope();
        if (Object.prototype.hasOwnProperty.call(env.wallets, code)) return true;

        var providers = parseProviderList();
        if (providers.indexOf(code) !== -1) return true;

        // Some template flows expose pvls before listPv has been populated.
        if (Array.isArray(window.pvls)) {
            for (var i = 0; i < window.pvls.length; i++) {
                var row = window.pvls[i] || {};
                if (normalizeCode(row.pvcode || row.pvcd) === code) return true;
            }
        }
        return false;
    }

    function installLegacySessionStorageBridge() {
        if (Storage.prototype.__balanceCacheBridgeInstalled) return;

        Storage.prototype.getItem = function (key) {
            if (this === window.sessionStorage && isLegacyWalletKey(key)) {
                var wallet = get(key);
                return wallet ? JSON.stringify(wallet) : null;
            }
            return nativeStorageGetItem.call(this, key);
        };

        Storage.prototype.setItem = function (key, value) {
            // Legacy scripts can write directly to localStorage. Once the
            // session ends, do not let an in-flight callback repopulate it.
            if (this === window.localStorage && isMemberStorageKey(key) && !canUseMemberCache()) {
                return;
            }
            if (this === window.sessionStorage) {
                var parsed = safeParse(value);
                if (validWallet(parsed)) {
                    // Compatibility only: legacy code thinks it wrote to
                    // sessionStorage, but the authoritative value is persisted
                    // exclusively by balanceCache in localStorage.
                    setWallet(key, parsed);
                    return;
                }
            }
            return nativeStorageSetItem.call(this, key, value);
        };

        Storage.prototype.removeItem = function (key) {
            if (this === window.sessionStorage && isLegacyWalletKey(key)) {
                invalidate(key, 'legacy_session_remove');
                // Also remove any real pre-migration entry that may still exist.
                return nativeStorageRemoveItem.call(this, key);
            }
            return nativeStorageRemoveItem.call(this, key);
        };

        // A few LIVE PROD balance functions enumerate Object.keys(sessionStorage)
        // before calling getItem(). Expose the localStorage wallet codes virtually
        // so those legacy readers keep working without persisting balance data in
        // sessionStorage.
        if (!Object.keys.__balanceCacheBridgeInstalled) {
            var bridgedObjectKeys = function (obj) {
                var keys = nativeObjectKeys(obj);
                if (obj === window.sessionStorage) {
                    var wallets = readEnvelope().wallets;
                    nativeObjectKeys(wallets).forEach(function (code) {
                        if (keys.indexOf(code) === -1) keys.push(code);
                    });
                }
                return keys;
            };
            try {
                Object.defineProperty(bridgedObjectKeys, '__balanceCacheBridgeInstalled', {
                    value: true,
                    configurable: false,
                    enumerable: false,
                    writable: false
                });
            } catch (e) {
                bridgedObjectKeys.__balanceCacheBridgeInstalled = true;
            }
            Object.keys = bridgedObjectKeys;
        }

        try {
            Object.defineProperty(Storage.prototype, '__balanceCacheBridgeInstalled', {
                value: true,
                configurable: false,
                enumerable: false,
                writable: false
            });
        } catch (e) {
            Storage.prototype.__balanceCacheBridgeInstalled = true;
        }
    }

    function purgeLegacySessionBalances() {
        var toRemove = [];
        for (var i = 0; i < sessionStorage.length; i++) {
            var key = sessionStorage.key(i);
            var parsed = safeParse(nativeStorageGetItem.call(sessionStorage, key));
            if (parsed && typeof parsed === 'object' && parsed.balance !== undefined && parsed.ts !== undefined) {
                toRemove.push(key);
            }
        }
        toRemove.forEach(function (key) { nativeStorageRemoveItem.call(sessionStorage, key); });
        localStorage.removeItem(PREFIX + 'anon');
    }

    function notify() {
        subscribers.slice().forEach(function (fn) {
            try { fn(readEnvelope()); } catch (e) { /* subscriber isolation */ }
        });
    }

    function subscribe(fn) {
        if (typeof fn !== 'function') return function () {};
        subscribers.push(fn);
        return function () {
            subscribers = subscribers.filter(function (item) { return item !== fn; });
        };
    }

    window.addEventListener('storage', function (event) {
        if (storageKey && event.key === storageKey) {
            notify();
        }
    });

    // Anonymous SSR is the authoritative cleanup point after a session times
    // out while this origin was not open. Do this on BOTH desktop and mobile.
    if (!serverAuthenticated) expireMemberSession('anonymous_page');
    purgeLegacySessionBalances();
    installLegacySessionStorageBridge();

    // SSR maintenance is authoritative on page load. Mark before consumers calculate TOTAL.
    // This also clears a valid-but-stale balance from a previous page/cache TTL.
    document.querySelectorAll('[data-provider-state="MAINTENANCE"]').forEach(function (node) {
        var code = node.getAttribute('data-provider-code');
        if (!code && node.previousElementSibling && node.previousElementSibling.hasAttribute('data-id')) {
            code = node.previousElementSibling.getAttribute('data-id');
        }
        if (code) markProviderMaintenance(code);
    });

    window.balanceCache = {
        get: get,
        getUsable: getUsable,
        needsRefresh: function (code) { return getUsable(code) === null; },
        setWallet: setWallet,
        setFromListBalance: setFromListBalance,
        ingestApiResponse: ingestApiResponse,
        lockProvider: lockProvider,
        unlockProvider: unlockProvider,
        isProviderLocked: isProviderLocked,
        isProviderMaintenance: isProviderMaintenance,
        markProviderMaintenance: markProviderMaintenance,
        renderProviderMaintenance: renderProviderMaintenance,
        getProviderState: getProviderState,
        renderProviderLocked: renderProviderLocked,
        invalidate: invalidate,
        total: total,
        beginRequest: beginRequest,
        endRequest: endRequest,
        isRequestCurrent: isRequestCurrent,
        clearCurrentMember: clearCurrentMember,
        clearAllMembers: clearAllMembers,
        subscribe: subscribe,
        ensureProviderList: ensureProviderList,
        waitForUiLoading: waitForUiLoading,
        getProviderList: function () { return readProviderList() || []; },
        hasMemberScope: function () { return !!storageKey; },
        key: function () { return storageKey; },
        legacyBridgeInstalled: function () { return Storage.prototype.__balanceCacheBridgeInstalled === true; },
        physicalSessionBalanceKeys: function () {
            return nativeObjectKeys(sessionStorage).filter(function (key) {
                var parsed = safeParse(nativeStorageGetItem.call(sessionStorage, key));
                return parsed && typeof parsed === 'object' && parsed.balance !== undefined && parsed.ts !== undefined;
            });
        }
    };

    // Compatibility for existing page scripts (login / withdrawal) without
    // modifying app.js or toto.js. Balance data is still stored only in localStorage.
    window.setBalanceToSession = function (listBalance) {
        return window.balanceCache.setFromListBalance(listBalance);
    };
    window.isBalanceExpired = function (valueOrWallet) {
        var wallet = valueOrWallet;
        if (typeof wallet === 'string') wallet = safeParse(wallet);
        if (!validWallet(wallet)) return true;
        return Number(wallet.hasTransfer || 0) === 1 || Number(wallet.ts) <= Date.now();
    };

    // Keep the existing listPv contract, but make it MEMBER-aware and normalized.
    // This metadata controls which provider wallets need to be queried.
    var originalSetListPvToSession = window.setListPvToSession;
    window.setListPvToSession = function (listPv) {
        if (!canUseMemberCache()) return [];
        if (typeof originalSetListPvToSession === 'function') {
            try { originalSetListPvToSession(listPv); } catch (e) { /* normalize below */ }
        }
        return writeProviderList(listPv);
    };

    function isTrackedBalanceUrl(url) {
        url = String(url || '');
        return url.indexOf('/api/wallet/main/getBalance') !== -1
            || url.indexOf('/api/wallet/provider/getBalance') !== -1
            || url.indexOf('/api/wallet/calibrate/list') !== -1;
    }

    function formatBatchTotal(amount) {
        if (typeof window.formatCurrency === 'function') {
            return window.formatCurrency(amount, null, 2);
        }
        var n = Number(amount || 0);
        return Number.isFinite(n) ? n.toFixed(2) : '0.00';
    }

    // V9: Desktop header Check All is orchestrated here instead of relying on a
    // "network went quiet" timer. A quiet period is not a valid completion
    // signal because provider requests can be chained/sequential. TOTAL is
    // rendered only after every eligible MAIN/provider task has settled.
    var headerBalanceBatchInProgress = false;

    function headerSpinnerHtml() {
        return '<i class="fa fa-spinner fa-pulse fa-fw"></i>';
    }

    // V10: even cache-hit wallets get a short loading affordance when MEMBER
    // explicitly runs Check All. This is UI feedback only; cache hits still do
    // not call the backend. Network/error paths keep the spinner until they
    // settle, then render the balance or Retry.
    var CACHE_HIT_LOADING_MS = 300;

    function waitForUiLoading(ms) {
        var delay = Number(ms);
        if (!Number.isFinite(delay) || delay < 0) delay = CACHE_HIT_LOADING_MS;
        return new Promise(function (resolve) {
            window.setTimeout(resolve, delay);
        });
    }

    function setHeaderMainBalance(balance) {
        var formatted = formatBatchTotal(balance) + ' K';
        var holder = document.getElementById('main-balance-holder');
        var credit = document.getElementById('creditBalance');
        if (holder) holder.textContent = formatted;
        if (credit) credit.textContent = formatted;
    }

    function setHeaderMainLoading() {
        var holder = document.getElementById('main-balance-holder');
        var credit = document.getElementById('creditBalance');
        if (holder) holder.innerHTML = headerSpinnerHtml();
        if (credit) credit.innerHTML = headerSpinnerHtml();
    }

    function setHeaderMainRetry() {
        var retry = (window.alertMsg && window.alertMsg.retry) ? window.alertMsg.retry : 'Retry';
        var holder = document.getElementById('main-balance-holder');
        var credit = document.getElementById('creditBalance');
        if (holder) holder.textContent = retry;
        if (credit) credit.textContent = retry;
    }

    function setHeaderProviderBalance(code, balance) {
        var node = document.getElementById('game-balance-' + normalizeCode(code).toLowerCase());
        if (!node || isProviderLocked(code) || isProviderMaintenance(code)) return;
        node.textContent = formatBatchTotal(balance) + ' K';
    }

    function setHeaderProviderLoading(code) {
        var node = document.getElementById('game-balance-' + normalizeCode(code).toLowerCase());
        if (!node || isProviderLocked(code) || isProviderMaintenance(code)) return;
        node.innerHTML = headerSpinnerHtml();
    }

    function setHeaderProviderRetry(code) {
        var node = document.getElementById('game-balance-' + normalizeCode(code).toLowerCase());
        if (!node || isProviderLocked(code) || isProviderMaintenance(code)) return;
        var retry = (window.alertMsg && window.alertMsg.retry) ? window.alertMsg.retry : 'Retry';
        node.textContent = retry;
    }

    function setHeaderTotalLoading() {
        document.querySelectorAll('.totalWallet').forEach(function (node) {
            node.innerHTML = headerSpinnerHtml();
        });
    }

    function setHeaderTotalFromCache() {
        var summary = total();
        var formatted = formatBatchTotal(summary.amount) + ' K';
        document.querySelectorAll('.totalWallet').forEach(function (node) {
            node.textContent = formatted;
        });
    }

    function requestHeaderMainBalance() {
        // Always show a short spinner for an explicit Check All, even when the
        // value is served from localStorage. This avoids the action looking
        // unresponsive while preserving the no-backend-request cache behavior.
        setHeaderMainLoading();
        var cached = getUsable('MAIN');
        if (cached !== null) {
            return waitForUiLoading().then(function () {
                setHeaderMainBalance(cached.balance);
                return cached.balance;
            });
        }

        if (typeof window.callApi3 !== 'function') {
            setHeaderMainRetry();
            return Promise.resolve(null);
        }

        var seq = beginRequest('MAIN', true);
        return window.callApi3(window.location.origin + '/api/wallet/main/getBalance', 'GET', null).then(function (resp) {
            if (resp && resp.success && resp.data) {
                setFromListBalance(resp.data.listBalance || [], seq);
            }
            endRequest('MAIN', seq);
            var stored = get('MAIN');
            if (resp && resp.success && stored !== null) {
                setHeaderMainBalance(stored.balance);
                return stored.balance;
            }
            setHeaderMainRetry();
            return null;
        }, function (err) {
            endRequest('MAIN', seq);
            setHeaderMainRetry();
            if (typeof window.errorHandler === 'function') window.errorHandler(err);
            return null;
        });
    }

    function requestHeaderProviderBalance(code, transferredProvider) {
        code = normalizeCode(code);
        if (!code || isProviderLocked(code) || isProviderMaintenance(code)) return Promise.resolve(null);

        // Explicit Check All always gives visual feedback. Cache hits and known
        // zero wallets only wait for the short UI delay; no XHR is created.
        setHeaderProviderLoading(code);

        // If MEMBER never transferred to this provider, existing behavior treats
        // it as a known zero without calling provider/getBalance.
        if (!transferredProvider[code]) {
            return waitForUiLoading().then(function () {
                setHeaderProviderBalance(code, 0);
                return 0;
            });
        }

        var cached = getUsable(code);
        if (cached !== null) {
            return waitForUiLoading().then(function () {
                setHeaderProviderBalance(code, cached.balance);
                return cached.balance;
            });
        }

        if (typeof window.callApi3 !== 'function') {
            setHeaderProviderRetry(code);
            return Promise.resolve(null);
        }

        var seq = beginRequest(code, true);
        return window.callApi3(window.location.origin + '/api/wallet/provider/getBalance', 'POST', { pvcd: code }).then(function (resp) {
            if (Number(resp && resp.code) === PROVIDER_LOCKED_CODE) {
                lockProvider(code, PROVIDER_LOCKED_CODE);
                endRequest(code, seq);
                return null;
            }
            if (Number(resp && resp.code) === PROVIDER_MAINTENANCE_CODE) {
                markProviderMaintenance(code);
                endRequest(code, seq);
                return null;
            }
            if (resp && resp.success && resp.data) {
                setFromListBalance(resp.data.listBalance || [], seq);
            }
            endRequest(code, seq);

            var stored = get(code);
            if (resp && resp.success && stored !== null) {
                setHeaderProviderBalance(code, stored.balance);
                return stored.balance;
            }

            setHeaderProviderRetry(code);
            return null;
        }, function (err) {
            endRequest(code, seq);
            setHeaderProviderRetry(code);
            if (typeof window.errorHandler === 'function') window.errorHandler(err);
            return null;
        });
    }

    function checkAllHeaderBalances() {
        if (headerBalanceBatchInProgress) return Promise.resolve(false);
        headerBalanceBatchInProgress = true;
        setHeaderTotalLoading();

        return ensureProviderList(false).then(function (listProvider) {
            var transferredProvider = {};
            (Array.isArray(listProvider) ? listProvider : []).forEach(function (code) {
                code = normalizeCode(code);
                if (code) transferredProvider[code] = true;
            });

            var tasks = [requestHeaderMainBalance()];

            // A .game-wallet exists only for active, non-maintenance and
            // server-not-disabled providers rendered by the JSP. Runtime-locked
            // providers lose this class in renderProviderLocked(), so they are
            // automatically excluded from subsequent batches as well.
            document.querySelectorAll('.game-wallet[id^="game-balance-"]').forEach(function (node) {
                var code = normalizeCode(node.id.replace(/^game-balance-/i, ''));
                if (!code || isProviderLocked(code) || isProviderMaintenance(code)) return;
                tasks.push(requestHeaderProviderBalance(code, transferredProvider));
            });

            return Promise.all(tasks);
        }).then(function () {
            // IMPORTANT: do not expose TOTAL until every eligible wallet task is
            // settled. This fixes the V8 race where TOTAL appeared while provider
            // XHRs were still running.
            setHeaderTotalFromCache();
            headerBalanceBatchInProgress = false;
            return true;
        }, function (err) {
            // Individual wallet requests are converted to settled results above,
            // so this path is mainly for provider-list/bootstrap failures.
            setHeaderTotalFromCache();
            headerBalanceBatchInProgress = false;
            if (typeof window.errorHandler === 'function') window.errorHandler(err);
            return false;
        });
    }

    // JSP-only compatibility bridge: cache every successful balance response
    // before legacy LIVE PROD page code renders it. This keeps app.js/toto.js
    // untouched and also covers header flows that still call their own helpers.
    function installApiResponseBridge() {
        if (typeof window.callApi3 === 'function' && !window.callApi3.__balanceCacheWrapped) {
            var originalCallApi3 = window.callApi3;
            var wrappedCallApi3 = function () {
                var args = Array.prototype.slice.call(arguments);
                if (isLogoutApiUrl(args[0])) beginMemberLogout();
                // Some legacy scripts still call calibrate/list directly.
                // Do not dispatch another authenticated request after logout.
                if ((logoutInProgress || providerListAuthUnavailable)
                        && isProviderListApiUrl(args[0])) {
                    return Promise.resolve({ success: false, data: { listPv: [] } });
                }
                var payload = args.length > 2 ? args[2] : null;
                var logoutRequest = isLogoutApiUrl(args[0]);
                var result = originalCallApi3.apply(this, args);
                if (!result || typeof result.then !== 'function') return result;
                return result.then(function (resp) {
                    if (logoutRequest && resp && resp.success === true) {
                        expireMemberSession('logout_success');
                    } else if (logoutRequest && resp && resp.success === false) {
                        restoreProviderListAfterFailedLogout();
                    }
                    handleProviderResponse(resp, payload);
                    ingestApiResponse(resp);
                    return resp;
                }, function (error) {
                    if (logoutRequest) restoreProviderListAfterFailedLogout();
                    throw error;
                });
            };
            wrappedCallApi3.__balanceCacheWrapped = true;
            window.callApi3 = wrappedCallApi3;
        }

        // callApi is callback based in the legacy templates. Wrap only the
        // success callback and preserve all arguments/signatures.
        if (typeof window.callApi === 'function' && !window.callApi.__balanceCacheWrapped) {
            var originalCallApi = window.callApi;
            var wrappedCallApi = function () {
                var args = Array.prototype.slice.call(arguments);
                if (isLogoutApiUrl(args[0])) beginMemberLogout();
                var payload = args.length > 1 ? args[1] : null;
                if (typeof args[2] === 'function') {
                    var success = args[2];
                    args[2] = function (resp) {
                        if (isLogoutApiUrl(args[0])) {
                            if (resp && resp.success === true) expireMemberSession('logout_success');
                            else if (resp && resp.success === false) restoreProviderListAfterFailedLogout();
                        }
                        handleProviderResponse(resp, payload);
                        ingestApiResponse(resp);
                        return success.apply(this, arguments);
                    };
                }
                return originalCallApi.apply(this, args);
            };
            wrappedCallApi.__balanceCacheWrapped = true;
            window.callApi = wrappedCallApi;
        }

        if (typeof window.callApi2 === 'function' && !window.callApi2.__balanceCacheWrapped) {
            var originalCallApi2 = window.callApi2;
            var wrappedCallApi2 = function () {
                var args = Array.prototype.slice.call(arguments);
                if (isLogoutApiUrl(args[0])) beginMemberLogout();
                var payload = args.length > 2 ? args[2] : null;
                if (typeof args[3] === 'function') {
                    var success = args[3];
                    args[3] = function (resp) {
                        if (isLogoutApiUrl(args[0])) {
                            if (resp && resp.success === true) expireMemberSession('logout_success');
                            else if (resp && resp.success === false) restoreProviderListAfterFailedLogout();
                        }
                        handleProviderResponse(resp, payload);
                        ingestApiResponse(resp);
                        return success.apply(this, arguments);
                    };
                }
                return originalCallApi2.apply(this, args);
            };
            wrappedCallApi2.__balanceCacheWrapped = true;
            window.callApi2 = wrappedCallApi2;
        }

        // Some LIVE PROD code uses jQuery.ajax directly instead of callApi*.
        // ajaxSuccess provides a final safety net for successful listBalance
        // responses. Duplicate ingestion is idempotent.
        if (window.jQuery && !window.jQuery(document).data('balanceCacheAjaxBridge')) {
            window.jQuery(document).data('balanceCacheAjaxBridge', true);

            // Detect the actual logout HTTP request (after confirmation).
            // This also covers logout flows using jQuery.ajax directly.
            window.jQuery(document).on('ajaxSend.balanceCacheLogout', function (_event, _xhr, settings) {
                if (settings && isLogoutApiUrl(settings.url)) beginMemberLogout();
            });

            window.jQuery(document).on('ajaxComplete.balanceCacheLogout', function (_event, xhr, settings) {
                if (!settings || !isLogoutApiUrl(settings.url)) return;
                var resp = xhr && xhr.responseJSON;
                if (!resp && xhr && typeof xhr.responseText === 'string') {
                    resp = safeParse(xhr.responseText);
                }
                if ((xhr && (xhr.status < 200 || xhr.status >= 300))
                        || (resp && resp.success === false)) {
                    restoreProviderListAfterFailedLogout();
                } else {
                    expireMemberSession('logout_ajax_success');
                }
            });

            // Includes non-2xx API responses: ajaxSuccess alone cannot see a
            // 401 body carrying session-expired code 14000.
            window.jQuery(document).on('ajaxComplete.balanceCacheSession', function (_event, xhr) {
                var resp = xhr && xhr.responseJSON;
                if (!resp && xhr && typeof xhr.responseText === 'string') {
                    resp = safeParse(xhr.responseText);
                }
                if (resp && Number(resp.code) === 14000) {
                    expireMemberSession('ajax_session_expired');
                }
            });

            window.jQuery(document).on('ajaxSuccess.balanceCache', function (_event, xhr, settings) {
                var resp = xhr && xhr.responseJSON;
                if (!resp && xhr && typeof xhr.responseText === 'string') {
                    resp = safeParse(xhr.responseText);
                }
                var payload = settings ? settings.data : null;
                handleProviderResponse(resp, payload);
                ingestApiResponse(resp);
            });
        }
    }

    installApiResponseBridge();

    // Initialize locked providers from server-side user_data.disabledProvider.
    // Persistence remains in Spring Session/Redis, not in the balance localStorage object.
    initialDisabledProviderRaw.split(',').forEach(function (value) {
        var code = normalizeCode(value);
        if (!code) return;
        lockedProviders[code] = { messageCode: PROVIDER_LOCKED_CODE, updatedAt: Date.now() };
        renderProviderLocked(code);
    });

    // Remove the temporary V6 providerStates field if an older POC cache exists.
    if (storageKey) {
        var currentEnvelope = readEnvelope();
        writeEnvelope(currentEnvelope);
    }

    // If a page loads another legacy script after this JSP include, give it one
    // more chance to be wrapped without polling indefinitely.
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', installApiResponseBridge, { once: true });
    } else {
        setTimeout(installApiResponseBridge, 0);
    }

    // Preload listPv after the page scripts have finished parsing. LIVE PROD
    // app.js/toto.js expects this metadata synchronously when the user clicks
    // "check all balance"; without preloading, MAIN can refresh while every
    // provider path short-circuits on a missing/stale listPv.
    function preloadProviderList() {
        ensureProviderList(false);
    }
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', preloadProviderList, { once: true });
    } else {
        setTimeout(preloadProviderList, 0);
    }

    // Desktop header Check All: intercept the existing reload icon and run an
    // explicit Promise-based batch. app.js / toto.js remain untouched, but their
    // legacy counter/timer cannot expose TOTAL before provider requests finish.
    document.addEventListener('click', function (event) {
        var node = event.target;
        var control = null;
        while (node && node !== document) {
            if (node.id === 'iconReload') {
                control = node;
                break;
            }
            node = node.parentNode;
        }
        if (!control) return;

        event.preventDefault();
        event.stopPropagation();
        event.stopImmediatePropagation();
        checkAllHeaderBalances();
    }, true);

    // Do not clear data in confirm_signout(): user may cancel the dialog.
    // Cleanup is performed only after confirmed logout / 14000 / anonymous SSR.
})(window);
</script><script src="https://cdn.robotaset.com/assets/js/common/Alert.min.js"></script>
		<script src="https://cdn.robotaset.com/assets/js/common/sha256.min.js"></script>
		<script src="https://cdn.robotaset.com/assets/js/pages/AccountValidation.min.js"></script>
		<script src="https://cdn.robotaset.com/assets/js/pages/240715_Account.min.js"></script>
		<script src="https://cdn.robotaset.com/assets/js/pages/240715_login.min.js"></script>
	<!-- Start of LiveChat (www.livechat.com) code -->
<script>
    window.__lc = window.__lc || {};
    window.__lc.license = 15907821;
    ;(function(n,t,c){function i(n){return e._h?e._h.apply(null,n):e._q.push(n)}var e={_q:[],_h:null,_v:"2.0",on:function(){i(["on",c.call(arguments)])},once:function(){i(["once",c.call(arguments)])},off:function(){i(["off",c.call(arguments)])},get:function(){if(!e._h)throw new Error("[LiveChatWidget] You can't use getters before load.");return i(["get",c.call(arguments)])},call:function(){i(["call",c.call(arguments)])},init:function(){var n=t.createElement("script");n.async=!0,n.type="text/javascript",n.src="https://cdn.livechatinc.com/tracking.js",t.head.appendChild(n)}};!n.__lc.asyncInit&&e.init(),n.LiveChatWidget=n.LiveChatWidget||e}(window,document,[].slice))
</script>
<noscript><a href="https://www.livechat.com/chat-with/15907821/" rel="nofollow">Chat with us</a>, powered by <a href="https://www.livechat.com/?welcome" rel="noopener nofollow" target="_blank">LiveChat</a></noscript>
<!-- End of LiveChat code -->
<script>
window.openGameUrl = window.openGameUrl || function(url) {
    var ua = navigator.userAgent || '';
    if (/Mobile|Android/i.test(ua)) {
        window.location.href = url;
    } else {
        window.open(url, '_blank');
    }
};
</script>
<script>
            $(document).ready(function () {
                $(document).on('click', 'li.game a', function () {
                    var target = $(this).attr("data-url");

                    if ($(this).closest(".game").hasClass("sub")) {
                        location.href = target;
                    } else {
                        do_login(target);
                        return false;
                    }
                });

                $(document).on('click', '.btn-game', function () {
                    var target = $(this).attr("data-url");

                    do_login(target);
                });

                $(document).on('click', '.close_modal', function () {
                    close_mask();
                });
            });
        </script>
    <div class="reward_pop" style="display:none;" id="BannerPop">
			<div class="sub_color">
				<div class="logo_wrap">
					<img loading="lazy" decoding="async" src="https://cdn.robotaset.com/assets/tpl/e360fd1668/images/logo.gif" alt="LogoVio77">
				</div>
			</div>
			<button class="close_icon btn" id="CloseBannerPop" onclick="closePopupBanner(15);">Tutup</button>
			<div class="card reward_content">
				<a href="https://jali.pro/spygroup" aria-label="PARTNERSHIP RUTO77" title="PARTNERSHIP RUTO77" class="banner-popup-link" onclick="closePopupBanner(15);"><img loading="lazy" decoding="async" src="https://barangtupunyokito.sgp1.cdn.digitaloceanspaces.com/spy77/ms/ruto-partner.jpg" alt="PARTNERSHIP RUTO77"></a></div>
		</div>
		<script>popupBannerTimer();</script>
	<div class="modal fade" id="LoginPopupModal" tabindex="-1" role="dialog" aria-labelledby="LoginPopupTitle" aria-hidden="true">
			<div class="modal-dialog modal-dialog-centered" role="document">
				<div class="modal-content">
					<div class="modal-header">
						<h5 class="modal-title">Masuk</h5>
						<button type="button" class="close close-modal" data-dismiss="modal" aria-label="Close">
							<span aria-hidden="true">&times;</span>
						</button>
					</div>
					<div class="modal-body">
						<form id="LoginPopup" action="" method="POST">
							<div class="form-group clearfix">
								<label for="username" class="col-sm-4 col-12">Nama Pengguna<span>*</span></label>
								<input name="username" id="LP_Username" class="col-sm-8 col-12" type="text" minlength="5" maxlength="16" required="required" placeholder='Nama pengguna harus minimal antara 5 dan 16 karakter Dan gunakan alfanumerik'>
							</div>
							<div class="form-group clearfix">
								<label for="password" class="col-sm-4 col-12">Kata Sandi<span>*</span></label>
								<input name="password" id="LP_Password" class="col-sm-8 col-12" type="password" minlength="6" maxlength="16" required="required" placeholder='Panjang kata sandi minimal harus antara 6 dan 16 karakter'>
							</div>
						 	<div class="form-group clearfix">
						 		<div class="row">
						 			<div class="col-sm-6 offset-sm-4" style="padding-left:0;">
								   		<input type="hidden" name="target" id="target">
										<input type="hidden" id="gmsb">
								   		<button class="bttn-login" id="btnLoginPopup" type="submit">Masuk</button>
						 			</div>
						 		</div>
						 	</div>
						</form>
					</div>
				</div>
			</div>
		</div>

		<div class="modal fade" id="CaptchaPopupModal" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="CaptchaPopupTitle" aria-describedby="CaptchaPopupDesc" aria-hidden="true">
			<div class="modal-dialog modal-dialog-centered" role="document">
				<div class="modal-content">
					<div class="modal-header">
						<h5 id="CaptchaPopupTitle" class="modal-title">Masuk</h5>
						<button type="button" class="close close-modal" aria-label="" data-dismiss="modal" aria-label='Tutup modal Captcha'>
							<span aria-hidden="true">&times;</span>
						</button>
					</div>
					<div class="modal-body" id="CaptchaPopupDesc">
						<form id="CaptchaPopup" method="POST" autocomplete="off">
							<div class="form-group">
								<div class="row clearfix">
									<label for="captcha" class="col-md-3">Captcha</label>
									<input type="text" class="form-control col-md-5" name="captcha" maxlength="4" id="LP_Captcha" placeholder="Captcha" required>
									<div class="col-md-4">
										<img loading="lazy" src="/captcha/login/1793625994336" alt='Gambar captcha' id="imgCaptcha" class="img-captcha img-thumbnail" width="100" height="32" align="left">
										<i class="fas fa-redo-alt" id="ReloadCaptcha" role="button" aria-label='Muat ulang Captcha'></i>
									</div>
								</div>
							</div>
						 	<div class="form-group clearfix">
						 		<div class="row">
						 			<div class="col-sm-9 offset-sm-3" style="padding-left:0;">
								   		<button class="bttn-login" id="BtnCaptchaPopup" type="submit" style="margin-left:0;">Masuk Sekarang</button>
						 			</div>
						 		</div>
						 	</div>
						</form>
					</div>
				</div>
			</div>
		</div>
		<script>
function getIconEventTag(gmsbevent) {
	var tags = {
        1: { alt: 'hot', src: 'https://cdn.robotaset.com/assets/images/provider/pp-hot-tag-w-frame.png' },
        2: { alt: 'new', src: 'https://cdn.robotaset.com/assets/images/provider/pp-new-tag-w-frame.png' },
        3: { alt: 'exclusive', src: 'https://cdn.robotaset.com/assets/images/provider/pp-excl-tag.png' }
    };
    var tag = tags[gmsbevent];
    return tag
        ? '<img loading="lazy" alt="' + tag.alt + '" class="game-icon-frame" style="width:100%" src="' + tag.src + '">'
        : '';
}
</script>
<!-- Transfer Balance Modal -->


    
    
        <div class="modal fade transfer-balance-modal-component" id="transferBalanceModal" tabindex="-1" role="dialog"
             aria-labelledby="transferBalanceModalLabel" aria-hidden="true"
             data-backdrop="static" data-keyboard="false">
            <div class="modal-dialog modal-dialog-centered" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <div class="transfer-balance-title-wrapper">
                            <h5 class="modal-title"
                                id="transferBalanceModalLabel">Transfer Saldo</h5>
                            <button type="button" class="transfer-balance-info-btn" id="transferBalanceInfoBtn" aria-label="Info">
                                <i class="fas fa-question-circle"></i>
                            </button>
                        </div>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <div class="transfer-provider-locked-notice" role="alert" aria-live="assertive" style="display:none;">
                        <div class="transfer-provider-locked-heading">
                            <i class="fas fa-lock" aria-hidden="true"></i>
                            <strong>Terkunci</strong>
                        </div>
                        <p>Akun anda saat ini tidak diperbolehkan untuk membuka permainan ini. Silahkan hubungi Customer Service untuk informasi lebih lanjut.</p>
                        <button type="button" class="btn-check-provider-unlock" aria-label="Check provider lock status">
                            <i class="fas fa-sync-alt" aria-hidden="true"></i>
                            <span class="provider-unlock-button-label"></span>
                        </button>
                        <p class="transfer-provider-unlock-feedback" role="status" aria-live="polite" style="display:none;"></p>
                    </div>
                        <form id="transferBalanceForm">
                            <div class="form-group textfield-wrap">
                                <div class="row">
                                    <label for="walletBalance" class="col-sm-5">Saldo Dompet</label>
                                    <div class="row col-sm-7">
                                        <div class="input-field">
                                            <div class="transfer-main-balance-field">
                                                <input type="text" class="form-control mb-0" id="walletBalance" readonly>
                                                <button type="button" class="btn-retry-main-balance" style="display:none;"
                                                        aria-label="Retry MAIN balance">
                                                    <i class="fas fa-redo-alt" aria-hidden="true"></i>
                                                    <span class="retry-main-label"></span>
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="form-group textfield-wrap">
                                <div class="row">
                                    <label for="providerBalance" class="col-sm-5">Saldo pada <span
                                            id="providerNameDisplay"></span></label>
                                    <div class="row col-sm-7">
                                        <div class="input-field">
                                            <input type="text" class="form-control" id="providerBalance" readonly>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="form-group textfield-wrap">
                                <div class="row">
                                    <label for="transferAmount" class="col-sm-5">Jumlah</label>
                                    <div class="row col-sm-7">
                                        <div class="input-field">
                                            <input type="number" class="form-control mb-0" id="transferAmount" min="1" step="1" inputmode="numeric" placeholder="0.00">
                                            <div class="invalid-feedback" id="transferAmountError"></div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="form-group textfield-wrap">
                                <div class="row">
                                    <label class="col-sm-5"></label>
                                    <div class="row col-sm-7">
                                        <div class="custom-checkbox-wrapper">
                                            <input type="checkbox" class="custom-checkbox-input" id="transferAll">
                                            <label class="custom-checkbox-label" for="transferAll">
                                                <span class="checkbox-slider"></span>
                                                <span class="checkbox-text">Masukan semua</span>
                                            </label>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </form>
                        
                        <div class="transfer-balance-status" role="status" aria-live="polite" style="display:none; margin-bottom:10px;"></div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary btn-preview" id="btnPreview">

                                <span>Coba lihat dulu</span>
                            </button>
                            <button type="button" class="btn btn-primary" id="btnTransfer">
                                <i class="fas fa-play me-2"></i>Transfer saldo & main
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    


<!-- Transfer Balance Info Tooltip -->
<div class="transfer-balance-tooltip" id="transferBalanceTooltip" style="display: none;">
    <div class="transfer-balance-tooltip-content">
        <button type="button" class="transfer-balance-tooltip-close" aria-label="Close">
            <i class="fas fa-times"></i>
        </button>
        <h6 class="transfer-balance-tooltip-title">Transfer Saldo</h6>
        <div class="transfer-balance-tooltip-body">
            <p><strong>Saldo Dompet:</strong> Saldo yang tersedia di wallet utama Anda.</p>
            <p><strong>Saldo pada:</strong> Saldo yang tersedia di provider game.</p>
            <p><strong>Jumlah:</strong> Masukkan jumlah yang ingin ditransfer dari wallet ke provider game.</p>
            <p><strong>:</strong> Centang untuk mentransfer seluruh saldo wallet ke provider game.</p>
        </div>
    </div>
</div>



<style>
    /* A locked provider is an information-only modal, never a transfer form. */
    .transfer-balance-modal-component .transfer-provider-locked-notice {
        padding: 16px 14px;
        margin: 8px 0;
        border: 1px solid rgba(218, 165, 32, 0.5);
        border-radius: 7px;
        font-size: 14px;
        line-height: 1.55;
        text-align: left;
    }
    .transfer-balance-modal-component .transfer-provider-locked-heading {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-bottom: 10px;
        font-size: 16px;
    }
    .transfer-balance-modal-component .transfer-provider-locked-notice p {
        margin: 10px 0 0 0;
    }

    /* MAIN wallet retry is independent from provider balance and transfer retry. */
    .transfer-balance-modal-component .transfer-main-balance-field {
        display: flex;
        align-items: center;
        gap: 7px;
        width: 100%;
        min-width: 0;
    }
    .transfer-balance-modal-component .transfer-main-balance-field #walletBalance {
        flex: 1 1 0;
        min-width: 0;
        width: 100%;
    }
    .transfer-balance-modal-component .btn-retry-main-balance {
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 5px;
        border: 1px solid #d6a125;
        border-radius: 5px;
        background: #d6a125;
        color: #151515;
        padding: 7px 9px;
        font-size: 12px;
        line-height: 1.3;
        font-weight: 600;
        cursor: pointer;
        white-space: nowrap;
    }
    .transfer-balance-modal-component .btn-retry-main-balance:hover {
        background: #efba37;
    }
    .transfer-balance-modal-component .btn-retry-main-balance:focus-visible {
        outline: 2px solid #ffffff;
        outline-offset: 2px;
    }
    .transfer-balance-modal-component .btn-retry-main-balance:disabled {
        opacity: 0.55;
        cursor: wait;
    }

    /* Mobile: keep the failed-balance text readable; retry lives below MAIN. */
    .transfer-balance-modal-component.mobile-modal .transfer-main-balance-field {
        flex-direction: column;
        align-items: stretch;
    }
    .transfer-balance-modal-component.mobile-modal .btn-retry-main-balance {
        width: 100%;
        min-height: 36px;
    }

    /* Custom Checkbox Toggle Switch Style - Scoped to transfer balance modal */
    .transfer-balance-modal-component .custom-checkbox-wrapper {
        position: relative;
        display: inline-block;
    }

    .transfer-balance-modal-component .custom-checkbox-input {
        position: absolute;
        opacity: 0;
        width: 0;
        height: 0;
    }

    .transfer-balance-modal-component .custom-checkbox-label {
        display: flex;
        align-items: center;
        cursor: pointer;
        user-select: none;
        gap: 12px;
    }

    .transfer-balance-modal-component .checkbox-slider {
        position: relative;
        display: inline-block;
        width: 38px;
        height: 26px;
        background-color: #ccc;
        border-radius: 26px;
        transition: background-color 0.3s ease;
        box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
        margin-right: 0;
    }

    .transfer-balance-modal-component .checkbox-slider::before {
        content: "";
        position: absolute;
        width: 20px;
        height: 20px;
        left: 3px;
        top: 3px;
        background-color: white;
        border-radius: 50%;
        transition: transform 0.3s ease;
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
    }

    .transfer-balance-modal-component .custom-checkbox-input:checked + .custom-checkbox-label .checkbox-slider {
        background-color: #28a745;
    }

    .transfer-balance-modal-component .custom-checkbox-input:checked + .custom-checkbox-label .checkbox-slider::before {
        transform: translateX(12px);
    }

    .transfer-balance-modal-component .custom-checkbox-input:focus + .custom-checkbox-label .checkbox-slider {
        box-shadow: 0 0 0 3px rgba(40, 167, 69, 0.25);
    }

    .transfer-balance-modal-component .checkbox-text {
        font-weight: 500;
        color: #666;
        font-size: 14px;
        vertical-align: 8px;
    }

    .transfer-balance-modal-component .custom-checkbox-input:checked + .custom-checkbox-label .checkbox-text {
        color: #28a745;
        font-weight: 600;
    }

    /* Button Icon Spacing - Scoped to transfer balance modal */
    .transfer-balance-modal-component .btn i.me-2 {
        margin-right: 0.5rem;
    }

    /* Disabled button styling for desktop */
    .transfer-balance-modal-component .modal-footer .btn:disabled {
        opacity: 0.6;
        cursor: not-allowed;
    }

    /* Disabled checkbox styling for desktop */
    .transfer-balance-modal-component .custom-checkbox-input:disabled + .custom-checkbox-label {
        opacity: 0.6;
        cursor: not-allowed;
    }

    /* Disabled input styling for desktop */
    .transfer-balance-modal-component .input-field .form-control:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        background-color: #e9ecef !important;
    }

    /* Preview button styling for desktop - low priority */
    .transfer-balance-modal-component .modal-footer .btn-preview {
        background-color: transparent !important;
        color: #adb5bd !important;
        border: 1px solid transparent !important;
        font-size: 0.875rem !important;
        font-weight: 400 !important;
        padding: 0.5rem 0.75rem !important;
        opacity: 0.5 !important;
    }

    .transfer-balance-modal-component .modal-footer .btn-preview:hover {
        background-color: transparent !important;
        color: #6c757d !important;
        opacity: 0.7 !important;
        text-decoration: underline !important;
    }

    .transfer-balance-modal-component .modal-footer .btn-preview:focus {
        box-shadow: none !important;
        outline: none !important;
    }

    /* Input validation styling */
    .transfer-balance-modal-component .form-control.is-invalid {
        border-color: #dc3545 !important;
        box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25) !important;
    }

    .transfer-balance-modal-component .invalid-feedback {
        display: block;
        width: 100%;
        margin-top: 0.25rem;
        font-size: 0.875rem;
        color: #ff4d4f !important;
    }

    /* Input styling for desktop - Readonly inputs (faded) */
    .transfer-balance-modal-component .input-field .form-control[readonly] {
        background-color: #3d3d3d !important;
        border-color: #e9ecef !important;
        color: white !important;
        cursor: not-allowed;
    }

    /* Input styling for desktop - Editable inputs (focused) */
    .transfer-balance-modal-component .input-field .form-control:not([readonly]) {
        background-color: #ffffff !important;
        border: 2px solid #007bff !important;
        color: #212529 !important;
        box-shadow: 0 0 0 0.15rem rgba(0, 123, 255, 0.15) !important;
        font-weight: 500;
    }

    .transfer-balance-modal-component .input-field .form-control:not([readonly]):focus {
        border-color: #0056b3 !important;
        box-shadow: 0 0 0 0.3rem rgba(0, 123, 255, 0.35) !important;
        outline: 0;
        background-color: #f8f9ff !important;
    }

    .transfer-balance-modal-component .input-field .form-control:not([readonly]):hover {
        border-color: #0056b3 !important;
        box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25) !important;
    }

    /* Title wrapper for desktop */
    .transfer-balance-modal-component .modal-header .transfer-balance-title-wrapper {
        display: flex;
        align-items: center;
        gap: 0.5rem;
    }

    .transfer-balance-modal-component .transfer-balance-info-btn {
        background: none;
        border: none;
        color: #adb5bd;
        font-size: 0.85rem;
        cursor: pointer;
        padding: 0.2rem;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.2s ease;
        opacity: 0.6;
    }

    .transfer-balance-modal-component .transfer-balance-info-btn:hover {
        color: #6c757d;
        opacity: 0.8;
        transform: scale(1.05);
    }

    .transfer-balance-modal-component .transfer-balance-info-btn:focus {
        outline: 1px solid #adb5bd;
        outline-offset: 1px;
        border-radius: 50%;
        opacity: 0.8;
    }

    /* Tooltip Popup */
    .transfer-balance-tooltip {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.6);
        z-index: 10000;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 1rem;
    }

    .transfer-balance-tooltip-content {
        background: #ffffff;
        border-radius: 8px;
        max-width: 500px;
        width: 100%;
        max-height: 80vh;
        overflow-y: auto;
        box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
        position: relative;
        padding: 1.5rem;
    }

    .transfer-balance-tooltip-close {
        position: absolute;
        top: 0.75rem;
        right: 0.75rem;
        background: none;
        border: none;
        font-size: 1.25rem;
        color: #666;
        cursor: pointer;
        padding: 0.25rem;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: color 0.2s ease;
    }

    .transfer-balance-tooltip-close:hover {
        color: #000;
    }

    .transfer-balance-tooltip-title {
        margin: 0 0 1rem 0;
        font-size: 1.25rem;
        font-weight: 600;
        color: #333;
        padding-right: 2rem;
    }

    .transfer-balance-tooltip-body {
        color: #555;
        line-height: 1.6;
    }

    .transfer-balance-tooltip-body p {
        margin-bottom: 0.75rem;
    }

    .transfer-balance-tooltip-body p:last-child {
        margin-bottom: 0;
    }

    .transfer-balance-tooltip-body strong {
        color: #333;
        font-weight: 600;
    }
    /* Inline transfer result: accessible for both desktop and mobile themes. */
    .transfer-balance-modal-component .transfer-balance-status {
        padding: 10px 12px;
        border-radius: 6px;
        font-size: 13px;
        line-height: 1.45;
        overflow-wrap: anywhere;
        text-align: left;
    }
    .transfer-balance-modal-component .transfer-balance-status.is-error {
        color: #ff4d4f !important;
        background: rgba(180, 37, 37, 0.2);
        border: 1px solid rgba(235, 90, 90, 0.6);
    }
    .transfer-balance-modal-component .transfer-balance-status.is-success {
        color: #d4ffda;
        background: rgba(34, 139, 64, 0.18);
        border: 1px solid rgba(80, 185, 111, 0.6);
    }
    .transfer-balance-modal-component .transfer-balance-status-title {
        display: flex;
        align-items: center;
        gap: 7px;
        font-weight: 600;
        margin-bottom: 4px;
    }
    .transfer-balance-modal-component .transfer-balance-countdown-seconds {
        font-weight: 700;
        font-variant-numeric: tabular-nums;
    }
    /* Check unlock status on demand; no polling or navigation refresh. */
    .transfer-balance-modal-component .btn-check-provider-unlock {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        gap: 8px;
        margin-top: 10px;
        padding: 9px 14px;
        border: 1px solid currentColor;
        border-radius: 6px;
        background: transparent;
        color: inherit;
        cursor: pointer;
        font: inherit;
    }
    .transfer-balance-modal-component .btn-check-provider-unlock:disabled {
        opacity: .55;
        cursor: wait;
    }
    .transfer-balance-modal-component .transfer-provider-unlock-feedback {
        margin: 10px 0 0;
        font-size: 12px;
        line-height: 1.45;
    }
    /* Distinguish API/status failures from the informational locked state. */
    .transfer-balance-modal-component .transfer-provider-unlock-feedback.is-error {
        color: #ff4d4f !important;
    }
    /* Read-only balance fields also display failure text. Their existing desktop
       and mobile theme rules must not override the error color. */
    .transfer-balance-modal-component #walletBalance.transfer-balance-load-error,
    .transfer-balance-modal-component #providerBalance.transfer-balance-load-error {
        color: #ff4d4f !important;
    }
</style>

<script>
    // Language strings for validation messages
    var transferBalanceLang = {
        errorAmountNegative: 'Jumlah tidak boleh negatif',
        errorAmountExceed: 'Jumlah tidak boleh melebihi saldo dompet',
        errorAmountZero: 'Jumlah harus lebih dari 0',
        errorAmountInteger: "Jumlah transfer harus berupa bilangan bulat (tanpa desimal).",
        // Localized message for an unsuccessful or uncertain transfer request.
        // Never offer an automatic retry here: the backend may have processed it.
        transferOutcomeUnknown: "Transfer saldo gagal. Silakan periksa saldo atau riwayat transaksi sebelum mencoba kembali.",
        verificationUnavailable: "Gagal memverifikasi saldo atau riwayat transfer provider. Silakan coba lagi.",
        mainBalanceUnavailable: "Saldo gagal dimuat",
        transferAlreadyRecorded: "Transfer ke provider ini sudah tercatat. Silakan periksa saldo atau riwayat transaksi.",
        checkProviderStatus: "Periksa status",
        checkingProviderStatus: "Memeriksa status...",
        stillProviderLocked: "Provider masih terkunci.",
        providerStatusUnavailable: "Gagal memeriksa status provider. Silakan coba lagi."
    };

    // Global flag for player transfer balance (defaults to false if not set)

    // Transfer Balance Modal Handler
    var transferBalanceModal = {
        currentProvider: null,
        gameUrl: null,
        // [IDTF-2100] null means "not known yet", which is different from a
        // real balance of 0. Starting these at 0 was what let the form validate
        // and submit against a balance nobody had confirmed.
        walletBalance: null,
        providerBalance: null,
        balanceRequestVersion: 0,
        providerBalanceLoading: false,
        mainBalanceLoading: false,
        // Provider-first-transfer decisions use only the member-scoped listPv.
        transferRechecking: false,
        retryMainVerificationRequired: false,
        // One explicit retry click may verify server-side balances and then submit.
        // Never create a second transfer from a background callback alone.
        transferAlreadyRecorded: false,
        unlockCheckPending: false,
        providerListLoading: false,
        transferPending: false,
        // Keep a successful transfer visible before launching the chosen game.
        redirectPending: false,
        redirectTimer: null,
        // An ambiguous result keeps its warning but no longer locks the modal forever.
        // A manual retry is allowed after a short cooldown, with fresh balances first.
        transferUncertain: false,
        transferFailed: false,
        failureCooldown: false,
        failureCooldownTimer: null,
        transferButtonLabel: null,
        transferMobileButtonLabel: null,

        startFailureCooldown: function () {
            var self = this;
            if (self.failureCooldownTimer !== null) {
                window.clearTimeout(self.failureCooldownTimer);
                self.failureCooldownTimer = null;
            }
            self.transferFailed = true;
            self.failureCooldown = true;
            self.enableControls(); // Preview stays clickable, transfer stays disabled.
            self.failureCooldownTimer = window.setTimeout(function () {
                self.failureCooldownTimer = null;
                self.failureCooldown = false;
                self.enableControls(); // Transfer CTA clickable; balance guard still applies.
            }, 3000);
        },

        showStatus: function (message, type) {
            // text() prevents backend error strings from being interpreted as HTML.
            $('.transfer-balance-status')
                .removeClass('is-error is-success')
                .addClass(message ? (type === 'success' ? 'is-success' : 'is-error') : '')
                .attr('role', type === 'success' ? 'status' : 'alert')
                .text(message || '')
                .toggle(!!message);
        },

        showRedirectCountdown: function (seconds) {
            var $status = $('.transfer-balance-status');
            if (seconds === 3) {
                // Only static, trusted UI markup is inserted here; errors still use text().
                $status.removeClass('is-error').addClass('is-success')
                    .attr('role', 'status')
                    .html('<div class="transfer-balance-status-title">'
                        + '<i class="fas fa-check-circle" aria-hidden="true"></i>'
                        + '<span>Transfer saldo berhasil!</span></div>'
                        + '<div>Mengalihkan ke permainan dalam '
                        + '<strong class="transfer-balance-countdown-seconds">3</strong> detik...</div>')
                    .show();
            }
            $status.find('.transfer-balance-countdown-seconds').text(String(seconds));
        },

        startRedirectCountdown: function (version, providerCode) {
            var self = this;
            if (self.redirectTimer !== null) {
                window.clearTimeout(self.redirectTimer);
                self.redirectTimer = null;
            }
            var secondsLeft = 3;
            function tick() {
                self.redirectTimer = null;
                if (!self.redirectPending || version !== self.balanceRequestVersion
                        || providerCode !== self.currentProvider) return;
                if (secondsLeft === 0) {
                    self.redirectPending = false;
                    self.launchGame(true);
                    return;
                }
                self.showRedirectCountdown(secondsLeft);
                secondsLeft -= 1;
                self.redirectTimer = window.setTimeout(tick, 1000);
            }
            tick();
        },

        isProviderBlocked: function () {
            return !!(this.currentProvider && (
                balanceCache.isProviderLocked(this.currentProvider) ||
                balanceCache.isProviderMaintenance(this.currentProvider)));
        },

        providerStatusLabel: function () {
            if (balanceCache.isProviderLocked(this.currentProvider)) {
                return 'Terkunci' || 'Provider Locked';
            }
            if (balanceCache.isProviderMaintenance(this.currentProvider)) {
                return 'Pemeliharaan' || 'Pemeliharaan';
            }
            return null;
        },

        // Keep provider-specific lock messaging separate from MAIN balance errors.
        // This state is based on the recognized locked status (19175), never on
        // generic -1000 failures or text matching in an error message.
        syncLockedNotice: function (forceHide) {
            var locked = !forceHide && !!this.currentProvider
                && balanceCache.isProviderLocked(this.currentProvider);
            var $modal = $('#transferBalanceModal');
            $modal.find('.transfer-provider-locked-notice').toggle(locked);
            $modal.find('.transfer-balance-body > form, .modal-body > form, .modal-footer').toggle(!locked);
            $modal.find('.transfer-balance-info-btn').toggle(!locked);
            $modal.find('.btn-check-provider-unlock')
                .prop('disabled', this.unlockCheckPending)
                .find('.provider-unlock-button-label')
                .text(this.unlockCheckPending ? transferBalanceLang.checkingProviderStatus
                    : transferBalanceLang.checkProviderStatus);
            if (locked) $modal.find('.transfer-balance-status').hide();
            else $modal.find('.transfer-provider-unlock-feedback').removeClass('is-error').hide().text('');
            // Include the selected provider's display name in the locked title.
            // The name is already resolved from the game model when loadBalances runs.
            var lockedTitle = '';
            if (locked) {
                var providerName = $.trim($modal.find('#providerNameDisplay').text())
                    || this.resolveProviderName(this.currentProvider,
                        window.pendingGameLaunch && window.pendingGameLaunch.$btn)
                    || this.currentProvider;
                var lockedLabel = $.trim($modal.find('.transfer-provider-locked-heading strong').first().text());
                lockedTitle = providerName + ' - ' + lockedLabel;
            }
            $modal.find('.transfer-balance-title, #transferBalanceModalLabel').each(function () {
                var $title = $(this);
                if (!$title.data('original-transfer-title')) {
                    $title.data('original-transfer-title', $title.text());
                }
                $title.text(locked ? lockedTitle : $title.data('original-transfer-title'));
            });
        },

        // The MAIN balance response may include a fresh locked-provider list
        // derived from backend user.dsbpv. Consume it only in this modal;
        // other pages, including /bank/transfer, are not modified.
        syncDisabledProvidersFromMain: function (response) {
            // Missing disabledProviders is NOT a list of zero locked providers.
            // Only a successful, backend-derived snapshot can authorize unlock.
            if (!response || response.success !== true || !response.data
                    || !Array.isArray(response.data.disabledProviders)) return false;
            var code = this.normalizeProviderCode(this.currentProvider);
            if (!code) return false;
            var isLocked = response.data.disabledProviders.some(function (item) {
                return String(item || '').trim().toUpperCase() === code;
            });
            if (isLocked && !balanceCache.isProviderLocked(code)) {
                balanceCache.lockProvider(code, 19175);
            } else if (!isLocked && balanceCache.isProviderLocked(code)) {
                balanceCache.unlockProvider(code);
            }
            return true;
        },

        // A locked popup may refresh its status explicitly, without reloading
        // the page or polling. This action NEVER executes setTransfer or launchGame.
        checkProviderUnlock: function () {
            var self = this;
            var code = self.currentProvider;
            if (!code || !window.pendingGameLaunch || !balanceCache.isProviderLocked(code)
                    || self.unlockCheckPending || self.transferPending || self.redirectPending) return;

            var version = self.balanceRequestVersion;
            self.unlockCheckPending = true;
            $('.transfer-provider-unlock-feedback').removeClass('is-error').hide().text('');
            self.syncLockedNotice();

            // Force actual backend refresh, not bal.v1 TTL cache. The response
            // includes authoritative dsbpv-derived disabledProviders if available.
            var seq = balanceCache.beginRequest('MAIN', true);
            callApi3('/api/wallet/main/getBalance', 'GET', null).then(function (response) {
                balanceCache.endRequest('MAIN', seq);
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                if (!response || response.success !== true || !response.data
                        || !Array.isArray(response.data.listBalance)
                        || !Array.isArray(response.data.disabledProviders)) {
                    throw new Error('MAIN provider status response incomplete');
                }
                // Sync before writing wallets: locked providers must never be
                // allowed to reuse stale provider balances.
                self.syncDisabledProvidersFromMain(response);
                balanceCache.setFromListBalance(response.data.listBalance, seq);
                if (balanceCache.isProviderLocked(code)) {
                    $('.transfer-provider-unlock-feedback')
                        .removeClass('is-error')
                        .text(transferBalanceLang.stillProviderLocked).show();
                    return;
                }
                // The lock was removed. Restore the existing normal first-transfer
                // UI and load provider balance only if member history needs it.
                self.unlockCheckPending = false;
                self.resetForm();
                self.loadBalances(code);
            }).catch(function () {
                balanceCache.endRequest('MAIN', seq);
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                // Network/error response must never clear a previously locked state.
                $('.transfer-provider-unlock-feedback')
                    .addClass('is-error')
                    .text(transferBalanceLang.providerStatusUnavailable).show();
            }).then(function () {
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                self.unlockCheckPending = false;
                self.syncLockedNotice();
            });
        },

        handleProviderUnavailable: function (code) {
            // 9002 is the session-level PROVIDER_LOCKED from getProviderBalance;
            // 19175 is GAME_PROVIDER_DISABLE returned by Kafka.
            // Both are terminal locked states for THIS modal.
            if (Number(code) === 19175 || Number(code) === 9002) {
                if (!balanceCache.isProviderLocked(this.currentProvider)) {
                    balanceCache.lockProvider(this.currentProvider, 19175);
                }
            } else if (Number(code) === 9004) {
                if (!balanceCache.isProviderMaintenance(this.currentProvider)) {
                    balanceCache.markProviderMaintenance(this.currentProvider);
                }
            } else {
                balanceCache.invalidate(this.currentProvider, 'balance_unavailable');
            }
            this.providerBalance = null;
            this.renderBalances();
            this.enableControls();
        },

        // Only providers in this member's listPv may require a balance request.
        // A first-transfer wallet is a known zero, not an API error.
        loadProviderBalanceIfNeeded: function (version) {
            var self = this;
            var code = self.currentProvider;
            if (version !== self.balanceRequestVersion || !code || self.isProviderBlocked()
                    || self.isFirstTransferToProvider(code)
                    || !self.hasCurrentMemberProviderList()
                    || balanceCache.getUsable(code) !== null || self.providerBalanceLoading) {
                self.renderBalances();
                self.enableControls();
                return Promise.resolve();
            }
            self.providerBalanceLoading = true;

            var seq = balanceCache.beginRequest(code, true);
            return callApi3('/api/wallet/provider/getBalance', 'POST', { pvcd: code }).then(function (response) {
                balanceCache.endRequest(code, seq);
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                if (Number(response && response.code) === 19175 || Number(response && response.code) === 9002
                        || Number(response && response.code) === 9004) {
                    self.handleProviderUnavailable(response.code);
                } else if (response && response.success && response.data && Array.isArray(response.data.listBalance)) {
                    balanceCache.setFromListBalance(response.data.listBalance, seq);
                } else {
                    balanceCache.invalidate(code, 'provider_balance_failed');
                }
            }).catch(function (error) {
                balanceCache.endRequest(code, seq);
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                var response = error && (error.responseJSON || error.response || error);
                if (Number(response && response.code) === 19175 || Number(response && response.code) === 9002
                        || Number(response && response.code) === 9004) {
                    self.handleProviderUnavailable(response.code);
                } else {
                    balanceCache.invalidate(code, 'provider_balance_error');
                }
            }).then(function () {
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                self.providerBalanceLoading = false;
                self.renderBalances();
                self.enableControls();
            });
        },

        // RG08: MAIN retry is independent of provider locked/maintenance state.
        // Never refresh the page, re-fetch a provider, or submit a transfer.
        retryMainBalance: function () {
            var self = this;
            if (!self.currentProvider || !window.pendingGameLaunch || self.walletBalance !== null
                    || self.mainBalanceLoading || self.transferPending || self.redirectPending
                    || self.transferRechecking) return;

            var version = self.balanceRequestVersion;
            var code = self.currentProvider;
            self.mainBalanceLoading = true;
            self.renderBalances();
            self.enableControls();
            balanceCache.invalidate('MAIN', 'manual_main_balance_retry');
            var seq = balanceCache.beginRequest('MAIN', true);

            callApi3('/api/wallet/main/getBalance', 'GET', null).then(function (response) {
                balanceCache.endRequest('MAIN', seq);
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                self.syncDisabledProvidersFromMain(response);
                if (response && response.success && response.data && Array.isArray(response.data.listBalance)) {
                    balanceCache.setFromListBalance(response.data.listBalance, seq);
                    var stored = balanceCache.getUsable('MAIN');
                    if (stored !== null && Number.isFinite(Number(stored.balance))) {
                        self.walletBalance = Number(stored.balance);
                        if ($('#transferAll, #transferAllMobile').is(':checked')) {
                            $('#transferAmount').val(Math.floor(Math.max(0, self.walletBalance)));
                        }
                    }
                }
            }).catch(function () {
                balanceCache.endRequest('MAIN', seq);
                // Preserve null: never treat a failed request as a valid zero.
            }).then(function () {
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                self.mainBalanceLoading = false;
                self.renderBalances();
                self.enableControls();
            });
        },

        retryBalances: function () {
            var self = this;
            if (self.transferPending || self.redirectPending || self.transferRechecking
                    || self.isProviderBlocked()) return;
            var code = self.currentProvider;
            if (!code) return;
            self.transferRechecking = true;
            if (self.transferUncertain) {
                self.retryMainVerificationRequired = true;
                // Do not use an independently repopulated MAIN cache as proof
                // that this specific ambiguous transaction was reconciled.
                balanceCache.invalidate('MAIN', 'manual_transfer_recheck');
            }
            // After an uncertain transfer, force a fresh listPv before re-reading
            // balances: the previous transfer may actually have succeeded.
            if (self.transferUncertain || !self.hasCurrentMemberProviderList()) {
                self.disableControls();
                balanceCache.ensureProviderList(true).then(function () {
                    if (code !== self.currentProvider) return;
                    self.loadBalances(code);
                }).catch(function () {
                    // On failure, do not treat an unverified provider list as [].
                }).then(function () {
                    self.transferRechecking = false;
                    if (code === self.currentProvider) self.enableControls();
                });
            } else {
                self.loadBalances(code);
                self.transferRechecking = false;
            }
        },

        // Every click (initial transfer AND retry) checks the authoritative MAIN
        // wallet first, then re-reads this member's listPv from the backend.
        // Only submit if that fresh list does NOT contain the selected provider.
        // LocalStorage is a UI cache, not proof of first transfer.
        verifyAndSubmitTransfer: function () {
            var self = this;
            if (self.transferPending || self.redirectPending || self.transferRechecking
                    || self.failureCooldown || self.isProviderBlocked() || self.transferAlreadyRecorded) return;

            var code = self.currentProvider;
            var version = self.balanceRequestVersion;
            if (!code || !window.pendingGameLaunch) return;

            self.transferRechecking = true;
            self.mainBalanceLoading = true;
            self.disableControls();
            var $buttons = $('#btnTransfer, #btnTransferMobile');
            if (self.transferButtonLabel === null) self.transferButtonLabel = $('#btnTransfer').html();
            if (self.transferMobileButtonLabel === null) self.transferMobileButtonLabel = $('#btnTransferMobile').html();
            // Keep the existing localized CTA label. Only replace its play icon
            // with a spinner while MAIN and listPv are being verified.
            $buttons.find('i.fa-play').removeClass('fa-play').addClass('fa-spinner fa-spin');

            function isCurrent() {
                return version === self.balanceRequestVersion && code === self.currentProvider
                    && !!window.pendingGameLaunch;
            }
            function finishVerification() {
                if (!isCurrent()) return;
                self.transferRechecking = false;
                self.mainBalanceLoading = false;
                $('#btnTransfer').html(self.transferButtonLabel);
                $('#btnTransferMobile').html(self.transferMobileButtonLabel);
                self.renderBalances();
                self.enableControls();
            }
            function verifyFailed() {
                if (!isCurrent()) return;
                // A failed PRE-SUBMIT check is not proof of a failed transfer:
                // no new transfer was sent. Preserve the prior uncertainty (if any),
                // and never use cached listPv or cached MAIN as authorization.
                self.transferFailed = true;
                self.showStatus(transferBalanceLang.verificationUnavailable);
                finishVerification();
            }

            // 1. Force a real MAIN balance fetch, not the browser TTL cache.
            //    A failed MAIN response must prevent the list check and transfer.
            var seq = balanceCache.beginRequest('MAIN', true);
            callApi3('/api/wallet/main/getBalance', 'GET', null)
                .then(function (response) {
                    balanceCache.endRequest('MAIN', seq);
                    if (!isCurrent()) return null;
                    if (!response || response.success !== true || !response.data
                            || !Array.isArray(response.data.listBalance)) {
                        throw new Error('MAIN refresh failed');
                    }
                    self.syncDisabledProvidersFromMain(response);
                    if (self.isProviderBlocked()) {
                        finishVerification();
                        return null;
                    }
                    balanceCache.setFromListBalance(response.data.listBalance, seq);
                    var updated = balanceCache.getUsable('MAIN');
                    if (!updated || !Number.isFinite(Number(updated.balance))) {
                        throw new Error('MAIN balance unavailable');
                    }
                    self.walletBalance = Number(updated.balance);

                    // 2. Always fetch listPv directly from the backend.
                    //    ensureProviderList(true) may silently return stale cache
                    //    when HTTP fails, so it is not a safe pre-submit check.
                    if (typeof window.fetch !== 'function') {
                        throw new Error('listPv fetch unavailable');
                    }
                    return window.fetch(window.location.origin + '/api/wallet/calibrate/list', {
                        credentials: 'same-origin', cache: 'no-store'
                    }).then(function (httpResponse) {
                        if (!httpResponse.ok) throw new Error('listPv refresh failed');
                        return httpResponse.json();
                    }).then(function (payload) {
                        if (!isCurrent()) return;
                        if (!payload || payload.success !== true || !payload.data
                                || !Array.isArray(payload.data.listPv)
                                || typeof window.setListPvToSession !== 'function') {
                            throw new Error('listPv response invalid');
                        }
                        // Make the decision from the actual API payload, not
                        // from a LocalStorage read which may have been tampered.
                        var serverListPv = payload.data.listPv.map(function (item) {
                            return self.normalizeProviderCode(item);
                        }).filter(function (item) { return !!item; });
                        window.setListPvToSession(serverListPv);
                        if (!self.hasCurrentMemberProviderList()) {
                            throw new Error('listPv member scope invalid');
                        }
                        if (serverListPv.indexOf(code) !== -1) {
                            // The provider has already received a transfer.
                            // Do not send an unnecessary second deposit.
                            self.transferAlreadyRecorded = true;
                            self.transferUncertain = false;
                            self.transferFailed = true;
                            self.showStatus(transferBalanceLang.transferAlreadyRecorded);
                            finishVerification();
                            return;
                        }
                        // Verified current MAIN and a fresh backend listPv.
                        // Only the initial provider balance may safely be zero.
                        self.providerBalance = 0;
                        self.transferUncertain = false;
                        self.retryMainVerificationRequired = false;
                        self.transferFailed = false;
                        if ($('#transferAll, #transferAllMobile').is(':checked')) {
                            $('#transferAmount').val(Math.floor(Math.max(0, self.walletBalance)));
                        }
                        finishVerification();
                        if (!isCurrent() || self.isProviderBlocked()) return;
                        // The original user click automatically continues exactly
                        // once; submitVerifiedTransfer will revalidate the amount.
                        self.submitVerifiedTransfer();
                    });
                }, function (error) {
                    balanceCache.endRequest('MAIN', seq);
                    throw error;
                }).catch(function () {
                    verifyFailed();
                });
        },

        normalizeProviderCode: function (providerCode) {
            return typeof providerCode === 'string' ? providerCode.trim().toUpperCase() : '';
        },

        resolveProviderCode: function (target, $btn, fallbackProviderCode) {
            var providerCode = '';

            if ($btn && $btn.length) {
                providerCode = $btn.attr('data-provider') || $btn.data('provider') || '';
            }

            if (!providerCode && typeof target === 'string') {
                var match = target.match(/\/(?:play|game)\/([^\/?#]+)/i);
                if (match && match[1]) {
                    providerCode = match[1];
                }
            }

            return this.normalizeProviderCode(providerCode || fallbackProviderCode);
        },

        resolveProviderName: function (code, $btn) {
            code = this.normalizeProviderCode(code);
            if (!code) return '';
            // The game-list page already has an authoritative provider model.
            var $page = $('#transferPageProviderName');
            if ($page.length && this.normalizeProviderCode($page.attr('data-provider-code')) === code) {
                var pageName = $.trim($page.text());
                if (pageName) return pageName;
            }
            // Game-group cards have their own provider names (no hardcoded mapping).
            var $sources = $btn && $btn.length ? $btn.add($btn.closest('[data-provider-name]')) : $();
            $sources = $sources.add($('.game-front-type[data-provider-code]'));
            var name = '';
            $sources.each(function () {
                var $source = $(this);
                var sourceCode = String($source.attr('data-provider-code') || '').trim().toUpperCase();
                var candidate = $.trim($source.attr('data-provider-name') || '');
                if (candidate && sourceCode === code) {
                    name = candidate;
                    return false;
                }
            });
            if (name) return name;
            // Optional provider list on pages which expose one.
            if (Array.isArray(window.pvls)) {
                for (var i = 0; i < window.pvls.length; i++) {
                    var pv = window.pvls[i] || {};
                    if (this.normalizeProviderCode(pv.pvcode || pv.pvcd) === code) {
                        return pv.pvnm || pv.providerName || code;
                    }
                }
            }
            return code; // Safe fallback when name metadata is genuinely unavailable.
        },

        isFirstTransferToProvider: function (providerCode) {
            var code = this.normalizeProviderCode(providerCode);
            if (!code) return false;
            if (this.hasCurrentMemberProviderList()) {
                return this.getTransferredProviders().indexOf(code) === -1;
            }
            // Without a verified listPv for this member, the provider's
            // transfer history is UNKNOWN. Do not assume an initial zero balance.
            return false;
        },

        getTransferredProviders: function () {
            var listPv = localStorage.getItem('listPv');
            var listPvArray = [];

            if (listPv) {
                try {
                    listPvArray = JSON.parse(listPv);
                } catch (e) {
                    listPvArray = [];
                }
            }

            if (!Array.isArray(listPvArray)) {
                return [];
            }

            return listPvArray.map(this.normalizeProviderCode).filter(function (providerCode) {
                return providerCode !== '';
            });
        },

        // listPv can survive a member switch. Never infer a zero balance from
        // an unscoped/malformed provider list; ask the centralized cache to
        // refresh its member-scoped list before making that decision.
        hasCurrentMemberProviderList: function () {
            var scope = window.__balanceScope;
            if (!scope || localStorage.getItem('bal.meta.listPvScope') !== scope) {
                return false;
            }
            try {
                return Array.isArray(JSON.parse(localStorage.getItem('listPv')));
            } catch (e) {
                return false;
            }
        },

        updateTransferredProviders: function (providers) {
            var listPvArray = this.getTransferredProviders();
            var providersToAdd = Array.isArray(providers) ? providers : [providers];
            var self = this;

            providersToAdd.forEach(function (providerCode) {
                var normalizedProviderCode = self.normalizeProviderCode(providerCode);
                if (normalizedProviderCode && listPvArray.indexOf(normalizedProviderCode) === -1) {
                    listPvArray.push(normalizedProviderCode);
                }
            });

            if (typeof window.setListPvToSession === 'function') {
                window.setListPvToSession(listPvArray);
            } else {
                localStorage.setItem('listPv', JSON.stringify(listPvArray));
            }
        },

        loadBalances: function (providerCode) {
            var self = this;
            var version = ++self.balanceRequestVersion;
            self.currentProvider = self.normalizeProviderCode(providerCode);
            self.providerBalanceLoading = false;
            self.providerListLoading = !self.hasCurrentMemberProviderList();
            var $trigger = window.pendingGameLaunch && window.pendingGameLaunch.$btn;
            $('#providerNameDisplay').text(self.resolveProviderName(self.currentProvider, $trigger));
            self.walletBalance = null;
            self.providerBalance = null;
            var cachedMain = balanceCache.getUsable('MAIN');
            self.mainBalanceLoading = cachedMain === null;
            if (cachedMain !== null) self.walletBalance = Number(cachedMain.balance);
            // Preserve the spinner only for genuinely outstanding balances.
            $('#walletBalance, #providerBalance').val('...');
            self.disableControls();
            self.renderBalances();
            // A known-locked provider needs only an informational modal.
            // Do not fetch MAIN or a provider balance for a transfer we cannot make.
            if (balanceCache.isProviderLocked(self.currentProvider)) {
                self.mainBalanceLoading = false;
                self.providerListLoading = false;
                self.renderBalances();
                return;
            }
            if (self.transferUncertain) {
                self.showStatus(transferBalanceLang.transferOutcomeUnknown);
            }

            if (self.providerListLoading && typeof balanceCache.ensureProviderList === 'function') {
                balanceCache.ensureProviderList(false).then(function () {
                    if (version !== self.balanceRequestVersion) return;
                    self.providerListLoading = false;
                    self.loadProviderBalanceIfNeeded(version);
                    self.renderBalances();
                    self.enableControls();
                }).catch(function () {
                    if (version !== self.balanceRequestVersion) return;
                    self.providerListLoading = false;
                    self.renderBalances();
                    self.enableControls();
                });
            } else {
                self.providerListLoading = false;
                self.loadProviderBalanceIfNeeded(version);
            }

            if (cachedMain !== null) {
                self.renderBalances();
                self.enableControls();
                return;
            }

            var seq = balanceCache.beginRequest('MAIN', true);
            callApi3('/api/wallet/main/getBalance', 'GET', null).then(function (response) {
                balanceCache.endRequest('MAIN', seq);
                if (version !== self.balanceRequestVersion) return;
                self.syncDisabledProvidersFromMain(response);
                if (response && response.success && response.data && Array.isArray(response.data.listBalance)) {
                    balanceCache.setFromListBalance(response.data.listBalance, seq);
                    var stored = balanceCache.getUsable('MAIN');
                    if (stored !== null) {
                        self.walletBalance = Number(stored.balance);
                        if (self.retryMainVerificationRequired && self.hasCurrentMemberProviderList()) {
                            // A new MAIN response has confirmed the current balance.
                            // If the provider was actually transferred during the
                            // uncertain request, loadProviderBalanceIfNeeded checks it.
                            self.transferUncertain = false;
                            self.retryMainVerificationRequired = false;
                        }
                    }
                }
            }).catch(function () {
                balanceCache.endRequest('MAIN', seq);
            }).then(function () {
                if (version !== self.balanceRequestVersion) return;
                self.mainBalanceLoading = false;
                self.renderBalances();
                self.enableControls();
            });
        },

        renderBalances: function () {
            $('#walletBalance')
                .toggleClass('transfer-balance-load-error', this.walletBalance === null && !this.mainBalanceLoading)
                .val(this.walletBalance === null
                    ? (this.mainBalanceLoading ? '...' : transferBalanceLang.mainBalanceUnavailable)
                    : this.formatCurrency(this.walletBalance));
            // MAIN retry stays available after MAIN failure even if provider is
            // locked or under maintenance; provider transfer remains blocked.
            var canRetryMain = this.walletBalance === null && !this.mainBalanceLoading
                && !!this.currentProvider && !this.transferPending && !this.redirectPending
                && !this.transferRechecking;
            $('.btn-retry-main-balance').toggle(canRetryMain)
                .prop('disabled', !canRetryMain)
                .find('.retry-main-label').text(alertMsg.retry || 'Coba lagi');

            this.providerBalance = null;
            var providerCode = this.currentProvider;
            var blockedLabel = this.providerStatusLabel();
            var neverTransferred = this.isFirstTransferToProvider(providerCode);
            var pv = blockedLabel ? null : balanceCache.getUsable(providerCode);

            // A missing balance is an error only after all relevant loads finish.
            $('#providerBalance').removeClass('transfer-balance-load-error');
            if (blockedLabel) {
                $('#providerBalance').val(blockedLabel);
            } else if (neverTransferred) {
                this.providerBalance = 0;
                $('#providerBalance').val(this.formatCurrency(0));
            } else if (pv !== null) {
                this.providerBalance = Number(pv.balance);
                $('#providerBalance').val(this.formatCurrency(this.providerBalance));
            } else {
                var pending = this.providerBalanceLoading || this.providerListLoading || this.mainBalanceLoading;
                $('#providerBalance')
                    .toggleClass('transfer-balance-load-error', !pending)
                    .val(pending ? '...' : (alertMsg.retry || 'Coba lagi'));
            }
            this.syncLockedNotice();
        },

        showBalanceUnavailable: function () {
            // Expired MAIN must not be silently used as the origin balance.
            this.walletBalance = null;
            this.mainBalanceLoading = false;
            this.renderBalances();
            this.disableControls();

        },

        showModal: function () {
            if (window.pendingGameLaunch) {
                this.gameUrl = window.pendingGameLaunch.target;
            }
            // loadBalances may have already resolved synchronously from cache.
            this.enableControls();
            
            var isMobile = $('#transferBalanceModal').hasClass('mobile-modal') || window.innerWidth <= 768;
            if (isMobile) {
                $('#transferBalanceModal').fadeIn();
            } else {
                $('#transferBalanceModal').modal('show');
            }
        },

        hideModal: function () {
            // Do not dismiss while a transfer has been sent but not resolved.
            if (this.transferPending || this.redirectPending) return;
            ++this.balanceRequestVersion;
            var isMobile = $('#transferBalanceModal').hasClass('mobile-modal') || window.innerWidth <= 768;
            if (isMobile) {
                $('#transferBalanceModal').fadeOut();
            } else {
                $('#transferBalanceModal').modal('hide');
            }
            this.resetForm();
            this.syncLockedNotice(true);
            window.pendingGameLaunch = null;
        },

        resetForm: function () {
            if (this.redirectTimer !== null) {
                window.clearTimeout(this.redirectTimer);
                this.redirectTimer = null;
            }
            if (this.failureCooldownTimer !== null) {
                window.clearTimeout(this.failureCooldownTimer);
                this.failureCooldownTimer = null;
            }
            this.failureCooldown = false;
            this.transferFailed = false;
            this.transferUncertain = false;
            this.transferRechecking = false;
            this.retryMainVerificationRequired = false;
            this.transferAlreadyRecorded = false;
            this.unlockCheckPending = false;
            $('#transferAmount').val('').prop('readonly', false);
            $('#transferAll, #transferAllMobile').prop('checked', false);
            this.clearValidation();
            this.showStatus('');
            // Restore the original CTA if a game was opened in another tab.
            if (this.transferButtonLabel !== null) $('#btnTransfer').html(this.transferButtonLabel);
            if (this.transferMobileButtonLabel !== null) $('#btnTransferMobile').html(this.transferMobileButtonLabel);
            this.enableControls();
        },

        validateAmount: function (amount) {
            var self = this;
            var $input = $('#transferAmount');
            var $error = $('#transferAmountError, #transferAmountErrorMobile');
            var isValid = true;
            var errorMessage = '';

            // [IDTF-2100] Refuse to validate against an unknown balance rather
            // than treating it as 0 and letting the transfer through.
            if (self.walletBalance === null || self.walletBalance === undefined
                || isNaN(parseFloat(self.walletBalance))) {
                $input.addClass('is-invalid');
                $error.text(transferBalanceLang.errorBalanceUnknown || alertMsg.retry).show();
                return false;
            }

            // Reject fractions (including pasted decimals/exponent notation) rather
            // than silently changing the amount the member intended to transfer.
            var transferAllSelected = $('#transferAll, #transferAllMobile').is(':checked');
            var rawAmount = String($input.val() || '').trim();
            if (!Number.isSafeInteger(amount) || (!transferAllSelected && !/^\d+$/.test(rawAmount))) {
                isValid = false;
                errorMessage = transferBalanceLang.errorAmountInteger;
            }
            // Check if negative
            else if (amount < 0) {
                isValid = false;
                errorMessage = transferBalanceLang.errorAmountNegative || 'Amount cannot be negative';
            }
            // Check if exceeds wallet balance
            else if (amount > parseFloat(self.walletBalance)) {
                isValid = false;
                errorMessage = transferBalanceLang.errorAmountExceed || 'Amount cannot exceed wallet balance';
            }
            // Check if zero
            else if (amount === 0) {
                isValid = false;
                errorMessage = transferBalanceLang.errorAmountZero || 'Amount must be greater than 0';
            }

            if (!isValid) {
                $input.addClass('is-invalid');
                $error.text(errorMessage).show();
            } else {
                $input.removeClass('is-invalid');
                $error.text('').hide();
            }

            return isValid;
        },

        clearValidation: function () {
            $('#transferAmount').removeClass('is-invalid');
            $('#transferAmountError, #transferAmountErrorMobile').text('').hide();
        },

        disableControls: function () {
            // Disable checkboxes
            $('#transferAll, #transferAllMobile').prop('disabled', true);
            
            // A failed transfer must not prevent previewing the selected game.
            // Keep Preview disabled only while an API transfer/redirect is pending.
            $('#btnPreview, #btnPreviewMobile').prop('disabled',
                this.isProviderBlocked() || !this.transferFailed
                || this.transferPending || this.redirectPending);
            $('#btnTransfer, #btnTransferMobile').prop('disabled', true);
            
            // Disable amount input
            $('#transferAmount').prop('disabled', true);
        },

        enableControls: function () {
            var balancesReady = this.walletBalance !== null && this.providerBalance !== null
                && Number.isFinite(this.walletBalance) && Number.isFinite(this.providerBalance)
                && !this.providerBalanceLoading && !this.mainBalanceLoading
                && !this.providerListLoading;
            var blocked = this.isProviderBlocked() || this.transferAlreadyRecorded;
            var inFlight = this.transferPending || this.redirectPending || this.transferRechecking;
            if (inFlight || blocked || !balancesReady || this.failureCooldown) {
                this.disableControls();
                // After a failed transfer, let the member choose to preview at once.
                // After 3 seconds, allow an explicit retry click even if balances
                // are unknown: handleTransfer will refresh, never submit stale origins.
                if (this.transferFailed && !this.failureCooldown && !inFlight && !blocked
                        && !this.mainBalanceLoading && !this.providerBalanceLoading && !this.providerListLoading) {
                    $('#btnTransfer, #btnTransferMobile').prop('disabled', false);
                }

                return;
            }
            $('#transferAll, #transferAllMobile').prop('disabled', false);
            $('#btnPreview, #btnPreviewMobile, #btnTransfer, #btnTransferMobile').prop('disabled', false);
            $('#transferAmount').prop('disabled', false);
        },

        // UI click entry point: no transfer is sent based solely on LocalStorage.
        handleTransfer: function () {
            var self = this;
            if (self.transferPending || self.redirectPending || self.failureCooldown
                    || self.transferRechecking || self.isProviderBlocked() || self.transferAlreadyRecorded) {
                self.enableControls();
                return;
            }
            if (self.walletBalance === null || self.providerBalance === null
                    || !Number.isFinite(self.walletBalance) || !Number.isFinite(self.providerBalance)
                    || self.mainBalanceLoading || self.providerBalanceLoading || self.providerListLoading) {
                // Retry after a transfer error is allowed even if caches are
                // unavailable; verification will get fresh values from the server.
                if (self.transferFailed || self.transferUncertain) self.verifyAndSubmitTransfer();
                self.enableControls();
                return;
            }
            // Avoid unnecessary API calls for invalid manual input.
            var amount = Number($('#transferAmount').val()) || 0;
            if ($('#transferAll, #transferAllMobile').is(':checked')) {
                amount = Math.floor(self.walletBalance);
            }
            if (!self.validateAmount(amount)) return;
            self.verifyAndSubmitTransfer();
        },

        // Only called once MAIN and listPv have both been freshly verified.
        submitVerifiedTransfer: function () {
            var self = this;
            if (self.transferPending || self.redirectPending || self.failureCooldown
                    || self.transferRechecking || self.isProviderBlocked() || self.transferAlreadyRecorded) return;
            var amount = Number($('#transferAmount').val()) || 0;
            var transferAll = $('#transferAll, #transferAllMobile').is(':checked');
            if (transferAll) amount = Math.floor(self.walletBalance);
            if (!self.validateAmount(amount)) return;

            var code = self.currentProvider;
            var version = self.balanceRequestVersion;
            var $buttons = $('#btnTransfer, #btnTransferMobile');
            if (self.transferButtonLabel === null) self.transferButtonLabel = $('#btnTransfer').html();
            if (self.transferMobileButtonLabel === null) self.transferMobileButtonLabel = $('#btnTransferMobile').html();
            self.showStatus('');
            self.transferFailed = false;
            self.transferUncertain = false;
            self.retryMainVerificationRequired = false;
            self.transferPending = true;
            self.disableControls();
            $buttons.html('<i class="fas fa-spinner fa-spin me-2"></i>Processing...');

            function restoreButtons() {
                $('#btnTransfer').html(self.transferButtonLabel);
                $('#btnTransferMobile').html(self.transferMobileButtonLabel);
                self.transferPending = false;
                self.renderBalances();
                self.enableControls();
            }

            function handleFailure(response, ambiguous) {
                var errorCode = Number(response && response.code);
                if (errorCode === 19175 || errorCode === 9002 || errorCode === 9004) {
                    self.handleProviderUnavailable(errorCode);
                    self.showStatus((errorCode === 19175 || errorCode === 9002)
                        ? (self.providerStatusLabel() || 'Provider Locked')
                        : (self.providerStatusLabel() || 'Pemeliharaan'));
                } else if (ambiguous || !response || !Number.isFinite(errorCode) || errorCode === -1000) {
                    // The transfer was submitted. A network / generic error does
                    // not prove it was rejected; never automatically repeat it.
                    self.transferUncertain = true;
                    // Preserve MAIN and provider amounts DISPLAYED in this popup;
                    // changing MAIN to "Coba lagi" immediately is misleading.
                    // These are snapshots, not validated balances for a retry.
                    balanceCache.invalidate('MAIN', 'transfer_outcome_unknown');
                    balanceCache.invalidate(code, 'transfer_outcome_unknown');
                    self.showStatus(transferBalanceLang.transferOutcomeUnknown);
                } else {
                    self.showStatus((response && response.data && response.data.message)
                        || 'Transfer gagal. Silakan periksa jumlah dan coba lagi.');
                }
                restoreButtons();
                self.startFailureCooldown();
            }

            callApi3('/api/wallet/v2/setTransfer', 'POST', {
                transferFrom: 'MAIN',
                transferTo: code,
                amount: amount,
                isWithdrawAll: transferAll ? 1 : 0,
                originFrom: self.walletBalance,
                originTo: self.providerBalance,
                bonusId: 0,
                bonusPercentage: 0,
                bonusReward: 0
            }).then(function (response) {
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                if (response && response.success) {
                    if (response.data && Array.isArray(response.data.listBalance)) {
                        balanceCache.setFromListBalance(response.data.listBalance);
                    } else {
                        balanceCache.invalidate('MAIN', 'transfer_without_balances');
                        balanceCache.invalidate(code, 'transfer_without_balances');
                    }
                    var responseListPv = response.data && Array.isArray(response.data.listPv)
                        ? response.data.listPv : [];
                    self.updateTransferredProviders(responseListPv.concat([code]));
                    self.transferPending = false;
                    self.redirectPending = true;
                    self.disableControls();

                    $buttons.html('<i class="fas fa-check me-2"></i>Berhasil');
                    self.startRedirectCountdown(version, code);
                } else {
                    handleFailure(response, false);
                }
            }).catch(function (error) {
                if (version !== self.balanceRequestVersion || code !== self.currentProvider) return;
                var response = error && (error.responseJSON || error.response || error);
                handleFailure(response, true);
            });
        },

        launchGame: function (transferCompleted) {
            // Even "Coba lihat dulu" must not bypass a known provider lock.
            if (this.currentProvider && balanceCache.isProviderLocked(this.currentProvider)) {
                if (this.redirectTimer !== null) {
                    window.clearTimeout(this.redirectTimer);
                    this.redirectTimer = null;
                }
                this.transferPending = false;
                this.redirectPending = false;
                this.syncLockedNotice();
                return;
            }
            if (!transferCompleted && (this.transferPending || this.redirectPending)) return;
            if (!window.pendingGameLaunch) {
                this.hideModal();
                return;
            }

            var target = window.pendingGameLaunch.target;
            var $btn = window.pendingGameLaunch.$btn;

            // A successful transfer already updated the central balance cache.
            // Re-fetching balances here would race with navigation and clear
            // the success message before the 3-second confirmation is shown.
            this.hideModal();

            // Use original game launch logic
            
            
            openGameUrl(target);
            
            if (!(/Mobile|Android/i.test(navigator.userAgent || ''))) {
                window.location.reload();
            }
        },

        formatCurrency: function (amount) {
            return parseFloat(amount || 0).toLocaleString('en-US', {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2
            });
        },

        // Check if transfer balance modal should be shown and show it if needed
        // Returns true if modal was shown (caller should return early), false otherwise
        checkAndShowIfNeeded: function (target, providerCode, $btn) {
            providerCode = this.resolveProviderCode(target, $btn, providerCode);
            if (this.transferPending || this.redirectPending) return true;
            if (!providerCode) {
                // Do not block game launch or submit an invalid transfer destination.
                return false;
            }

            // Only member-scoped listPv can confirm prior transfers to this provider.
            // Never let stale listPv from another login skip this popup.
            if (!balanceCache.isProviderLocked(providerCode)
                    && this.hasCurrentMemberProviderList()
                    && this.getTransferredProviders().indexOf(providerCode) !== -1) {
                return false;
            }

            // Provider not yet transferred to --> show modal
            window.pendingGameLaunch = {
                target: target,
                providerCode: providerCode,
                $btn: $btn
            };

            this.loadBalances(providerCode);
            this.showModal();
            return true;
        }
    };

    // Initialize transfer modal handlers
    $(document).ready(function () {
        // Transfer All checkbox (Desktop and Mobile)
        $(document).on('change', '#transferAll, #transferAllMobile', function () {
            if ($(this).is(':checked')) {
                // Transfer-all excludes fractional MAIN units; never submit cents.
                $('#transferAmount').val(Math.floor(Math.max(0, transferBalanceModal.walletBalance || 0))).prop('readonly', true);
                transferBalanceModal.clearValidation();
            } else {
                $('#transferAmount').prop('readonly', false);
            }
        });

        // Do not allow decimal separators or exponent notation when typing.
        // Pasted/non-keyboard input is independently rejected by validateAmount.
        $(document).on('keydown', '#transferAmount', function (event) {
            if (['.', ',', 'e', 'E', '+', '-'].indexOf(event.key) !== -1) {
                event.preventDefault();
            }
        });

        // Amount input validation (Desktop and Mobile)
        $(document).on('input blur', '#transferAmount', function () {
            var raw = String($(this).val() || '').trim();
            if (raw !== '') {
                transferBalanceModal.validateAmount(Number(raw));
            } else {
                transferBalanceModal.clearValidation();
            }
        });

        // Preview button - launch game without transfer (Desktop and Mobile)
        $(document).on('click', '#btnPreview, #btnPreviewMobile', function () {
            transferBalanceModal.launchGame(false);
        });

        // Explicit retry for MAIN balance only (desktop/mobile).
        $(document).on('click', '.btn-retry-main-balance', function () {
            transferBalanceModal.retryMainBalance();
        });

        // The locked information screen has its own on-demand status refresh.
        $(document).on('click', '.btn-check-provider-unlock', function () {
            transferBalanceModal.checkProviderUnlock();
        });

        window.addEventListener('balancecache:providerlocked', function (event) {
            if (event.detail && event.detail.providerCode === transferBalanceModal.currentProvider) {
                transferBalanceModal.providerBalance = null;
                transferBalanceModal.renderBalances();
                transferBalanceModal.enableControls();
            }
        });
        window.addEventListener('balancecache:providerunlocked', function (event) {
            if (event.detail && event.detail.providerCode === transferBalanceModal.currentProvider) {
                transferBalanceModal.providerBalance = null;
                transferBalanceModal.renderBalances();
                transferBalanceModal.enableControls();
            }
        });
        window.addEventListener('balancecache:providermaintenance', function (event) {
            if (event.detail && event.detail.providerCode === transferBalanceModal.currentProvider) {
                transferBalanceModal.providerBalance = null;
                transferBalanceModal.renderBalances();
                transferBalanceModal.enableControls();
            }
        });

        // Transfer button (Desktop and Mobile)
        $(document).on('click', '#btnTransfer, #btnTransferMobile', function () {
            transferBalanceModal.handleTransfer();
        });

        // Bootstrap's data-dismiss handler may run before this delegated handler.
        // Prevent dismissing a transfer whose result is still pending.
        $('#transferBalanceModal').on('hide.bs.modal', function (event) {
            if (transferBalanceModal.transferPending || transferBalanceModal.redirectPending) event.preventDefault();
        });
        $(document).on('click', '.close-transfer-modal, [data-dismiss="modal"]', function (event) {
            if (transferBalanceModal.transferPending || transferBalanceModal.redirectPending) {
                event.preventDefault();
                event.stopImmediatePropagation();
                return;
            }
            transferBalanceModal.hideModal();
        });

        // Transfer Balance Info Tooltip handlers
        $(document).on('click', '#transferBalanceInfoBtn, #transferBalanceInfoBtnMobile', function (e) {
            e.stopPropagation();
            $('#transferBalanceTooltip').fadeIn(200);
        });

        $(document).on('click', '.transfer-balance-tooltip-close, .transfer-balance-tooltip', function (e) {
            if ($(e.target).hasClass('transfer-balance-tooltip') || $(e.target).closest('.transfer-balance-tooltip-close').length) {
                $('#transferBalanceTooltip').fadeOut(200);
            }
        });

        // Close tooltip when clicking outside
        $(document).on('click', '.transfer-balance-tooltip-content', function (e) {
            e.stopPropagation();
        });
    });
</script></body>
</html>
