playsout-web-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/chunk-AJVRILLC.js +2 -0
  2. package/chunk-EZLO3WY6.js +2 -0
  3. package/chunk-MUMDBAO7.cjs +2 -0
  4. package/chunk-Z2CIDSTP.cjs +2 -0
  5. package/core/api.d.ts +19 -0
  6. package/core/api.d.ts.map +1 -0
  7. package/core/errors.d.ts +31 -0
  8. package/core/errors.d.ts.map +1 -0
  9. package/core/events.d.ts +30 -0
  10. package/core/events.d.ts.map +1 -0
  11. package/core/index.d.ts +38 -0
  12. package/core/index.d.ts.map +1 -0
  13. package/core/storage.d.ts +24 -0
  14. package/core/storage.d.ts.map +1 -0
  15. package/core/types.d.ts +127 -0
  16. package/core/types.d.ts.map +1 -0
  17. package/data/games.d.ts +30 -0
  18. package/data/games.d.ts.map +1 -0
  19. package/iife-entry.d.ts +3 -0
  20. package/iife-entry.d.ts.map +1 -0
  21. package/index.cjs +1 -0
  22. package/index.d.ts +9 -0
  23. package/index.d.ts.map +1 -0
  24. package/index.global.js +1471 -0
  25. package/index.iife.js +1471 -0
  26. package/index.js +1 -0
  27. package/package.json +63 -0
  28. package/public-api.d.ts +24 -0
  29. package/public-api.d.ts.map +1 -0
  30. package/react/context.d.ts +40 -0
  31. package/react/context.d.ts.map +1 -0
  32. package/react/index.cjs +1 -0
  33. package/react/index.d.ts +6 -0
  34. package/react/index.d.ts.map +1 -0
  35. package/react/index.js +1 -0
  36. package/vue/composable.d.ts +88 -0
  37. package/vue/composable.d.ts.map +1 -0
  38. package/vue/index.cjs +1 -0
  39. package/vue/index.d.ts +8 -0
  40. package/vue/index.d.ts.map +1 -0
  41. package/vue/index.js +1 -0
  42. package/vue/plugin.d.ts +14 -0
  43. package/vue/plugin.d.ts.map +1 -0
  44. package/web-components/PlaysoutWidget.d.ts +46 -0
  45. package/web-components/PlaysoutWidget.d.ts.map +1 -0
  46. package/web-components/assetUrl.d.ts +2 -0
  47. package/web-components/assetUrl.d.ts.map +1 -0
  48. package/web-components/imageCache.d.ts +13 -0
  49. package/web-components/imageCache.d.ts.map +1 -0
  50. package/web-components/index.cjs +1471 -0
  51. package/web-components/index.d.ts +3 -0
  52. package/web-components/index.d.ts.map +1 -0
  53. package/web-components/index.js +1471 -0
package/index.iife.js ADDED
@@ -0,0 +1,1471 @@
1
+ "use strict";var Playsout=(()=>{var F=Object.defineProperty;var Re=Object.getOwnPropertyDescriptor;var Me=Object.getOwnPropertyNames;var _e=Object.prototype.hasOwnProperty;var ze=(o,t)=>{for(var e in t)F(o,e,{get:t[e],enumerable:!0})},Ge=(o,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of Me(t))!_e.call(o,i)&&i!==e&&F(o,i,{get:()=>t[i],enumerable:!(a=Re(t,i))||a.enumerable});return o};var De=o=>Ge(F({},"__esModule",{value:!0}),o);var At={};ze(At,{Login:()=>gt,PlaysoutSDKClass:()=>It,destroy:()=>dt,getCategories:()=>vt,getGames:()=>yt,getLocale:()=>bt,getToken:()=>mt,getUser:()=>pt,getUserInfo:()=>ht,init:()=>st,instance:()=>Tt,isInitialized:()=>xt,isLoggedIn:()=>St,logout:()=>ut,mount:()=>lt,off:()=>kt,on:()=>wt,setLocale:()=>ft,unmount:()=>ct});var x=class extends Error{constructor(e,a,i){super(a);this.code=e;this.details=i;this.name="SDKError"}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details}}},Ne={NOT_INITIALIZED:"SDK not initialized. Please call PlaysoutSDK.init() first.",ALREADY_INITIALIZED:"SDK already initialized. Please do not call init() more than once.",NOT_LOGGED_IN:"User not logged in. Please log in first.",TOKEN_EXPIRED:"Login token has expired. Please log in again.",INVALID_TOKEN:"Invalid login token. Please log in again.",NETWORK_ERROR:"Network connection failed. Please check your network.",TIMEOUT:"Request timed out. Please try again later.",SERVER_ERROR:"Server is busy. Please try again later.",API_ERROR:"API request failed.",INVALID_PARAMS:"Invalid parameter(s).",MISSING_PARAMS:"Missing required parameter(s).",FEATURE_NOT_SUPPORTED:"This feature is not supported in the current environment.",UNKNOWN:"An unknown error occurred.",PAYMENT_FAILED:"Payment failed.",SHARE_FAILED:"Share failed."};function g(o,t){return new x(o,Ne[o],t)}var z="playsout_",G=class{constructor(t){this.storage=t}get(t){try{return this.storage.getItem(z+t)}catch{return null}}set(t,e){try{this.storage.setItem(z+t,e)}catch(a){console.warn("[PlaysoutSDK] Storage set failed:",a)}}remove(t){try{this.storage.removeItem(z+t)}catch{}}clear(){try{let t=[];for(let e=0;e<this.storage.length;e++){let a=this.storage.key(e);a&&a.startsWith(z)&&t.push(a)}t.forEach(e=>this.storage.removeItem(e))}catch{}}},q=class{constructor(){this.store=new Map}get(t){return this.store.get(t)??null}set(t,e){this.store.set(t,e)}remove(t){this.store.delete(t)}clear(){this.store.clear()}};function oe(o="localStorage"){return typeof window>"u"||o==="memory"?new q:o==="sessionStorage"?new G(sessionStorage):new G(localStorage)}var S=oe(),h={get:o=>S.get(o),set:(o,t)=>{S.set(o,t)},remove:o=>{S.remove(o)},clear:()=>{S.clear()},getJSON:o=>{let t=S.get(o);if(!t)return null;try{return JSON.parse(t)}catch{return null}},setJSON:(o,t)=>{S.set(o,JSON.stringify(t))},configure(o){S=oe(o)}},p={TOKEN_DATA:"token_data",USER:"user",LOCALE:"locale",CONFIG:"config"};var W=class{constructor(){this.events=new Map}on(t,e){return this.events.has(t)||this.events.set(t,new Set),this.events.get(t).add(e),()=>{this.off(t,e)}}once(t,e){let a=i=>{e(i),this.off(t,a)};return this.on(t,a)}off(t,e){this.events.get(t)?.delete(e),this.events.get(t)?.size===0&&this.events.delete(t)}emit(t,e){this.events.get(t)?.forEach(a=>{try{a(e)}catch(i){console.error(`[PlaysoutSDK] Event handler error for "${t}":`,i)}})}listenerCount(t){return this.events.get(t)?.size??0}clear(){this.events.clear()}},I=new W,y={on:(o,t)=>I.on(o,t),once:(o,t)=>I.once(o,t),off:(o,t)=>{I.off(o,t)},clear:()=>{I.clear()},emit:(o,t)=>{I.emit(o,t)}};var Oe="https://games.playsout.com/resources/icon/image";function s(o){if(!o||/^(data:|https?:|blob:)/i.test(o))return o;let t=o.replace(/^\.\//,"");return`${Oe}/${t}`}var Ue=o=>{if(!o)return o;try{let t=new URL(o);if(t.hostname==="games.playsout.com"){let e=t.pathname,a=e.endsWith("/"),i=/\.[a-z0-9]+$/i.test(e);!a&&!i&&(t.pathname=`${e}/`)}return t.toString()}catch{return o}},Be=o=>o.map(t=>{if(!t.externalUrl)return t;let e=Ue(t.externalUrl);return e===t.externalUrl?t:{...t,externalUrl:e}}),je=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:s("./games/BlockCrushFun.png"),isNew:!0,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/BlockCrushFun"},{id:"DogeSurvivors",title:"Doge Survivors",category:"Doge OS",image:s("./games/DogeSurvivors.jpg"),isNew:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeSurvivors/"},{id:"DogeMaze",title:"Doge Maze",category:"Doge OS",image:s("./games/DogeMaze.jpg"),isNew:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMaze/"},{id:"DogeMart",title:"Doge Mart",category:"Doge OS",image:s("./games/DogeMart.jpg"),isNew:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMart/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:s("./games/KittyEscape.jpg"),isNew:!0,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:s("./games/SimulatedAdventures.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/simulated/"},{id:"ProjectIDLE",title:"Project: IDLE",category:"Simulation",image:s("./games/ProjectIDLE.jpg"),isNew:!0,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:s("./games/CulinaryStar.webp"),description:"Cooking game",isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CulinaryStar/"},{id:"PickaxeQuest",title:"Pickaxe Quest",category:"Adventure",image:s("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:s("./games/MonsterSurvivors.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/MonsterSurvivors/"},{id:"IdleTowerDefense",title:"Idle Tower Defense",category:"RPG",image:s("./games/IdleTowerDefense.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/IdleTowerDefense/"},{id:"MushroomWarriors",title:"Mushroom Warriors",category:"RPG",image:s("./games/MushroomWarriors.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:s("./games/FollowThePath.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/FollowThePath/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:s("./games/ColorRun.jpg"),isNew:!1,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorRun/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:s("./games/StupidArrow.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:s("./games/ZigZag.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:s("./games/SpikesEverywhere.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:s("./games/ArrowRacer.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:s("./games/CircleLeap.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:s("./games/ColorMatcher.jpg"),isNew:!1,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:s("./games/EndlessMaze.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/EndlessMaze/"},{id:"SpinningAround",title:"Spinning Around",category:"Arcade",image:s("./games/SpinningAround.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:s("./games/BoomBallz.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/BoomBallz/"},{id:"CubeHead",title:"Cube Head",category:"Arcade",image:s("./games/CubeHead.jpg"),isNew:!1,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:s("./games/CapybaraLink.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CapybaraLink/"},{id:"Snake2048",title:"Snake 2048",category:"Puzzle",image:s("./games/Snake2048.jpg"),isNew:!0,isHot:!0,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/Snake2048/"},{id:"FishTankFury",title:"Fish Tank Fury",category:"Puzzle",image:s("./games/FishTankFury.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:s("./games/ConnectBalls.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:s("./games/CircularBreaker.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:s("./games/OneDoor.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:s("./games/CatchtheFruits.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/CatchtheFruits/"},{id:"Falling2048",title:"Falling 2048",category:"Casual",image:s("./games/Falling2048.jpg"),isNew:!0,isHot:!1,enable:!0,orientation:"portrait",externalUrl:"https://games.playsout.com/Falling2048/"}],ie=Be(je),w=()=>ie.filter(o=>o.enable),_t={Adventure:w().filter(o=>o.category==="Adventure"),Moba:w().filter(o=>o.category==="Moba")};var re=o=>ie.find(t=>t.id===o);var ne=()=>Array.from(new Set(w().map(o=>o.category)));var Z="https://api.playsout.com",Q=3e4,Ke=new Set([10010,10011,10012,10013]);function $e(o){let t=String(o?.platform||"").toLowerCase();if(t==="tiktok"){let e=o.authorizationCode;if(typeof e!="string"||!e.trim())throw g("MISSING_PARAMS","authorizationCode is required for TikTok login");return{platform:t,authorizationCode:e}}if(t==="grab"||t==="eros"){let e=o;if(typeof e.platformUserId!="string"||!e.platformUserId.trim())throw g("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof e.platformToken!="string"||!e.platformToken.trim())throw g("MISSING_PARAMS","platformToken is required for Grab/Eros login");return{platform:t,platformUserId:e.platformUserId,platformToken:e.platformToken,username:typeof e.username=="string"?e.username:void 0,inviteCode:typeof e.inviteCode=="string"?e.inviteCode:void 0}}throw g("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,Y=null,E=null;function ce(o){Y=o}function de(o){E=o}async function se(o,t={},e,a=!1){let i=e?.apiBaseUrl||Z,r=o.startsWith("http")?o:`${i}${o}`,n=new AbortController,d=setTimeout(()=>n.abort(),Q);try{let m=h.getJSON(p.TOKEN_DATA),b={"Content-Type":"application/json",...t.headers};m?.accessToken&&!b.token&&(b.token=m.accessToken);let f=await fetch(r,{...t,signal:n.signal,headers:b});if(clearTimeout(d),!f.ok){if(f.status===401&&!a)return await le(o,t,e);throw g(f.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${f.status}: ${f.statusText}`)}let u=await f.json();if(u.code!==void 0&&Ke.has(u.code)&&!a){if(o.includes("/platform/refreshToken"))throw g("TOKEN_EXPIRED",u.msg||"Token expired");return await le(o,t,e)}if(u.code!==0&&u.code!==1e4)throw g("API_ERROR",u.msg||"API request failed");return u.data}catch(m){throw clearTimeout(d),m instanceof x?m:m instanceof Error?m.name==="AbortError"?g("TIMEOUT"):g("NETWORK_ERROR",m.message):g("UNKNOWN")}}async function le(o,t,e){await ge(e);let a=e?.apiBaseUrl||Z,i=o.startsWith("http")?o:`${a}${o}`,r=new AbortController,n=setTimeout(()=>r.abort(),Q);try{let d=h.getJSON(p.TOKEN_DATA),m={"Content-Type":"application/json",...t.headers};d?.accessToken&&(m.token=d.accessToken);let b=await fetch(i,{...t,signal:r.signal,headers:m});if(clearTimeout(n),!b.ok)throw g(b.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${b.status}: ${b.statusText}`);let f=await b.json();if(f.code!==0&&f.code!==1e4)throw g("API_ERROR",f.msg||"API request failed");return f.data}catch(d){throw clearTimeout(n),d instanceof x?d:d instanceof Error&&d.name==="AbortError"?g("TIMEOUT"):g("NETWORK_ERROR",d?.message||"Request failed")}}async function ge(o){return A||(A=(async()=>{let t=h.getJSON(p.TOKEN_DATA);if(!t?.refreshToken)throw g("NOT_LOGGED_IN","No refresh token available");let e=o?.apiBaseUrl||Z,a=new AbortController,i=setTimeout(()=>a.abort(),Q);try{let r=await fetch(`${e}/platform/refreshToken`,{method:"POST",signal:a.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t.refreshToken})});if(clearTimeout(i),!r.ok)throw g("TOKEN_EXPIRED","Failed to refresh token");let n=await r.json();if(n.code!==0&&n.code!==1e4||!n.data)throw g("TOKEN_EXPIRED",n.msg||"Failed to refresh token");let d=n.data;if(h.setJSON(p.TOKEN_DATA,d),Y)try{Y(d)}catch{}return d}catch(r){if(clearTimeout(i),r instanceof x){if(E)try{E()}catch{}throw r}if(r instanceof Error&&r.name==="AbortError")throw g("TIMEOUT");if(E)try{E()}catch{}throw g("TOKEN_EXPIRED","Refresh token failed")}finally{A=null}})(),A)}var J=class{constructor(){this.config=null}configure(t){this.config=t}async refreshToken(){return await ge(this.config||void 0)}async getGames(t){let e=w();if(t?.category&&(e=e.filter(a=>a.category===t.category)),t?.search){let a=t.search.toLowerCase();e=e.filter(i=>i.title.toLowerCase().includes(a)||i.category.toLowerCase().includes(a)||i.description&&i.description.toLowerCase().includes(a))}if(t?.sortBy)switch(t.sortBy){case"newest":e=e.filter(a=>a.isNew).concat(e.filter(a=>!a.isNew));break;case"rating":e=e.filter(a=>a.isHot).concat(e.filter(a=>!a.isHot));break}if(t?.page&&t?.pageSize){let a=(t.page-1)*t.pageSize;e=e.slice(a,a+t.pageSize)}return e}async getCategories(){let t=w(),e=new Map;return t.forEach(a=>{let i=e.get(a.category)||0;e.set(a.category,i+1)}),Array.from(e.entries()).map(([a,i],r)=>({id:`category_${r}`,name:a,count:i}))}async getGameById(t){return re(t)}async getCategoryNames(){return ne()}async loginOnly(t){let e=$e(t);return await se("/platform/login",{method:"POST",body:JSON.stringify(e)},this.config??void 0)}async Login(t){let e=await this.loginOnly(t),a;try{a=await this.getUserInfo()}catch{}return{tokenData:e,user:a}}async getUserInfo(){return await se("/platform/user",{method:"GET"},this.config??void 0)}async getUser(){return h.getJSON(p.USER)}async validateToken(t){return!!t}},V=null;function D(){return V||(V=new J),V}var qe="https://api.playsout.com",ue="zh",C=class o{constructor(){this.config=null;this._isInitialized=!1;this._user=null;this._token=null;this._locale=ue;this._widget=null}static getInstance(){return o.instance||(o.instance=new o),o.instance}async init(t={}){if(this._isInitialized)throw g("ALREADY_INITIALIZED");this.config={apiBaseUrl:t.apiBaseUrl||qe,debug:t.debug||!1,storage:t.storage||"localStorage",locale:t.locale||ue,appId:t.appId||""},h.configure(this.config.storage),ce(i=>{this._token=i.accessToken}),de(()=>{this._user=null,this._token=null,h.remove(p.TOKEN_DATA),h.remove(p.USER),y.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out")});let e=h.getJSON(p.TOKEN_DATA);this._user=h.getJSON(p.USER),this._locale=h.get(p.LOCALE)||this.config.locale;let a=Math.floor(Date.now()/1e3);if(e&&e.refreshExpiresAt>a&&(this._token=e.accessToken),this._isInitialized=!0,this.config.debug&&(console.log("[PlaysoutSDK] Initialized with config:",this.config),console.log("[PlaysoutSDK] Restored token:",this._token?this._token.substring(0,20)+"...":"(none)")),y.emit("initialized"),e){let i=Math.floor(Date.now()/1e3);if(e.expiresAt-i<=300)try{let r=D();r.configure(this.config),await r.refreshToken();let n=h.getJSON(p.TOKEN_DATA);n&&(this._token=n.accessToken),this.config.debug&&console.log("[PlaysoutSDK] Token proactively refreshed at init")}catch(r){this.config.debug&&console.warn("[PlaysoutSDK] Proactive refresh failed, will retry on next request:",r)}}}destroy(){this.config=null,this._isInitialized=!1,this._user=null,this._token=null,h.clear(),y.clear()}get isInitialized(){return this._isInitialized}get isLoggedIn(){return!!this._token}get user(){return this._user}get token(){return this._token}get locale(){return this._locale}get sdkConfig(){return this.config}async Login(t){this.ensureInitialized(),this.config?.debug&&console.log("[PlaysoutSDK] Login with params:",t);let e=D();e.configure(this.config);let a=await e.loginOnly(t);h.setJSON(p.TOKEN_DATA,a),this.config?.debug&&console.log("[PlaysoutSDK] Token saved, expires at:",new Date(a.expiresAt*1e3).toISOString());let i;try{i=await e.getUserInfo()}catch(r){this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo failed, login still success:",r)}return this._token=a.accessToken,i&&(this._user={userId:String(i.id),username:i.username},h.setJSON(p.USER,this._user)),this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",i),y.emit("login",{user:this._user,token:this._token}),{tokenData:a,user:i}}async getUserInfo(){if(this.ensureInitialized(),!this._token)throw g("NOT_LOGGED_IN","Please login first");let t=D();t.configure(this.config);let e=await t.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",e),e&&(this._user={userId:String(e.id),username:e.username},h.setJSON(p.USER,this._user)),e}logout(){this._user=null,this._token=null,h.remove(p.TOKEN_DATA),h.remove(p.USER),y.emit("logout")}getToken(){return this.ensureInitialized(),this._token}getUser(){return this.ensureInitialized(),this._user}setLocale(t){if(this.ensureInitialized(),!["zh","en","ja","ko","vi","th","id","ms"].includes(t))throw g("INVALID_PARAMS",`Unsupported locale: ${t}`);this._locale=t,h.set(p.LOCALE,t),this.config?.debug&&console.log("[PlaysoutSDK] Locale changed to:",t);let e=this._widget||document.querySelector("playsout-widget");e&&e.getAttribute("locale")!==t&&e.setAttribute("locale",t),y.emit("localeChange",t)}getLocale(){return this.ensureInitialized(),this._locale}async getGames(t){this.ensureInitialized();let e=w();if(t?.category&&(e=e.filter(a=>a.category===t.category)),t?.search){let a=t.search.toLowerCase();e=e.filter(i=>i.title.toLowerCase().includes(a)||i.category.toLowerCase().includes(a)||i.description&&i.description.toLowerCase().includes(a))}if(t?.sortBy)switch(t.sortBy){case"newest":e=e.filter(a=>a.isNew).concat(e.filter(a=>!a.isNew));break;case"rating":e=e.filter(a=>a.isHot).concat(e.filter(a=>!a.isHot));break}if(t?.page&&t?.pageSize){let a=(t.page-1)*t.pageSize;e=e.slice(a,a+t.pageSize)}return e}async getCategories(){this.ensureInitialized();let t=w(),e=new Map;return t.forEach(a=>{let i=e.get(a.category)||0;e.set(a.category,i+1)}),Array.from(e.entries()).map(([a,i],r)=>({id:`category_${r}`,name:a,count:i}))}async getGameById(t){return this.ensureInitialized(),w().find(e=>e.id===t)}mount(t,e){if(this.ensureInitialized(),typeof document>"u")throw g("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let a=document.querySelector(t);if(!a)throw g("INVALID_PARAMS",`Container not found: ${t}`);let i=document.createElement("playsout-widget");this.config?.appId&&i.setAttribute("app-id",this.config.appId),i.setAttribute("locale",e?.locale||this._locale),i.setAttribute("theme",e?.theme||"dark"),e?.detailMode&&i.setAttribute("detail-mode",e.detailMode),this._widget=i,e?.onGameClick&&i.addEventListener("game-click",r=>{let n=r;e.onGameClick(n.detail)}),e?.onLoginRequired&&i.addEventListener("login-required",e.onLoginRequired),e?.onLocaleChange&&i.addEventListener("locale-change",r=>{let n=r;e.onLocaleChange(n.detail)}),a.appendChild(i),this.config?.debug&&console.log("[PlaysoutSDK] Widget mounted to:",t)}unmount(){let t=document.querySelector("playsout-widget");t&&t.remove(),this._widget=null}on(t,e){return this.ensureInitialized(),y.on(t,e)}off(t,e){this.ensureInitialized(),y.off(t,e)}ensureInitialized(){if(!this._isInitialized)throw g("NOT_INITIALIZED")}},l=C.getInstance();typeof window<"u"&&(window.__playsout_sdk_instance=l);var N=Object.freeze({init:l.init.bind(l),mount:l.mount.bind(l),unmount:l.unmount.bind(l),destroy:l.destroy.bind(l),Login:l.Login.bind(l),logout:l.logout.bind(l),getToken:l.getToken.bind(l),getUserInfo:l.getUserInfo.bind(l),getUser:l.getUser.bind(l),setLocale:l.setLocale.bind(l),getLocale:l.getLocale.bind(l),getGames:l.getGames.bind(l),getCategories:l.getCategories.bind(l),on:l.on.bind(l),off:l.off.bind(l),get isInitialized(){return l.isInitialized},get isLoggedIn(){return l.isLoggedIn},instance:l,PlaysoutSDKClass:C});var We="games.playsout.com";var X="__playsout_img_cache_v1",H=`${X}_blob_`,U=4*1024*1024-1024*1024;function c(...o){}var T=new Map,O=new Map,Ve=50,L=new Map,B=new Map,v=0;function ee(){try{let o=localStorage.getItem(X);if(!o)return c("loadCacheIndex: \u65E0\u7F13\u5B58\u7D22\u5F15"),v=0,new Map;let t=JSON.parse(o);c("loadCacheIndex: \u52A0\u8F7D\u4E86",t.length,"\u6761\u8BB0\u5F55"),v=0;for(let e of t){let a=`${H}${btoa(e.url).replace(/[\/+=]/g,"_")}`;localStorage.getItem(a)&&(v+=e.size)}return c("loadCacheIndex: \u5F53\u524D blob \u603B\u91CF",v,"bytes"),new Map(t.map(e=>[e.url,e]))}catch{return c("loadCacheIndex: \u89E3\u6790\u5931\u8D25"),v=0,new Map}}function j(o){try{let t=Array.from(o.values());t.length>200&&(t.sort((e,a)=>a.timestamp-e.timestamp),t.length=200),localStorage.setItem(X,JSON.stringify(t)),c("saveCacheIndex: \u4FDD\u5B58\u4E86",t.length,"\u6761\u8BB0\u5F55")}catch(t){c("saveCacheIndex: \u4FDD\u5B58\u5931\u8D25",t)}}function Ye(o,t){if(!(v+t<=U))try{let e=ee(),a=Array.from(e.values()).map(i=>({record:i,score:he(i.url)??1/0})).filter(i=>i.score>o).sort((i,r)=>r.score-i.score);for(let{record:i}of a){if(v+t<=U)break;let r=`${H}${btoa(i.url).replace(/[\/+=]/g,"_")}`;localStorage.removeItem(r),e.delete(i.url),v-=i.size,c("evictLowerPriorityEntries: \u91CA\u653E\u4F4E\u4F18\u5148\u7EA7\u7F13\u5B58",i.url,"\u8282\u7701",i.size,"bytes")}j(e)}catch(e){c("evictLowerPriorityEntries: \u5931\u8D25",e)}}function me(o,t){if(T.size>=Ve){let e=null,a=1/0;for(let[i,r]of T)r.lastAccess<a&&(a=r.lastAccess,e=i);if(e){let i=T.get(e);URL.revokeObjectURL(URL.createObjectURL(i.blob)),T.delete(e),c("addToMemoryCache: LRU\u6DD8\u6C70",e)}}T.set(o,{blob:t,lastAccess:Date.now()}),c("addToMemoryCache: \u6DFB\u52A0\u5230\u5185\u5B58\u7F13\u5B58",o,"\u5927\u5C0F:",t.size,"bytes")}async function Je(o){if(O.has(o)){c("cacheImage:",o,"\u8BE5\u8BF7\u6C42\u5DF2\u5728\u8FDB\u884C\u4E2D\uFF0C\u7B49\u5F85\u5B8C\u6210"),await O.get(o);return}c("cacheImage: \u5F00\u59CB\u4E0B\u8F7D",o);let t=(async()=>{try{let e=await fetch(o);if(!e.ok){c("cacheImage:",o,"\u54CD\u5E94\u5931\u8D25",e.status);return}let a=await e.blob(),i=e.headers.get("ETag")||"";c("cacheImage:",o,"\u4E0B\u8F7D\u6210\u529F\uFF0C\u5927\u5C0F:",a.size,"ETag:",i),me(o,a);let r=he(o);if(r!==void 0)if(Ye(r,a.size),v+a.size<=U)try{let n=ee();n.set(o,{url:o,timestamp:Date.now(),etag:i,size:a.size}),j(n);let d=JSON.stringify({type:a.type,data:Array.from(new Uint8Array(await a.arrayBuffer()))}),m=`${H}${btoa(o).replace(/[\/+=]/g,"_")}`;localStorage.setItem(m,d),v+=a.size,c("cacheImage:",o,"\u5DF2\u4FDD\u5B58\u5230localStorage\uFF08\u5360\u7528",a.size,"bytes\uFF0C\u9884\u7B97\u5269\u4F59",U-v,"\uFF09")}catch(n){n.name==="QuotaExceededError"?c("cacheImage: localStorage \u914D\u989D\u5DF2\u6EE1\uFF0C\u505C\u6B62\u5199\u5165"):c("cacheImage:",o,"localStorage\u4FDD\u5B58\u5931\u8D25",n)}else c("cacheImage:",o,"\u817E\u51FA\u7A7A\u95F4\u540E\u4ECD\u8D85\u8FC7\u9884\u7B97\uFF0C\u8DF3\u8FC7");else c("cacheImage:",o,"\u975E\u4F18\u5148\u7EA7URL\uFF0C\u4E0D\u5199\u5165localStorage")}catch(e){c("cacheImage:",o,"\u4E0B\u8F7D\u5931\u8D25",e)}finally{O.delete(o)}})();O.set(o,t)}function te(o){try{if(new URL(o).hostname===We)return c("isCacheableImage:",o,"\u662FCDN\u56FE\u7247"),!0}catch{}return o.startsWith("/games/")||o.startsWith("./games/")||o.startsWith("/home-")||o.startsWith("./home-")||o.startsWith("/logo")||o.startsWith("./logo")?(c("isCacheableImage:",o,"\u662F\u672C\u5730\u56FE\u7247"),!0):(c("isCacheableImage:",o,"\u4E0D\u662F\u53EF\u7F13\u5B58\u7684\u56FE\u7247"),!1)}function he(o){return B.has(o)?B.get(o):L.get(o)}function pe(o){let t=-1e3;for(let e of o)te(e)&&B.set(e,t++);c("setCriticalAssets: \u5171",B.size,"\u4E2A\u5173\u952E\u8D44\u6E90")}function fe(o,t=!1){t||L.clear();let e=0;if(t){for(let i of L.values())i>e&&(e=i);e+=1}let a=e;for(let i of o)te(i)&&L.set(i,a++);c("setPriorityCache: \u5F53\u524D\u5171",L.size,"\u4E2A\u4F18\u5148\u7F13\u5B58URL")}function be(o){if(c("resolveWithCache:",o),!te(o))return c("resolveWithCache:",o,"\u4E0D\u662FCDN\u56FE\u7247\uFF0C\u539F\u6837\u8FD4\u56DE"),o;if(T.has(o)){let e=T.get(o);e.lastAccess=Date.now();try{let a=URL.createObjectURL(e.blob);return c("resolveWithCache:",o,"\u547D\u4E2D\u5185\u5B58\u7F13\u5B58\uFF0C\u8FD4\u56DEblob URL"),a}catch{c("resolveWithCache:",o,"\u521B\u5EFAblob URL\u5931\u8D25")}}let t=ee();if(t.has(o)){let e=`${H}${btoa(o).replace(/[\/+=]/g,"_")}`,a=localStorage.getItem(e);if(a)try{let{type:i,data:r}=JSON.parse(a),n=new Blob([new Uint8Array(r)],{type:i});me(o,n);let d=URL.createObjectURL(n);return c("resolveWithCache:",o,"\u547D\u4E2DlocalStorage\u7F13\u5B58\uFF0C\u540C\u6B65\u8FD4\u56DEblob URL"),d}catch(i){c("resolveWithCache:",o,"localStorage blob\u89E3\u6790\u5931\u8D25\uFF0C\u6E05\u9664\u7F13\u5B58",i),t.delete(o),j(t),localStorage.removeItem(e)}else c("resolveWithCache:",o,"localStorage blob\u4E0D\u5B58\u5728\uFF0C\u6E05\u9664\u7D22\u5F15"),t.delete(o),j(t)}return c("resolveWithCache:",o,"\u5B8C\u5168\u6CA1\u6709\u7F13\u5B58\uFF0C\u540E\u53F0\u4E0B\u8F7D"),Je(o),o}var ye={app:{title:"Playsout Mini Games",description:"Play quick games without login."},home:{loggedIn:"Logged in",logIn:"Log in",games:"Games",bannerAlt:"Playsout Games",searchPlaceholder:"Search by title or category",noGames:"No games found"},profile:{title:"Profile",settings:"Settings",language:"Language",recentGames:"Recently Played Games",noGames:"No games played yet",guest:"Guest",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"Adventure",Simulation:"Simulation",Casual:"Casual",Arcade:"Arcade",Moba:"Moba",Puzzle:"Puzzle"},auth:{loginSuccess:"Login successful!",loginTitle:"Playsout Login",welcome:"Welcome to the Playsout game platform",prompt:"Log in to start playing",mustLogin:"You must log in to play",authorizeHint:"Click the button below to authorize your login",authorizing:"Authorizing...",authorize:"Authorize login",terms:"By authorizing, you agree to our Terms of Service",signingIn:"Signing In",signMessage:"Please sign the message in your wallet"},game:{loading:"Loading",notFound:"Game not found",backHome:"Back to home",pageTitleSuffix:"Game Platform",header:{back:"Back",shareAria:"Share game",toggleMenuAria:"Toggle menu",fallbackTitle:"Game"}},menu:{favorite:"Favorite",favorited:"Favorited",profile:"Profile",login:"Login",refresh:"Refresh",loggedIn:"Logged in"},share:{title:"Share Game",closeLabel:"Close",retry:"Retry",loading:"Loading...",imageAlt:"Game share image",shareUrlLabel:"Share URL:",copied:"Copied",copy:"Copy",saveShare:"Save & Share",hint:"Image includes a QR code that links to this game",loadError:"Failed to load share image",downloadError:"Failed to download image"},checkin:{successTitle:"You got rewards!",successMessage:"Your rewards have been claimed.",failedTitle:"Check-in failed",canceledTitle:"Check-in canceled",errors:{userRejected:"You canceled the check-in operation",insufficientFunds:"Insufficient funds to pay gas",alreadyCheckedIn:"You already checked in today. Come back tomorrow!",network:"Network error. Please try again later"}},store:{title:"Gem Store",hot:"HOT",buy:"BUY",cancel:"Cancel",unit:"Gems",successTitle:"Payment Successful",successMessage:"You received {amount} gems!"},payment:{title:"Confirm Purchase",insufficientTitle:"Insufficient Balance",insufficientDesc:"Available: {gems} Gems",cancel:"Cancel",confirm:"Confirm",recharge:"Recharge",successTitle:"Payment Successful",successMessage:"{cost} <gem></gem> have been deducted."}};var ve={app:{title:"Playsout \u5C0F\u6E38\u620F",description:"\u65E0\u9700\u767B\u5F55\u5373\u53EF\u7545\u73A9\u5C0F\u6E38\u620F\u3002"},home:{loggedIn:"\u5DF2\u767B\u5F55",logIn:"\u767B\u5F55",games:"\u6E38\u620F",bannerAlt:"Playsout \u6E38\u620F",searchPlaceholder:"\u6309\u6807\u9898\u6216\u7C7B\u522B\u641C\u7D22",noGames:"\u672A\u627E\u5230\u6E38\u620F"},profile:{title:"\u4E2A\u4EBA\u4E2D\u5FC3",settings:"\u8BBE\u7F6E",language:"\u8BED\u8A00",recentGames:"\u6700\u8FD1\u73A9\u8FC7\u7684\u6E38\u620F",noGames:"\u8FD8\u6CA1\u6709\u73A9\u8FC7\u6E38\u620F",guest:"\u6E38\u5BA2",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"\u5192\u9669",Simulation:"\u6A21\u62DF",Casual:"\u4F11\u95F2",Arcade:"\u8857\u673A",Moba:"MOBA",Puzzle:"\u76CA\u667A"},auth:{loginSuccess:"\u767B\u5F55\u6210\u529F!",loginTitle:"Playsout \u767B\u5F55",welcome:"\u6B22\u8FCE\u6765\u5230 Playsout \u6E38\u620F\u5E73\u53F0",prompt:"\u767B\u5F55\u5F00\u59CB\u6E38\u620F",mustLogin:"\u60A8\u5FC5\u987B\u767B\u5F55\u624D\u80FD\u73A9\u6E38\u620F",authorizeHint:"\u70B9\u51FB\u4E0B\u65B9\u6309\u94AE\u6388\u6743\u767B\u5F55",authorizing:"\u6388\u6743\u4E2D...",authorize:"\u6388\u6743\u767B\u5F55",terms:"\u6388\u6743\u5373\u8868\u793A\u60A8\u540C\u610F\u6211\u4EEC\u7684\u670D\u52A1\u6761\u6B3E",signingIn:"\u767B\u5F55\u4E2D",signMessage:"\u8BF7\u5728\u94B1\u5305\u4E2D\u7B7E\u540D"},game:{loading:"\u52A0\u8F7D\u4E2D",notFound:"\u627E\u4E0D\u5230\u6E38\u620F",backHome:"\u8FD4\u56DE\u9996\u9875",pageTitleSuffix:"\u6E38\u620F\u5E73\u53F0",header:{back:"\u8FD4\u56DE",shareAria:"\u5206\u4EAB\u6E38\u620F",toggleMenuAria:"\u5207\u6362\u83DC\u5355",fallbackTitle:"\u6E38\u620F"}},menu:{favorite:"\u6536\u85CF",favorited:"\u5DF2\u6536\u85CF",profile:"\u4E2A\u4EBA\u4E2D\u5FC3",login:"\u767B\u5F55",refresh:"\u5237\u65B0",loggedIn:"\u5DF2\u767B\u5F55"},share:{title:"\u5206\u4EAB\u6E38\u620F",closeLabel:"\u5173\u95ED",retry:"\u91CD\u8BD5",loading:"\u52A0\u8F7D\u4E2D...",imageAlt:"\u6E38\u620F\u5206\u4EAB\u56FE\u7247",shareUrlLabel:"\u5206\u4EAB\u94FE\u63A5:",copied:"\u5DF2\u590D\u5236",copy:"\u590D\u5236",saveShare:"\u4FDD\u5B58\u5E76\u5206\u4EAB",hint:"\u56FE\u7247\u5305\u542B\u6B64\u6E38\u620F\u7684\u4E8C\u7EF4\u7801",loadError:"\u52A0\u8F7D\u5206\u4EAB\u56FE\u7247\u5931\u8D25",downloadError:"\u4E0B\u8F7D\u56FE\u7247\u5931\u8D25"},checkin:{successTitle:"\u9886\u53D6\u6210\u529F!",successMessage:"\u60A8\u7684\u5956\u52B1\u5DF2\u9886\u53D6\u3002",failedTitle:"\u7B7E\u5230\u5931\u8D25",canceledTitle:"\u7B7E\u5230\u53D6\u6D88",errors:{userRejected:"\u60A8\u53D6\u6D88\u4E86\u7B7E\u5230\u64CD\u4F5C",insufficientFunds:"\u4F59\u989D\u4E0D\u8DB3\u4EE5\u652F\u4ED8 Gas \u8D39",alreadyCheckedIn:"\u4ECA\u5929\u5DF2\u7ECF\u7B7E\u5230\u8FC7\u4E86\u3002\u660E\u5929\u518D\u6765\u5427!",network:"\u7F51\u7EDC\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5"}},store:{title:"\u5B9D\u77F3\u5546\u5E97",hot:"\u70ED\u95E8",buy:"\u8D2D\u4E70",cancel:"\u53D6\u6D88",unit:"\u5B9D\u77F3",successTitle:"\u652F\u4ED8\u6210\u529F",successMessage:"\u60A8\u83B7\u5F97\u4E86 {amount} \u5B9D\u77F3\uFF01"},payment:{title:"\u786E\u8BA4\u8D2D\u4E70",insufficientTitle:"\u4F59\u989D\u4E0D\u8DB3",insufficientDesc:"\u53EF\u7528\u4F59\u989D: {gems} \u5B9D\u77F3",cancel:"\u53D6\u6D88",confirm:"\u786E\u8BA4",recharge:"\u5145\u503C",successTitle:"\u652F\u4ED8\u6210\u529F",successMessage:"\u5DF2\u6263\u9664 {cost}<gem></gem>\u3002"}};var we={app:{title:"Playsout \u30DF\u30CB\u30B2\u30FC\u30E0",description:"\u30ED\u30B0\u30A4\u30F3\u306A\u3057\u3067\u30B2\u30FC\u30E0\u3092\u30D7\u30EC\u30A4\u3002"},home:{loggedIn:"\u30ED\u30B0\u30A4\u30F3\u6E08\u307F",logIn:"\u30ED\u30B0\u30A4\u30F3",games:"\u30B2\u30FC\u30E0",bannerAlt:"Playsout \u30B2\u30FC\u30E0",searchPlaceholder:"\u30BF\u30A4\u30C8\u30EB\u307E\u305F\u306F\u30AB\u30C6\u30B4\u30EA\u3067\u691C\u7D22",noGames:"\u30B2\u30FC\u30E0\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093"},profile:{title:"\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB",settings:"\u8A2D\u5B9A",language:"\u8A00\u8A9E",recentGames:"\u6700\u8FD1\u30D7\u30EC\u30A4\u3057\u305F\u30B2\u30FC\u30E0",noGames:"\u307E\u3060\u30D7\u30EC\u30A4\u3057\u305F\u30B2\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093",guest:"\u30B2\u30B9\u30C8",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"\u30A2\u30C9\u30D9\u30F3\u30C1\u30E3\u30FC",Simulation:"\u30B7\u30DF\u30E5\u30EC\u30FC\u30B7\u30E7\u30F3",Casual:"\u30AB\u30B8\u30E5\u30A2\u30EB",Arcade:"\u30A2\u30FC\u30B1\u30FC\u30C9",Moba:"MOBA",Puzzle:"\u30D1\u30BA\u30EB"},auth:{loginSuccess:"\u30ED\u30B0\u30A4\u30F3\u6210\u529F!",loginTitle:"Playsout \u30ED\u30B0\u30A4\u30F3",welcome:"Playsout \u30B2\u30FC\u30E0\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3078\u3088\u3046\u3053\u305D",prompt:"\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u30D7\u30EC\u30A4\u3092\u958B\u59CB",mustLogin:"\u30D7\u30EC\u30A4\u3059\u308B\u306B\u306F\u30ED\u30B0\u30A4\u30F3\u304C\u5FC5\u8981\u3067\u3059",authorizeHint:"\u4E0B\u306E\u30DC\u30BF\u30F3\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u30ED\u30B0\u30A4\u30F3\u3092\u627F\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044",authorizing:"\u627F\u8A8D\u4E2D...",authorize:"\u30ED\u30B0\u30A4\u30F3\u3092\u627F\u8A8D",terms:"\u627F\u8A8D\u3059\u308B\u3053\u3068\u3067\u3001\u5229\u7528\u898F\u7D04\u306B\u540C\u610F\u3057\u305F\u3053\u3068\u306B\u306A\u308A\u307E\u3059",signingIn:"\u30B5\u30A4\u30F3\u30A4\u30F3\u4E2D",signMessage:"\u30A6\u30A9\u30EC\u30C3\u30C8\u3067\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u7F72\u540D\u3057\u3066\u304F\u3060\u3055\u3044"},game:{loading:"\u8AAD\u307F\u8FBC\u307F\u4E2D",notFound:"\u30B2\u30FC\u30E0\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093",backHome:"\u30DB\u30FC\u30E0\u306B\u623B\u308B",pageTitleSuffix:"\u30B2\u30FC\u30E0\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0",header:{back:"\u623B\u308B",shareAria:"\u30B2\u30FC\u30E0\u3092\u5171\u6709",toggleMenuAria:"\u30E1\u30CB\u30E5\u30FC\u5207\u308A\u66FF\u3048",fallbackTitle:"\u30B2\u30FC\u30E0"}},menu:{favorite:"\u304A\u6C17\u306B\u5165\u308A",favorited:"\u304A\u6C17\u306B\u5165\u308A\u6E08\u307F",profile:"\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB",login:"\u30ED\u30B0\u30A4\u30F3",refresh:"\u66F4\u65B0",loggedIn:"\u30ED\u30B0\u30A4\u30F3\u6E08\u307F"},share:{title:"\u30B2\u30FC\u30E0\u3092\u5171\u6709",closeLabel:"\u9589\u3058\u308B",retry:"\u518D\u8A66\u884C",loading:"\u8AAD\u307F\u8FBC\u307F\u4E2D...",imageAlt:"\u30B2\u30FC\u30E0\u5171\u6709\u753B\u50CF",shareUrlLabel:"\u5171\u6709URL:",copied:"\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F",copy:"\u30B3\u30D4\u30FC",saveShare:"\u4FDD\u5B58\u3057\u3066\u5171\u6709",hint:"\u753B\u50CF\u306B\u306F\u30B2\u30FC\u30E0\u3078\u306EQR\u30B3\u30FC\u30C9\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059",loadError:"\u5171\u6709\u753B\u50CF\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",downloadError:"\u753B\u50CF\u306E\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u306B\u5931\u6557\u3057\u307E\u3057\u305F"},checkin:{successTitle:"\u5831\u916C\u3092\u7372\u5F97\u3057\u307E\u3057\u305F!",successMessage:"\u5831\u916C\u304C\u8ACB\u6C42\u3055\u308C\u307E\u3057\u305F\u3002",failedTitle:"\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u5931\u6557",canceledTitle:"\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u30AD\u30E3\u30F3\u30BB\u30EB",errors:{userRejected:"\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u64CD\u4F5C\u3092\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F",insufficientFunds:"\u30AC\u30B9\u4EE3\u3092\u652F\u6255\u3046\u6B8B\u9AD8\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059",alreadyCheckedIn:"\u672C\u65E5\u306F\u65E2\u306B\u30C1\u30A7\u30C3\u30AF\u30A4\u30F3\u6E08\u307F\u3067\u3059\u3002\u660E\u65E5\u307E\u305F\u6765\u3066\u304F\u3060\u3055\u3044!",network:"\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u3002\u5F8C\u3067\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044"}},store:{title:"\u30B8\u30A7\u30E0\u30B9\u30C8\u30A2",hot:"HOT",buy:"\u8CFC\u5165",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB",unit:"\u30B8\u30A7\u30E0",successTitle:"\u652F\u6255\u3044\u5B8C\u4E86",successMessage:"{amount}\u30B8\u30A7\u30E0\u3092\u53D7\u3051\u53D6\u308A\u307E\u3057\u305F\uFF01"},payment:{title:"\u8CFC\u5165\u78BA\u8A8D",insufficientTitle:"\u6B8B\u9AD8\u4E0D\u8DB3",insufficientDesc:"\u4FDD\u6709: {gems} \u30B8\u30A7\u30E0",cancel:"\u30AD\u30E3\u30F3\u30BB\u30EB",confirm:"\u78BA\u8A8D",recharge:"\u30C1\u30E3\u30FC\u30B8",successTitle:"\u652F\u6255\u3044\u5B8C\u4E86",successMessage:"{cost}<gem></gem>\u304C\u5DEE\u3057\u5F15\u304B\u308C\u307E\u3057\u305F\u3002"}};var ke={app:{title:"Playsout \uBBF8\uB2C8 \uAC8C\uC784",description:"\uB85C\uADF8\uC778 \uC5C6\uC774 \uAC8C\uC784\uC744 \uC990\uAE30\uC138\uC694."},home:{loggedIn:"\uB85C\uADF8\uC778\uB428",logIn:"\uB85C\uADF8\uC778",games:"\uAC8C\uC784",bannerAlt:"Playsout \uAC8C\uC784",searchPlaceholder:"\uC81C\uBAA9 \uB610\uB294 \uCE74\uD14C\uACE0\uB9AC\uB85C \uAC80\uC0C9",noGames:"\uAC8C\uC784\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4"},profile:{title:"\uD504\uB85C\uD544",settings:"\uC124\uC815",language:"\uC5B8\uC5B4",recentGames:"\uCD5C\uADFC \uD50C\uB808\uC774\uD55C \uAC8C\uC784",noGames:"\uC544\uC9C1 \uD50C\uB808\uC774\uD55C \uAC8C\uC784\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",guest:"\uC190\uB2D8",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"\uC5B4\uB4DC\uBCA4\uCC98",Simulation:"\uC2DC\uBBAC\uB808\uC774\uC158",Casual:"\uCE90\uC8FC\uC5BC",Arcade:"\uC544\uCF00\uC774\uB4DC",Moba:"MOBA",Puzzle:"\uD37C\uC990"},auth:{loginSuccess:"\uB85C\uADF8\uC778 \uC131\uACF5!",loginTitle:"Playsout \uB85C\uADF8\uC778",welcome:"Playsout \uAC8C\uC784 \uD50C\uB7AB\uD3FC\uC5D0 \uC624\uC2E0 \uAC83\uC744 \uD658\uC601\uD569\uB2C8\uB2E4",prompt:"\uAC8C\uC784\uC744 \uC2DC\uC791\uD558\uB824\uBA74 \uB85C\uADF8\uC778\uD558\uC138\uC694",mustLogin:"\uAC8C\uC784\uC744 \uD558\uB824\uBA74 \uB85C\uADF8\uC778\uD574\uC57C \uD569\uB2C8\uB2E4",authorizeHint:"\uB85C\uADF8\uC778\uC744 \uC2B9\uC778\uD558\uB824\uBA74 \uC544\uB798 \uBC84\uD2BC\uC744 \uD074\uB9AD\uD558\uC138\uC694",authorizing:"\uC2B9\uC778 \uC911...",authorize:"\uB85C\uADF8\uC778 \uC2B9\uC778",terms:"\uC2B9\uC778\uD558\uBA74 \uC11C\uBE44\uC2A4 \uC57D\uAD00\uC5D0 \uB3D9\uC758\uD558\uAC8C \uB429\uB2C8\uB2E4",signingIn:"\uB85C\uADF8\uC778 \uC911",signMessage:"\uC9C0\uAC11\uC5D0\uC11C \uBA54\uC2DC\uC9C0\uC5D0 \uC11C\uBA85\uD574\uC8FC\uC138\uC694"},game:{loading:"\uB85C\uB529 \uC911",notFound:"\uAC8C\uC784\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",backHome:"\uD648\uC73C\uB85C \uB3CC\uC544\uAC00\uAE30",pageTitleSuffix:"\uAC8C\uC784 \uD50C\uB7AB\uD3FC",header:{back:"\uB4A4\uB85C",shareAria:"\uAC8C\uC784 \uACF5\uC720",toggleMenuAria:"\uBA54\uB274 \uC804\uD658",fallbackTitle:"\uAC8C\uC784"}},menu:{favorite:"\uC990\uACA8\uCC3E\uAE30",favorited:"\uC990\uACA8\uCC3E\uAE30\uB428",profile:"\uD504\uB85C\uD544",login:"\uB85C\uADF8\uC778",refresh:"\uC0C8\uB85C\uACE0\uCE68",loggedIn:"\uB85C\uADF8\uC778\uB428"},share:{title:"\uAC8C\uC784 \uACF5\uC720",closeLabel:"\uB2EB\uAE30",retry:"\uC7AC\uC2DC\uB3C4",loading:"\uB85C\uB529 \uC911...",imageAlt:"\uAC8C\uC784 \uACF5\uC720 \uC774\uBBF8\uC9C0",shareUrlLabel:"\uACF5\uC720 URL:",copied:"\uBCF5\uC0AC\uB428",copy:"\uBCF5\uC0AC",saveShare:"\uC800\uC7A5 \uBC0F \uACF5\uC720",hint:"\uC774\uBBF8\uC9C0\uC5D0 \uAC8C\uC784\uC73C\uB85C \uC5F0\uACB0\uB418\uB294 QR \uCF54\uB4DC\uAC00 \uD3EC\uD568\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4",loadError:"\uACF5\uC720 \uC774\uBBF8\uC9C0\uB97C \uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4",downloadError:"\uC774\uBBF8\uC9C0\uB97C \uB2E4\uC6B4\uB85C\uB4DC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4"},checkin:{successTitle:"\uBCF4\uC0C1\uC744 \uBC1B\uC558\uC2B5\uB2C8\uB2E4!",successMessage:"\uBCF4\uC0C1\uC774 \uC9C0\uAE09\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",failedTitle:"\uCD9C\uC11D \uC2E4\uD328",canceledTitle:"\uCD9C\uC11D \uCDE8\uC18C\uB428",errors:{userRejected:"\uCD9C\uC11D \uC791\uC5C5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4",insufficientFunds:"\uAC00\uC2A4\uBE44\uB97C \uC9C0\uBD88\uD560 \uC790\uAE08\uC774 \uBD80\uC871\uD569\uB2C8\uB2E4",alreadyCheckedIn:"\uC624\uB298 \uC774\uBBF8 \uCD9C\uC11D\uD588\uC2B5\uB2C8\uB2E4. \uB0B4\uC77C \uB2E4\uC2DC \uC624\uC138\uC694!",network:"\uB124\uD2B8\uC6CC\uD06C \uC624\uB958. \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2DC\uB3C4\uD574 \uC8FC\uC138\uC694"}},store:{title:"\uBCF4\uC11D \uC0C1\uC810",hot:"\uC778\uAE30",buy:"\uAD6C\uB9E4",cancel:"\uCDE8\uC18C",unit:"\uBCF4\uC11D",successTitle:"\uACB0\uC81C \uC131\uACF5",successMessage:"{amount}\uAC1C\uC758 \uBCF4\uC11D\uC744 \uBC1B\uC558\uC2B5\uB2C8\uB2E4!"},payment:{title:"\uAD6C\uB9E4 \uD655\uC778",insufficientTitle:"\uC794\uC561 \uBD80\uC871",insufficientDesc:"\uBCF4\uC720: {gems} \uBCF4\uC11D",cancel:"\uCDE8\uC18C",confirm:"\uD655\uC778",recharge:"\uCDA9\uC804",successTitle:"\uACB0\uC81C \uC131\uACF5",successMessage:"{cost}<gem></gem>\uC774 \uCC28\uAC10\uB418\uC5C8\uC2B5\uB2C8\uB2E4."}};var xe={app:{title:"Playsout \u0E21\u0E34\u0E19\u0E34\u0E40\u0E01\u0E21",description:"\u0E40\u0E25\u0E48\u0E19\u0E40\u0E01\u0E21\u0E14\u0E48\u0E27\u0E19\u0E42\u0E14\u0E22\u0E44\u0E21\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A"},home:{loggedIn:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E41\u0E25\u0E49\u0E27",logIn:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A",games:"\u0E40\u0E01\u0E21",bannerAlt:"\u0E40\u0E01\u0E21 Playsout",searchPlaceholder:"\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E15\u0E32\u0E21\u0E0A\u0E37\u0E48\u0E2D\u0E2B\u0E23\u0E37\u0E2D\u0E2B\u0E21\u0E27\u0E14\u0E2B\u0E21\u0E39\u0E48",noGames:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E40\u0E01\u0E21"},profile:{title:"\u0E42\u0E1B\u0E23\u0E44\u0E1F\u0E25\u0E4C",settings:"\u0E01\u0E32\u0E23\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32",language:"\u0E20\u0E32\u0E29\u0E32",recentGames:"\u0E40\u0E01\u0E21\u0E17\u0E35\u0E48\u0E40\u0E25\u0E48\u0E19\u0E25\u0E48\u0E32\u0E2A\u0E38\u0E14",noGames:"\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E40\u0E01\u0E21\u0E17\u0E35\u0E48\u0E40\u0E25\u0E48\u0E19",guest:"\u0E1C\u0E39\u0E49\u0E40\u0E22\u0E35\u0E48\u0E22\u0E21\u0E0A\u0E21",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"\u0E1C\u0E08\u0E0D\u0E20\u0E31\u0E22",Simulation:"\u0E08\u0E33\u0E25\u0E2D\u0E07\u0E2A\u0E16\u0E32\u0E19\u0E01\u0E32\u0E23\u0E13\u0E4C",Casual:"\u0E41\u0E04\u0E0A\u0E0A\u0E27\u0E25",Arcade:"\u0E2D\u0E32\u0E23\u0E4C\u0E40\u0E04\u0E14",Moba:"\u0E42\u0E21\u0E1A\u0E32",Puzzle:"\u0E1B\u0E23\u0E34\u0E28\u0E19\u0E32"},auth:{loginSuccess:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08!",loginTitle:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A Playsout",welcome:"\u0E22\u0E34\u0E19\u0E14\u0E35\u0E15\u0E49\u0E2D\u0E19\u0E23\u0E31\u0E1A\u0E2A\u0E39\u0E48\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E40\u0E01\u0E21 Playsout",prompt:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E23\u0E34\u0E48\u0E21\u0E40\u0E25\u0E48\u0E19",mustLogin:"\u0E04\u0E38\u0E13\u0E15\u0E49\u0E2D\u0E07\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E25\u0E48\u0E19",authorizeHint:"\u0E04\u0E25\u0E34\u0E01\u0E1B\u0E38\u0E48\u0E21\u0E14\u0E49\u0E32\u0E19\u0E25\u0E48\u0E32\u0E07\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E2D\u0E19\u0E38\u0E0D\u0E32\u0E15\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A",authorizing:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E19\u0E38\u0E0D\u0E32\u0E15...",authorize:"\u0E2D\u0E19\u0E38\u0E0D\u0E32\u0E15\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A",terms:"\u0E01\u0E32\u0E23\u0E2D\u0E19\u0E38\u0E0D\u0E32\u0E15\u0E41\u0E2A\u0E14\u0E07\u0E27\u0E48\u0E32\u0E04\u0E38\u0E13\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E02\u0E49\u0E2D\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E43\u0E19\u0E01\u0E32\u0E23\u0E43\u0E2B\u0E49\u0E1A\u0E23\u0E34\u0E01\u0E32\u0E23\u0E02\u0E2D\u0E07\u0E40\u0E23\u0E32",signingIn:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E25\u0E07\u0E0A\u0E37\u0E48\u0E2D\u0E40\u0E02\u0E49\u0E32\u0E43\u0E0A\u0E49",signMessage:"\u0E01\u0E23\u0E38\u0E13\u0E32\u0E40\u0E0B\u0E47\u0E19\u0E0A\u0E37\u0E48\u0E2D\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E43\u0E19\u0E01\u0E23\u0E30\u0E40\u0E1B\u0E4B\u0E32\u0E40\u0E07\u0E34\u0E19\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"},game:{loading:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14",notFound:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E40\u0E01\u0E21",backHome:"\u0E01\u0E25\u0E31\u0E1A\u0E2B\u0E19\u0E49\u0E32\u0E2B\u0E25\u0E31\u0E01",pageTitleSuffix:"\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E40\u0E01\u0E21",header:{back:"\u0E01\u0E25\u0E31\u0E1A",shareAria:"\u0E41\u0E0A\u0E23\u0E4C\u0E40\u0E01\u0E21",toggleMenuAria:"\u0E2A\u0E25\u0E31\u0E1A\u0E40\u0E21\u0E19\u0E39",fallbackTitle:"\u0E40\u0E01\u0E21"}},menu:{favorite:"\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E42\u0E1B\u0E23\u0E14",favorited:"\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E43\u0E19\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E42\u0E1B\u0E23\u0E14\u0E41\u0E25\u0E49\u0E27",profile:"\u0E42\u0E1B\u0E23\u0E44\u0E1F\u0E25\u0E4C",login:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A",refresh:"\u0E23\u0E35\u0E40\u0E1F\u0E23\u0E0A",loggedIn:"\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E41\u0E25\u0E49\u0E27"},share:{title:"\u0E41\u0E0A\u0E23\u0E4C\u0E40\u0E01\u0E21",closeLabel:"\u0E1B\u0E34\u0E14",retry:"\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48",loading:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14...",imageAlt:"\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E\u0E41\u0E0A\u0E23\u0E4C\u0E40\u0E01\u0E21",shareUrlLabel:"\u0E41\u0E0A\u0E23\u0E4C URL:",copied:"\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E41\u0E25\u0E49\u0E27",copy:"\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01",saveShare:"\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E41\u0E25\u0E30\u0E41\u0E0A\u0E23\u0E4C",hint:"\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E\u0E23\u0E27\u0E21\u0E23\u0E2B\u0E31\u0E2A QR \u0E17\u0E35\u0E48\u0E25\u0E34\u0E07\u0E01\u0E4C\u0E44\u0E1B\u0E22\u0E31\u0E07\u0E40\u0E01\u0E21\u0E19\u0E35\u0E49",loadError:"\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E\u0E41\u0E0A\u0E23\u0E4C\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",downloadError:"\u0E14\u0E32\u0E27\u0E19\u0E4C\u0E42\u0E2B\u0E25\u0E14\u0E23\u0E39\u0E1B\u0E20\u0E32\u0E1E\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08"},checkin:{successTitle:"\u0E04\u0E38\u0E13\u0E44\u0E14\u0E49\u0E23\u0E31\u0E1A\u0E23\u0E32\u0E07\u0E27\u0E31\u0E25!",successMessage:"\u0E23\u0E31\u0E1A\u0E23\u0E32\u0E07\u0E27\u0E31\u0E25\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E41\u0E25\u0E49\u0E27",failedTitle:"\u0E40\u0E0A\u0E47\u0E04\u0E2D\u0E34\u0E19\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27",canceledTitle:"\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01\u0E40\u0E0A\u0E47\u0E04\u0E2D\u0E34\u0E19",errors:{userRejected:"\u0E04\u0E38\u0E13\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E47\u0E04\u0E2D\u0E34\u0E19",insufficientFunds:"\u0E40\u0E07\u0E34\u0E19\u0E44\u0E21\u0E48\u0E1E\u0E2D\u0E08\u0E48\u0E32\u0E22\u0E04\u0E48\u0E32\u0E41\u0E01\u0E4A\u0E2A",alreadyCheckedIn:"\u0E04\u0E38\u0E13\u0E40\u0E0A\u0E47\u0E04\u0E2D\u0E34\u0E19\u0E27\u0E31\u0E19\u0E19\u0E35\u0E49\u0E44\u0E1B\u0E41\u0E25\u0E49\u0E27 \u0E01\u0E25\u0E31\u0E1A\u0E21\u0E32\u0E43\u0E2B\u0E21\u0E48\u0E1E\u0E23\u0E38\u0E48\u0E07\u0E19\u0E35\u0E49!",network:"\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E40\u0E04\u0E23\u0E37\u0E2D\u0E02\u0E48\u0E32\u0E22 \u0E42\u0E1B\u0E23\u0E14\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E20\u0E32\u0E22\u0E2B\u0E25\u0E31\u0E07"}},store:{title:"\u0E23\u0E49\u0E32\u0E19\u0E04\u0E49\u0E32\u0E2D\u0E31\u0E0D\u0E21\u0E13\u0E35",hot:"\u0E21\u0E32\u0E41\u0E23\u0E07",buy:"\u0E0B\u0E37\u0E49\u0E2D",cancel:"\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",unit:"\u0E2D\u0E31\u0E0D\u0E21\u0E13\u0E35",successTitle:"\u0E0A\u0E33\u0E23\u0E30\u0E40\u0E07\u0E34\u0E19\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",successMessage:"\u0E04\u0E38\u0E13\u0E44\u0E14\u0E49\u0E23\u0E31\u0E1A {amount} \u0E2D\u0E31\u0E0D\u0E21\u0E13\u0E35!"},payment:{title:"\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E01\u0E32\u0E23\u0E0B\u0E37\u0E49\u0E2D",insufficientTitle:"\u0E22\u0E2D\u0E14\u0E04\u0E07\u0E40\u0E2B\u0E25\u0E37\u0E2D\u0E44\u0E21\u0E48\u0E1E\u0E2D",insufficientDesc:"\u0E21\u0E35\u0E2D\u0E22\u0E39\u0E48: {gems} \u0E2D\u0E31\u0E0D\u0E21\u0E13\u0E35",cancel:"\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",confirm:"\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19",recharge:"\u0E40\u0E15\u0E34\u0E21\u0E40\u0E07\u0E34\u0E19",successTitle:"\u0E0A\u0E33\u0E23\u0E30\u0E40\u0E07\u0E34\u0E19\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",successMessage:"\u0E2B\u0E31\u0E01 {cost} <gem></gem> \u0E41\u0E25\u0E49\u0E27"}};var Se={app:{title:"Playsout Mini Games",description:"Ch\u01A1i game nhanh kh\xF4ng c\u1EA7n \u0111\u0103ng nh\u1EADp."},home:{loggedIn:"\u0110\xE3 \u0111\u0103ng nh\u1EADp",logIn:"\u0110\u0103ng nh\u1EADp",games:"Tr\xF2 ch\u01A1i",bannerAlt:"Tr\xF2 ch\u01A1i Playsout",searchPlaceholder:"T\xECm ki\u1EBFm theo ti\xEAu \u0111\u1EC1 ho\u1EB7c danh m\u1EE5c",noGames:"Kh\xF4ng t\xECm th\u1EA5y tr\xF2 ch\u01A1i"},profile:{title:"H\u1ED3 s\u01A1",settings:"C\xE0i \u0111\u1EB7t",language:"Ng\xF4n ng\u1EEF",recentGames:"Tr\xF2 ch\u01A1i \u0111\xE3 ch\u01A1i g\u1EA7n \u0111\xE2y",noGames:"Ch\u01B0a ch\u01A1i game n\xE0o",guest:"Kh\xE1ch",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"Phi\xEAu l\u01B0u",Simulation:"M\xF4 ph\u1ECFng",Casual:"Ph\u1ED5 th\xF4ng",Arcade:"Arcade",Moba:"Moba",Puzzle:"Gi\u1EA3i \u0111\u1ED1"},auth:{loginSuccess:"\u0110\u0103ng nh\u1EADp th\xE0nh c\xF4ng!",loginTitle:"\u0110\u0103ng nh\u1EADp Playsout",welcome:"Ch\xE0o m\u1EEBng \u0111\u1EBFn v\u1EDBi n\u1EC1n t\u1EA3ng tr\xF2 ch\u01A1i Playsout",prompt:"\u0110\u0103ng nh\u1EADp \u0111\u1EC3 b\u1EAFt \u0111\u1EA7u ch\u01A1i",mustLogin:"B\u1EA1n ph\u1EA3i \u0111\u0103ng nh\u1EADp \u0111\u1EC3 ch\u01A1i",authorizeHint:"Nh\u1EA5p v\xE0o n\xFAt b\xEAn d\u01B0\u1EDBi \u0111\u1EC3 \u1EE7y quy\u1EC1n \u0111\u0103ng nh\u1EADp",authorizing:"\u0110ang \u1EE7y quy\u1EC1n...",authorize:"\u1EE6y quy\u1EC1n \u0111\u0103ng nh\u1EADp",terms:"B\u1EB1ng c\xE1ch \u1EE7y quy\u1EC1n, b\u1EA1n \u0111\u1ED3ng \xFD v\u1EDBi \u0110i\u1EC1u kho\u1EA3n d\u1ECBch v\u1EE5 c\u1EE7a ch\xFAng t\xF4i",signingIn:"\u0110ang \u0111\u0103ng nh\u1EADp",signMessage:"Vui l\xF2ng k\xFD tin nh\u1EAFn trong v\xED c\u1EE7a b\u1EA1n"},game:{loading:"\u0110ang t\u1EA3i",notFound:"Kh\xF4ng t\xECm th\u1EA5y tr\xF2 ch\u01A1i",backHome:"V\u1EC1 trang ch\u1EE7",pageTitleSuffix:"N\u1EC1n t\u1EA3ng tr\xF2 ch\u01A1i",header:{back:"Quay l\u1EA1i",shareAria:"Chia s\u1EBB tr\xF2 ch\u01A1i",toggleMenuAria:"Chuy\u1EC3n \u0111\u1ED5i menu",fallbackTitle:"Tr\xF2 ch\u01A1i"}},menu:{favorite:"Y\xEAu th\xEDch",favorited:"\u0110\xE3 y\xEAu th\xEDch",profile:"H\u1ED3 s\u01A1",login:"\u0110\u0103ng nh\u1EADp",refresh:"L\xE0m m\u1EDBi",loggedIn:"\u0110\xE3 \u0111\u0103ng nh\u1EADp"},share:{title:"Chia s\u1EBB tr\xF2 ch\u01A1i",closeLabel:"\u0110\xF3ng",retry:"Th\u1EED l\u1EA1i",loading:"\u0110ang t\u1EA3i...",imageAlt:"H\xECnh \u1EA3nh chia s\u1EBB tr\xF2 ch\u01A1i",shareUrlLabel:"URL chia s\u1EBB:",copied:"\u0110\xE3 sao ch\xE9p",copy:"Sao ch\xE9p",saveShare:"L\u01B0u & Chia s\u1EBB",hint:"H\xECnh \u1EA3nh bao g\u1ED3m m\xE3 QR li\xEAn k\u1EBFt \u0111\u1EBFn tr\xF2 ch\u01A1i n\xE0y",loadError:"Kh\xF4ng t\u1EA3i \u0111\u01B0\u1EE3c h\xECnh \u1EA3nh chia s\u1EBB",downloadError:"Kh\xF4ng t\u1EA3i xu\u1ED1ng \u0111\u01B0\u1EE3c h\xECnh \u1EA3nh"},checkin:{successTitle:"B\u1EA1n \u0111\xE3 nh\u1EADn ph\u1EA7n th\u01B0\u1EDFng!",successMessage:"Ph\u1EA7n th\u01B0\u1EDFng c\u1EE7a b\u1EA1n \u0111\xE3 \u0111\u01B0\u1EE3c nh\u1EADn.",failedTitle:"\u0110i\u1EC3m danh th\u1EA5t b\u1EA1i",canceledTitle:"\u0110i\u1EC3m danh \u0111\xE3 h\u1EE7y",errors:{userRejected:"B\u1EA1n \u0111\xE3 h\u1EE7y thao t\xE1c \u0111i\u1EC3m danh",insufficientFunds:"Kh\xF4ng \u0111\u1EE7 ti\u1EC1n \u0111\u1EC3 tr\u1EA3 ph\xED Gas",alreadyCheckedIn:"H\xF4m nay b\u1EA1n \u0111\xE3 \u0111i\u1EC3m danh r\u1ED3i. H\xE3y quay l\u1EA1i v\xE0o ng\xE0y mai!",network:"L\u1ED7i m\u1EA1ng. Vui l\xF2ng th\u1EED l\u1EA1i sau"}},store:{title:"C\u1EEDa h\xE0ng \u0110\xE1 qu\xFD",hot:"HOT",buy:"MUA",cancel:"H\u1EE7y",unit:"\u0110\xE1 qu\xFD",successTitle:"Thanh to\xE1n th\xE0nh c\xF4ng",successMessage:"B\u1EA1n \u0111\xE3 nh\u1EADn \u0111\u01B0\u1EE3c {amount} \u0111\xE1 qu\xFD!"},payment:{title:"X\xE1c nh\u1EADn mua",insufficientTitle:"S\u1ED1 d\u01B0 kh\xF4ng \u0111\u1EE7",insufficientDesc:"Hi\u1EC7n c\xF3: {gems} \u0110\xE1 qu\xFD",cancel:"H\u1EE7y",confirm:"X\xE1c nh\u1EADn",recharge:"N\u1EA1p ti\u1EC1n",successTitle:"Thanh to\xE1n th\xE0nh c\xF4ng",successMessage:"\u0110\xE3 tr\u1EEB {cost} <gem></gem>."}};var Te={app:{title:"Playsout Mini Games",description:"Mainkan game cepat tanpa login."},home:{loggedIn:"Sudah login",logIn:"Login",games:"Game",bannerAlt:"Game Playsout",searchPlaceholder:"Cari berdasarkan judul atau kategori",noGames:"Game tidak ditemukan"},profile:{title:"Profil",settings:"Pengaturan",language:"Bahasa",recentGames:"Game yang Baru Dimainkan",noGames:"Belum ada game yang dimainkan",guest:"Tamu",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"Petualangan",Simulation:"Simulasi",Casual:"Kasual",Arcade:"Arcade",Moba:"Moba",Puzzle:"Teka-teki"},auth:{loginSuccess:"Login berhasil!",loginTitle:"Login Playsout",welcome:"Selamat datang di platform game Playsout",prompt:"Login untuk mulai bermain",mustLogin:"Anda harus login untuk bermain",authorizeHint:"Klik tombol di bawah untuk mengotorisasi login",authorizing:"Mengotorisasi...",authorize:"Otorisasi login",terms:"Dengan mengotorisasi, Anda menyetujui Ketentuan Layanan kami",signingIn:"Masuk...",signMessage:"Silakan tanda tangani pesan di dompet Anda"},game:{loading:"Memuat",notFound:"Game tidak ditemukan",backHome:"Kembali ke beranda",pageTitleSuffix:"Platform Game",header:{back:"Kembali",shareAria:"Bagikan game",toggleMenuAria:"Alihkan menu",fallbackTitle:"Game"}},menu:{favorite:"Favorit",favorited:"Difavoritkan",profile:"Profil",login:"Login",refresh:"Segarkan",loggedIn:"Sudah login"},share:{title:"Bagikan Game",closeLabel:"Tutup",retry:"Coba lagi",loading:"Memuat...",imageAlt:"Gambar berbagi game",shareUrlLabel:"URL Berbagi:",copied:"Disalin",copy:"Salin",saveShare:"Simpan & Bagikan",hint:"Gambar termasuk kode QR yang menautkan ke game ini",loadError:"Gagal memuat gambar berbagi",downloadError:"Gagal mengunduh gambar"},checkin:{successTitle:"Anda mendapat hadiah!",successMessage:"Hadiah Anda telah diklaim.",failedTitle:"Check-in gagal",canceledTitle:"Check-in dibatalkan",errors:{userRejected:"Anda membatalkan operasi check-in",insufficientFunds:"Dana tidak cukup untuk membayar biaya Gas",alreadyCheckedIn:"Anda sudah check-in hari ini. Kembali lagi besok!",network:"Kesalahan jaringan. Silakan coba lagi nanti"}},store:{title:"Toko Permata",hot:"HOT",buy:"BELI",cancel:"Batal",unit:"Permata",successTitle:"Pembayaran Berhasil",successMessage:"Anda menerima {amount} permata!"},payment:{title:"Konfirmasi Pembelian",insufficientTitle:"Saldo Tidak Cukup",insufficientDesc:"Tersedia: {gems} Permata",cancel:"Batal",confirm:"Konfirmasi",recharge:"Isi Ulang",successTitle:"Pembayaran Berhasil",successMessage:"{cost} <gem></gem> telah dikurangi."}};var Ie={app:{title:"Permainan Mini Playsout",description:"Main permainan pantas tanpa log masuk."},home:{loggedIn:"Log masuk",logIn:"Log masuk",games:"Permainan",bannerAlt:"Permainan Playsout",searchPlaceholder:"Cari mengikut tajuk atau kategori",noGames:"Tiada permainan dijumpai"},profile:{title:"Profil",settings:"Tetapan",language:"Bahasa",recentGames:"Permainan Baru Dimainkan",noGames:"Belum ada permainan dimainkan",guest:"Pelawat",languages:{en:"English",zh:"\u4E2D\u6587",ja:"\u65E5\u672C\u8A9E",ko:"\uD55C\uAD6D\uC5B4",th:"\u0E44\u0E17\u0E22",vi:"Ti\u1EBFng Vi\u1EC7t",id:"Bahasa Indonesia",ms:"Bahasa Melayu",es:"Espa\xF1ol"}},categories:{Adventure:"Pengembaraan",Simulation:"Simulasi",Casual:"Santai",Arcade:"Arked",Moba:"Moba",Puzzle:"Teka-teki"},auth:{loginSuccess:"Log masuk berjaya!",loginTitle:"Log masuk Playsout",welcome:"Selamat datang ke platform permainan Playsout",prompt:"Log masuk untuk mula bermain",mustLogin:"Anda mesti log masuk untuk bermain",authorizeHint:"Klik butang di bawah untuk membenarkan log masuk",authorizing:"Membenarkan...",authorize:"Benarkan log masuk",terms:"Dengan membenarkan, anda bersetuju dengan Syarat Perkhidmatan kami",signingIn:"Sedang log masuk",signMessage:"Sila tandatangan mesej dalam dompet anda"},game:{loading:"Memuatkan",notFound:"Permainan tidak dijumpai",backHome:"Kembali ke laman utama",pageTitleSuffix:"Platform Permainan",header:{back:"Kembali",shareAria:"Kongsi permainan",toggleMenuAria:"Togol menu",fallbackTitle:"Permainan"}},menu:{favorite:"Kegemaran",favorited:"Dikegemarankan",profile:"Profil",login:"Log masuk",refresh:"Muat semula",loggedIn:"Log masuk"},share:{title:"Kongsi Permainan",closeLabel:"Tutup",retry:"Cuba lagi",loading:"Memuatkan...",imageAlt:"Imej kongsi permainan",shareUrlLabel:"URL Kongsi:",copied:"Disalin",copy:"Salin",saveShare:"Simpan & Kongsi",hint:"Imej termasuk kod QR yang memaut ke permainan ini",loadError:"Gagal memuatkan imej kongsi",downloadError:"Gagal memuat turun imej"},checkin:{successTitle:"Anda mendapat ganjaran!",successMessage:"Ganjaran anda telah dituntut.",failedTitle:"Daftar masuk gagal",canceledTitle:"Daftar masuk dibatalkan",errors:{userRejected:"Anda membatalkan operasi daftar masuk",insufficientFunds:"Dana tidak mencukupi untuk membayar yuran Gas",alreadyCheckedIn:"Anda sudah daftar masuk hari ini. Kembali lagi esok!",network:"Ralat rangkaian. Sila cuba lagi kemudian"}},store:{title:"Kedai Permata",hot:"HOT",buy:"BELI",cancel:"Batal",unit:"Permata",successTitle:"Pembayaran Berjaya",successMessage:"Anda menerima {amount} permata!"},payment:{title:"Sahkan Pembelian",insufficientTitle:"Baki Tidak Mencukupi",insufficientDesc:"Tersedia: {gems} Permata",cancel:"Batal",confirm:"Sahkan",recharge:"Tambah Nilai",successTitle:"Pembayaran Berjaya",successMessage:"{cost} <gem></gem> telah ditolak."}};var P=o=>{if(typeof window>"u")return o;let t=s(o);return be(t)},rt="https://games.playsout.com/resources/icon/fonts",K=o=>{if(typeof window>"u")return o;let t=o.replace(/^\.\//,"");return`${rt}/${t}`},R={en:ye,zh:ve,ja:we,ko:ke,th:xe,vi:Se,id:Te,ms:Ie};function ae(o,t){let e=t.split("."),a=o;for(let i of e)if(a&&typeof a=="object"&&i in a)a=a[i];else return t;return typeof a=="string"?a:t}function Ae(o,t={}){return o.replace(/\{(\w+)\}/g,(e,a)=>String(t[a]??`{${a}}`))}var Ee=`
2
+ :root {
3
+ --playsout-primary: #6366f1;
4
+ --playsout-bg: #0f1419;
5
+ --playsout-bg-card: #1e2a3a;
6
+ --playsout-text: #f8fafc;
7
+ --playsout-text-muted: #94a3b8;
8
+ --playsout-border: #334155;
9
+ --playsout-radius: 8px;
10
+ --playsout-padding: 12px;
11
+ }
12
+
13
+ /* Adelle Sans \u5B57\u4F53 */
14
+ @font-face {
15
+ font-family: "Adelle Sans";
16
+ src: url('${K("./AdelleSans-Regular.woff2")}') format('woff2'),
17
+ url('${K("./AdelleSans-Regular.woff")}') format('woff');
18
+ font-style: normal;
19
+ font-display: swap;
20
+ font-weight: 300;
21
+ }
22
+ @font-face {
23
+ font-family: "Adelle Sans";
24
+ src: url('${K("./AdelleSans-Semibold.woff2")}') format('woff2'),
25
+ url('${K("./AdelleSans-Semibold.woff")}') format('woff');
26
+ font-style: normal;
27
+ font-display: swap;
28
+ font-weight: 600;
29
+ }
30
+
31
+ /* \u5168\u5C40\u5B57\u4F53 + \u80CC\u666F */
32
+ * {
33
+ box-sizing: border-box;
34
+ margin: 0;
35
+ padding: 0;
36
+ font-family: "Adelle Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
37
+ }
38
+
39
+ /* \u684C\u9762\u7AEF\u5916\u5C42\u5BB9\u5668\uFF1A\u5C45\u4E2D + \u6E10\u53D8\u80CC\u666F */
40
+ @media (min-width: 769px) {
41
+ body {
42
+ background: linear-gradient(135deg, #1e3a8a 0%, #1e1b4b 50%, #0f1419 100%);
43
+ background-attachment: fixed;
44
+ }
45
+ }
46
+
47
+ /* \u79FB\u52A8\u7AEF\u6EDA\u52A8\u5BB9\u5668 */
48
+ .playsout-scroll-container {
49
+ min-height: 100vh;
50
+ overflow-y: auto;
51
+ -webkit-overflow-scrolling: touch;
52
+ scrollbar-width: none;
53
+ -ms-overflow-style: none;
54
+ }
55
+ .playsout-scroll-container::-webkit-scrollbar {
56
+ display: none;
57
+ }
58
+
59
+ /* mobile-container: \u4E0E demo \u5B8C\u5168\u4E00\u81F4 */
60
+ .mobile-container {
61
+ max-width: 414px; /* iPhone 13 Pro Max \u5BBD\u5EA6\uFF0C\u4E0E demo \u4E00\u81F4 */
62
+ margin: 0 auto;
63
+ background-color: #0f1419;
64
+ min-height: 100vh;
65
+ position: relative;
66
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
67
+ border-radius: 0.25rem; /* rounded-md */
68
+ }
69
+
70
+ @media (max-width: 768px) {
71
+ .mobile-container {
72
+ max-width: none;
73
+ margin: 0;
74
+ box-shadow: none;
75
+ border-radius: 0;
76
+ }
77
+ }
78
+
79
+ .playsout-widget {
80
+ background: var(--playsout-bg);
81
+ color: var(--playsout-text);
82
+ min-height: 100vh;
83
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
84
+ }
85
+
86
+ /* Header */
87
+ .widget-header {
88
+ display: flex;
89
+ align-items: center;
90
+ justify-content: space-between;
91
+ padding: 1rem 1rem; /* py-4 px-4 */
92
+ background: var(--playsout-bg);
93
+ position: sticky;
94
+ top: 0;
95
+ z-index: 100;
96
+ }
97
+
98
+ .widget-logo {
99
+ display: flex;
100
+ align-items: center;
101
+ gap: 4px;
102
+ }
103
+
104
+ .widget-logo img {
105
+ width: 40px;
106
+ height: 32px;
107
+ object-fit: contain;
108
+ }
109
+
110
+ .widget-user {
111
+ display: flex;
112
+ align-items: center;
113
+ gap: 0.75rem; /* gap-3 */
114
+ }
115
+
116
+ /* Gems Button: demo \u98CE\u683C */
117
+ .widget-gems-btn {
118
+ display: flex;
119
+ align-items: center;
120
+ gap: 0.375rem; /* gap-1.5 */
121
+ padding: 0.375rem 0.75rem; /* py-1.5 px-3 */
122
+ border-radius: 9999px; /* rounded-full */
123
+ background: #1a1a1a;
124
+ border: 1px solid #2a2a2a;
125
+ color: #94a3b8;
126
+ cursor: pointer;
127
+ transition: background 0.15s;
128
+ }
129
+ .widget-gems-btn:hover {
130
+ background: #2a3b50;
131
+ }
132
+ .widget-gems-amount {
133
+ font-size: 0.875rem; /* text-sm */
134
+ font-weight: 700;
135
+ color: white;
136
+ }
137
+ .widget-gems-icon {
138
+ color: #a855f7; /* \u7D2B\u8272 */
139
+ width: 1rem;
140
+ height: 1rem;
141
+ fill: #a855f7;
142
+ }
143
+
144
+ /* Profile Button: demo \u98CE\u683C */
145
+ .widget-profile-btn {
146
+ display: flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ width: 2.5rem; /* w-10 */
150
+ height: 2.5rem; /* h-10 */
151
+ border-radius: 50%;
152
+ background: #1e2a3a;
153
+ cursor: pointer;
154
+ transition: background 0.15s;
155
+ border: none;
156
+ }
157
+ .widget-profile-btn:hover {
158
+ background: #2a3b50;
159
+ }
160
+ .widget-profile-btn svg {
161
+ width: 1.25rem; /* w-5 h-5 */
162
+ height: 1.25rem;
163
+ color: #94a3b8;
164
+ }
165
+
166
+ /* Banner */
167
+ .widget-banner {
168
+ padding: 0 1rem 1.5rem; /* px-4 pb-6\uFF0C\u4E0E demo \u4E00\u81F4 */
169
+ }
170
+
171
+ .banner-image {
172
+ width: 100%;
173
+ height: auto;
174
+ aspect-ratio: 750 / 300;
175
+ object-fit: cover;
176
+ border-radius: 1rem; /* rounded-2xl */
177
+ border: 1px solid #1e2a3a; /* border-game-card */
178
+ background: #1e2a3a;
179
+ display: block;
180
+ user-select: none;
181
+ -webkit-user-drag: none;
182
+ }
183
+
184
+ /* Search */
185
+ .widget-search {
186
+ padding: 0 1rem 1.5rem; /* px-4 pb-6 */
187
+ position: relative;
188
+ }
189
+
190
+ .search-wrapper {
191
+ position: relative;
192
+ display: flex;
193
+ align-items: center;
194
+ }
195
+
196
+ .search-icon {
197
+ position: absolute;
198
+ left: 14px;
199
+ top: 50%;
200
+ transform: translateY(-50%);
201
+ color: #94a3b8;
202
+ pointer-events: none;
203
+ display: flex;
204
+ align-items: center;
205
+ }
206
+
207
+ .search-input {
208
+ width: 100%;
209
+ background: #1a1a1a;
210
+ color: white;
211
+ border: 1px solid #2a2a2a;
212
+ border-radius: 1rem; /* rounded-2xl */
213
+ padding: 0.875rem 1rem 0.875rem 2.75rem; /* py-3.5 pl-11 */
214
+ font-size: 0.875rem;
215
+ outline: none;
216
+ transition: border-color 0.2s;
217
+ -webkit-appearance: none;
218
+ }
219
+
220
+ .search-input:focus {
221
+ border-color: #06b6d4; /* focus:border-cyan-500 */
222
+ }
223
+
224
+ .search-input::placeholder {
225
+ color: #6b7280; /* placeholder-gray-500 */
226
+ }
227
+
228
+ /* \u53F3\u4FA7 Search \u6309\u94AE\uFF08\u4E0E demo \u4E00\u81F4\uFF09 */
229
+ .search-btn {
230
+ position: absolute;
231
+ right: 0.5rem; /* right-2 */
232
+ top: 50%;
233
+ transform: translateY(-50%);
234
+ width: 2.25rem; /* w-9 */
235
+ height: 2.25rem; /* h-9 */
236
+ border-radius: 0.75rem; /* rounded-xl */
237
+ background: #2a3b50;
238
+ border: none;
239
+ cursor: pointer;
240
+ display: flex;
241
+ align-items: center;
242
+ justify-content: center;
243
+ color: #22d3ee; /* text-cyan-400 */
244
+ transition: background 0.15s;
245
+ }
246
+ .search-btn:hover {
247
+ background: #374151;
248
+ }
249
+
250
+ /* Categories */
251
+ .widget-categories {
252
+ padding: 0 1rem 2rem; /* px-4 mb-8 */
253
+ }
254
+
255
+ .categories-wrapper {
256
+ display: flex;
257
+ flex-wrap: wrap;
258
+ gap: 0.75rem; /* gap-3 */
259
+ }
260
+
261
+ .category-btn {
262
+ flex-shrink: 0;
263
+ display: flex;
264
+ align-items: center;
265
+ gap: 0.5rem; /* gap-2 */
266
+ padding: 0.375rem 0.75rem; /* py-1.5 px-3 */
267
+ border-radius: 9999px; /* rounded-full */
268
+ border: 1px solid transparent;
269
+ font-size: 0.875rem; /* text-sm */
270
+ font-weight: 500;
271
+ cursor: pointer;
272
+ transition: all 0.15s;
273
+ background: #1E232F;
274
+ white-space: nowrap;
275
+ }
276
+
277
+ .category-btn:hover {
278
+ border-color: rgba(255, 255, 255, 0.1);
279
+ }
280
+
281
+ .category-btn.active {
282
+ background: #1E232F;
283
+ border-color: rgba(6, 182, 212, 0.5); /* border-cyan-500/50 */
284
+ }
285
+
286
+ .category-btn.active .category-label {
287
+ color: white;
288
+ }
289
+
290
+ .category-icon {
291
+ width: 1rem; /* w-4 */
292
+ height: 1rem; /* h-4 */
293
+ display: flex;
294
+ align-items: center;
295
+ justify-content: center;
296
+ }
297
+
298
+ .category-label {
299
+ color: #9ca3af; /* text-gray-400 */
300
+ transition: color 0.15s;
301
+ }
302
+
303
+ /* Games Section */
304
+ .widget-games {
305
+ padding: 0 1rem 1rem; /* px-4 pb-4 */
306
+ }
307
+
308
+ .section-title {
309
+ font-size: 1rem; /* text-base \u2248 16px */
310
+ font-weight: 600;
311
+ margin-bottom: 1rem; /* mb-4 */
312
+ color: #94a3b8; /* text-game-text */
313
+ }
314
+
315
+ .games-grid {
316
+ display: grid;
317
+ grid-template-columns: repeat(2, 1fr);
318
+ gap: 0.5rem; /* gap-2\uFF088px\uFF09\uFF0C\u4E0E demo \u4E00\u81F4 */
319
+ }
320
+
321
+ /* Game Card: \u4E0E demo globals.css \u4E00\u81F4 */
322
+ .game-card {
323
+ background: #1e2a3a; /* bg-game-card */
324
+ border-radius: 0.75rem; /* rounded-xl */
325
+ overflow: hidden;
326
+ cursor: pointer;
327
+ user-select: none;
328
+ -webkit-user-select: none;
329
+ transition: transform 0.2s;
330
+ display: flex;
331
+ flex-direction: column;
332
+ }
333
+
334
+ .game-card:hover {
335
+ transform: translateY(-2px); /* -translate-y-0.5 \u2248 2px */
336
+ }
337
+
338
+ .game-image-wrapper {
339
+ position: relative;
340
+ width: 100%;
341
+ aspect-ratio: 1; /* 1:1 \u65B9\u5F62\uFF0C\u4E0E demo \u4E00\u81F4 */
342
+ flex-shrink: 0;
343
+ overflow: hidden;
344
+ }
345
+
346
+ .game-image {
347
+ width: 100%;
348
+ height: 100%;
349
+ object-fit: cover;
350
+ background: #1e2a3a;
351
+ user-select: none;
352
+ -webkit-user-drag: none;
353
+ }
354
+
355
+ /* NEW/HOT \u5FBD\u6807\uFF1A\u4E0E\u6807\u9898\u540C\u4E00\u884C */
356
+ .title-row {
357
+ display: flex;
358
+ align-items: center;
359
+ gap: 0.5rem; /* gap-2 */
360
+ height: 1rem; /* height: 16px */
361
+ min-height: 1rem;
362
+ overflow: visible;
363
+ }
364
+
365
+ .game-tag {
366
+ font-size: 0.5rem; /* text-[8px] */
367
+ font-weight: 700;
368
+ padding: 2px 3px;
369
+ border-radius: 3px;
370
+ flex-shrink: 0;
371
+ text-transform: uppercase;
372
+ line-height: 1;
373
+ }
374
+
375
+ .game-tag.new {
376
+ background: #dc2626; /* \u7EA2\u8272\uFF0C\u4E0E demo \u4E00\u81F4 */
377
+ color: white;
378
+ }
379
+
380
+ .game-tag.hot {
381
+ background: #f59e0b; /* \u6A59\u8272\uFF0C\u4E0E demo \u4E00\u81F4 */
382
+ color: white;
383
+ }
384
+
385
+ .game-info {
386
+ padding: 6px;
387
+ flex-shrink: 0;
388
+ display: flex;
389
+ flex-direction: column;
390
+ background-color: rgba(30, 42, 58, 0.95); /* \u4E0E demo \u5B8C\u5168\u4E00\u81F4 */
391
+ }
392
+
393
+ .game-title {
394
+ font-size: 0.6875rem; /* text-[11px] */
395
+ font-weight: 600;
396
+ color: white;
397
+ margin: 0;
398
+ white-space: nowrap;
399
+ overflow: hidden;
400
+ text-overflow: ellipsis;
401
+ line-height: 1rem; /* line-height: 16px */
402
+ user-select: text;
403
+ -webkit-user-select: text;
404
+ }
405
+
406
+ .divider {
407
+ height: 1px;
408
+ background-color: #2a3b50; /* \u4E0E demo divider \u4E00\u81F4 */
409
+ margin: 4px 0;
410
+ }
411
+
412
+ .game-category {
413
+ font-size: 0.5625rem; /* text-[9px] */
414
+ color: #64748b;
415
+ margin: 0;
416
+ line-height: 0.75rem; /* line-height: 12px */
417
+ text-align: left;
418
+ user-select: text;
419
+ -webkit-user-select: text;
420
+ }
421
+
422
+ /* Empty State */
423
+ .empty-state {
424
+ text-align: center;
425
+ padding: 48px 16px;
426
+ color: var(--playsout-text-muted);
427
+ }
428
+
429
+ .empty-state-icon {
430
+ font-size: 48px;
431
+ margin-bottom: 16px;
432
+ }
433
+
434
+ /* Loading */
435
+ .loading {
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ min-height: 200px;
440
+ color: var(--playsout-text-muted);
441
+ }
442
+
443
+ .loading-spinner {
444
+ width: 32px;
445
+ height: 32px;
446
+ border: 3px solid var(--playsout-border);
447
+ border-top-color: var(--playsout-primary);
448
+ border-radius: 50%;
449
+ animation: spin 1s linear infinite;
450
+ }
451
+
452
+ @keyframes spin {
453
+ to {
454
+ transform: rotate(360deg);
455
+ }
456
+ }
457
+
458
+ /* No Results */
459
+ .no-results {
460
+ text-align: center;
461
+ padding: 48px 16px;
462
+ color: var(--playsout-text-muted);
463
+ }
464
+
465
+ /* ========== Store Modal ========== */
466
+ .store-modal-overlay {
467
+ position: fixed;
468
+ inset: 0;
469
+ z-index: 1000;
470
+ background: rgba(0, 0, 0, 0.6);
471
+ backdrop-filter: blur(4px);
472
+ -webkit-backdrop-filter: blur(4px);
473
+ display: flex;
474
+ align-items: flex-end;
475
+ justify-content: center;
476
+ animation: modalFadeIn 0.2s ease-out;
477
+ }
478
+
479
+ /* ========== Profile Modal ========== */
480
+ .profile-modal-overlay {
481
+ position: fixed;
482
+ inset: 0;
483
+ z-index: 1000;
484
+ background: rgba(0, 0, 0, 0.6);
485
+ backdrop-filter: blur(4px);
486
+ -webkit-backdrop-filter: blur(4px);
487
+ display: flex;
488
+ align-items: flex-end;
489
+ justify-content: center;
490
+ animation: modalFadeIn 0.2s ease-out;
491
+ }
492
+
493
+ .profile-modal {
494
+ width: 100%;
495
+ max-width: 28rem;
496
+ background: #111827;
497
+ border-top: 1px solid #374151;
498
+ border-radius: 1.5rem 1.5rem 0 0;
499
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
500
+ display: flex;
501
+ flex-direction: column;
502
+ max-height: 90vh;
503
+ animation: modalSlideUp 0.3s ease-out;
504
+ }
505
+
506
+ @media (min-width: 640px) {
507
+ .profile-modal {
508
+ border-radius: 1.5rem;
509
+ margin: 1rem;
510
+ }
511
+ }
512
+
513
+ .profile-modal-header {
514
+ display: flex;
515
+ align-items: center;
516
+ justify-content: space-between;
517
+ padding: 0.75rem 1rem;
518
+ border-bottom: 1px solid #374151;
519
+ }
520
+
521
+ .profile-modal-title {
522
+ font-size: 1.125rem;
523
+ font-weight: 700;
524
+ color: white;
525
+ }
526
+
527
+ .profile-modal-close {
528
+ background: none;
529
+ border: none;
530
+ color: #9ca3af;
531
+ font-size: 1.25rem;
532
+ cursor: pointer;
533
+ padding: 0.25rem;
534
+ line-height: 1;
535
+ }
536
+ .profile-modal-close:hover {
537
+ color: white;
538
+ }
539
+
540
+ .profile-modal-content {
541
+ flex: 1;
542
+ overflow-y: auto;
543
+ padding: 1rem;
544
+ display: flex;
545
+ flex-direction: column;
546
+ gap: 1.5rem;
547
+ }
548
+
549
+ .profile-section {
550
+ display: flex;
551
+ flex-direction: column;
552
+ gap: 0.75rem;
553
+ }
554
+
555
+ .profile-section-title {
556
+ font-size: 1rem;
557
+ font-weight: 600;
558
+ color: #e5e7eb;
559
+ border-left: 3px solid #06b6d4;
560
+ padding-left: 0.75rem;
561
+ }
562
+
563
+ .profile-recent-games {
564
+ display: flex;
565
+ overflow-x: auto;
566
+ gap: 1rem;
567
+ padding: 0.25rem 1rem 1rem;
568
+ margin: 0 -1rem;
569
+ scrollbar-width: none;
570
+ }
571
+ .profile-recent-games::-webkit-scrollbar {
572
+ display: none;
573
+ }
574
+
575
+ .profile-recent-game {
576
+ flex-shrink: 0;
577
+ width: 5.25rem;
578
+ display: flex;
579
+ flex-direction: column;
580
+ gap: 0.5rem;
581
+ cursor: pointer;
582
+ }
583
+
584
+ @media (min-width: 640px) {
585
+ .profile-recent-game {
586
+ width: 11rem;
587
+ }
588
+ }
589
+
590
+ .profile-recent-game-image {
591
+ width: 100%;
592
+ aspect-ratio: 1;
593
+ border-radius: 1rem;
594
+ object-fit: cover;
595
+ background: #2a2a2a;
596
+ border: 1px solid #2a2a2a;
597
+ transition: transform 0.15s;
598
+ }
599
+
600
+ .profile-recent-game:active .profile-recent-game-image {
601
+ transform: scale(0.98);
602
+ }
603
+
604
+ .profile-recent-info {
605
+ min-width: 0;
606
+ }
607
+
608
+ .profile-recent-title {
609
+ font-size: 0.875rem;
610
+ font-weight: 500;
611
+ color: white;
612
+ overflow: hidden;
613
+ text-overflow: ellipsis;
614
+ white-space: nowrap;
615
+ }
616
+
617
+ @media (min-width: 640px) {
618
+ .profile-recent-title {
619
+ font-size: 1rem;
620
+ }
621
+ }
622
+
623
+ .profile-recent-category {
624
+ font-size: 0.75rem;
625
+ color: #6b7280;
626
+ overflow: hidden;
627
+ text-overflow: ellipsis;
628
+ white-space: nowrap;
629
+ }
630
+
631
+ @media (min-width: 640px) {
632
+ .profile-recent-category {
633
+ font-size: 0.875rem;
634
+ }
635
+ }
636
+
637
+ .profile-no-games {
638
+ text-align: center;
639
+ padding: 2.5rem;
640
+ color: #6b7280;
641
+ font-size: 0.875rem;
642
+ background: #1a1a1a;
643
+ border-radius: 0.75rem;
644
+ border: 1px dashed #2a2a2a;
645
+ }
646
+
647
+ /* \u7528\u6237\u4FE1\u606F\u5FBD\u7AE0\uFF08\u7B80\u6D01\u98CE\u683C\uFF09 */
648
+ .profile-user-badge {
649
+ display: inline-flex;
650
+ align-items: center;
651
+ gap: 0.5rem;
652
+ padding: 0.625rem 1rem;
653
+ background: linear-gradient(135deg, rgba(99, 102, 241, 0.15), rgba(139, 92, 246, 0.15));
654
+ border: 1px solid rgba(99, 102, 241, 0.3);
655
+ border-radius: 2rem;
656
+ margin-bottom: 1.25rem;
657
+ }
658
+
659
+ .profile-user-icon {
660
+ width: 1.25rem;
661
+ height: 1.25rem;
662
+ color: #a5b4fc;
663
+ flex-shrink: 0;
664
+ }
665
+
666
+ .profile-username-text {
667
+ font-size: 0.9375rem;
668
+ font-weight: 600;
669
+ color: #e0e7ff;
670
+ }
671
+
672
+ .profile-settings {
673
+ background: #1a1a1a;
674
+ border-radius: 0.75rem;
675
+ border: 1px solid #2a2a2a;
676
+ overflow: hidden;
677
+ }
678
+
679
+ .profile-setting-item {
680
+ display: flex;
681
+ align-items: center;
682
+ justify-content: space-between;
683
+ padding: 1rem;
684
+ cursor: pointer;
685
+ transition: background 0.15s;
686
+ }
687
+
688
+ .profile-setting-item:hover {
689
+ background: #252525;
690
+ }
691
+
692
+ .profile-setting-label {
693
+ color: white;
694
+ font-weight: 500;
695
+ font-size: 0.875rem;
696
+ }
697
+
698
+ .profile-setting-value {
699
+ display: flex;
700
+ align-items: center;
701
+ gap: 0.5rem;
702
+ color: #9ca3af;
703
+ font-size: 0.875rem;
704
+ }
705
+
706
+ .profile-language-select {
707
+ background: transparent;
708
+ border: none;
709
+ color: #9ca3af;
710
+ font-size: 0.875rem;
711
+ cursor: pointer;
712
+ padding: 0.25rem;
713
+ }
714
+
715
+ .profile-language-select option {
716
+ background: #1a1a1a;
717
+ color: white;
718
+ }
719
+
720
+ /* ========== Language Select Modal ========== */
721
+ .language-modal-overlay {
722
+ position: fixed;
723
+ inset: 0;
724
+ z-index: 1001;
725
+ background: rgba(0, 0, 0, 0.5);
726
+ backdrop-filter: blur(4px);
727
+ -webkit-backdrop-filter: blur(4px);
728
+ display: flex;
729
+ align-items: flex-end;
730
+ justify-content: center;
731
+ animation: modalFadeIn 0.2s ease-out;
732
+ }
733
+
734
+ .language-modal {
735
+ width: 100%;
736
+ max-width: 28rem;
737
+ background: #1a1a1a;
738
+ border-radius: 1.5rem 1.5rem 0 0;
739
+ border: 1px solid #2a2a2a;
740
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
741
+ max-height: 80vh;
742
+ display: flex;
743
+ flex-direction: column;
744
+ animation: modalSlideUp 0.3s ease-out;
745
+ }
746
+
747
+ @media (min-width: 640px) {
748
+ .language-modal {
749
+ border-radius: 1.5rem;
750
+ margin: 1rem;
751
+ }
752
+ }
753
+
754
+ .language-modal-header {
755
+ display: flex;
756
+ align-items: center;
757
+ justify-content: space-between;
758
+ padding: 1rem;
759
+ border-bottom: 1px solid #2a2a2a;
760
+ }
761
+
762
+ .language-modal-title {
763
+ font-size: 1rem;
764
+ font-weight: 700;
765
+ color: white;
766
+ }
767
+
768
+ .language-modal-close {
769
+ background: none;
770
+ border: none;
771
+ color: #9ca3af;
772
+ font-size: 1.25rem;
773
+ cursor: pointer;
774
+ padding: 0.25rem;
775
+ line-height: 1;
776
+ }
777
+ .language-modal-close:hover {
778
+ color: white;
779
+ }
780
+
781
+ .language-modal-list {
782
+ overflow-y: auto;
783
+ padding: 0.5rem;
784
+ max-height: 60vh;
785
+ }
786
+
787
+ .language-option {
788
+ width: 100%;
789
+ display: flex;
790
+ align-items: center;
791
+ justify-content: space-between;
792
+ padding: 1rem;
793
+ background: transparent;
794
+ border: none;
795
+ border-radius: 0.75rem;
796
+ cursor: pointer;
797
+ transition: all 0.15s;
798
+ color: #d1d5db;
799
+ }
800
+
801
+ .language-option:hover {
802
+ background: #252525;
803
+ }
804
+
805
+ .language-option.active {
806
+ background: rgba(6, 182, 212, 0.1);
807
+ color: #22d3ee;
808
+ border: 1px solid rgba(6, 182, 212, 0.5);
809
+ }
810
+
811
+ .language-option-label {
812
+ font-size: 1rem;
813
+ font-weight: 500;
814
+ }
815
+
816
+ .language-option-check {
817
+ font-size: 1rem;
818
+ }
819
+
820
+ .store-modal {
821
+ width: 100%;
822
+ max-width: 28rem; /* max-w-sm */
823
+ background: #111827; /* gray-900 */
824
+ border-top: 1px solid #374151;
825
+ border-radius: 1.5rem 1.5rem 0 0; /* rounded-t-3xl */
826
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
827
+ display: flex;
828
+ flex-direction: column;
829
+ max-height: 90vh;
830
+ animation: modalSlideUp 0.3s ease-out;
831
+ }
832
+
833
+ @media (min-width: 640px) {
834
+ .store-modal {
835
+ border-radius: 1.5rem;
836
+ margin: 1rem;
837
+ }
838
+ }
839
+
840
+ .store-modal-header {
841
+ display: flex;
842
+ align-items: center;
843
+ justify-content: center;
844
+ padding: 0.75rem;
845
+ border-bottom: 1px solid #374151;
846
+ }
847
+
848
+ .store-modal-title {
849
+ font-size: 1.125rem; /* text-lg */
850
+ font-weight: 700;
851
+ color: white;
852
+ letter-spacing: 0.025em;
853
+ }
854
+
855
+ .store-modal-content {
856
+ flex: 1;
857
+ overflow-y: auto;
858
+ padding: 0.75rem;
859
+ display: flex;
860
+ flex-direction: column;
861
+ gap: 0.5rem;
862
+ }
863
+
864
+ .store-pack {
865
+ display: flex;
866
+ align-items: center;
867
+ justify-content: space-between;
868
+ padding: 0.75rem;
869
+ background: #1f2937; /* gray-800 */
870
+ border-radius: 0.75rem;
871
+ border: 1px solid #374151;
872
+ transition: background 0.15s;
873
+ position: relative;
874
+ }
875
+ .store-pack:hover {
876
+ background: #1a2233;
877
+ }
878
+
879
+ .store-pack-hot {
880
+ position: absolute;
881
+ top: 0;
882
+ right: 0;
883
+ background: linear-gradient(135deg, #ef4444, #ec4899); /* red-500 to pink-500 */
884
+ color: white;
885
+ font-size: 0.625rem;
886
+ font-weight: 700;
887
+ padding: 2px 8px;
888
+ border-radius: 0 0.75rem 0 0.5rem;
889
+ text-transform: uppercase;
890
+ letter-spacing: 0.05em;
891
+ }
892
+
893
+ .store-pack-left {
894
+ display: flex;
895
+ align-items: center;
896
+ gap: 0.75rem;
897
+ }
898
+
899
+ .store-pack-icon {
900
+ width: 2.5rem;
901
+ height: 2.5rem;
902
+ border-radius: 50%;
903
+ background: #374151;
904
+ display: flex;
905
+ align-items: center;
906
+ justify-content: center;
907
+ border: 1px solid #4b5563;
908
+ flex-shrink: 0;
909
+ }
910
+
911
+ .store-pack-icon svg {
912
+ color: #a855f7; /* purple-500 */
913
+ width: 1.25rem;
914
+ height: 1.25rem;
915
+ }
916
+
917
+ .store-pack-info {
918
+ display: flex;
919
+ flex-direction: column;
920
+ }
921
+
922
+ .store-pack-amount {
923
+ font-size: 1rem;
924
+ font-weight: 700;
925
+ color: white;
926
+ }
927
+
928
+ .store-pack-amount span {
929
+ font-size: 0.75rem;
930
+ font-weight: 400;
931
+ color: #a78bfa; /* purple-400 */
932
+ }
933
+
934
+ .store-pack-price {
935
+ font-size: 0.75rem;
936
+ color: #9ca3af; /* gray-400 */
937
+ }
938
+
939
+ .store-buy-btn {
940
+ background: linear-gradient(135deg, #0891b2, #2563eb); /* cyan-600 to blue-600 */
941
+ color: white;
942
+ font-size: 0.75rem;
943
+ font-weight: 700;
944
+ padding: 0.375rem 1rem;
945
+ border-radius: 9999px;
946
+ border: none;
947
+ cursor: pointer;
948
+ transition: all 0.15s;
949
+ box-shadow: 0 10px 15px -3px rgba(6, 182, 212, 0.2);
950
+ }
951
+ .store-buy-btn:hover {
952
+ background: linear-gradient(135deg, #22d3ee, #3b82f6); /* cyan-500 to blue-500 */
953
+ transform: scale(0.97);
954
+ }
955
+
956
+ .store-modal-footer {
957
+ padding: 0.75rem;
958
+ padding-bottom: 1.5rem;
959
+ border-top: 1px solid #374151;
960
+ border-radius: 0 0 1.5rem 1.5rem;
961
+ background: #111827;
962
+ }
963
+
964
+ @media (min-width: 640px) {
965
+ .store-modal-footer {
966
+ padding-bottom: 0.75rem;
967
+ border-radius: 0 0 1.5rem 1.5rem;
968
+ }
969
+ }
970
+
971
+ .store-cancel-btn {
972
+ width: 100%;
973
+ text-align: center;
974
+ font-size: 1rem;
975
+ font-weight: 500;
976
+ color: #9ca3af;
977
+ background: none;
978
+ border: none;
979
+ cursor: pointer;
980
+ transition: color 0.15s;
981
+ padding: 0.25rem;
982
+ }
983
+ .store-cancel-btn:hover {
984
+ color: #e5e7eb;
985
+ }
986
+
987
+ /* ========== Toast ========== */
988
+ .toast-container {
989
+ position: fixed;
990
+ top: 1rem;
991
+ left: 50%;
992
+ transform: translateX(-50%);
993
+ z-index: 2000;
994
+ display: flex;
995
+ flex-direction: column;
996
+ align-items: center;
997
+ gap: 0.5rem;
998
+ pointer-events: none;
999
+ width: 100%;
1000
+ max-width: 24rem;
1001
+ }
1002
+
1003
+ .toast {
1004
+ background: #ffffff;
1005
+ color: #0f172a;
1006
+ border: 1px solid #e2e8f0;
1007
+ border-radius: 1rem;
1008
+ padding: 0.75rem 1rem;
1009
+ font-size: 0.875rem;
1010
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -2px rgba(0, 0, 0, 0.1);
1011
+ animation: toastIn 0.2s ease-out;
1012
+ max-width: 100%;
1013
+ text-align: center;
1014
+ display: flex;
1015
+ align-items: center;
1016
+ gap: 0.75rem;
1017
+ pointer-events: auto;
1018
+ }
1019
+
1020
+ .toast-icon {
1021
+ flex-shrink: 0;
1022
+ width: 2.5rem;
1023
+ height: 2.5rem;
1024
+ border-radius: 9999px;
1025
+ background: #dcfce7;
1026
+ border: 1px solid #bbf7d0;
1027
+ display: flex;
1028
+ align-items: center;
1029
+ justify-content: center;
1030
+ }
1031
+
1032
+ .toast-icon svg {
1033
+ width: 1.25rem;
1034
+ height: 1.25rem;
1035
+ color: #16a34a;
1036
+ }
1037
+
1038
+ .toast-content {
1039
+ flex: 1;
1040
+ min-width: 0;
1041
+ }
1042
+
1043
+ .toast-title {
1044
+ font-weight: 600;
1045
+ color: #0f172a;
1046
+ line-height: 1.375;
1047
+ }
1048
+
1049
+ .toast-message {
1050
+ color: #475569;
1051
+ font-size: 0.8125rem;
1052
+ margin-top: 0.125rem;
1053
+ line-height: 1.375;
1054
+ }
1055
+
1056
+ @keyframes modalFadeIn {
1057
+ from { opacity: 0; }
1058
+ to { opacity: 1; }
1059
+ }
1060
+
1061
+ @keyframes modalSlideUp {
1062
+ from { transform: translateY(100%); }
1063
+ to { transform: translateY(0); }
1064
+ }
1065
+
1066
+ @keyframes toastIn {
1067
+ from { opacity: 0; transform: translateY(-20px); }
1068
+ to { opacity: 1; transform: translateY(0); }
1069
+ }
1070
+
1071
+ /* \u767B\u5F55\u63D0\u793A Toast */
1072
+ .login-prompt-toast {
1073
+ background: linear-gradient(135deg, rgba(251, 191, 36, 0.15), rgba(245, 158, 11, 0.15));
1074
+ border-color: rgba(251, 191, 36, 0.4);
1075
+ }
1076
+
1077
+ .login-prompt-toast .toast-icon {
1078
+ color: #fbbf24;
1079
+ }
1080
+
1081
+ .login-prompt-toast .toast-title {
1082
+ color: #fef3c7;
1083
+ }
1084
+
1085
+ /* ========== \u6E38\u620F\u8BE6\u60C5\u9875\u6837\u5F0F\uFF08iframe \u5D4C\u5165\u6A21\u5F0F\uFF09========== */
1086
+ .detail-nav {
1087
+ display: flex;
1088
+ align-items: center;
1089
+ padding: 0.75rem 0.5rem;
1090
+ background-color: #1a2332;
1091
+ border-bottom: 1px solid #1e2a3a;
1092
+ color: #ffffff;
1093
+ gap: 0.5rem;
1094
+ position: sticky;
1095
+ top: 0;
1096
+ z-index: 100;
1097
+ }
1098
+
1099
+ .detail-back-btn {
1100
+ display: flex;
1101
+ align-items: center;
1102
+ justify-content: center;
1103
+ gap: 0.125rem;
1104
+ padding: 0 0.5rem;
1105
+ height: 2rem;
1106
+ background: transparent;
1107
+ border: none;
1108
+ border-radius: 0.375rem;
1109
+ color: #ffffff;
1110
+ cursor: pointer;
1111
+ transition: color 0.2s, background 0.2s;
1112
+ flex-shrink: 0;
1113
+ }
1114
+
1115
+ .detail-back-btn:hover {
1116
+ color: #3b82f6;
1117
+ background-color: rgba(59, 130, 246, 0.1);
1118
+ }
1119
+
1120
+ .detail-back-btn:active {
1121
+ background-color: rgba(59, 130, 246, 0.2);
1122
+ }
1123
+
1124
+ .detail-back-text {
1125
+ font-size: 0.875rem;
1126
+ font-weight: 500;
1127
+ }
1128
+
1129
+ .detail-title {
1130
+ font-size: 1.125rem;
1131
+ font-weight: 600;
1132
+ flex: 1;
1133
+ white-space: nowrap;
1134
+ overflow: hidden;
1135
+ text-overflow: ellipsis;
1136
+ }
1137
+
1138
+ .detail-spacer {
1139
+ width: 2rem;
1140
+ flex-shrink: 0;
1141
+ }
1142
+
1143
+ .detail-iframe-container {
1144
+ flex: 1;
1145
+ width: 100%;
1146
+ overflow: hidden;
1147
+ background-color: #0f1419;
1148
+ }
1149
+
1150
+ .detail-iframe {
1151
+ width: 100%;
1152
+ height: calc(100vh - 4rem);
1153
+ border: none;
1154
+ display: block;
1155
+ }
1156
+ `,Ce=`
1157
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:none">
1158
+ <symbol id="icon-adventure" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1159
+ <polyline points="14.5 17.5 3 6 3 3 6 3 17.5 14.5"/>
1160
+ <line x1="13" x2="19" y1="19" y2="13"/>
1161
+ <line x1="16" x2="20" y1="16" y2="20"/>
1162
+ <line x1="19" x2="21" y1="21" y2="19"/>
1163
+ </symbol>
1164
+ <symbol id="icon-simulation" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1165
+ <path d="m2 7 4.41-4.41A2 2 0 0 1 7.83 2h8.34a2 2 0 0 1 1.42.59L22 7"/>
1166
+ <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/>
1167
+ <path d="M15 22v-4a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4"/>
1168
+ <path d="M2 7h20"/>
1169
+ <path d="M22 7v3a2 2 0 0 1-2 2 2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 16 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 12 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 8 12a2.7 2.7 0 0 1-1.59-.63.7.7 0 0 0-.82 0A2.7 2.7 0 0 1 4 12a2 2 0 0 1-2-2V7"/>
1170
+ </symbol>
1171
+ <symbol id="icon-casual" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1172
+ <line x1="6" x2="10" y1="11" y2="11"/>
1173
+ <line x1="8" x2="8" y1="9" y2="13"/>
1174
+ <line x1="15" x2="15.01" y1="12" y2="12"/>
1175
+ <line x1="18" x2="18.01" y1="10" y2="10"/>
1176
+ <path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/>
1177
+ </symbol>
1178
+ <symbol id="icon-arcade" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1179
+ <path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>
1180
+ </symbol>
1181
+ <symbol id="icon-moba" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1182
+ <path d="M9 10h.01"/>
1183
+ <path d="M15 10h.01"/>
1184
+ <path d="M12 2a8 8 0 0 0-8 8v12l3-3 2.5 2.5L12 19l2.5 2.5L17 19l3 3V10a8 8 0 0 0-8-8z"/>
1185
+ </symbol>
1186
+ <symbol id="icon-puzzle" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1187
+ <path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/>
1188
+ <path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/>
1189
+ <path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/>
1190
+ <path d="M17.599 6.5a3 3 0 0 0 .399-1.375"/>
1191
+ <path d="M6.003 5.125A3 3 0 0 0 6.401 6.5"/>
1192
+ <path d="M3.477 10.896a4 4 0 0 1 .585-.396"/>
1193
+ <path d="M19.938 10.5a4 4 0 0 1 .585.396"/>
1194
+ <path d="M6 18a4 4 0 0 1-1.967-.516"/>
1195
+ <path d="M19.967 17.484A4 4 0 0 1 18 18"/>
1196
+ </symbol>
1197
+ <symbol id="icon-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1198
+ <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
1199
+ </symbol>
1200
+ <symbol id="icon-warning" viewBox="0 0 24 24" fill="currentColor">
1201
+ <path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/>
1202
+ </symbol>
1203
+ </svg>
1204
+ `,nt=o=>{switch(o){case"Adventure":return"#FF7D54";case"Simulation":return"#4ADE80";case"Casual":return"#60A5FA";case"Arcade":return"#A78BFA";case"Moba":return"#FACC15";case"Puzzle":return"#FB923C";case"Doge OS":return"#FBBF24";default:return"#22d3ee"}},Le=[{id:"Doge OS",name:"Doge OS",iconType:"image",iconSrc:"https://games.playsout.com/resources/icon/image/doge32.png"},{id:"Adventure",name:"Adventure",iconType:"icon",iconKey:"adventure",color:"#FF7D54"},{id:"Simulation",name:"Simulation",iconType:"icon",iconKey:"simulation",color:"#4ADE80"},{id:"Casual",name:"Casual",iconType:"icon",iconKey:"casual",color:"#60A5FA"},{id:"Arcade",name:"Arcade",iconType:"icon",iconKey:"arcade",color:"#A78BFA"},{id:"Moba",name:"Moba",iconType:"icon",iconKey:"moba",color:"#FACC15"},{id:"Puzzle",name:"Puzzle",iconType:"icon",iconKey:"puzzle",color:"#FB923C"}],M=class extends HTMLElement{constructor(){super();this._appId="";this._locale="zh";this.games=[];this.filteredGames=[];this.selectedCategory=null;this.searchQuery="";this.bannerUrl="";this.userPoints=1e3;this.avatarUrl="";this.recentGames=[];this._detailMode="iframe";this.currentView="list";this.currentGame=null;this.gemPacks=[{amount:12,price:.99,hot:!1},{amount:60,price:4.99,hot:!0},{amount:180,price:14.99,hot:!1},{amount:360,price:29.99,hot:!1}];this.toastTimeout=null;this.shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["app-id","locale","banner-url","user-points","avatar-url","recent-games","detail-mode"]}t(e,a){let i=R[this._locale]??R.en,r=ae(i,e);if(r!==e)return Ae(r,a??{});let n=ae(R.en,e);return Ae(n,a??{})}hasTranslation(e){let a=R[this._locale]??R.en;return ae(a,e)!==e}connectedCallback(){this.render(),this.loadGames()}attributeChangedCallback(e,a,i){if(a!==i){switch(e){case"app-id":this._appId=i||"";break;case"locale":this._locale=i||"zh";break;case"banner-url":this.bannerUrl=i||"";break;case"user-points":this.userPoints=parseInt(i||"1000",10);break;case"avatar-url":this.avatarUrl=i||"";break;case"recent-games":try{this.recentGames=i?JSON.parse(i):[]}catch{this.recentGames=[]}break;case"detail-mode":this._detailMode=i||"link";break}this.shadow.innerHTML&&(e==="locale"?(this.render(),this.loadGames()):this.updateUI())}}async loadGames(){this.showLoading();let e=window.__playsout_sdk_instance;if(!e||!e.isInitialized){let a=()=>{e&&e.isInitialized&&(y.off("initialized",a),this.loadGames())};e?y.on("initialized",a):this.pollForSDK();return}this.doLoadGames(e)}pollForSDK(){let e=setInterval(()=>{let a=window.__playsout_sdk_instance;a&&a.isInitialized&&(clearInterval(e),this.loadGames())},100);setTimeout(()=>{clearInterval(e),this.games.length||(this.showError(),console.warn("[PlaysoutWidget] SDK initialization timeout"))},1e4)}async doLoadGames(e){try{this.games=await e.getGames();let a=this.games.map(i=>{if(!i.image)return null;let r=window.__playsout_resolveAsset,n=typeof r=="function"?r(i.image):i.image;return typeof n!="string"?null:n.startsWith("http")?n:null}).filter(Boolean);a.length>0&&fe(a,!0),this.filterGames()}catch(a){console.error("[PlaysoutWidget] Failed to load games:",a),this.showError()}}filterGames(){let e=[...this.games];if(this.selectedCategory&&(e=e.filter(a=>a.category===this.selectedCategory)),this.searchQuery){let a=this.searchQuery.toLowerCase();e=e.filter(i=>i.title.toLowerCase().includes(a)||i.category.toLowerCase().includes(a))}this.filteredGames=e,this.renderGames()}showLoading(){let e=this.shadow.querySelector(".widget-content");e&&(e.innerHTML=`
1205
+ <div class="loading">
1206
+ <div class="loading-spinner"></div>
1207
+ </div>
1208
+ `)}showError(){let e=this.shadow.querySelector(".widget-content");e&&(e.innerHTML=`
1209
+ <div class="empty-state">
1210
+ <div class="empty-state-icon">
1211
+ <svg width="48" height="48" viewBox="0 0 24 24" fill="currentColor">
1212
+ <use href="#icon-warning"/>
1213
+ </svg>
1214
+ </div>
1215
+ <p>Failed to load games</p>
1216
+ </div>
1217
+ `)}render(){console.log("[PlaysoutWidget] render called");let e=this.bannerUrl||s("./home-banner.webp");if(this.__criticalAssetsMarked!==!0){let a=s("./logowhite.png"),i=Le.filter(r=>r.iconType==="image"&&r.iconSrc).map(r=>r.iconSrc);pe([a,e,...i]),this.__criticalAssetsMarked=!0}if(this.currentView==="detail"&&this.currentGame){this.renderGameDetail();return}this.shadow.innerHTML=`
1218
+ <style>${Ee}</style>
1219
+ ${Ce}
1220
+ <div class="playsout-scroll-container">
1221
+ <div class="mobile-container">
1222
+ <div class="playsout-widget">
1223
+ <!-- Header -->
1224
+ <header class="widget-header">
1225
+ <div class="widget-logo">
1226
+ <img src="${P("./logowhite.png")}" alt="Playsout" />
1227
+ </div>
1228
+ <div class="widget-user">
1229
+ <!-- Gems Button -->
1230
+ <button class="widget-gems-btn" id="gems-btn" aria-label="Gem Store">
1231
+ <span class="widget-gems-amount" id="gems-amount">${this.userPoints}</span>
1232
+ <svg class="widget-gems-icon" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
1233
+ <path d="M6 3h12l4 6-10 13L2 9Z"/>
1234
+ <path d="M11 3 8 9l4 13 4-13-3-6"/>
1235
+ <path d="M2 9h20"/>
1236
+ </svg>
1237
+ </button>
1238
+ <!-- Profile Button -->
1239
+ <button class="widget-profile-btn" id="profile-btn" aria-label="Profile">
1240
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1241
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
1242
+ <circle cx="12" cy="7" r="4"/>
1243
+ </svg>
1244
+ </button>
1245
+ </div>
1246
+ </header>
1247
+
1248
+ <!-- Banner -->
1249
+ <div class="widget-banner">
1250
+ <img
1251
+ class="banner-image"
1252
+ src="${e?P(e):""}"
1253
+ alt="Playsout Games"
1254
+ />
1255
+ </div>
1256
+
1257
+ <!-- Search -->
1258
+ <div class="widget-search">
1259
+ <div class="search-wrapper">
1260
+ <span class="search-icon">
1261
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1262
+ <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
1263
+ </svg>
1264
+ </span>
1265
+ <input
1266
+ type="text"
1267
+ class="search-input"
1268
+ id="search-input"
1269
+ placeholder="${this.t("home.searchPlaceholder")}"
1270
+ />
1271
+ <button class="search-btn" id="search-btn" aria-label="Search">
1272
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1273
+ <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
1274
+ </svg>
1275
+ </button>
1276
+ </div>
1277
+ </div>
1278
+
1279
+ <!-- Categories -->
1280
+ <div class="widget-categories">
1281
+ <div class="categories-wrapper" id="categories">
1282
+ ${Le.map(a=>{let i=this.selectedCategory===a.id,r=a.color||nt(a.id),n=a.iconType==="image"&&a.iconSrc?`<img src="${P(a.iconSrc)}" alt="" style="width:1rem;height:1rem;object-fit:contain;" />`:`<svg width="1rem" height="1rem" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" color="${r}" style="color:${r}"><use href="#icon-${a.iconKey}"/></svg>`,d=this.hasTranslation(`categories.${a.id}`)?this.t(`categories.${a.id}`):a.name;return`
1283
+ <button class="category-btn${i?" active":""}" data-category="${a.id}">
1284
+ <span class="category-icon">${n}</span>
1285
+ <span class="category-label">${d}</span>
1286
+ </button>`}).join("")}
1287
+ </div>
1288
+ </div>
1289
+
1290
+ <!-- Games Content -->
1291
+ <div class="widget-content">
1292
+ <div class="loading">
1293
+ <div class="loading-spinner"></div>
1294
+ </div>
1295
+ </div>
1296
+ </div>
1297
+ </div>
1298
+ </div>
1299
+ `,this.attachEventListeners()}updateUI(){let e=this.shadow.querySelector(".banner-image");e&&this.bannerUrl&&(e.src=this.bannerUrl);let a=this.shadow.querySelector("#gems-amount");a&&(a.textContent=String(this.userPoints))}showStoreModal(){this.hideStoreModal();let e=document.createElement("div");e.className="store-modal-overlay",e.id="store-modal-overlay",e.innerHTML=`
1300
+ <div class="store-modal" id="store-modal">
1301
+ <div class="store-modal-header">
1302
+ <h2 class="store-modal-title">${this.t("store.title")}</h2>
1303
+ </div>
1304
+ <div class="store-modal-content">
1305
+ ${this.gemPacks.map(a=>`
1306
+ <div class="store-pack">
1307
+ ${a.hot?'<div class="store-pack-hot">HOT</div>':""}
1308
+ <div class="store-pack-left">
1309
+ <div class="store-pack-icon">
1310
+ <svg viewBox="0 0 24 24" fill="currentColor">
1311
+ <path d="M19 3H5L2 9l10 12L22 9l-3-6zm-7 14.8L5.1 9h13.8L12 17.8z"/>
1312
+ </svg>
1313
+ </div>
1314
+ <div class="store-pack-info">
1315
+ <span class="store-pack-amount">${a.amount} <span>gems</span></span>
1316
+ <span class="store-pack-price">US$${a.price}</span>
1317
+ </div>
1318
+ </div>
1319
+ <button class="store-buy-btn" data-amount="${a.amount}">${this.t("store.buy")}</button>
1320
+ </div>
1321
+ `).join("")}
1322
+ </div>
1323
+ <div class="store-modal-footer">
1324
+ <button class="store-cancel-btn" id="store-cancel">${this.t("store.cancel")}</button>
1325
+ </div>
1326
+ </div>
1327
+ `,this.shadow.appendChild(e),e.querySelectorAll(".store-buy-btn").forEach(a=>{a.addEventListener("click",()=>{let i=parseInt(a.dataset.amount||"0",10);this.handleGemPurchase(i)})}),e.querySelector("#store-cancel")?.addEventListener("click",()=>{this.hideStoreModal()}),e.addEventListener("click",a=>{a.target===e&&this.hideStoreModal()})}hideStoreModal(){this.shadow.querySelector("#store-modal-overlay")?.remove()}showProfileModal(){this.hideProfileModal();let e=document.createElement("div");e.className="profile-modal-overlay",e.id="profile-modal-overlay";let a=window.__playsout_sdk_instance,n=((typeof a?.isInitialized=="function"?a.isInitialized():a?.isInitialized)?a.getUser():null)?.username||this.t("profile.guest"),d=this.recentGames.length>0?this.recentGames.slice(0,5).map(u=>`
1328
+ <div class="profile-recent-game" data-game-id="${u.id}">
1329
+ <img class="profile-recent-game-image" src="${P(u.image)}" alt="${u.title}" loading="lazy" />
1330
+ <div class="profile-recent-info">
1331
+ <h4 class="profile-recent-title">${u.title}</h4>
1332
+ <p class="profile-recent-category">${this.hasTranslation(`categories.${u.category}`)?this.t(`categories.${u.category}`):u.category}</p>
1333
+ </div>
1334
+ </div>
1335
+ `).join(""):`<div class="profile-no-games">${this.t("profile.noGames")}</div>`;e.innerHTML=`
1336
+ <div class="profile-modal" id="profile-modal">
1337
+ <div class="profile-modal-header">
1338
+ <h2 class="profile-modal-title">${this.t("profile.title")}</h2>
1339
+ <button class="profile-modal-close" id="profile-close-btn">\u2715</button>
1340
+ </div>
1341
+ <div class="profile-modal-content">
1342
+ <!-- \u7528\u6237\u4FE1\u606F\u5FBD\u7AE0 -->
1343
+ <div class="profile-user-badge">
1344
+ <svg class="profile-user-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1345
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
1346
+ <circle cx="12" cy="7" r="4"></circle>
1347
+ </svg>
1348
+ <span class="profile-username-text">${n}</span>
1349
+ </div>
1350
+
1351
+ <section class="profile-section">
1352
+ <h3 class="profile-section-title">${this.t("profile.recentGames")}</h3>
1353
+ <div class="profile-recent-games">${d}</div>
1354
+ </section>
1355
+ <section class="profile-section">
1356
+ <h3 class="profile-section-title">${this.t("profile.settings")}</h3>
1357
+ <div class="profile-settings">
1358
+ <div class="profile-setting-item" id="profile-language-btn">
1359
+ <span class="profile-setting-label">${this.t("profile.language")}</span>
1360
+ <div class="profile-setting-value">
1361
+ <span id="profile-current-lang">${this.t(`profile.languages.${this._locale}`)}</span>
1362
+ <span>\u203A</span>
1363
+ </div>
1364
+ </div>
1365
+ </div>
1366
+ </section>
1367
+ </div>
1368
+ </div>
1369
+ `,this.shadow.appendChild(e),e.querySelector("#profile-close-btn")?.addEventListener("click",()=>{this.hideProfileModal()}),e.addEventListener("click",u=>{u.target===e&&this.hideProfileModal()});let m=()=>{let u=window.__playsout_sdk_instance,$=(u?.getUser?u.getUser():null)?.username||this.t("profile.guest"),_=this.shadow.querySelector(".profile-username-text");_&&(_.textContent=$)},b=()=>{let u=this.shadow.querySelector(".profile-username-text");u&&(u.textContent=this.t("profile.guest")),this.hideProfileModal()},f=window.__playsout_sdk_instance;f?.on&&(f.on("login",m),f.on("logout",m),f.on("authExpired",b)),e.querySelectorAll(".profile-recent-game").forEach(u=>{u.addEventListener("click",()=>{let k=window.__playsout_sdk_instance,$=typeof k?.isInitialized=="function"?k.isInitialized():k?.isInitialized,_=typeof k?.isLoggedIn=="function"?k.isLoggedIn():k?.isLoggedIn;if(!$||!_){this.hideProfileModal(),this.showLoginPrompt();return}let Pe=u.dataset.gameId;this.dispatchEvent(new CustomEvent("game-click",{bubbles:!0,composed:!0,detail:Pe})),this.hideProfileModal()})}),e.querySelector("#profile-language-btn")?.addEventListener("click",()=>{this.showLanguageSelectModal()})}hideProfileModal(){this.shadow.querySelector("#profile-modal-overlay")?.remove(),this.shadow.querySelector("#language-modal-overlay")?.remove()}showLanguageSelectModal(){this.shadow.querySelector("#language-modal-overlay")?.remove();let e=document.createElement("div");e.className="language-modal-overlay",e.id="language-modal-overlay";let a=[{code:"en",label:"English"},{code:"zh",label:"\u4E2D\u6587"},{code:"ja",label:"\u65E5\u672C\u8A9E"},{code:"ko",label:"\uD55C\uAD6D\uC5B4"},{code:"th",label:"\u0E44\u0E17\u0E22"},{code:"vi",label:"Ti\u1EBFng Vi\u1EC7t"},{code:"id",label:"Bahasa Indonesia"},{code:"ms",label:"Bahasa Melayu"},{code:"es",label:"Espa\xF1ol"}];e.innerHTML=`
1370
+ <div class="language-modal">
1371
+ <div class="language-modal-header">
1372
+ <h3 class="language-modal-title">${this.t("profile.language")}</h3>
1373
+ <button class="language-modal-close" id="language-close-btn">\u2715</button>
1374
+ </div>
1375
+ <div class="language-modal-list">
1376
+ ${a.map(i=>`
1377
+ <button class="language-option${i.code===this._locale?" active":""}" data-lang="${i.code}">
1378
+ <span class="language-option-label">${i.label}</span>
1379
+ ${i.code===this._locale?'<span class="language-option-check">\u2713</span>':""}
1380
+ </button>
1381
+ `).join("")}
1382
+ </div>
1383
+ </div>
1384
+ `,this.shadow.appendChild(e),e.querySelector("#language-close-btn")?.addEventListener("click",()=>{this.shadow.querySelector("#language-modal-overlay")?.remove()}),e.addEventListener("click",i=>{i.target===e&&this.shadow.querySelector("#language-modal-overlay")?.remove()}),e.querySelectorAll(".language-option").forEach(i=>{i.addEventListener("click",()=>{let r=i.dataset.lang;if(r&&r!==this._locale){this._locale=r,this.setAttribute("locale",this._locale),this.dispatchEvent(new CustomEvent("locale-change",{bubbles:!0,composed:!0,detail:this._locale}));let n=this.shadow.querySelector("#profile-current-lang");n&&(n.textContent=this.t(`profile.languages.${this._locale}`)),this.shadow.querySelector("#language-modal-overlay")?.remove()}})})}handleGemPurchase(e){this.userPoints+=e,this.updateUI(),this.hideStoreModal(),this.showToast(`${e}`)}showToast(e){this.toastTimeout&&clearTimeout(this.toastTimeout),this.shadow.querySelector("#toast-container")?.remove();let a=document.createElement("div");a.className="toast-container",a.id="toast-container",a.innerHTML=`
1385
+ <div class="toast">
1386
+ <div class="toast-icon">
1387
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
1388
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5" d="M5 13l4 4L19 7"/>
1389
+ </svg>
1390
+ </div>
1391
+ <div class="toast-content">
1392
+ <div class="toast-title">${e}</div>
1393
+ <div class="toast-message">${this.t("store.successMessage",{amount:e})}</div>
1394
+ </div>
1395
+ </div>
1396
+ `,this.shadow.appendChild(a),this.toastTimeout=window.setTimeout(()=>{a.style.opacity="0",a.style.transition="opacity 0.2s",setTimeout(()=>a.remove(),200)},3e3)}renderGames(){let e=this.shadow.querySelector(".widget-content");if(e){if(this.filteredGames.length===0){e.innerHTML=`
1397
+ <div class="widget-games">
1398
+ <div class="no-results">
1399
+ <p>${this.t("home.noGames")}</p>
1400
+ </div>
1401
+ </div>
1402
+ `;return}e.innerHTML=`
1403
+ <div class="widget-games">
1404
+ <div class="games-grid">
1405
+ ${this.filteredGames.map((a,i)=>this.renderGameCard(a,i)).join("")}
1406
+ </div>
1407
+ </div>
1408
+ `,e.querySelectorAll(".game-card").forEach(a=>{a.addEventListener("click",()=>{let i=a.getAttribute("data-game-id"),r=this.games.find(n=>n.id===i);if(r){let n=window.__playsout_sdk_instance,d=typeof n?.isInitialized=="function"?n.isInitialized():n?.isInitialized,m=typeof n?.isLoggedIn=="function"?n.isLoggedIn():n?.isLoggedIn;if(!d||!m){this.showLoginPrompt();return}if(this.dispatchEvent(new CustomEvent("game-click",{detail:r,bubbles:!0,composed:!0})),this._detailMode==="iframe"&&r.externalUrl)this.currentGame=r,this.currentView="detail",this.render();else{let b=r.externalUrl||`/games/${r.id}`;window.location.href=b}}})})}}showLoginPrompt(){this.toastTimeout&&clearTimeout(this.toastTimeout),this.shadow.querySelector("#toast-container")?.remove();let e=document.createElement("div");e.className="toast-container";let a=this.t.bind(this);e.innerHTML=`
1409
+ <div class="toast login-prompt-toast">
1410
+ <div class="toast-icon">
1411
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1412
+ <circle cx="12" cy="12" r="10"></circle>
1413
+ <line x1="12" y1="8" x2="12" y2="12"></line>
1414
+ <line x1="12" y1="16" x2="12.01" y2="16"></line>
1415
+ </svg>
1416
+ </div>
1417
+ <div class="toast-content">
1418
+ <div class="toast-title">${a("auth.mustLogin")}</div>
1419
+ </div>
1420
+ </div>
1421
+ `,this.shadow.appendChild(e),this.toastTimeout=window.setTimeout(()=>{e.style.opacity="0",e.style.transform="translateY(10px)",e.style.transition="all 0.2s ease-out",setTimeout(()=>e.remove(),200)},1e3)}renderGameCard(e,a){let i=[];e.isNew&&i.push('<span class="game-tag new">NEW</span>'),e.isHot&&i.push('<span class="game-tag hot">HOT</span>');let r=a<8?"eager":"lazy";return`
1422
+ <div class="game-card" data-game-id="${e.id}">
1423
+ <div class="game-image-wrapper">
1424
+ <img
1425
+ class="game-image"
1426
+ src="${P(e.image)}"
1427
+ alt="${e.title}"
1428
+ loading="${r}"
1429
+ draggable="false"
1430
+ />
1431
+ </div>
1432
+ <div class="game-info">
1433
+ <div class="title-row">
1434
+ <h3 class="game-title">${e.title}</h3>
1435
+ ${i.length>0?i.join(""):""}
1436
+ </div>
1437
+ <div class="divider"></div>
1438
+ <p class="game-category">${this.hasTranslation(`categories.${e.category}`)?this.t(`categories.${e.category}`):e.category}</p>
1439
+ </div>
1440
+ </div>
1441
+ `}renderGameDetail(){if(!this.currentGame)return;let e=this.currentGame,a=e.externalUrl||`/games/${e.id}`;this.shadow.innerHTML=`
1442
+ <style>${Ee}</style>
1443
+ ${Ce}
1444
+ <div class="playsout-scroll-container">
1445
+ <div class="mobile-container">
1446
+ <div class="playsout-widget">
1447
+ <!-- \u5BFC\u822A\u680F -->
1448
+ <header class="detail-nav">
1449
+ <button class="detail-back-btn" id="detail-back-btn" aria-label="${this.t("game.header.back")}">
1450
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1451
+ <path d="M15 18l-6-6 6-6"/>
1452
+ </svg>
1453
+ <span class="detail-back-text">${this.t("game.header.back")}</span>
1454
+ </button>
1455
+ <span class="detail-title">${e.title}</span>
1456
+ <div class="detail-spacer"></div>
1457
+ </header>
1458
+
1459
+ <!-- \u6E38\u620F iframe -->
1460
+ <div class="detail-iframe-container">
1461
+ <iframe
1462
+ src="${a}"
1463
+ class="detail-iframe"
1464
+ allow="fullscreen"
1465
+ sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
1466
+ ></iframe>
1467
+ </div>
1468
+ </div>
1469
+ </div>
1470
+ </div>
1471
+ `,this.shadow.getElementById("detail-back-btn")?.addEventListener("click",()=>{this.currentView="list",this.currentGame=null,this.render(),this.loadGames()})}attachEventListeners(){this.shadow.getElementById("gems-btn")?.addEventListener("click",()=>{this.showStoreModal()}),this.shadow.getElementById("profile-btn")?.addEventListener("click",()=>{this.showProfileModal()});let e=this.shadow.getElementById("search-input");e?.addEventListener("input",i=>{let r=i.target;this.searchQuery=r.value,this.filterGames()}),this.shadow.getElementById("search-btn")?.addEventListener("click",()=>{e?.focus()});let a=this.shadow.getElementById("categories");a?.addEventListener("click",i=>{let n=i.target.closest(".category-btn");if(n){let d=n.getAttribute("data-category")||"";this.selectedCategory===d?(this.selectedCategory=null,a.querySelectorAll(".category-btn").forEach(m=>{m.classList.remove("active")})):(this.selectedCategory=d,a.querySelectorAll(".category-btn").forEach(m=>{m.classList.remove("active")}),n.classList.add("active")),this.filterGames()}})}};customElements.get("playsout-widget")||customElements.define("playsout-widget",M);typeof customElements<"u"&&(customElements.get("playsout-widget")||customElements.define("playsout-widget",M));var{init:st,mount:lt,unmount:ct,destroy:dt,Login:gt,logout:ut,getToken:mt,getUserInfo:ht,getUser:pt,setLocale:ft,getLocale:bt,getGames:yt,getCategories:vt,on:wt,off:kt,isInitialized:xt,isLoggedIn:St,instance:Tt,PlaysoutSDKClass:It}=N;typeof window<"u"&&(window.Playsout=N,window.__playsout_sdk_instance=N.instance);return De(At);})();