handler-playable-sdk 0.1.0 → 0.1.1

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.
@@ -0,0 +1,493 @@
1
+ import * as THREE from 'three';
2
+
3
+ /**
4
+ * Handler SDK - Three.js Base Context
5
+ *
6
+ * Creates the base Three.js scene with Handler SDK lifecycle integration.
7
+ * Handles resize, pause/resume, and provides the overlay for UI elements.
8
+ *
9
+ * DO NOT EDIT - Handler SDK Core
10
+ */
11
+
12
+ /**
13
+ * Theme configuration for Three.js base
14
+ */
15
+ type ThreeTheme = {
16
+ background?: string;
17
+ text?: string;
18
+ text_muted?: string;
19
+ primary?: string;
20
+ cta_text?: string;
21
+ surface_shadow?: string;
22
+ };
23
+ /**
24
+ * Context returned by createThreeBase
25
+ */
26
+ type ThreeBaseContext = {
27
+ scene: THREE.Scene;
28
+ camera: THREE.OrthographicCamera;
29
+ renderer: THREE.WebGLRenderer;
30
+ overlay: HTMLElement;
31
+ applySize: (size?: {
32
+ width?: number;
33
+ height?: number;
34
+ }) => void;
35
+ };
36
+ /**
37
+ * Create the base Three.js context with Handler SDK integration
38
+ *
39
+ * @param root - The root HTML element to render into (from Handler.getRoot())
40
+ * @param theme - Optional theme configuration
41
+ * @returns Three.js scene context with overlay
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const root = Handler.getRoot();
46
+ * const { scene, camera, renderer, overlay } = await createThreeBase(root, {
47
+ * background: '#160a17',
48
+ * text: '#fef4dd',
49
+ * primary: '#ffb43b'
50
+ * });
51
+ * ```
52
+ */
53
+ declare function createThreeBase(root: HTMLElement, theme?: ThreeTheme): Promise<ThreeBaseContext>;
54
+
55
+ /**
56
+ * Handler SDK - GameObject System for Three.js
57
+ *
58
+ * Unity-style component-based architecture for Three.js objects.
59
+ * Automatically syncs config values to Three.js objects and enables hot-reload.
60
+ *
61
+ * DO NOT EDIT - Handler SDK Core
62
+ */
63
+
64
+ /**
65
+ * Transform Component - Position, scale, rotation
66
+ */
67
+ declare class Transform {
68
+ position: {
69
+ x: number;
70
+ y: number;
71
+ };
72
+ scale: number;
73
+ rotation: number;
74
+ constructor(config?: {
75
+ position?: {
76
+ x: number;
77
+ y: number;
78
+ };
79
+ scale?: number;
80
+ rotation?: number;
81
+ });
82
+ update(config: {
83
+ position?: {
84
+ x: number;
85
+ y: number;
86
+ };
87
+ scale?: number;
88
+ rotation?: number;
89
+ }): void;
90
+ syncToThree(threeObject: THREE.Object3D): void;
91
+ }
92
+ /**
93
+ * Renderer Component - Visual properties
94
+ */
95
+ declare class Renderer {
96
+ z_index: number;
97
+ alpha: number;
98
+ visible: boolean;
99
+ tint: number | null;
100
+ constructor(config?: {
101
+ z_index?: number;
102
+ alpha?: number;
103
+ visible?: boolean;
104
+ tint?: number | null;
105
+ });
106
+ update(config: {
107
+ z_index?: number;
108
+ alpha?: number;
109
+ visible?: boolean;
110
+ tint?: number | null;
111
+ }): void;
112
+ syncToThree(threeObject: THREE.Object3D): void;
113
+ }
114
+ /**
115
+ * Base GameObject class - Unity-style entity with components
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const characterGO = gameObjectManager.create('character_1', characterMesh);
120
+ * characterGO.setPosition(100, 200);
121
+ * characterGO.setAlpha(0.8);
122
+ * ```
123
+ */
124
+ declare class GameObject {
125
+ instanceId: string;
126
+ objectConfig: string;
127
+ threeObject: THREE.Object3D;
128
+ transform: Transform;
129
+ renderer: Renderer;
130
+ private _config;
131
+ constructor(instanceId: string, objectConfig: string, threeObject: THREE.Object3D, config: any);
132
+ /**
133
+ * Sync all components to Three.js object
134
+ */
135
+ sync(): void;
136
+ /**
137
+ * Update config and sync (for hot-reload)
138
+ */
139
+ updateConfig(newConfig: any): void;
140
+ /**
141
+ * Get component value
142
+ */
143
+ getComponent<T>(componentName: string): T | undefined;
144
+ /**
145
+ * Get transform position
146
+ */
147
+ getPosition(): {
148
+ x: number;
149
+ y: number;
150
+ };
151
+ /**
152
+ * Set transform position
153
+ */
154
+ setPosition(x: number, y: number): void;
155
+ /**
156
+ * Get renderer alpha
157
+ */
158
+ getAlpha(): number;
159
+ /**
160
+ * Set renderer alpha
161
+ */
162
+ setAlpha(alpha: number): void;
163
+ /**
164
+ * Get renderer visible
165
+ */
166
+ getVisible(): boolean;
167
+ /**
168
+ * Set renderer visible
169
+ */
170
+ setVisible(visible: boolean): void;
171
+ }
172
+ /**
173
+ * GameObject Manager - Manages all game objects and enables hot-reload
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const gameObjectManager = new GameObjectManager(config);
178
+ * const characterGO = gameObjectManager.create('character_1', characterMesh);
179
+ * ```
180
+ */
181
+ declare class GameObjectManager {
182
+ private objects;
183
+ private config;
184
+ constructor(config: any);
185
+ /**
186
+ * Create a GameObject from config
187
+ */
188
+ create(instanceId: string, threeObject: THREE.Object3D): GameObject;
189
+ /**
190
+ * Get GameObject by instance ID
191
+ */
192
+ get(instanceId: string): GameObject | undefined;
193
+ /**
194
+ * Update config and sync all objects (for hot-reload)
195
+ */
196
+ updateConfig(newConfig: any): void;
197
+ /**
198
+ * Get all GameObjects
199
+ */
200
+ getAll(): GameObject[];
201
+ /**
202
+ * Remove GameObject
203
+ */
204
+ remove(instanceId: string): void;
205
+ /**
206
+ * Clear all GameObjects
207
+ */
208
+ clear(): void;
209
+ }
210
+
211
+ /**
212
+ * Handler SDK - Font Registry
213
+ *
214
+ * Maps font IDs to actual font families/paths.
215
+ * UI config references fonts by ID only (e.g., "brand.primary").
216
+ * This registry resolves IDs to actual font values.
217
+ *
218
+ * Font paths and platform differences are handled here, NOT in config.
219
+ *
220
+ * DO NOT EDIT - Handler SDK Core
221
+ */
222
+ type FontDefinition = {
223
+ family: string;
224
+ weight?: string | number;
225
+ style?: string;
226
+ };
227
+ /**
228
+ * Resolve font ID to font family string
229
+ * @param fontId Font ID from UI config (e.g., "brand.primary")
230
+ * @returns CSS font-family string
231
+ */
232
+ declare function resolveFont(fontId: string): string;
233
+ /**
234
+ * Resolve font ID to font weight
235
+ * @param fontId Font ID from UI config
236
+ * @returns Font weight (string or number)
237
+ */
238
+ declare function resolveFontWeight(fontId: string): string | number;
239
+ /**
240
+ * Register a new font (for engine initialization)
241
+ * @param fontId Font ID
242
+ * @param definition Font definition
243
+ */
244
+ declare function registerFont(fontId: string, definition: FontDefinition): void;
245
+ /**
246
+ * Get all registered font IDs
247
+ */
248
+ declare function getRegisteredFontIds(): string[];
249
+
250
+ /**
251
+ * Handler SDK - Type Definitions for Three.js Integration
252
+ *
253
+ * DO NOT EDIT - Handler SDK Core
254
+ */
255
+ /**
256
+ * Object configuration from JSON files
257
+ */
258
+ interface ObjectConfig {
259
+ object_config?: string;
260
+ transform?: {
261
+ position?: {
262
+ x: number;
263
+ y: number;
264
+ };
265
+ scale?: number;
266
+ rotation?: number;
267
+ offset?: {
268
+ x?: number;
269
+ y?: number;
270
+ };
271
+ };
272
+ render?: {
273
+ z_index?: number;
274
+ alpha?: number;
275
+ visible?: boolean;
276
+ tint?: number | string | null;
277
+ background_color?: string;
278
+ background_alpha?: number;
279
+ border_color?: string;
280
+ };
281
+ gameplay?: {
282
+ rules?: Record<string, unknown>;
283
+ tuning?: Record<string, unknown>;
284
+ };
285
+ ui?: {
286
+ text?: string;
287
+ font?: string;
288
+ fontSize?: number;
289
+ letterSpacing?: number;
290
+ align?: string;
291
+ };
292
+ effects?: Record<string, unknown>;
293
+ audio?: Record<string, unknown>;
294
+ physics?: Record<string, unknown>;
295
+ interaction?: Record<string, unknown>;
296
+ identity?: Record<string, unknown>;
297
+ visibility?: Record<string, unknown>;
298
+ }
299
+ /**
300
+ * Engine configuration
301
+ */
302
+ interface EngineConfig {
303
+ assets?: Record<string, string>;
304
+ runtime?: {
305
+ ui?: Record<string, unknown>;
306
+ theme?: Record<string, unknown>;
307
+ ui_styles?: Record<string, unknown>;
308
+ timeline?: Record<string, number>;
309
+ };
310
+ }
311
+ /**
312
+ * Theme configuration
313
+ */
314
+ interface ThemeConfig {
315
+ background_color?: string;
316
+ text_color?: string;
317
+ square_color?: string;
318
+ cta_background?: string;
319
+ cta_text?: string;
320
+ melt_color?: string;
321
+ danger_color?: string;
322
+ brush_color?: string;
323
+ success_color?: string;
324
+ }
325
+ /**
326
+ * Gameplay configuration
327
+ */
328
+ interface GameplayConfig {
329
+ [key: string]: unknown;
330
+ }
331
+ /**
332
+ * Object-centric configuration
333
+ * This is the main config type that students work with
334
+ */
335
+ interface ObjectCentricConfig {
336
+ /** Map of object instance IDs to their configurations */
337
+ objects: Map<string, ObjectConfig>;
338
+ /** Engine configuration (assets, runtime settings) */
339
+ engine: EngineConfig;
340
+ /** Theme configuration */
341
+ theme: ThemeConfig;
342
+ /** Gameplay configuration */
343
+ gameplay: GameplayConfig;
344
+ }
345
+
346
+ /**
347
+ * Handler SDK - EndGame UI Panel for Three.js
348
+ *
349
+ * Success screen with logo, text, CTA button, and tutorial hand.
350
+ * Fully configurable via UI config system.
351
+ * Uses HTML overlay elements for UI, Three.js sprites for images.
352
+ *
353
+ * DO NOT EDIT - Handler SDK Core
354
+ */
355
+
356
+ declare function createHTMLElementWrapper(element: HTMLElement): {
357
+ element: HTMLElement;
358
+ alpha: number;
359
+ visible: boolean;
360
+ position: {
361
+ set(x: number, y: number): void;
362
+ readonly x: number;
363
+ readonly y: number;
364
+ };
365
+ scale: {
366
+ set(x: number, y?: number): void;
367
+ readonly x: number;
368
+ };
369
+ };
370
+ interface EndGamePanelElements {
371
+ panel: ReturnType<typeof createHTMLElementWrapper> & {
372
+ element: HTMLElement;
373
+ };
374
+ logo: THREE.Sprite;
375
+ title: ReturnType<typeof createHTMLElementWrapper> & {
376
+ element: HTMLElement;
377
+ };
378
+ subtitle: ReturnType<typeof createHTMLElementWrapper> & {
379
+ element: HTMLElement;
380
+ };
381
+ footer: ReturnType<typeof createHTMLElementWrapper> & {
382
+ element: HTMLElement;
383
+ };
384
+ ctaButton: ReturnType<typeof createHTMLElementWrapper> & {
385
+ element: HTMLElement;
386
+ addEventListener: HTMLElement['addEventListener'];
387
+ };
388
+ ctaText: ReturnType<typeof createHTMLElementWrapper> & {
389
+ element: HTMLElement;
390
+ };
391
+ ctaHint: ReturnType<typeof createHTMLElementWrapper> & {
392
+ element: HTMLElement;
393
+ };
394
+ hand: THREE.Sprite;
395
+ }
396
+ /**
397
+ * Create EndGame success panel with all UI elements
398
+ */
399
+ declare function createEndGamePanel(config: ObjectCentricConfig, handTexture: THREE.Texture | null, logoTexture: THREE.Texture | null): EndGamePanelElements;
400
+ /**
401
+ * Animate panel entrance with staggered animations
402
+ */
403
+ declare function animatePanelEntrance(elements: EndGamePanelElements, config: ObjectCentricConfig, onComplete?: () => void): void;
404
+ /**
405
+ * Animate tutorial hand clicking CTA button
406
+ */
407
+ declare function animateHandClick(hand: THREE.Sprite, ctaButton: ReturnType<typeof createHTMLElementWrapper> & {
408
+ element: HTMLElement;
409
+ }, config: ObjectCentricConfig, onClick: () => void): void;
410
+
411
+ /**
412
+ * Handler SDK - Tutorial UI Components for Three.js
413
+ *
414
+ * Tutorial hand and label components for game tutorials.
415
+ * Config requirement: All UI properties from object-centric config.
416
+ *
417
+ * DO NOT EDIT - Handler SDK Core
418
+ */
419
+
420
+ /**
421
+ * Create hand tutorial sprite (Three.js Sprite)
422
+ * Hand properties from object-centric config (hand_tutorial_1)
423
+ *
424
+ * @param handTexture - Texture for the hand sprite
425
+ * @param config - Object-centric configuration
426
+ * @param baseCharacterPos - Base position of the character for animation reference
427
+ */
428
+ declare function createHandTutorial(handTexture: THREE.Texture | null, config: ObjectCentricConfig, baseCharacterPos: {
429
+ x: number;
430
+ y: number;
431
+ }): THREE.Sprite;
432
+ /**
433
+ * Create tutorial label text (HTML overlay)
434
+ * Uses ui.tutorial config object with UI component schema
435
+ *
436
+ * @param config - Object-centric configuration
437
+ */
438
+ declare function createTutorialLabel(config: ObjectCentricConfig): HTMLElement;
439
+ /**
440
+ * Update hand animation
441
+ * Animation parameters from object-centric config (hand_tutorial_1)
442
+ *
443
+ * @param hand - The hand sprite
444
+ * @param baseCharacterPos - Base character position
445
+ * @param time - Current time for animation
446
+ * @param isDragging - Whether the user is currently dragging
447
+ * @param config - Object-centric configuration
448
+ */
449
+ declare function updateHandAnimation(hand: THREE.Sprite, baseCharacterPos: {
450
+ x: number;
451
+ y: number;
452
+ }, time: number, isDragging: boolean, config: ObjectCentricConfig): void;
453
+
454
+ /**
455
+ * Handler SDK - Asset Loader Utilities for Three.js
456
+ *
457
+ * Asset loading and texture creation utilities for Three.js.
458
+ * Config requirement: All asset paths from config.assets, colors from config.theme.
459
+ *
460
+ * DO NOT EDIT - Handler SDK Core
461
+ */
462
+
463
+ /**
464
+ * Load an asset with fallback placeholder
465
+ * Asset path comes from config.assets
466
+ *
467
+ * @param path - Asset path
468
+ * @param renderer - Three.js renderer instance (for context if needed)
469
+ * @param fallbackColor - Color for fallback placeholder
470
+ * @param isChar - Whether this is a character sprite (affects placeholder shape)
471
+ */
472
+ declare function loadAsset(path: string, renderer: THREE.WebGLRenderer, fallbackColor?: number, isChar?: boolean): Promise<THREE.Texture | null>;
473
+ /**
474
+ * Load character frames from sprite sheet
475
+ * Uses config.assets.character_sprite for path
476
+ * Character sheet dimensions come from config (cols: 3, rows: 2)
477
+ *
478
+ * @param path - Path to the sprite sheet
479
+ * @param renderer - Three.js renderer instance
480
+ * @param config - Object-centric configuration
481
+ */
482
+ declare function loadCharacterFrames(path: string, renderer: THREE.WebGLRenderer, config: ObjectCentricConfig): Promise<THREE.Texture[]>;
483
+ /**
484
+ * Create brush texture
485
+ * Uses config.theme.brush_color for color
486
+ * Brush size comes from config.gameplay.brush
487
+ *
488
+ * @param renderer - Three.js renderer instance
489
+ * @param config - Object-centric configuration
490
+ */
491
+ declare function createBrushTexture(renderer: THREE.WebGLRenderer, config: ObjectCentricConfig): THREE.Texture;
492
+
493
+ export { type EndGamePanelElements, GameObject, GameObjectManager, type ObjectCentricConfig, Renderer, type ThreeBaseContext, type ThreeTheme, Transform, animateHandClick, animatePanelEntrance, createBrushTexture, createEndGamePanel, createHandTutorial, createThreeBase, createTutorialLabel, getRegisteredFontIds, loadAsset, loadCharacterFrames, registerFont, resolveFont, resolveFontWeight, updateHandAnimation };
@@ -0,0 +1,109 @@
1
+ "use strict";var ni=Object.create;var ke=Object.defineProperty;var ai=Object.getOwnPropertyDescriptor;var ii=Object.getOwnPropertyNames;var si=Object.getPrototypeOf,oi=Object.prototype.hasOwnProperty;var ri=(e,t)=>{for(var n in t)ke(e,n,{get:t[n],enumerable:!0})},Rn=(e,t,n,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ii(t))!oi.call(e,i)&&i!==n&&ke(e,i,{get:()=>t[i],enumerable:!(a=ai(t,i))||a.enumerable});return e};var be=(e,t,n)=>(n=e!=null?ni(si(e)):{},Rn(t||!e||!e.__esModule?ke(n,"default",{value:e,enumerable:!0}):n,e)),li=e=>Rn(ke({},"__esModule",{value:!0}),e);var Ri={};ri(Ri,{GameObject:()=>Ce,GameObjectManager:()=>Ne,Renderer:()=>Ae,Transform:()=>Se,animateHandClick:()=>la,animatePanelEntrance:()=>ra,createBrushTexture:()=>fa,createEndGamePanel:()=>oa,createHandTutorial:()=>ca,createThreeBase:()=>aa,createTutorialLabel:()=>da,getRegisteredFontIds:()=>sa,loadAsset:()=>st,loadCharacterFrames:()=>ma,registerFont:()=>ia,resolveFont:()=>O,resolveFontWeight:()=>B,updateHandAnimation:()=>pa});module.exports=li(Ri);var fe=be(require("three"));var K={};function De(e,t,n=!1){K[e]||(K[e]=[]),K[e].push({fn:t,once:n})}function Qe(e,t){if(K[e]){if(!t){delete K[e];return}K[e]=K[e].filter(n=>n.fn!==t)}}function $e(e,...t){let n=K[e];if(n)for(let a of[...n])a.fn(...t),a.once&&Qe(e,a.fn)}function P(e,t){De(e,t,!0)}var Fe={name:"handler-playable-sdk",version:"0.1.1",description:"Handler Playable SDK v0.1 with contract-aligned surface (root sandbox, canonical event envelope).",main:"dist/index.js",module:"dist/index.mjs",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.mjs",require:"./dist/index.js"},"./pixi":{types:"./dist/pixi/index.d.ts",import:"./dist/pixi/index.mjs",require:"./dist/pixi/index.js"},"./three":{types:"./dist/three/index.d.ts",import:"./dist/three/index.mjs",require:"./dist/three/index.js"}},scripts:{build:"tsup src/index.ts src/pixi/index.ts src/three/index.ts --format cjs,esm --dts --clean --minify",lint:"eslint 'src/**/*.{ts,tsx}'",typecheck:"tsc --noEmit",prepublishOnly:"npm run build"},author:"Handler",license:"MIT",publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/HandlerAIGames/handler-playable-sdk.git"},files:["dist","LICENSE","README.md"],peerDependencies:{"pixi.js":"^8.0.0",three:"^0.160.0"},peerDependenciesMeta:{"pixi.js":{optional:!0},three:{optional:!0}},devDependencies:{"@types/three":"^0.160.0",eslint:"^8.57.1","pixi.js":"^8.8.1",three:"^0.160.0","ts-node":"^10.9.2",tsup:"^8.4.0",typescript:"^5.7.2"}};var W=0,di=W++,Hn=W++,Mn=W++,Ln=W++,kn=W++,Dn=W++,$n=W++,Fn=W++,Pn=W++,Wn=W++,zn=W++,On=W++,b=di;function Bn(){return b===Hn}function Nn(){return b===Mn}function Yn(){return b===Ln}function In(){return b===kn}function re(){return b===Dn}function le(){return b===$n}function Gn(){return b===Fn}function jn(){return b===Pn}function Vn(){return b===Wn}function Ze(){return b===zn}function Ue(){return b===On}function qn(){let e=typeof AD_PROTOCOL!="undefined"?AD_PROTOCOL:"none",t=typeof AD_NETWORK!="undefined"?AD_NETWORK:"web_embed";if(e==="mraid")try{mraid.getState(),b=Hn;return}catch{}else if(e==="dapi")try{dapi.isReady(),b=Mn;return}catch{}if(t==="facebook")try{typeof FbPlayableAd!="undefined"&&(b=Ln)}catch{}else if(t==="google")try{typeof ExitApi!="undefined"&&(b=kn)}catch{}else if(t==="mintegral")window.gameReady&&(b=Dn);else if(t==="tapjoy")window.TJ_API&&(b=$n);else if(t==="tiktok")window.openAppStore&&(b=Fn);else if(t==="smadex")try{window.smxTracking&&(b=Pn)}catch{}else if(t==="snapchat")try{window.ScPlayableAd&&(b=Wn)}catch{}else t==="vungle"?b=zn:(e==="nucleo"||t==="nucleo")&&(b=On)}var Un={mechanic_id:"TODO_mechanic_id",variant_id:"TODO_variant_id",deployment_id:"TODO_deployment_id",export_id:"TODO_export_id",profile_id:"TODO_profile_id",instance_id:"default"},pi=Math.random().toString(36).slice(2),ce=null,xe={...Un},ea="web_embed",ui={},et=!1,_e=!1,we=!1,ta=!1,it=1,nt=0,Oe=!1,q=!1,ze="",de=Math.floor(window.innerWidth),pe=Math.floor(window.innerHeight),at=de>pe,X=!1,Te=!1,Xn=!1,Kn=!1,tt=!1,Pe=null;function Jn(){if(ce)return ce;let e=document.createElement("div");return e.id="handler-root",e.setAttribute("data-handler-root","true"),document.body.appendChild(e),ce=e,e}function We(e){switch(e){case"interaction":return"engagement";case"finish":return"complete";case"install":return"cta_click";default:return e}}function na(e,t){return{event_name:e,ts:Date.now(),session_id:pi,deployment_id:xe.deployment_id,variant_id:xe.variant_id,export_profile_id:xe.profile_id,instance_id:xe.instance_id||"default",env:ea==="mraid"?"mraid":"web",payload:t}}function h(e,t){let n=We(e),a=na(n,t);$e(n,a),n!==e&&$e(e,a)}function Ee(){Pe&&(Pe(de,pe),Pe=null)}function ue(e){it=e,h("volume",e)}function me(e){e&&(ta=!0),!we&&(we=!0,h("pause"),ue(0))}function ve(e){!e&&ta||we&&(we=!1,h("resume"),ue(it))}function Q(e,t){de=Math.floor(e||window.innerWidth),pe=Math.floor(t||window.innerHeight),at=de>pe,h("resize",{width:de,height:pe})}function mi(){if(Bn())try{let e=mraid.getMaxSize();Q(e.width,e.height);let t=()=>{mraid.isViewable()&&mraid.getState()!=="hidden"?ve():me()};if(mraid.addEventListener("viewableChange",t),mraid.addEventListener("stateChange",t),mraid.addEventListener("sizeChange",()=>{let n=mraid.getMaxSize();Q(n.width,n.height)}),mraid.getAudioVolume){let n=mraid.getAudioVolume();ue(n?1:0)}if(mraid.addEventListener("audioVolumeChange",n=>{n!==null&&ue(n>0?1:0)}),mraid.addEventListener("error",(n,a)=>{console.warn("mraid error:",n,"action:",a)}),Oe=!0,mraid.isViewable()&&mraid.getState()!=="hidden")X=!0,h("boot"),h("view"),h("ready"),q=!0,Ee();else{let n=()=>{X=!0,h("boot"),h("view"),h("ready"),q=!0,Ee()};mraid.addEventListener("ready",n)}}catch(e){console.warn("MRAID hook skipped",e)}}function fi(){if(Nn())try{let e=dapi.getScreenSize();Q(e.width,e.height),dapi.addEventListener("viewableChange",n=>{n.isViewable?ve():me()}),dapi.addEventListener("adResized",n=>{let a=dapi.getScreenSize();Q(n.width||a.width,n.height||a.height)});let t=dapi.getAudioVolume();if(ue(t?1:0),dapi.addEventListener("audioVolumeChange",n=>ue(n?1:0)),Oe=!0,dapi.isViewable())X=!0,h("boot"),h("view"),h("ready"),q=!0,Ee();else{let n=()=>{X=!0,h("boot"),h("view"),h("ready"),q=!0,Ee()};dapi.addEventListener("ready",n)}}catch(e){console.warn("DAPI hook skipped",e)}}function Qn(){let e=()=>{X||document.visibilityState==="visible"&&(document.readyState==="complete"||document.readyState==="interactive")&&(X=!0,h("boot"),h("view"),h("ready"),q=!0,Ee(),Te&&(Te=!1,J.start()))};window.addEventListener("resize",()=>Q()),document.addEventListener("visibilitychange",()=>{document.visibilityState==="visible"?(ve(),e()):me()}),document.readyState==="complete"||document.readyState==="interactive"?e():window.addEventListener("load",e),Oe=!0}function yi(){let e=t=>{typeof TouchEvent!="undefined"&&t instanceof TouchEvent&&(Xn=!0),!(Xn&&t instanceof MouseEvent)&&(nt+=1,h("interaction",nt))};document.addEventListener("mousedown",e),document.addEventListener("touchstart",e)}function hi(e){var a,i,s,o,r,l,d,p,m,u,c,f;let t=typeof AD_PROTOCOL!="undefined"?AD_PROTOCOL:"none";if((typeof AD_NETWORK!="undefined"?AD_NETWORK:"web_embed")==="google")try{(a=window.ExitApi)==null||a.exit();return}catch{}if(t==="mraid"&&typeof mraid!="undefined")mraid.open(e||"");else if(t==="dapi"&&typeof dapi!="undefined")dapi.openStoreUrl();else if(le())(s=(i=window.TJ_API)==null?void 0:i.click)==null||s.call(i);else if(Yn())(r=(o=window.FbPlayableAd)==null?void 0:o.onCTAClick)==null||r.call(o);else if(Vn())(d=(l=window.ScPlayableAd)==null?void 0:l.onCTAClick)==null||d.call(l);else if(jn())try{(m=(p=window.smxTracking)==null?void 0:p.redirect)==null||m.call(p)}catch(y){console.warn("Smadex redirect failed",y)}else if(In()){let y=window.ExitApi;y&&typeof y.exit=="function"?y.exit(e||ze||""):e&&window.open(e)}else re()?(u=window.install)==null||u.call(window):Gn()?(c=window.openAppStore)==null||c.call(window):Ze()?(f=parent==null?void 0:parent.postMessage)==null||f.call(parent,"download","*"):e&&window.open(e)}function gi(){let e=typeof AD_NETWORK!="undefined"?AD_NETWORK:"web_embed",t=n=>{if(!n)return;let a=new Image;a.src=n};if(e==="bigabid"){let n=window.BIGABID_BIDTIMEMACROS;if(!n)return;P("view",()=>t(n.mraid_viewable)),P("start",()=>t(n.game_viewable)),P("engagement",()=>t(n.engagement));let a=()=>t(n.complete);P("complete",a),De("engagement",i=>{var s;((s=i==null?void 0:i.payload)==null?void 0:s.count)>3&&a()}),P("cta_click",()=>t(n.click))}else if(e==="inmobi"){let n=window.INMOBI_DSPMACROS;if(!n)return;P("view",()=>t(n.Ad_Load_Start)),P("start",()=>t(n.Ad_Viewable)),P("engagement",()=>t(n.First_Engagement)),P("complete",()=>t(n.Gameplay_Complete)),P("cta_click",()=>t(n.DSP_Click)),P("start",()=>{[5,10,15,20,25,30].forEach(a=>setTimeout(()=>t(n[`Spent_${a}_Seconds`]),a*1e3))})}}function bi(){if(!le())return;let e=window.TJ_API;e&&e.setPlayableAPI&&e.setPlayableAPI({skipAd:()=>{try{J.finish()}catch(t){console.warn("Tapjoy skip failed",t)}}})}function Zn(){var t,n,a;let e=window.TJ_API;(t=e==null?void 0:e.objectiveComplete)==null||t.call(e),(n=e==null?void 0:e.playableFinished)==null||n.call(e),(a=e==null?void 0:e.gameplayFinished)==null||a.call(e)}function _i(){re()&&(window.mintGameStart=()=>{ve(!0),Q()},window.mintGameClose=()=>{me(!0)})}function xi(){if(!Ue())return;let e=window.NUC;!e||!e.trigger||(J.on("cta_click",()=>{var t,n;return(n=(t=e.trigger).convert)==null?void 0:n.call(t,ze)}),J.on("complete",()=>{var t,n;return(n=(t=e.trigger).tryAgain)==null?void 0:n.call(t)}))}var J={init(e={},t){if(ea=e.profile||"web_embed",ui=e.consent||{},xe={...Un,...e.ids||{}},ce=e.rootEl||ce,ze=e.destinationUrl||(/android/i.test(navigator.userAgent)?"https://play.google.com/store":"https://www.apple.com/app-store/"),t&&(Pe=t),h("init"),document.body.oncontextmenu=()=>!1,Jn(),Ti(ce),qn(),mi(),fi(),!Oe){if(document.readyState==="complete")Qn();else if(!Kn){Kn=!0;let n=()=>{Qn(),window.removeEventListener("load",n),document.removeEventListener("DOMContentLoaded",n)};window.addEventListener("load",n),document.addEventListener("DOMContentLoaded",n)}}yi(),gi(),bi(),_i(),xi(),console.log(`%c @handler/playable-sdk %c v${Fe.version||"0.0.0"} `,"background: #007acc; color: #fff; font-size: 14px; padding: 4px 8px; border-top-left-radius: 4px; border-bottom-left-radius: 4px;","background: #e1e4e8; color: #333; font-size: 14px; padding: 4px 8px; border-top-right-radius: 4px; border-bottom-right-radius: 4px;"),X&&!q&&(h("boot"),h("view"),h("ready"),Te&&(Te=!1,J.start()),q=!0),q=X},getRoot(){return Jn()},get version(){return Fe.version||"0.0.0"},get maxWidth(){return de},get maxHeight(){return pe},get isLandscape(){return at},get isReady(){return q},get isStarted(){return et},get isPaused(){return we},get isFinished(){return _e},get volume(){return it},get interactions(){return nt},on(e,t){De(We(e),t)},off(e,t){Qe(We(e),t)},start(){var e,t;if(!et){if(!X){Te=!0;return}if(et=!0,h("start"),Q(),re())me(),(e=window.gameReady)==null||e.call(window);else if(le()){let n=window.TJ_API;(t=n==null?void 0:n.setPlayableBuild)==null||t.call(n,{orientation:at?"landscape":"portrait",buildID:Fe.version||"dev"})}}},finish(){var e,t;_e||(_e=!0,h("complete"),re()?(e=window.gameEnd)==null||e.call(window):Ze()?(t=parent==null?void 0:parent.postMessage)==null||t.call(parent,"complete","*"):le()&&Zn())},install(e){if(!_e){_e=!0,le()?(Zn(),setTimeout(()=>J.install(e),300)):(h("complete"),setTimeout(()=>J.install(e),0));return}tt||(tt=!0,setTimeout(()=>tt=!1,500),h("cta_click"),h("conversion"),hi(e||ze))},emit(e,t){let n=We(e);if(!["view","boot","start","engagement","complete","cta_click","conversion","retry","pause","resume","resize","volume","error"].includes(n)&&!n.startsWith("custom."))throw new Error(`Event ${e} must be canonical or namespaced as custom.<mechanic_id>.<event>`);let a=na(n,t);$e(n,a)},retry(){var e,t,n;if(re())(e=window.gameRetry)==null||e.call(window);else if(Ue()){let a=window.NUC;(n=(t=a==null?void 0:a.trigger)==null?void 0:t.tryAgain)==null||n.call(t)}h("engagement",{action:"retry"})},pause(){me(!0)},resume(){ve(!0)},resize(e,t){Q(e,t)}},Be=J;function Ti(e){let t=document.createElement("script");t.type="text/javascript",t.textContent=`
2
+ (function(){
3
+ var events = ['touchstart','touchend','mousedown','keydown'];
4
+ function unlock(){
5
+ if(window.AudioContext && AudioContext.prototype.resume){
6
+ if(!window.__handler_audio_ctx){
7
+ window.__handler_audio_ctx = new AudioContext();
8
+ }
9
+ if(window.__handler_audio_ctx.state === 'suspended'){
10
+ window.__handler_audio_ctx.resume();
11
+ }
12
+ }
13
+ events.forEach(function(e){ document.removeEventListener(e, unlock); });
14
+ }
15
+ events.forEach(function(e){ document.addEventListener(e, unlock, false); });
16
+ })();
17
+ `,e.appendChild(t)}async function aa(e,t={}){let n=()=>({width:e.clientWidth||window.innerWidth||320,height:e.clientHeight||window.innerHeight||480});e.innerHTML="",e.style.position="relative",e.style.display="flex",e.style.flexDirection="column",e.style.alignItems="stretch",e.style.width="100%",e.style.height="100dvh",e.style.minHeight="100vh",e.style.maxWidth="100%",e.style.maxHeight="100%",e.style.boxSizing="border-box",e.style.overflow="hidden",t.background&&(e.style.background=t.background);let a=document.createElement("div");a.setAttribute("style",["position:relative","width:100%","height:100%","display:flex","align-items:center","justify-content:center",`background:${t.background||"transparent"}`,"color:var(--h-text, #f4f6ff)",'font-family:var(--h-font-main, "Inter", "Helvetica Neue", Arial, sans-serif)',"box-sizing:border-box"].join(";")),e.appendChild(a);let i=document.createElement("div");i.setAttribute("style",["position:absolute","inset:0","display:flex","align-items:center","justify-content:center","pointer-events:auto"].join(";")),a.appendChild(i);let s=new fe.Scene,{width:o,height:r}=n(),l=new fe.OrthographicCamera(-o/2,o/2,r/2,-r/2,.1,1e3);l.position.set(0,0,1),l.lookAt(0,0,0);let d=new fe.WebGLRenderer({antialias:!0,alpha:!0});d.setPixelRatio(window.devicePixelRatio||1),d.setSize(o,r),d.domElement.style.maxWidth="100%",d.domElement.style.maxHeight="100%",i.appendChild(d.domElement);let p=c=>{let f=n(),y=typeof(c==null?void 0:c.width)=="number"?c.width:f.width,g=typeof(c==null?void 0:c.height)=="number"?c.height:f.height;d.setSize(y,g),d.setPixelRatio(window.devicePixelRatio||1),l.left=-y/2,l.right=y/2,l.top=g/2,l.bottom=-g/2,l.updateProjectionMatrix()};requestAnimationFrame(()=>p());let m=!1;Be.on("pause",()=>{m=!0,document.querySelectorAll("audio").forEach(f=>f.pause())}),Be.on("resume",()=>{m=!1,document.querySelectorAll("audio").forEach(f=>{f.currentTime>0&&!f.ended&&f.play().catch(()=>{})})}),Be.on("resize",({payload:c})=>{p({width:c==null?void 0:c.width,height:c==null?void 0:c.height})}),window.addEventListener("resize",()=>p());let u=document.createElement("div");return u.setAttribute("style",["position:absolute","inset:0","display:flex","flex-direction:column","align-items:center","justify-content:flex-start","gap:12px","pointer-events:none","font-family:Arial,sans-serif","padding:20px 16px","padding-bottom:clamp(24px, 6vh, 96px)","box-sizing:border-box","z-index:2"].join(";")),e.appendChild(u),{scene:s,camera:l,renderer:d,overlay:u,applySize:p}}var A=be(require("three")),Se=class{constructor(t){var n,a;this.position=(t==null?void 0:t.position)||{x:0,y:0},this.scale=(n=t==null?void 0:t.scale)!=null?n:1,this.rotation=(a=t==null?void 0:t.rotation)!=null?a:0}update(t){t.position!==void 0&&(this.position={...t.position}),t.scale!==void 0&&(this.scale=t.scale),t.rotation!==void 0&&(this.rotation=t.rotation)}syncToThree(t){t.position.set(this.position.x,this.position.y,0),t.scale.set(this.scale,this.scale,this.scale),t.rotation.z=this.rotation}},Ae=class{constructor(t){var n,a,i,s;this.z_index=(n=t==null?void 0:t.z_index)!=null?n:0,this.alpha=(a=t==null?void 0:t.alpha)!=null?a:1,this.visible=(i=t==null?void 0:t.visible)!=null?i:!0,this.tint=(s=t==null?void 0:t.tint)!=null?s:null}update(t){t.z_index!==void 0&&(this.z_index=t.z_index),t.alpha!==void 0&&(this.alpha=t.alpha),t.visible!==void 0&&(this.visible=t.visible),t.tint!==void 0&&(this.tint=t.tint)}syncToThree(t){if(t.renderOrder=this.z_index,t.visible=this.visible,t instanceof A.Mesh&&t.material&&(Array.isArray(t.material)?t.material.forEach(n=>{n instanceof A.Material&&(n.opacity=this.alpha,n.transparent=this.alpha<1)}):t.material instanceof A.Material&&(t.material.opacity=this.alpha,t.material.transparent=this.alpha<1)),this.tint!==null&&t instanceof A.Mesh&&t.material){let n=typeof this.tint=="string"?new A.Color(this.tint):new A.Color(this.tint);Array.isArray(t.material)?t.material.forEach(a=>{(a instanceof A.MeshBasicMaterial||a instanceof A.MeshStandardMaterial)&&a.color.copy(n)}):(t.material instanceof A.MeshBasicMaterial||t.material instanceof A.MeshStandardMaterial)&&t.material.color.copy(n)}}},Ce=class{constructor(t,n,a,i){this.instanceId=t,this.objectConfig=n,this.threeObject=a,this._config=i,this.transform=new Se(i.transform),this.renderer=new Ae(i.render),this.sync()}sync(){this.transform.syncToThree(this.threeObject),this.renderer.syncToThree(this.threeObject)}updateConfig(t){this._config=t,t.transform&&this.transform.update(t.transform),t.render&&this.renderer.update(t.render),this.sync()}getComponent(t){return this._config[t]}getPosition(){return{...this.transform.position}}setPosition(t,n){this.transform.position={x:t,y:n},this.transform.syncToThree(this.threeObject)}getAlpha(){return this.renderer.alpha}setAlpha(t){this.renderer.alpha=t,this.renderer.syncToThree(this.threeObject)}getVisible(){return this.renderer.visible}setVisible(t){this.renderer.visible=t,this.renderer.syncToThree(this.threeObject)}},Ne=class{constructor(t){this.objects=new Map;this.config=t}create(t,n){let a=this.config.objects.get(t);if(!a)throw new Error(`Object config not found: ${t}`);let i=new Ce(t,a.object_config||t,n,a);return this.objects.set(t,i),i}get(t){return this.objects.get(t)}updateConfig(t){this.config=t;for(let[n,a]of this.objects.entries()){let i=t.objects.get(n);i&&a.updateConfig(i)}}getAll(){return Array.from(this.objects.values())}remove(t){this.objects.delete(t)}clear(){this.objects.clear()}};var Ye={"brand.primary":{family:"Arial, sans-serif",weight:"400"},"brand.warning":{family:"Arial Black, Arial, sans-serif",weight:"900"},"brand.heading":{family:"Arial Black, Arial, sans-serif",weight:"800"},"brand.body":{family:"Arial, sans-serif",weight:"400"}};function O(e){let t=Ye[e];return t?t.family:(console.warn(`Font ID "${e}" not found in registry, using fallback`),"Arial, sans-serif")}function B(e){var n;let t=Ye[e];return t&&(n=t.weight)!=null?n:"400"}function ia(e,t){Ye[e]=t}function sa(){return Object.keys(Ye)}var ye=be(require("three"));function ie(e){return{element:e,get alpha(){return parseFloat(e.style.opacity||"1")},set alpha(t){e.style.opacity=t.toString()},get visible(){return e.style.display!=="none"},set visible(t){e.style.display=t?"":"none"},position:{set(t,n){e.style.left=`${t}px`,e.style.top=`${n}px`},get x(){return parseFloat(e.style.left||"0")},get y(){return parseFloat(e.style.top||"0")}},scale:{set(t,n){e.style.transform=`scale(${t})`},get x(){let t=e.style.transform.match(/scale\(([^)]+)\)/);return t?parseFloat(t[1]):1}}}}function oa(e,t,n){var _t,xt,Tt,wt,Et,vt,St,At,Ct,Rt,Ht,Mt,Lt,kt,Dt,$t,Ft,Pt,Wt,zt,Ot,Bt,Nt,Yt,It,Gt,jt,Vt,qt,Xt,Kt,Jt,Qt,Zt,Ut,en,tn,nn,an,sn,on,rn,ln,cn,dn,pn,un,mn,fn,yn,hn,gn,bn,_n,xn,Tn,wn,En,vn,Sn,An,Cn;let a=e.objects.get("ui_endgame_1"),i=e.objects.get("ui_endgame_logo_1"),s=e.objects.get("ui_endgame_title_1"),o=e.objects.get("ui_endgame_subtitle_1"),r=e.objects.get("ui_endgame_footer_1"),l=e.objects.get("ui_endgame_cta_1"),d=e.objects.get("ui_endgame_cta_hint_1"),p=e.objects.get("ui_endgame_hand_1"),m=e.engine.runtime||{},u=((_t=a==null?void 0:a.gameplay)==null?void 0:_t.tuning)||{},c=(a==null?void 0:a.render)||{},f=(xt=u.panel_width)!=null?xt:320,y=(Tt=u.panel_height)!=null?Tt:400,g=(wt=u.panel_padding)!=null?wt:32,S=(Et=u.panel_radius)!=null?Et:24,x=c.background_color||u.panel_bg_color||"#1a0a0a",T=c.background_alpha!==void 0&&c.background_alpha!==null?c.background_alpha:(vt=u.panel_bg_alpha)!=null?vt:.98,_=c.border_color||u.panel_border_color||"#ffffff",E=(St=u.panel_border_width)!=null?St:2,H=(At=u.panel_border_alpha)!=null?At:.3,w=document.createElement("div");w.style.cssText=`
18
+ position: absolute;
19
+ width: ${f}px;
20
+ height: ${y}px;
21
+ background: ${x};
22
+ opacity: ${T};
23
+ border: ${E}px solid ${_};
24
+ border-opacity: ${H};
25
+ border-radius: ${S}px;
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: center;
29
+ justify-content: center;
30
+ transform: translate(-50%, -50%);
31
+ opacity: 0;
32
+ visibility: hidden;
33
+ pointer-events: auto;
34
+ `;let L=ie(w);L.element=w;let N=((Ct=i==null?void 0:i.gameplay)==null?void 0:Ct.tuning)||{},C=(i==null?void 0:i.transform)||{},M=(Rt=N.logo_size)!=null?Rt:56,z=(Ht=C.scale)!=null?Ht:1,Y=(Lt=(Mt=C.offset)==null?void 0:Mt.y)!=null?Lt:-130,se=(kt=N.logo_alpha)!=null?kt:1,Z=new ye.SpriteMaterial({map:n||void 0,transparent:!0,alphaTest:.1}),v=new ye.Sprite(Z);v.position.set(0,Y,0),v.material.opacity=0;let I=0,U=0;if(n&&(I=((Dt=n.image)==null?void 0:Dt.width)||100,U=(($t=n.image)==null?void 0:$t.height)||100),I>0&&U>0){let oe=I/U,Ke,Je;oe>1?(Ke=M,Je=M/oe):(Je=M,Ke=M*oe);let ei=Ke/I*z,ti=Je/U*z;v.scale.set(ei,ti,1)}else{let oe=M/100*z;v.scale.set(oe,oe,1)}v.targetAlpha=se,v.baseScaleX=v.scale.x,v.baseScaleY=v.scale.y;let k=s==null?void 0:s.ui,G=((Ft=s==null?void 0:s.gameplay)==null?void 0:Ft.tuning)||{},ya=(k==null?void 0:k.text)||"MISSION ACCOMPLISHED",ot=(k==null?void 0:k.font)||"brand.heading",ha=(k==null?void 0:k.fontSize)||24,ga=(Pt=k==null?void 0:k.letterSpacing)!=null?Pt:1,Re=(Wt=s==null?void 0:s.render)==null?void 0:Wt.tint,ba=typeof Re=="string"?Re:Re?`#${Re.toString(16).padStart(6,"0")}`:"#00FF88",_a=f-g*2-30,xa=G.font_weight_override?G.font_weight_override:B(ot),ee=document.createElement("div");ee.textContent=ya,ee.style.cssText=`
35
+ font-family: ${O(ot)};
36
+ font-size: ${ha}px;
37
+ font-weight: ${xa};
38
+ color: ${ba};
39
+ text-align: center;
40
+ letter-spacing: ${ga}px;
41
+ -webkit-text-stroke: ${(zt=G.stroke_width)!=null?zt:2}px ${G.stroke_color||"#000000"};
42
+ text-shadow: ${(Ot=G.shadow_distance)!=null?Ot:4}px ${(Bt=G.shadow_distance)!=null?Bt:4}px ${(Nt=G.shadow_blur)!=null?Nt:8}px rgba(0,0,0,${(Yt=G.shadow_alpha)!=null?Yt:.9});
43
+ opacity: 0;
44
+ position: absolute;
45
+ transform: translate(-50%, -50%);
46
+ white-space: nowrap;
47
+ max-width: ${_a}px;
48
+ `;let rt=(It=u.title_offset_y)!=null?It:30,Ta=rt+((Gt=G.animation_start_y_offset)!=null?Gt:-20);ee.style.top=`${Ta}px`,ee.style.left="50%";let lt=ie(ee);lt.element=ee,w.appendChild(ee);let D=o==null?void 0:o.ui,ct=((jt=o==null?void 0:o.gameplay)==null?void 0:jt.tuning)||{},wa=(D==null?void 0:D.text)||"RESCUE COMPLETE",dt=(D==null?void 0:D.font)||"brand.body",Ea=(D==null?void 0:D.fontSize)||11,va=(Vt=D==null?void 0:D.letterSpacing)!=null?Vt:.5,He=(qt=o==null?void 0:o.render)==null?void 0:qt.tint,Sa=typeof He=="string"?He:He?`#${He.toString(16).padStart(6,"0")}`:"#B0B0B0",te=document.createElement("div");te.textContent=wa,te.style.cssText=`
49
+ font-family: ${O(dt)};
50
+ font-size: ${Ea}px;
51
+ font-weight: ${B(dt)};
52
+ color: ${Sa};
53
+ text-align: center;
54
+ letter-spacing: ${va}px;
55
+ opacity: 0;
56
+ position: absolute;
57
+ transform: translate(-50%, -50%);
58
+ white-space: nowrap;
59
+ `;let Aa=rt+20+((Xt=ct.animation_start_y_offset)!=null?Xt:-10);te.style.top=`${Aa}px`,te.style.left="50%";let Ge=ie(te);Ge.element=te,Ge.animationStartYOffset=(Kt=ct.animation_start_y_offset)!=null?Kt:-10,w.appendChild(te);let j=r==null?void 0:r.ui,pt=((Jt=r==null?void 0:r.gameplay)==null?void 0:Jt.tuning)||{},Ca=(j==null?void 0:j.text)||((Qt=m.ui)==null?void 0:Qt.cta_hint)||"Continue the adventure!",ut=(j==null?void 0:j.font)||"brand.body",Ra=(j==null?void 0:j.fontSize)||16,Me=(Zt=r==null?void 0:r.render)==null?void 0:Zt.tint,Ha=typeof Me=="string"?Me:Me?`#${Me.toString(16).padStart(6,"0")}`:"#FFFFFF",Ma=(Ut=pt.max_width)!=null?Ut:f-g*2,La=(en=pt.line_height)!=null?en:1.4,ne=document.createElement("div");ne.textContent=Ca,ne.style.cssText=`
60
+ font-family: ${O(ut)};
61
+ font-size: ${Ra}px;
62
+ font-weight: ${B(ut)};
63
+ color: ${Ha};
64
+ text-align: center;
65
+ opacity: 0;
66
+ position: absolute;
67
+ transform: translate(-50%, -50%);
68
+ max-width: ${Ma}px;
69
+ line-height: ${La};
70
+ word-wrap: break-word;
71
+ `;let ka=(tn=u.footer_offset_y)!=null?tn:120;ne.style.top=`${ka}px`,ne.style.left="50%";let je=ie(ne);je.element=ne;let Da=((nn=r==null?void 0:r.render)==null?void 0:nn.alpha)!==void 0&&((an=r==null?void 0:r.render)==null?void 0:an.alpha)!==null?r.render.alpha:1;je.targetAlpha=Da,w.appendChild(ne);let V=((sn=l==null?void 0:l.gameplay)==null?void 0:sn.tuning)||{},$=l==null?void 0:l.ui,$a=(on=V.button_width)!=null?on:260,Fa=(rn=V.button_height)!=null?rn:56,Pa=(ln=V.button_radius)!=null?ln:16,Wa=V.button_bg_color||((cn=m.theme)==null?void 0:cn.cta_background)||"#ffb43b",za=(dn=V.button_bg_alpha)!=null?dn:1,Oa=V.button_border_color||"#ffffff",Ba=(pn=V.button_border_width)!=null?pn:2,Mi=(un=V.button_border_alpha)!=null?un:.2,Ve=(mn=u.cta_offset_y)!=null?mn:160,R=document.createElement("button");R.style.cssText=`
72
+ width: ${$a}px;
73
+ height: ${Fa}px;
74
+ background: ${Wa};
75
+ opacity: ${za};
76
+ border: ${Ba}px solid ${Oa};
77
+ border-radius: ${Pa}px;
78
+ cursor: pointer;
79
+ opacity: 0;
80
+ position: absolute;
81
+ transform: translate(-50%, -50%);
82
+ box-shadow: inset 0 0 1px rgba(0,0,0,0.15);
83
+ `,R.style.top=`${Ve}px`,R.style.left="50%";let mt=ie(R);mt.element=R,w.appendChild(R);let Na=($==null?void 0:$.text)||((fn=m.ui)==null?void 0:fn.cta_label_end)||"DOWNLOAD",ft=($==null?void 0:$.font)||"brand.heading",Ya=($==null?void 0:$.fontSize)||20,Ia=V.button_text_color||((yn=m.theme)==null?void 0:yn.cta_text)||"#1a0a0a";R.textContent=Na,R.style.fontFamily=O(ft),R.style.fontSize=`${Ya}px`,R.style.fontWeight=String(B(ft)),R.style.color=Ia,R.style.letterSpacing=`${(hn=$==null?void 0:$.letterSpacing)!=null?hn:1}px`;let yt=ie(R);yt.element=R;let F=d==null?void 0:d.ui,ht=((gn=d==null?void 0:d.gameplay)==null?void 0:gn.tuning)||{},Ga=(F==null?void 0:F.text)||"Play the full game",gt=(F==null?void 0:F.font)||"brand.body",ja=(F==null?void 0:F.fontSize)||11,Va=(bn=F==null?void 0:F.letterSpacing)!=null?bn:0,Le=(_n=d==null?void 0:d.render)==null?void 0:_n.tint,qa=typeof Le=="string"?Le:Le?`#${Le.toString(16).padStart(6,"0")}`:"#CCCCCC",ae=document.createElement("div");ae.textContent=Ga,ae.style.cssText=`
84
+ font-family: ${O(gt)};
85
+ font-size: ${ja}px;
86
+ font-weight: ${B(gt)};
87
+ color: ${qa};
88
+ text-align: center;
89
+ letter-spacing: ${Va}px;
90
+ opacity: 0;
91
+ position: absolute;
92
+ transform: translate(-50%, -50%);
93
+ white-space: nowrap;
94
+ `;let Xa=Ve+35+((xn=ht.animation_start_y_offset)!=null?xn:5);ae.style.top=`${Xa}px`,ae.style.left="50%";let qe=ie(ae);qe.element=ae,qe.animationStartYOffset=(Tn=ht.animation_start_y_offset)!=null?Tn:5,w.appendChild(ae);let Xe=((wn=p==null?void 0:p.gameplay)==null?void 0:wn.tuning)||{},Ka=(En=Xe.hand_offset_x)!=null?En:50,Ja=(vn=Xe.hand_offset_y)!=null?vn:50,Qa=(An=(Sn=p==null?void 0:p.transform)==null?void 0:Sn.scale)!=null?An:.1875,Za=(Cn=Xe.hand_scale_multiplier)!=null?Cn:2.5,Ua=new ye.SpriteMaterial({map:t||void 0,transparent:!0,alphaTest:.1}),ge=new ye.Sprite(Ua),bt=Qa*Za*100;return ge.scale.set(bt,bt,1),ge.position.set(Ka,Ve+Ja,0),ge.material.opacity=0,ge.visible=!1,{panel:L,logo:v,title:lt,subtitle:Ge,footer:je,ctaButton:mt,ctaText:yt,ctaHint:qe,hand:ge}}function ra(e,t,n){var H,w,L,N,C,M,z,Y;let a=t.objects.get("ui_endgame_1"),i=((H=a==null?void 0:a.gameplay)==null?void 0:H.tuning)||{},s=(w=i.animation_duration_ms)!=null?w:800,o=(L=i.fade_in_duration_ms)!=null?L:600,r=(N=i.scale_animation_intensity)!=null?N:.1,l=(C=i.logo_animation_delay_ms)!=null?C:100,d=(M=i.title_animation_delay_ms)!=null?M:200,p=(z=i.footer_animation_delay_ms)!=null?z:300,m=(Y=i.cta_animation_delay_ms)!=null?Y:400,{panel:u,logo:c,title:f,subtitle:y,footer:g,ctaButton:S,ctaText:x,ctaHint:T}=e;u.visible=!0,u.element.style.visibility="visible";let _=Date.now(),E=()=>{let se=Date.now()-_,Z=Math.min(se/o,1),v=1-Math.pow(1-Z,3);u.alpha=v,u.element.style.opacity=v.toString();let I=1+r*(1-v);u.element.style.transform=`translate(-50%, -50%) scale(${I})`,Z<1?requestAnimationFrame(E):(setTimeout(()=>wi(c,s,t),l),setTimeout(()=>{Ei(f,s),setTimeout(()=>vi(y,s),50)},d),setTimeout(()=>Si(g,s),p),setTimeout(()=>{Ai(S,x,s),setTimeout(()=>Ci(T,s),50),n&&n()},m))};E()}function wi(e,t,n){var u,c,f,y,g;let a=n==null?void 0:n.objects.get("ui_endgame_logo_1"),s=(c=(((u=a==null?void 0:a.gameplay)==null?void 0:u.tuning)||{}).animation_start_scale)!=null?c:1.2,o=Date.now(),r=e.material.opacity,l=(f=e.targetAlpha)!=null?f:1,d=(y=e.baseScaleX)!=null?y:e.scale.x,p=(g=e.baseScaleY)!=null?g:e.scale.y,m=()=>{let S=Date.now()-o,x=Math.min(S/t,1),T=1-Math.pow(1-x,2);e.material.opacity=r+(l-r)*T;let _=s+(1-s)*T;e.scale.set(d*_,p*_,1),x<1&&requestAnimationFrame(m)};m()}function Ei(e,t){let n=Date.now(),a=parseFloat(e.element.style.opacity||"0"),i=parseFloat(e.element.style.top||"0"),s=()=>{let o=Date.now()-n,r=Math.min(o/t,1),l=1-Math.pow(1-r,2);e.element.style.opacity=(a+(1-a)*l).toString(),e.element.style.top=`${i-20*(1-l)}px`,r<1&&requestAnimationFrame(s)};s()}function vi(e,t){var r;let n=Date.now(),a=parseFloat(e.element.style.opacity||"0"),i=parseFloat(e.element.style.top||"0"),s=i-((r=e.animationStartYOffset)!=null?r:-10),o=()=>{let l=Date.now()-n,d=Math.min(l/t,1),p=1-Math.pow(1-d,2);e.element.style.opacity=(a+(1-a)*p).toString(),e.element.style.top=`${i+(s-i)*p}px`,d<1&&requestAnimationFrame(o)};o()}function Si(e,t){var o;let n=Date.now(),a=parseFloat(e.element.style.opacity||"0"),i=(o=e.targetAlpha)!=null?o:1,s=()=>{let r=Date.now()-n,l=Math.min(r/t,1),d=1-Math.pow(1-l,2);e.element.style.opacity=(a+(i-a)*d).toString(),l<1&&requestAnimationFrame(s)};s()}function Ai(e,t,n){let a=Date.now(),i=parseFloat(e.element.style.opacity||"0"),s=()=>{let o=Date.now()-a,r=Math.min(o/n,1),l=1-Math.pow(1-r,2);e.element.style.opacity=(i+(1-i)*l).toString(),t.element.style.opacity=(i+(1-i)*l).toString(),e.element.style.transform=`translate(-50%, -50%) scale(${1+.1*(1-l)})`,r<1&&requestAnimationFrame(s)};s()}function Ci(e,t){var r;let n=Date.now(),a=parseFloat(e.element.style.opacity||"0"),i=parseFloat(e.element.style.top||"0"),s=i-((r=e.animationStartYOffset)!=null?r:5),o=()=>{let l=Date.now()-n,d=Math.min(l/t,1),p=1-Math.pow(1-d,2);e.element.style.opacity=(a+(1-a)*p).toString(),e.element.style.top=`${i+(s-i)*p}px`,d<1&&requestAnimationFrame(o)};o()}function la(e,t,n,a){var p,m,u,c;let i=n.objects.get("ui_endgame_hand_1"),s=((p=i==null?void 0:i.gameplay)==null?void 0:p.tuning)||{},o=(m=s.click_animation_duration_ms)!=null?m:600,r=(u=s.click_delay_ms)!=null?u:2e3,l=(c=s.click_repeat_delay_ms)!=null?c:3e3,d=()=>{var w,L;e.visible=!0,e.material.opacity=1;let f=e.position.x,y=e.position.y,g=(w=s.hand_offset_x)!=null?w:50,S=(L=s.hand_offset_y)!=null?L:50,x=t.element.getBoundingClientRect(),T=g,_=S,E=Date.now(),H=()=>{var v,I,U;let N=Date.now()-E,C=Math.min(N/o,1),M=C<.5?2*C*C:1-Math.pow(-2*C+2,2)/2;e.position.set(f+(T-f)*M,y+(_-y)*M,0);let z=(I=(v=i==null?void 0:i.transform)==null?void 0:v.scale)!=null?I:.1875,Y=(U=s.hand_scale_multiplier)!=null?U:2.5,se=z*Y*100,Z=se+se*.2*Math.sin(C*Math.PI);e.scale.set(Z,Z,1),C<1?requestAnimationFrame(H):(t.element.style.transform="translate(-50%, -50%) scale(0.95)",setTimeout(()=>{t.element.style.transform="translate(-50%, -50%) scale(1)",a()},100),setTimeout(()=>{e.material.opacity=0,setTimeout(()=>{e.position.set(f,y,0),d()},l)},500))};H()};setTimeout(d,r)}var Ie=be(require("three"));function ca(e,t,n){var m,u,c,f;let a=t.objects.get("hand_tutorial_1"),i=((m=a==null?void 0:a.gameplay)==null?void 0:m.tuning)||{},s=(a==null?void 0:a.render)||{},o=(a==null?void 0:a.transform)||{},r=new Ie.SpriteMaterial({map:e||void 0,transparent:!0,alphaTest:.1}),l=new Ie.Sprite(r);l.position.set(n.x,n.y,0),l.material.opacity=0;let d=(u=i.hand_scale_multiplier)!=null?u:2.5,p=(c=o.scale)!=null?c:.1875;return l.scale.set(p*d*100,p*d*100,1),l.renderOrder=(f=s.z_index)!=null?f:99999,l}function da(e){var f,y,g,S,x,T,_,E,H;let t=e.objects.get("ui_tutorial_1"),n=t==null?void 0:t.ui,a=(t==null?void 0:t.render)||{},i=((f=e.engine.runtime)==null?void 0:f.ui_styles)||{},s=((y=e.engine.runtime)==null?void 0:y.ui)||{},o=(n==null?void 0:n.text)||s.tutorial_label||s.label_text||"CLEAN!",r=(n==null?void 0:n.font)||"brand.warning",l=(n==null?void 0:n.fontSize)||i.label_font_size||52,d=(S=n==null?void 0:n.letterSpacing)!=null?S:(g=i.label_letter_spacing)!=null?g:-1,p=(n==null?void 0:n.align)||"center",m=a.tint,u=typeof m=="string"?m:m?`#${m.toString(16).padStart(6,"0")}`:i.label_fill||"#FFF1C1",c=document.createElement("div");return c.textContent=o,c.style.cssText=`
95
+ font-family: ${O(r)};
96
+ font-size: ${l}px;
97
+ font-weight: ${B(r)};
98
+ color: ${u};
99
+ text-align: ${p};
100
+ letter-spacing: ${d}px;
101
+ text-shadow: ${(x=i.label_shadow_distance)!=null?x:2}px ${(T=i.label_shadow_distance)!=null?T:2}px ${(_=i.label_shadow_blur)!=null?_:4}px rgba(0,0,0,${(E=i.label_shadow_alpha)!=null?E:.8});
102
+ -webkit-text-stroke: ${i.label_stroke||"#8B0000"} 2px;
103
+ opacity: ${(H=a.alpha)!=null?H:0};
104
+ visibility: ${a.visible!==!1?"visible":"hidden"};
105
+ pointer-events: none;
106
+ position: absolute;
107
+ transform: translate(-50%, 0);
108
+ white-space: nowrap;
109
+ `,c}function pa(e,t,n,a,i){var l,d,p,m,u,c,f;let s=i.objects.get("hand_tutorial_1"),o=((l=s==null?void 0:s.gameplay)==null?void 0:l.tuning)||{},r=(s==null?void 0:s.transform)||{};if(!a){let y=(d=o.animation_duration)!=null?d:1.5,g=n%y/y,S=g<.5?2*g*g:-1+(4-2*g)*g,x=(p=o.x_offset)!=null?p:0,T=(m=o.y_offset)!=null?m:0,_=(u=o.animation_range)!=null?u:40,E=_*.7,H=_,w=t.x+x+E,L=t.y+T+H,N=w+E,C=L+H;e.position.set(w+(N-w)*S,L+(C-L)*S,0);let M=(c=r.scale)!=null?c:.1875,z=(f=o.hand_scale_multiplier)!=null?f:2.5,Y=M*z*100;e.scale.set(Y,Y,1)}}var he=be(require("three")),ua=new he.TextureLoader;async function st(e,t,n=16777215,a=!1){try{let s=(globalThis.INLINE_ASSETS||{})[e];return await ua.loadAsync(s||e)}catch{console.warn(`Asset missing: ${e}. Using placeholder.`);let s=document.createElement("canvas");s.width=64,s.height=64;let o=s.getContext("2d");return o&&(o.fillStyle=`#${n.toString(16).padStart(6,"0")}`,a?o.fillRect(0,0,30,60):(o.beginPath(),o.arc(32,32,30,0,Math.PI*2),o.fill(),o.fillRect(27,32,10,40))),new he.CanvasTexture(s)}}async function ma(e,t,n){var f,y,g,S;let i=(globalThis.INLINE_ASSETS||{})[e]||e,s;try{s=await ua.loadAsync(i),console.log("[character] loaded sheet",{path:e,sourceUsed:i})}catch(x){let E=((n.gameplay.character_sheet||{}).fallback_color||"#ff00ff").replace("#","");s=await st(e,t,parseInt(E,16),!0),console.warn("[character] fallback loadAsset used",{path:e,err:x})}if(!s)return[];let o=n.gameplay.character_sheet||{},r=(f=o.cols)!=null?f:3,l=(y=o.rows)!=null?y:2,d=((g=s.image)==null?void 0:g.width)||0,p=((S=s.image)==null?void 0:S.height)||0,m=d/r,u=p/l;if(!Number.isFinite(m)||!Number.isFinite(u)||m<=0||u<=0)return[s];let c=[];for(let x=0;x<l;x++)for(let T=0;T<r;T++){let _=document.createElement("canvas");_.width=m,_.height=u;let E=_.getContext("2d");E&&s.image&&E.drawImage(s.image,T*m,x*u,m,u,0,0,m,u),c.push(new he.CanvasTexture(_))}return c.length>2&&c.push(...c.slice(1,-1).reverse()),console.log("[character] frames prepared",{count:c.length}),c}function fa(e,t){var m,u,c,f;let n=t.gameplay.brush||{},a=t.theme.brush_color||"#ffffff",i=(m=n.radius)!=null?m:20,s=(u=n.inner_radius)!=null?u:15,o=(c=n.alpha)!=null?c:.8,r=(f=n.inner_alpha)!=null?f:.3,l=n.inner_color||"#ffffff",d=document.createElement("canvas");d.width=i*2,d.height=i*2;let p=d.getContext("2d");return p&&(p.clearRect(0,0,d.width,d.height),p.beginPath(),p.arc(i,i,i,0,Math.PI*2),p.fillStyle=a,p.globalAlpha=o,p.fill(),p.beginPath(),p.arc(i,i,s,0,Math.PI*2),p.fillStyle=l,p.globalAlpha=r,p.fill()),new he.CanvasTexture(d)}0&&(module.exports={GameObject,GameObjectManager,Renderer,Transform,animateHandClick,animatePanelEntrance,createBrushTexture,createEndGamePanel,createHandTutorial,createThreeBase,createTutorialLabel,getRegisteredFontIds,loadAsset,loadCharacterFrames,registerFont,resolveFont,resolveFontWeight,updateHandAnimation});