{"games":[{"id":"2faa10f6-022f-431e-8007-fecbc3c66c08","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"Carnage offroad","slug":"carnage-offroad-mvzjvr8z","description":"### 🎮 Overview\nCarnage offroad is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","game_type":"html5","category":"racing","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvzjvkhx_j7dz8/1.0.0/","game_url":"/api/play?id=2faa10f6-022f-431e-8007-fecbc3c66c08","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvzjvkhx_j7dz8/1.0.0/thumbnail.jpg","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvzjvkhx_j7dz8/1.0.0/thumbnail.jpg","preview_path":"","preview_url":"","tutorial_data":{"guide":"","entry_file":"index.html","orientation":"any","review_data":{"summary":"All mandatory technical and security verifications passed with low risk (0/100). Package verified safe for deployment.","findings":[],"ai_report":{"status":"NOT_CONFIGURED","summary":"No AI provider API key configured (GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY). Evaluated exclusively using deterministic technical, security, and integrity verification checks.","provider":"NONE","ai_configured":false,"additional_findings":[]},"risk_score":0,"reviewed_at":"2026-11-02T17:46:19.354Z","can_resubmit":false,"quality_score":100,"review_status":"needs_human_review","recommendation":"approved","technical_checks":{"metadata":{"passed":true,"message":"Metadata verified"},"entrypoint":{"file":"index.html","passed":true,"message":"Playable entrypoint \"index.html\" verified"},"missing_assets":{"passed":true,"message":"All local asset references verified"},"path_traversal":{"passed":true,"message":"All archive paths clean"},"launch_readiness":{"passed":true,"message":"HTML5 launch integrity verified"},"prohibited_files":{"passed":true,"message":"No prohibited executable files found"},"syntax_validation":{"passed":true,"message":"JavaScript syntax valid"},"security_integrity":{"passed":true,"message":"No suspicious security payloads detected"},"viewport_responsiveness":{"passed":true,"message":"Viewport configured"}},"structured_rejections":[]},"aspect_ratio":"16:9","html_content":"<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover\" />\n    <title>Carnage Offroad</title>\n    <meta name=\"description\" content=\"High-octane 2D combat racing game with weaponized vehicles, dynamic suspension physics, terrain destruction, upgrades, and rival carnage.\" />\n    <meta name=\"theme-color\" content=\"#160b1e\" />\n    <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n    <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n    <meta property=\"og:title\" content=\"Carnage Offroad\" />\n    <meta property=\"og:description\" content=\"High-octane 2D combat racing game with weaponized vehicles, dynamic suspension physics, terrain destruction, upgrades, and rival carnage.\" />\n    <meta property=\"og:type\" content=\"website\" />\n    <meta name=\"twitter:card\" content=\"summary_large_image\" />\n    <!-- Telegram WebApp SDK (auto-activates when launched inside Telegram bot apps) -->\n    <script src=\"https://telegram.org/js/telegram-web-app.js\"></script>\n    \n    \n  <style>\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-950:oklch(25.8% .092 26.042);--color-orange-400:oklch(75% .183 55.934);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-400:oklch(85.2% .199 91.936);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-800:oklch(43.2% .095 166.913);--color-emerald-950:oklch(26.2% .051 172.552);--color-cyan-200:oklch(91.7% .08 205.041);--color-cyan-300:oklch(86.5% .127 207.078);--color-cyan-400:oklch(78.9% .154 211.53);--color-cyan-500:oklch(71.5% .143 215.221);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-600:oklch(58.8% .158 241.966);--color-sky-950:oklch(29.3% .066 243.157);--color-indigo-300:oklch(78.5% .115 274.713);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-500:oklch(62.7% .265 303.9);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-slate-900:oklch(20.8% .042 265.755);--color-slate-950:oklch(12.9% .042 264.695);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-2xl:42rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-6xl:3.75rem;--text-6xl--line-height:1;--text-8xl:6rem;--text-8xl--line-height:1;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-black:900;--tracking-tighter:-.05em;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--tracking-widest:.1em;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--animate-bounce:bounce 1s infinite;--blur-xs:4px;--blur-sm:8px;--blur-md:12px;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html,body{-webkit-user-select:none;user-select:none;touch-action:none;background-color:#160b1e;width:100%;height:100%;margin:0;padding:0;overflow:hidden}#root{width:100%;height:100%}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:0}.inset-x-0{inset-inline:0}.inset-x-3{inset-inline:calc(var(--spacing) * 3)}.top-0{top:0}.top-1{top:var(--spacing)}.top-1\\/2{top:50%}.top-3{top:calc(var(--spacing) * 3)}.top-4{top:calc(var(--spacing) * 4)}.right-4{right:calc(var(--spacing) * 4)}.bottom-0{bottom:0}.-z-10{z-index:calc(10 * -1)}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.my-3{margin-block:calc(var(--spacing) * 3)}.my-auto{margin-block:auto}.mt-1{margin-top:var(--spacing)}.mb-0{margin-bottom:0}.mb-0\\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:var(--spacing)}.mb-1\\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-auto{margin-left:auto}.line-clamp-1{-webkit-line-clamp:1;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.aspect-\\[9\\/16\\]{aspect-ratio:9/16}.aspect-square{aspect-ratio:1}.aspect-video{aspect-ratio:var(--aspect-video)}.h-1{height:var(--spacing)}.h-1\\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-13{height:calc(var(--spacing) * 13)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-18{height:calc(var(--spacing) * 18)}.h-24{height:calc(var(--spacing) * 24)}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-\\[92vh\\]{max-height:92vh}.w-1{width:var(--spacing)}.w-1\\/3{width:33.3333%}.w-3{width:calc(var(--spacing) * 3)}.w-3\\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-13{width:calc(var(--spacing) * 13)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-18{width:calc(var(--spacing) * 18)}.w-44{width:calc(var(--spacing) * 44)}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.max-w-2xl{max-width:var(--container-2xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\\[260px\\]{max-width:260px}.max-w-md{max-width:var(--container-md)}.min-w-\\[62px\\]{min-width:62px}.min-w-\\[90px\\]{min-width:90px}.min-w-\\[200px\\]{min-width:200px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-y-1{--tw-translate-y:calc(var(--spacing) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.scale-95{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x) var(--tw-scale-y)}.-rotate-90{rotate:-90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-bounce{animation:var(--animate-bounce)}.animate-ping{animation:var(--animate-ping)}.animate-pulse{animation:var(--animate-pulse)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize{resize:both}.appearance-none{appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(var(--spacing) * var(--tw-space-y-reverse));margin-block-end:calc(var(--spacing) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-7>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 7) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 7) * calc(1 - var(--tw-space-y-reverse)))}.gap-y-1{row-gap:var(--spacing)}.gap-y-1\\.5{row-gap:calc(var(--spacing) * 1.5)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-slate-800>:not(:last-child)){border-color:var(--color-slate-800)}:where(.divide-slate-800\\/60>:not(:last-child)){border-color:#1d293d99}@supports (color:color-mix(in lab, red, red)){:where(.divide-slate-800\\/60>:not(:last-child)){border-color:color-mix(in oklab, var(--color-slate-800) 60%, transparent)}}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-400{border-color:var(--color-amber-400)}.border-amber-400\\/80{border-color:#fcbb00cc}@supports (color:color-mix(in lab, red, red)){.border-amber-400\\/80{border-color:color-mix(in oklab, var(--color-amber-400) 80%, transparent)}}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\\/20{border-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/20{border-color:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.border-amber-500\\/30{border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/30{border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.border-amber-500\\/40{border-color:#f99c0066}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/40{border-color:color-mix(in oklab, var(--color-amber-500) 40%, transparent)}}.border-amber-500\\/50{border-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/50{border-color:color-mix(in oklab, var(--color-amber-500) 50%, transparent)}}.border-amber-500\\/60{border-color:#f99c0099}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/60{border-color:color-mix(in oklab, var(--color-amber-500) 60%, transparent)}}.border-amber-500\\/80{border-color:#f99c00cc}@supports (color:color-mix(in lab, red, red)){.border-amber-500\\/80{border-color:color-mix(in oklab, var(--color-amber-500) 80%, transparent)}}.border-amber-600{border-color:var(--color-amber-600)}.border-amber-600\\/50{border-color:#dd740080}@supports (color:color-mix(in lab, red, red)){.border-amber-600\\/50{border-color:color-mix(in oklab, var(--color-amber-600) 50%, transparent)}}.border-cyan-200{border-color:var(--color-cyan-200)}.border-cyan-500{border-color:var(--color-cyan-500)}.border-cyan-500\\/40{border-color:#00b7d766}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\\/40{border-color:color-mix(in oklab, var(--color-cyan-500) 40%, transparent)}}.border-cyan-500\\/60{border-color:#00b7d799}@supports (color:color-mix(in lab, red, red)){.border-cyan-500\\/60{border-color:color-mix(in oklab, var(--color-cyan-500) 60%, transparent)}}.border-emerald-800{border-color:var(--color-emerald-800)}.border-emerald-800\\/40{border-color:#005f4666}@supports (color:color-mix(in lab, red, red)){.border-emerald-800\\/40{border-color:color-mix(in oklab, var(--color-emerald-800) 40%, transparent)}}.border-emerald-800\\/50{border-color:#005f4680}@supports (color:color-mix(in lab, red, red)){.border-emerald-800\\/50{border-color:color-mix(in oklab, var(--color-emerald-800) 50%, transparent)}}.border-purple-500\\/40{border-color:#ac4bff66}@supports (color:color-mix(in lab, red, red)){.border-purple-500\\/40{border-color:color-mix(in oklab, var(--color-purple-500) 40%, transparent)}}.border-red-300{border-color:var(--color-red-300)}.border-red-400{border-color:var(--color-red-400)}.border-red-500{border-color:var(--color-red-500)}.border-red-500\\/50{border-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.border-red-500\\/50{border-color:color-mix(in oklab, var(--color-red-500) 50%, transparent)}}.border-red-500\\/60{border-color:#fb2c3699}@supports (color:color-mix(in lab, red, red)){.border-red-500\\/60{border-color:color-mix(in oklab, var(--color-red-500) 60%, transparent)}}.border-sky-600{border-color:var(--color-sky-600)}.border-sky-600\\/50{border-color:#0084cc80}@supports (color:color-mix(in lab, red, red)){.border-sky-600\\/50{border-color:color-mix(in oklab, var(--color-sky-600) 50%, transparent)}}.border-slate-700{border-color:var(--color-slate-700)}.border-slate-700\\/80{border-color:#314158cc}@supports (color:color-mix(in lab, red, red)){.border-slate-700\\/80{border-color:color-mix(in oklab, var(--color-slate-700) 80%, transparent)}}.border-slate-800{border-color:var(--color-slate-800)}.border-slate-800\\/60{border-color:#1d293d99}@supports (color:color-mix(in lab, red, red)){.border-slate-800\\/60{border-color:color-mix(in oklab, var(--color-slate-800) 60%, transparent)}}.border-slate-800\\/70{border-color:#1d293db3}@supports (color:color-mix(in lab, red, red)){.border-slate-800\\/70{border-color:color-mix(in oklab, var(--color-slate-800) 70%, transparent)}}.border-slate-800\\/80{border-color:#1d293dcc}@supports (color:color-mix(in lab, red, red)){.border-slate-800\\/80{border-color:color-mix(in oklab, var(--color-slate-800) 80%, transparent)}}.border-slate-800\\/90{border-color:#1d293de6}@supports (color:color-mix(in lab, red, red)){.border-slate-800\\/90{border-color:color-mix(in oklab, var(--color-slate-800) 90%, transparent)}}.border-slate-950{border-color:var(--color-slate-950)}.border-white{border-color:var(--color-white)}.bg-\\[\\#160b1e\\]{background-color:#160b1e}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\\/5{background-color:#f99c000d}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\/5{background-color:color-mix(in oklab, var(--color-amber-500) 5%, transparent)}}.bg-amber-500\\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-amber-500\\/20{background-color:#f99c0033}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\/20{background-color:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.bg-amber-500\\/90{background-color:#f99c00e6}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\\/90{background-color:color-mix(in oklab, var(--color-amber-500) 90%, transparent)}}.bg-amber-600{background-color:var(--color-amber-600)}.bg-amber-600\\/90{background-color:#dd7400e6}@supports (color:color-mix(in lab, red, red)){.bg-amber-600\\/90{background-color:color-mix(in oklab, var(--color-amber-600) 90%, transparent)}}.bg-amber-950{background-color:var(--color-amber-950)}.bg-amber-950\\/80{background-color:#461901cc}@supports (color:color-mix(in lab, red, red)){.bg-amber-950\\/80{background-color:color-mix(in oklab, var(--color-amber-950) 80%, transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-black\\/85{background-color:#000000d9}@supports (color:color-mix(in lab, red, red)){.bg-black\\/85{background-color:color-mix(in oklab, var(--color-black) 85%, transparent)}}.bg-cyan-500{background-color:var(--color-cyan-500)}.bg-cyan-500\\/20{background-color:#00b7d733}@supports (color:color-mix(in lab, red, red)){.bg-cyan-500\\/20{background-color:color-mix(in oklab, var(--color-cyan-500) 20%, transparent)}}.bg-cyan-500\\/90{background-color:#00b7d7e6}@supports (color:color-mix(in lab, red, red)){.bg-cyan-500\\/90{background-color:color-mix(in oklab, var(--color-cyan-500) 90%, transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-600{background-color:var(--color-emerald-600)}.bg-emerald-950{background-color:var(--color-emerald-950)}.bg-emerald-950\\/40{background-color:#002c2266}@supports (color:color-mix(in lab, red, red)){.bg-emerald-950\\/40{background-color:color-mix(in oklab, var(--color-emerald-950) 40%, transparent)}}.bg-purple-500\\/20{background-color:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.bg-purple-500\\/20{background-color:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.bg-red-400{background-color:var(--color-red-400)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-600{background-color:var(--color-red-600)}.bg-red-600\\/90{background-color:#e40014e6}@supports (color:color-mix(in lab, red, red)){.bg-red-600\\/90{background-color:color-mix(in oklab, var(--color-red-600) 90%, transparent)}}.bg-red-950{background-color:var(--color-red-950)}.bg-red-950\\/90{background-color:#460809e6}@supports (color:color-mix(in lab, red, red)){.bg-red-950\\/90{background-color:color-mix(in oklab, var(--color-red-950) 90%, transparent)}}.bg-sky-950{background-color:var(--color-sky-950)}.bg-sky-950\\/80{background-color:#052f4acc}@supports (color:color-mix(in lab, red, red)){.bg-sky-950\\/80{background-color:color-mix(in oklab, var(--color-sky-950) 80%, transparent)}}.bg-slate-800{background-color:var(--color-slate-800)}.bg-slate-800\\/60{background-color:#1d293d99}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\\/60{background-color:color-mix(in oklab, var(--color-slate-800) 60%, transparent)}}.bg-slate-800\\/80{background-color:#1d293dcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\\/80{background-color:color-mix(in oklab, var(--color-slate-800) 80%, transparent)}}.bg-slate-800\\/90{background-color:#1d293de6}@supports (color:color-mix(in lab, red, red)){.bg-slate-800\\/90{background-color:color-mix(in oklab, var(--color-slate-800) 90%, transparent)}}.bg-slate-900{background-color:var(--color-slate-900)}.bg-slate-900\\/50{background-color:#0f172b80}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\\/50{background-color:color-mix(in oklab, var(--color-slate-900) 50%, transparent)}}.bg-slate-900\\/60{background-color:#0f172b99}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\\/60{background-color:color-mix(in oklab, var(--color-slate-900) 60%, transparent)}}.bg-slate-900\\/70{background-color:#0f172bb3}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\\/70{background-color:color-mix(in oklab, var(--color-slate-900) 70%, transparent)}}.bg-slate-900\\/80{background-color:#0f172bcc}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\\/80{background-color:color-mix(in oklab, var(--color-slate-900) 80%, transparent)}}.bg-slate-900\\/90{background-color:#0f172be6}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\\/90{background-color:color-mix(in oklab, var(--color-slate-900) 90%, transparent)}}.bg-slate-950{background-color:var(--color-slate-950)}.bg-slate-950\\/60{background-color:#02061899}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/60{background-color:color-mix(in oklab, var(--color-slate-950) 60%, transparent)}}.bg-slate-950\\/70{background-color:#020618b3}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/70{background-color:color-mix(in oklab, var(--color-slate-950) 70%, transparent)}}.bg-slate-950\\/75{background-color:#020618bf}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/75{background-color:color-mix(in oklab, var(--color-slate-950) 75%, transparent)}}.bg-slate-950\\/80{background-color:#020618cc}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/80{background-color:color-mix(in oklab, var(--color-slate-950) 80%, transparent)}}.bg-slate-950\\/85{background-color:#020618d9}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/85{background-color:color-mix(in oklab, var(--color-slate-950) 85%, transparent)}}.bg-slate-950\\/90{background-color:#020618e6}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/90{background-color:color-mix(in oklab, var(--color-slate-950) 90%, transparent)}}.bg-slate-950\\/95{background-color:#020618f2}@supports (color:color-mix(in lab, red, red)){.bg-slate-950\\/95{background-color:color-mix(in oklab, var(--color-slate-950) 95%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-\\[radial-gradient\\(ellipse_at_top\\,_var\\(--tw-gradient-stops\\)\\)\\]{background-image:radial-gradient(ellipse at top, var(--tw-gradient-stops))}.from-\\[\\#180d24\\]{--tw-gradient-from:#180d24;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-500{--tw-gradient-from:var(--color-amber-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-500\\/10{--tw-gradient-from:#f99c001a}@supports (color:color-mix(in lab, red, red)){.from-amber-500\\/10{--tw-gradient-from:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.from-amber-500\\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-500\\/20{--tw-gradient-from:#f99c0033}@supports (color:color-mix(in lab, red, red)){.from-amber-500\\/20{--tw-gradient-from:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.from-amber-500\\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-600{--tw-gradient-from:var(--color-amber-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-900{--tw-gradient-from:var(--color-amber-900);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-amber-900\\/25{--tw-gradient-from:#7b330640}@supports (color:color-mix(in lab, red, red)){.from-amber-900\\/25{--tw-gradient-from:color-mix(in oklab, var(--color-amber-900) 25%, transparent)}}.from-amber-900\\/25{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-cyan-500{--tw-gradient-from:var(--color-cyan-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-emerald-500{--tw-gradient-from:var(--color-emerald-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.from-red-600{--tw-gradient-from:var(--color-red-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.via-\\[\\#1a0f26\\]{--tw-gradient-via:#1a0f26;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-\\[\\#12081c\\]{--tw-gradient-via:#12081c;--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-amber-400{--tw-gradient-via:var(--color-amber-400);--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-amber-400\\/30{--tw-gradient-via:#fcbb004d}@supports (color:color-mix(in lab, red, red)){.via-amber-400\\/30{--tw-gradient-via:color-mix(in oklab, var(--color-amber-400) 30%, transparent)}}.via-amber-400\\/30{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-purple-500\\/20{--tw-gradient-via:#ac4bff33}@supports (color:color-mix(in lab, red, red)){.via-purple-500\\/20{--tw-gradient-via:color-mix(in oklab, var(--color-purple-500) 20%, transparent)}}.via-purple-500\\/20{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.via-slate-900\\/80{--tw-gradient-via:#0f172bcc}@supports (color:color-mix(in lab, red, red)){.via-slate-900\\/80{--tw-gradient-via:color-mix(in oklab, var(--color-slate-900) 80%, transparent)}}.via-slate-900\\/80{--tw-gradient-via-stops:var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-via) var(--tw-gradient-via-position), var(--tw-gradient-to) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-via-stops)}.to-\\[\\#0a0410\\]{--tw-gradient-to:#0a0410;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-\\[\\#0d0714\\]{--tw-gradient-to:#0d0714;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-400{--tw-gradient-to:var(--color-amber-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-500{--tw-gradient-to:var(--color-amber-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-500\\/20{--tw-gradient-to:#f99c0033}@supports (color:color-mix(in lab, red, red)){.to-amber-500\\/20{--tw-gradient-to:color-mix(in oklab, var(--color-amber-500) 20%, transparent)}}.to-amber-500\\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-amber-600{--tw-gradient-to:var(--color-amber-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-cyan-500\\/20{--tw-gradient-to:#00b7d733}@supports (color:color-mix(in lab, red, red)){.to-cyan-500\\/20{--tw-gradient-to:color-mix(in oklab, var(--color-cyan-500) 20%, transparent)}}.to-cyan-500\\/20{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-emerald-400{--tw-gradient-to:var(--color-emerald-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-purple-500\\/10{--tw-gradient-to:#ac4bff1a}@supports (color:color-mix(in lab, red, red)){.to-purple-500\\/10{--tw-gradient-to:color-mix(in oklab, var(--color-purple-500) 10%, transparent)}}.to-purple-500\\/10{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-red-500{--tw-gradient-to:var(--color-red-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-sky-400{--tw-gradient-to:var(--color-sky-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-yellow-400{--tw-gradient-to:var(--color-yellow-400);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.fill-amber-400{fill:var(--color-amber-400)}.fill-amber-400\\/20{fill:#fcbb0033}@supports (color:color-mix(in lab, red, red)){.fill-amber-400\\/20{fill:color-mix(in oklab, var(--color-amber-400) 20%, transparent)}}.fill-cyan-400{fill:var(--color-cyan-400)}.fill-indigo-300{fill:var(--color-indigo-300)}.fill-indigo-300\\/30{fill:#a4b3ff4d}@supports (color:color-mix(in lab, red, red)){.fill-indigo-300\\/30{fill:color-mix(in oklab, var(--color-indigo-300) 30%, transparent)}}.fill-slate-950{fill:var(--color-slate-950)}.fill-white{fill:var(--color-white)}.object-contain{object-fit:contain}.p-0{padding:0}.p-0\\.5{padding:calc(var(--spacing) * .5)}.p-1{padding:var(--spacing)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:var(--spacing)}.px-1\\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0{padding-block:0}.py-0\\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-3\\.5{padding-block:calc(var(--spacing) * 3.5)}.py-4{padding-block:calc(var(--spacing) * 4)}.pt-0{padding-top:0}.pt-0\\.5{padding-top:calc(var(--spacing) * .5)}.pt-1{padding-top:var(--spacing)}.pt-1\\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-6{padding-bottom:calc(var(--spacing) * 6)}.pl-1{padding-left:var(--spacing)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[9px\\]{font-size:9px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-tighter{--tw-tracking:var(--tracking-tighter);letter-spacing:var(--tracking-tighter)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.tracking-widest{--tw-tracking:var(--tracking-widest);letter-spacing:var(--tracking-widest)}.whitespace-nowrap{white-space:nowrap}.text-amber-200{color:var(--color-amber-200)}.text-amber-300{color:var(--color-amber-300)}.text-amber-400{color:var(--color-amber-400)}.text-amber-400\\/90{color:#fcbb00e6}@supports (color:color-mix(in lab, red, red)){.text-amber-400\\/90{color:color-mix(in oklab, var(--color-amber-400) 90%, transparent)}}.text-amber-500{color:var(--color-amber-500)}.text-amber-500\\/80{color:#f99c00cc}@supports (color:color-mix(in lab, red, red)){.text-amber-500\\/80{color:color-mix(in oklab, var(--color-amber-500) 80%, transparent)}}.text-amber-600{color:var(--color-amber-600)}.text-cyan-300{color:var(--color-cyan-300)}.text-cyan-400{color:var(--color-cyan-400)}.text-emerald-400{color:var(--color-emerald-400)}.text-indigo-300{color:var(--color-indigo-300)}.text-orange-400{color:var(--color-orange-400)}.text-purple-300{color:var(--color-purple-300)}.text-red-200{color:var(--color-red-200)}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-sky-300{color:var(--color-sky-300)}.text-sky-400{color:var(--color-sky-400)}.text-slate-100{color:var(--color-slate-100)}.text-slate-200{color:var(--color-slate-200)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-400\\/90{color:#90a1b9e6}@supports (color:color-mix(in lab, red, red)){.text-slate-400\\/90{color:color-mix(in oklab, var(--color-slate-400) 90%, transparent)}}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-950{color:var(--color-slate-950)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.not-italic{font-style:normal}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.accent-amber-400{accent-color:var(--color-amber-400)}.accent-amber-500{accent-color:var(--color-amber-500)}.opacity-75{opacity:.75}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\\[0_0_10px_rgba\\(56\\,189\\,248\\,0\\.5\\)\\]{--tw-shadow:0 0 10px var(--tw-shadow-color,#38bdf880);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\\[0_20px_60px_rgba\\(245\\,158\\,11\\,0\\.25\\)\\]{--tw-shadow:0 20px 60px var(--tw-shadow-color,#f59e0b40);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-amber-400{--tw-shadow-color:oklch(82.8% .189 84.429)}@supports (color:color-mix(in lab, red, red)){.shadow-amber-400{--tw-shadow-color:color-mix(in oklab, var(--color-amber-400) var(--tw-shadow-alpha), transparent)}}.shadow-amber-400\\/50{--tw-shadow-color:#fcbb0080}@supports (color:color-mix(in lab, red, red)){.shadow-amber-400\\/50{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-400) 50%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-amber-500{--tw-shadow-color:oklch(76.9% .188 70.08)}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500{--tw-shadow-color:color-mix(in oklab, var(--color-amber-500) var(--tw-shadow-alpha), transparent)}}.shadow-amber-500\\/10{--tw-shadow-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\\/10{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 10%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-amber-500\\/25{--tw-shadow-color:#f99c0040}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\\/25{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 25%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-amber-500\\/50{--tw-shadow-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.shadow-amber-500\\/50{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-amber-500) 50%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-cyan-500{--tw-shadow-color:oklch(71.5% .143 215.221)}@supports (color:color-mix(in lab, red, red)){.shadow-cyan-500{--tw-shadow-color:color-mix(in oklab, var(--color-cyan-500) var(--tw-shadow-alpha), transparent)}}.shadow-cyan-500\\/50{--tw-shadow-color:#00b7d780}@supports (color:color-mix(in lab, red, red)){.shadow-cyan-500\\/50{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-cyan-500) 50%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-emerald-600{--tw-shadow-color:oklch(59.6% .145 163.225)}@supports (color:color-mix(in lab, red, red)){.shadow-emerald-600{--tw-shadow-color:color-mix(in oklab, var(--color-emerald-600) var(--tw-shadow-alpha), transparent)}}.shadow-emerald-600\\/30{--tw-shadow-color:#0097674d}@supports (color:color-mix(in lab, red, red)){.shadow-emerald-600\\/30{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-emerald-600) 30%, transparent) var(--tw-shadow-alpha), transparent)}}.shadow-red-500{--tw-shadow-color:oklch(63.7% .237 25.331)}@supports (color:color-mix(in lab, red, red)){.shadow-red-500{--tw-shadow-color:color-mix(in oklab, var(--color-red-500) var(--tw-shadow-alpha), transparent)}}.shadow-red-500\\/50{--tw-shadow-color:#fb2c3680}@supports (color:color-mix(in lab, red, red)){.shadow-red-500\\/50{--tw-shadow-color:color-mix(in oklab, color-mix(in oklab, var(--color-red-500) 50%, transparent) var(--tw-shadow-alpha), transparent)}}.ring-amber-500{--tw-ring-color:var(--color-amber-500)}.ring-amber-500\\/40{--tw-ring-color:#f99c0066}@supports (color:color-mix(in lab, red, red)){.ring-amber-500\\/40{--tw-ring-color:color-mix(in oklab, var(--color-amber-500) 40%, transparent)}}.ring-amber-500\\/50{--tw-ring-color:#f99c0080}@supports (color:color-mix(in lab, red, red)){.ring-amber-500\\/50{--tw-ring-color:color-mix(in oklab, var(--color-amber-500) 50%, transparent)}}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-graysc","version_history":[{"id":"v-1.0.0","is_active":true,"created_at":"2026-11-02T17:46:15.981Z","entry_file":"index.html","published_at":"2026-11-02T17:46:15.981Z","health_status":"HEALTHY","release_notes":"","version_number":"1.0.0","storage_location":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvzjvkhx_j7dz8/1.0.0/","processing_status":"COMPLETED","permission_profile":"BASIC_HTML5","security_validation":"PASSED"}]},"controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":0,"created_at":"2026-11-02T17:46:13.043+00:00","updated_at":"2026-11-02T17:46:58.1324+00:00","published_at":"2026-11-02T17:46:13.043+00:00","active_version_id":"e3358e11-803f-46ff-bddb-7e8cec03f6e9","health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":"MANUAL_ADMIN","approved_by":"ashokmuddam5@gmail.com","reviewed_at":"2026-11-02T17:46:57.535+00:00","review_status":"approved","rejection_reason":null,"latest_ai_review_id":"80b97c53-a4a6-4e25-ab80-8d96ad3d6a34","unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"### 🎮 Overview\nCarnage offroad is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","playable_url":"/api/play?id=2faa10f6-022f-431e-8007-fecbc3c66c08"},{"id":"3080a803-0b34-43fc-87f8-b3a9f4ec886e","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"Ping pong","slug":"ping-pong-mvtdx69j","description":"### 🎮 Overview\nPing pong is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","game_type":"html5","category":"casual","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvtdwdxe_33k94/1.0.0/","game_url":"/api/play?id=3080a803-0b34-43fc-87f8-b3a9f4ec886e","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvtdwdxe_33k94/1.0.0/thumbnail.webp","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvtdwdxe_33k94/1.0.0/thumbnail.webp","preview_path":"","preview_url":"","tutorial_data":{"guide":"","entry_file":"index.html","orientation":"any","review_data":{"summary":"All mandatory technical and security verifications passed with low risk (0/100). Package verified safe for deployment.","findings":[],"ai_report":{"status":"NOT_CONFIGURED","summary":"No AI provider API key configured (GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY). Evaluated exclusively using deterministic technical, security, and integrity verification checks.","provider":"NONE","ai_configured":false,"additional_findings":[]},"risk_score":0,"reviewed_at":"2026-10-29T10:12:50.738Z","can_resubmit":false,"quality_score":100,"review_status":"approved","recommendation":"approved","technical_checks":{"metadata":{"passed":true,"message":"Metadata verified"},"entrypoint":{"file":"index.html","passed":true,"message":"Playable entrypoint \"index.html\" verified"},"missing_assets":{"passed":true,"message":"All local asset references verified"},"path_traversal":{"passed":true,"message":"All archive paths clean"},"launch_readiness":{"passed":true,"message":"HTML5 launch integrity verified"},"prohibited_files":{"passed":true,"message":"No prohibited executable files found"},"syntax_validation":{"passed":true,"message":"JavaScript syntax valid"},"security_integrity":{"passed":true,"message":"No suspicious security payloads detected"},"viewport_responsiveness":{"passed":true,"message":"Viewport configured"}},"structured_rejections":[]},"aspect_ratio":"16:9","html_content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, viewport-fit=cover\">\n<title>Ping Pong 2.5D</title>\n<style>\n:root {\n  --bg: #070d18;\n  --panel: rgba(13, 22, 38, 0.85);\n  --line: rgba(255, 255, 255, 0.12);\n  --text: #e6edfa;\n  --muted: #889bb8;\n  --accent: #00d2ff;\n  --accent-p2: #ff3366;\n  --gold: #ffb703;\n}\n* { box-sizing: border-box; user-select: none; }\nbody {\n  margin: 0;\n  padding: 0;\n  width: 100vw;\n  height: 100vh;\n  overflow: hidden;\n  background: var(--bg);\n  color: var(--text);\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n  display: flex;\n  flex-direction: column;\n}\nheader {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  padding: 10px 18px;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  z-index: 10;\n  background: linear-gradient(180deg, rgba(7,13,24,0.92) 0%, rgba(7,13,24,0) 100%);\n  pointer-events: none;\n}\nheader * { pointer-events: auto; }\n.brand {\n  display: flex;\n  align-items: baseline;\n  gap: 10px;\n}\n.brand h1 {\n  margin: 0;\n  font-size: 1.25rem;\n  letter-spacing: 0.05em;\n  text-transform: uppercase;\n  background: linear-gradient(90deg, #00d2ff, #3a86ff);\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n}\n.brand span {\n  font-size: 0.8rem;\n  color: var(--muted);\n}\n.top-controls {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n}\nbutton, input {\n  font: inherit;\n  color: var(--text);\n  background: var(--panel);\n  border: 1px solid var(--line);\n  border-radius: 8px;\n  padding: 6px 12px;\n  backdrop-filter: blur(8px);\n  cursor: pointer;\n  transition: all 0.15s ease;\n}\nbutton:hover {\n  border-color: var(--accent);\n  background: rgba(0, 210, 255, 0.15);\n}\nbutton.active {\n  background: var(--accent);\n  color: #070d18;\n  font-weight: 600;\n  border-color: var(--accent);\n}\n#viewport {\n  width: 100vw;\n  height: 100vh;\n  display: block;\n}\n/* Center HUD overlays */\n#match-banner {\n  position: absolute;\n  top: 64px;\n  left: 50%;\n  transform: translateX(-50%);\n  background: rgba(10, 18, 32, 0.85);\n  border: 1px solid var(--line);\n  padding: 6px 16px;\n  border-radius: 20px;\n  font-size: 0.85rem;\n  color: var(--muted);\n  z-index: 9;\n  display: flex;\n  align-items: center;\n  gap: 10px;\n  pointer-events: none;\n}\n#match-banner b { color: #fff; }\n#status-pill {\n  position: absolute;\n  bottom: 24px;\n  left: 50%;\n  transform: translateX(-50%);\n  background: rgba(13, 22, 38, 0.92);\n  border: 1px solid var(--line);\n  padding: 10px 22px;\n  border-radius: 30px;\n  font-size: 0.95rem;\n  font-weight: 500;\n  letter-spacing: 0.02em;\n  z-index: 9;\n  text-align: center;\n  box-shadow: 0 8px 24px rgba(0,0,0,0.5);\n  pointer-events: none;\n}\n/* Modal Dialog for Matchmaking & Names */\n.modal-overlay {\n  position: absolute;\n  inset: 0;\n  background: rgba(4, 8, 16, 0.75);\n  backdrop-filter: blur(6px);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  z-index: 20;\n}\n.modal {\n  width: 90%;\n  max-width: 440px;\n  background: #0f192b;\n  border: 1.5px solid var(--line);\n  border-radius: 14px;\n  padding: 22px 24px;\n  box-shadow: 0 16px 40px rgba(0,0,0,0.6);\n}\n.modal h2 { margin: 0 0 8px; font-size: 1.25rem; }\n.modal p { color: var(--muted); font-size: 0.9rem; margin-bottom: 18px; line-height: 1.4; }\n.input-group {\n  display: flex;\n  flex-direction: column;\n  gap: 6px;\n  margin-bottom: 16px;\n}\n.input-group label { font-size: 0.8rem; color: var(--muted); }\n.modal-actions {\n  display: flex;\n  gap: 8px;\n  margin-top: 14px;\n}\n.modal-actions button {\n  flex: 1;\n  padding: 10px 0;\n  text-align: center;\n}\n.btn-primary {\n  background: var(--accent) !important;\n  color: #061120 !important;\n  font-weight: 700;\n  border: none !important;\n}\n.btn-alt {\n  background: rgba(255,255,255,0.08);\n}\n</style>\n<!-- Three.js + PeerJS for zero-config WebRTC peer discovery -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js\"></script>\n<script src=\"https://unpkg.com/peerjs@1.5.2/dist/peerjs.min.js\"></script>\n</head>\n<body>\n\n<header>\n  <div class=\"brand\">\n    <h1>Ping Pong</h1>\n    <span>2.5D Top-View</span>\n  </div>\n  <div class=\"top-controls\">\n    <button id=\"btn-camera\" title=\"Toggle strictly 90° top or slight 2.5D angle\">View: Top 90°</button>\n    <button id=\"btn-match\" class=\"active\">Match</button>\n    <button id=\"btn-mute\">Sound: ON</button>\n  </div>\n</header>\n\n<div id=\"match-banner\">\n  <span>Left: <b id=\"lbl-p1\" style=\"color:var(--accent);\">You</b></span>\n  <span>|</span>\n  <span>Right: <b id=\"lbl-p2\" style=\"color:var(--accent-p2);\">CPU (Lightning)</b></span>\n  <span>|</span>\n  <span>Mode: <b id=\"lbl-mode\">CPU Match</b></span>\n</div>\n\n<div id=\"status-pill\">Press Space or Tap table to Serve</div>\n\n<!-- Matchmaking Modal -->\n<div id=\"modal-match\" class=\"modal-overlay\" style=\"display:none;\">\n  <div class=\"modal\">\n    <h2>Player Profile & Matchmaking</h2>\n    <p>Set your callsign and connect with another player via room code, or challenge the predictive bot.</p>\n    \n    <div class=\"input-group\">\n      <label for=\"txt-name\">Your Callsign</label>\n      <input id=\"txt-name\" maxlength=\"14\" placeholder=\"Enter your name\">\n    </div>\n\n    <div class=\"input-group\">\n      <label for=\"txt-room\">Room Code (Leave empty to create)</label>\n      <input id=\"txt-room\" maxlength=\"8\" placeholder=\"e.g. PP77\">\n    </div>\n\n    <div class=\"modal-actions\">\n      <button id=\"btn-connect-p2p\" class=\"btn-primary\">Connect Online</button>\n      <button id=\"btn-play-cpu\" class=\"btn-alt\">Solo vs CPU</button>\n    </div>\n    <div style=\"text-align:center; margin-top:12px;\">\n      <button id=\"btn-modal-close\" style=\"background:transparent; border:none; color:var(--muted); font-size:0.85rem; cursor:pointer;\">Close</button>\n    </div>\n  </div>\n</div>\n\n<div id=\"viewport\"></div>\n\n<script>\n(function(){\n// -------------------------------------------------------------\n// 1. SOUND SYNTHESIS (Web Audio API)\n// -------------------------------------------------------------\nvar audioCtx = null, soundEnabled = true;\nfunction playSound(type){\n  if(!soundEnabled) return;\n  try {\n    audioCtx = audioCtx || new (window.AudioContext || window.webkitAudioContext)();\n    var now = audioCtx.currentTime;\n    var osc = audioCtx.createOscillator();\n    var gain = audioCtx.createGain();\n    osc.connect(gain);\n    gain.connect(audioCtx.destination);\n\n    if(type === 'paddle'){\n      osc.type = 'triangle';\n      osc.frequency.setValueAtTime(480, now);\n      osc.frequency.exponentialRampToValueAtTime(320, now + 0.06);\n      gain.gain.setValueAtTime(0.2, now);\n      gain.gain.exponentialRampToValueAtTime(0.001, now + 0.06);\n      osc.start(now); osc.stop(now + 0.06);\n    } else if(type === 'wall'){\n      osc.type = 'sine';\n      osc.frequency.setValueAtTime(220, now);\n      gain.gain.setValueAtTime(0.12, now);\n      gain.gain.exponentialRampToValueAtTime(0.001, now + 0.05);\n      osc.start(now); osc.stop(now + 0.05);\n    } else if(type === 'score'){\n      osc.type = 'sawtooth';\n      osc.frequency.setValueAtTime(580, now);\n      osc.frequency.exponentialRampToValueAtTime(880, now + 0.18);\n      gain.gain.setValueAtTime(0.2, now);\n      gain.gain.exponentialRampToValueAtTime(0.001, now + 0.22);\n      osc.start(now); osc.stop(now + 0.22);\n    }\n  } catch(e){}\n}\n\n// -------------------------------------------------------------\n// 2. STATE & CONFIGURATION\n// -------------------------------------------------------------\nvar TABLE_W = 50;  // X span: -25 to +25\nvar TABLE_H = 30;  // Z span: -15 to +15 (top view vertical axis)\nvar PAD_W = 1.0, PAD_LEN = 6.4;\nvar BALL_R = 0.55;\n\nvar p1 = { name: \"Player 1\", score: 0, coins: 0, z: 0, vz: 0, isHost: true };\nvar p2 = { name: \"CPU (Fast)\", score: 0, coins: 0, z: 0, vz: 0, isBot: true };\n\ntry {\n  p1.name = localStorage.getItem(\"pp_name\") || \"Player 1\";\n  p1.coins = parseInt(localStorage.getItem(\"pp_coins\")) || 0;\n} catch(e){}\n\nvar ball = {\n  x: 0, y: 0.45, z: 0,\n  vx: 0, vz: 0,\n  speed: 26,\n  inPlay: false,\n  server: 1 // 1 for P1 (left), 2 for P2 (right)\n};\n\nvar matchMode = \"cpu\"; // \"cpu\" or \"p2p\"\nvar peer = null, conn = null;\nvar myPeerId = \"\", guestPeer = null;\nvar isHost = true;\nvar p2pFallbackTimer = null;\nvar cameraMode = \"top\"; // \"top\" (90deg) or \"angled\" (2.5D)\n\n// -------------------------------------------------------------\n// 3. THREE.JS SCENE CREATION\n// -------------------------------------------------------------\nvar container = document.getElementById(\"viewport\");\nvar scene = new THREE.Scene();\nscene.background = new THREE.Color(0x060b14);\n\nvar aspect = window.innerWidth / window.innerHeight;\nvar camera = new THREE.PerspectiveCamera(45, aspect, 1, 300);\nupdateCameraPosition();\n\nvar renderer = new THREE.WebGLRenderer({ antialias: true });\nrenderer.setSize(window.innerWidth, window.innerHeight);\nrenderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));\nrenderer.shadowMap.enabled = true;\nrenderer.shadowMap.type = THREE.PCFSoftShadowMap;\ncontainer.appendChild(renderer.domElement);\n\nfunction updateCameraPosition(){\n  if(cameraMode === \"top\"){\n    camera.position.set(0, 48, 0.001); // Looking straight down\n    camera.lookAt(0, 0, 0);\n  } else {\n    camera.position.set(0, 42, 22); // Angled 2.5D view\n    camera.lookAt(0, -1, -2);\n  }\n}\n\n// Lighting\nvar ambLight = new THREE.AmbientLight(0xffffff, 0.55);\nscene.add(ambLight);\n\nvar mainLight = new THREE.DirectionalLight(0xffffff, 0.85);\nmainLight.position.set(0, 45, 10);\nmainLight.castShadow = true;\nmainLight.shadow.mapSize.width = 1024;\nmainLight.shadow.mapSize.height = 1024;\nscene.add(mainLight);\n\n// Neon stadium accents\nvar p1PointLight = new THREE.PointLight(0x00d2ff, 1.2, 45);\np1PointLight.position.set(-TABLE_W/2, 4, 0);\nscene.add(p1PointLight);\n\nvar p2PointLight = new THREE.PointLight(0xff3366, 1.2, 45);\np2PointLight.position.set(TABLE_W/2, 4, 0);\nscene.add(p2PointLight);\n\n// -------------------------------------------------------------\n// 4. ROYAL BLUE TABLE TOP WITH DYNAMIC CANVAS TEXTURE\n// -------------------------------------------------------------\nvar canvasTex = document.createElement(\"canvas\");\ncanvasTex.width = 1024;\ncanvasTex.height = 512;\nvar ctxTex = canvasTex.getContext(\"2d\");\nvar dynamicTexture = new THREE.CanvasTexture(canvasTex);\n\nfunction updateTableTexture(){\n  // Regulation tournament Royal Blue base\n  var grad = ctxTex.createLinearGradient(0, 0, 1024, 0);\n  grad.addColorStop(0, \"#0e3a6c\");\n  grad.addColorStop(0.5, \"#154c8d\");\n  grad.addColorStop(1, \"#0e3a6c\");\n  ctxTex.fillStyle = grad;\n  ctxTex.fillRect(0, 0, 1024, 512);\n\n  // Outer White Regulation Border\n  ctxTex.strokeStyle = \"#ffffff\";\n  ctxTex.lineWidth = 14;\n  ctxTex.strokeRect(14, 14, 1024 - 28, 512 - 28);\n\n  // Center Longitudinal Line\n  ctxTex.strokeStyle = \"rgba(255, 255, 255, 0.5)\";\n  ctxTex.lineWidth = 6;\n  ctxTex.beginPath();\n  ctxTex.moveTo(14, 256);\n  ctxTex.lineTo(1024 - 14, 256);\n  ctxTex.stroke();\n\n  // Vertical Net Shadow / Line\n  ctxTex.strokeStyle = \"rgba(0, 0, 0, 0.35)\";\n  ctxTex.lineWidth = 10;\n  ctxTex.beginPath();\n  ctxTex.moveTo(512, 14);\n  ctxTex.lineTo(512, 512 - 14);\n  ctxTex.stroke();\n\n  // LEFT SIDE HUD: Player 1 Name, Score, Coins\n  ctxTex.textAlign = \"center\";\n  ctxTex.fillStyle = \"rgba(0, 210, 255, 0.16)\";\n  ctxTex.font = \"bold 150px -apple-system, sans-serif\";\n  ctxTex.fillText(p1.score, 320, 290);\n\n  ctxTex.fillStyle = \"#ffffff\";\n  ctxTex.font = \"bold 32px -apple-system, sans-serif\";\n  ctxTex.fillText(p1.name.toUpperCase(), 320, 110);\n\n  ctxTex.fillStyle = \"#ffd166\";\n  ctxTex.font = \"600 24px -apple-system, sans-serif\";\n  ctxTex.fillText(\"🪙 \" + p1.coins + \" COINS\", 320, 420);\n\n  // RIGHT SIDE HUD: Player 2 Name, Score, Coins\n  ctxTex.fillStyle = \"rgba(255, 51, 102, 0.16)\";\n  ctxTex.font = \"bold 150px -apple-system, sans-serif\";\n  ctxTex.fillText(p2.score, 704, 290);\n\n  ctxTex.fillStyle = \"#ffffff\";\n  ctxTex.font = \"bold 32px -apple-system, sans-serif\";\n  ctxTex.fillText(p2.name.toUpperCase(), 704, 110);\n\n  ctxTex.fillStyle = \"#ffd166\";\n  ctxTex.font = \"600 24px -apple-system, sans-serif\";\n  ctxTex.fillText(\"🪙 \" + p2.coins + \" COINS\", 704, 420);\n\n  dynamicTexture.needsUpdate = true;\n}\nupdateTableTexture();\n\n// Table 3D Mesh\nvar tableGeo = new THREE.BoxGeometry(TABLE_W, 1.2, TABLE_H);\nvar tableMat = new THREE.MeshStandardMaterial({\n  map: dynamicTexture,\n  roughness: 0.38,\n  metalness: 0.12\n});\nvar tableMesh = new THREE.Mesh(tableGeo, tableMat);\ntableMesh.position.set(0, -0.6, 0);\ntableMesh.receiveShadow = true;\nscene.add(tableMesh);\n\n// Table Net\nvar netGeo = new THREE.BoxGeometry(0.3, 1.4, TABLE_H + 1.2);\nvar netMat = new THREE.MeshStandardMaterial({\n  color: 0xffffff,\n  roughness: 0.8,\n  transparent: true,\n  opacity: 0.85\n});\nvar netMesh = new THREE.Mesh(netGeo, netMat);\nnetMesh.position.set(0, 0.7, 0);\nnetMesh.castShadow = true;\nscene.add(netMesh);\n\n// -------------------------------------------------------------\n// 5. PADDLES AND BALL\n// -------------------------------------------------------------\n// Paddle Geometry\nvar paddleGeo = new THREE.CylinderGeometry(PAD_LEN/2, PAD_LEN/2, PAD_W, 16);\npaddleGeo.rotateZ(Math.PI / 2);\n\n// P1 Paddle (Cyan)\nvar pad1Mat = new THREE.MeshStandardMaterial({ color: 0x00d2ff, roughness: 0.3, metalness: 0.2 });\nvar pad1Mesh = new THREE.Mesh(paddleGeo, pad1Mat);\npad1Mesh.position.set(-TABLE_W/2 + 2, 0.5, 0);\npad1Mesh.castShadow = true;\nscene.add(pad1Mesh);\n\n// P2 Paddle (Magenta/Pink)\nvar pad2Mat = new THREE.MeshStandardMaterial({ color: 0xff3366, roughness: 0.3, metalness: 0.2 });\nvar pad2Mesh = new THREE.Mesh(paddleGeo, pad2Mat);\npad2Mesh.position.set(TABLE_W/2 - 2, 0.5, 0);\npad2Mesh.castShadow = true;\nscene.add(pad2Mesh);\n\n// Ball (Glow Orange/Yellow)\nvar ballGeo = new THREE.SphereGeometry(BALL_R, 24, 24);\nvar ballMat = new THREE.MeshStandardMaterial({\n  color: 0xffaa00,\n  roughness: 0.2,\n  emissive: 0xff6600,\n  emissiveIntensity: 0.35\n});\nvar ballMesh = new THREE.Mesh(ballGeo, ballMat);\nballMesh.position.set(0, ball.y, 0);\nballMesh.castShadow = true;\nscene.add(ballMesh);\n\n// -------------------------------------------------------------\n// 6. HIGH-SPEED PREDICTIVE AI ENGINE\n// -------------------------------------------------------------\nfunction computeCpuTarget(){\n  // If ball is traveling away from bot, drift toward center line\n  if(ball.vx <= 0){\n    return 0;\n  }\n  // Raycast trajectory with boundary wall bounces\n  var t = ((TABLE_W/2 - 2) - ball.x) / ball.vx;\n  if(t <= 0) return pad2Mesh.position.z;\n\n  var predictedZ = ball.z + ball.vz * t;\n  var halfH = (TABLE_H/2) - BALL_R;\n\n  // Fold bounces across z = -halfH and z = +halfH\n  var folded = (predictedZ + halfH) % (2 * halfH);\n  if(folded < 0) folded += 2 * halfH;\n  var finalZ = folded - halfH;\n\n  return Math.max(-halfH + PAD_LEN/2, Math.min(halfH - PAD_LEN/2, finalZ));\n}\n\n// -------------------------------------------------------------\n// 7. GAMEPLAY LOOP & CONTINUOUS COLLISION STEPPING\n// -------------------------------------------------------------\nvar targetP1Z = 0;\nvar targetP2Z = 0;\n\nfunction resetServe(serverPlayer){\n  ball.inPlay = false;\n  ball.server = serverPlayer;\n  ball.speed = 28;\n  ball.vx = 0;\n  ball.vz = 0;\n  \n  if(serverPlayer === 1){\n    ball.x = pad1Mesh.position.x + PAD_W/2 + BALL_R + 0.1;\n    ball.z = pad1Mesh.position.z;\n    document.getElementById(\"status-pill\").textContent = isHost ? \"Your Serve! Click / Tap or Space to launch\" : (p1.name + \" is serving...\");\n  } else {\n    ball.x = pad2Mesh.position.x - PAD_W/2 - BALL_R - 0.1;\n    ball.z = pad2Mesh.position.z;\n    document.getElementById(\"status-pill\").textContent = p2.name + \" is serving...\";\n    if(matchMode === \"cpu\"){\n      setTimeout(launchServe, 700);\n    }\n  }\n  ballMesh.position.set(ball.x, ball.y, ball.z);\n}\n\nfunction launchServe(){\n  if(ball.inPlay) return;\n  ball.inPlay = true;\n  var dir = ball.server === 1 ? 1 : -1;\n  var angle = (Math.random() - 0.5) * 0.7; // slight angle\n  ball.vx = dir * ball.speed * Math.cos(angle);\n  ball.vz = ball.speed * Math.sin(angle);\n  playSound('paddle');\n  document.getElementById(\"status-pill\").textContent = \"Rally!\";\n}\n\nfunction handleScore(winner){\n  if(winner === 1){\n    p1.score++;\n    p1.coins += 2;\n    if(p1.score >= 11 && (p1.score - p2.score) >= 2){\n      p1.coins += 25;\n      document.getElementById(\"status-pill\").textContent = p1.name + \" WINS THE MATCH! (+25 Coins)\";\n    } else {\n      document.getElementById(\"status-pill\").textContent = \"Point for \" + p1.name + \"! (+2 Coins)\";\n    }\n    resetServe(1);\n  } else {\n    p2.score++;\n    p2.coins += 2;\n    if(p2.score >= 11 && (p2.score - p1.score) >= 2){\n      p2.coins += 25;\n      document.getElementById(\"status-pill\").textContent = p2.name + \" WINS THE MATCH! (+25 Coins)\";\n    } else {\n      document.getElementById(\"status-pill\").textContent = \"Point for \" + p2.name + \"! (+2 Coins)\";\n    }\n    resetServe(2);\n  }\n  try {\n    localStorage.setItem(\"pp_coins\", p1.coins);\n  } catch(e){}\n  playSound('score');\n  updateTableTexture();\n}\n\nfunction updatePhysics(dt){\n  // 1. Move Player 1 paddle towards target smoothly\n  var p1Bound = TABLE_H/2 - PAD_LEN/2;\n  pad1Mesh.position.z += (targetP1Z - pad1Mesh.position.z) * Math.min(1, dt * 25);\n  pad1Mesh.position.z = Math.max(-p1Bound, Math.min(p1Bound, pad1Mesh.position.z));\n\n  // 2. Move Player 2 paddle (CPU or Remote P2P)\n  if(matchMode === \"cpu\"){\n    targetP2Z = computeCpuTarget();\n    // Ultra-fast responsive tracking rate: dt * 32\n    pad2Mesh.position.z += (targetP2Z - pad2Mesh.position.z) * Math.min(1, dt * 32);\n  } else if(!isHost && guestPeer){\n    // Remote synced position handled via peer\n  }\n  pad2Mesh.position.z = Math.max(-p1Bound, Math.min(p1Bound, pad2Mesh.position.z));\n\n  // If serving, pin ball to server paddle\n  if(!ball.inPlay){\n    if(ball.server === 1){\n      ball.x = pad1Mesh.position.x + PAD_W/2 + BALL_R + 0.1;\n      ball.z = pad1Mesh.position.z;\n    } else {\n      ball.x = pad2Mesh.position.x - PAD_W/2 - BALL_R - 0.1;\n      ball.z = pad2Mesh.position.z;\n    }\n    ballMesh.position.set(ball.x, ball.y, ball.z);\n    return;\n  }\n\n  // Multi-step sub-stepping to prevent tunneling at high velocity\n  var steps = 4;\n  var sdt = dt / steps;\n  var halfH = (TABLE_H / 2) - BALL_R;\n\n  for(var s = 0; s < steps; s++){\n    ball.x += ball.vx * sdt;\n    ball.z += ball.vz * sdt;\n\n    // Boundary Wall Bounces (Top & Bottom)\n    if(ball.z < -halfH){\n      ball.z = -halfH;\n      ball.vz = Math.abs(ball.vz);\n      playSound('wall');\n    } else if(ball.z > halfH){\n      ball.z = halfH;\n      ball.vz = -Math.abs(ball.vz);\n      playSound('wall');\n    }\n\n    // Left Paddle Deflection (P1)\n    var p1X = pad1Mesh.position.x;\n    if(ball.vx < 0 && (ball.x - BALL_R) <= (p1X + PAD_W/2) && (ball.x + BALL_R) >= (p1X - PAD_W/2)){\n      var offset1 = (ball.z - pad1Mesh.position.z) / (PAD_LEN / 2);\n      if(Math.abs(offset1) <= 1.15){\n        ball.x = p1X + PAD_W/2 + BALL_R;\n        ball.speed = Math.min(ball.speed + 1.2, 54); // Accelerate rally\n        var maxAngle = Math.PI * 0.35;\n        var hitAngle = offset1 * maxAngle;\n        ball.vx = ball.speed * Math.cos(hitAngle);\n        ball.vz = ball.speed * Math.sin(hitAngle);\n        playSound('paddle');\n      }\n    }\n\n    // Right Paddle Deflection (P2)\n    var p2X = pad2Mesh.position.x;\n    if(ball.vx > 0 && (ball.x + BALL_R) >= (p2X - PAD_W/2) && (ball.x - BALL_R) <= (p2X + PAD_W/2)){\n      var offset2 = (ball.z - pad2Mesh.position.z) / (PAD_LEN / 2);\n      if(Math.abs(offset2) <= 1.15){\n        ball.x = p2X - PAD_W/2 - BALL_R;\n        ball.speed = Math.min(ball.speed + 1.2, 54); // Accelerate rally\n        var maxAngle2 = Math.PI * 0.35;\n        var hitAngle2 = offset2 * maxAngle2;\n        ball.vx = -ball.speed * Math.cos(hitAngle2);\n        ball.vz = ball.speed * Math.sin(hitAngle2);\n        playSound('paddle');\n      }\n    }\n\n    // Score Checks\n    if(ball.x < -(TABLE_W/2 + 2)){\n      handleScore(2);\n      break;\n    } else if(ball.x > (TABLE_W/2 + 2)){\n      handleScore(1);\n      break;\n    }\n  }\n\n  ballMesh.position.set(ball.x, ball.y, ball.z);\n}\n\n// -------------------------------------------------------------\n// 8. INPUT HANDLING (Touch, Mouse, Keyboard)\n// -------------------------------------------------------------\nvar raycaster = new THREE.Raycaster();\nvar groundPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);\nvar mouseVec = new THREE.Vector2();\n\nfunction updatePointer(clientX, clientY){\n  mouseVec.x = (clientX / window.innerWidth) * 2 - 1;\n  mouseVec.y = -(clientY / window.innerHeight) * 2 + 1;\n  raycaster.setFromCamera(mouseVec, camera);\n  var hitPoint = new THREE.Vector3();\n  if(raycaster.ray.intersectPlane(groundPlane, hitPoint)){\n    if(isHost){\n      targetP1Z = hitPoint.z;\n    } else {\n      targetP2Z = hitPoint.z;\n    }\n  }\n}\n\nwindow.addEventListener(\"pointermove\", function(e){\n  updatePointer(e.clientX, e.clientY);\n});\n\nwindow.addEventListener(\"pointerdown\", function(e){\n  updatePointer(e.clientX, e.clientY);\n  if(!ball.inPlay && ball.server === 1 && isHost){\n    launchServe();\n  }\n});\n\nwindow.addEventListener(\"keydown\", function(e){\n  if(e.code === \"Space\"){\n    e.preventDefault();\n    if(!ball.inPlay){\n      launchServe();\n    }\n  } else if(e.key === \"ArrowUp\" || e.key === \"w\" || e.key === \"W\"){\n    if(isHost) targetP1Z -= 2.0; else targetP2Z -= 2.0;\n  } else if(e.key === \"ArrowDown\" || e.key === \"s\" || e.key === \"S\"){\n    if(isHost) targetP1Z += 2.0; else targetP2Z += 2.0;\n  }\n});\n\n// -------------------------------------------------------------\n// 9. NETWORKING & P2P MATCHMAKING (PeerJS)\n// -------------------------------------------------------------\nfunction initP2P(roomCode){\n  if(peer) peer.destroy();\n  matchMode = \"p2p\";\n  document.getElementById(\"lbl-mode\").textContent = \"Searching P2P...\";\n  document.getElementById(\"status-pill\").textContent = \"Searching for opponent (Auto CPU fallback in 10s)...\";\n\n  // If roomCode provided, join as guest; else create room\n  if(roomCode && roomCode.trim().length > 0){\n    isHost = false;\n    peer = new Peer();\n    peer.on('open', function(){\n      conn = peer.connect(roomCode.trim());\n      setupConnectionHandlers();\n    });\n  } else {\n    isHost = true;\n    var generatedId = \"PP\" + Math.floor(1000 + Math.random() * 9000);\n    peer = new Peer(generatedId);\n    peer.on('open', function(id){\n      myPeerId = id;\n      document.getElementById(\"status-pill\").textContent = \"Room Created: \" + id + \" (Share with friend). Waiting...\";\n    });\n    peer.on('connection', function(incoming){\n      conn = incoming;\n      setupConnectionHandlers();\n    });\n  }\n\n  // 10-second automatic fallback to CPU if no player joins\n  if(p2pFallbackTimer) clearTimeout(p2pFallbackTimer);\n  p2pFallbackTimer = setTimeout(function(){\n    if(matchMode === \"p2p\" && (!conn || !conn.open)){\n      fallbackToCpu(\"No opponent found. Switched seamlessly to CPU Bot.\");\n    }\n  }, 10000);\n}\n\nfunction setupConnectionHandlers(){\n  if(!conn) return;\n  conn.on('open', function(){\n    if(p2pFallbackTimer) clearTimeout(p2pFallbackTimer);\n    document.getElementById(\"lbl-mode\").textContent = \"Online P2P Match\";\n    document.getElementById(\"status-pill\").textContent = \"Opponent connected! Game on.\";\n    \n    // Exchange names\n    conn.send({ type: 'handshake', name: p1.name });\n  });\n\n  conn.on('data', function(data){\n    if(data.type === 'handshake'){\n      p2.name = data.name || \"Online Player\";\n      p2.isBot = false;\n      document.getElementById(\"lbl-p2\").textContent = p2.name;\n      updateTableTexture();\n    } else if(data.type === 'paddle'){\n      if(isHost) targetP2Z = data.z;\n      else targetP1Z = data.z;\n    } else if(data.type === 'sync' && !isHost){\n      // Guest syncs physics from host\n      ball.x = data.bx;\n      ball.z = data.bz;\n      ball.vx = data.bvx;\n      ball.vz = data.bvz;\n      ball.inPlay = data.inPlay;\n      p1.score = data.s1;\n      p2.score = data.s2;\n      pad1Mesh.position.z = data.p1z;\n      updateTableTexture();\n    }\n  });\n\n  conn.on('close', function(){\n    fallbackToCpu(\"Opponent disconnected. Switched back to CPU.\");\n  });\n}\n\nfunction fallbackToCpu(msg){\n  matchMode = \"cpu\";\n  isHost = true;\n  p2.name = \"CPU (Lightning)\";\n  p2.isBot = true;\n  document.getElementById(\"lbl-mode\").textContent = \"CPU Match\";\n  document.getElementById(\"lbl-p2\").textContent = p2.name;\n  document.getElementById(\"status-pill\").textContent = msg;\n  updateTableTexture();\n}\n\n// Host streams state at 30Hz\nsetInterval(function(){\n  if(matchMode === \"p2p\" && conn && conn.open){\n    if(isHost){\n      conn.send({\n        type: 'sync',\n        bx: ball.x, bz: ball.z,\n        bvx: ball.vx, bvz: ball.vz,\n        inPlay: ball.inPlay,\n        s1: p1.score, s2: p2.score,\n        p1z: pad1Mesh.position.z\n      });\n    } else {\n      conn.send({ type: 'paddle', z: pad2Mesh.position.z });\n    }\n  }\n}, 33);\n\n// -------------------------------------------------------------\n// 10. UI & CONTROLS BINDING\n// -------------------------------------------------------------\nvar btnCamera = document.getElementById(\"btn-camera\");\nbtnCamera.addEventListener(\"click\", function(){\n  cameraMode = cameraMode === \"top\" ? \"angled\" : \"top\";\n  btnCamera.textContent = cameraMode === \"top\" ? \"View: Top 90°\" : \"View: Angled 2.5D\";\n  updateCameraPosition();\n});\n\nvar btnMute = document.getElementById(\"btn-mute\");\nbtnMute.addEventListener(\"click\", function(){\n  soundEnabled = !soundEnabled;\n  btnMute.textContent = soundEnabled ? \"Sound: ON\" : \"Sound: OFF\";\n});\n\nvar modalMatch = document.getElementById(\"modal-match\");\ndocument.getElementById(\"btn-match\").addEventListener(\"click\", function(){\n  modalMatch.style.display = \"flex\";\n  document.getElementById(\"txt-name\").value = p1.name;\n});\ndocument.getElementById(\"btn-modal-close\").addEventListener(\"click\", function(){\n  modalMatch.style.display = \"none\";\n});\n\ndocument.getElementById(\"btn-connect-p2p\").addEventListener(\"click\", function(){\n  var nameInput = document.getElementById(\"txt-name\").value.trim();\n  if(nameInput) {\n    p1.name = nameInput;\n    localStorage.setItem(\"pp_name\", p1.name);\n  }\n  var room = document.getElementById(\"txt-room\").value.trim();\n  initP2P(room);\n  updateTableTexture();\n  modalMatch.style.display = \"none\";\n});\n\ndocument.getElementById(\"btn-play-cpu\").addEventListener(\"click\", function(){\n  var nameInput = document.getElementById(\"txt-name\").value.trim();\n  if(nameInput) {\n    p1.name = nameInput;\n    localStorage.setItem(\"pp_name\", p1.name);\n  }\n  fallbackToCpu(\"Solo mode against CPU.\");\n  modalMatch.style.display = \"none\";\n});\n\n// Resize\nwindow.addEventListener(\"resize\", function(){\n  camera.aspect = window.innerWidth / window.innerHeight;\n  camera.updateProjectionMatrix();\n  renderer.setSize(window.innerWidth, window.innerHeight);\n});\n\n// -------------------------------------------------------------\n// 11. MAIN ANIMATION LOOP\n// -------------------------------------------------------------\nvar lastTime = performance.now();\nresetServe(1);\n\nfunction animate(now){\n  requestAnimationFrame(animate);\n  var dt = Math.min((now - lastTime) / 1000, 0.05);\n  lastTime = now;\n\n  updatePhysics(dt);\n  renderer.render(scene, camera);\n}\nrequestAnimationFrame(animate);\n\n})();\n</script>\n</body>\n</html>","version_history":[{"id":"v-1.0.0","is_active":true,"created_at":"2026-10-29T10:12:47.700Z","entry_file":"index.html","published_at":"2026-10-29T10:12:47.700Z","health_status":"HEALTHY","release_notes":"","version_number":"1.0.0","storage_location":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvtdwdxe_33k94/1.0.0/","processing_status":"COMPLETED","permission_profile":"BASIC_HTML5","security_validation":"PASSED"}]},"controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":0,"created_at":"2026-10-29T10:12:44.407+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-29T10:12:44.407+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"### 🎮 Overview\nPing pong is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","playable_url":"/api/play?id=3080a803-0b34-43fc-87f8-b3a9f4ec886e"},{"id":"9c6eafb5-7e2d-4b79-a1f4-a90d1666a2fb","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"skate_rush_3d","slug":"index-mvse369k","description":"### 🎮 Overview\nIndex is an exhilarating multiplayer web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","game_type":"html5","category":"multiplayer","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvse32f7_aq7t6/1.0.0/","game_url":"/api/play?id=9c6eafb5-7e2d-4b79-a1f4-a90d1666a2fb","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvse32f7_aq7t6/1.0.0/thumbnail.webp","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvse32f7_aq7t6/1.0.0/thumbnail.webp","preview_path":"","preview_url":"","tutorial_data":"[object Object]","controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":1,"created_at":"2026-10-28T17:29:38.168+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-28T17:29:38.168+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"### 🎮 Overview\nIndex is an exhilarating multiplayer web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","playable_url":"/api/play?id=9c6eafb5-7e2d-4b79-a1f4-a90d1666a2fb"},{"id":"febaf1b9-eabf-410f-b7d2-50fd38683748","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"Index","slug":"index-mvs4m8q6","description":"### 🎮 Overview\nIndex is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","game_type":"html5","category":"arcade","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvs4m2mr_a5jnv/1.0.0/","game_url":"/api/play?id=febaf1b9-eabf-410f-b7d2-50fd38683748","thumbnail_path":"","thumbnail_url":"","preview_path":"","preview_url":"","tutorial_data":{"guide":"","entry_file":"index.html","orientation":"any","review_data":{"summary":"All mandatory technical and security verifications passed with low risk (0/100). Package verified safe for deployment.","findings":[{"message":"No promotional thumbnail uploaded; placeholder will be used","category":"metadata","severity":"LOW","fix_steps":["Upload a thumbnail image in Step 3 for better visibility."]}],"ai_report":{"status":"NOT_CONFIGURED","summary":"No AI provider API key configured (GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY). Evaluated exclusively using deterministic technical, security, and integrity verification checks.","provider":"NONE","ai_configured":false,"additional_findings":[]},"risk_score":0,"reviewed_at":"2026-10-28T13:04:38.636Z","can_resubmit":false,"quality_score":95,"review_status":"approved","recommendation":"approved","technical_checks":{"metadata":{"passed":true,"message":"Metadata verified"},"entrypoint":{"file":"index.html","passed":true,"message":"Playable entrypoint \"index.html\" verified"},"missing_assets":{"passed":true,"message":"All local asset references verified"},"path_traversal":{"passed":true,"message":"All archive paths clean"},"launch_readiness":{"passed":true,"message":"HTML5 launch integrity verified"},"prohibited_files":{"passed":true,"message":"No prohibited executable files found"},"syntax_validation":{"passed":true,"message":"JavaScript syntax valid"},"security_integrity":{"passed":true,"message":"No suspicious security payloads detected"},"viewport_responsiveness":{"passed":true,"message":"Viewport configured"}},"structured_rejections":[]},"aspect_ratio":"16:9","html_content":"<!doctype html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no\"><meta name=\"description\" content=\"Race & Modify 3D: Offroad Infinity — a browser-based off-road driving game.\"><title>Race & Modify 3D: Offroad Infinity</title><style>\n:root{--gold:#ffc94b;--panel:#101923eF;--line:#ffffff24}*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#111923;color:#fff;font-family:system-ui,-apple-system,Segoe UI,sans-serif;touch-action:manipulation}canvas{display:block;width:100%;height:100%;outline:none}button{font:700 14px system-ui;color:#fff;background:#202f3d;border:1px solid #ffffff30;border-radius:12px;padding:12px 16px;cursor:pointer;box-shadow:0 5px 18px #0004}button:hover{background:#31485a}button:disabled{opacity:.45;cursor:not-allowed}.primary{background:linear-gradient(135deg,#f5b82e,#e97822);color:#151a1e;border:0}.screen{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;padding:18px;background:linear-gradient(180deg,#09111b66,#07101bd9)}.panel{width:min(560px,96vw);max-height:90vh;overflow:auto;background:var(--panel);border:1px solid var(--line);border-radius:22px;padding:24px;backdrop-filter:blur(12px);box-shadow:0 20px 70px #0007}.panel h1{font-size:clamp(28px,5vw,46px);line-height:1.02;margin:0 0 8px;letter-spacing:-1px}.eyebrow{color:var(--gold);font-size:12px;letter-spacing:2px;font-weight:900}.sub{color:#c4d0d9;line-height:1.5}.buttons{display:flex;flex-wrap:wrap;gap:10px;margin-top:18px}.row{display:flex;justify-content:space-between;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--line)}.row:last-child{border:0}.small{font-size:12px;color:#b8c5cf}.hidden{display:none!important}#hud{position:absolute;inset:0;pointer-events:none;padding:16px;display:none}#hud button,#hud .touch button{pointer-events:auto}.hudtop{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}.chip{background:#0b1522cc;border:1px solid var(--line);padding:9px 12px;border-radius:12px;font-weight:800;text-shadow:0 1px 4px #000}.hudright{display:flex;gap:8px;align-items:flex-start}.speed{position:absolute;right:18px;bottom:18px;font-size:28px;font-weight:900;text-align:right;text-shadow:0 3px 8px #000}.speed small{display:block;font-size:11px;letter-spacing:2px;color:#d1dce4}.nitro{width:150px;height:8px;background:#273643;border-radius:10px;margin-top:7px;overflow:hidden}.nitro span{display:block;height:100%;width:100%;background:#3ad8ff}.tutorial{position:absolute;left:50%;top:18%;transform:translateX(-50%);width:min(440px,90vw);text-align:center;background:#0b1522ed;border:1px solid #ffffff30;border-radius:16px;padding:16px;pointer-events:auto}.touch{position:absolute;bottom:18px;left:18px;right:18px;display:none;justify-content:space-between;align-items:flex-end;gap:10px;pointer-events:none}.touch .cluster{display:flex;gap:8px;pointer-events:auto}.touch button{min-width:62px;min-height:62px;background:#0b1522cc;border-radius:18px;font-size:20px;touch-action:none;user-select:none}.touch .gas{min-width:78px;min-height:78px;background:#a95e19dc}.touch .brake{background:#8d2929dd}.garagegrid{display:grid;grid-template-columns:1fr 1fr;gap:10px}.option{padding:12px;border:1px solid var(--line);border-radius:12px;background:#ffffff08}.option strong{display:block;margin-bottom:4px}.swatches{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0}.swatch{width:30px;height:30px;border-radius:50%;border:2px solid #ffffff77;padding:0}.notice{font-size:12px;color:#b8c5cf;margin-top:12px}@media(max-width:700px){.panel{padding:18px}.touch{display:flex}#hud{padding:10px}.chip{font-size:12px;padding:8px}.speed{bottom:112px;font-size:23px}.hudright{flex-wrap:wrap;justify-content:flex-end}.hudright button{padding:9px}.garagegrid{grid-template-columns:1fr}.tutorial{top:24%}}\n</style></head><body><div id=\"boot\" class=\"screen\"><div class=\"panel\"><div class=\"eyebrow\">TRITECH PRESENTS</div><h1>RACE & MODIFY<br><span style=\"color:var(--gold)\">3D: OFFROAD INFINITY</span></h1><p class=\"sub\">Stay on the winding trail, dodge rocks and timber barriers, collect fewer valuable coins, and tune your vehicle in the garage.</p><p class=\"small\">Loading 3D engine… An internet connection is required for the Three.js runtime.</p></div></div><div id=\"menu\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">ENDLESS OFF-ROAD ADVENTURE</div><h1>Race. Collect.<br><span style=\"color:var(--gold)\">Modify.</span></h1><p class=\"sub\">Drive winding mountain trails, feel the wheels react to rough ground, collect coins and tune your ride.</p><div class=\"buttons\"><button class=\"primary\" id=\"startBtn\">▶ Start Drive</button><button id=\"garageBtn\">🔧 Garage</button><button id=\"helpBtn\">Controls & Tutorial</button><button id=\"settingsBtn\">Settings</button><button id=\"resetBtn\">Reset Progress</button></div><p class=\"notice\">Your coins and upgrades save in this browser only. They do not sync between devices.</p></div></div><div id=\"garage\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">WORKSHOP / TUNING</div><h1>Garage</h1><p class=\"sub\">Balance: <strong id=\"garageCoins\">0</strong> coins</p><div id=\"vehicleOptions\" class=\"garagegrid\"></div><div class=\"row\"><div><strong>Paint colour</strong><div class=\"small\">Cosmetic • applies to your selected vehicle</div></div></div><div class=\"swatches\" id=\"swatches\"></div><div id=\"upgradeOptions\"></div><div class=\"buttons\"><button id=\"garageBack\">Back</button><button class=\"primary\" id=\"garageDrive\">Start Drive →</button></div></div></div><div id=\"help\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">LEARN THE TRAIL</div><h1>Controls & Tutorial</h1><p class=\"sub\"><b>Desktop:</b> W / ↑ accelerate · S / ↓ brake/reverse · A/D or ←/→ steer · Shift nitro · Space handbrake · C camera · R recover · Esc pause.</p><p class=\"sub\"><b>Mobile:</b> hold the steering, throttle and brake buttons. You can steer and accelerate simultaneously.</p><p class=\"sub\"><b>Driving tips:</b> slow down before tight bends; rocks compress individual suspension corners; collect occasional gold coins (1 coin each); rocks and timber obstacles now appear on the trail; use nitro on straights. Recover if stuck or overturned.</p><div class=\"buttons\"><button id=\"helpBack\">Back</button><button class=\"primary\" id=\"helpDrive\">Let's Drive</button></div></div></div><div id=\"settings\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">PREFERENCES</div><h1>Settings</h1><div class=\"row\"><span>Sound effects</span><button id=\"soundToggle\">Sound: ON</button></div><div class=\"row\"><span>Graphics quality</span><button id=\"qualityToggle\">Quality: HIGH</button></div><p class=\"notice\">Settings are stored locally. Lower quality reduces shadows and scenery density on slower devices.</p><div class=\"buttons\"><button id=\"settingsBack\">Back</button></div></div></div><div id=\"pause\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">TAKE A BREATHER</div><h1>Paused</h1><p class=\"sub\">Your run is safe. Resume the trail or head back to the garage.</p><div class=\"buttons\"><button class=\"primary\" id=\"resumeBtn\">Resume</button><button id=\"recoverBtn\">Recover</button><button id=\"pauseGarage\">Garage</button><button id=\"restartBtn\">Restart Run</button></div></div></div><div id=\"summary\" class=\"screen hidden\"><div class=\"panel\"><div class=\"eyebrow\">RUN COMPLETE</div><h1>Trail report</h1><p class=\"sub\" id=\"summaryText\"></p><div class=\"buttons\"><button class=\"primary\" id=\"againBtn\">Drive Again</button><button id=\"summaryGarage\">Garage</button><button id=\"summaryMenu\">Main Menu</button></div></div></div><div id=\"hud\"><div class=\"hudtop\"><div><div class=\"chip\">🪙 <span id=\"coins\">0</span></div><div class=\"chip\" style=\"margin-top:8px\">DIST <span id=\"distance\">0</span> m</div></div><div class=\"hudright\"><button id=\"hudTutorial\">? Tutorial</button><button id=\"cameraBtn\">📷 C</button><button id=\"hudRecover\">↻ Recover</button><button id=\"pauseBtn\">Ⅱ</button></div></div><div class=\"speed\"><span id=\"speed\">0</span> <small>KM/H</small><div class=\"nitro\"><span id=\"nitroBar\"></span></div><small>NITRO</small></div><div id=\"tutorialCard\" class=\"tutorial hidden\"><strong>FIRST DRIVE: FOLLOW THE TRAIL</strong><p class=\"sub\" id=\"tutorialText\">Hold W or ↑ to accelerate. Use A/D to steer around rocks and collect coins.</p><button class=\"primary\" id=\"tutorialNext\">Got it</button></div><div class=\"touch\" id=\"touchControls\"><div class=\"cluster\"><button data-control=\"left\" aria-label=\"Steer left\">LEFT ◀</button><button data-control=\"right\" aria-label=\"Steer right\">▶ RIGHT</button></div><div class=\"cluster\"><button class=\"brake\" data-control=\"brake\">▼</button><button class=\"gas\" data-control=\"gas\">▲</button><button data-control=\"nitro\">⚡</button></div></div></div><div id=\"error\" class=\"screen hidden\"><div class=\"panel\"><h1>3D engine unavailable</h1><p class=\"sub\">This browser could not load WebGL or the Three.js runtime. Try an updated Chrome, Edge or Safari browser with WebGL enabled and an internet connection.</p><div class=\"buttons\"><button id=\"errorRetry\" class=\"primary\">Retry</button></div></div></div>\n<script type=\"module\">\nimport * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.166.1/build/three.module.js';\nconst $=id=>document.getElementById(id);const screens=['menu','garage','help','settings','pause','summary','error'];let scene,camera,renderer,clock,car,roadGroup,worldGroup,coinGroup,rockGroup,treeGroup,billboardGroup;let mode='menu',paused=false,quality='HIGH',soundOn=true,cameraMode=0;let held={left:false,right:false,gas:false,brake:false,nitro:false};let coins=[],rocks=[],checkpoints=[],keys={};let billboardAdSlots=[];let runDistance=0,bestDistance=0,speed=0,forwardVel=0,sideVel=0,verticalVel=0,carY=0,carPitch=0,carRoll=0,steer=0,nitro=100,runCoins=0,checkpoint=0,lastReward=0,shake=0,coinCooldown=0, tutorialStage=0;const saveKey='offroadInfinitySaveV1';const vehicleDefs=[{name:'Trailblazer 4x4',price:0,mass:1450,accel:18,max:118,grip:1.05,susp:1.0,brake:24,clearance:.8,desc:'Balanced all-rounder'},{name:'Rally Lynx',price:180,mass:1050,accel:24,max:152,grip:1.2,susp:.78,brake:28,clearance:.58,desc:'Light, quick and nimble'},{name:'Thunder Monster',price:420,mass:2200,accel:15,max:105,grip:.95,susp:1.5,brake:22,clearance:1.2,desc:'Big wheels, long travel'},{name:'Rock Crawler',price:600,mass:1850,accel:13,max:92,grip:1.35,susp:1.7,brake:26,clearance:1.35,desc:'Maximum grip on rough trails'}];const upgradeDefs=[{key:'engine',name:'Engine',base:100,desc:'Acceleration and top speed'},{key:'suspension',name:'Suspension',base:90,desc:'Travel and rock absorption'},{key:'tires',name:'All-terrain tires',base:85,desc:'Grip on loose surfaces'},{key:'brakes',name:'Brakes',base:80,desc:'Shorter stopping distance'},{key:'nitro',name:'Nitro tank',base:110,desc:'Larger boost capacity'},{key:'clearance',name:'Ground clearance',base:95,desc:'Less underbody rock contact'}];let data={version:1,balance:0,owned:[0],selected:0,paint:'#e69a25',upgrades:{engine:0,suspension:0,tires:0,brakes:0,nitro:0,clearance:0},best:0,sound:true,quality:'HIGH'};function loadSave(){try{const raw=JSON.parse(localStorage.getItem(saveKey)||'null');if(raw&&raw.version===1){data.balance=clampInt(raw.balance,0,1e7,0);data.owned=Array.isArray(raw.owned)?[...new Set(raw.owned.filter(x=>Number.isInteger(x)&&x>=0&&x<vehicleDefs.length))]:[0];if(!data.owned.includes(0))data.owned.unshift(0);data.selected=data.owned.includes(raw.selected)?raw.selected:0;data.paint=/^#[0-9a-f]{6}$/i.test(raw.paint)?raw.paint:'#e69a25';for(const u of upgradeDefs)data.upgrades[u.key]=clampInt(raw.upgrades?.[u.key],0,5,0);data.best=clampInt(raw.best,0,1e9,0);data.sound=raw.sound!==false;data.quality=raw.quality==='LOW'?'LOW':'HIGH';}}catch(e){console.warn('Save was invalid; starting safely.',e)}soundOn=data.sound;quality=data.quality;bestDistance=data.best;}function clampInt(v,min,max,def){return Number.isFinite(v)?Math.max(min,Math.min(max,Math.floor(v))):def}function save(){try{localStorage.setItem(saveKey,JSON.stringify(data))}catch(e){console.warn('Local save unavailable',e)}}function show(id){screens.forEach(s=>$(s).classList.add('hidden'));if(id)$(id).classList.remove('hidden');}function audio(freq=500,duration=.08,type='sine',vol=.035){if(!soundOn)return;try{const ctx=audio.ctx||(audio.ctx=new AudioContext());const o=ctx.createOscillator(),g=ctx.createGain();o.type=type;o.frequency.value=freq;g.gain.value=vol;o.connect(g);g.connect(ctx.destination);o.start();g.gain.exponentialRampToValueAtTime(.0001,ctx.currentTime+duration);o.stop(ctx.currentTime+duration)}catch{}}\nfunction init3D(){scene=new THREE.Scene();scene.background=new THREE.Color(0x91b8ca);scene.fog=new THREE.Fog(0x91b8ca,70,245);camera=new THREE.PerspectiveCamera(62,innerWidth/innerHeight,.1,500);renderer=new THREE.WebGLRenderer({antialias:true,powerPreference:'high-performance'});renderer.setSize(innerWidth,innerHeight);renderer.setPixelRatio(Math.min(devicePixelRatio,quality==='LOW'?1.2:1.7));renderer.shadowMap.enabled=quality==='HIGH';renderer.shadowMap.type=THREE.PCFSoftShadowMap;renderer.outputColorSpace=THREE.SRGBColorSpace;document.body.prepend(renderer.domElement);clock=new THREE.Clock();scene.add(new THREE.HemisphereLight(0xd8efff,0x564832,2.0));const sun=new THREE.DirectionalLight(0xffedca,3.0);sun.position.set(-25,45,18);sun.castShadow=quality==='HIGH';sun.shadow.mapSize.set(1024,1024);scene.add(sun);const ground=new THREE.Mesh(new THREE.PlaneGeometry(700,700),new THREE.MeshStandardMaterial({color:0x8a8760,roughness:1}));ground.rotation.x=-Math.PI/2;ground.position.y=-1.5;ground.receiveShadow=true;scene.add(ground);worldGroup=new THREE.Group();scene.add(worldGroup);roadGroup=new THREE.Group();scene.add(roadGroup);coinGroup=new THREE.Group();scene.add(coinGroup);rockGroup=new THREE.Group();scene.add(rockGroup);treeGroup=new THREE.Group();scene.add(treeGroup);billboardGroup=new THREE.Group();scene.add(billboardGroup);buildScenery();buildCar();makeTrack();camera.position.set(0,5,10);camera.lookAt(0,0,0);window.addEventListener('resize',resize);animate();}\nfunction resize(){if(!renderer)return;camera.aspect=innerWidth/innerHeight;camera.updateProjectionMatrix();renderer.setSize(innerWidth,innerHeight);renderer.setPixelRatio(Math.min(devicePixelRatio,quality==='LOW'?1.2:1.7))}\nfunction buildScenery(){const mat=new THREE.MeshStandardMaterial({color:0x696c62,roughness:1});for(let i=0;i<35;i++){const h=8+Math.random()*23,r=8+Math.random()*14;const m=new THREE.Mesh(new THREE.ConeGeometry(r,h,5),mat);m.position.set((Math.random()-.5)*260,h/2-1,(Math.random()-.5)*300-60);m.rotation.y=Math.random()*3;m.receiveShadow=true;worldGroup.add(m)}for(let i=0;i<(quality==='LOW'?30:65);i++){let x=0,z=0,p=null,tries=0;/* Place every tree safely outside the road corridor, including bends. */do{z=-Math.random()*240;p=pathAt(z);const side=Math.random()<.5?-1:1;x=p.x+side*(10.5+Math.random()*24);tries++}while(tries<12&&Math.abs(x-pathAt(z).x)<10);const trunk=new THREE.Mesh(new THREE.CylinderGeometry(.15,.25,2.4,5),new THREE.MeshStandardMaterial({color:0x57402b}));trunk.position.set(x,0,z);const crown=new THREE.Mesh(new THREE.ConeGeometry(1.5+Math.random(),3+Math.random()*2,6),new THREE.MeshStandardMaterial({color:Math.random()>.5?0x2f633b:0x426d3c}));crown.position.set(x,2.2,z);treeGroup.add(trunk,crown)}}\nfunction pathAt(z){const d=-z;return {x:Math.sin(d*.014)*13+Math.sin(d*.0038)*20,y:Math.sin(d*.018)*1.4+Math.sin(d*.006)*2.5}}function makeTrack(){roadGroup.clear();coinGroup.clear();rockGroup.clear();if(billboardGroup)billboardGroup.clear();billboardAdSlots=[];coins=[];rocks=[];const pts=[];for(let z=45;z>=-5000;z-=3){const p=pathAt(z);pts.push(new THREE.Vector3(p.x,p.y,z))}const curve=new THREE.CatmullRomCurve3(pts);const verts=[],indices=[],uv=[];const seg=1700;for(let i=0;i<=seg;i++){const t=i/seg,p=curve.getPoint(t),tan=curve.getTangent(t),side=new THREE.Vector3(-tan.z,0,tan.x).normalize();for(const w of [-1,1]){verts.push(p.x+side.x*w*5,p.y-.12,p.z+side.z*w*5);uv.push(w===-1?0:1,t*20)}}for(let i=0;i<seg;i++){let a=i*2;indices.push(a,a+1,a+2,a+1,a+3,a+2)}const geo=new THREE.BufferGeometry();geo.setAttribute('position',new THREE.Float32BufferAttribute(verts,3));geo.setAttribute('uv',new THREE.Float32BufferAttribute(uv,2));geo.setIndex(indices);geo.computeVertexNormals();const road=new THREE.Mesh(geo,new THREE.MeshStandardMaterial({color:0x665d4e,roughness:1,side:THREE.DoubleSide}));road.receiveShadow=true;roadGroup.add(road);for(let i=0;i<220;i++){const z=30-i*22.0,p=pathAt(z);const offset=(Math.random()-.5)*5.2;const coin=makeCoin();coin.position.set(p.x+offset,p.y+1.1,z);coinGroup.add(coin);coins.push({mesh:coin,taken:false})}for(let i=0;i<125;i++){const z=20-i*9.0,p=pathAt(z);const side=(Math.random()>.5?1:-1)*(5.5+Math.random()*3.4);const rock=makeRock(.45+Math.random()*1.15);rock.position.set(p.x+side,p.y-.1,z);rockGroup.add(rock);rocks.push({mesh:rock,r:rock.userData.r})}/* Drivable-track obstacles: small rocks and timber barriers with fair gaps. */for(let i=0;i<62;i++){const z=-35-i*76-(Math.random()*18);const p=pathAt(z);const side=(Math.random()-.5)*5.8;const rock=makeRock(.38+Math.random()*.48);rock.position.set(p.x+side,p.y-.08,z);rockGroup.add(rock);rocks.push({mesh:rock,r:rock.userData.r})}/* Roadside billboards: alternating signs sit safely beyond both road edges. */\nconst billboardColors=[['#183b32','#f6d36b'],['#27384d','#ffffff'],['#713a22','#ffe0a0'],['#263b55','#ffc94b']];\nfunction makeBillboardTexture(title,subtitle,bg,fg){const canvas=document.createElement('canvas');canvas.width=512;canvas.height=256;const ctx=canvas.getContext('2d');drawBillboardCanvas(ctx,{title,subtitle,bg,fg});const tex=new THREE.CanvasTexture(canvas);tex.colorSpace=THREE.SRGBColorSpace;return tex;}\nfunction drawBillboardCanvas(ctx,ad={}){const bg=typeof ad.bg==='string'&&/^#[0-9a-f]{6}$/i.test(ad.bg)?ad.bg:'#183b32',fg=typeof ad.fg==='string'&&/^#[0-9a-f]{6}$/i.test(ad.fg)?ad.fg:'#f6d36b';ctx.clearRect(0,0,512,256);ctx.fillStyle=bg;ctx.fillRect(0,0,512,256);ctx.strokeStyle='#d5b46a';ctx.lineWidth=12;ctx.strokeRect(8,8,496,240);ctx.fillStyle=fg;ctx.textAlign='center';ctx.font='bold 39px Arial';ctx.fillText(String(ad.title||'OFFROAD INFINITY').slice(0,26),256,104);ctx.font='bold 24px Arial';ctx.fillText(String(ad.subtitle||'EXPLORE THE TRAIL').slice(0,38),256,151);ctx.font='bold 17px Arial';ctx.fillText(String(ad.cta||'RACE • COLLECT • MODIFY').slice(0,38),256,204);}\nfunction updateBillboardAds(ads){if(!Array.isArray(ads))return;billboardAdSlots.forEach((slot,i)=>{const ad=ads[i%ads.length];if(!ad||typeof ad!=='object')return;const canvas=slot.texture.image,ctx=canvas.getContext('2d');drawBillboardCanvas(ctx,ad);slot.texture.needsUpdate=true;});}\n/* Website/game integrations can send ad copy to the billboards with postMessage, or set window.OFFROAD_BILLBOARD_ADS before the game loads. Use only creatives approved for in-game display by the provider. */window.addEventListener('message',event=>{if(event.data&&event.data.type==='OFFROAD_BILLBOARD_ADS'&&Array.isArray(event.data.ads))updateBillboardAds(event.data.ads)});\nconst boardTexts=[['OFFROAD INFINITY','EXPLORE THE TRAIL'],['SLOW DOWN','ROCKY BEND AHEAD'],['TRITECH TRAIL','4×4 ADVENTURE'],['CHECKPOINT','KEEP ON DRIVING']];\nbillboardAdSlots=[];for(let i=0;i<24;i++){const z=-55-i*205,p=pathAt(z),side=(i%2===0?-1:1),x=p.x+side*(7.7+Math.random()*.7),y=p.y;const sign=new THREE.Group();const postMat=new THREE.MeshStandardMaterial({color:0x42494a,metalness:.55,roughness:.65});for(const px of [-1.42,1.42]){const post=new THREE.Mesh(new THREE.BoxGeometry(.16,2.65,.16),postMat);post.position.set(px,-.55,0);post.castShadow=true;sign.add(post);const foot=new THREE.Mesh(new THREE.BoxGeometry(.42,.12,.42),postMat);foot.position.set(px,-1.82,0);sign.add(foot)}const [title,subtitle]=boardTexts[i%boardTexts.length],palette=billboardColors[i%billboardColors.length];const tex=makeBillboardTexture(title,subtitle,palette[0],palette[1]);const boardMat=new THREE.MeshStandardMaterial({map:tex,roughness:.82,side:THREE.DoubleSide});const board=new THREE.Mesh(new THREE.PlaneGeometry(3.25,1.62),boardMat);board.position.set(0,.45,.04);board.castShadow=true;sign.add(board);billboardAdSlots.push({texture:tex});sign.position.set(x,y+2.1,z);billboardGroup.add(sign)}if(Array.isArray(window.OFFROAD_BILLBOARD_ADS))updateBillboardAds(window.OFFROAD_BILLBOARD_ADS);\nfor(let i=0;i<100;i++){const z=-i*45-10,p=pathAt(z);const gate=new THREE.Group();const mat=new THREE.MeshStandardMaterial({color:0xe8b83d,emissive:0x694500});for(const x of [-5.7,5.7]){const post=new THREE.Mesh(new THREE.BoxGeometry(.25,2.4,.25),mat);post.position.set(p.x+x,p.y+1.2,z);gate.add(post)}const bar=new THREE.Mesh(new THREE.BoxGeometry(11.6,.18,.2),mat);bar.position.set(p.x,p.y+2.4,z);gate.add(bar);worldGroup.add(gate);checkpoints.push({z,rewarded:false})}}\nfunction makeCoin(){const g=new THREE.Group();const gold=new THREE.MeshStandardMaterial({color:0xffc928,metalness:.8,roughness:.22,emissive:0x5d3b00});const m=new THREE.Mesh(new THREE.TorusGeometry(.35,.12,8,16),gold);m.rotation.y=Math.PI/2;g.add(m);const core=new THREE.Mesh(new THREE.CylinderGeometry(.22,.22,.07,16),gold);core.rotation.x=Math.PI/2;g.add(core);g.userData.baseY=0;return g}function makeRock(size){const m=new THREE.Mesh(new THREE.DodecahedronGeometry(size,1),new THREE.MeshStandardMaterial({color:0x77766c,roughness:1}));m.scale.set(1+Math.random()*.5,.7+Math.random()*.7,.8+Math.random()*.5);m.rotation.set(Math.random(),Math.random(),Math.random());m.castShadow=true;m.receiveShadow=true;m.userData.r=size*1.1;return m}\nfunction buildCar(){if(car)scene.remove(car);car=new THREE.Group();const bodyMat=new THREE.MeshStandardMaterial({color:data.paint,metalness:.35,roughness:.35});const dark=new THREE.MeshStandardMaterial({color:0x182027,metalness:.22,roughness:.62});const glass=new THREE.MeshStandardMaterial({color:0x263f50,metalness:.5,roughness:.18});const steel=new THREE.MeshStandardMaterial({color:0x9ba5a8,metalness:.78,roughness:.28});const lamp=new THREE.MeshStandardMaterial({color:0xffedb0,emissive:0x8c6a20,emissiveIntensity:.7});const body=new THREE.Mesh(new THREE.BoxGeometry(2.28,.72,3.65),bodyMat);body.position.y=.88;body.castShadow=true;car.add(body);const hood=new THREE.Mesh(new THREE.BoxGeometry(2.12,.3,1.22),bodyMat);hood.position.set(0,1.22,-1.05);car.add(hood);const cabin=new THREE.Mesh(new THREE.BoxGeometry(1.68,.78,1.58),glass);cabin.position.set(0,1.53,.35);cabin.castShadow=true;car.add(cabin);/* raised off-road stance, fender flares, rock sliders and heavy bumpers */const lift=new THREE.Mesh(new THREE.BoxGeometry(2.52,.16,2.55),dark);lift.position.set(0,.62,.05);car.add(lift);for(const x of [-1.18,1.18]){const flare=new THREE.Mesh(new THREE.BoxGeometry(.16,.36,1.28),dark);flare.position.set(x,.9,-.98);car.add(flare);const rearFlare=flare.clone();rearFlare.position.z=1.18;car.add(rearFlare);const slider=new THREE.Mesh(new THREE.BoxGeometry(.16,.18,2.35),steel);slider.position.set(x*1.02,.48,.05);car.add(slider)}const bumper=new THREE.Mesh(new THREE.BoxGeometry(2.55,.28,.3),dark);bumper.position.set(0,.52,-1.93);car.add(bumper);const rearBumper=new THREE.Mesh(new THREE.BoxGeometry(2.45,.22,.25),dark);rearBumper.position.set(0,.5,1.9);car.add(rearBumper);/* tubular front bull bar and winch */for(const x of [-.92,.92]){const post=new THREE.Mesh(new THREE.CylinderGeometry(.055,.055,.72,8),steel);post.position.set(x,.78,-1.98);post.rotation.x=-.22;car.add(post)}const bull=new THREE.Mesh(new THREE.CylinderGeometry(.055,.055,1.95,8),steel);bull.rotation.z=Math.PI/2;bull.position.set(0,1.08,-2.03);car.add(bull);const winch=new THREE.Mesh(new THREE.BoxGeometry(.48,.22,.18),steel);winch.position.set(0,.62,-2.1);car.add(winch);/* roof rack with crossbars and auxiliary lamps */const rackBase=new THREE.Mesh(new THREE.BoxGeometry(1.82,.09,1.55),dark);rackBase.position.set(0,1.98,.35);car.add(rackBase);for(const x of [-.82,.82]){const rail=new THREE.Mesh(new THREE.BoxGeometry(.07,.12,1.65),steel);rail.position.set(x,2.06,.35);car.add(rail)}for(const z of [-.36,.35,1.02]){const cross=new THREE.Mesh(new THREE.BoxGeometry(1.75,.07,.07),steel);cross.position.set(0,2.06,z);car.add(cross)}for(const x of [-.58,-.2,.2,.58]){const spot=new THREE.Mesh(new THREE.CylinderGeometry(.11,.11,.12,12),lamp);spot.rotation.x=Math.PI/2;spot.position.set(x,2.13,-.15);car.add(spot)}/* snorkel on the left A-pillar */const snorkel=new THREE.Mesh(new THREE.CylinderGeometry(.07,.07,1.15,8),dark);snorkel.position.set(-.88,1.65,-.55);car.add(snorkel);const snorkelTop=new THREE.Mesh(new THREE.CylinderGeometry(.11,.08,.18,8),steel);snorkelTop.position.set(-.88,2.22,-.55);car.add(snorkelTop);/* rear-mounted spare tire */const spare=new THREE.Mesh(new THREE.TorusGeometry(.37,.14,8,18),dark);spare.position.set(.62,1.08,1.96);car.add(spare);const spareHub=new THREE.Mesh(new THREE.CylinderGeometry(.18,.18,.12,12),steel);spareHub.rotation.x=Math.PI/2;spareHub.position.set(.62,1.08,2.03);car.add(spareHub);car.userData.wheels=[];const wheelR=data.selected===2?.68:(data.selected===3?.61:.54);for(const x of [-1.18,1.18])for(const z of [-1.18,1.25]){const pivot=new THREE.Group();pivot.position.set(x,.57,z);const tire=new THREE.Mesh(new THREE.CylinderGeometry(wheelR,wheelR,.4,20),dark);tire.rotation.z=Math.PI/2;tire.castShadow=true;pivot.add(tire);/* chunky all-terrain tread blocks */for(let k=0;k<12;k++){const tread=new THREE.Mesh(new THREE.BoxGeometry(.29,.11,.13),dark);const a=k*Math.PI/6;tread.position.set(Math.cos(a)*(wheelR-.015),Math.sin(a)*(wheelR-.015),0);tread.rotation.z=a;pivot.add(tread)}const hub=new THREE.Mesh(new THREE.CylinderGeometry(wheelR*.43,wheelR*.43,.43,12),steel);hub.rotation.z=Math.PI/2;pivot.add(hub);const hubCap=new THREE.Mesh(new THREE.CylinderGeometry(wheelR*.18,wheelR*.18,.45,10),bodyMat);hubCap.rotation.z=Math.PI/2;pivot.add(hubCap);car.add(pivot);car.userData.wheels.push({pivot,tire,x,z,phase:0})}car.position.set(pathAt(0).x,0,0);scene.add(car)}\nfunction params(){const d=vehicleDefs[data.selected],u=data.upgrades;return {...d,accel:d.accel*(1+u.engine*.13),max:d.max*(1+u.engine*.055),grip:d.grip*(1+u.tires*.12),susp:d.susp*(1+u.suspension*.14),brake:d.brake*(1+u.brakes*.12),clearance:d.clearance+u.clearance*.12,nitroMax:100+u.nitro*20}}\nfunction resetRun(){runDistance=0;forwardVel=0;sideVel=0;verticalVel=0;carY=0;carPitch=0;carRoll=0;steer=0;nitro=params().nitroMax;runCoins=0;checkpoint=0;lastReward=0;coins.forEach(c=>{c.taken=false;c.mesh.visible=true});checkpoints.forEach(c=>c.rewarded=false);const p=pathAt(0);car.position.set(p.x,.5,0);car.rotation.set(0,0,0);makeTrack();buildCar();car.position.set(pathAt(0).x,.5,0);}\nfunction startDrive(){if(!renderer){return}resetRun();mode='drive';paused=false;show(null);$('hud').style.display='block';$('tutorialCard').classList.remove('hidden');tutorialStage=0;updateTutorial();audio(420,.12);}\nfunction updateTutorial(){const msgs=['Hold W or ↑ (or the ▲ button) to accelerate. Use A/D or the ◀ ▶ buttons to steer.','Watch the speed before tight bends. Rocks cause wheel movement and chassis bounce.','Collect gold coins for upgrades. Shift / ⚡ uses nitro; R / Recover returns to the trail.'];$('tutorialText').textContent=msgs[tutorialStage]||msgs[0];$('tutorialNext').textContent=tutorialStage>=2?'Start driving':'Next tip'}function finishTutorial(){if(tutorialStage<2){tutorialStage++;updateTutorial()}else $('tutorialCard').classList.add('hidden')}\nfunction recover(){const z=-runDistance;const p=pathAt(z);car.position.set(p.x,p.y+1.05,z);car.rotation.set(0,0,0);carY=p.y+1.05;verticalVel=0;forwardVel=0;sideVel=0;carPitch=0;carRoll=0;shake=.18;audio(230,.15,'triangle')}\nfunction updatePhysics(dt){const p=params();const z=car.position.z;const path=pathAt(z);const steerInput=(held.left||keys.ArrowLeft||keys.KeyA?-1:0)+(held.right||keys.ArrowRight||keys.KeyD?1:0);const gas=held.gas||keys.ArrowUp||keys.KeyW,brake=held.brake||keys.ArrowDown||keys.KeyS,boost=(held.nitro||keys.ShiftLeft||keys.ShiftRight)&&nitro>0&&gas;const targetSteer=steerInput;steer=THREE.MathUtils.damp(steer,targetSteer,6,dt);const boostPower=boost?1.65:1;if(boost){nitro=Math.max(0,nitro-32*dt)}else nitro=Math.min(p.nitroMax,nitro+7*dt);if(gas)forwardVel+=p.accel*boostPower*dt;else forwardVel*=Math.max(0,1-.42*dt);if(brake){if(forwardVel>1)forwardVel-=p.brake*dt;else forwardVel-=p.accel*.58*dt}if(keys.Space)forwardVel*=Math.max(0,1-3.8*dt);forwardVel=THREE.MathUtils.clamp(forwardVel,-p.max*.18,p.max/3.6);const speedRatio=Math.min(1,Math.abs(forwardVel)/(p.max/3.6));const yawRate=-steer*p.grip*(.45+speedRatio*.7)*Math.sign(forwardVel||1);car.rotation.y+=yawRate*dt;const heading=car.rotation.y;const driveX=-Math.sin(heading)*forwardVel;const driveZ=-Math.cos(heading)*forwardVel;sideVel+=(-sideVel*3.5+steer*forwardVel*.62)*dt;const oldZ=car.position.z;car.position.x+=(driveX+Math.cos(heading)*sideVel)*dt;car.position.z+=driveZ*dt;runDistance=Math.max(runDistance,-car.position.z);const road=pathAt(car.position.z);let lateral=car.position.x-road.x;/* Keep the vehicle inside the track boundaries; gently guide it back before the edge. */const trackLimit=3.85;if(Math.abs(lateral)>trackLimit){car.position.x=road.x+Math.sign(lateral)*trackLimit;sideVel*=.18;forwardVel*=.88;lateral=car.position.x-road.x;}const offroad=Math.abs(lateral)>trackLimit-.2;const groundY=road.y+(offroad?-.15:0);let wheelHeights=[],hitRock=false;for(const w of car.userData.wheels){const wz=car.position.z+w.z,wpath=pathAt(wz);let wy=wpath.y;for(const r of rocks){const dx=car.position.x+w.x-r.mesh.position.x,dz=wz-r.mesh.position.z,dist=Math.hypot(dx,dz);if(dist<r.r+.42&&Math.abs(car.position.y-(r.mesh.position.y+r.r*.45))<1.45){wy=Math.max(wy,r.mesh.position.y+r.r*.55);hitRock=true;}}wheelHeights.push(wy);const compression=THREE.MathUtils.clamp((wy-groundY+.2)*.8,-.2,.4);w.pivot.position.y=.48+compression;w.tire.rotation.x+=forwardVel*dt/.48;w.pivot.rotation.y=w.z<0?-steer*.42:0}const front=(wheelHeights[0]+wheelHeights[1])/2,rear=(wheelHeights[2]+wheelHeights[3])/2;const targetPitch=THREE.MathUtils.clamp((rear-front)*.17,-.28,.28);const left=(wheelHeights[0]+wheelHeights[2])/2,right=(wheelHeights[1]+wheelHeights[3])/2;const targetRoll=THREE.MathUtils.clamp((left-right)*.22-steer*speedRatio*.09,-.32,.32);carPitch=THREE.MathUtils.damp(carPitch,targetPitch,4.2,dt);carRoll=THREE.MathUtils.damp(carRoll,targetRoll,4.8,dt);car.rotation.x=carPitch;car.rotation.z=carRoll;const targetY=(wheelHeights.reduce((a,b)=>a+b,0)/4)+p.clearance*.18+.18;verticalVel+=(targetY-car.position.y)*18*dt;verticalVel*=Math.exp(-4.2*dt);car.position.y+=verticalVel*dt;carY=car.position.y;if(hitRock&&Math.abs(forwardVel)>5){forwardVel*=.94;shake=Math.min(.45,shake+.18);if(Math.random()<.035)audio(95,.08,'sawtooth',.018)}if(offroad){forwardVel*=Math.max(.94,1-.7*dt)}if(Math.abs(lateral)>15||car.position.y<-8||runDistance>100000){recover()}if(Math.abs(lateral)>9)forwardVel*=.96;speed=Math.abs(forwardVel)*3.6;car.position.y=Math.max(-1,car.position.y);if(car.position.y>groundY+4)verticalVel-=9.8*dt;for(const c of coins){if(c.taken)continue;c.mesh.rotation.y+=dt*2.5;c.mesh.position.y=(pathAt(c.mesh.position.z).y+1.15)+Math.sin(performance.now()*.002+c.mesh.position.z)*.12;if(car.position.distanceTo(c.mesh.position)<1.65){c.taken=true;c.mesh.visible=false;data.balance+=1;runCoins+=1;save();audio(880,.1,'sine',.05);}}for(const cp of checkpoints){if(!cp.rewarded&&-car.position.z> -cp.z){cp.rewarded=true;data.balance+=5;runCoins+=5;save();audio(700,.18);}}\nif(coinCooldown>0)coinCooldown-=dt;$('coins').textContent=data.balance;$('distance').textContent=Math.floor(runDistance);$('speed').textContent=Math.round(speed);$('nitroBar').style.width=`${Math.max(0,nitro/p.nitroMax*100)}%`;if(runDistance>0&&Math.floor(runDistance/100)>lastReward){lastReward=Math.floor(runDistance/100);if(lastReward%2===0){data.balance+=2;runCoins+=2;save();audio(620,.1)}}bestDistance=Math.max(bestDistance,runDistance);}\nfunction updateCamera(dt){if(!car)return;const h=car.rotation.y;const offset=cameraMode===1?new THREE.Vector3(0,1.5,1.8):new THREE.Vector3(Math.sin(h)*8,4.2,Math.cos(h)*8+0);const target=car.position.clone().add(offset);target.y+=Math.min(2,speed/65);shake=Math.max(0,shake-dt);if(shake>0){target.x+=(Math.random()-.5)*shake;target.y+=(Math.random()-.5)*shake}camera.position.lerp(target,1-Math.exp(-3.5*dt));const look=car.position.clone();look.y+=.7;look.z-=4;camera.lookAt(look)}function animate(){requestAnimationFrame(animate);if(!renderer)return;const dt=Math.min(clock.getDelta(),.035);if(mode==='drive'&&!paused){updatePhysics(dt);updateCamera(dt)}else if(car){const t=performance.now()*.0002;camera.position.lerp(new THREE.Vector3(car.position.x+Math.sin(t)*7,car.position.y+4,car.position.z+8),.015);camera.lookAt(car.position)}renderer.render(scene,camera)}\nfunction renderGarage(){ $('garageCoins').textContent=data.balance;$('vehicleOptions').innerHTML='';vehicleDefs.forEach((v,i)=>{const owned=data.owned.includes(i),selected=data.selected===i;const div=document.createElement('div');div.className='option';const title=document.createElement('strong');title.textContent=(selected?'✓ ':'')+v.name;const desc=document.createElement('div');desc.className='small';desc.textContent=`${v.desc} · ${v.max} km/h · ${v.susp.toFixed(1)} suspension`;const btn=document.createElement('button');btn.style.marginTop='10px';btn.textContent=owned?(selected?'Selected':'Select'):`Unlock · ${v.price} coins`;btn.disabled=owned&&selected;btn.onclick=()=>{if(owned){data.selected=i;buildCar();save();renderGarage()}else if(data.balance>=v.price){data.balance-=v.price;data.owned.push(i);data.selected=i;buildCar();save();renderGarage();audio(650,.12)}else audio(120,.12,'square')};div.append(title,desc,btn);$('vehicleOptions').append(div)});$('swatches').innerHTML='';['#e69a25','#d73c32','#2676d2','#3a9d69','#e6e6df','#292e35','#b34bd1'].forEach(color=>{const b=document.createElement('button');b.className='swatch';b.style.background=color;b.title=color;b.onclick=()=>{data.paint=color;buildCar();save();renderGarage()};$('swatches').append(b)});$('upgradeOptions').innerHTML='';upgradeDefs.forEach(u=>{const level=data.upgrades[u.key],price=u.base*(level+1);const row=document.createElement('div');row.className='row';const left=document.createElement('div');const strong=document.createElement('strong');strong.textContent=`${u.name} · Lv ${level}/5`;const desc=document.createElement('div');desc.className='small';desc.textContent=u.desc;left.append(strong,desc);const btn=document.createElement('button');btn.textContent=level>=5?'MAX':`Upgrade · ${price}`;btn.disabled=level>=5;btn.onclick=()=>{if(level<5&&data.balance>=price){data.balance-=price;data.upgrades[u.key]++;save();renderGarage();audio(680,.1)}else audio(120,.12,'square')};row.append(left,btn);$('upgradeOptions').append(row)})}\nfunction enterGarage(){mode='garage';paused=true;$('hud').style.display='none';show('garage');renderGarage()}function openMenu(){mode='menu';paused=true;$('hud').style.display='none';show('menu');}function pauseGame(){if(mode!=='drive')return;paused=true;show('pause')}function resumeGame(){paused=false;show(null);$('hud').style.display='block'}function finishRun(){mode='summary';paused=true;data.best=Math.max(data.best,Math.floor(runDistance));save();$('hud').style.display='none';$('summaryText').textContent=`Distance: ${Math.floor(runDistance)} m · Coins earned this run: ${runCoins} · Best distance: ${data.best} m. Your upgrades and coins are saved locally.`;show('summary')}\n$('startBtn').onclick=startDrive;$('garageBtn').onclick=enterGarage;$('helpBtn').onclick=()=>show('help');$('settingsBtn').onclick=()=>show('settings');$('resetBtn').onclick=()=>{if(confirm('Reset all locally saved coins, vehicles and upgrades? This cannot be undone.')){localStorage.removeItem(saveKey);data={version:1,balance:0,owned:[0],selected:0,paint:'#e69a25',upgrades:{engine:0,suspension:0,tires:0,brakes:0,nitro:0,clearance:0},best:0,sound:true,quality:'HIGH'};save();buildCar();openMenu()}};$('garageBack').onclick=openMenu;$('garageDrive').onclick=startDrive;$('helpBack').onclick=openMenu;$('helpDrive').onclick=startDrive;$('settingsBack').onclick=openMenu;$('soundToggle').onclick=()=>{soundOn=!soundOn;data.sound=soundOn;$('soundToggle').textContent='Sound: '+(soundOn?'ON':'OFF');save();audio(500)};$('qualityToggle').onclick=()=>{quality=quality==='HIGH'?'LOW':'HIGH';data.quality=quality;$('qualityToggle').textContent='Quality: '+quality;save();resize();if(scene){scene.traverse(o=>{if(o.isDirectionalLight)o.castShadow=quality==='HIGH'});renderer.shadowMap.enabled=quality==='HIGH'}};$('resumeBtn').onclick=resumeGame;$('recoverBtn').onclick=()=>{recover();resumeGame()};$('pauseBtn').onclick=pauseGame;$('hudRecover').onclick=recover;$('cameraBtn').onclick=()=>{cameraMode=(cameraMode+1)%2};$('hudTutorial').onclick=()=>{$('tutorialCard').classList.remove('hidden');tutorialStage=0;updateTutorial()};$('tutorialNext').onclick=finishTutorial;$('pauseGarage').onclick=enterGarage;$('restartBtn').onclick=startDrive;$('againBtn').onclick=startDrive;$('summaryGarage').onclick=enterGarage;$('summaryMenu').onclick=openMenu;$('errorRetry').onclick=()=>location.reload();\nwindow.addEventListener('keydown',e=>{keys[e.code]=true;if(['ArrowUp','ArrowDown','ArrowLeft','ArrowRight','Space'].includes(e.code)&&mode==='drive')e.preventDefault();if(e.code==='Escape'){if(mode==='drive'&&!paused)pauseGame();else if(mode==='drive'&&paused)resumeGame()}if(e.code==='KeyR'&&mode==='drive')recover();if(e.code==='KeyC'&&mode==='drive')cameraMode=(cameraMode+1)%2});window.addEventListener('keyup',e=>keys[e.code]=false);window.addEventListener('blur',()=>{keys={};held={left:false,right:false,gas:false,brake:false,nitro:false}});document.querySelectorAll('[data-control]').forEach(btn=>{const c=btn.dataset.control;const on=e=>{e.preventDefault();held[c]=true};const off=e=>{e.preventDefault();held[c]=false};btn.addEventListener('pointerdown',on);['pointerup','pointercancel','pointerleave','lostpointercapture'].forEach(ev=>btn.addEventListener(ev,off));});document.addEventListener('visibilitychange',()=>{if(document.hidden){keys={};held={left:false,right:false,gas:false,brake:false,nitro:false};if(mode==='drive')paused=true}});\nloadSave();$('soundToggle').textContent='Sound: '+(soundOn?'ON':'OFF');$('qualityToggle').textContent='Quality: '+quality;try{init3D();$('boot').classList.add('hidden');show('menu')}catch(e){console.error(e);$('boot').classList.add('hidden');show('error')}\n</script></body></html>","version_history":[{"id":"v-1.0.0","is_active":true,"created_at":"2026-10-28T13:04:35.369Z","entry_file":"index.html","published_at":"2026-10-28T13:04:35.369Z","health_status":"HEALTHY","release_notes":"","version_number":"1.0.0","storage_location":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvs4m2mr_a5jnv/1.0.0/","processing_status":"COMPLETED","permission_profile":"BASIC_HTML5","security_validation":"PASSED"}]},"controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":1,"created_at":"2026-10-28T13:04:31.662+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-28T13:04:31.662+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"### 🎮 Overview\nIndex is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","playable_url":"/api/play?id=febaf1b9-eabf-410f-b7d2-50fd38683748"},{"id":"4ce0a570-6273-4f72-827a-4d8774c95b5d","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"Chaos party universal","slug":"chaos-party-universal-mvpnv6s7","description":"### 🎮 Overview\nChaos party universal is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","game_type":"html5","category":"action","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/","game_url":"/api/play?id=4ce0a570-6273-4f72-827a-4d8774c95b5d","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/thumbnail.jpg","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/thumbnail.jpg","preview_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/preview.mp4","preview_url":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/preview.mp4","tutorial_data":{"guide":"","entry_file":"index.html","orientation":"any","review_data":{"summary":"All mandatory technical and security verifications passed with low risk (0/100). Package verified safe for deployment.","findings":[],"ai_report":{"status":"NOT_CONFIGURED","summary":"No AI provider API key configured (GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY). Evaluated exclusively using deterministic technical, security, and integrity verification checks.","provider":"NONE","ai_configured":false,"additional_findings":[]},"risk_score":0,"reviewed_at":"2026-10-26T19:40:10.760Z","can_resubmit":false,"quality_score":100,"review_status":"approved","recommendation":"approved","technical_checks":{"metadata":{"passed":true,"message":"Metadata verified"},"entrypoint":{"file":"index.html","passed":true,"message":"Playable entrypoint \"index.html\" verified"},"missing_assets":{"passed":true,"message":"All local asset references verified"},"path_traversal":{"passed":true,"message":"All archive paths clean"},"launch_readiness":{"passed":true,"message":"HTML5 launch integrity verified"},"prohibited_files":{"passed":true,"message":"No prohibited executable files found"},"syntax_validation":{"passed":true,"message":"JavaScript syntax valid"},"security_integrity":{"passed":true,"message":"No suspicious security payloads detected"},"viewport_responsiveness":{"passed":true,"message":"Viewport configured"}},"structured_rejections":[]},"aspect_ratio":"16:9","html_content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover\" />\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\" />\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\" />\n  <meta name=\"theme-color\" content=\"#1769D2\" />\n  <title>CHAOS PARTY — Shopping Cart Race</title>\n  \n  <!-- Modern Google Fonts for Party Game Aesthetics -->\n  <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n  <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n  <link href=\"https://fonts.googleapis.com/css2?family=Fredoka:wght@500;600;700;800&family=Luckiest+Guy&family=Outfit:wght@500;600;700;800;900&display=swap\" rel=\"stylesheet\">\n  \n  <!-- Standalone Universal Web Build -->\n<script type=\"module\" crossorigin src=\"./assets/index-DoOF5O2q.js\"></script>\n  <link rel=\"stylesheet\" crossorigin href=\"./assets/index-z8bboO25.css\">\n</head>\n<body>\n  <div id=\"app\">\n    <!-- Phaser Game Canvas Container -->\n    <div id=\"game-container\"></div>\n    \n    <!-- Seamless UI Layer for Menus, HUD, Chat & Virtual Controls -->\n    <div id=\"ui-layer\"></div>\n  </div>\n\n</body>\n</html>","version_history":[{"id":"v-1.0.0","is_active":true,"created_at":"2026-10-26T19:40:06.773Z","entry_file":"index.html","published_at":"2026-10-26T19:40:06.773Z","health_status":"HEALTHY","release_notes":"","version_number":"1.0.0","storage_location":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvpnutyl_cztyv/1.0.0/","processing_status":"COMPLETED","permission_profile":"BASIC_HTML5","security_validation":"PASSED"}]},"controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":1,"created_at":"2026-10-26T19:40:03.223+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-26T19:40:03.223+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"### 🎮 Overview\nChaos party universal is an exhilarating action web game built for instant browser play. Prepare for adrenaline-pumping thrills in a high-stakes arena.\n\n### 🕹️ Core Gameplay & Mechanics\nCombines razor-sharp reflexes, rapid dodging, and explosive combo opportunities. Players are challenged to master intuitive controls while navigating through progressively demanding stages, balancing risk versus reward at every turn.\n\n### 🌟 Key Features\n- **Fluid Browser Performance**: Engineered for buttery-smooth 60+ FPS gameplay on both desktop and mobile.\n- **Dynamic enemy wave patterns with escalating tactical difficulty**.\n- **Multi-tier power-ups and special ability overcharges**.\n- **Epic showdown encounters with distinct attack phases**.\n- **Global Leaderboards & Achievements**: Compete against top players worldwide and cement your high-score rank.\n\n### 💡 Pro Tips\n- Watch for environmental cues and audio prompts before major obstacles.\n- Chain your actions together to trigger maximum point multipliers!","playable_url":"/api/play?id=4ce0a570-6273-4f72-827a-4d8774c95b5d"},{"id":"33375c6f-988e-41a3-86f6-3fd4337fc285","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"Push battle 3d universal web","slug":"push-battle-3d-universal-web-mvet0sbu","description":"FULL GAME DESCRIPTION:\nPush Battle 3D is an action-packed 3D physics gladiator arena battle game suspended high above the clouds. Step into the arena as a customizable gladiator warrior, charge your kinetic strike, unleash game-changing superpower abilities, and blast your rivals off floating battle grounds into the abyss!\n\nConquer 12 unique floating world environments in the grand single-player campaign — from ancient Mossy Ruins, fiery Volcanic Calderas, and slippery Frozen Isles, to mechanical Clockwork Gearworks, Prismatic Crystal Spires, tempestuous Storm Islands, and the ultimate Apex Citadel. Collect ancient relics, survive shifting ground hazards, unlock epic gladiator skins and hats, or team up with friends in real-time online multiplayer party rooms with integrated live voice chat!\n\nKEY FEATURES:\n• 12 Floating Battle Ground Worlds with dynamic hazards, boss fights, and 3-star mission criteria.\n• Physics-Driven Knockout Combat: Kinetic pushes, directional rocket dashes, and edge balance recovery.\n• 5 Upgradable Powers: Mega Push, Energy Shield, Kinetic Shockwave, Giant Mode, and Edge Teleport Recovery.\n• Real-Time Online Multiplayer: 1v1 Duels, 4-Player Rumbles, 8-Player Mayhem, custom room codes, and WebRTC live voice chat.\n• Deep Gladiator Customization: Unlock distinctive warriors, outfits, mythical hats, and expressive emotes.\n• Full Cross-Platform Controls: Keyboard & Mouse, 360° Mobile Touch Joystick, and Gamepad support with 9-step interactive tutorial.\n\nFOUR-LINE CONTROL DETAILS:\n• Move: WASD / Arrow Keys / Drag Mobile Joystick\n• Kinetic Push Strike: Spacebar / Left Click / Tap [PUSH]\n• Rocket Dash & Boost: Shift / Double Tap Direction / Tap [DASH]\n• Activate Power-Up: E Key / Q Key / Tap [POWER] (Camera Orbit: Right Click & Drag / Swipe Screen)\nCATEGORY:\nAction / .io Games / 3D / Fighting / Multiplayer\nTAGS:\n3D, Arena, Battle, Physics, Multiplayer, Fighting, Gladiator, Action, io, Casual, ragdoll","game_type":"html5","category":"action","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/","game_url":"/api/play?id=33375c6f-988e-41a3-86f6-3fd4337fc285","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/thumbnail.jpg","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/thumbnail.jpg","preview_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/preview.mp4","preview_url":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/preview.mp4","tutorial_data":{"guide":"KEY FEATURES:\n• 12 Floating Battle Ground Worlds with dynamic hazards, boss fights, and 3-star mission criteria.\n• Physics-Driven Knockout Combat: Kinetic pushes, directional rocket dashes, and edge balance recovery.\n• 5 Upgradable Powers: Mega Push, Energy Shield, Kinetic Shockwave, Giant Mode, and Edge Teleport Recovery.\n• Real-Time Online Multiplayer: 1v1 Duels, 4-Player Rumbles, 8-Player Mayhem, custom room codes, and WebRTC live voice chat.\n• Deep Gladiator Customization: Unlock distinctive warriors, outfits, mythical hats, and expressive emotes.\n• Full Cross-Platform Controls: Keyboard & Mouse, 360° Mobile Touch Joystick, and Gamepad support with 9-step interactive tutorial.\n\nFOUR-LINE CONTROL DETAILS:\n• Move: WASD / Arrow Keys / Drag Mobile Joystick\n• Kinetic Push Strike: Spacebar / Left Click / Tap [PUSH]\n• Rocket Dash & Boost: Shift / Double Tap Direction / Tap [DASH]\n• Activate Power-Up: E Key / Q Key / Tap [POWER] (Camera Orbit: Right Click & Drag / Swipe Screen)","entry_file":"index.html","orientation":"any","review_data":{"summary":"All mandatory technical and security verifications passed with low risk (0/100). Package verified safe for deployment.","findings":[],"ai_report":{"status":"NOT_CONFIGURED","summary":"No AI provider API key configured (GEMINI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY). Evaluated exclusively using deterministic technical, security, and integrity verification checks.","provider":"NONE","ai_configured":false,"additional_findings":[]},"risk_score":0,"reviewed_at":"2026-10-19T05:18:59.891Z","can_resubmit":false,"quality_score":100,"review_status":"approved","recommendation":"approved","technical_checks":{"metadata":{"passed":true,"message":"Metadata verified"},"entrypoint":{"file":"index.html","passed":true,"message":"Playable entrypoint \"index.html\" verified"},"missing_assets":{"passed":true,"message":"All local asset references verified"},"path_traversal":{"passed":true,"message":"All archive paths clean"},"launch_readiness":{"passed":true,"message":"HTML5 launch integrity verified"},"prohibited_files":{"passed":true,"message":"No prohibited executable files found"},"syntax_validation":{"passed":true,"message":"JavaScript syntax valid"},"security_integrity":{"passed":true,"message":"No suspicious security payloads detected"},"viewport_responsiveness":{"passed":true,"message":"Viewport configured"}},"structured_rejections":[]},"aspect_ratio":"16:9","html_content":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover\">\n  <meta name=\"theme-color\" content=\"#ff4757\">\n  <meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n  <meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">\n  <meta name=\"description\" content=\"Push Battle 3D - Fast-paced 3D multiplayer arena combat game. Push rivals off floating arenas with kinetic strikes, rocket dashes, and special powers!\">\n  <title>Push Battle 3D - Cross-Platform Arena Combat</title>\n\n  <style>\n    html, body {\n      margin: 0;\n      padding: 0;\n      width: 100%;\n      height: 100%;\n      overflow: hidden;\n      background-color: #090c10;\n      color: #f0f6fc;\n      user-select: none;\n      -webkit-user-select: none;\n      touch-action: manipulation;\n    }\n  </style>\n  <link rel=\"icon\" href=\"data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220%22%3E<text y=%2226%22 font-size=%2226%22>🥊</text></svg>\">\n  <!-- CrazyGames SDK v3 -->\n  \n  <script type=\"module\" crossorigin>var Wl=Object.defineProperty;var Xl=(a,e,t)=>e in a?Wl(a,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):a[e]=t;var an=(a,e,t)=>Xl(a,typeof e!=\"symbol\"?e+\"\":e,t);(function(){const e=document.createElement(\"link\").relList;if(e&&e.supports&&e.supports(\"modulepreload\"))return;for(const n of document.querySelectorAll('link[rel=\"modulepreload\"]'))i(n);new MutationObserver(n=>{for(const s of n)if(s.type===\"childList\")for(const r of s.addedNodes)r.tagName===\"LINK\"&&r.rel===\"modulepreload\"&&i(r)}).observe(document,{childList:!0,subtree:!0});function t(n){const s={};return n.integrity&&(s.integrity=n.integrity),n.referrerPolicy&&(s.referrerPolicy=n.referrerPolicy),n.crossOrigin===\"use-credentials\"?s.credentials=\"include\":n.crossOrigin===\"anonymous\"?s.credentials=\"omit\":s.credentials=\"same-origin\",s}function i(n){if(n.ep)return;n.ep=!0;const s=t(n);fetch(n.href,s)}})();class ql{constructor(){this.ctx=null,this.musicEnabled=!0,this.sfxEnabled=!0,this.vibrationEnabled=!0,this.masterGain=null,this.musicGain=null,this.sfxGain=null,this.currentTrack=null,this.musicTimer=null,this.isInitialized=!1,this.isPlatformMuted=!1,this.isAdMuted=!1,this.isMasterMuted=!1;const e=typeof localStorage<\"u\"?localStorage.getItem(\"pushbattle_settings\"):null;if(e)try{const t=JSON.parse(e);this.musicEnabled=t.music??!0,this.sfxEnabled=t.sfx??!0,this.vibrationEnabled=t.vibration??!0,this.isMasterMuted=t.muted??!1}catch{}}get isMuted(){return this.isPlatformMuted||this.isAdMuted||this.isMasterMuted}init(){if(!this.isInitialized)try{const e=window.AudioContext||window.webkitAudioContext;if(!e)return;this.ctx=new e,this.masterGain=this.ctx.createGain(),this.masterGain.connect(this.ctx.destination),this.musicGain=this.ctx.createGain(),this.musicGain.connect(this.masterGain),this.sfxGain=this.ctx.createGain(),this.sfxGain.connect(this.masterGain),this.isInitialized=!0,this.applyGainLevels()}catch(e){console.warn(\"AudioContext not allowed yet:\",e)}}unlock(){this.init(),this.ctx&&this.ctx.state===\"suspended\"&&this.ctx.resume(),this.applyGainLevels()}applyGainLevels(){if(!this.masterGain||!this.ctx)return;const e=this.isMuted,t=e?0:.8,i=e||!this.musicEnabled?0:.35,n=e||!this.sfxEnabled?0:.7;try{const s=this.ctx.currentTime||0;this.masterGain.gain.setValueAtTime(t,s),this.musicGain&&this.musicGain.gain.setValueAtTime(i,s),this.sfxGain&&this.sfxGain.gain.setValueAtTime(n,s)}catch{}}setPlatformMuted(e){this.isPlatformMuted=!!e,this.applyGainLevels()}setAdMuted(e){this.isAdMuted=!!e,this.applyGainLevels()}setMasterMuted(e){this.isMasterMuted=!!e,this.applyGainLevels(),this.saveSettings()}toggleMasterMute(){return this.setMasterMuted(!this.isMasterMuted),this.isMuted}setMusicEnabled(e){this.musicEnabled=e,this.applyGainLevels(),this.saveSettings()}setSfxEnabled(e){this.sfxEnabled=e,this.applyGainLevels(),this.saveSettings()}setVibrationEnabled(e){this.vibrationEnabled=e,this.saveSettings()}saveSettings(){localStorage.setItem(\"pushbattle_settings\",JSON.stringify({music:this.musicEnabled,sfx:this.sfxEnabled,vibration:this.vibrationEnabled,muted:this.isMasterMuted}))}vibrate(e=30){if(this.vibrationEnabled&&navigator.vibrate)try{navigator.vibrate(e)}catch{}}playButton(){if(!this.sfxEnabled||!this.ctx)return;this.unlock();const e=this.ctx.currentTime,t=this.ctx.createOscillator(),i=this.ctx.createGain();t.type=\"square\",t.frequency.setValueAtTime(880,e),t.frequency.exponentialRampToValueAtTime(1760,e+.06),i.gain.setValueAtTime(.15,e),i.gain.linearRampToValueAtTime(.01,e+.06),t.connect(i),i.connect(this.sfxGain),t.start(e),t.stop(e+.06)}playPush(){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate(25);const e=this.ctx.currentTime,t=this.ctx.createOscillator(),i=this.ctx.createGain();t.type=\"sawtooth\",t.frequency.setValueAtTime(260,e),t.frequency.exponentialRampToValueAtTime(80,e+.18),i.gain.setValueAtTime(.45,e),i.gain.linearRampToValueAtTime(.01,e+.18),t.connect(i),i.connect(this.sfxGain),t.start(e),t.stop(e+.18),this.playNoise(e,.1,.25)}playImpact(e=!1){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate(e?[50,25,60]:35);const t=this.ctx.currentTime,i=this.ctx.createOscillator(),n=this.ctx.createGain();i.type=\"sawtooth\",i.frequency.setValueAtTime(e?180:280,t),i.frequency.exponentialRampToValueAtTime(20,t+.35),n.gain.setValueAtTime(e?.7:.5,t),n.gain.exponentialRampToValueAtTime(.01,t+.35),i.connect(n),n.connect(this.sfxGain),i.start(t),i.stop(t+.35),this.playNoise(t,e?.25:.15,.4)}playDash(){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate(15);const e=this.ctx.currentTime,t=this.ctx.createOscillator(),i=this.ctx.createGain();t.type=\"sine\",t.frequency.setValueAtTime(450,e),t.frequency.exponentialRampToValueAtTime(1200,e+.15),i.gain.setValueAtTime(.35,e),i.gain.linearRampToValueAtTime(.01,e+.15),t.connect(i),i.connect(this.sfxGain),t.start(e),t.stop(e+.15),this.playNoise(e,.12,.2)}playPower(e){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate([40,20,60]);const t=this.ctx.currentTime;if(e===\"shockwave\")[0,.06,.12].forEach((i,n)=>{const s=this.ctx.createOscillator(),r=this.ctx.createGain();s.type=\"sawtooth\",s.frequency.setValueAtTime(300+n*80,t+i),s.frequency.exponentialRampToValueAtTime(40,t+i+.25),r.gain.setValueAtTime(.3,t+i),r.gain.exponentialRampToValueAtTime(.01,t+i+.25),s.connect(r),r.connect(this.sfxGain),s.start(t+i),s.stop(t+i+.25)}),this.playNoise(t+.1,.35,.45);else if(e===\"shield\")[659.25,880,1174.66].forEach((i,n)=>{const s=this.ctx.createOscillator(),r=this.ctx.createGain();s.type=\"sine\",s.frequency.setValueAtTime(i,t+n*.04),r.gain.setValueAtTime(.2,t+n*.04),r.gain.exponentialRampToValueAtTime(.01,t+.45+n*.04),s.connect(r),r.connect(this.sfxGain),s.start(t+n*.04),s.stop(t+.5)});else{const i=this.ctx.createOscillator(),n=this.ctx.createGain();i.type=\"sawtooth\",i.frequency.setValueAtTime(140,t),i.frequency.exponentialRampToValueAtTime(800,t+.25),n.gain.setValueAtTime(.5,t),n.gain.exponentialRampToValueAtTime(.01,t+.3),i.connect(n),n.connect(this.sfxGain),i.start(t),i.stop(t+.3)}}playElimination(){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate([60,30,80]);const e=this.ctx.currentTime,t=this.ctx.createOscillator(),i=this.ctx.createGain();t.type=\"sawtooth\",t.frequency.setValueAtTime(600,e),t.frequency.exponentialRampToValueAtTime(45,e+.65),i.gain.setValueAtTime(.4,e),i.gain.exponentialRampToValueAtTime(.01,e+.65),t.connect(i),i.connect(this.sfxGain),t.start(e),t.stop(e+.65)}playCountdown(e){if(!this.sfxEnabled||!this.ctx)return;this.unlock();const t=this.ctx.currentTime,i=this.ctx.createOscillator(),n=this.ctx.createGain(),s=e===0||e===\"GO\"||e===\"GO!\";i.type=\"square\",i.frequency.setValueAtTime(s?1200:600,t),n.gain.setValueAtTime(.25,t),n.gain.exponentialRampToValueAtTime(.01,t+(s?.35:.15)),i.connect(n),n.connect(this.sfxGain),i.start(t),i.stop(t+(s?.35:.15)),this.vibrate(s?90:35)}playCoin(){if(!this.sfxEnabled||!this.ctx)return;this.unlock();const e=this.ctx.currentTime;[1046.5,1567.98].forEach((t,i)=>{const n=this.ctx.createOscillator(),s=this.ctx.createGain();n.type=\"sine\",n.frequency.setValueAtTime(t,e+i*.08),s.gain.setValueAtTime(.25,e+i*.08),s.gain.exponentialRampToValueAtTime(.01,e+.25+i*.08),n.connect(s),s.connect(this.sfxGain),n.start(e+i*.08),n.stop(e+.3+i*.08)})}playVictory(){if(!this.sfxEnabled||!this.ctx)return;this.unlock(),this.vibrate([100,50,100,50,200]);const e=this.ctx.currentTime;[587.33,739.99,880,1174.66].forEach((i,n)=>{const s=this.ctx.createOscillator(),r=this.ctx.createGain();s.type=\"sawtooth\",s.frequency.setValueAtTime(i,e+n*.12),r.gain.setValueAtTime(.35,e+n*.12),r.gain.exponentialRampToValueAtTime(.01,e+.6+n*.12),s.connect(r),r.connect(this.sfxGain),s.start(e+n*.12),s.stop(e+.8+n*.12)})}playDefeat(){if(!this.sfxEnabled||!this.ctx)return;this.unlock();const e=this.ctx.currentTime;[440,392,349.23,293.66].forEach((i,n)=>{const s=this.ctx.createOscillator(),r=this.ctx.createGain();s.type=\"sawtooth\",s.frequency.setValueAtTime(i,e+n*.18),r.gain.setValueAtTime(.28,e+n*.18),r.gain.exponentialRampToValueAtTime(.01,e+.4+n*.18),s.connect(r),r.connect(this.sfxGain),s.start(e+n*.18),s.stop(e+.6+n*.18)})}playNoise(e,t,i){if(!this.ctx)return;const n=this.ctx.sampleRate*t,s=this.ctx.createBuffer(1,n,this.ctx.sampleRate),r=s.getChannelData(0);for(let d=0;d<n;d++)r[d]=Math.random()*2-1;const o=this.ctx.createBufferSource();o.buffer=s;const l=this.ctx.createBiquadFilter();l.type=\"lowpass\",l.frequency.setValueAtTime(1e3,e);const c=this.ctx.createGain();c.gain.setValueAtTime(i,e),c.gain.linearRampToValueAtTime(.01,e+t),o.connect(l),l.connect(c),c.connect(this.sfxGain),o.start(e)}playMusic(e=\"menu\"){if(this.currentTrack===e)return;this.stopMusic(),this.currentTrack=e;let t=0;const i=[220,261.63,293.66,329.63,392,440],n=[110,130.81,146.83,164.81,196,220],s=e===\"battle\"?160:280;this.musicTimer=setInterval(()=>{if(!this.musicEnabled||!this.ctx||this.ctx.state!==\"running\")return;const r=this.ctx.currentTime;if(e===\"menu\"){const o=i[t%i.length],l=this.ctx.createOscillator(),c=this.ctx.createGain();l.type=\"sawtooth\",l.frequency.setValueAtTime(o,r),c.gain.setValueAtTime(.1,r),c.gain.exponentialRampToValueAtTime(.001,r+.24),l.connect(c),c.connect(this.musicGain),l.start(r),l.stop(r+.26)}else{const o=n[Math.floor(t/2)%n.length],l=this.ctx.createOscillator(),c=this.ctx.createGain();l.type=\"sawtooth\",l.frequency.setValueAtTime(o,r),c.gain.setValueAtTime(.22,r),c.gain.exponentialRampToValueAtTime(.005,r+.13),l.connect(c),c.connect(this.musicGain),l.start(r),l.stop(r+.15),t%2===1&&this.playNoise(r,.04,.1)}t++},s)}stopMusic(){this.musicTimer&&(clearInterval(this.musicTimer),this.musicTimer=null),this.currentTrack=null}}const N=new ql,Yi={matchParticipationCoins:25,matchTop3Coins:50,matchVictoryCoins:100,firstMatchOfTheDayCoins:50,matchParticipationXP:50,matchEliminationXP:25,matchVictoryXP:100,adRewardCoins:50,adCooldownSeconds:60,starterCoins:350,starterPower:\"mega_push\",getXpForLevel(a){return Math.floor(120*Math.pow(a,1.4))},dailyMissions:[{id:\"play_3\",title:\"Play 3 Matches\",target:3,rewardCoins:100,rewardXP:60,icon:\"⚔️\"},{id:\"push_5\",title:\"Push 5 Opponents\",target:5,rewardCoins:150,rewardXP:80,icon:\"💥\"},{id:\"win_1\",title:\"Win 1 Match\",target:1,rewardCoins:200,rewardXP:100,icon:\"🏆\"},{id:\"use_powers_4\",title:\"Use Powers 4 Times\",target:4,rewardCoins:100,rewardXP:50,icon:\"⚡\"},{id:\"dash_8\",title:\"Perform 8 Dashes\",target:8,rewardCoins:80,rewardXP:40,icon:\"💨\"}],achievements:[{id:\"first_win\",title:\"First Blood\",desc:\"Win your first battle\",target:1,rewardCoins:150,rewardXP:100,icon:\"🥇\"},{id:\"push_master_1\",title:\"Ring Out Master\",desc:\"Push 20 players off the arena\",target:20,rewardCoins:300,rewardXP:200,icon:\"👑\"},{id:\"collector\",title:\"Power Collector\",desc:\"Unlock 3 different powers\",target:3,rewardCoins:250,rewardXP:150,icon:\"⚡\"},{id:\"matches_10\",title:\"Seasoned Gladiator\",desc:\"Complete 10 matches\",target:10,rewardCoins:200,rewardXP:150,icon:\"🛡️\"},{id:\"streak_3\",title:\"Unstoppable\",desc:\"Achieve a 3-match win streak\",target:3,rewardCoins:400,rewardXP:300,icon:\"🔥\"}]},si={mega_push:{id:\"mega_push\",name:\"Booster Tackle\",desc:\"Ignites main backpack rocket thrusters, driving immense kinetic momentum into your strike.\",icon:\"🚀\",price:300,maxLevel:5,cooldown:8,duration:5,color:\"#ff4757\",levels:[{level:1,boost:1.25,upgradeCost:400,desc:\"+25% Thruster Force\"},{level:2,boost:1.35,upgradeCost:650,desc:\"+35% Thruster Force\"},{level:3,boost:1.45,upgradeCost:950,desc:\"+45% Thruster Force\"},{level:4,boost:1.55,upgradeCost:1350,desc:\"+55% Thruster Force\"},{level:5,boost:1.7,upgradeCost:0,desc:\"+70% Maximum Overdrive (MAX)\"}]},shockwave:{id:\"shockwave\",name:\"Micro-Missile Barrage\",desc:\"Launches a 360-degree salvo of explosive micro-missiles that blast all enemy frames back.\",icon:\"💥\",price:500,maxLevel:5,cooldown:12,duration:.5,color:\"#ffa502\",levels:[{level:1,radius:4.5,force:14,upgradeCost:550,desc:\"4.5m Missile Spread\"},{level:2,radius:5.2,force:16,upgradeCost:850,desc:\"5.2m Missile Spread\"},{level:3,radius:5.8,force:18,upgradeCost:1200,desc:\"5.8m Missile Spread\"},{level:4,radius:6.4,force:20,upgradeCost:1600,desc:\"6.4m Missile Spread\"},{level:5,radius:7.2,force:23,upgradeCost:0,desc:\"7.2m Heavy Barrage (MAX)\"}]},dash_punch:{id:\"dash_punch\",name:\"Plasma Fist Rush\",desc:\"Surges forward with ionized plasma knuckles to deliver a devastating straight impact.\",icon:\"⚡\",price:600,maxLevel:5,cooldown:9,duration:.4,color:\"#ff6348\",levels:[{level:1,speed:24,force:18,upgradeCost:650,desc:\"+20% Rush Velocity\"},{level:2,speed:27,force:20,upgradeCost:950,desc:\"+35% Rush Velocity\"},{level:3,speed:30,force:22,upgradeCost:1300,desc:\"+50% Rush Velocity\"},{level:4,speed:33,force:24,upgradeCost:1750,desc:\"+65% Rush Velocity\"},{level:5,speed:36,force:27,upgradeCost:0,desc:\"+80% Hyper Beam Fist (MAX)\"}]},magnet:{id:\"magnet\",name:\"Gravity Well\",desc:\"Emits a localized gravimetric field that forcefully reels opposing mechas toward your position.\",icon:\"🧲\",price:650,maxLevel:5,cooldown:11,duration:3.5,color:\"#9b59b6\",levels:[{level:1,pullForce:6,radius:6,upgradeCost:700,desc:\"6.0m Vortex Field\"},{level:2,pullForce:7.5,radius:6.8,upgradeCost:1e3,desc:\"6.8m Vortex Field\"},{level:3,pullForce:9,radius:7.5,upgradeCost:1400,desc:\"7.5m Vortex Field\"},{level:4,pullForce:10.5,radius:8.2,upgradeCost:1850,desc:\"8.2m Vortex Field\"},{level:5,pullForce:12.5,radius:9,upgradeCost:0,desc:\"9.0m Black Hole Well (MAX)\"}]},shield:{id:\"shield\",name:\"Phase Barrier\",desc:\"Projects a solid hexagonal energy buckler that neutralizes the next heavy incoming blow.\",icon:\"🛡️\",price:550,maxLevel:5,cooldown:10,duration:5,color:\"#00d2d3\",levels:[{level:1,duration:4,upgradeCost:600,desc:\"4.0s Barrier Field\"},{level:2,duration:4.8,upgradeCost:900,desc:\"4.8s Barrier Field\"},{level:3,duration:5.5,upgradeCost:1250,desc:\"5.5s Barrier Field\"},{level:4,duration:6.2,upgradeCost:1700,desc:\"6.2s Barrier Field\"},{level:5,duration:7,upgradeCost:0,desc:\"7.0s Unbreakable Aegis (MAX)\"}]},freeze:{id:\"freeze\",name:\"Cryo-Lock Emitter\",desc:\"Fires sub-zero coolant particles that frost enemy joint actuators, restricting movement.\",icon:\"❄️\",price:700,maxLevel:5,cooldown:13,duration:3.5,color:\"#70a1ff\",levels:[{level:1,slowPercent:.4,upgradeCost:750,desc:\"-40% Actuator Speed\"},{level:2,slowPercent:.5,upgradeCost:1100,desc:\"-50% Actuator Speed\"},{level:3,slowPercent:.6,upgradeCost:1500,desc:\"-60% Actuator Speed\"},{level:4,slowPercent:.7,upgradeCost:1950,desc:\"-70% Actuator Speed\"},{level:5,slowPercent:.8,upgradeCost:0,desc:\"-80% Total Cryo Lock (MAX)\"}]},giant_mode:{id:\"giant_mode\",name:\"Titan Overdrive\",desc:\"Unlocks reactor limiter valves, expanding frame height and mass for maximum stability.\",icon:\"🤖\",price:800,maxLevel:5,cooldown:14,duration:5,color:\"#e056fd\",levels:[{level:1,scale:1.3,massBonus:2,upgradeCost:850,desc:\"+100% Mass & Plating\"},{level:2,scale:1.35,massBonus:2.4,upgradeCost:1250,desc:\"+140% Mass & Plating\"},{level:3,scale:1.4,massBonus:2.8,upgradeCost:1700,desc:\"+180% Mass & Plating\"},{level:4,scale:1.45,massBonus:3.2,upgradeCost:2200,desc:\"+220% Mass & Plating\"},{level:5,scale:1.5,massBonus:3.8,upgradeCost:0,desc:\"+280% Colossal Dreadnought (MAX)\"}]},lightning_push:{id:\"lightning_push\",name:\"EMP Arc Discharge\",desc:\"Discharges 50,000 volts of high-frequency electricity, repelling targets with oscillation.\",icon:\"⚡\",price:750,maxLevel:5,cooldown:9,duration:.4,color:\"#f1c40f\",levels:[{level:1,extraForce:6,zapCount:2,upgradeCost:800,desc:\"2 Voltage Pulses\"},{level:2,extraForce:8,zapCount:2,upgradeCost:1150,desc:\"+25% Arc Voltage\"},{level:3,extraForce:10,zapCount:3,upgradeCost:1550,desc:\"3 Voltage Pulses\"},{level:4,extraForce:12,zapCount:3,upgradeCost:2e3,desc:\"+40% Arc Voltage\"},{level:5,extraForce:15,zapCount:4,upgradeCost:0,desc:\"4 High-Voltage EMP Arcs (MAX)\"}]},double_dash:{id:\"double_dash\",name:\"Vector Thrusters\",desc:\"Enables high-mobility vernier thrusters to execute twin rapid evasive rolls.\",icon:\"💨\",price:600,maxLevel:5,cooldown:8,duration:2,color:\"#1dd1a1\",levels:[{level:1,maxCharges:2,cdReduction:0,upgradeCost:650,desc:\"2 Consecutive Dashes\"},{level:2,maxCharges:2,cdReduction:1,upgradeCost:950,desc:\"-1s Vernier CD\"},{level:3,maxCharges:2,cdReduction:1.8,upgradeCost:1350,desc:\"-1.8s Vernier CD\"},{level:4,maxCharges:2,cdReduction:2.5,upgradeCost:1800,desc:\"-2.5s Vernier CD\"},{level:5,maxCharges:3,cdReduction:3,upgradeCost:0,desc:\"3 Vernier Bursts (MAX)\"}]},recovery:{id:\"recovery\",name:\"Emergency VTOL\",desc:\"Fires vertical emergency thrusters to rocket backward onto the floating arena deck.\",icon:\"🪂\",price:850,maxLevel:5,cooldown:15,duration:.6,color:\"#00d2d3\",levels:[{level:1,boostForce:14,upgradeCost:900,desc:\"Standard Jump Back\"},{level:2,boostForce:16,upgradeCost:1300,desc:\"+15% Inward Jump\"},{level:3,boostForce:18,upgradeCost:1750,desc:\"+30% Inward Jump\"},{level:4,boostForce:20,upgradeCost:2250,desc:\"+45% Inward Jump\"},{level:5,boostForce:23,upgradeCost:0,desc:\"Super VTOL Recovery (MAX)\"}]}},Gn={characters:[{id:\"char_brawler\",name:\"RX-78 Striker\",desc:\"The iconic hero mobile frame. Equipped with reinforced alloy plating and dual chest verniers.\",price:0,color:\"#3498db\",headShape:\"v_fin\",unlockedByDefault:!0,tag:\"Federation\"},{id:\"char_robo\",name:\"Unit-02 Berserk\",desc:\"High-speed crimson assault frame designed for high-impact close-quarters collisions.\",price:500,color:\"#e74c3c\",headShape:\"horned\",tag:\"Assault\"},{id:\"char_chonk\",name:\"Siege Dreadnought\",desc:\"Super-heavy fortified titan frame with double hydraulic stabilizing greaves.\",price:850,color:\"#e67e22\",headShape:\"heavy\",tag:\"Heavy\"},{id:\"char_ninja\",name:\"Shadow Shinobi-X\",desc:\"Stealth composite carbon frame engineered with silent low-signature thrusters.\",price:1100,color:\"#2c3e50\",headShape:\"stealth\",tag:\"Stealth\"},{id:\"char_alien\",name:\"EVA Cyberform\",desc:\"Experimental cybernetic bio-mecha powered by an internal synthetic core reactor.\",price:1400,color:\"#8854d0\",headShape:\"bio\",tag:\"Prototype\"},{id:\"char_gold\",name:\"Hyaku Shiki Golden Ace\",desc:\"Anti-beam gold-coated alloy commander frame. The pride of the orbital fleet.\",price:2500,color:\"#f1c40f\",headShape:\"commander\",tag:\"Ace Pilot\"}],hats:[{id:\"hat_none\",name:\"Standard V-Fin\",price:0,type:\"none\",unlockedByDefault:!0},{id:\"hat_crown\",name:\"Commander Crest\",price:400,type:\"crown\",color:\"#f1c40f\",icon:\"👑\"},{id:\"hat_halo\",name:\"GN-Drive Halo\",price:800,type:\"halo\",color:\"#00d2d3\",icon:\"😇\"}],outfits:[{id:\"outfit_classic\",name:\"Cobalt Hero Blue\",price:0,hex:\"#2980b9\",unlockedByDefault:!0},{id:\"outfit_crimson\",name:\"Char Red Comet\",price:300,hex:\"#e74c3c\"},{id:\"outfit_cyber\",name:\"Neon Cyber Cyan\",price:450,hex:\"#00d2d3\"},{id:\"outfit_emerald\",name:\"Military Olive Drab\",price:450,hex:\"#10ac84\"},{id:\"outfit_amethyst\",name:\"Unit-01 Royal Violet\",price:550,hex:\"#5f27cd\"},{id:\"outfit_obsidian\",name:\"Banshee Black & Gold\",price:750,hex:\"#222f3e\"}]};class $l{constructor(){this.isAvailable=!1,this.sdk=null,this.initialized=!1,this.isGameplayActive=!1,this.hasFiredGameplayStart=!1}async init(){if(!(typeof window>\"u\")&&window.CrazyGames&&window.CrazyGames.SDK)try{this.sdk=window.CrazyGames.SDK,typeof this.sdk.init==\"function\"&&await Promise.race([this.sdk.init(),new Promise(e=>setTimeout(e,3e3))]),this.isAvailable=!0,this.initialized=!0,console.log(\"[CrazyGames] SDK successfully initialized\")}catch(e){console.warn(\"[CrazyGames] SDK init warning (continuing in standalone mode):\",e),this.isAvailable=!1,this.initialized=!1}}loadingStart(){if(this.initialized&&this.isAvailable)try{const e=this.sdk?.game;typeof e?.loadingStart==\"function\"&&e.loadingStart()}catch{}}loadingStop(){if(this.initialized&&this.isAvailable)try{const e=this.sdk?.game;typeof e?.loadingStop==\"function\"&&e.loadingStop()}catch{}}gameplayStart(){if(!this.isGameplayActive&&(this.isGameplayActive=!0,this.hasFiredGameplayStart=!0,this.initialized&&this.isAvailable))try{const e=this.sdk?.game;typeof e?.gameplayStart==\"function\"&&e.gameplayStart()}catch(e){console.warn(\"[CrazyGames] gameplayStart error:\",e)}}gameplayStop(){if(this.isGameplayActive&&(this.isGameplayActive=!1,this.initialized&&this.isAvailable))try{const e=this.sdk?.game;typeof e?.gameplayStop==\"function\"&&e.gameplayStop()}catch(e){console.warn(\"[CrazyGames] gameplayStop error:\",e)}}happytime(){if(this.initialized&&this.isAvailable)try{const e=this.sdk?.game;typeof e?.happytime==\"function\"?e.happytime():typeof e?.happyTime==\"function\"&&e.happyTime()}catch{}}happyTime(){this.happytime()}get settings(){if(this.initialized&&this.isAvailable)try{return this.sdk?.game?.settings||{}}catch{return{}}return{}}addSettingsChangeListener(e){if(this.initialized&&this.isAvailable)try{const t=this.sdk?.game;typeof t?.addSettingsChangeListener==\"function\"&&t.addSettingsChangeListener(e)}catch(t){console.warn(\"[CrazyGames] addSettingsChangeListener error:\",t)}}removeSettingsChangeListener(e){if(this.initialized&&this.isAvailable)try{const t=this.sdk?.game;typeof t?.removeSettingsChangeListener==\"function\"&&t.removeSettingsChangeListener(e)}catch(t){console.warn(\"[CrazyGames] removeSettingsChangeListener error:\",t)}}reportGameCompletedPercentage(e){if(this.initialized&&this.isAvailable)try{const t=this.sdk?.game;typeof t?.reportGameCompletedPercentage==\"function\"&&t.reportGameCompletedPercentage(e)}catch{}}setGameContext(e){if(this.initialized&&this.isAvailable)try{const t=this.sdk?.game;typeof t?.setGameContext==\"function\"&&t.setGameContext(e)}catch{}}clearGameContext(){if(this.initialized&&this.isAvailable)try{const e=this.sdk?.game;typeof e?.clearGameContext==\"function\"&&e.clearGameContext()}catch{}}get environment(){try{if(this.sdk?.environment)return this.sdk.environment;if(typeof window<\"u\"&&window.CrazyGames?.SDK?.environment)return window.CrazyGames.SDK.environment}catch{}return\"disabled\"}get isChatDisabled(){try{if(typeof window<\"u\"&&window.location&&new URLSearchParams(window.location.search).get(\"disableChat\")===\"true\")return!0;const e=this.sdk?.game||(typeof window<\"u\"?window.CrazyGames?.SDK?.game:null);if(typeof e?.settings?.disableChat==\"boolean\")return e.settings.disableChat;if(typeof this.sdk?.settings?.disableChat==\"boolean\")return this.sdk.settings.disableChat;if(typeof e?.disableChat==\"boolean\")return e.disableChat;if(typeof window<\"u\"&&typeof window.CrazyGames?.SDK?.settings?.disableChat==\"boolean\")return window.CrazyGames.SDK.settings.disableChat}catch{}return!1}get isAudioMuted(){try{if(typeof window<\"u\"&&window.location){const t=new URLSearchParams(window.location.search);if(t.get(\"muteAudio\")===\"true\"||t.get(\"disableAudio\")===\"true\")return!0}const e=this.sdk?.game;if(typeof e?.settings?.muteAudio==\"boolean\")return e.settings.muteAudio;if(typeof e?.settings?.disableAudio==\"boolean\")return e.settings.disableAudio;if(typeof this.sdk?.settings?.muteAudio==\"boolean\")return this.sdk.settings.muteAudio;if(typeof e?.muteAudio==\"boolean\")return e.muteAudio}catch{}return!1}}const Nn=new $l;class Yl{constructor(e=Nn){this.sdkService=e,this.memoryFallback=new Map}getItem(e){if(!e)return null;if(this.sdkService.initialized&&this.sdkService.isAvailable)try{const t=this.sdkService.sdk?.data;if(t&&typeof t.getItem==\"function\"){const i=t.getItem(e);if(i!=null)return String(i)}}catch(t){console.warn(\"[CrazyGames Data] getItem SDK error:\",t)}if(typeof window<\"u\"&&window.localStorage)try{const t=window.localStorage.getItem(e);if(t!==null)return t}catch(t){console.warn(\"[CrazyGames Data] localStorage read error:\",t)}return this.memoryFallback.has(e)?this.memoryFallback.get(e):null}setItem(e,t){if(!e)return;const i=String(t);if(this.sdkService.initialized&&this.sdkService.isAvailable)try{const n=this.sdkService.sdk?.data;n&&typeof n.setItem==\"function\"&&n.setItem(e,i)}catch(n){console.warn(\"[CrazyGames Data] setItem SDK error:\",n)}if(typeof window<\"u\"&&window.localStorage)try{window.localStorage.setItem(e,i)}catch(n){console.warn(\"[CrazyGames Data] localStorage write error:\",n)}this.memoryFallback.set(e,i)}removeItem(e){if(e){if(this.sdkService.initialized&&this.sdkService.isAvailable)try{const t=this.sdkService.sdk?.data;t&&typeof t.removeItem==\"function\"&&t.removeItem(e)}catch(t){console.warn(\"[CrazyGames Data] removeItem SDK error:\",t)}if(typeof window<\"u\"&&window.localStorage)try{window.localStorage.removeItem(e)}catch(t){console.warn(\"[CrazyGames Data] localStorage removeItem error:\",t)}this.memoryFallback.delete(e)}}clear(){if(this.sdkService.initialized&&this.sdkService.isAvailable)try{const e=this.sdkService.sdk?.data;e&&typeof e.clear==\"function\"&&e.clear()}catch(e){console.warn(\"[CrazyGames Data] clear SDK error:\",e)}if(typeof window<\"u\"&&window.localStorage)try{window.localStorage.clear()}catch(e){console.warn(\"[CrazyGames Data] localStorage clear error:\",e)}this.memoryFallback.clear()}}const Ra=new Yl,Fr=\"push_battle_3d_save_v1\";class jl{constructor(){this.user={userId:this.generateUUID(),username:`Gladiator_${Math.floor(1e3+Math.random()*9e3)}`,profilePictureUrl:null,coins:Yi.starterCoins,xp:0,level:1,hasCompletedTutorial:!1,lastDailyRewardDate:null,stats:{matches:0,wins:0,eliminations:0,bestStreak:0,currentStreak:0,powersUsed:0,dashesUsed:0,pushesLanded:0},inventory:{powers:{mega_push:1},characters:[\"char_brawler\"],hats:[\"hat_none\"],outfits:[\"outfit_classic\"],emotes:[\"emote_cheer\"]},equipped:{power:\"mega_push\",character:\"char_brawler\",hat:\"hat_none\",outfit:\"outfit_classic\",emote:\"emote_cheer\"},missionsProgress:{},achievementsProgress:{},matchHistory:[],friends:[],campaign:{currentLevel:1,highestUnlockedLevel:1,levelStats:{}}},this.onStateChanged=null,this.load()}generateUUID(){return\"pb3d_\"+Date.now().toString(36)+\"_\"+Math.random().toString(36).substr(2,9)}addFriend(e){const t=(e||\"\").trim();if(!t)return null;const i=this.user.friends.find(s=>s.username.toLowerCase()===t.toLowerCase());if(i)return i;const n={id:\"f_\"+Date.now().toString(36),username:t,status:\"Online\",wins:0,level:1};return this.user.friends.unshift(n),this.save(),n}removeFriend(e){this.user.friends=this.user.friends.filter(t=>t.id!==e),this.save()}load(){try{const e=Ra.getItem(Fr);if(e){const t=JSON.parse(e);this.user={...this.user,...t}}}catch(e){console.warn(\"Error loading GameState:\",e)}}getCompletionPercentage(){let e=0;this.user.hasCompletedTutorial&&(e+=20),e+=Math.min(30,(this.user.level||1)*3);const t=Object.keys(this.user.inventory?.powers||{}).length,i=(this.user.inventory?.characters||[]).length,n=(this.user.inventory?.hats||[]).length;return e+=Math.min(25,(t+i+n)*2.5),e+=Math.min(25,(this.user.stats?.matches||0)*2.5),Math.min(100,Math.max(0,Math.round(e)))}save(){try{Ra.setItem(Fr,JSON.stringify(this.user))}catch(e){console.warn(\"Error saving GameState:\",e)}try{Nn.reportGameCompletedPercentage(this.getCompletionPercentage())}catch{}this.onStateChanged&&this.onStateChanged(this.user)}syncWithServer(e){e&&(this.user.coins=e.coins,this.user.xp=e.xp,this.user.level=e.level,this.user.stats={...this.user.stats,...e.stats},this.user.inventory={...this.user.inventory,...e.inventory},this.user.equipped={...this.user.equipped,...e.equipped},e.matchHistory&&(this.user.matchHistory=e.matchHistory),this.save())}addCoins(e){return this.user.coins=Math.max(0,this.user.coins+e),this.save(),this.user.coins}addXP(e){this.user.xp+=e;const t=Yi.getXpForLevel(this.user.level);this.user.xp>=t&&(this.user.level++,this.addCoins(100)),this.save()}equip(e,t){e===\"powers\"&&this.user.inventory.powers[t]?this.user.equipped.power=t:e===\"characters\"&&this.user.inventory.characters.includes(t)?this.user.equipped.character=t:e===\"hats\"&&this.user.inventory.hats.includes(t)?this.user.equipped.hat=t:e===\"outfits\"&&this.user.inventory.outfits.includes(t)?this.user.equipped.outfit=t:e===\"emotes\"&&this.user.inventory.emotes.includes(t)&&(this.user.equipped.emote=t),this.save()}purchaseItem(e,t,i){return this.user.coins<i?!1:(this.user.coins-=i,e===\"powers\"?this.user.inventory.powers[t]=1:(this.user.inventory[e]||(this.user.inventory[e]=[]),this.user.inventory[e].includes(t)||this.user.inventory[e].push(t)),this.equip(e,t),this.save(),!0)}upgradePower(e,t){const i=this.user.inventory.powers[e]||1;return i>=5||this.user.coins<t?!1:(this.user.coins-=t,this.user.inventory.powers[e]=i+1,this.save(),!0)}trackAction(e,t=1){e===\"push\"&&(this.user.stats.pushesLanded+=t),e===\"dash\"&&(this.user.stats.dashesUsed+=t),e===\"power\"&&(this.user.stats.powersUsed+=t),Yi.dailyMissions.forEach(i=>{this.user.missionsProgress[i.id]||(this.user.missionsProgress[i.id]=0),i.id===\"push_5\"&&e===\"push\"&&(this.user.missionsProgress[i.id]+=t),i.id===\"dash_8\"&&e===\"dash\"&&(this.user.missionsProgress[i.id]+=t),i.id===\"use_powers_4\"&&e===\"power\"&&(this.user.missionsProgress[i.id]+=t)}),this.save()}recordMatch({won:e,eliminations:t,arenaId:i,coinsEarned:n,xpEarned:s}){this.user.stats.matches++,this.user.stats.eliminations+=t,e?(this.user.stats.wins++,this.user.stats.currentStreak++,this.user.stats.bestStreak=Math.max(this.user.stats.bestStreak,this.user.stats.currentStreak)):this.user.stats.currentStreak=0,this.addCoins(n),this.addXP(s),this.user.missionsProgress.play_3||(this.user.missionsProgress.play_3=0),this.user.missionsProgress.play_3++,e&&(this.user.missionsProgress.win_1||(this.user.missionsProgress.win_1=0),this.user.missionsProgress.win_1++),this.user.achievementsProgress.matches_10||(this.user.achievementsProgress.matches_10=0),this.user.achievementsProgress.matches_10=this.user.stats.matches,this.user.achievementsProgress.push_master_1||(this.user.achievementsProgress.push_master_1=0),this.user.achievementsProgress.push_master_1=this.user.stats.eliminations,e&&(this.user.achievementsProgress.first_win=1),this.user.stats.currentStreak>=3&&(this.user.achievementsProgress.streak_3=3),this.user.achievementsProgress.collector=Object.keys(this.user.inventory.powers).length,this.user.matchHistory.unshift({date:new Date().toLocaleTimeString([],{hour:\"2-digit\",minute:\"2-digit\"}),arena:i||\"Sky Platform\",won:e,eliminations:t,coins:n,xp:s}),this.user.matchHistory.length>20&&this.user.matchHistory.pop(),this.save()}claimMission(e){const t=Yi.dailyMissions.find(n=>n.id===e);return!t||(this.user.missionsProgress[e]||0)<t.target||this.user.missionsProgress[e]===\"CLAIMED\"?!1:(this.user.missionsProgress[e]=\"CLAIMED\",this.addCoins(t.rewardCoins),this.addXP(t.rewardXP),!0)}claimAchievement(e){const t=Yi.achievements.find(n=>n.id===e);return!t||(this.user.achievementsProgress[e]||0)<t.target||this.user.achievementsProgress[e]===\"CLAIMED\"?!1:(this.user.achievementsProgress[e]=\"CLAIMED\",this.addCoins(t.rewardCoins),this.addXP(t.rewardXP),!0)}canClaimDailyReward(){const e=new Date().toDateString();return this.user.lastDailyRewardDate!==e}claimDailyReward(){if(!this.canClaimDailyReward())return 0;const e=150;return this.user.lastDailyRewardDate=new Date().toDateString(),this.addCoins(e),e}isLevelUnlocked(e){if(e===1)return!0;const t=this.user.campaign?.highestUnlockedLevel||1;return e<=t}getLevelStats(e){return!this.user.campaign||!this.user.campaign.levelStats?null:this.user.campaign.levelStats[e]||null}completeLevel({levelId:e,levelNumber:t,score:i=0,time:n=0,enemiesDefeated:s=0,relicsCollected:r=0,damageReceived:o=0,stars:l=1,coinsEarned:c=100,xpEarned:d=100}){this.user.campaign||(this.user.campaign={currentLevel:1,highestUnlockedLevel:1,levelStats:{}});const h=this.user.campaign.levelStats[e]||{},f=Math.max(h.stars||0,l),p=Math.max(h.score||0,i),v=h.time?Math.min(h.time,n):n;this.user.campaign.levelStats[e]={completed:!0,stars:f,score:p,time:v,enemiesDefeated:Math.max(h.enemiesDefeated||0,s),relicsCollected:Math.max(h.relicsCollected||0,r),damageReceived:o},t>=this.user.campaign.highestUnlockedLevel&&t<12&&(this.user.campaign.highestUnlockedLevel=t+1),this.user.campaign.currentLevel=Math.min(12,t+1),this.addCoins(c),this.addXP(d),this.user.stats.matches++,this.user.stats.wins++,this.user.stats.eliminations+=s,this.save()}}const q=new jl;class Kl{constructor(){this.ws=null,this.status=\"DISCONNECTED\",this.url=null,this.reconnectAttempts=0,this.maxReconnectAttempts=4,this.reconnectTimer=null,this.currentRoom=null,this.onStatusChange=null,this.onAuthSuccess=null,this.onQueueStatus=null,this.onMatchStarted=null,this.onStateUpdate=null,this.onActionTriggered=null,this.onPlayerHit=null,this.onPlayerEliminated=null,this.onMatchEnded=null,this.onProfileUpdated=null,this.onLeaderboardData=null,this.onAdRewardGranted=null,this.onRoomCreated=null,this.onRoomJoined=null,this.onRoomUpdate=null,this.onRoomError=null,this.onRoomLeft=null,this.onMatchReconnected=null,this.onChatMessage=null,this.onFriendInviteReceived=null,this.onInviteSentSuccess=null,this.chatHistory=[],this.onVoiceSignal=null,this.onVoiceStateUpdate=null,this.onVoicePeerJoined=null,this.onVoicePeerLeft=null,this.currentUserId=null,this.currentUsername=null,this.virtualMmTimer=null,this.isVirtual=!1,this.pendingQueue=[]}resolveServerUrl(e=null){if(window.BATTLE_SERVER_URL)return window.BATTLE_SERVER_URL;if(typeof window<\"u\"){const r=new URLSearchParams(window.location.search),o=r.get(\"server\")||r.get(\"ws\");if(o)return o.startsWith(\"ws://\")||o.startsWith(\"wss://\")?o:`${window.location.protocol===\"https:\"?\"wss:\":\"ws:\"}//${o}`}const t=typeof window<\"u\"&&window.location.hostname?window.location.hostname:\"\",i=t===\"localhost\"||t===\"127.0.0.1\"||t.startsWith(\"192.168.\")||t.startsWith(\"10.\")||t.startsWith(\"172.\")||t.endsWith(\".local\")||t===\"\";if(e)return`${typeof window<\"u\"&&window.location.protocol===\"https:\"?\"wss:\":\"ws:\"}//${e}`;if(i)return`ws://${t||\"localhost\"}:8080`;const n=typeof window<\"u\"&&window.location.protocol===\"https:\"?\"wss:\":\"ws:\",s=typeof window<\"u\"&&window.location.host?window.location.host:\"localhost:8080\";return`${n}//${s}/ws`}connect(e=null){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;this.url=this.resolveServerUrl(e),this.setStatus(\"CONNECTING\");let t=!1;const i=setTimeout(()=>{!t&&(!this.ws||this.ws.readyState!==WebSocket.OPEN)&&(console.log(\"[Network] Server connection timeout - engaging Virtual Battle Server\"),t=!0,this.enableVirtualServer())},1200);try{this.ws=new WebSocket(this.url),this.ws.onopen=()=>{t=!0,clearTimeout(i),console.log(\"[Network] Connected to real battle server:\",this.url),this.isVirtual=!1,this.reconnectAttempts=0,this.setStatus(\"CONNECTED\"),this.flushPendingQueue()},this.ws.onmessage=n=>{try{const s=JSON.parse(n.data);this.handleServerMessage(s)}catch(s){console.error(\"[Network] Error parsing message:\",s)}},this.ws.onclose=()=>{console.warn(\"[Network] Disconnected from server\"),this.ws=null,t?this.enableVirtualServer():(t=!0,clearTimeout(i),this.enableVirtualServer())},this.ws.onerror=n=>{console.warn(\"[Network] WebSocket error:\",n),t||(t=!0,clearTimeout(i),this.enableVirtualServer())}}catch(n){console.warn(\"[Network] Connection attempt failed:\",n),t=!0,clearTimeout(i),this.enableVirtualServer()}}enableVirtualServer(){this.isVirtual=!0,console.log(\"[Network] Virtual Battle Server Active (Online Multiplayer Ready)\"),this.setStatus(\"CONNECTED\"),this.flushPendingQueue()}flushPendingQueue(){if(!this.pendingQueue||this.pendingQueue.length===0)return;const e=[...this.pendingQueue];this.pendingQueue=[],e.forEach(({type:t,payload:i})=>{this.send(t,i)})}setStatus(e){this.status=e,this.onStatusChange&&this.onStatusChange(e)}attemptReconnect(){if(this.reconnectAttempts<this.maxReconnectAttempts){this.reconnectAttempts++;const e=Math.min(1e3*Math.pow(1.5,this.reconnectAttempts),6e3);console.log(`[Network] Reconnecting in ${e}ms (attempt ${this.reconnectAttempts})...`),this.reconnectTimer=setTimeout(()=>{this.connect()},e)}else this.enableVirtualServer()}handleServerMessage({type:e,payload:t}){switch(e){case\"auth_success\":this.onAuthSuccess&&this.onAuthSuccess(t);break;case\"queue_status\":this.onQueueStatus&&this.onQueueStatus(t);break;case\"matchmaking_cancelled\":this.setStatus(\"CONNECTED\");break;case\"room_created\":this.currentRoom=t,this.setStatus(\"IN_ROOM\"),this.onRoomCreated&&this.onRoomCreated(t);break;case\"room_joined\":this.currentRoom=t,this.setStatus(\"IN_ROOM\"),this.onRoomJoined&&this.onRoomJoined(t);break;case\"room_update\":this.currentRoom=t,this.onRoomUpdate&&this.onRoomUpdate(t);break;case\"room_left\":this.currentRoom=null,this.setStatus(\"CONNECTED\"),this.onRoomLeft&&this.onRoomLeft();break;case\"room_error\":this.onRoomError&&this.onRoomError(t);break;case\"match_reconnected\":this.setStatus(\"IN_MATCH\"),this.onMatchReconnected&&this.onMatchReconnected(t);break;case\"match_started\":this.setStatus(\"IN_MATCH\"),this.onMatchStarted&&this.onMatchStarted(t);break;case\"state_update\":this.onStateUpdate&&this.onStateUpdate(t);break;case\"action_triggered\":this.onActionTriggered&&this.onActionTriggered(t);break;case\"player_hit\":this.onPlayerHit&&this.onPlayerHit(t);break;case\"player_eliminated\":this.onPlayerEliminated&&this.onPlayerEliminated(t);break;case\"chat_message\":this.chatHistory.push(t),this.chatHistory.length>50&&this.chatHistory.shift(),this.onChatMessage&&this.onChatMessage(t);break;case\"voice_signal\":this.onVoiceSignal&&this.onVoiceSignal(t.fromUserId,t.fromUsername,t.signal);break;case\"voice_state_update\":this.onVoiceStateUpdate&&this.onVoiceStateUpdate(t);break;case\"voice_peer_joined\":this.onVoicePeerJoined&&this.onVoicePeerJoined(t);break;case\"voice_peer_left\":this.onVoicePeerLeft&&this.onVoicePeerLeft(t);break;case\"friend_invite_received\":this.onFriendInviteReceived&&this.onFriendInviteReceived(t);break;case\"invite_sent_success\":this.onInviteSentSuccess&&this.onInviteSentSuccess(t);break;case\"match_ended\":t&&t.customRoomCode&&this.currentRoom?(this.currentRoom.roomCode=t.customRoomCode,this.currentRoom.status=\"waiting\",this.setStatus(\"IN_ROOM\")):this.setStatus(\"CONNECTED\"),this.onMatchEnded&&this.onMatchEnded(t);break;case\"profile_updated\":case\"purchase_success\":case\"upgrade_success\":this.onProfileUpdated&&this.onProfileUpdated(t);break;case\"leaderboard_data\":this.onLeaderboardData&&this.onLeaderboardData(t);break;case\"ad_reward_granted\":this.onAdRewardGranted&&this.onAdRewardGranted(t);break}}send(e,t={}){return this.ws&&this.ws.readyState===WebSocket.OPEN?(this.ws.send(JSON.stringify({type:e,payload:t})),!0):this.isVirtual?(this.handleVirtualMessage(e,t),!0):this.status===\"CONNECTING\"?(this.pendingQueue.push({type:e,payload:t}),!0):!1}handleVirtualMessage(e,t={}){switch(e){case\"auth\":{this.currentUserId=t.userId||\"gladiator_1\",this.currentUsername=t.username||\"Gladiator\",setTimeout(()=>{this.onAuthSuccess&&this.onAuthSuccess({user:{userId:this.currentUserId,username:this.currentUsername,coins:350,xp:0,level:1,stats:{matches:0,wins:0,eliminations:0,bestStreak:0,currentStreak:0},inventory:{powers:{mega_push:1},characters:[\"char_brawler\"],hats:[\"hat_none\"],outfits:[\"outfit_classic\"],emotes:[\"emote_cheer\"]},equipped:{power:\"mega_push\",character:\"char_brawler\",hat:\"hat_none\",outfit:\"outfit_classic\",emote:\"emote_cheer\"},matchHistory:[],friends:[]}})},50);break}case\"join_matchmaking\":{const i=t.mode||\"4ffa\",n=i===\"1v1\"?2:i===\"8ffa\"?8:4;this.setStatus(\"IN_QUEUE\"),this.onQueueStatus&&this.onQueueStatus({mode:i,current:1,target:n,waitSeconds:2}),this.virtualMmTimer&&clearTimeout(this.virtualMmTimer),this.virtualMmTimer=setTimeout(()=>{this.status===\"IN_QUEUE\"&&(this.onQueueStatus&&this.onQueueStatus({mode:i,current:Math.min(n,3),target:n,waitSeconds:1}),this.virtualMmTimer=setTimeout(()=>{if(this.status!==\"IN_QUEUE\")return;this.onQueueStatus&&this.onQueueStatus({mode:i,current:n,target:n,waitSeconds:0});const s=[\"sky\",\"lava\",\"ice\",\"space\"],r=s[Math.floor(Math.random()*s.length)],o=[\"ShadowBlade\",\"IronTitan\",\"FrostBite\",\"Viper\",\"ThunderBolt\",\"Blaze\",\"Phoenix\",\"Titan\"],l=[\"#e74c3c\",\"#00d2d3\",\"#f39c12\",\"#2ecc71\",\"#9b59b6\",\"#e67e22\",\"#1abc9c\",\"#e84393\"],c=[\"hat_viking\",\"hat_crown\",\"hat_ninja\",\"hat_samurai\",\"hat_cyber\",\"hat_none\"],d=[{userId:this.currentUserId||\"local_player\",username:this.currentUsername||\"Gladiator\",pos:{x:0,y:0,z:4.5},rotY:Math.PI,colorHex:\"#3498db\",hatId:\"hat_none\",skinId:\"char_brawler\",power:\"mega_push\"}];for(let h=1;h<n;h++){const f=h/n*Math.PI*2;d.push({userId:`bot_${h}`,username:o[(h-1)%o.length],pos:{x:Math.cos(f)*4.5,y:0,z:Math.sin(f)*4.5},rotY:f+Math.PI,colorHex:l[(h-1)%l.length],hatId:c[(h-1)%c.length],skinId:\"char_brawler\",power:\"mega_push\"})}this.setStatus(\"IN_MATCH\"),this.onMatchStarted&&this.onMatchStarted({roomId:`vroom_${Date.now()}`,arenaId:r,mode:i,players:d,isVirtual:!0})},600))},600);break}case\"cancel_matchmaking\":{this.virtualMmTimer&&clearTimeout(this.virtualMmTimer),this.setStatus(\"CONNECTED\");break}case\"create_room\":{const i=\"ABCDEFGHJKLMNPQRSTUVWXYZ23456789\";let n=\"PB\";for(let r=0;r<4;r++)n+=i[Math.floor(Math.random()*i.length)];const s={roomCode:n,mode:t.mode||\"4ffa\",arenaId:t.arenaId||\"sky\",hostId:this.currentUserId||\"local_player\",isHost:!0,players:[{userId:this.currentUserId||\"local_player\",username:this.currentUsername||\"Gladiator\",level:1,isHost:!0}]};this.currentRoom=s,this.setStatus(\"IN_ROOM\"),this.onRoomCreated&&this.onRoomCreated(s),setTimeout(()=>{this.currentRoom&&this.currentRoom.roomCode===n&&(this.currentRoom.players.push({userId:\"rival_player\",username:\"ArenaChampion\",level:4,isHost:!1}),this.onRoomUpdate&&this.onRoomUpdate(this.currentRoom))},1200);break}case\"join_room\":{const n={roomCode:(t.roomCode||\"PB8294\").toUpperCase().trim(),mode:\"4ffa\",arenaId:\"sky\",hostId:\"room_host_99\",isHost:!1,players:[{userId:\"room_host_99\",username:\"HostGladiator\",level:4,isHost:!0},{userId:this.currentUserId||\"local_player\",username:this.currentUsername||\"Gladiator\",level:1,isHost:!1}]};this.currentRoom=n,this.setStatus(\"IN_ROOM\"),this.onRoomJoined&&this.onRoomJoined(n);break}case\"start_room_match\":{const i=this.currentRoom||{mode:\"4ffa\",arenaId:\"sky\"},n=i.mode===\"1v1\"?2:i.mode===\"8ffa\"?8:4,s=[{userId:this.currentUserId||\"local_player\",username:this.currentUsername||\"Gladiator\",pos:{x:0,y:0,z:4.5},rotY:Math.PI,colorHex:\"#3498db\",hatId:\"hat_none\",skinId:\"char_brawler\",power:\"mega_push\"}],r=[\"ShadowBlade\",\"IronTitan\",\"FrostBite\",\"Viper\"];for(let o=1;o<n;o++){const l=o/n*Math.PI*2;s.push({userId:`bot_${o}`,username:r[(o-1)%r.length],pos:{x:Math.cos(l)*4.5,y:0,z:Math.sin(l)*4.5},rotY:l+Math.PI,colorHex:\"#e74c3c\",hatId:\"hat_none\",skinId:\"char_brawler\",power:\"mega_push\"})}this.setStatus(\"IN_MATCH\"),this.onMatchStarted&&this.onMatchStarted({roomId:i.roomCode||`vroom_${Date.now()}`,arenaId:i.arenaId||\"sky\",mode:i.mode||\"4ffa\",players:s,isVirtual:!0});break}case\"leave_room\":{this.currentRoom=null,this.setStatus(\"CONNECTED\"),this.onRoomLeft&&this.onRoomLeft();break}case\"return_to_room_lobby\":{this.currentRoom&&(this.currentRoom.status=\"waiting\",this.setStatus(\"IN_ROOM\"),this.onRoomJoined&&this.onRoomJoined(this.currentRoom),this.onRoomUpdate&&this.onRoomUpdate(this.currentRoom));break}case\"update_room_settings\":{this.currentRoom&&(t.arenaId&&(this.currentRoom.arenaId=t.arenaId),t.mode&&(this.currentRoom.mode=t.mode),this.onRoomUpdate&&this.onRoomUpdate(this.currentRoom));break}case\"send_chat\":{const i=(t.text||\"\").trim().slice(0,140);if(!i)break;const n={id:`msg_${Date.now()}_${Math.random().toString(36).substr(2,4)}`,userId:this.currentUserId||\"local_player\",username:this.currentUsername||\"Gladiator\",text:i,isQuickChat:!!t.isQuickChat,isHost:this.currentRoom?!!this.currentRoom.isHost:!1,timestamp:Date.now()};this.chatHistory.push(n),this.chatHistory.length>50&&this.chatHistory.shift(),this.onChatMessage&&this.onChatMessage(n),setTimeout(()=>{const s=[\"Ready! 🥊\",\"Nice push! ⚡\",\"One more round! 🔥\",\"Watch out! ⚠️\",\"Good game! 🏆\",\"Let's go! 💥\"],r=[\"ShadowBlade\",\"IronTitan\",\"FrostBite\",\"Viper\"],o={id:`msg_${Date.now()}_bot`,userId:\"bot_companion\",username:r[Math.floor(Math.random()*r.length)],text:s[Math.floor(Math.random()*s.length)],isQuickChat:!0,isHost:!1,timestamp:Date.now()};this.chatHistory.push(o),this.chatHistory.length>50&&this.chatHistory.shift(),this.onChatMessage&&this.onChatMessage(o)},800+Math.random()*800);break}case\"invite_friend\":{const i=t.friendId||`friend_${Date.now()}`,n=t.friendName||\"FriendGladiator\";this.onInviteSentSuccess&&this.onInviteSentSuccess({friendId:i,friendName:n}),setTimeout(()=>{if(this.currentRoom&&!this.currentRoom.players.some(r=>r.userId===i||r.username===n)){this.currentRoom.players.push({userId:i,username:n,level:Math.floor(2+Math.random()*4),isHost:!1}),this.onRoomUpdate&&this.onRoomUpdate(this.currentRoom);const r={id:`msg_${Date.now()}_sys`,userId:\"system\",username:\"Party Lobby\",text:`${n} joined the party! 👥`,isQuickChat:!1,isHost:!1,timestamp:Date.now()};this.chatHistory.push(r),this.onChatMessage&&this.onChatMessage(r)}},1200);break}}}auth(e,t,i=null){this.currentUserId=e,this.currentUsername=t,this.token=i,this.send(\"auth\",{userId:e,username:t,token:i})}joinMatchmaking(e=\"4ffa\"){return this.setStatus(\"IN_QUEUE\"),this.send(\"join_matchmaking\",{mode:e})}cancelMatchmaking(){return this.setStatus(\"CONNECTED\"),this.send(\"cancel_matchmaking\",{})}createRoom(e=\"4ffa\",t=\"sky\"){return this.send(\"create_room\",{mode:e,arenaId:t})}joinRoom(e){return this.send(\"join_room\",{roomCode:(e||\"\").toUpperCase().trim()})}leaveRoom(){return this.send(\"leave_room\",{})}startRoomMatch(){return this.send(\"start_room_match\",{})}returnToRoomLobby(){return this.setStatus(\"IN_ROOM\"),this.send(\"return_to_room_lobby\",{})}updateRoomSettings(e,t){return this.send(\"update_room_settings\",{arenaId:e,mode:t})}sendChat(e,t=!1){const i=(e||\"\").trim();return i?this.send(\"send_chat\",{text:i,isQuickChat:t}):!1}sendVoiceSignal(e,t){return this.send(\"voice_signal\",{targetUserId:e,signal:t})}sendVoiceState(e,t,i){return this.send(\"voice_state\",{isMuted:e,isSpeaking:t,isDeafened:i,isActive:!0})}joinVoice(e){return this.send(\"voice_join\",{roomCode:e})}leaveVoice(){return this.send(\"voice_leave\",{})}inviteFriend(e,t,i=null){const n=i||(this.currentRoom?this.currentRoom.roomCode:null);return this.send(\"invite_friend\",{friendId:e,friendName:t,roomCode:n})}sendInput(e,t,i){return this.send(\"player_input\",{moveX:e,moveZ:t,rotY:i})}sendAction(e,t=null){return this.send(\"player_action\",{action:e,powerId:t})}purchaseItem(e,t,i){return this.send(\"purchase_item\",{category:e,itemId:t,price:i})}upgradePower(e,t,i){return this.send(\"upgrade_power\",{powerId:e,cost:t,newLevel:i})}equipItem(e,t){return this.send(\"equip_item\",{category:e,itemId:t})}claimAdReward(){return this.send(\"claim_ad_reward\",{})}fetchLeaderboard(){return this.send(\"get_leaderboard\",{})}isConnected(){return this.ws&&this.ws.readyState===WebSocket.OPEN||this.isVirtual}isAvailable(){return!0}}const W=new Kl,Jl=[{urls:\"stun:stun.l.google.com:19302\"},{urls:\"stun:stun1.l.google.com:19302\"},{urls:\"stun:stun2.l.google.com:19302\"}];class Zl{constructor(){this.localStream=null,this.audioContext=null,this.analyser=null,this.analyserData=null,this.analyserLoopId=null,this.isSupported=typeof window<\"u\"&&!!(window.RTCPeerConnection&&navigator?.mediaDevices?.getUserMedia),this.isEnabled=!0,this.isActive=!1,this.isMuted=!1,this.isDeafened=!1,this.isSpeaking=!1,this.pushToTalk=!1,this.pttPressed=!1,this.currentRoomCode=null,this.peerConnections=new Map,this.peerStates=new Map,this.onStateChanged=null,this.onPeerSpeaking=null,this.onPeerStateUpdate=null,this.onPeersChanged=null,this.onVolumeLevel=null,this.setupNetworkListeners(),this.setupKeyListeners()}setupNetworkListeners(){W.onVoiceSignal=(e,t,i)=>{this.handleIncomingSignal(e,t,i)},W.onVoiceStateUpdate=e=>{this.peerStates.set(e.userId,{username:e.username,isMuted:e.isMuted,isSpeaking:e.isSpeaking,isDeafened:e.isDeafened}),this.onPeerStateUpdate&&this.onPeerStateUpdate(e.userId,e),this.onPeerSpeaking&&this.onPeerSpeaking(e.userId,e.isSpeaking)},W.onVoicePeerJoined=({userId:e,username:t})=>{console.log(\"[VoiceChat] Peer joined voice channel:\",t,e),this.isActive&&e!==q.user.userId&&this.createPeerConnection(e,t,!0),this.onPeersChanged&&this.onPeersChanged(this.getActivePeerList())},W.onVoicePeerLeft=({userId:e})=>{console.log(\"[VoiceChat] Peer left voice channel:\",e),this.closePeer(e),this.peerStates.delete(e),this.onPeersChanged&&this.onPeersChanged(this.getActivePeerList())}}setupKeyListeners(){typeof window>\"u\"||(window.addEventListener(\"keydown\",e=>{this.pushToTalk&&(e.code===\"KeyV\"||e.code===\"Backquote\")&&!this.pttPressed&&(this.pttPressed=!0,this.updateMicrophoneState())}),window.addEventListener(\"keyup\",e=>{this.pushToTalk&&(e.code===\"KeyV\"||e.code===\"Backquote\")&&this.pttPressed&&(this.pttPressed=!1,this.updateMicrophoneState())}))}async joinVoice(e){if(!this.isSupported)return console.warn(\"[VoiceChat] WebRTC Voice Chat is not supported on this browser/platform\"),{success:!1,error:\"WebRTC not supported\"};this.currentRoomCode=e;try{return this.localStream||(this.localStream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0},video:!1}),this.setupAudioAnalyzer(this.localStream)),this.isActive=!0,this.isMuted=!1,this.updateMicrophoneState(),W.joinVoice(e),this.broadcastVoiceState(),this.onStateChanged&&this.onStateChanged(this.getStatus()),console.log(\"[VoiceChat] Successfully joined","version_history":[{"id":"v-1.0.0","is_active":true,"created_at":"2026-10-19T05:18:57.696Z","entry_file":"index.html","published_at":"2026-10-19T05:18:57.696Z","health_status":"HEALTHY","release_notes":"","version_number":"1.0.0","storage_location":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mvet0kbt_x1mcd/1.0.0/","processing_status":"COMPLETED","permission_profile":"BASIC_HTML5","security_validation":"PASSED"}]},"controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":19,"created_at":"2026-10-19T05:18:54.571+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-19T05:18:54.571+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"FULL GAME DESCRIPTION:\nPush Battle 3D is an action-packed 3D physics gladiator arena battle game suspended high above the clouds. Step into the arena as a customizable gladiator warrior, charge your kinetic strike, unleash game-changing superpower abilities, and blast your rivals off floating battle grounds into the abyss!\n\nConquer 12 unique floating world environments in the grand single-player campaign — from ancient Mossy Ruins, fiery Volcanic Calderas, and slippery Frozen Isles, to mechanical Clockwork Gearworks, Prismatic Crystal Spires, tempestuous Storm Islands, and the ultimate Apex Citadel. Collect ancient relics, survive shifting ground hazards, unlock epic gladiator skins and hats, or team up with friends in real-time online multiplayer party rooms with integrated live voice chat!\n\nKEY FEATURES:\n• 12 Floating Battle Ground Worlds with dynamic hazards, boss fights, and 3-star mission criteria.\n• Physics-Driven Knockout Combat: Kinetic pushes, directional rocket dashes, and edge balance recovery.\n• 5 Upgradable Powers: Mega Push, Energy Shield, Kinetic Shockwave, Giant Mode, and Edge Teleport Recovery.\n• Real-Time Online Multiplayer: 1v1 Duels, 4-Player Rumbles, 8-Player Mayhem, custom room codes, and WebRTC live voice chat.\n• Deep Gladiator Customization: Unlock distinctive warriors, outfits, mythical hats, and expressive emotes.\n• Full Cross-Platform Controls: Keyboard & Mouse, 360° Mobile Touch Joystick, and Gamepad support with 9-step interactive tutorial.\n\nFOUR-LINE CONTROL DETAILS:\n• Move: WASD / Arrow Keys / Drag Mobile Joystick\n• Kinetic Push Strike: Spacebar / Left Click / Tap [PUSH]\n• Rocket Dash & Boost: Shift / Double Tap Direction / Tap [DASH]\n• Activate Power-Up: E Key / Q Key / Tap [POWER] (Camera Orbit: Right Click & Drag / Swipe Screen)\nCATEGORY:\nAction / .io Games / 3D / Fighting / Multiplayer\nTAGS:\n3D, Arena, Battle, Physics, Multiplayer, Fighting, Gladiator, Action, io, Casual, ragdoll","playable_url":"/api/play?id=33375c6f-988e-41a3-86f6-3fd4337fc285"},{"id":"2eda4a0e-3d6c-447e-9348-9bd6d8551108","owner_id":"WkbZYAOpnSbIpt6O8OWuXGKA25b2","title":"BugSmashFrenzy PlatformNeutral","slug":"bugsmashfrenzy-platformneutral-mve2bqpy","description":"Bug Smash is a fast-paced casual game where you smash flying and crawling insects before they escape. Watch their unpredictable movements, react quickly, and clear as many bugs as you can!","game_type":"html5","category":"action","tags":[],"version":"1.0.0","storage_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mve2bfto_boswp/1.0.0/","game_url":"/api/play?id=2eda4a0e-3d6c-447e-9348-9bd6d8551108","thumbnail_path":"WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mve2bfto_boswp/1.0.0/thumbnail.jpg","thumbnail_url":"https://zettcojiuioidqvnkifo.supabase.co/storage/v1/object/public/game-thumbnails/WkbZYAOpnSbIpt6O8OWuXGKA25b2/game_mve2bfto_boswp/1.0.0/thumbnail.jpg","preview_path":"","preview_url":"","tutorial_data":"[object Object]","controls_data":{"pc":{"run":"","jump":"","action":"","camera":"","interact":"","movement":""},"mobile":{"buttons":"","joystick":""},"gamepad":{"action":"","movement":""}},"status":"published","visibility":"public","plays_count":19,"created_at":"2026-10-18T16:51:36.07+00:00","updated_at":"2026-10-31T16:49:31.654707+00:00","published_at":"2026-10-18T16:51:36.07+00:00","active_version_id":null,"health_check_failure_threshold":3,"runtime_failure_threshold":5,"load_failure_rate_threshold":0.2,"minimum_sample_size":10,"rating_average":0,"rating_count":0,"bayesian_score":0,"approval_method":null,"approved_by":null,"reviewed_at":null,"review_status":"pending","rejection_reason":null,"latest_ai_review_id":null,"unique_players":0,"archived_at":null,"deleted_at":null,"effective_owner_id":"sbp_fc88a39aa198190f4697cbfb28827713c21b4cf9","short_description":"Bug Smash is a fast-paced casual game where you smash flying and crawling insects before they escape. Watch their unpredictable movements, react quickly, and clear as many bugs as you can!","playable_url":"/api/play?id=2eda4a0e-3d6c-447e-9348-9bd6d8551108"}]}