1var __UVW1={id:'kobet-org'}; 2/** 3 * Site widget 4 * Loaded via <script> on affiliate sites. 5 * Expects window.__UVW1 = { id: "site_id" } to be set before this script runs. 6 */ 7(function () { 8 'use strict'; 9 10 var SITE_ID = (typeof __UVW1 !== 'undefined' && __UVW1.id) ? __UVW1.id : null; 11 if (!SITE_ID) return; 12 13 var API_BASE = '/widget-api'; 14 15 /* Click tracking helpers â set from config */ 16 var _CP = 's'; // click param name (randomized per site) 17 var _CS = {}; // click source map (randomized per site) 18 var COUNTRY_NAMES = { 19 GB:'the UK',UK:'the UK',AU:'Australia',NZ:'New Zealand',CA:'Canada', 20 DE:'Germany',AT:'Austria',CH:'Switzerland',FI:'Finland',NO:'Norway', 21 SE:'Sweden',DK:'Denmark',NL:'the Netherlands',BE:'Belgium',IE:'Ireland', 22 FR:'France',ES:'Spain',IT:'Italy',PT:'Portugal',PL:'Poland', 23 CZ:'Czech Republic',HU:'Hungary',RO:'Romania',GR:'Greece', 24 BR:'Brazil',MX:'Mexico',CL:'Chile',AR:'Argentina',PE:'Peru',CO:'Colombia', 25 JP:'Japan',KR:'South Korea',IN:'India',ZA:'South Africa', 26 US:'the US',TR:'Turkey',RU:'Russia',UA:'Ukraine' 27 }; 28 /* Loader overlay */ 29 var _loader = null; 30 function showLoader() { 31 if (_loader) { _loader.style.display = 'flex'; return; } 32 _loader = document.createElement('div'); 33 _loader.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:999999;display:flex;align-items:center;justify-content:center;'; 34 var spin = document.createElement('div'); 35 spin.style.cssText = 'width:48px;height:48px;border:4px solid rgba(255,255,255,0.3);border-top-color:#fff;border-radius:50%;animation:uvw1-spin .6s linear infinite;'; 36 var st = document.createElement('style'); 37 st.textContent = '@keyframes uvw1-spin{to{transform:rotate(360deg)}}'; 38 document.head.appendChild(st); 39 _loader.appendChild(spin); 40 document.body.appendChild(_loader); 41 window.addEventListener('pageshow', function() { if (_loader) _loader.style.display = 'none'; }); 42 } 43 44 function goOpen(src) { 45 showLoader(); 46 var p = _CP + '=' + (_CS[src] || src); 47 fetch(API_BASE + '/click/' + SITE_ID + '?' + p) 48 .then(function(r) { return r.json(); }) 49 .then(function(d) { if (d.u) window.location.href = d.u; }) 50 .catch(function() { if (_loader) _loader.style.display = 'none'; }); 51 } 52 function goSet(el, src) { el.style.cursor = 'pointer'; el.onclick = function(e) { e.preventDefault(); goOpen(src); }; } 53 function goTrack(src) { var p = _CP + '=' + (_CS[src] || src); fetch(API_BASE + '/click/' + SITE_ID + '?' + p).catch(function(){}); } 54 55 /* ============================================================ 56 STYLES â injected once into <head> 57 ============================================================ */ 58 function injectStyles() { 59 /* Google Font â Press Start 2P for retro slot machine */ 60 var fontLink = document.createElement('link'); 61 fontLink.rel = 'stylesheet'; 62 fontLink.href = 'https://fonts.googleapis.com/css2?family=VT323&display=swap'; 63 document.head.appendChild(fontLink); 64 65 var css = '' + 66 /* ---- Header button ---- */ 67 '.uvw1-header-btn{' + 68 'position:absolute;z-index:9990;box-sizing:border-box;padding:8px 20px;border:none;border-radius:20px;height:38px;' + 69 'color:#fff;font-weight:600;font-size:15px;cursor:pointer;' + 70 'text-decoration:none;white-space:nowrap;' + 71 'display:flex;justify-content:center;align-items:center;' + 72 'overflow:hidden;background-size:300% 300%;' + 73 'animation:uvw1-gradientShift 4s ease infinite,uvw1-pulse 5s ease-in-out infinite !important;' + 74 'box-shadow:0 2px 5px rgba(0,0,0,.2);transition:all .3s ease;' + 75 'font-family:Arial,Helvetica,sans-serif;' + 76 'text-shadow:0 1px 2px rgba(0,0,0,.2);' + 77 '}' + 78 '.uvw1-header-btn:hover{transform:translateY(-50%) translateY(-2px);box-shadow:0 4px 8px rgba(0,0,0,.3);}' + 79 '@keyframes uvw1-gradientShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}' + 80 '@keyframes uvw1-pulse{0%,100%{transform:translateY(-50%) scale(1)}5%{transform:translateY(-50%) scale(1.05)}10%{transform:translateY(-50%) scale(1)}15%{transform:translateY(-50%) scale(1.05)}20%,100%{transform:translateY(-50%) scale(1)}}' + 81 82 /* ---- Sticky footer text accents ---- */ 83 '.uvw1-sticky-brand{color:#ffd700;font-weight:800;text-decoration:none;text-shadow:0 0 10px rgba(255,215,0,.4),0 0 20px rgba(255,215,0,.15);' + 84 'animation:uvw1-brandGlow 2.5s ease-in-out infinite;letter-spacing:.5px;cursor:pointer;}' + 85 '.uvw1-sticky-brand:hover{text-decoration:none;}' + 86 '@keyframes uvw1-brandGlow{0%,100%{text-shadow:0 0 10px rgba(255,215,0,.4),0 0 20px rgba(255,215,0,.15)}' + 87 '50%{text-shadow:0 0 14px rgba(255,215,0,.6),0 0 28px rgba(255,215,0,.25)}}' + 88 '.uvw1-sticky-warn{color:#ff9a9a;font-weight:700;}' + 89 '.uvw1-sticky-highlight{color:#7dffb3;font-weight:700;text-shadow:0 0 8px rgba(125,255,179,.35);}' + 90 91 /* ---- Sticky footer ---- */ 92 '.uvw1-footer{' + 93 'position:fixed;bottom:0;left:0;right:0;z-index:9998;width:100%;' + 94 'font-family:Helvetica Neue,Helvetica,Arial,sans-serif;' + 95 'background:linear-gradient(to right,#1a365d,#4a3880);' + 96 'border-top:1px solid rgba(59,130,246,.5);' + 97 'transform:translateY(0);transition:transform .4s ease-out;color:#fff;' + 98 '}' + 99 '.uvw1-footer.uvw1-hidden{transform:translateY(100%);transition:none;}' + 100 '.uvw1-footer.uvw1-hiding{transform:translateY(100%);transition:transform .4s ease-out;}' + 101 '.uvw1-footer.uvw1-visible{transition:transform .4s ease-out;}' + 102 /* Collapsed transitions */ 103 '.uvw1-footer .uvw1-footer-logos{transition:opacity .3s ease;}' + 104 '.uvw1-footer .uvw1-stars,' + 105 '.uvw1-footer .uvw1-mobile-text,' + 106 '.uvw1-footer .uvw1-footer-text,' + 107 '.uvw1-footer .uvw1-footer-close{transition:opacity .3s ease,max-height .3s ease;overflow:hidden;}
107' + 108 /* Collapsed: hide logos */ 109 '.uvw1-footer.uvw1-collapsed .uvw1-footer-logos{opacity:0!important;width:0!important;margin:0!important;pointer-events:none;}' + 110 /* Collapsed: hide stars, text, close */ 111 '.uvw1-footer.uvw1-collapsed .uvw1-stars,' + 112 '.uvw1-footer.uvw1-collapsed .uvw1-mobile-text,' + 113 '.uvw1-footer.uvw1-collapsed .uvw1-footer-text,' + 114 '.uvw1-footer.uvw1-collapsed .uvw1-footer-close{' + 115 'opacity:0!important;max-height:0!important;margin:0!important;padding:0!important;pointer-events:none;' + 116 '}' + 117 '.uvw1-footer.uvw1-collapsed .uvw1-footer-inner{padding:8px 20px;transition:padding .3s ease;}' + 118 '.uvw1-footer.uvw1-collapsed .uvw1-footer-row{margin-bottom:0;justify-content:center;transition:margin .3s ease;}' + 119 '.uvw1-footer.uvw1-collapsed .uvw1-brand-info{margin-left:0;margin-right:15px;}' + 120 '.uvw1-footer.uvw1-collapsed .uvw1-brand-name{font-size:16px;font-weight:600;}' + 121 '.uvw1-footer.uvw1-collapsed .uvw1-footer-btn.uvw1-desktop-only{padding:10px 25px;margin-right:0;}' + 122 /* Inner container */ 123 '.uvw1-footer-inner{padding:12px 20px;position:relative;max-width:1000px;margin:0 auto;box-sizing:border-box;}' + 124 /* Close button */ 125 '.uvw1-footer-close{' + 126 'position:absolute;top:5px;right:10px;background:rgba(255,255,255,.1);border:none;' + 127 'color:rgba(255,255,255,.7);cursor:pointer;font-size:20px;line-height:.8;' + 128 'padding:2px 8px;z-index:10;border-radius:4px;transition:background .2s,color .2s;' + 129 '}' + 130 '.uvw1-footer-close:hover{background:rgba(255,255,255,.2);color:#fff;}' + 131 /* Footer row */ 132 '.uvw1-footer-row{display:flex;align-items:center;justify-content:flex-start;margin-bottom:10px;padding-top:2px;}' + 133 /* Logos section */ 134 '.uvw1-footer-logos{display:flex;align-items:center;margin-left:25px;}' + 135 /* Logo cards */ 136 '.uvw1-logo-card{' + 137 'width:60px;height:42px;border-radius:10px;display:flex;align-items:center;justify-content:center;' + 138 'font-weight:bold;font-size:16px;text-align:center;position:relative;' + 139 'box-shadow:0 2px 8px rgba(0,0,0,.15);background-color:#333;color:#f0f0f0;' + 140 '}' + 141 '.uvw1-logo-card.uvw1-logo-old{opacity:.5;}' + 142 '.uvw1-logo-card.uvw1-logo-old img{opacity:.7!important;}' + 143 '.uvw1-logo-card img{max-width:100%;max-height:100%;object-fit:contain;}' + 144 /* Badges */ 145 '.uvw1-badge-x{' + 146 'position:absolute;top:-6px;left:-6px;width:16px;height:16px;background-color:#f44336;' + 147 'border-radius:50%;display:flex;align-items:center;justify-content:center;' + 148 'font-weight:bold;font-size:10px;color:white;box-shadow:0 2px 4px rgba(0,0,0,.2);' + 149 '}' + 150 '.uvw1-badge-ok{' + 151 'position:absolute;top:-6px;right:-6px;width:16px;height:16px;background-color:#4CAF50;' + 152 'border-radius:50%;display:flex;align-items:center;justify-content:center;' + 153 'font-size:10px;color:white;box-shadow:0 2px 4px rgba(0,0,0,.2);' + 154 '}' + 155 /* Arrow between logos */ 156 '.uvw1-footer-arrow{margin:0 12px;color:#93c5fd;font-size:16px;animation:uvw1-arrowPulse 1.5s ease-in-out infinite;}' + 157 '@keyframes uvw1-arrowPulse{0%,100%{transform:translateX(0);opacity:.7}50%{transform:translateX(3px);opacity:1}}' + 158 /* Brand info */ 159 '.uvw1-brand-info{margin-left:22px;}' + 160 '.uvw1-brand-name{color:white;font-weight:800;font-size:16px;margin:0;text-shadow:0 1px 3px rgba(0,0,0,.5);text-decoration:none;}' + 161 '.uvw1-brand-name:hover{text-decoration:none;}' + 162 '.uvw1-stars{color:#f59e0b;font-size:12px;margin:2px 0 0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif!important;}' + 163 '.uvw1-star{display:inline-block;color:#f59e0b;animation:uvw1-starTwinkle 2.5s ease-in-out infinite;}' + 164 '.uvw1-star:nth-child(1){animation-delay:0s}' + 165 '.uvw1-star:nth-child(2){animation-delay:.2s}' + 166 '.uvw1-star:nth-child(3){animation-delay:.4s}' + 167 '.uvw1-star:nth-child(4){animation-delay:.6s}' + 168 '.uvw1-star:nth-child(5){animation-delay:.8s}' + 169 '@keyframes uvw1-starTwinkle{0%,100%{opacity:.6;transform:scale(1)}50%{opacity:1;transform:scale(1.1)}}' + 170 /* Footer text */ 171 '.uvw1-footer-text{color:rgba(255,255,255,.95);font-size:13px;line-height:1.4;flex:1;margin:0 15px;max-width:400px;}
171' + 172 '.uvw1-footer-text.uvw1-desktop-only{display:none;}' + 173 /* Mobile text row */ 174 '.uvw1-mobile-text{display:flex;align-items:center;justify-content:space-between;}' + 175 /* CTA button */ 176 '.uvw1-footer-btn{' + 177 'font-weight:bold;padding:12px 20px;border-radius:6px;border:none;cursor:pointer;' + 178 'text-transform:uppercase;font-size:15px;white-space:normal;text-align:center;flex-shrink:0;' + 179 'color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.3);' + 180 'box-shadow:0 2px 15px rgba(0,0,0,.3);' + 181 'transition:transform .3s ease,box-shadow .3s ease;' + 182 'background-size:300% 300%;' + 183 'animation:uvw1-gradientShift 4s ease infinite,uvw1-footerPulse 5s ease-in-out infinite;' + 184 'word-break:normal;overflow-wrap:break-word;letter-spacing:-.3px;line-height:1.1;' + 185 '}' + 186 '.uvw1-footer-btn:hover{transform:translateY(-2px);box-shadow:0 4px 20px rgba(0,0,0,.4);}' + 187 '@keyframes uvw1-footerPulse{0%,100%{transform:scale(1)}5%{transform:scale(1.05)}10%{transform:scale(1)}15%{transform:scale(1.05)}20%,100%{transform:scale(1)}}' + 188 /* Button arrow */ 189 '.uvw1-btn-arrow{display:inline-block;margin-left:8px;font-size:1.3em;font-weight:bold;vertical-align:middle;line-height:1;position:relative;top:-3px;animation:uvw1-btnArrowPulse 1.2s ease-in-out infinite;}' + 190 '@keyframes uvw1-btnArrowPulse{0%,100%{transform:translateX(0)}50%{transform:translateX(4px)}}' + 191 192 /* ---- Floating gift icon ---- */ 193 '.uvw1-float-icon{position:fixed;right:15px;top:50%;transform:translateY(-50%);z-index:9990;cursor:pointer;display:none;}' + 194 '.uvw1-float-icon.uvw1-visible{display:block;animation:uvw1-iconAppear .5s cubic-bezier(.34,1.56,.64,1);}' + 195 '.uvw1-float-icon.uvw1-winner{animation:uvw1-iconPulse 2s ease-in-out infinite;}' + 196 '@keyframes uvw1-iconAppear{from{transform:translateY(-50%) scale(0) rotate(-180deg);opacity:0}
196to{transform:translateY(-50%) scale(1) rotate(0);opacity:1}}' + 197 '@keyframes uvw1-iconPulse{0%,100%{transform:translateY(-50%) scale(1)}50%{transform:translateY(-50%) scale(1.15)}}' + 198 '.uvw1-float-icon img{width:55px;height:auto;display:block;filter:drop-shadow(0 4px 8px rgba(0,0,0,.4));transition:transform .2s,filter .2s;animation:uvw1-iconWiggle 5s ease-in-out infinite;}' + 199 '@keyframes uvw1-iconWiggle{0%,85%,100%{transform:rotate(0) scale(1)}88%{transform:rotate(-8deg) scale(1.05)}91%{transform:rotate(8deg) scale(1.05)}94%{transform:rotate(-5deg) scale(1.02)}97%{transform:rotate(3deg) scale(1.01)}}' + 200 '.uvw1-float-icon:hover img{transform:scale(1.1);filter:drop-shadow(0 6px 12px rgba(0,0,0,.5));animation:none;}' + 201 202 /* ---- Popup overlay ---- */ 203 '.uvw1-overlay{position:fixed;inset:0;background:rgba(0,0,0,.85);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);display:none;align-items:flex-start;justify-content:center;z-index:9999;opacity:0;transition:opacity .4s;padding:20px;overflow-y:auto;-webkit-overflow-scrolling:touch;}' + 204 '.uvw1-overlay.uvw1-show{display:flex;opacity:1;}' + 205 '.uvw1-popup-wrap{position:relative;max-width:420px;width:100%;flex-shrink:0;margin:auto;animation:uvw1-popupIn .5s cubic-bezier(.34,1.56,.64,1);}' + 206 '@keyframes uvw1-popupIn{from{transform:scale(.8) translateY(50px);opacity:0}to{transform:scale(1) translateY(0);opacity:1}}' + 207 208 /* Close button */ 209 '.uvw1-popup-close{position:absolute;top:-7px;right:-7px;width:28px;height:28px;' + 210 "background:linear-gradient(180deg,#3a3a4a,#2a2a3a);border:2px solid #555;border-radius:50%;color:#ffd700;font-family:'VT323',monospace;font-size:18px;line-height:28px;" + 211 'text-align:center;cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;opacity:0;visibility:hidden;text-shadow:0 0 8px #ffd700;' + 212 'box-shadow:0 3px 6px rgba(0,0,0,.5),inset 0 1px 0 rgba(255,255,255,.1);transition:opacity .3s,visibility .3s,transform .1s;}' + 213 '.uvw1-popup-close.uvw1-visible{opacity:1;visibility:visible;}' + 214 '.uvw1-popup-close:hover{transform:scale(1.1);text-shadow:0 0 12px #ffd700;border-color:#ffd700;background:linear-gradient(180deg,#4a4a5a,#3a3a4a);}' + 215 216 /* Machine body */ 217 '.uvw1-machine{background:linear-gradient(180deg,#4a4a5a 0%,#3a3a4a 5%,#2a2a3a 50%,#1a1a2a 95%,#0a0a1a 100%);border-radius:20px;' + 218 'box-shadow:0 20px 60px rgba(0,0,0,.8),inset 0 2px 0 rgba(255,255,255,.1),inset 0 -2px 0 rgba(0,0,0,.3);border:4px solid #555;border-top-color:#777;border-bottom-color:#333;overflow:hidden;}' + 219 220 /* Brand switch LED panel */ 221 '.uvw1-brand-panel{background:linear-gradient(180deg,#0a0a12,#050508);padding:12px 20px;margin:10px;border-radius:8px;border:2px solid #333;' + 222 'box-shadow:inset 0 0 20px rgba(0,0,0,.8),0 2px 4px rgba(0,0,0,.3),0 0 15px rgba(100,150,255,.1);}' + 223 ".uvw1-brand-title{display:flex;align-items:center;justify-content:center;gap:8px;margin-bottom:12px;font-family:'VT323',monospace;font-size:18px;color:#ccc;text-transform:uppercase;letter-spacing:1px;white-space:nowrap;overflow:hidden;}" + 224 '.uvw1-brand-title-flag{font-size:18px;position:relative;top:2px;}' + 225 '.uvw1-brand-logos{display:flex;align-items:center;justify-content:center;gap:18px;}' + 226 '.uvw1-brand-logo-wrap{display:flex;align-items:center;position:relative;}' + 227 '.uvw1-brand-logo-wrap.uvw1-old{overflow:visible;}' + 228 ".uvw1-brand-blocked{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) rotate(-15deg);font-family:'VT323','Courier New',monospace;font-size:14px;line-height:1;color:#fff;background:rgba(180,30,30,.85);padding:0 4px 1px;border-radius:2px;text-transform:uppercase;letter-spacing:.5px;white-space:nowrap;box-shadow:0 2px 6px rgba(0,0,0,.3);z-index:2;}" + 229 '.uvw1-brand-logo-img{max-height:50px;max-width:120px;object-fit:contain;}' + 230 '.uvw1-old .uvw1-brand-logo-img{filter:grayscale(1) opacity(.4);}' + 231 '.uvw1-new .uvw1-brand-logo-img{filter:drop-shadow(0 0 8px rgba(100,255,100,.6));cursor:pointer;}' + 232 ".uvw1-brand-arrow{font-family:'VT323',monospace;font-size:24px;color:#ffd700;text-shadow:0 0 8px #ffd700,0 0 15px rgba(255,215,0,.5);animation:uvw1-arrowPulseP .8s ease-in-out infinite;}" + 233 '@keyframes uvw1-arrowPulseP{0%,100%{transform:translateX(0);opacity:1}50%{transform:translateX(4px);opacity:.8}}' + 234 235 /* Game area */ 236 '.uvw1-game-area{background:linear-gradient(180deg,#0a0a12,#050508);margin:15px;border-radius:10px;border:3px solid #333;border-top-color:#444;border-bottom-color:#222;' + 237 'box-shadow:inset 0 0 40px rgba(0,0,0,.9),0 4px 8px rgba(0,0,0,.5),0 0 20px rgba(100,150,255,.1);padding:12px;overflow:visible;}' + 238 239 /* Ticker */ 240 '.uvw1-ticker-wrap{padding:6px 10px;overflow:hidden;position:relative;margin-bottom:5px;border-bottom:1px solid rgba(255,140,0,.2);}' + 241 ".uvw1-ticker-wrap::before,.uvw1-ticker-wrap::after{content:'';position:absolute;top:0;bottom:0;width:30px;z-index:2;}" + 242 '.uvw1-ticker-wrap::before{left:0;background:linear-gradient(90deg,#0a0a12 30%,transparent);}' + 243 '.uvw1-ticker-wrap::after{right:0;background:linear-gradient(-90deg,#0a0a12 30%,transparent);}' + 244 ".uvw1-ticker-text{font-family:'VT323',monospace;font-size:24px;color:#ff8c00;letter-spacing:1px;text-shadow:0 0 4px #ff8c00;white-space:nowrap;display:inline-block;animation:uvw1-marquee 15s linear infinite;will-change:transform;transform:translateZ(0);}" +
245 '@keyframes uvw1-marquee{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}' + 246 247 /* Reels */ 248 '.uvw1-reels-wrap{margin-bottom:12px;padding:10px;background:rgba(0,0,0,.4);border-radius:10px;box-shadow:0 0 20px rgba(100,150,255,.15),inset 0 0 15px rgba(0,0,0,.5);display:flex;justify-content:center;gap:10px;}' + 249 '.uvw1-reel{width:85px;height:95px;overflow:hidden;background:#050505;border-radius:6px;border:3px solid #333;border-top-color:#222;border-bottom-color:#444;position:relative;box-shadow:0 4px 8px rgba(0,0,0,.5),inset 0 0 30px rgba(0,0,0,.9);}' + 250 ".uvw1-reel::after{content:'';position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.7) 0%,transparent 30%,transparent 70%,rgba(0,0,0,.7) 100%);z-index:3;pointer-events:none;}" + 251 '.uvw1-reel.uvw1-cracked{animation:uvw1-reelShake .5s ease-out;}' + 252 '.uvw1-reel.uvw1-cracked .uvw1-reel-sym{animation:uvw1-bgPulse .4s ease-in-out infinite;}' + 253 '@keyframes uvw1-reelShake{0%,100%{transform:translateX(0)}10%{transform:translateX(-4px) rotate(-1deg)}20%{transform:translateX(4px) rotate(1deg)}30%{transform:translateX(-4px) rotate(-1deg)}40%{transform:translateX(4px) rotate(1deg)}50%{transform:translateX(-2px)}60%{transform:translateX(2px)}70%{transform:translateX(-1px)}80%{transform:translateX(1px)}}' + 254 '@keyframes uvw1-bgPulse{0%,100%{background:linear-gradient(180deg,#ff9999,#ffaaaa 20%,#ffcccc 50%,#ffaaaa 80%,#ff9999)}50%{background:linear-gradient(180deg,#e8e8f0,#f5f5ff 20%,#fff 50%,#f5f5ff 80%,#e8e8f0)}}' + 255 '.uvw1-reel-strip{display:flex;flex-direction:column;transition:transform .1s linear;}' + 256 '.uvw1-reel-strip.uvw1-spinning{transition:none;filter:blur(2px);}' + 257 '.uvw1-reel-strip.uvw1-stopping{transition:transform .6s cubic-bezier(.25,.1,.25,1),filter .3s;filter:blur(0);}' + 258 '.uvw1-reel-sym{width:100%;height:95px;display:flex;align-items:center;justify-content:center;font-size:48px;' + 259 'background:linear-gradient(180deg,#e8e8f0,#f5f5ff 20%,#fff 50%,#f5f5ff 80%,#e8e8f0);border-bottom:1px solid #ccc;border-top:1px solid #fff;box-shadow:inset 0 0 20px rgba(200,220,255,.5);}' + 260 261 /* Hearts/Lives */ 262 '.uvw1-hearts{display:flex;justify-content:center;align-items:center;gap:8px;padding:12px 0;}' + 263 ".uvw1-hearts-label{font-family:'VT323',monospace;font-size:18px;color:#fff;margin-right:8px;text-shadow:0 0 5px #fff;}" + 264 ".uvw1-heart{width:28px;height:28px;background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOtwAADrcBHI9bQQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKLSURBVFiF1ZbBaxNBFMZ/m8RabcGahlA8FD1IvfRSvIhHoQdPHnr1UnLVq96LiBaE/gFV+xcoeCgNCCKIYKFUeylUsDGXRqNpklojyeZ5mNnd2c1mE0JI2g+GGd6b9/bt+76dHWjFIiARIx8S4yDfIXYxGBCLSDYQWMb6NXBjAhJ3IQkQB7H9e9iCfx+gDPwAZrV5B0jfhAtzcBbgOnAGaIIc6xzLUNmDGvARuBMsxgYkDSIRI+NvqQNB+4L7t0Ee6zHnxdlO4ImgQABWQG6D1QCuzcyotxsbE2zb4vBQyOViADmQOljfgVs6yVtgGhgBmQ5QVgI50LZXqP7nQV4a+wSQdbN1DhqNhoiILC01g60tGVSUOtDmjCeaivtG7FAoMMWTaPHGjJqmpuIUixBoK8BEIFE3GAcqwI4KtWDAIqzq+YrxQm4Hak5V8ThkMspo226lBsJsUT7X5ih+0nC6BYw6gfU6rK465rAHtXt4x/1NPZ83nAOlwKmkadjcAmqOppJJ2NhQY2EhTGdR2ovcP6rnScPWSkEiAfPzypjN9pWCEeAvcM6wDZSCWGAGf8U2EEsDhT4+tAC80OtHwJFaNoF4sJihwDwJy8BFAfmqO5MCmejxHPgC1IGfIL+0TTx/Oaoo90q21eVPJmw81T+eeyf9Stb6M4J3qOsWy5BKQewS8NDzt6XgG0hW+94Dv4E/SnBFI7cPUd80qGBrFsVpJ3wG1vV6BTjwCm7b6aFT0C3W0ELaDxHcMy24B37BrXWTeOgdCBNhGHadxba+lB7h3a0rqBOu4BfoLl2gkwjDIABX8T7q58BejzlPDQUmPgGXqzD+Rl9uqnCMYmG/j7V1xCae4jd7TTJ0Cv4DKZdBhaN0klIAAAAASUVORK5CYII=') center/contain no-repeat;image-rendering:pixelated;transition:all .3s;}" + 265 '.uvw1-heart.uvw1-active{animation:uvw1-heartBeat .8s ease-in-out infinite;filter:drop-shadow(0 0 10px #ff0040);}' + 266 '.uvw1-heart.uvw1-used{opacity:.85;filter:grayscale(1) brightness(1.1) drop-shadow(0 0 6px #ff0040);transform:scale(.75);}' + 267 '.uvw1-heart.uvw1-burning{animation:uvw1-heartBurn .8s ease-out forwards;}' + 268 '.uvw1-heart.uvw1-win{animation:uvw1-heartWin .3s ease-in-out infinite;filter:drop-shadow(0 0 12px #ffd700) brightness(1.3) hue-rotate(40deg);}' + 269 270 /* Heart particles */ 271 '.uvw1-heart-particle{position:fixed;width:8px;height:8px;background:#ff0040;border-radius:50%;pointer-events:none;z-index:10001;box-shadow:0 0 6px #ff0040,0 0 10px #ff4444;animation:uvw1-particleExplode .6s ease-out forwards;}' + 272 '.uvw1-heart-particle:nth-child(odd){background:#ff4466;}' + 273 '.uvw1-heart-particle:nth-child(3n){background:#ff6688;width:6px;height:6px;}
273' + 274 '@keyframes uvw1-particleExplode{0%{transform:translate(0,0) scale(1);opacity:1}100%{transform:translate(var(--tx),var(--ty)) scale(0);opacity:0}}' + 275 '@keyframes uvw1-heartBeat{0%,100%{transform:scale(1)}50%{transform:scale(1.15)}}' + 276 '@keyframes uvw1-heartBurn{0%{transform:scale(1);filter:drop-shadow(0 0 10px #ff0040) brightness(1);opacity:1}20%{transform:scale(1.3);filter:drop-shadow(0 0 20px #ff4444) drop-shadow(0 0 30px #ff0000) brightness(1.5)}40%{transform:scale(1.1) rotate(-10deg);filter:drop-shadow(0 0 15px #ff6600) brightness(1.3)}60%{transform:scale(.85) rotate(5deg);filter:drop-shadow(0 0 10px #ff3300) grayscale(.3) brightness(1)}80%{transform:scale(.8);filter:grayscale(.8) brightness(1.1);opacity:.9}100%{transform:scale(.75);filter:grayscale(1) brightness(1.1) drop-shadow(0 0 6px #ff0040);opacity:.85}}' + 277 '@keyframes uvw1-heartWin{0%,100%{transform:scale(1)}50%{transform:scale(1.2)}}' + 278 ".uvw1-hearts-count{font-family:'VT323',monospace;font-size:18px;color:#ffaa00;margin-left:12px;text-shadow:0 0 5px #ffaa00;}" + 279 280 /* Message area */ 281 '.uvw1-msg-area{margin-top:8px;border-top:1px solid rgba(255,255,255,.1);padding-top:5px;}' + 282 ".uvw1-msg{text-align:center;padding:0 15px;font-family:'VT323',monospace;font-size:18px;font-weight:bold;height:36px;line-height:36px;color:#666;}" + 283 '.uvw1-dots{display:none;justify-content:center;align-items:center;gap:6px;height:36px;}' + 284 '.uvw1-dots.uvw1-active{display:flex;}' + 285 '.uvw1-dot{width:6px;height:6px;background:#fff;opacity:.3;animation:uvw1-dotBlink .8s steps(1) infinite;}' + 286 '.uvw1-dot:nth-child(1){animation-delay:0s}.uvw1-dot:nth-child(2){animation-delay:.25s}.uvw1-dot:nth-child(3){animation-delay:.5s}' + 287 '@keyframes uvw1-dotBlink{0%,50%{opacity:.3}25%{opacity:1;box-shadow:0 0 6px #fff}}' + 288 '.uvw1-msg.uvw1-press-spin{color:#ffd700;text-shadow:0 0 10px #ffd700,0 0 20px rgba(255,215,0,.5);line-height:1.4;height:auto;}' + 289 '.uvw1-msg.uvw1-press-spin .uvw1-arrow-down{display:inline-block;font-size:22px;animation:uvw1-arrowDown .6s ease-in-out infinite;}' + 290 '@keyframes uvw1-arrowDown{0%,100%{transform:translateY(0);opacity:1}50%{transform:translateY(4px);opacity:.6}}' + 291 '.uvw1-msg.uvw1-try-again{color:#ff8c00;text-shadow:0 0 4px #ff8c00;animation:uvw1-msgBlink .5s ease-in-out 3;}' + 292 '.uvw1-msg.uvw1-winner-msg{color:#fff;font-size:20px;text-shadow:0 0 5px rgba(255,255,255,.6);animation:uvw1-msgWin .3s ease-in-out infinite;}' + 293 '@keyframes uvw1-msgBlink{0%,100%{opacity:1}50%{opacity:.5}}' + 294 '@keyframes uvw1-msgWin{0%,100%{transform:scale(1)}50%{transform:scale(1.02)}}' + 295 296 /* Prize section */ 297 '.uvw1-prize-section{padding:5px 15px 7px;text-align:center;display:none;}' + 298 '.uvw1-prize-section.uvw1-revealed{display:block;animation:uvw1-prizeReveal .5s ease-out;}' + 299 '@keyframes uvw1-prizeReveal{from{transform:scale(.8);opacity:0}to{transform:scale(1);opacity:1}}' + 300 ".uvw1-prize-value{font-family:'VT323',monospace;font-size:32px;font-weight:bold;color:#ffdd00;text-shadow:0 0 8px #ffdd00,0 0 15px rgba(255,221,0,.4);animation:uvw1-ledGlow 2s ease-in-out infinite;white-space:nowrap;}" + 301 '.uvw1-prize-detail-span{font-size:32px;color:#ffcc00;text-shadow:0 0 8px #ffcc00;}' + 302 ".uvw1-prize-sub{font-family:'VT323',monospace;font-size:16px;color:#888;margin-top:6px;}" + 303 '@keyframes uvw1-ledGlow{0%,100%{text-shadow:0 0 15px #ffdd00,0 0 30px rgba(255,221,0,.5)}50%{text-shadow:0 0 25px #ffdd00,0 0 50px rgba(255,221,0,.8)}}' + 304 305 /* Buttons */ 306 ".uvw1-slot-btn{width:90%;margin:0 auto 15px;padding:12px 16px;font-family:'VT323',monospace;font-size:18px;font-weight:bold;color:#fff;" + 307 'border:3px solid #666;border-top-color:#888;border-left-color:#777;border-bottom-color:#444;border-right-color:#555;border-radius:8px;cursor:pointer;text-transform:uppercase;text-decoration:none;' + 308 'letter-spacing:1px;display:flex;align-items:center;justify-content:center;gap:10px;text-shadow:0 2px 3px rgba(0,0,0,.6);transition:all .08s;}
308' + 309 '.uvw1-spin-btn{background:radial-gradient(ellipse at 50% 30%,#ff7788,#ff3344 40%,#dd1122 80%,#bb0011);' + 310 'box-shadow:inset 0 3px 6px rgba(255,255,255,.3),inset 0 -3px 6px rgba(0,0,0,.4),0 4px 0 #880011,0 6px 10px rgba(0,0,0,.5),0 0 15px rgba(255,50,50,.4),0 0 30px rgba(255,50,50,.2);' + 311 'border-color:#ff5566;animation:uvw1-spinPulse 1s ease-in-out infinite;}' + 312 '@keyframes uvw1-spinPulse{0%,100%{transform:scale(1);box-shadow:inset 0 3px 6px rgba(255,255,255,.3),inset 0 -3px 6px rgba(0,0,0,.4),0 4px 0 #880011,0 6px 10px rgba(0,0,0,.5),0 0 15px rgba(255,50,50,.4),0 0 30px rgba(255,50,50,.2)}50%{transform:scale(1.03);box-shadow:inset 0 3px 6px rgba(255,255,255,.4),inset 0 -3px 6px rgba(0,0,0,.3),0 4px 0 #880011,0 6px 10px rgba(0,0,0,.5),0 0 25px rgba(255,50,50,.5),0 0 45px rgba(255,50,50,.3)}}' + 313 '.uvw1-spin-btn:hover:not(:disabled){background:radial-gradient(ellipse at 50% 30%,#ff8899,#ff5566 40%,#ee2233 80%,#cc1122);}' + 314 '.uvw1-spin-btn:active:not(:disabled){box-shadow:inset 0 3px 8px rgba(0,0,0,.5),0 1px 0 #333,0 2px 5px rgba(0,0,0,.4);transform:translateY(3px);animation:none;}' + 315 '.uvw1-spin-btn:disabled{background:radial-gradient(ellipse at 50% 30%,#555,#444 40%,#333 80%,#222);border-color:#444;color:#666;cursor:not-allowed;animation:none;' + 316 'box-shadow:inset 0 3px 6px rgba(255,255,255,.1),inset 0 -3px 6px rgba(0,0,0,.4),0 4px 0 #222,0 6px 10px rgba(0,0,0,.5);}' + 317 '.uvw1-claim-btn{display:none;margin-top:0;font-size:24px;padding:14px 18px;' + 318 'background:radial-gradient(ellipse at 50% 30%,#ffaa44,#ff8800 40%,#dd6600 80%,#bb4400);' + 319 'box-shadow:inset 0 3px 6px rgba(255,255,255,.4),inset 0 -3px 6px rgba(0,0,0,.4),0 4px 0 #884400,0 6px 15px rgba(0,0,0,.5),0 0 20px rgba(255,140,0,.4),0 0 40px rgba(255,140,0,.2);' + 320 'color:#fff;text-shadow:0 2px 4px rgba(0,0,0,.9),0 0 10px rgba(0,0,0,.5);border-color:#ffaa44;animation:uvw1-claimPulse .8s ease-in-out infinite;text-decoration:none;}' + 321 '.uvw1-claim-btn.uvw1-show{display:flex;}' + 322 '.uvw1-claim-btn:hover{background:radial-gradient(ellipse at 50% 30%,#ffcc66,#ffaa44 40%,#ff8800 80%,#dd6600);' + 323 'box-shadow:inset 0 3px 6px rgba(255,255,255,.5),inset 0 -3px 6px rgba(0,0,0,.3),0 4px 0 #995500,0 6px 15px rgba(0,0,0,.5),0 0 30px rgba(255,140,0,.6),0 0 60px rgba(255,140,0,.3);}' + 324 '.uvw1-claim-btn:active{box-shadow:inset 0 3px 8px rgba(0,0,0,.5),0 1px 0 #333,0 2px 5px rgba(0,0,0,.4);transform:translateY(3px);animation:none;}' + 325 '@keyframes uvw1-claimPulse{0%,100%{transform:scale(1);box-shadow:inset 0 3px 6px rgba(255,255,255,.4),inset 0 -3px 6px rgba(0,0,0,.4),0 4px 0 #884400,0 6px 15px rgba(0,0,0,.5),0 0 20px rgba(255,140,0,.4),0 0 40px rgba(255,140,0,.2)}50%{transform:scale(1.05);box-shadow:inset 0 3px 6px rgba(255,255,255,.5),inset 0 -3px 6px rgba(0,0,0,.3),0 4px 0 #884400,0 6px 15px rgba(0,0,0,.5),0 0 35px rgba(255,140,0,.6),0 0 60px rgba(255,140,0,.4)}}' + 326 327 /* Machine winner state */ 328 '.uvw1-machine.uvw1-winner{animation:uvw1-machineShake .5s ease-in-out;}' + 329 '.uvw1-machine.uvw1-winner .uvw1-reel-sym{background:linear-gradient(180deg,#fff8e0,#fffef5 20%,#fffff0 50%,#fffef5 80%,#fff8e0);' + 330 'box-shadow:inset 0 0 25px rgba(255,215,0,.4),0 0 15px rgba(255,215,0,.6);animation:uvw1-symbolGlow .3s ease-in-out infinite alternate;}' + 331 '.uvw1-machine.uvw1-winner .uvw1-game-area{box-shadow:inset 0 0 30px rgba(0,0,0,.6),0 0 30px rgba(255,215,0,.5),0 0 50px rgba(255,180,0,.3);}' + 332 '@keyframes uvw1-symbolGlow{from{box-shadow:inset 0 0 25px rgba(255,215,0,.3),0 0 10px rgba(255,215,0,.4)}to{box-shadow:inset 0 0 30px rgba(255,215,0,.5),0 0 20px rgba(255,215,0,.8)}}' + 333 '@keyframes uvw1-machineShake{0%,100%{transform:translateX(0)}20%{transform:translateX(-5px) rotate(-1deg)}40%{transform:translateX(5px) rotate(1deg)}60%{transform:translateX(-5px) rotate(-1deg)}80%{transform:translateX(5px) rotate(1deg)}}' + 334 335 /* Coin fall */ 336 '.uvw1-coin-fall{position:fixed;top:-30px;z-index:10000;animation:uvw1-coinFall 3s ease-out forwards;}' + 337 '@keyframes uvw1-coinFall{from{transform:translateY(0) rotate(0);opacity:1}to{transform:translateY(100vh) rotate(720deg);opacity:0}
337}' + 338 339 /* Timer */ 340 '.uvw1-timer{display:none;align-items:center;justify-content:center;gap:6px;margin:5px 0;}' + 341 '.uvw1-timer.uvw1-show{display:flex;}' + 342 ".uvw1-timer-label{font-family:'VT323',monospace;font-size:16px;color:#888;}" + 343 '.uvw1-timer-value{color:#ff6666;text-shadow:0 0 8px rgba(255,100,100,.6);}' + 344 '.uvw1-timer.uvw1-urgent .uvw1-timer-value{color:#ff3333;animation:uvw1-urgentBlink .5s ease-in-out infinite;}' + 345 '@keyframes uvw1-urgentBlink{0%,100%{opacity:1;text-shadow:0 0 10px #ff3333}50%{opacity:.7;text-shadow:0 0 5px #ff3333}}' + 346 347 /* ---- Banner popup ---- */ 348 '.uvw1-banner{position:relative;border-radius:18px;overflow:hidden;width:100%;' + 349 'box-shadow:0 0 30px rgba(255,215,0,.15),0 20px 60px rgba(0,0,0,.7);border:1px solid rgba(255,215,0,.2);}' + 350 '.uvw1-banner-bg{position:absolute;inset:0;background-size:cover;background-position:center;z-index:0;}' + 351 '.uvw1-banner-bg::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.45) 0%,rgba(0,0,0,.7) 40%,rgba(0,0,0,.92) 100%);}' + 352 353 /* Warning strip */ 354 '.uvw1-banner-warning{position:relative;z-index:1;background:linear-gradient(135deg,rgba(180,40,40,.35),rgba(120,30,30,.15));' + 355 'border-bottom:1px solid rgba(255,80,80,.15);padding:14px 20px;text-align:center;}' + 356 '.uvw1-banner-warn-icon{display:inline-block;width:18px;height:18px;background:#d44;border-radius:50%;color:#fff;font-size:12px;font-weight:900;' + 357 'line-height:18px;text-align:center;margin-right:6px;vertical-align:middle;flex-shrink:0;}' + 358 '@keyframes uvw1-warnPulse{0%,100%{box-shadow:0 0 0 0 rgba(204,51,51,.6)}50%{box-shadow:0 0 0 6px rgba(204,51,51,0)}}' + 359 '.uvw1-banner-restricted{color:#ff8a8a;font-size:14px;font-weight:600;line-height:1.5;display:inline;}' + 360 '.uvw1-banner-restricted .uvw1-banner-oldname{color:#fff;font-weight:800;}' + 361 362 /* Content area */ 363 '.uvw1-banner-body{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;padding:22px 24px 24px;text-align:center;}' + 364 '.uvw1-banner-recommend{color:rgba(255,255,255,.45);font-size:11px;text-transform:uppercase;letter-spacing:2px;margin-bottom:18px;}' + 365 366 /* Logo with glow + pulse */ 367 '.uvw1-banner-logo-wrap{position:relative;margin-bottom:14px;padding-bottom:14px;border-bottom:1px solid rgba(255,255,255,.08);}' + 368 '.uvw1-banner-logo-wrap::before{content:"";position:absolute;inset:-20px;background:radial-gradient(ellipse,rgba(255,215,0,.15) 0%,transparent 70%);z-index:0;animation:uvw1-logoGlow 3s ease-in-out infinite;}' + 369 '.uvw1-banner-logo{position:relative;z-index:1;max-height:55px;max-width:190px;object-fit:contain;filter:drop-shadow(0 2px 10px rgba(0,0,0,.4));animation:uvw1-logoPulse 3s ease-in-out infinite;}' + 370 '@keyframes uvw1-logoGlow{0%,100%{opacity:.6;transform:scale(1)}50%{opacity:1;transform:scale(1.1)}}' + 371 '@keyframes uvw1-logoPulse{0%,100%{transform:scale(1);filter:drop-shadow(0 2px 10px rgba(0,0,0,.4))}50%{transform:scale(1.03);filter:drop-shadow(0 0 18px rgba(255,215,0,.3))}}' + 372 373 /* Bonus card */ 374 '.uvw1-banner-bonus{background:linear-gradient(135deg,rgba(255,255,255,.07),rgba(255,255,255,.02));' + 375 'border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:16px 20px;margin-bottom:20px;width:100%;box-sizing:border-box;}' + 376 '.uvw1-banner-bonus-label{font-size:11px;color:rgba(255,255,255,.45);text-transform:uppercase;letter-spacing:2.5px;margin-bottom:8px;font-weight:600;}' + 377 ".uvw1-banner-prize-line{font-size:20px;font-weight:800;color:#fff;font-family:'Arial Black',Arial,sans-serif;line-height:1.3;}" + 378 ".uvw1-banner-prize-line .uvw1-banner-pct{color:#ffd700;text-shadow:0 0 20px rgba(255,215,0,.4);}" + 379 '.uvw1-banner-sub{font-size:11px;color:rgba(255,215,0,.6);margin-top:10px;text-transform:uppercase;letter-spacing:1.5px;font-weight:600;}' + 380 '.uvw1-banner-exclusive{margin-top:12px;font-size:10px;color:rgba(255,255,255,.35);letter-spacing:.5px;}' + 381 '.uvw1-banner-timer{margin-top:14px;width:100%;}' + 382 '.uvw1-banner-timer-text{font-size:10px;color:rgba(255,255,255,.35);letter-spacing:.5px;margin-bottom:5px;}' + 383 '.uvw1-banner-timer-text span{color:rgba(255,255,255,.6);font-variant-numeric:tabular-nums;}' + 384 '.uvw1-banner-timer-bar{width:100%;height:3px;background:rgba(255,255,255,.08);border-radius:2px;overflow:hidden;}
384' + 385 '.uvw1-banner-timer-fill{height:100%;background:linear-gradient(90deg,#22c55e,#16a34a);border-radius:2px;width:0%;}' + 386 387 /* CTA button */ 388 '.uvw1-banner-btn{display:block;width:100%;padding:15px 20px;border-radius:12px;border:none;cursor:pointer;font-size:16px;font-weight:800;' + 389 'color:#fff;text-decoration:none;text-transform:uppercase;letter-spacing:1.5px;text-align:center;box-sizing:border-box;position:relative;overflow:hidden;' + 390 'background:linear-gradient(135deg,#22c55e,#16a34a,#15803d);background-size:200% 200%;' + 391 'animation:uvw1-bannerBtnShift 3s ease infinite,uvw1-bannerBtnPulse 2s ease-in-out infinite;' + 392 'box-shadow:0 4px 20px rgba(34,197,94,.3);transition:transform .2s,box-shadow .2s;}' + 393 '.uvw1-banner-btn::after{content:"";position:absolute;top:0;left:-100%;width:60%;height:100%;' + 394 'background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.25) 50%,transparent 70%);animation:uvw1-btnShine 3s ease-in-out infinite;}' + 395 '.uvw1-banner-btn:hover{transform:translateY(-2px);box-shadow:0 8px 30px rgba(34,197,94,.4);}' + 396 '@keyframes uvw1-bannerBtnShift{0%,100%{background-position:0% 50%}50%{background-position:100% 50%}}' + 397 '@keyframes uvw1-bannerBtnPulse{0%,100%{box-shadow:0 4px 20px rgba(34,197,94,.3)}50%{box-shadow:0 4px 28px rgba(34,197,94,.5)}}' + 398 '@keyframes uvw1-btnShine{0%,70%{left:-100%}100%{left:150%}}' + 399 400 /* Close button â small, inside banner */ 401 '.uvw1-banner-close{position:absolute;top:8px;right:8px;width:22px;height:22px;' + 402 'background:rgba(0,0,0,.3);border:none;border-radius:50%;color:rgba(255,255,255,.5);font-size:14px;line-height:1;' + 403 'cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;padding-bottom:4px;' + 404 'opacity:0;transition:opacity .3s,color .2s;}' + 405 '.uvw1-banner-close.uvw1-visible{opacity:1;}' + 406 '.uvw1-banner-close:hover{color:#fff;}' + 407 408 /* Entrance animation */ 409 '@keyframes uvw1-bannerIn{from{opacity:0;transform:scale(.92) translateY(20px)}to{opacity:1;transform:scale(1) translateY(0)}}' + 410 '.uvw1-popup-wrap .uvw1-banner{animation:uvw1-bannerIn .4s cubic-bezier(.16,1,.3,1) forwards;}' + 411 412 /* ---- Responsive: banner mobile ---- */ 413 '@media(max-width:480px){' + 414 '.uvw1-banner-warning{padding:16px 28px;}' + 415 '}' + 416 417 /* ---- Wallet sticky footer ---- */ 418 '.uvw1-wallet{position:fixed;bottom:0;left:0;right:0;z-index:9990;transform:translateY(100%);transition:transform .5s cubic-bezier(.4,0,.2,1);}' + 419 '.uvw1-wallet.uvw1-show{transform:translateY(0);}' + 420 '.uvw1-wallet-inner{background:linear-gradient(to right,#1a365d,#4a3880);border-top:1px solid rgba(59,130,246,.5);padding:14px 20px 12px;display:flex;align-items:center;justify-content:center;gap:16px;flex-wrap:nowrap;}' + 421 '.uvw1-wallet-close{position:absolute;top:6px;right:8px;background:none;border:none;color:rgba(255,255,255,.4);font-size:16px;cursor:pointer;padding:2px 6px;transition:color .2s;}' + 422 '.uvw1-wallet-close:hover{color:#fff;}' + 423 '.uvw1-wallet-icon{font-size:28px;flex-shrink:0;animation:uvw1-walletPulse 2s ease-in-out infinite;}' + 424 '@keyframes uvw1-walletPulse{0%,100%{transform:scale(1)}50%{transform:scale(1.1)}}' + 425 '.uvw1-wallet-info{display:flex;flex-direction:column;gap:2px;min-width:0;}' + 426 '.uvw1-wallet-bonus{line-height:1.3;}' + 427 '.uvw1-wallet-bonus-label{color:rgba(255,255,255,.8);font-size:12px;font-weight:600;letter-spacing:.5px;}' + 428 '.uvw1-wallet-bonus-value{color:#ffd700;font-size:20px;font-weight:800;text-shadow:0 0 8px rgba(255,215,0,.3);}' + 429 '.uvw1-wallet-hurry{color:#ff6b6b;font-size:11px;font-weight:700;letter-spacing:.5px;animation:uvw1-hurryBlink 1.5s ease-in-out infinite;}' + 430 '@keyframes uvw1-hurryBlink{0%,100%{opacity:1}50%{opacity:.4}}' + 431 '.uvw1-wallet.uvw1-urgent .uvw1-wallet-inner{animation:uvw1-walletUrgent 1s ease-in-out infinite;}' + 432 '@keyframes uvw1-walletUrgent{0%,100%{border-top-color:rgba(255,68,68,.5)}50%{border-top-color:rgba(255,68,68,.15)}}' + 433 '.uvw1-wallet-btn{flex-shrink:0;padding:10px 24px;border-radius:10px;border:none;cursor:pointer;font-size:16px;font-weight:900;color:#fff;text-transform:uppercase;letter-spacing:1px;' + 434 'background:rgba(255,255,255,.06);box-shadow:0 1px 8px var(--glow,rgba(34,197,94,.2));transition:transform .2s,box-shadow .5s;position:relative;overflow:hidden;}
434' + 435 '.uvw1-wallet-btn::before{content:"";position:absolute;top:0;left:0;bottom:0;width:var(--progress,100%);' + 436 'background:linear-gradient(90deg,var(--fill-start,#22c55e),var(--fill-end,#16a34a));' + 437 'transition:width 1s linear,background .5s;z-index:0;' + 438 'box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -1px 0 rgba(0,0,0,.15);' + 439 '-webkit-mask:linear-gradient(#000,#000) left/calc(100% - 4px) 100% no-repeat,' + 440 'radial-gradient(circle 4px at left,#000 98%,transparent) right/4px 8px repeat-y;' + 441 'mask:linear-gradient(#000,#000) left/calc(100% - 4px) 100% no-repeat,' + 442 'radial-gradient(circle 4px at left,#000 98%,transparent) right/4px 8px repeat-y;' + 443 'animation:uvw1-flameEdge .8s linear infinite;}' + 444 '.uvw1-wallet-btn::after{content:"";position:absolute;top:0;left:-100%;width:60%;height:100%;' + 445 'background:linear-gradient(105deg,transparent 30%,rgba(255,255,255,.25) 50%,transparent 70%);animation:uvw1-btnShine 3s ease-in-out infinite;z-index:1;}' + 446 '.uvw1-wallet-btn:hover{transform:translateY(-1px);}' + 447 '.uvw1-wallet-btn span,.uvw1-wallet-btn .uvw1-btn-arrow{position:relative;z-index:2;text-shadow:0 1px 3px rgba(0,0,0,.4);}' + 448 '@keyframes uvw1-btnPulseGlow{0%,100%{box-shadow:0 1px 6px var(--glow,rgba(34,197,94,.2))}50%{box-shadow:0 1px 10px var(--glow,rgba(34,197,94,.35)),0 0 16px var(--glow,rgba(34,197,94,.15))}}' + 449 '@keyframes uvw1-flameEdge{0%{-webkit-mask-position:left top,right 0;mask-position:left top,right 0}100%{-webkit-mask-position:left top,right -8px;mask-position:left top,right -8px}}' + 450 451 /* ---- Responsive: wallet mobile ---- */ 452 '@media(max-width:849px){' + 453 '.uvw1-wallet-inner{padding:12px 15px 10px;gap:8px;flex-wrap:wrap;}' + 454 '.uvw1-wallet-icon{font-size:24px;}' + 455 '.uvw1-wallet-info{flex-basis:100%;text-align:center;min-width:0;}' + 456 '.uvw1-wallet-bonus-value{font-size:18px;}' + 457 '.uvw1-wallet-bonus-label{margin-bottom:3px;}' + 458 '.uvw1-wallet-btn{flex-basis:100%;padding:12px 20px;font-size:17px;font-weight:900;border-radius:8px;}' + 459 '}' + 460 461 /* ---- Responsive: footer mobile ---- */ 462 '@media(max-width:849px){' + 463 '.uvw1-footer-inner{display:flex;flex-direction:column;padding:12px 15px;position:relative;}' + 464 '.uvw1-footer-content{flex:1;display:flex;flex-direction:column;justify-content:center;}' + 465 '.uvw1-footer-close{top:3px;right:3px;font-size:16px;padding:2px 6px;}' + 466 '.uvw1-footer-row{margin-bottom:0;flex-wrap:nowrap;justify-content:center;padding-right:25px;}' + 467 '.uvw1-footer-logos{margin-left:0;}' + 468 '.uvw1-footer-arrow{margin:0 10px;}' + 469 '.uvw1-brand-info{margin-left:18px;}' + 470 '.uvw1-logo-card{width:55px;height:40px;}' + 471 '.uvw1-mobile-text{display:block;margin-top:8px;}' + 472 '.uvw1-footer-text.uvw1-in-mobile{display:block;text-align:center;font-size:12px;line-height:1.3;margin:0;max-width:none;}' + 473 '.uvw1-footer-btn:not(.uvw1-desktop-only){' + 474 'position:static;width:100%;box-sizing:border-box;margin-top:10px;padding:12px 20px;' + 475 'display:flex;align-items:center;justify-content:center;' + 476 'font-size:15px;font-weight:700;letter-spacing:.5px;line-height:1.2;border-radius:8px;' + 477 '}' + 478 '.uvw1-footer-btn:not(.uvw1-desktop-only) .uvw1-btn-arrow{top:-2px;}' + 479 '.uvw1-footer-btn.uvw1-desktop-only{display:none!important;}' + 480 '.uvw1-footer .uvw1-footer-row,.uvw1-footer .uvw1-mobile-text{' + 481 'transition:transform .5s cubic-bezier(.4,0,.2,1),opacity .5s cubic-bezier(.4,0,.2,1)!important;' + 482 'transform:translateY(0)!important;opacity:1!important;' + 483 '}' + 484 '.uvw1-footer.uvw1-collapsed .uvw1-footer-row,' + 485 '.uvw1-footer.uvw1-collapsed .uvw1-mobile-text{' + 486 'transform:translateY(-20px)!important;opacity:0!important;height:0!important;' + 487 'overflow:hidden!important;margin:0!important;padding:0!important;pointer-events:none!important;' + 488 'transition:transform .5s cubic-bezier(.4,0,.2,1),opacity .5s cubic-bezier(.4,0,.2,1),height .5s cubic-bezier(.4,0,.2,1)!important;' + 489 '}' + 490 '.uvw1-footer.uvw1-collapsed .uvw1-footer-btn:not(.uvw1-desktop-only){margin:0!important;}' + 491 '}' + 492 '@media(min-width:850px){' + 493 '.uvw1-footer-inner{padding:10px 15px;display:flex;align-items:center;}' + 494 '.uvw1-footer-btn:not(.uvw1-desktop-only){display:none!important;}' + 495 '.uvw1-footer-content{margin-bottom:0;flex:1;justify-content:space-between;display:flex;align-items:center;}' + 496 '.uvw1-mobile-text{display:none;}' + 497 '.uvw1-footer-text.uvw1-desktop-only{display:block!important;margin-left:25px;margin-right:20px;max-width:450px;font-size:12px;}' + 498 '.uvw1-footer-btn.uvw1-desktop-only{display:block!important;margin-right:30px;padding-top:14px;}' + 499 '.uvw1-footer-row{margin-bottom:0;flex:1;}' + 500 '.uvw1-brand-info{min-width:120px;flex-shrink:0;margin-right:0;}' + 501 '}' + 502 '@supports(padding-bottom:env(safe-area-inset-bottom)){.uvw1-footer{padding-bottom:env(safe-area-inset-bottom);}}' + 503 '@media(max-width:480px){' + 504 '.uvw1-overlay{padding:10px;}' + 505 '.uvw1-popup-wrap{max-width:100%;}' + 506 '.uvw1-machine{border-radius:16px;border-width:3px;}' + 507 '.uvw1-popup-close{right:5px;top:-5px;}' + 508 '.uvw1-reel{width:90px;height:100px;}' + 509 '.uvw1-reel-sym{height:100px;font-size:50px;}
509' + 510 '.uvw1-reels-wrap{gap:8px;margin-top:5px;}' + 511 '.uvw1-brand-panel{padding:12px 15px;margin:8px;}' + 512 '.uvw1-brand-title{font-size:14px;gap:6px;margin-bottom:10px;}' + 513 '.uvw1-brand-title-flag{font-size:16px;}' + 514 '.uvw1-brand-logos{gap:14px;}' + 515 '.uvw1-brand-logo-img{max-height:42px;max-width:100px;}' + 516 '.uvw1-brand-arrow{font-size:20px;}' + 517 '.uvw1-game-area{margin:10px;padding:10px;overflow:visible;}' + 518 '.uvw1-prize-section{margin-top:5px;padding:5px 10px 10px;}' + 519 '.uvw1-prize-value{font-size:28px;text-shadow:0 0 5px rgba(255,204,0,.4);}' + 520 '.uvw1-prize-detail-span{font-size:28px;text-shadow:0 0 5px rgba(255,204,0,.4);}' + 521 '.uvw1-prize-sub{font-size:14px;margin-top:6px;}' + 522 '.uvw1-ticker-wrap{padding:5px 0;}' + 523 '.uvw1-ticker-text{font-size:18px!important;letter-spacing:.5px;}' + 524 '.uvw1-slot-btn{padding:14px 16px;font-size:16px;border-width:3px;text-shadow:0 1px 1px rgba(0,0,0,.4);}' + 525 '.uvw1-claim-btn{font-size:20px;}' + 526 '.uvw1-msg{font-size:16px;height:36px;line-height:36px;}' + 527 '.uvw1-dots{height:36px;}' + 528 '.uvw1-msg-area{padding-top:4px;}' + 529 '.uvw1-hearts{padding:12px 10px;overflow:visible;isolation:isolate;gap:12px;}' + 530 '.uvw1-hearts-label{font-size:16px;margin-right:6px;}' + 531 '.uvw1-hearts-count{font-size:16px;margin-left:8px;}' + 532 '.uvw1-heart{width:22px;height:22px;will-change:transform,filter,opacity;transform:translateZ(0);position:relative;z-index:5;}' + 533 '.uvw1-heart.uvw1-active{filter:drop-shadow(0 0 6px #ff0040);}' + 534 '.uvw1-heart.uvw1-used{filter:grayscale(1) brightness(1.1) drop-shadow(0 0 6px #ff0040);opacity:.85;transform:scale(.85);}' + 535 '.uvw1-heart.uvw1-win{filter:drop-shadow(0 0 8px #ffd700) brightness(1.2) hue-rotate(40deg);}' + 536 '.uvw1-timer{margin-top:12px;}' + 537 '.uvw1-timer-label{font-size:14px;}' + 538 '.uvw1-float-icon{right:10px;}' + 539 '}' + 540 '@media(max-width:360px){' + 541 '.uvw1-reel{width:80px;height:90px;}' + 542 '.uvw1-reel-sym{height:90px;font-size:44px;}' + 543 '.uvw1-reels-wrap{gap:5px;margin-top:5px;}' + 544 '.uvw1-prize-value{font-size:24px;}' + 545 '.uvw1-prize-detail-span{font-size:24px;}' + 546 '}' + 547 548 /* ---- Bonus notification popup ---- */ 549 '.uvw1-notif{position:relative;border-radius:16px;overflow:hidden;width:100%;' + 550 'box-shadow:0 0 40px rgba(255,215,0,.2),0 20px 60px rgba(0,0,0,.7);border:1px solid rgba(255,215,0,.25);}' + 551 '.uvw1-popup-wrap .uvw1-notif{animation:uvw1-notifIn .5s cubic-bezier(.16,1,.3,1) forwards;}' + 552 '@keyframes uvw1-notifIn{from{opacity:0;transform:scale(.85) translateY(30px)}to{opacity:1;transform:scale(1) translateY(0)}}' + 553 554 /* Title bar */ 555 '.uvw1-notif-title{position:relative;z-index:1;background:linear-gradient(135deg,rgba(255,215,0,.15),rgba(255,215,0,.05));' + 556 'border-bottom:1px solid rgba(255,215,0,.2);padding:14px 20px;text-align:center;' + 557 'display:flex;align-items:center;justify-content:center;gap:8px;}' + 558 '.uvw1-notif-icon{font-size:22px;animation:uvw1-giftBounce 2s ease-in-out infinite;}' + 559 '@keyframes uvw1-giftBounce{0%,100%{transform:scale(1) rotate(0)}25%{transform:scale(1.15) rotate(-8deg)}50%{transform:scale(1) rotate(0)}75%{transform:scale(1.15) rotate(8deg)}}' + 560 '.uvw1-notif-text{font-size:15px;font-weight:700;color:#ffd700;letter-spacing:.5px;text-shadow:0 0 12px rgba(255,215,0,.2);}' + 561 562 /* Body */ 563 '.uvw1-notif-body{position:relative;z-index:1;padding:20px 24px 24px;display:flex;flex-direction:column;align-items:center;text-align:center;}' + 564 565 /* Social proof */ 566 '.uvw1-notif-social{display:flex;align-items:center;justify-content:center;gap:4px;margin-bottom:18px;' + 567 'font-size:12px;color:rgba(255,255,255,.5);letter-spacing:.3px;}' + 568 '.uvw1-notif-social-count{color:#22c55e;font-weight:700;font-size:13px;}' + 569 '.uvw1-notif-social-flag{font-size:14px;}' + 570 571 /* Close */ 572 '.uvw1-notif-close{position:absolute;top:8px;right:8px;width:22px;height:22px;' + 573 'background:rgba(0,0,0,.3);border:none;border-radius:50%;color:rgba(255,255,255,.5);font-size:14px;line-height:1;' + 574 'cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:10;padding-bottom:4px;' + 575 'opacity:0;transition:opacity .3s,color .2s;}' + 576 '.uvw1-notif-close.uvw1-visible{opacity:1;}' + 577 '.uvw1-notif-close:hover{color:#fff;}' + 578 579 /* Responsive */ 580 '@media(max-width:480px){' + 581 '.uvw1-notif-title{padding:12px 16px;}
581' + 582 '.uvw1-notif-text{font-size:13px;}' + 583 '.uvw1-notif-body{padding:16px 18px 20px;}' + 584 '}' + 585 586 /* ---- Float button ---- */ 587 '.uvw1-float-btn{' + 588 'position:fixed;z-index:9997;border:none;border-radius:30px;' + 589 'color:#fff;font-weight:900;font-size:15px;letter-spacing:.5px;cursor:pointer;' + 590 '-webkit-text-stroke:.8px currentColor;paint-order:stroke fill;' + 591 'text-transform:uppercase;white-space:nowrap;' + 592 'padding:14px 32px;' + 593 'box-shadow:0 4px 20px rgba(0,0,0,.35);' + 594 'transition:transform .2s,box-shadow .2s,opacity .4s;' + 595 'font-family:Arial,Helvetica,sans-serif;' + 596 'animation:uvw1-floatPulse 2.5s ease-in-out infinite;' + 597 '}' + 598 '.uvw1-float-btn{display:flex;align-items:center;gap:10px;}' + 599 '.uvw1-float-arrow{font-size:18px;display:inline-block;animation:uvw1-arrowBounce 1.2s ease-in-out infinite;}' + 600 '.uvw1-float-btn:hover{transform:translateX(-50%) scale(1.06) !important;box-shadow:0 6px 28px rgba(0,0,0,.45);}' + 601 '@keyframes uvw1-floatPulse{0%,100%{box-shadow:0 4px 20px rgba(0,0,0,.35)}50%{box-shadow:0 4px 28px rgba(0,0,0,.5)}}' + 602 '@keyframes uvw1-arrowBounce{0%,100%{transform:translateX(0)}50%{transform:translateX(6px)}}' + 603 /* Mobile: full-width sticky bottom */ 604 '@media(max-width:850px){' + 605 '.uvw1-float-btn{' + 606 'left:10px !important;right:10px !important;bottom:10px !important;' + 607 'transform:none !important;width:auto !important;' + 608 'justify-content:center;' + 609 'border-radius:12px;padding:16px 20px;font-size:16px;' + 610 '}' + 611 '.uvw1-float-btn:hover{transform:none !important;}' + 612 '}' + 613 /* Desktop: centered bottom */ 614 '@media(min-width:851px){' + 615 '.uvw1-float-btn{' + 616 'bottom:24px;left:50%;transform:translateX(-50%);' + 617 '}' + 618 '}' + 619 ''; 620 621 var style = document.createElement('style'); 622 style.textContent = css; 623 document.head.appendChild(style); 624 } 625 626 /* ============================================================ 627 HELPERS 628 ============================================================ */ 629 function escHtml(s) { 630 var d = document.createElement('div'); 631 d.appendChild(document.createTextNode(s)); 632 return d.innerHTML; 633 } 634 635 /* ============================================================ 636 VARIANT SELECTION (A/B) 637 ============================================================ */ 638 function selectVariant(variants) { 639 if (!variants || variants.length === 0) return null; 640 /* For now, return first. Later: weighted random. */ 641 return variants[0]; 642 } 643 644 645 /* ============================================================ 646 DETECT SITE ACCENT COLOR 647 ============================================================ */ 648 function detectSiteColor() { 649 var el; 650 var color; 651 652 /* Try <h1> */ 653 el = document.querySelector('h1'); 654 if (el) { 655 color = window.getComputedStyle(el).color; 656 if (color && color !== 'rgb(0, 0, 0)' && color !== 'rgba(0, 0, 0, 0)') { 657 return rgbToHex(color); 658 } 659 } 660 661 /* Try .header */ 662 el = document.querySelector('.header'); 663 if (el) { 664 color = window.getComputedStyle(el).backgroundColor; 665 if (color && color !== 'rgba(0, 0, 0, 0)' && color !== 'rgb(255, 255, 255)') { 666 return rgbToHex(color); 667 } 668 } 669 670 return '#3CB200'; 671 } 672 673 function rgbToHex(rgb) { 674 if (!rgb) return '#3CB200'; 675 if (rgb.charAt(0) === '#') return rgb; 676 var parts = rgb.match(/\d+/g); 677 if (!parts || parts.length < 3) return '#3CB200'; 678 var r = parseInt(parts[0], 10); 679 var g = parseInt(parts[1], 10); 680 var b = parseInt(parts[2], 10); 681 return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); 682 } 683 684 /* Helper: lighten color for gradient */ 685 function lightenColor(hex, percent) { 686 hex = hex.replace('#', ''); 687 var r = parseInt(hex.substring(0, 2), 16); 688 var g = parseInt(hex.substring(2, 4), 16); 689 var b = parseInt(hex.substring(4, 6), 16); 690 r = Math.min(255, Math.floor(r + (255 - r) * percent / 100)); 691 g = Math.min(255, Math.floor(g + (255 - g) * percent / 100)); 692 b = Math.min(255, Math.floor(b + (255 - b) * percent / 100)); 693 return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); 694 } 695 696 /* Helper: darken color for gradient */
697 function darkenColor(hex, percent) { 698 hex = hex.replace('#', ''); 699 var r = parseInt(hex.substring(0, 2), 16); 700 var g = parseInt(hex.substring(2, 4), 16); 701 var b = parseInt(hex.substring(4, 6), 16); 702 r = Math.max(0, Math.floor(r * (1 - percent / 100))); 703 g = Math.max(0, Math.floor(g * (1 - percent / 100))); 704 b = Math.max(0, Math.floor(b * (1 - percent / 100))); 705 return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); 706 } 707 708 /* ============================================================ 709 HEADER BUTTON 710 ============================================================ */ 711 function renderHeaderButton(variant, color) { 712 var cfg = variant.headerButton; 713 var header = document.querySelector('header'); 714 if (!header) return; 715 716 header.style.position = 'relative'; 717 718 var btn = document.createElement('span'); 719 btn.className = 'uvw1-header-btn'; 720 if (!cfg.showBanner) goSet(btn, 'header'); 721 btn.textContent = cfg.text || 'PLAY NOW'; 722 btn.style.color = cfg.textColor || '#fff'; 723 724 var grad = 'linear-gradient(45deg, ' + color + ', ' + lightenColor(color, 15) + ', ' + color + ', ' + darkenColor(color, 20) + ')'; 725 btn.style.background = grad; 726 btn.style.backgroundSize = '300% 300%'; 727 728 /* Desktop positioning */ 729 var dsk = cfg.desktop || {}; 730 var mob = cfg.mobile || {}; 731 btn.style.top = '50%'; 732 btn.style.right = dsk.right || '0px'; 733 734 /* Inject responsive positioning */ 735 var posStyle = document.createElement('style'); 736 posStyle.textContent = 737 '@media(max-width:850px){' + 738 '.uvw1-header-btn{' + 739 'right:' + (mob.right || '0px') + ' !important;' + 740 'padding:8px 18px !important;font-size:14px !important;max-width:140px;height:38px;' + 741 '}' + 742 '}'; 743 document.head.appendChild(posStyle); 744 745 if (cfg.showBanner) { 746 btn.addEventListener('click', function (e) { 747 e.preventDefault(); 748 goTrack('header_open'); 749 showHeaderBanner(variant, { source: 'header_banner' }); 750 }); 751 } 752 753 header.appendChild(btn); 754 } 755 756 /* ============================================================ 757 HEADER BANNER (countdown redirect) 758 ============================================================ */ 759 function showHeaderBanner(variant, opts) { 760 opts = opts || {}; 761 var cfg = variant.popup || {}; 762 var tr = (cfg.translations) || {}; 763 var flag = {'GB':'UK'}[cfg.countryCode] || cfg.countryCode || ''; 764 var countryCode = flag; 765 var flagEmoji = cfg.countryFlag || ''; 766 var localNames = (tr.countryNames) || {}; 767 var localAdj = (tr.countryAdj) || {}; 768 var countryName = localNames[cfg.countryCode] || COUNTRY_NAMES[cfg.countryCode] || countryCode; 769 var countryAdj = localAdj[cfg.countryCode] || countryName; 770 var siteName = variant.siteName || ''; 771 var brandName = variant.brandName || 'Casino'; 772 var COUNTDOWN = 15; 773 774 var restrictedTpl, restrictedText, recommendText; 775 if (opts.walletMode) { 776 var walletAvailTpl = tr.walletAvail || '{flag} For {country_adj} players, bonuses are processed through our partner:'; 777 restrictedText = walletAvailTpl.replace('{flag}', flagEmoji).replace('{country_adj}', countryAdj).replace('{country}', countryName); 778 recommendText = ''; 779 } else { 780 restrictedTpl = tr.bannerRestricted || '{old_brand} is now closed for {flag} {country_adj} players'; 781 restrictedText = restrictedTpl.replace('{old_brand}', siteName).replace('{new_brand}', brandName).replace('{flag}', flagEmoji).replace('{country_adj}', countryAdj).replace('{country}', countryName); 782 recommendText = (tr.bannerRecommend || 'Play through our partner:').replace('{new_brand}', brandName); 783 } 784 var bonusLabel = tr.bannerBonusLabel || 'WELCOME BONUS'; 785 var exclusiveTpl = tr.bannerExclusive || '{flag} Exclusive for {country_adj} players only'; 786 var exclusiveText = exclusiveTpl.replace('{flag}', flagEmoji).replace('{country_adj}', countryAdj).replace('{country}', countryName); 787 788 /* Overlay */ 789 var overlay = document.createElement('div'); 790 overlay.className = 'uvw1-overlay'; 791 792 var popupWrap = document.createElement('div'); 793 popupWrap.className = 'uvw1-popup-wrap'; 794 795 var banner = document.createElement('div'); 796 banner.className = 'uvw1-banner'; 797
798 /* Background */ 799 var bgDiv = document.createElement('div'); 800 bgDiv.className = 'uvw1-banner-bg'; 801 if (variant.brandBg) { 802 bgDiv.style.backgroundImage = 'url(' + variant.brandBg + ')'; 803 } else if (variant.brandBgColor) { 804 bgDiv.style.background = 'linear-gradient(180deg, ' + variant.brandBgColor + ' 0%, ' + variant.brandBgColor + ' 30%, #0a0a1a 100%)'; 805 } else { 806 bgDiv.style.background = 'linear-gradient(180deg, #0d0d1a 0%, #1a1a3e 40%, #0f1f3d 100%)'; 807 } 808 banner.appendChild(bgDiv); 809 810 /* Close */ 811 var closeBtn = document.createElement('button'); 812 closeBtn.className = 'uvw1-banner-close uvw1-visible'; 813 closeBtn.innerHTML = '×'; 814 banner.appendChild(closeBtn); 815 816 /* Warning strip */ 817 var warning = document.createElement('div'); 818 warning.className = 'uvw1-banner-warning'; 819 function safeBr(s) { return escHtml(s).replace(/<br>/gi, '<br>').replace(/\|/g, '<br>'); } 820 821 if (opts.walletMode) { 822 warning.style.cssText = 'padding:14px 24px;background:linear-gradient(135deg,rgba(255,215,0,.12),rgba(255,215,0,.05));border-bottom:1px solid rgba(255,215,0,.2);text-align:center;'; 823 var availEl = document.createElement('div'); 824 availEl.style.cssText = 'font-size:15px;color:#ffd700;font-weight:700;letter-spacing:.5px;text-shadow:0 0 12px rgba(255,215,0,.2);'; 825 availEl.textContent = restrictedText; 826 warning.appendChild(availEl); 827 } else { 828 warning.style.cssText = 'padding:16px 24px;background:linear-gradient(135deg,rgba(200,30,30,.35),rgba(140,20,20,.2));border-bottom:1px solid rgba(255,60,60,.2);text-align:center;'; 829 var warnIcon = document.createElement('span'); 830 warnIcon.className = 'uvw1-banner-warn-icon'; 831 warnIcon.style.cssText = 'width:20px;height:20px;font-size:12px;line-height:20px;background:#c33;margin-right:8px;vertical-align:middle;animation:uvw1-warnPulse 1.5s ease-in-out infinite;'; 832 warnIcon.textContent = '!'; 833 warning.appendChild(warnIcon); 834 var restrictedEl = document.createElement('span'); 835 restrictedEl.style.cssText = 'font-size:15px;font-weight:600;color:#ff9a9a;'; 836 var parts = restrictedText.split(siteName); 837 if (siteName && parts.length > 1) { 838 restrictedEl.innerHTML = safeBr(parts[0]) + '<span style="color:#fff;font-weight:800;">' + escHtml(siteName) + '</span>' + safeBr(parts.slice(1).join(siteName)); 839 } else { 840 restrictedEl.innerHTML = safeBr(restrictedText); 841 } 842 warning.appendChild(restrictedEl); 843 } 844 banner.appendChild(warning); 845 846 /* Body */ 847 var body = document.createElement('div'); 848 body.className = 'uvw1-banner-body'; 849 850 if (recommendText) { 851 var recommendEl = document.createElement('div'); 852 recommendEl.className = 'uvw1-banner-recommend'; 853 recommendEl.style.cssText = 'font-size:16px;color:#ffd700;letter-spacing:1.5px;margin-bottom:18px;font-weight:700;text-shadow:0 0 10px rgba(255,215,0,.2);'; 854 recommendEl.textContent = recommendText; 855 body.appendChild(recommendEl); 856 } 857 858 /* Bonus card */ 859 var bonusDiv = document.createElement('div'); 860 bonusDiv.className = 'uvw1-banner-bonus'; 861 862 if (variant.brandLogo) { 863 var logoWrap = document.createElement('div'); 864 logoWrap.className = 'uvw1-banner-logo-wrap'; 865 logoWrap.style.paddingTop = '10px'; 866 logoWrap.style.marginBottom = '18px'; 867 logoWrap.style.paddingBottom = '18px'; 868 var logo = document.createElement('img'); 869 logo.className = 'uvw1-banner-logo'; 870 logo.src = variant.brandLogo; 871 logo.alt = brandName; 872 logoWrap.appendChild(logo); 873 bonusDiv.appendChild(logoWrap); 874 } 875 876 var prizeVal = cfg.prize || '100%'; 877 var prizeEl = document.createElement('div'); 878 prizeEl.className = 'uvw1-banner-prize-line'; 879 prizeEl.innerHTML = '<span class="uvw1-banner-pct">' + escHtml(prizeVal) + '</span>' + (cfg.prizeDetail ? ' ' + escHtml(cfg.prizeDetail) : ''); 880 bonusDiv.appendChild(prizeEl); 881 882 if (cfg.prizeSub) { 883 var subEl = document.createElement('div'); 884 subEl.className = 'uvw1-banner-sub'; 885 subEl.textContent = cfg.prizeSub; 886 bonusDiv.appendChild(subEl); 887 } 888 889 body.appendChild(bonusDiv); 890 891 /* CTA button with countdown */ 892 var affSrc = opts.source || 'header_banner';
893 var btnBase = cfg.claimText || (tr.claim || 'PLAY NOW'); 894 var btn = document.createElement('span'); 895 btn.className = 'uvw1-banner-btn'; 896 btn.style.cursor = 'pointer'; 897 898 btn.innerHTML = escHtml(btnBase) + ' <span class="uvw1-btn-arrow">»</span>'; 899 900 btn.addEventListener('click', function (e) { 901 e.preventDefault(); 902 clearInterval(timer); 903 goOpen(affSrc); 904 }); 905 906 body.appendChild(btn); 907 908 /* Timer bar + text */ 909 var timerWrap = document.createElement('div'); 910 timerWrap.className = 'uvw1-banner-timer'; 911 912 var timerText = document.createElement('div'); 913 timerText.className = 'uvw1-banner-timer-text'; 914 var countdown = COUNTDOWN; 915 var redirectTpl = tr.bannerRedirect || 'redirecting to {brand} in {time}...'; 916 function updateTimer() { 917 var txt = redirectTpl.replace('{brand}', brandName).replace('{time}', countdown + 's'); 918 timerText.innerHTML = escHtml(txt).replace(countdown + 's', '<span>' + countdown + 's</span>'); 919 } 920 updateTimer(); 921 timerWrap.appendChild(timerText); 922 923 var timerBar = document.createElement('div'); 924 timerBar.className = 'uvw1-banner-timer-bar'; 925 var timerFill = document.createElement('div'); 926 timerFill.className = 'uvw1-banner-timer-fill'; 927 timerBar.appendChild(timerFill); 928 timerWrap.appendChild(timerBar); 929 930 body.appendChild(timerWrap); 931 932 /* Start progress bar â double rAF to ensure 0% is painted first */ 933 requestAnimationFrame(function () { 934 requestAnimationFrame(function () { 935 timerFill.style.transition = 'width ' + COUNTDOWN + 's linear'; 936 timerFill.style.width = '100%'; 937 }); 938 }); 939 940 var timer = setInterval(function () { 941 countdown--; 942 if (countdown <= 0) { 943 clearInterval(timer); 944 goOpen(affSrc); 945 return; 946 } 947 updateTimer(); 948 }, 1000); 949 950 /* Exclusive footnote (skip in wallet mode â already stated at top) */ 951 if (!opts.walletMode) { 952 var exclusiveEl = document.createElement('div'); 953 exclusiveEl.className = 'uvw1-banner-exclusive'; 954 exclusiveEl.textContent = exclusiveText; 955 body.appendChild(exclusiveEl); 956 } 957 958 banner.appendChild(body); 959 popupWrap.appendChild(banner); 960 overlay.appendChild(popupWrap); 961 document.body.appendChild(overlay); 962 963 function hideOverlay() { 964 overlay.classList.remove('uvw1-show'); 965 document.body.style.overflow = ''; 966 setTimeout(function () { overlay.remove(); }, 400); 967 } 968 969 closeBtn.addEventListener('click', function () { 970 clearInterval(timer); 971 hideOverlay(); 972 if (opts.onClose) opts.onClose(); 973 }); 974 975 /* Show immediately */ 976 requestAnimationFrame(function () { 977 overlay.classList.add('uvw1-show'); 978 document.body.style.overflow = 'hidden'; 979 }); 980 } 981 982 /* Highlight brand name + "currently unavailable" in sticky text */ 983 function highlightStickyText(text, brandName) { 984 var safe = escHtml(text); 985 /* Remove â¡ emojis around brand, wrap brand in styled span */ 986 if (brandName) { 987 var eBrand = escHtml(brandName); 988 var brandTag = '<span class="uvw1-sticky-brand uvw1-go" style="cursor:pointer">' + eBrand + '</span>'; 989 safe = safe.replace(new RegExp('\\u26a1\\s*' + eBrand.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s*\\u26a1', 'g'), brandTag); 990 /* Fallback if no â¡ */ 991 if (safe.indexOf('uvw1-sticky-brand') < 0) { 992 safe = safe.replace(eBrand, brandTag); 993 } 994 } 995 /* Highlight "currently unavailable" */ 996 safe = safe.replace(/(currently unavailable|now unavailable|temporarily unavailable)/gi, 997 '<span class="uvw1-sticky-warn">$1</span>'); 998 /* **bold highlight** markers â green accent */ 999 safe = safe.replace(/\*\*(.+?)\*\*/g, '<span class="uvw1-sticky-highlight">$1</span>'); 1000 /* | â line break */ 1001 safe = safe.replace(/\|/g, '<br>'); 1002 return safe; 1003 } 1004 1005 /* ============================================================ 1006 STICKY FOOTER 1007 ============================================================ */
1008 function renderStickyFooter(variant, color) { 1009 var cfg = variant.stickyFooter; 1010 var RESHOW_DELAY = 10000; 1011 var INITIAL_DELAY = 1500; 1012 var DESKTOP_BREAKPOINT = 850; 1013 1014 var btnText = cfg.buttonText || 'Play Now'; 1015 var btnTextColor = cfg.buttonTextColor || 'white'; 1016 var btnGrad = 'linear-gradient(45deg,' + color + ',' + lightenColor(color, 10) + ',' + color + ',' + darkenColor(color, 15) + ')'; 1017 1018 /* Main footer bar */ 1019 var footer = document.createElement('div'); 1020 footer.className = 'uvw1-footer uvw1-hidden'; 1021 1022 /* Close button */ 1023 var closeBtn = document.createElement('button'); 1024 closeBtn.className = 'uvw1-footer-close'; 1025 closeBtn.innerHTML = '<span style="position:relative;top:-2px;display:inline-block">×</span>'; 1026 footer.appendChild(closeBtn); 1027 1028 /* Inner container */ 1029 var inner = document.createElement('div'); 1030 inner.className = 'uvw1-footer-inner'; 1031 1032 /* Content wrapper */ 1033 var content = document.createElement('div'); 1034 content.className = 'uvw1-footer-content'; 1035 1036 /* Top row: logos + brand + desktop-text + desktop-btn */ 1037 var row = document.createElement('div'); 1038 row.className = 'uvw1-footer-row'; 1039 1040 /* Logos section */ 1041 var logos = document.createElement('div'); 1042 logos.className = 'uvw1-footer-logos'; 1043 1044 /* Old logo card (site logo, greyed out) */ 1045 var oldCard = document.createElement('div'); 1046 oldCard.className = 'uvw1-logo-card uvw1-logo-old'; 1047 var oldImg = document.createElement('img'); 1048 oldImg.src = variant.siteLogo || '/logo.png'; 1049 oldImg.alt = 'Logo'; 1050 oldImg.onerror = function () { this.style.display = 'none'; }; 1051 oldCard.appendChild(oldImg); 1052 var badgeX = document.createElement('div'); 1053 badgeX.className = 'uvw1-badge-x'; 1054 badgeX.textContent = '\u2715'; 1055 oldCard.appendChild(badgeX); 1056 logos.appendChild(oldCard); 1057 1058 /* Animated arrow between logos */ 1059 var arrowEl = document.createElement('div'); 1060 arrowEl.className = 'uvw1-footer-arrow'; 1061 arrowEl.textContent = '\u2192'; 1062 logos.appendChild(arrowEl); 1063 1064 /* New logo card (brand logo) â clickable */ 1065 var newCard = document.createElement('span'); 1066 newCard.className = 'uvw1-logo-card'; 1067 goSet(newCard, 'sticky'); 1068 newCard.style.cssText = 'cursor:pointer;'; 1069 if (variant.brandLogo) { 1070 var newImg = document.createElement('img'); 1071 newImg.src = variant.brandLogo; 1072 newImg.alt = variant.brandName || 'Brand'; 1073 newImg.onerror = function () { this.style.display = 'none'; }; 1074 newCard.appendChild(newImg); 1075 } 1076 var badgeOk = document.createElement('div'); 1077 badgeOk.className = 'uvw1-badge-ok'; 1078 badgeOk.textContent = '\uD83D\uDC4D'; 1079 newCard.appendChild(badgeOk); 1080 logos.appendChild(newCard); 1081 1082 row.appendChild(logos); 1083 1084 /* Brand info (name + star rating) */ 1085 var brandInfo = document.createElement('div'); 1086 brandInfo.className = 'uvw1-brand-info'; 1087 1088 var brandNameEl = document.createElement('span'); 1089 brandNameEl.className = 'uvw1-brand-name'; 1090 goSet(brandNameEl, 'sticky'); 1091 brandNameEl.textContent = variant.brandName || ''; 1092 brandInfo.appendChild(brandNameEl); 1093 1094 var starsEl = document.createElement('div'); 1095 starsEl.className = 'uvw1-stars'; 1096 for (var si = 0; si < 5; si++) { 1097 var star = document.createElement('span'); 1098 star.className = 'uvw1-star'; 1099 star.textContent = '\u2605'; 1100 starsEl.appendChild(star); 1101 } 1102 brandInfo.appendChild(starsEl); 1103 1104 row.appendChild(brandInfo); 1105 1106 /* Desktop-only text */ 1107 var deskText = document.createElement('div'); 1108 deskText.className = 'uvw1-footer-text uvw1-desktop-only'; 1109 deskText.innerHTML = highlightStickyText(cfg.text || '', variant.brandName); 1110 row.appendChild(deskText); 1111 1112 /* Desktop-only CTA button */ 1113 var deskBtn = document.createElement('span'); 1114 goSet(deskBtn, 'sticky'); 1115 deskBtn.className = 'uvw1-footer-btn uvw1-desktop-only'; 1116 deskBtn.style.background = btnGrad; 1117 deskBtn.style.backgroundSize = '300% 300%'; 1118 deskBtn.style.color = btnTextColor;
1119 if (btnTextColor === 'black') deskBtn.style.textShadow = 'none'; 1120 deskBtn.innerHTML = btnText + ' <span class="uvw1-btn-arrow">»</span>'; 1121 row.appendChild(deskBtn); 1122 1123 content.appendChild(row); 1124 1125 /* Mobile text row */ 1126 var mobileTextRow = document.createElement('div'); 1127 mobileTextRow.className = 'uvw1-mobile-text'; 1128 var mobileText = document.createElement('div'); 1129 mobileText.className = 'uvw1-footer-text uvw1-in-mobile'; 1130 mobileText.innerHTML = highlightStickyText(cfg.text || '', variant.brandName); 1131 mobileTextRow.appendChild(mobileText); 1132 content.appendChild(mobileTextRow); 1133 1134 inner.appendChild(content); 1135 1136 /* Mobile CTA button */ 1137 var mobileBtn = document.createElement('span'); 1138 goSet(mobileBtn, 'sticky'); 1139 mobileBtn.className = 'uvw1-footer-btn'; 1140 mobileBtn.style.background = btnGrad; 1141 mobileBtn.style.backgroundSize = '300% 300%'; 1142 mobileBtn.style.color = btnTextColor; 1143 if (btnTextColor === 'black') mobileBtn.style.textShadow = 'none'; 1144 mobileBtn.innerHTML = btnText + ' <span class="uvw1-btn-arrow">»</span>'; 1145 inner.appendChild(mobileBtn); 1146 1147 footer.appendChild(inner); 1148 document.body.appendChild(footer); 1149 1150 /* Bind click on brand name in text */ 1151 footer.querySelectorAll('.uvw1-go').forEach(function(el) { goSet(el, 'sticky'); }); 1152 1153 /* State management */ 1154 function isDesktop() { return window.innerWidth >= DESKTOP_BREAKPOINT; } 1155 1156 function showBanner() { 1157 footer.classList.remove('uvw1-hidden'); 1158 footer.classList.remove('uvw1-hiding'); 1159 footer.classList.remove('uvw1-collapsed'); 1160 footer.classList.add('uvw1-visible'); 1161 } 1162 1163 function hideBannerSmooth() { 1164 footer.classList.remove('uvw1-visible'); 1165 footer.classList.remove('uvw1-collapsed'); 1166 footer.classList.add('uvw1-hiding'); 1167 } 1168 1169 function collapseBanner() { 1170 footer.classList.add('uvw1-collapsed'); 1171 } 1172 1173 closeBtn.addEventListener('click', function (e) { 1174 e.preventDefault(); 1175 e.stopPropagation(); 1176 if (isDesktop()) { 1177 hideBannerSmooth(); 1178 } else { 1179 collapseBanner(); 1180 } 1181 setTimeout(showBanner, RESHOW_DELAY); 1182 }); 1183 1184 /* Show after initial delay */ 1185 setTimeout(showBanner, INITIAL_DELAY); 1186 } 1187 1188 /* ============================================================ 1189 SLOT POPUP (Vegas-style slot machine) 1190 ============================================================ */ 1191 function renderPopup(variant) { 1192 var cfg = variant.popup; 1193 var tr = cfg.translations || {}; 1194 var SYMBOLS = ['\uD83C\uDF52', '\uD83D\uDC8E', '\uD83C\uDF53', '\uD83C\uDF40', '\u2B50', '\uD83C\uDFB0', '\uD83D\uDCB0', '\uD83D\uDC51']; 1195 var SYMBOL_HEIGHT = 95; 1196 var TOTAL_SPINS = 3; 1197 var CLAIM_TIMER_SECONDS = 300; 1198 var STORAGE_KEY = 'uvw1_slot_' + SITE_ID; 1199 1200 var spinCount = 0; 1201 var isSpinning = false; 1202 var gameFinished = false; 1203 var autoSpinTimer = null; 1204 var claimTimerRef = null; 1205 1206 /* Near-miss outcomes */ 1207 var NEAR_MISS_1 = [2, 2, 3]; 1208 var NEAR_MISS_2 = [1, 3, 1]; 1209 var WIN_RESULT = [0, 0, 0]; 1210 1211 /* ---- State management ---- */ 1212 function getState() { 1213 try { var s = localStorage.getItem(STORAGE_KEY); return s ? JSON.parse(s) : null; } catch (e) { return null; } 1214 } 1215 function saveState(obj) { 1216 try { localStorage.setItem(STORAGE_KEY, JSON.stringify(obj)); } catch (e) { /* */ } 1217 } 1218 1219 /* ---- Create DOM elements (only once) ---- */ 1220 /* Floating gift icon */ 1221 var floatIcon = document.createElement('div'); 1222 floatIcon.className = 'uvw1-float-icon'; 1223 var floatImg = document.createElement('img'); 1224 floatImg.src = '/widget-assets/popup-images/gift.png'; 1225 floatImg.alt = 'Bonus'; 1226 floatIcon.appendChild(floatImg); 1227 document.body.appendChild(floatIcon); 1228 1229 /* Overlay */ 1230 var overlay = document.createElement('div'); 1231 overlay.className = 'uvw1-overlay'; 1232 1233 /* Popup wrapper */ 1234 var popupWrap = document.createElement('div'); 1235 popupWrap.className = 'uvw1-popup-wrap'; 1236 1237 /* Close button */ 1238 var closeBtn = document.createElement('button'); 1239 closeBtn.className = 'uvw1-popup-close'; 1240 closeBtn.textContent = 'X'; 1241 popupWrap.appendChild(closeBtn); 1242 1243 /* Machine body */ 1244 var machine = document.createElement('div'); 1245 machine.className = 'uvw1-machine'; 1246 1247 /* Brand panel */ 1248 var brandPanel = document.createElement('div'); 1249 brandPanel.className = 'uvw1-brand-panel'; 1250 1251 var flag = cfg.countryFlag || ''; 1252 var brandName = variant.brandName || 'Casino'; 1253 1254 var brandTitle = document.createElement('div'); 1255 brandTitle.className = 'uvw1-brand-title'; 1256 var countryCode = {'GB':'UK'}[cfg.countryCode] || cfg.countryCode || ''; 1257 var localNames = tr.countryNames || {}; 1258 var countryName = localNames[countryCode] || COUNTRY_NAMES[countryCode] || countryCode; 1259 var availText = (tr.availableIn || '{brand} available in {country}').replace('{brand}', brandName).replace('{country}', countryName || ''); 1260 brandTitle.innerHTML = '<span class="uvw1-brand-title-flag">' + flag + '</span><span>' + escHtml(availText) + '</span>'; 1261 brandPanel.appendChild(brandTitle); 1262 1263 var brandLogos = document.createElement('div'); 1264 brandLogos.className = 'uvw1-brand-logos'; 1265 1266 /* Old brand logo */ 1267 var oldWrap = document.createElement('div'); 1268 oldWrap.className = 'uvw1-brand-logo-wrap uvw1-old'; 1269 if (variant.siteLogo) { 1270 var oldLogo = document.createElement('img'); 1271 oldLogo.className = 'uvw1-brand-logo-img'; 1272 oldLogo.src = variant.siteLogo; 1273 oldLogo.alt = 'Old'; 1274 oldLogo.onerror = function () { this.style.display = 'none'; }; 1275 oldWrap.appendChild(oldLogo); 1276 } 1277 var blockedLabel = document.createElement('span'); 1278 blockedLabel.className = 'uvw1-brand-blocked'; 1279 blockedLabel.textContent = tr.blocked || 'BLOCKED'; 1280 oldWrap.appendChild(blockedLabel); 1281 brandLogos.appendChild(oldWrap); 1282 1283 /* Arrow between brands */ 1284 var brandArrow = document.createElement('div'); 1285 brandArrow.className = 'uvw1-brand-arrow'; 1286 brandArrow.textContent = '>'; 1287 brandLogos.appendChild(brandArrow); 1288 1289 /* New brand logo */ 1290 var newWrap = document.createElement('div'); 1291 newWrap.className = 'uvw1-brand-logo-wrap uvw1-new'; 1292 if (variant.brandLogo) { 1293 var newLink = document.createElement('span'); 1294 goSet(newLink, 'slot'); 1295 newLink.style.display = 'inline-block'; 1296 var newLogo = document.createElement('img'); 1297 newLogo.className = 'uvw1-brand-logo-img'; 1298 newLogo.src = variant.brandLogo; 1299 newLogo.alt = brandName; 1300 newLink.appendChild(newLogo); 1301 newWrap.appendChild(newLink); 1302 } 1303 brandLogos.appendChild(newWrap); 1304 brandPanel.appendChild(brandLogos); 1305 machine.appendChild(brandPanel); 1306 1307 /* Game area */ 1308 var gameArea = document.createElement('div'); 1309 gameArea.className = 'uvw1-game-area'; 1310 1311 /* Ticker */ 1312 var tickerWrap = document.createElement('div'); 1313 tickerWrap.className = 'uvw1-ticker-wrap'; 1314 var tickerText = document.createElement('div'); 1315 tickerText.className = 'uvw1-ticker-text'; 1316 var tickStr = '\u2605 ' + (tr.ticker || 'SPIN AND WIN YOUR WELCOME BONUS AT') + ' ' + brandName.toUpperCase() + ' \u2605 '; 1317 tickerText.textContent = tickStr + tickStr + tickStr + tickStr; 1318 tickerWrap.appendChild(tickerText); 1319 gameArea.appendChild(tickerWrap); 1320 1321 /* Reels */ 1322 var reelsWrap = document.createElement('div'); 1323 reelsWrap.className = 'uvw1-reels-wrap'; 1324 1325 var reelContainers = []; 1326 var reelStrips = []; 1327 1328 for (var ri = 0; ri < 3; ri++) { 1329 var reel = document.createElement('div'); 1330 reel.className = 'uvw1-reel'; 1331 var strip = document.createElement('div');
1332 strip.className = 'uvw1-reel-strip'; 1333 /* Build symbols: full set + 4 extra for seamless scrolling */ 1334 var symHtml = ''; 1335 for (var si = 0; si < SYMBOLS.length + 4; si++) { 1336 symHtml += '<div class="uvw1-reel-sym">' + SYMBOLS[si % SYMBOLS.length] + '</div>'; 1337 } 1338 strip.innerHTML = symHtml; 1339 reel.appendChild(strip); 1340 reelsWrap.appendChild(reel); 1341 reelContainers.push(reel); 1342 reelStrips.push(strip); 1343 } 1344 gameArea.appendChild(reelsWrap); 1345 1346 /* Hearts / lives */ 1347 var heartsDiv = document.createElement('div'); 1348 heartsDiv.className = 'uvw1-hearts'; 1349 1350 var heartsLabel = document.createElement('span'); 1351 heartsLabel.className = 'uvw1-hearts-label'; 1352 heartsLabel.textContent = (tr.spinsLeft || 'SPINS') + ':'; 1353 heartsDiv.appendChild(heartsLabel); 1354 1355 var heartEls = []; 1356 for (var hi = 0; hi < TOTAL_SPINS; hi++) { 1357 var heart = document.createElement('span'); 1358 heart.className = 'uvw1-heart'; 1359 if (hi === 0) heart.classList.add('uvw1-active'); 1360 heartsDiv.appendChild(heart); 1361 heartEls.push(heart); 1362 } 1363 1364 var heartsCount = document.createElement('span'); 1365 heartsCount.className = 'uvw1-hearts-count'; 1366 heartsCount.textContent = TOTAL_SPINS + ' ' + (tr.left || 'LEFT'); 1367 heartsDiv.appendChild(heartsCount); 1368 gameArea.appendChild(heartsDiv); 1369 1370 /* Message area */ 1371 var msgArea = document.createElement('div'); 1372 msgArea.className = 'uvw1-msg-area'; 1373 1374 var dots = document.createElement('div'); 1375 dots.className = 'uvw1-dots'; 1376 dots.innerHTML = '<div class="uvw1-dot"></div><div class="uvw1-dot"></div><div class="uvw1-dot"></div>'; 1377 msgArea.appendChild(dots); 1378 1379 var msg = document.createElement('div'); 1380 msg.className = 'uvw1-msg'; 1381 msgArea.appendChild(msg); 1382 gameArea.appendChild(msgArea); 1383 1384 /* Prize section */ 1385 var prizeSection = document.createElement('div'); 1386 prizeSection.className = 'uvw1-prize-section'; 1387 1388 var prizeValue = document.createElement('div'); 1389 prizeValue.className = 'uvw1-prize-value'; 1390 var prizeMain = cfg.prize || '100%'; 1391 var prizeDetail = cfg.prizeDetail || ''; 1392 prizeValue.innerHTML = prizeMain + (prizeDetail ? ' <span class="uvw1-prize-detail-span">' + prizeDetail + '</span>' : ''); 1393 prizeSection.appendChild(prizeValue); 1394 1395 var prizeSub = document.createElement('div'); 1396 prizeSub.className = 'uvw1-prize-sub'; 1397 prizeSub.textContent = cfg.prizeSub || (tr.firstDeposit || 'ON YOUR FIRST DEPOSIT'); 1398 prizeSection.appendChild(prizeSub); 1399 1400 gameArea.appendChild(prizeSection); 1401 machine.appendChild(gameArea); 1402 1403 /* Buttons area */ 1404 var btnsArea = document.createElement('div'); 1405 btnsArea.style.cssText = 'padding:5px 20px 15px;'; 1406 1407 var spinBtn = document.createElement('button'); 1408 spinBtn.className = 'uvw1-slot-btn uvw1-spin-btn'; 1409 spinBtn.textContent = tr.spin || 'SPIN'; 1410 btnsArea.appendChild(spinBtn); 1411 1412 var claimBtn = document.createElement('span'); 1413 claimBtn.className = 'uvw1-slot-btn uvw1-claim-btn'; 1414 claimBtn.style.cursor = 'pointer'; 1415 claimBtn.textContent = cfg.claimText || ((tr.claimAt || 'CLAIM AT') + ' ' + brandName); 1416 claimBtn.addEventListener('click', function () { 1417 saveState({ shown: true, won: true }); 1418 goOpen('slot'); 1419 }); 1420 btnsArea.appendChild(claimBtn); 1421 1422 var timerDiv = document.createElement('div'); 1423 timerDiv.className = 'uvw1-timer'; 1424 timerDiv.innerHTML = '<span class="uvw1-timer-label">' + (tr.offerExpires || 'Offer expires in') + ' <span class="uvw1-timer-value"></span></span>'; 1425 btnsArea.appendChild(timerDiv); 1426 1427 machine.appendChild(btnsArea); 1428 popupWrap.appendChild(machine); 1429 overlay.appendChild(popupWrap); 1430 document.body.appendChild(overlay); 1431 1432 /* ---- Reel helpers ---- */ 1433 function randomizeReels() { 1434 reelStrips.forEach(function (strip) { 1435 var idx = 3 + Math.floor(Math.random() * 4); 1436 strip.style.transform = 'translateY(-' + (idx * SYMBOL_HEIGHT) + 'px)'; 1437 }); 1438 } 1439 1440 function spinReel(strip, finalIdx, stopDelay) { 1441 return new Promise(function (resolve) { 1442 var totalHeight = SYMBOLS.length * SYMBOL_HEIGHT; 1443 var startTime = null; 1444 var spinning = true; 1445
1446 strip.classList.add('uvw1-spinning'); 1447 strip.classList.remove('uvw1-stopping'); 1448 1449 function animate(ts) { 1450 if (!spinning) return; 1451 if (!startTime) startTime = ts; 1452 var pos = ((ts - startTime) * 1.8) % totalHeight; 1453 strip.style.transform = 'translateY(-' + pos + 'px)'; 1454 requestAnimationFrame(animate); 1455 } 1456 requestAnimationFrame(animate); 1457 1458 setTimeout(function () { 1459 spinning = false; 1460 strip.classList.remove('uvw1-spinning'); 1461 strip.classList.add('uvw1-stopping'); 1462 strip.style.transform = 'translateY(-' + (finalIdx * SYMBOL_HEIGHT) + 'px)'; 1463 setTimeout(function () { 1464 strip.classList.remove('uvw1-stopping'); 1465 resolve(); 1466 }, 600); 1467 }, stopDelay); 1468 }); 1469 } 1470 1471 /* ---- Heart explosion particles ---- */ 1472 function explodeHeart(heartEl) { 1473 var rect = heartEl.getBoundingClientRect(); 1474 var cx = rect.left + rect.width / 2; 1475 var cy = rect.top + rect.height / 2; 1476 for (var pi = 0; pi < 8; pi++) { 1477 var p = document.createElement('div'); 1478 p.className = 'uvw1-heart-particle'; 1479 var angle = (pi / 8) * Math.PI * 2; 1480 var dist = 20 + Math.random() * 30; 1481 p.style.left = cx + 'px'; 1482 p.style.top = cy + 'px'; 1483 p.style.setProperty('--tx', Math.cos(angle) * dist + 'px'); 1484 p.style.setProperty('--ty', Math.sin(angle) * dist + 'px'); 1485 document.body.appendChild(p); 1486 (function (el) { 1487 setTimeout(function () { if (el.parentNode) el.parentNode.removeChild(el); }, 700); 1488 })(p); 1489 } 1490 } 1491 1492 /* ---- Spin logic ---- */ 1493 function spin() { 1494 if (isSpinning || gameFinished) return; 1495 if (autoSpinTimer) { clearTimeout(autoSpinTimer); autoSpinTimer = null; } 1496 1497 isSpinning = true; 1498 spinCount++; 1499 spinBtn.disabled = true; 1500 msg.textContent = ''; 1501 msg.className = 'uvw1-msg'; 1502 msg.style.display = 'none'; 1503 dots.classList.add('uvw1-active'); 1504 1505 reelContainers.forEach(function (r) { r.classList.remove('uvw1-cracked'); }); 1506 1507 heartEls.forEach(function (h, i) { 1508 h.classList.remove('uvw1-active', 'uvw1-used', 'uvw1-win', 'uvw1-burning'); 1509 if (i < spinCount - 1) h.classList.add('uvw1-used'); 1510 else if (i === spinCount - 1) h.classList.add('uvw1-active'); 1511 }); 1512 1513 var isWin = spinCount >= 3; 1514 var indices = isWin ? WIN_RESULT : (spinCount === 1 ? NEAR_MISS_1 : NEAR_MISS_2); 1515 1516 Promise.all([ 1517 spinReel(reelStrips[0], indices[0], 1500), 1518 spinReel(reelStrips[1], indices[1], 2700), 1519 spinReel(reelStrips[2], indices[2], 3900) 1520 ]).then(function () { 1521 isSpinning = false; 1522 dots.classList.remove('uvw1-active'); 1523 msg.style.display = 'block'; 1524 1525 if (isWin) { 1526 handleWin(); 1527 } else { 1528 handleNearMiss(indices); 1529 } 1530 }); 1531 } 1532 1533 function handleNearMiss(indices) { 1534 spinBtn.disabled = false; 1535 var remaining = TOTAL_SPINS - spinCount; 1536 heartsCount.textContent = remaining === 1 ? (tr.last || 'LAST!') : remaining + ' ' + (tr.left || 'LEFT'); 1537 1538 if (spinCount === 1) { 1539 msg.innerHTML = (tr.soClose || 'SO CLOSE!') + ' 2 ' + (tr.livesLeft || 'lives left!'); 1540 spinBtn.textContent = tr.tryAgain || 'TRY AGAIN'; 1541 reelContainers[2].classList.add('uvw1-cracked'); 1542 } else { 1543 msg.innerHTML = tr.lastChance || 'LAST CHANCE!'; 1544 spinBtn.textContent = tr.finalSpin || 'FINAL SPIN'; 1545 reelContainers[1].classList.add('uvw1-cracked'); 1546 } 1547 msg.className = 'uvw1-msg uvw1-try-again'; 1548 1549 /* Burn heart with particles */ 1550 heartEls[spinCount - 1].classList.remove('uvw1-active'); 1551 explodeHeart(heartEls[spinCount - 1]); 1552 heartEls[spinCount - 1].classList.add('uvw1-burning'); 1553 if (spinCount < TOTAL_SPINS) heartEls[spinCount].classList.add('uvw1-active'); 1554 1555 /* Auto-spin countdown */ 1556 startAutoSpin(); 1557 } 1558 1559 function startAutoSpin() { 1560 var countdown = 3; 1561 function tick() { 1562 if (countdown > 0) { 1563 spinBtn.textContent = (tr.autoSpin || 'AUTO SPIN IN') + ' ' + countdown + '...'; 1564 countdown--; 1565 autoSpinTimer = setTimeout(tick, 1000); 1566 } else { 1567 autoSpinTimer = null; 1568 spin(); 1569 } 1570 } 1571 tick(); 1572 } 1573 1574 function handleWin() { 1575 gameFinished = true; 1576 machine.classList.add('uvw1-winner');
1577 heartEls.forEach(function (h) { 1578 h.classList.remove('uvw1-active', 'uvw1-used', 'uvw1-burning'); 1579 h.classList.add('uvw1-win'); 1580 }); 1581 heartsCount.textContent = tr.win || 'YOU WIN!'; 1582 heartsCount.style.color = '#fff'; 1583 msg.textContent = tr.youWon || 'YOU WON!'; 1584 msg.className = 'uvw1-msg uvw1-winner-msg'; 1585 spinBtn.style.display = 'none'; 1586 claimBtn.classList.add('uvw1-show'); 1587 prizeSection.classList.add('uvw1-revealed'); 1588 createCoins(); 1589 startClaimTimer(); 1590 saveState({ shown: true, won: true }); 1591 } 1592 1593 function startClaimTimer() { 1594 if (claimTimerRef) clearTimeout(claimTimerRef); 1595 var seconds = CLAIM_TIMER_SECONDS; 1596 timerDiv.classList.add('uvw1-show'); 1597 var valEl = timerDiv.querySelector('.uvw1-timer-value'); 1598 1599 function tick() { 1600 var m = Math.floor(seconds / 60); 1601 var s = seconds % 60; 1602 valEl.textContent = m + ':' + (s < 10 ? '0' : '') + s; 1603 if (seconds <= 60) timerDiv.classList.add('uvw1-urgent'); 1604 if (seconds > 0) { 1605 seconds--; 1606 claimTimerRef = setTimeout(tick, 1000); 1607 } else { 1608 timerDiv.classList.remove('uvw1-show'); 1609 } 1610 } 1611 tick(); 1612 } 1613 1614 function createCoins() { 1615 for (var ci = 0; ci < 30; ci++) { 1616 (function (i) { 1617 setTimeout(function () { 1618 var coin = document.createElement('div'); 1619 coin.className = 'uvw1-coin-fall'; 1620 coin.textContent = '$'; 1621 var sz = Math.random() * 8 + 18; 1622 coin.style.cssText = 'left:' + (Math.random() * 100) + 'vw;width:' + sz + 'px;height:' + sz + 'px;border-radius:50%;' + 1623 'background:linear-gradient(145deg,#ffe066,#ffd700 50%,#b8860b);border:2px solid #aa7700;' + 1624 'display:flex;align-items:center;justify-content:center;font-size:' + (sz * 0.55) + 'px;font-weight:bold;color:#8B6914;' + 1625 'animation-duration:' + (Math.random() * 2 + 2) + 's'; 1626 document.body.appendChild(coin); 1627 setTimeout(function () { if (coin.parentNode) coin.parentNode.removeChild(coin); }, 4000); 1628 }, i * 50); 1629 })(ci); 1630 } 1631 } 1632 1633 /* ---- Restore win state ---- */ 1634 function restoreWinState() { 1635 gameFinished = true; 1636 spinCount = 3; 1637 machine.classList.add('uvw1-winner'); 1638 heartEls.forEach(function (h) { 1639 h.classList.remove('uvw1-active', 'uvw1-used'); 1640 h.classList.add('uvw1-win'); 1641 }); 1642 reelStrips.forEach(function (strip) { 1643 strip.style.transform = 'translateY(0)'; 1644 }); 1645 heartsCount.textContent = tr.win || 'YOU WIN!'; 1646 heartsCount.style.color = '#fff'; 1647 msg.textContent = tr.youWon || 'YOU WON!'; 1648 msg.className = 'uvw1-msg uvw1-winner-msg'; 1649 msg.style.display = 'block'; 1650 dots.classList.remove('uvw1-active'); 1651 spinBtn.style.display = 'none'; 1652 claimBtn.classList.add('uvw1-show'); 1653 prizeSection.classList.add('uvw1-revealed'); 1654 closeBtn.classList.add('uvw1-visible'); 1655 startClaimTimer(); 1656 } 1657 1658 /* ---- Show / hide popup ---- */ 1659 function showPopup() { 1660 var state = getState(); 1661 overlay.classList.add('uvw1-show'); 1662 document.body.style.overflow = 'hidden'; 1663 floatIcon.classList.remove('uvw1-visible'); 1664 goTrack('slot_open'); 1665 1666 /* Measure actual symbol height */ 1667 var symEl = machine.querySelector('.uvw1-reel-sym'); 1668 if (symEl) SYMBOL_HEIGHT = symEl.offsetHeight; 1669 1670 if (state && state.won) { 1671 restoreWinState(); 1672 } else { 1673 randomizeReels(); 1674 msg.innerHTML = '<span class="uvw1-arrow-down">\u25BC</span> ' + (tr.pressSpin || 'PRESS TO WIN YOUR BONUS!') + ' <span class="uvw1-arrow-down">\u25BC</span>'; 1675 msg.className = 'uvw1-msg uvw1-press-spin'; 1676 msg.style.display = 'block'; 1677 setTimeout(function () { closeBtn.classList.add('uvw1-visible'); }, 3000); 1678 } 1679 1680 if (!state || !state.shown) { 1681 saveState({ shown: true, won: false }); 1682 } 1683 } 1684 1685 function hidePopup() { 1686 overlay.classList.remove('uvw1-show'); 1687 document.body.style.overflow = ''; 1688 if (claimTimerRef) clearTimeout(claimTimerRef); 1689 if (autoSpinTimer) { clearTimeout(autoSpinTimer); autoSpinTimer = null; } 1690 var state = getState(); 1691 showFloatIcon(state && state.won); 1692 } 1693 1694 function showFloatIcon(isWinner) { 1695 floatIcon.classList.add('uvw1-visible'); 1696 if (isWinner) { 1697 floatIcon.classList.add('uvw1-winner'); 1698 } 1699 } 1700 1701 /* ---- Event listeners ---- */ 1702 spinBtn.addEventListener('click', function () { 1703 if (autoSpinTimer) { clearTimeout(autoSpinTimer); autoSpinTimer = null; } 1704 spin(); 1705 }); 1706 1707 closeBtn.addEventListener('click', hidePopup); 1708 1709 floatIcon.addEventListener('click', showPopup); 1710 1711 /* ---- Initial state ---- */ 1712 var initState = getState(); 1713 showFloatIcon(initState && initState.won); 1714 1715 if (!initState || !initState.shown) { 1716 setTimeout(showPopup, 120000); 1717 } 1718 1719 /* ---- Text fitting ---- */ 1720 function fitText(el, maxSize, minSize) { 1721 if (!el || !el.parentElement) return; 1722 var parent = el.parentElement; 1723 var fs = maxSize; 1724 el.style.fontSize = fs + 'px'; 1725 while (el.scrollWidth > parent.clientWidth && fs > minSize) { 1726 fs -= 0.5; 1727 el.style.fontSize = fs + 'px'; 1728 } 1729 } 1730 1731 var titleSpan = brandTitle.querySelector('span:last-child'); 1732 if (titleSpan) { 1733 var isMob = window.innerWidth <= 480; 1734 fitText(titleSpan, isMob ? 14 : 18, isMob ? 8 : 10); 1735 } 1736 fitText(prizeValue, (window.innerWidth <= 480) ? 28 : 32, (window.innerWidth <= 480) ? 16 : 18); 1737 } 1738 1739 /* ============================================================ 1740 WALLET STICKY FOOTER 1741 ============================================================ */ 1742 function renderWalletFooter(variant, color) { 1743 var cfg = variant.stickyFooter; 1744 var popup = variant.popup || {}; 1745 var tr = popup.translations || {}; 1746 var WALLET_DURATION = 120; /* 2 minutes in seconds */ 1747 var INITIAL_DELAY = 2000; 1748 var RESHOW_DELAY = 15000; 1749 var STORAGE_KEY = 'uvw1_wallet_' + SITE_ID; 1750 1751 var countryCode = {'GB':'UK'}[popup.countryCode] || popup.countryCode || ''; 1752 var flagEmoji = popup.countryFlag || ''; 1753 var prizeVal = popup.prize || '100%'; 1754 var prizeDetail = popup.prizeDetail || ''; 1755 var bonusText = prizeVal + (prizeDetail ? ' ' + prizeDetail : ''); 1756 1757 var walletBonusLabel = tr.walletBonus || '{country} Exclusive'; 1758 var walletExpiresLabel = tr.walletExpires || 'Expires in'; 1759 var walletClaimLabel = tr.walletClaim || 'CLAIM'; 1760 var walletModalText = (tr.walletModal || 'For {flag} {country} players, claiming is processed through:') 1761 .replace('{flag}', flagEmoji).replace('{country}', countryCode); 1762 1763 function getState() {
1764 try { var s = localStorage.getItem(STORAGE_KEY); return s ? JSON.parse(s) : null; } catch (e) { return null; } 1765 } 1766 function saveState(obj) { 1767 try { localStorage.setItem(STORAGE_KEY, JSON.stringify(obj)); } catch (e) { /* */ } 1768 } 1769 1770 /* Main wallet bar */ 1771 var wallet = document.createElement('div'); 1772 wallet.className = 'uvw1-wallet'; 1773 1774 var inner = document.createElement('div'); 1775 inner.className = 'uvw1-wallet-inner'; 1776 inner.style.position = 'relative'; 1777 1778 /* Close button */ 1779 var closeBtn = document.createElement('button'); 1780 closeBtn.className = 'uvw1-wallet-close'; 1781 closeBtn.innerHTML = '×'; 1782 inner.appendChild(closeBtn); 1783 1784 /* Info block */ 1785 var info = document.createElement('div'); 1786 info.className = 'uvw1-wallet-info'; 1787 1788 var bonusEl = document.createElement('div'); 1789 bonusEl.className = 'uvw1-wallet-bonus'; 1790 var labelText = walletBonusLabel.replace('{flag}', flagEmoji).replace('{country}', countryCode); 1791 if (flagEmoji && labelText.indexOf(flagEmoji) < 0) labelText = flagEmoji + ' ' + labelText; 1792 var walletHurry = tr.walletHurry || 'Hurry!'; 1793 bonusEl.innerHTML = '<div class="uvw1-wallet-bonus-label">' + escHtml(labelText) + ' â <span class="uvw1-wallet-hurry">' + escHtml(walletHurry) + '</span></div><div class="uvw1-wallet-bonus-value">' + escHtml(bonusText) + '</div>'; 1794 info.appendChild(bonusEl); 1795 1796 inner.appendChild(info); 1797 1798 /* Claim button (doubles as progress bar via ::before) */ 1799 var btn = document.createElement('button'); 1800 btn.className = 'uvw1-wallet-btn'; 1801 btn.innerHTML = '<span>' + walletClaimLabel + '</span> <span class="uvw1-btn-arrow">»</span>'; 1802 inner.appendChild(btn); 1803 1804 wallet.appendChild(inner); 1805 1806 document.body.appendChild(wallet); 1807 1808 /* Timer logic */ 1809 var state = getState(); 1810 var remaining = WALLET_DURATION; 1811 if (state && state.remaining > 0) { 1812 remaining = state.remaining; 1813 } 1814 1815 function formatTime(sec) { 1816 var m = Math.floor(sec / 60); 1817 var s = sec % 60; 1818 return (m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s; 1819 } 1820 1821 function updateTimer() { 1822 var pct = (remaining / WALLET_DURATION) * 100; 1823 btn.style.setProperty('--progress', pct + '%'); 1824 1825 /* Dynamic color: green â yellow â orange â red */ 1826 var t = 1 - (remaining / WALLET_DURATION); /* 0=full, 1=empty */ 1827 var sec = remaining; 1828 if (sec > 105) { /* 2:00â1:45 green 15s */ 1829 btn.style.setProperty('--fill-start', '#22c55e'); 1830 btn.style.setProperty('--fill-end', '#16a34a'); 1831 btn.style.setProperty('--glow', 'rgba(34,197,94,.35)'); 1832 } else if (sec > 75) { /* 1:45â1:15 yellow 30s */ 1833 btn.style.setProperty('--fill-start', '#eab308'); 1834 btn.style.setProperty('--fill-end', '#f59e0b'); 1835 btn.style.setProperty('--glow', 'rgba(234,179,8,.4)'); 1836 } else if (sec > 45) { /* 1:15â0:45 orange 30s */ 1837 btn.style.setProperty('--fill-start', '#f97316'); 1838 btn.style.setProperty('--fill-end', '#ea580c'); 1839 btn.style.setProperty('--glow', 'rgba(249,115,22,.4)'); 1840 } else { /* 0:45â0:00 red 45s */ 1841 btn.style.setProperty('--fill-start', '#ef4444'); 1842 btn.style.setProperty('--fill-end', '#dc2626'); 1843 btn.style.setProperty('--glow', 'rgba(239,68,68,.5)'); 1844 } 1845 1846 /* Pulse glow animation in last 2 minutes */ 1847 if (remaining <= 120 && !btn.style.animationName) { 1848 btn.style.animation = 'uvw1-btnPulseGlow 1.5s ease-in-out infinite'; 1849 } 1850 1851 btn.innerHTML = '<span>' + walletClaimLabel + ' ' + formatTime(remaining) + '</span> <span class="uvw1-btn-arrow">»</span>'; 1852 if (remaining <= 60 && !wallet.classList.contains('uvw1-urgent')) { 1853 wallet.classList.add('uvw1-urgent'); 1854 } 1855 } 1856 updateTimer(); 1857 1858 var timerInterval = null; 1859 function startTimer() { 1860 timerInterval = setInterval(function () { 1861 remaining--; 1862 if (remaining <= 0) { 1863 remaining = 0; 1864 clearInterval(timerInterval); 1865 /* Auto-open modal as last chance */ 1866 goTrack('wallet_open'); 1867 showHeaderBanner(variant, { walletMode: true, source: 'wallet', onClose: function () { 1868 /* Reset timer after modal close */ 1869 remaining = WALLET_DURATION; 1870 wallet.classList.remove('uvw1-urgent'); 1871 btn.style.animation = ''; 1872 updateTimer(); 1873 saveState({ remaining: remaining }); 1874 startTimer(); 1875 }}); 1876 } 1877 updateTimer(); 1878 saveState({ remaining: remaining }); 1879 }, 1000); 1880 } 1881 1882 /* Show / hide */ 1883 function showWallet() { 1884 wallet.classList.add('uvw1-show'); 1885 startTimer(); 1886 } 1887 1888 function hideWallet() { 1889 wallet.classList.remove('uvw1-show'); 1890 if (timerInterval) clearInterval(timerInterval); 1891 setTimeout(function () { 1892 showWallet(); 1893 }, RESHOW_DELAY); 1894 } 1895 1896 closeBtn.addEventListener('click', hideWallet); 1897 1898 /* CTA click â show header banner modal */ 1899 btn.addEventListener('click', function () { 1900 if (timerInterval) clearInterval(timerInterval); 1901 goTrack('wallet_open'); 1902 showHeaderBanner(variant, { walletMode: true, source: 'wallet', onClose: function () { 1903 if (remaining > 0) startTimer(); 1904 }}); 1905 }); 1906 1907 /* Initial show */ 1908 setTimeout(showWallet, INITIAL_DELAY); 1909 } 1910 1911 /* ============================================================ 1912 BONUS NOTIFICATION POPUP (compact card with social proof) 1913 ============================================================ */ 1914 function renderBonusPopup(variant, color) { 1915 var cfg = variant.popup; 1916 var tr = cfg.translations || {}; 1917 var STORAGE_KEY = 'uvw1_bonus_' + SITE_ID; 1918 1919 function getState() {
1920 try { var s = localStorage.getItem(STORAGE_KEY); return s ? JSON.parse(s) : null; } catch (e) { return null; } 1921 } 1922 function saveState(obj) { 1923 try { localStorage.setItem(STORAGE_KEY, JSON.stringify(obj)); } catch (e) { /* */ } 1924 } 1925 1926 var brandName = variant.brandName || 'Casino'; 1927 var siteName = variant.siteName || ''; 1928 var flagEmoji = cfg.countryFlag || ''; 1929 var countryCode = {'GB':'UK'}[cfg.countryCode] || cfg.countryCode || ''; 1930 var localNames = (tr.countryNames) || {}; 1931 var localAdj = (tr.countryAdj) || {}; 1932 var countryName = localNames[cfg.countryCode] || COUNTRY_NAMES[cfg.countryCode] || countryCode; 1933 var countryAdj = localAdj[cfg.countryCode] || countryName; 1934 1935 /* Social proof count â seeded by day so it's stable within a day */ 1936 var dayOfYear = Math.floor((new Date() - new Date(new Date().getFullYear(), 0, 1)) / 86400000); 1937 var socialCount = 800 + ((dayOfYear * 137 + dayOfYear * dayOfYear * 13) % 1701); 1938 1939 /* Translated strings */ 1940 var titleTpl = tr.bonusTitle || '{flag} Exclusive partner bonus for {country_adj} players!'; 1941 var titleText = titleTpl.replace('{flag}', '').replace('{new_brand}', brandName).replace('{old_brand}', siteName).replace('{country_adj}', countryAdj).replace('{country}', countryName).trim(); 1942 var socialTpl = tr.bonusSocial || '{count} {country_adj} players claimed today'; 1943 var socialText = socialTpl.replace('{count}', socialCount.toLocaleString()).replace('{country_adj}', countryAdj).replace('{country}', countryName); 1944 var btnText = cfg.claimText || (tr.claim || 'CLAIM YOUR BONUS'); 1945 1946 /* Floating gift icon */ 1947 var floatIcon = document.createElement('div'); 1948 floatIcon.className = 'uvw1-float-icon'; 1949 var floatImg = document.createElement('img'); 1950 floatImg.src = '/widget-assets/popup-images/gift.png'; 1951 floatImg.alt = 'Bonus'; 1952 floatIcon.appendChild(floatImg); 1953 document.body.appendChild(floatIcon); 1954 1955 /* Overlay */ 1956 var overlay = document.createElement('div'); 1957 overlay.className = 'uvw1-overlay'; 1958 1959 var popupWrap = document.createElement('div'); 1960 popupWrap.className = 'uvw1-popup-wrap'; 1961 1962 /* Notification card */ 1963 var notif = document.createElement('div'); 1964 notif.className = 'uvw1-notif'; 1965 1966 /* Background */ 1967 var bgDiv = document.createElement('div'); 1968 bgDiv.className = 'uvw1-banner-bg'; 1969 if (variant.brandBg) { 1970 bgDiv.style.backgroundImage = 'url(' + variant.brandBg + ')'; 1971 } else if (variant.brandBgColor) { 1972 bgDiv.style.background = 'linear-gradient(180deg, ' + variant.brandBgColor + ' 0%, ' + variant.brandBgColor + ' 30%, #0a0a1a 100%)'; 1973 } else { 1974 bgDiv.style.background = 'linear-gradient(180deg, #0d0d1a 0%, #1a1a3e 40%, #0f1f3d 100%)'; 1975 } 1976 notif.appendChild(bgDiv); 1977 1978 /* Close button */ 1979 var closeBtn = document.createElement('button'); 1980 closeBtn.className = 'uvw1-notif-close'; 1981 closeBtn.innerHTML = '×'; 1982 notif.appendChild(closeBtn); 1983 1984 /* Title bar */ 1985 var titleBar = document.createElement('div'); 1986 titleBar.className = 'uvw1-notif-title'; 1987 var giftIcon = document.createElement('span'); 1988 giftIcon.className = 'uvw1-notif-icon'; 1989 giftIcon.textContent = '\uD83C\uDF81'; 1990 titleBar.appendChild(giftIcon); 1991 var titleEl = document.createElement('span'); 1992 titleEl.className = 'uvw1-notif-text'; 1993 titleEl.innerHTML = titleText.replace(/\|/g, '<br>'); 1994 titleBar.appendChild(titleEl); 1995 notif.appendChild(titleBar); 1996 1997 /* Body */ 1998 var body = document.createElement('div'); 1999 body.className = 'uvw1-notif-body'; 2000 2001 /* Brand logo */ 2002 if (variant.brandLogo) { 2003 var logoWrap = document.createElement('div'); 2004 logoWrap.className = 'uvw1-banner-logo-wrap'; 2005 logoWrap.style.paddingTop = '6px'; 2006 logoWrap.style.marginBottom = '14px'; 2007 logoWrap.style.paddingBottom = '0'; 2008 logoWrap.style.borderBottom = 'none'; 2009 var logo = document.createElement('img'); 2010 logo.className = 'uvw1-banner-logo'; 2011 logo.src = variant.brandLogo; 2012 logo.alt = brandName; 2013 logoWrap.appendChild(logo); 2014 body.appendChild(logoWrap); 2015 } 2016 2017 /* Bonus card */ 2018 var bonusDiv = document.createElement('div'); 2019 bonusDiv.className = 'uvw1-banner-bonus'; 2020 2021 var prizeVal = cfg.prize || '100%'; 2022 var prizeEl = document.createElement('div'); 2023 prizeEl.className = 'uvw1-banner-prize-line'; 2024 prizeEl.innerHTML = '<span class="uvw1-banner-pct">' + escHtml(prizeVal) + '</span>' + (cfg.prizeDetail ? ' ' + escHtml(cfg.prizeDetail) : ''); 2025 bonusDiv.appendChild(prizeEl); 2026 2027 if (cfg.prizeSub) { 2028 var subEl = document.createElement('div'); 2029 subEl.className = 'uvw1-banner-sub'; 2030 subEl.textContent = cfg.prizeSub; 2031 bonusDiv.appendChild(subEl); 2032 } 2033 2034 body.appendChild(bonusDiv); 2035 2036 /* Social proof line */ 2037 var socialDiv = document.createElement('div'); 2038 socialDiv.className = 'uvw1-notif-social'; 2039 if (flagEmoji) { 2040 var socialFlag = document.createElement('span'); 2041 socialFlag.className = 'uvw1-notif-social-flag'; 2042 socialFlag.textContent = flagEmoji; 2043 socialDiv.appendChild(socialFlag); 2044 } 2045 var socialEl = document.createElement('span'); 2046 socialEl.innerHTML = '<span class="uvw1-notif-social-count">
2046' + escHtml(socialCount.toLocaleString()) + '</span> ' + escHtml(socialText.replace(socialCount.toLocaleString(), '').trim()); 2047 socialDiv.appendChild(socialEl); 2048 body.appendChild(socialDiv); 2049 2050 /* CTA button */ 2051 var btn = document.createElement('span'); 2052 btn.className = 'uvw1-banner-btn'; 2053 btn.style.cursor = 'pointer'; 2054 btn.innerHTML = escHtml(btnText) + ' <span class="uvw1-btn-arrow">»</span>'; 2055 btn.addEventListener('click', function () { 2056 saveState({ shown: true, clicked: true }); 2057 goOpen('bonus'); 2058 }); 2059 body.appendChild(btn); 2060 2061 notif.appendChild(body); 2062 popupWrap.appendChild(notif); 2063 overlay.appendChild(popupWrap); 2064 document.body.appendChild(overlay); 2065 2066 /* Show / hide */ 2067 function showPopup() { 2068 overlay.classList.add('uvw1-show'); 2069 document.body.style.overflow = 'hidden'; 2070 floatIcon.classList.remove('uvw1-visible'); 2071 goTrack('bonus_open'); 2072 setTimeout(function () { closeBtn.classList.add('uvw1-visible'); }, 2000); 2073 saveState({ shown: true }); 2074 } 2075 2076 function hidePopup() { 2077 overlay.classList.remove('uvw1-show'); 2078 document.body.style.overflow = ''; 2079 floatIcon.classList.add('uvw1-visible'); 2080 } 2081 2082 closeBtn.addEventListener('click', hidePopup); 2083 floatIcon.addEventListener('click', showPopup); 2084 2085 /* Initial state */ 2086 var initState = getState(); 2087 floatIcon.classList.add('uvw1-visible'); 2088 2089 if (!initState || !initState.shown) { 2090 setTimeout(showPopup, 120000); 2091 } 2092 } 2093 2094 /* ============================================================ 2095 FLOAT BUTTON (direct redirect, no popup) 2096 ============================================================ */ 2097 function renderFloatButton(variant, color) { 2098 var cfg = variant.floatButton; 2099 var btn = document.createElement('button'); 2100 btn.className = 'uvw1-float-btn'; 2101 btn.style.color = cfg.textColor || '#fff'; 2102 btn.style.background = 'linear-gradient(135deg, ' + lightenColor(color, 15) + ', ' + color + ', ' + darkenColor(color, 20) + ')'; 2103 btn.style.backgroundSize = '200% 200%'; 2104 2105 var textSpan = document.createElement('span'); 2106 textSpan.textContent = cfg.text || 'PLAY NOW'; 2107 btn.appendChild(textSpan); 2108 2109 var arrow = document.createElement('span'); 2110 arrow.className = 'uvw1-float-arrow'; 2111 arrow.innerHTML = '➜'; 2112 btn.appendChild(arrow); 2113 2114 goSet(btn, 'float_btn'); 2115 2116 document.body.appendChild(btn); 2117 } 2118 2119 /* ============================================================ 2120 INIT 2121 ============================================================ */ 2122 injectStyles(); 2123 2124 fetch(API_BASE + '/config/' + SITE_ID) 2125 .then(function (r) { 2126 if (!r.ok) throw new Error('Config fetch failed: ' + r.status); 2127 return r.json(); 2128 }) 2129 .then(function (config) { 2130 if (!config || !config.variants || config.variants.length === 0) return; 2131 2132 /* Init click tracking from config */ 2133 if (config.clickParam) _CP = config.clickParam; 2134 if (config.clickSources) _CS = config.clickSources; 2135 2136 var variant = selectVariant(config.variants); 2137 if (!variant) return; 2138 2139 var color = (variant.headerButton && variant.headerButton.color) || detectSiteColor(); 2140 2141 if (variant.headerButton && variant.headerButton.enabled) { 2142 renderHeaderButton(variant, color); 2143 } 2144 2145 if (variant.stickyFooter && variant.stickyFooter.enabled) { 2146 if (variant.stickyFooter.type === 'wallet') { 2147 renderWalletFooter(variant, color); 2148 } else { 2149 renderStickyFooter(variant, color); 2150 } 2151 } 2152 2153 if (variant.floatButton && variant.floatButton.enabled) { 2154 renderFloatButton(variant, color); 2155 } 2156 2157 if (variant.popup && variant.popup.enabled) { 2158 if (variant.popup.type === 'bonus') { 2159 renderBonusPopup(variant, color); 2160 } else { 2161 renderPopup(variant); 2162 } 2163 } 2164 }) 2165 .catch(function (err) { 2166 if (typeof console !== 'undefined') { 2167 console.warn('Widget init error:', err); 2168 } 2169 }); 2170})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.