{"asset_map": {"gem_red": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_red_b6b98f36-2a9a-4483-b066-2a797ebe6c88.webp", "type": "image", "prompt": "Generate a single sparkling diamond-shaped gem in deep ruby red (#FF1744). The gem features a faceted, crystalline appearance with multiple shine points and a bright white highlight at the top-center. Style: soft, dreamy, ASMR-friendly, clean polished game asset with a subtle outer glow. Transparent background, high resolution, front view.", "description": "A deep ruby red faceted diamond gem for the strawberry canvas", "subtype": "object", "aspect_ratio": [687, 558], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_pink": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_pink_26bbd506-b316-413c-a406-ad58cd9528cb.webp", "type": "image", "prompt": "Generate a single sparkling diamond-shaped gem in soft light pink (#FF80AB). Match the exact same faceted crystalline style, shape, and facet pattern as gem_red. Include the same subtle outer glow effect and white highlight point. Style: soft, dreamy, ASMR-friendly game asset. Transparent background.", "description": "A soft light pink faceted diamond gem, matching the red gem style", "subtype": "object", "aspect_ratio": [967, 783], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_dark_green": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_dark_green_a5458887-883f-4e18-be74-cd8124d7b5cd.webp", "type": "image", "prompt": "Generate a single sparkling diamond-shaped gem in dark forest green (#2E7D32). Match the exact same faceted crystalline style, shape, and facet pattern as gem_red. Include the same subtle outer glow effect and white highlight point. Style: soft, dreamy, ASMR-friendly game asset. Transparent background.", "description": "A dark forest green faceted diamond gem for the strawberry leaves", "subtype": "object", "aspect_ratio": [1022, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_light_green": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_light_green_6eb08a25-8145-41c5-b515-664740532d74.webp", "type": "image", "prompt": "Generate a single sparkling diamond-shaped gem in light spring green (#81C784). Match the exact same faceted crystalline style, shape, and facet pattern as gem_red. Include the same subtle outer glow effect and white highlight point. Style: soft, dreamy, ASMR-friendly game asset. Transparent background.", "description": "A light spring green faceted diamond gem for leaf highlights", "subtype": "object", "aspect_ratio": [1022, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_yellow": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_yellow_1448e3f1-2aec-448a-a8b5-b46d70de6f51.webp", "type": "image", "prompt": "Generate a single sparkling diamond-shaped gem in bright golden yellow (#FFD600). Match the exact same faceted crystalline style, shape, and facet pattern as gem_red. Include the same subtle outer glow effect and white highlight point. Style: soft, dreamy, ASMR-friendly game asset. Transparent background.", "description": "A bright golden yellow faceted diamond gem for the strawberry seeds", "subtype": "object", "aspect_ratio": [1023, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "sparkle_particle": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/sparkle_particle_29f82812-63b0-465a-8f21-e2519b7259a0.webp", "type": "image", "prompt": "Generate a small, bright four-pointed star sparkle particle. Bright white center fading softly to transparent at the edges. Soft, dreamy twinkle effect, minimal and clean, not harsh. Transparent background, game-ready visual effect asset.", "description": "A small four-pointed star sparkle for placement animations", "subtype": "effect", "aspect_ratio": [279, 499], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "gem_click_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/gem_click_sound_0bd49501-dcc6-4e79-9cc8-027678142c65.mp3", "type": "audio", "prompt": "High-quality ASMR crystal clink sound effect. A small, real diamond being placed gently on a hard polished surface. Short, quiet, crisp, and pure tone with a subtle, airy harmonic resonance. Zero background noise, high fidelity, delicate and satisfying tactile feedback for a relaxing experience.", "description": "A very soft, delicate ASMR crystal clink for placing diamonds, featuring a crisp attack and a pure harmonic tail.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.33, "loop": false, "animation": null}, "completion_shimmer_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/completion_shimmer_sound_fa7f2a7a-34bf-44ce-bf4d-e02879d9380b.mp3", "type": "audio", "prompt": "A magical and relaxing game completion fanfare. Gentle ascending chime melody with shimmering crystalline overtones. Includes a soft sparkle texture and a resonant bell-like finish. ASMR-friendly, soothing, rewarding, and airy. No heavy percussion or bass. Evokes a sense of accomplishment and rainbow light.", "description": "A magical, shimmering chime melody for completing a fruit canvas.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3.0, "loop": false, "animation": null}, "gem_blue": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_blue_3a1ef2fc-a8a7-4707-81a7-0dceb81751ed.webp", "type": "image", "prompt": "Generate a high-quality, deep sapphire blue faceted diamond gem. The gem should have sharp, clean facets, a sparkling crystalline appearance, and a polished finish. Match the artistic style, lighting, and top-down perspective of gem_red. Centered composition, professional game asset, transparent background.", "description": "A deep sapphire blue faceted diamond gem, matching the existing gem collection.", "subtype": "object", "aspect_ratio": [1023, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_purple": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_purple_7b755753-e9dd-49ad-a5fc-23fc1d2c46c4.webp", "type": "image", "prompt": "Generate a high-quality, professional game asset of a rich amethyst purple faceted diamond gem. The gem should have a sparkling, crystalline appearance with sharp facets and a transparent, glass-like quality. Top-down view, perfectly centered, matching the art style and diamond shape of gem_red. Clean lines, vibrant color, high resolution, transparent background.", "description": "A rich amethyst purple faceted diamond gem for the diamond painting canvas", "subtype": "object", "aspect_ratio": [1023, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_orange": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_orange_fbf3bf8e-57c4-4191-b01d-667583e0367f.webp", "type": "image", "prompt": "Generate a high-quality, bright amber orange faceted diamond gem. The gem should have a sparkling, crystalline appearance with sharp facets and realistic light reflections, matching the artistic style and top-down perspective of gem_red. Professional game asset, centered illustration, transparent background.", "description": "A bright amber orange faceted diamond gem for the diamond painting collection", "subtype": "object", "aspect_ratio": [1022, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_brown": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_brown_38f63dd4-2315-4780-b120-fb3de3e0201c.webp", "type": "image", "prompt": "Generate a smoky quartz brown faceted diamond gem. It must match the artistic style, facet pattern, and crystalline appearance of the gem in image 1. Top-down view, centered, highly detailed sparkling crystalline texture, clean sharp edges, professional game asset, transparent background.", "description": "A smoky quartz brown faceted diamond gem for the diamond painting canvas", "subtype": "object", "aspect_ratio": [1023, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_white": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_white_4137912b-406e-42d9-84b8-e5e520566ea0.webp", "type": "image", "prompt": "Generate a clear, brilliant white faceted diamond gem with a sparkling, crystalline appearance. The gem should have sharp facets and a transparent, glass-like quality, matching the visual style of gem_red. Top-down view, centered illustration, clean and polished game asset, transparent background.", "description": "A brilliant white faceted diamond gem, matching the existing gem collection style.", "subtype": "object", "aspect_ratio": [1016, 815], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "gem_black": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/gem_black_f7c61561-4811-442e-ad2a-36bfdfd73ef0.webp", "type": "image", "prompt": "Generate a polished onyx black faceted diamond gem. It should have a sparkling, crystalline appearance with sharp facets and a transparent quality, matching the exact art style and top-down perspective of image 1. Top-down view, centered on a transparent background, high resolution, game-ready asset.", "description": "A polished onyx black faceted diamond gem for the diamond painting canvas", "subtype": "object", "aspect_ratio": [1022, 830], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "color_complete_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/color_complete_sound_98e7452a-35a4-4658-96a5-0b6a0ce9ea60.mp3", "type": "audio", "prompt": "A brief, magical sparkle chime for a puzzle game. High-pitched crystal textures with a light ascending glissando. Satisfying 'ding' sound effect with a shimmering reverb tail. Sounds like a light magical success cue, clean and airy, consistent with a relaxing ASMR gem-placing aesthetic.", "description": "A light, magical sparkle chime for completing a specific color in the diamond painting. Brief and satisfying.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.54, "loop": false, "animation": null}, "slice_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/slice_sound_7ec03959-6b55-4d30-85d7-7fe257b9cdf0.mp3", "type": "audio", "prompt": "High-quality ASMR sound effect of a sharp blade slicing through a soft, juicy fruit. A quick, crisp 'swoosh' of air followed immediately by a wet, fibrous cut and a soft, heavy organic thud as the piece lands. Close-mic recording, intimate and satisfying texture, clean audio with no background noise, minimal reverb, focus on the squelch and the gentle impact.", "description": "ASMR-style sound effect of a sharp blade slicing through fruit followed by a soft thud.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.99, "loop": false, "animation": null}, "reveal_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/reveal_sound_9f4f1320-20da-4a56-89ac-241bb571369b.mp3", "type": "audio", "prompt": "A whimsical, cheerful 'ta-da' reveal sound effect. Brief and magical with a rising melodic motif. Features high-pitched crystalline chimes, a soft harp glissando, and a subtle sparkling glitter texture. Positive, bright, and satisfying resolution in a major key. Clean ASMR quality to match a diamond painting aesthetic, no heavy percussion, no dark tones.", "description": "A whimsical and magical 'ta-da' sound for revealing the surprise hidden inside the fruit.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.4, "loop": false, "animation": null}, "background_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/background_music_24810006-a09f-473f-abb2-3eecc256f0a0.mp3", "type": "audio", "prompt": "Extremely soft and relaxing ambient music for a cozy ASMR game. Minimalist light piano melodies, lush atmospheric pads, and gentle ethereal textures. 60-70 BPM, C Major or G Major. No drums, no sharp attacks, very low dynamic range to ensure a calming background presence. Seamless loop with a smooth transition at the end, evocative of peace and focus.", "description": "A soft, dreamy ambient track for a cozy ASMR diamond painting experience.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30.0, "loop": true, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>ASMR Fruit Diamond Art</title>\n    <style>\n        body, html {\n            margin: 0;\n            padding: 0;\n            width: 100%;\n            height: 100%;\n            overflow: hidden;\n            touch-action: none;\n            -ms-touch-action: none;\n            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n        }\n\n        #game-world {\n            position: relative;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(180deg, #1a0030 0%, #0a0020 100%);\n            display: flex;\n            flex-direction: column;\n        }\n\n        /* Menu Screen */\n        #menu-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(180deg, #1a0030 0%, #0a0020 100%);\n            z-index: 1000;\n            display: flex;\n            flex-direction: column;\n            overflow-y: auto;\n            padding: 40px 20px;\n            box-sizing: border-box;\n        }\n\n        #menu-title {\n            color: #FFFFFF;\n            font-size: 48px;\n            text-align: center;\n            margin-bottom: 40px;\n            font-weight: 800;\n            text-shadow: 0 0 20px rgba(255, 255, 255, 0.3);\n        }\n\n        #levels-grid {\n            display: grid;\n            grid-template-columns: repeat(3, 1fr);\n            gap: 20px;\n            width: 100%;\n        }\n\n        .level-card {\n            aspect-ratio: 1;\n            background: rgba(255, 255, 255, 0.05);\n            border-radius: 20px;\n            border: 2px solid rgba(255, 255, 255, 0.1);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            position: relative;\n            cursor: pointer;\n            transition: all 0.2s;\n            overflow: hidden;\n        }\n\n        .level-card:active {\n            transform: scale(0.95);\n        }\n\n        .level-card.locked {\n            filter: grayscale(1);\n            opacity: 0.6;\n            cursor: not-allowed;\n        }\n\n        .level-card .level-thumbnail {\n            width: 80%;\n            height: 80%;\n            object-fit: contain;\n            image-rendering: pixelated;\n        }\n\n        .level-card .level-name {\n            position: absolute;\n            bottom: 10px;\n            color: white;\n            font-size: 14px;\n            font-weight: 600;\n        }\n\n        .level-card .lock-icon {\n            font-size: 40px;\n            position: absolute;\n            z-index: 2;\n        }\n\n        /* Game Screen */\n        #game-screen {\n            display: none;\n            flex-direction: column;\n            width: 100%;\n            height: 100%;\n        }\n\n        #back-button {\n            position: absolute;\n            top: 20px;\n            left: 20px;\n            width: 60px;\n            height: 60px;\n            background: rgba(255, 255, 255, 0.1);\n            border-radius: 50%;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            color: white;\n            font-size: 30px;\n            z-index: 500;\n            cursor: pointer;\n            border: 1px solid rgba(255, 255, 255, 0.2);\n        }\n\n        /* Progress Bar Section */\n        #progress-section {\n            padding: 16px;\n            text-align: center;\n        }\n\n        #progress-label {\n            color: #E0E1DD;\n            font-size: 18px;\n            margin-bottom: 8px;\n            font-weight: 500;\n        }\n\n        #progress-bar-container {\n            width: 100%;\n            height: 24px;\n            background: rgba(255, 255, 255, 0.1);\n            border-radius: 20px;\n            overflow: hidden;\n            box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);\n        }\n\n        #progress-bar-fill {\n            height: 100%;\n            width: 0%;\n            background: linear-gradient(90deg, #FF80AB, #FFD600, #81C784);\n            border-radius: 20px;\n            transition: width 0.3s cubic-bezier(0.0, 0, 0.2, 1);\n            box-shadow: 0 0 10px rgba(255, 128, 171, 0.5);\n        }\n\n        /* Canvas Section */\n        #canvas-section {\n            flex: 1;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            padding: 16px;\n            position: relative;\n            overflow: hidden;\n            touch-action: none;\n        }\n\n        #zoom-container {\n            position: relative;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            transform-origin: center;\n            cursor: grab;\n        }\n\n        #zoom-container:active {\n            cursor: grabbing;\n        }\n\n        #game-canvas {\n            image-rendering: crisp-edges;\n            box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);\n        }\n\n        #sparkle-layer {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: none;\n        }\n\n        #zoom-controls {\n            position: absolute;\n            bottom: 32px;\n            right: 32px;\n            display: flex;\n            flex-direction: column;\n            gap: 16px;\n            z-index: 100;\n        }\n\n        .zoom-button {\n            width: 80px;\n            height: 80px;\n            border-radius: 50%;\n            background: rgba(255, 255, 255, 0.15);\n            backdrop-filter: blur(8px);\n            border: 2px solid rgba(255, 255, 255, 0.3);\n            color: white;\n            font-size: 40px;\n            font-weight: bold;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            user-select: none;\n            transition: all 0.2s;\n            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n        }\n\n        .zoom-button:active {\n            background: rgba(255, 255, 255, 0.3);\n            transform: scale(0.9);\n        }\n\n        /* Completion Message */\n        #completion-message {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%) scale(0);\n            background: rgba(255, 255, 255, 0.95);\n            color: #0A1128;\n            padding: 32px 48px;\n            border-radius: 24px;\n            font-size: 48px;\n            font-weight: 700;\n            text-align: center;\n            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);\n            pointer-events: none;\n            opacity: 0;\n            z-index: 200;\n            display: none; /* Hidden by default now */\n        }\n\n        /* Loading Screen */\n        #loading-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(180deg, #1a0030 0%, #0a0020 100%);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 3000;\n        }\n\n        #loading-content {\n            text-align: center;\n        }\n\n        #loading-title {\n            color: #FFFFFF;\n            font-size: 56px;\n            font-weight: 800;\n            margin-bottom: 40px;\n            text-shadow: 0 0 30px rgba(255, 255, 255, 0.4);\n            animation: pulse 2s ease-in-out infinite;\n        }\n\n        @keyframes pulse {\n            0% { transform: scale(1); opacity: 0.8; }\n            50% { transform: scale(1.05); opacity: 1; }\n            100% { transform: scale(1); opacity: 0.8; }\n        }\n\n        #sparkle-animation-container {\n            position: relative;\n            height: 60px;\n            width: 100%;\n        }\n\n        .loading-sparkle {\n            position: absolute;\n            width: 20px;\n            height: 20px;\n            background: white;\n            clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);\n            animation: float-sparkle 1.5s ease-in-out infinite;\n            box-shadow: 0 0 10px white;\n        }\n\n        @keyframes float-sparkle {\n            0% { transform: translate(0, 0) scale(0); opacity: 0; }\n            50% { transform: translate(0, -20px) scale(1.5); opacity: 1; }\n            100% { transform: translate(0, -40px) scale(0); opacity: 0; }\n        }\n\n        /* Main Menu */\n        #main-menu-screen {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: linear-gradient(180deg, #1a0030 0%, #0a0020 100%);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 2500;\n            overflow: hidden;\n        }\n\n        #menu-background {\n            position: absolute;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            pointer-events: auto;\n            z-index: 0;\n        }\n\n        .floating-silhouette {\n            position: absolute;\n            font-size: 120px;\n            filter: blur(20px) opacity(0.2);\n            animation: float-slow 40s ease-in-out infinite alternate;\n            user-select: none;\n            pointer-events: none;\n        }\n\n        .floating-gem-menu {\n            position: absolute;\n            width: 50px;\n            filter: drop-shadow(0 0 20px rgba(255, 255, 255, 0.4));\n            animation: float-gem 25s ease-in-out infinite alternate, sparkle-slow 4s infinite ease-in-out;\n            user-select: none;\n            cursor: pointer;\n            pointer-events: auto;\n            transition: transform 0.1s;\n        }\n\n        .floating-gem-menu:active {\n            transform: scale(0.8);\n        }\n\n        @keyframes float-slow {\n            0% { transform: translate(0, 0) rotate(0deg); }\n            100% { transform: translate(120px, 150px) rotate(30deg); }\n        }\n\n        @keyframes float-gem {\n            0% { transform: translate(0, 0) rotate(0deg) scale(1); }\n            100% { transform: translate(-80px, 100px) rotate(-20deg) scale(1.15); }\n        }\n\n        @keyframes sparkle-slow {\n            0%, 100% { filter: drop-shadow(0 0 15px rgba(255, 255, 255, 0.3)) brightness(1); }\n            50% { filter: drop-shadow(0 0 30px rgba(255, 255, 255, 0.7)) brightness(1.4); }\n        }\n\n        #main-menu-content {\n            text-align: center;\n            padding: 40px;\n            z-index: 10;\n            position: relative;\n        }\n\n        #main-menu-title {\n            color: #FFFFFF;\n            font-size: 64px;\n            font-weight: 800;\n            margin-bottom: 20px;\n            line-height: 1.1;\n            text-shadow: 0 0 40px rgba(255, 255, 255, 0.4);\n        }\n\n        #main-menu-subtitle {\n            color: rgba(255, 255, 255, 0.7);\n            font-size: 24px;\n            margin-bottom: 60px;\n            line-height: 1.4;\n        }\n\n        #start-button {\n            padding: 24px 80px;\n            font-size: 32px;\n            font-weight: 800;\n            color: white;\n            background: linear-gradient(135deg, #FF4081, #FFD600);\n            border: none;\n            border-radius: 60px;\n            cursor: pointer;\n            box-shadow: 0 10px 30px rgba(255, 64, 129, 0.5);\n            transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);\n        }\n\n        #start-button:active {\n            transform: scale(0.9);\n            box-shadow: 0 5px 15px rgba(255, 64, 129, 0.5);\n        }\n\n        #knife {\n            position: absolute;\n            width: 400px;\n            height: 80px;\n            z-index: 2000;\n            pointer-events: none;\n            display: none;\n            transform: translate(-50%, -50%);\n        }\n\n        /* Blade */\n        #knife::before {\n            content: '';\n            position: absolute;\n            bottom: 0;\n            left: 0;\n            width: 300px;\n            height: 40px;\n            background: linear-gradient(180deg, #e0e0e0 0%, #999 50%, #bbb 100%);\n            border-radius: 4px 100% 10px 4px;\n            box-shadow: 0 0 30px rgba(255, 255, 255, 0.4);\n        }\n\n        /* Handle */\n        #knife::after {\n            content: '';\n            position: absolute;\n            bottom: 5px;\n            left: -100px;\n            width: 120px;\n            height: 30px;\n            background: #3e2723;\n            border-radius: 8px 4px 4px 8px;\n            box-shadow: inset 0 0 10px rgba(0,0,0,0.5);\n        }\n\n        .fruit-half {\n            position: absolute;\n            pointer-events: none;\n            z-index: 1500;\n            transition: transform 1.5s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 1.5s;\n        }\n\n        .surprise-reveal {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%) scale(0);\n            font-size: 150px;\n            z-index: 1400;\n            pointer-events: none;\n            animation: surprise-pop 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;\n            animation-delay: 0.3s;\n        }\n\n        @keyframes surprise-pop {\n            0% { transform: translate(-50%, -50%) scale(0) rotate(-20deg); opacity: 0; }\n            70% { transform: translate(-50%, -50%) scale(1.2) rotate(10deg); opacity: 1; }\n            100% { transform: translate(-50%, -50%) scale(1) rotate(0deg); opacity: 1; }\n        }\n\n        /* Surprise animations */\n        .disco-spin { animation: surprise-pop 0.8s forwards, disco-spin-anim 2s linear infinite; }\n        @keyframes disco-spin-anim { from { filter: hue-rotate(0deg); transform: translate(-50%, -50%) rotate(0deg); } to { filter: hue-rotate(360deg); transform: translate(-50%, -50%) rotate(360deg); } }\n\n        .chick-bounce { animation: surprise-pop 0.8s forwards, chick-bounce-anim 0.5s ease-in-out infinite alternate; }\n        @keyframes chick-bounce-anim { from { transform: translate(-50%, -50%) translateY(0); } to { transform: translate(-50%, -50%) translateY(-30px); } }\n\n        .fire-pulse { animation: surprise-pop 0.8s forwards, fire-pulse-anim 0.6s ease-in-out infinite alternate; }\n        @keyframes fire-pulse-anim { from { transform: translate(-50%, -50%) scale(1); filter: brightness(1); } to { transform: translate(-50%, -50%) scale(1.2); filter: brightness(1.5); } }\n\n        .rainbow-fade { animation: surprise-pop 0.8s forwards, rainbow-fade-anim 3s linear infinite; }\n        @keyframes rainbow-fade-anim { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } }\n\n        .eyes-wiggle { animation: surprise-pop 0.8s forwards, eyes-wiggle-anim 0.3s ease-in-out infinite; }\n        @keyframes eyes-wiggle-anim { 0% { transform: translate(-50%, -50%) translateX(-5px); } 50% { transform: translate(-50%, -50%) translateX(5px); } 100% { transform: translate(-50%, -50%) translateX(-5px); } }\n\n        .confetti-burst { animation: surprise-pop 0.8s forwards, confetti-burst-anim 1s ease-out infinite; }\n        @keyframes confetti-burst-anim { 0% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } }\n\n        @keyframes bounce-glow {\n            0% { transform: scale(1); filter: brightness(1); }\n            50% { transform: scale(1.2); filter: brightness(2.5) drop-shadow(0 0 50px #fff); }\n            100% { transform: scale(1.1); filter: brightness(2) drop-shadow(0 0 40px #fff); }\n        }\n\n        .bounce-glow {\n            animation: bounce-glow 0.6s ease-in-out infinite alternate;\n        }\n\n        @keyframes knife-slice {\n            0% { left: -20%; top: -20%; transform: translate(-50%, -50%) rotate(45deg); }\n            100% { left: 120%; top: 120%; transform: translate(-50%, -50%) rotate(45deg); }\n        }\n\n        .slicing {\n            display: block !important;\n            animation: knife-slice 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards;\n        }\n\n        /* Color Palette Section */\n        #palette-section {\n            padding: 16px;\n            display: flex;\n            justify-content: center;\n            gap: 12px;\n            background: rgba(0, 0, 0, 0.3);\n        }\n\n        .color-button {\n            width: 96px;\n            height: 96px;\n            border-radius: 16px;\n            border: 3px solid transparent;\n            cursor: pointer;\n            transition: all 0.15s cubic-bezier(0.0, 0, 0.2, 1);\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            justify-content: center;\n            gap: 4px;\n            position: relative;\n            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);\n        }\n\n        .color-button:active {\n            transform: scale(0.95);\n        }\n\n        .color-button.selected {\n            border-color: #FFFFFF;\n            box-shadow: 0 0 20px rgba(255, 255, 255, 0.6), 0 4px 12px rgba(0, 0, 0, 0.4);\n            transform: scale(1.05);\n        }\n\n        .color-button .gem-preview {\n            width: 48px;\n            height: 48px;\n            image-rendering: crisp-edges;\n        }\n\n        .color-button .color-number {\n            color: #FFFFFF;\n            font-size: 20px;\n            font-weight: 700;\n            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8);\n        }\n\n        /* Pop Animation for finished colors */\n        .color-button.pop-out {\n            animation: pop-out 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;\n            pointer-events: none;\n        }\n\n        @keyframes pop-out {\n            0% { transform: scale(1.05); opacity: 1; }\n            40% { transform: scale(1.3); opacity: 1; }\n            100% { transform: scale(0); opacity: 0; }\n        }\n\n        /* Sparkle Animation */\n        .sparkle {\n            position: absolute;\n            pointer-events: none;\n            animation: sparkle-fade 0.6s ease-out forwards;\n        }\n\n        @keyframes sparkle-fade {\n            0% {\n                opacity: 1;\n                transform: scale(0) rotate(0deg);\n            }\n            50% {\n                opacity: 1;\n                transform: scale(1.5) rotate(180deg);\n            }\n            100% {\n                opacity: 0;\n                transform: scale(0.5) rotate(360deg);\n            }\n        }\n\n        @keyframes sparkle-explode {\n            0% {\n                opacity: 1;\n                transform: translate(-50%, -50%) scale(0) rotate(0deg);\n            }\n            100% {\n                opacity: 0;\n                transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(1.5) rotate(360deg);\n            }\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\">\n        <!-- Loading Screen -->\n        <div id=\"loading-screen\">\n            <div id=\"loading-content\">\n                <h1 id=\"loading-title\">ASMR Fruit Diamond Art</h1>\n                <div id=\"sparkle-animation-container\"></div>\n            </div>\n        </div>\n\n        <!-- Main Menu -->\n        <div id=\"main-menu-screen\" style=\"display: none;\">\n            <div id=\"menu-background\"></div>\n            <div id=\"main-menu-content\">\n                <h1 id=\"main-menu-title\">ASMR Fruit<br>Diamond Art</h1>\n                <p id=\"main-menu-subtitle\">Tap sparkling gems onto fruit canvases<br>and watch them come to life \u2728</p>\n                <button id=\"start-button\">START</button>\n            </div>\n        </div>\n\n        <!-- Level Select Screen -->\n        <div id=\"menu-screen\" style=\"display: none;\">\n            <h1 id=\"menu-title\">ASMR Fruit Art</h1>\n            <div id=\"levels-grid\"></div>\n        </div>\n\n        <!-- Game Screen -->\n        <div id=\"game-screen\">\n            <div id=\"back-button\">\u2190</div>\n            \n            <div id=\"progress-section\">\n                <div id=\"progress-label\">0%</div>\n                <div id=\"progress-bar-container\">\n                    <div id=\"progress-bar-fill\"></div>\n                </div>\n            </div>\n\n            <div id=\"canvas-section\">\n                <div id=\"zoom-container\">\n                    <canvas id=\"game-canvas\"></canvas>\n                    <div id=\"sparkle-layer\"></div>\n                </div>\n                \n                <div id=\"zoom-controls\">\n                    <div id=\"zoom-in\" class=\"zoom-button\">+</div>\n                    <div id=\"zoom-out\" class=\"zoom-button\">-</div>\n                </div>\n\n                <div id=\"completion-message\">Complete!</div>\n                <div id=\"knife\"></div>\n            </div>\n\n            <div id=\"palette-section\">\n                <!-- Color buttons will be generated here -->\n            </div>\n        </div>\n    </div>\n    <script>\n        async function run(mode) {\n            const loadingScreen = document.getElementById('loading-screen');\n            const mainMenuScreen = document.getElementById('main-menu-screen');\n            const startButton = document.getElementById('start-button');\n            const menuScreen = document.getElementById('menu-screen');\n            const gameScreen = document.getElementById('game-screen');\n            const levelsGrid = document.getElementById('levels-grid');\n            const backBtn = document.getElementById('back-button');\n            \n            const canvasSection = document.getElementById('canvas-section');\n            const zoomContainer = document.getElementById('zoom-container');\n            const sparkleLayer = document.getElementById('sparkle-layer');\n            const loadingSparkleContainer = document.getElementById('sparkle-animation-container');\n            const canvas = document.getElementById('game-canvas');\n            const ctx = canvas.getContext('2d');\n            \n            const zoomInBtn = document.getElementById('zoom-in');\n            const zoomOutBtn = document.getElementById('zoom-out');\n\n            const paletteSection = document.getElementById('palette-section');\n            const progressLabel = document.getElementById('progress-label');\n            const progressFill = document.getElementById('progress-bar-fill');\n            const completionMessage = document.getElementById('completion-message');\n            const knife = document.getElementById('knife');\n            // Audio context for Web Audio API\n            let audioContext;\n            let audioBuffers = {};\n            let bgMusicSource;\n\n            // Asset cache\n            const assetCache = {};\n\n            // Game state\n            let currentLevelIndex = 0;\n            let currentLevel = null;\n            let selectedColorIndex = 0;\n            let gridState = [];\n            let totalCells = 0;\n            let filledCells = 0;\n            let isComplete = false;\n            let cellSize = 0;\n            let unlockedLevelsCount = 1;\n            let mistakeCell = null;\n            \n            // Zoom and Pan state\n            let zoomScale = 1.0;\n            let panX = 0;\n            let panY = 0;\n            const minZoom = 1.0;\n            const maxZoom = 5.0;\n\n            // Touch tracking\n            let lastPinchDistance = 0;\n            let lastTouchX = 0;\n            let lastTouchY = 0;\n            let isPanning = false;\n            let isScaling = false;\n\n            let isSlicingAllowed = false;\n            let isDraggingSlice = false;\n            let lastSliceX = 0;\n            let lastSliceY = 0;\n            let hasSliced = false;\n\n            // Ensure we have 30 levels\n            function getLevels() {\n                return window.gameConfig.levels || [];\n            }\n\n            const allLevels = getLevels();\n\n            function updateTransform() {\n                zoomContainer.style.transform = `translate(${panX}px, ${panY}px) scale(${zoomScale})`;\n            }\n\n            function setZoom(newScale, centerX, centerY) {\n                const oldScale = zoomScale;\n                zoomScale = Math.max(minZoom, Math.min(maxZoom, newScale));\n                \n                if (centerX !== undefined && centerY !== undefined) {\n                    const scaleChange = zoomScale / oldScale;\n                    panX = centerX - (centerX - panX) * scaleChange;\n                    panY = centerY - (centerY - panY) * scaleChange;\n                }\n\n                if (zoomScale === 1.0) {\n                    panX = 0;\n                    panY = 0;\n                }\n\n                updateTransform();\n            }\n\n            function initAudioContext() {\n                if (!audioContext) {\n                    audioContext = new (window.AudioContext || window.webkitAudioContext)();\n                }\n                return audioContext;\n            }\n\n            async function preloadAssets() {\n                const assetIds = [\n                    'gem_red', 'gem_pink', 'gem_dark_green', \n                    'gem_light_green', 'gem_yellow', 'gem_blue',\n                    'gem_purple', 'gem_orange', 'gem_brown',\n                    'gem_white', 'gem_black',\n                    'gem_click_sound', 'completion_shimmer_sound',\n                    'color_complete_sound', 'slice_sound', 'reveal_sound', 'background_music',\n                    'sparkle_particle'\n                ];\n\n                const promises = assetIds.map(async (id) => {\n                    const assetInfo = lib.getAsset(id);\n                    if (!assetInfo) return;\n\n                    if (assetInfo.type === 'image') {\n                        return new Promise((resolve, reject) => {\n                            const img = new Image();\n                            img.onload = () => {\n                                assetCache[id] = img;\n                                resolve();\n                            };\n                            img.onerror = reject;\n                            img.src = assetInfo.url;\n                        });\n                    } else if (assetInfo.type === 'audio') {\n                        const response = await fetch(assetInfo.url);\n                        const arrayBuffer = await response.arrayBuffer();\n                        const ctx = initAudioContext();\n                        const audioBuffer = await ctx.decodeAudioData(arrayBuffer);\n                        audioBuffers[id] = audioBuffer;\n                    }\n                });\n\n                await Promise.all(promises);\n            }\n\n            function playSound(assetId, volume = 1.0, pitch = 1.0) {\n                if (!audioContext || !audioBuffers[assetId]) return;\n                const source = audioContext.createBufferSource();\n                const gainNode = audioContext.createGain();\n                source.buffer = audioBuffers[assetId];\n                source.playbackRate.value = pitch;\n                gainNode.gain.value = volume;\n                source.connect(gainNode);\n                gainNode.connect(audioContext.destination);\n                source.start(0);\n            }\n\n            function playBackgroundMusic() {\n                if (bgMusicSource) return;\n                if (!audioContext || !audioBuffers['background_music']) return;\n                \n                bgMusicSource = audioContext.createBufferSource();\n                bgMusicSource.buffer = audioBuffers['background_music'];\n                bgMusicSource.loop = true;\n                const gainNode = audioContext.createGain();\n                gainNode.gain.value = 0.3; // Gentle background volume\n                bgMusicSource.connect(gainNode);\n                gainNode.connect(audioContext.destination);\n                bgMusicSource.start(0);\n            }\n\n            function initLevel(index) {\n                currentLevelIndex = index;\n                currentLevel = allLevels[index];\n                const grid = currentLevel.grid;\n                const rows = grid.length;\n                const cols = grid[0].length;\n                \n                gridState = Array(rows).fill(null).map(() => Array(cols).fill(false));\n                \n                totalCells = 0;\n                for (let row = 0; row < rows; row++) {\n                    for (let col = 0; col < cols; col++) {\n                        if (grid[row][col] > 0) totalCells++;\n                    }\n                }\n                \n                filledCells = 0;\n                isComplete = false;\n                completionMessage.classList.remove('show');\n                zoomContainer.classList.remove('bounce-glow');\n                zoomContainer.style.opacity = '1';\n                knife.classList.remove('slicing');\n                selectedColorIndex = 0;\n                \n                // Show screen BEFORE calculating dimensions to ensure clientWidth/Height are correct\n                menuScreen.style.display = 'none';\n                gameScreen.style.display = 'flex';\n                \n                calculateCanvasDimensions();\n                createColorPalette();\n                updateProgress();\n                drawCanvas();\n            }\n\n            function calculateCanvasDimensions() {\n                const grid = currentLevel.grid;\n                const rows = grid.length;\n                const cols = grid[0].length;\n                const availableWidth = canvasSection.clientWidth - 32;\n                const availableHeight = canvasSection.clientHeight - 32;\n                const cellWidth = availableWidth / cols;\n                const cellHeight = availableHeight / rows;\n                cellSize = Math.min(cellWidth, cellHeight);\n                canvas.width = cols * cellSize;\n                canvas.height = rows * cellSize;\n                zoomContainer.style.width = `${canvas.width}px`;\n                zoomContainer.style.height = `${canvas.height}px`;\n                zoomScale = 1.0;\n                panX = 0;\n                panY = 0;\n                updateTransform();\n            }\n\n            function drawCanvas() {\n                const grid = currentLevel.grid;\n                const rows = grid.length;\n                const cols = grid[0].length;\n                ctx.clearRect(0, 0, canvas.width, canvas.height);\n                \n                for (let row = 0; row < rows; row++) {\n                    for (let col = 0; col < cols; col++) {\n                        const cellValue = grid[row][col];\n                        const x = col * cellSize;\n                        const y = row * cellSize;\n                        if (cellValue === 0) continue;\n                        \n                        ctx.fillStyle = 'rgba(255, 255, 255, 0.05)';\n                        ctx.fillRect(x, y, cellSize, cellSize);\n                        ctx.strokeStyle = 'rgba(255, 255, 255, 0.1)';\n                        ctx.lineWidth = 1;\n                        ctx.strokeRect(x, y, cellSize, cellSize);\n                        \n                        if (gridState[row][col]) {\n                            const gemAssetId = getGemAssetId(cellValue);\n                            const gemImage = assetCache[gemAssetId];\n                            if (gemImage) {\n                                const gemSize = cellSize * 0.8;\n                                const gemX = x + (cellSize - gemSize) / 2;\n                                const gemY = y + (cellSize - gemSize) / 2;\n                                ctx.save();\n                                const color = currentLevel.gemColors[cellValue - 1]?.colorHex || '#FFF';\n                                ctx.shadowColor = color;\n                                ctx.shadowBlur = 10 * window.gameConfig.visual.gemShineIntensity;\n                                ctx.drawImage(gemImage, gemX, gemY, gemSize, gemSize);\n                                ctx.restore();\n                            }\n                        } else {\n                            if (mistakeCell && mistakeCell.row === row && mistakeCell.col === col) {\n                                ctx.fillStyle = 'rgba(255, 0, 0, 0.6)';\n                                ctx.fillRect(x, y, cellSize, cellSize);\n                            }\n                            ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';\n                            ctx.font = `${cellSize * 0.4}px sans-serif`;\n                            ctx.textAlign = 'center';\n                            ctx.textBaseline = 'middle';\n                            ctx.fillText(cellValue, x + cellSize / 2, y + cellSize / 2);\n                        }\n                    }\n                }\n            }\n\n            function getGemAssetId(colorIndex) {\n                const assetMap = { \n                    1: 'gem_red', 2: 'gem_pink', 3: 'gem_dark_green', 4: 'gem_light_green', \n                    5: 'gem_yellow', 6: 'gem_blue', 7: 'gem_purple', 8: 'gem_orange',\n                    9: 'gem_brown', 10: 'gem_white', 11: 'gem_black'\n                };\n                return assetMap[colorIndex] || 'gem_red';\n            }\n\n            function isColorFinished(colorValue) {\n                if (!currentLevel) return false;\n                const grid = currentLevel.grid;\n                for (let row = 0; row < grid.length; row++) {\n                    for (let col = 0; col < grid[0].length; col++) {\n                        if (grid[row][col] === colorValue && !gridState[row][col]) {\n                            return false;\n                        }\n                    }\n                }\n                return true;\n            }\n\n            function selectNextAvailableColor() {\n                if (!currentLevel) return;\n                for (let i = 0; i < currentLevel.gemColors.length; i++) {\n                    if (!isColorFinished(i + 1)) {\n                        selectedColorIndex = i;\n                        return true;\n                    }\n                }\n                return false;\n            }\n\n            function createColorPalette() {\n                paletteSection.innerHTML = '';\n                currentLevel.gemColors.forEach((gemColor, index) => {\n                    const colorValue = index + 1;\n                    if (isColorFinished(colorValue)) return;\n\n                    const button = document.createElement('button');\n                    button.className = 'color-button';\n                    if (index === selectedColorIndex) button.classList.add('selected');\n                    button.style.background = `linear-gradient(135deg, ${gemColor.colorHex}ee, ${gemColor.colorHex}88)`;\n                    const gemPreview = document.createElement('img');\n                    gemPreview.className = 'gem-preview';\n                    gemPreview.src = assetCache[getGemAssetId(colorValue)]?.src || '';\n                    const colorNumber = document.createElement('div');\n                    colorNumber.className = 'color-number';\n                    colorNumber.textContent = colorValue;\n                    button.appendChild(gemPreview);\n                    button.appendChild(colorNumber);\n                    button.addEventListener('click', () => {\n                        selectedColorIndex = index;\n                        paletteSection.querySelectorAll('.color-button').forEach((btn) => {\n                            btn.classList.remove('selected');\n                        });\n                        button.classList.add('selected');\n                    });\n                    paletteSection.appendChild(button);\n                });\n            }\n\n            function handleCanvasClick(event) {\n                if (isComplete || isPanning || isScaling) return;\n                const rect = canvas.getBoundingClientRect();\n                const scaleX = canvas.width / rect.width;\n                const scaleY = canvas.height / rect.height;\n                const x = (event.clientX - rect.left) * scaleX;\n                const y = (event.clientY - rect.top) * scaleY;\n                const col = Math.floor(x / cellSize);\n                const row = Math.floor(y / cellSize);\n                const grid = currentLevel.grid;\n                if (row < 0 || row >= grid.length || col < 0 || col >= grid[0].length) return;\n                \n                const cellValue = grid[row][col];\n                if (cellValue === 0 || gridState[row][col]) return;\n                \n                if (cellValue === (selectedColorIndex + 1)) {\n                    gridState[row][col] = true;\n                    filledCells++;\n                    initAudioContext();\n                    const pitch = 0.8 + (cellValue - 1) * 0.1;\n                    playSound('gem_click_sound', window.gameConfig.audio.clickVolume, pitch);\n                    if (navigator.vibrate) navigator.vibrate(50); // Short buzz for correct placement\n                    createSparkle(col * cellSize + cellSize / 2, row * cellSize + cellSize / 2);\n                    updateProgress();\n                    drawCanvas();\n                    \n                    if (filledCells === totalCells) {\n                        completeCanvas();\n                    } else if (isColorFinished(cellValue)) {\n                        playSound('color_complete_sound', 0.8);\n                        if (navigator.vibrate) navigator.vibrate(300); // Satisfying rumble for color completion\n                        // Find the button and trigger pop animation\n                        const buttons = paletteSection.querySelectorAll('.color-button');\n                        const targetButton = Array.from(buttons).find(btn => btn.querySelector('.color-number').textContent === String(cellValue));\n                        if (targetButton) {\n                            targetButton.classList.add('pop-out');\n                            setTimeout(() => {\n                                selectNextAvailableColor();\n                                createColorPalette();\n                            }, 400); // Match animation duration\n                        }\n                    }\n                } else {\n                    mistakeCell = { row, col };\n                    if (navigator.vibrate) navigator.vibrate([50, 50, 50]); // Double buzz for mistake\n                    drawCanvas();\n                    shakeCell();\n                    setTimeout(() => {\n                        mistakeCell = null;\n                        drawCanvas();\n                    }, 400);\n                }\n            }\n\n            function createSparkle(x, y) {\n                const sparkleImg = assetCache['sparkle_particle'];\n                if (!sparkleImg) return;\n                const intensity = currentLevel.gemColors[selectedColorIndex]?.sparkleIntensity || 1;\n                for (let i = 0; i < 3; i++) {\n                    const sparkle = document.createElement('div');\n                    sparkle.className = 'sparkle';\n                    sparkle.style.left = `${x - 8 + Math.random() * 16}px`;\n                    sparkle.style.top = `${y - 8 + Math.random() * 16}px`;\n                    sparkle.style.width = `${16 * intensity}px`;\n                    sparkle.style.height = `${16 * intensity}px`;\n                    const img = document.createElement('img');\n                    img.src = sparkleImg.src;\n                    img.style.width = '100%';\n                    img.style.height = '100%';\n                    sparkle.appendChild(img);\n                    sparkleLayer.appendChild(sparkle);\n                    setTimeout(() => sparkle.remove(), 600);\n                }\n            }\n\n            function shakeCell() {\n                if (isComplete) return;\n                const shakeAmount = 6;\n                let shakeCount = 0;\n                const maxShakes = 8;\n                const interval = setInterval(() => {\n                    if (shakeCount >= maxShakes) {\n                        clearInterval(interval);\n                        updateTransform();\n                        return;\n                    }\n                    const offset = shakeCount % 2 === 0 ? shakeAmount : -shakeAmount;\n                    zoomContainer.style.transform = `translate(${panX + offset}px, ${panY}px) scale(${zoomScale})`;\n                    shakeCount++;\n                }, 40);\n            }\n\n            function updateProgress() {\n                const percentage = Math.floor((filledCells / totalCells) * 100);\n                progressLabel.textContent = `${percentage}%`;\n                progressFill.style.width = `${percentage}%`;\n                progressFill.style.background = `linear-gradient(90deg, ${window.gameConfig.visual.progressBarColor}, #FFD600, #81C784)`;\n            }\n\n            async function completeCanvas() {\n                isComplete = true;\n                if (navigator.vibrate) navigator.vibrate(600); // Extra long rumble for total completion\n                \n                // Unlock next level\n                if (currentLevelIndex + 1 === unlockedLevelsCount && unlockedLevelsCount < 30) {\n                    unlockedLevelsCount++;\n                    await savePlayerProgress({ unlockedLevelsCount });\n                }\n\n                // Shimmer animation\n                playShimmerAnimation();\n                playSound('completion_shimmer_sound', window.gameConfig.audio.completionVolume);\n\n                // Start celebration sequence\n                setTimeout(triggerCelebrationSequence, 1000);\n            }\n\n            function triggerCelebrationSequence() {\n                // 1. Glow and Bounce\n                zoomContainer.classList.add('bounce-glow');\n                \n                // 2. Automatically slice after a satisfying pause\n                setTimeout(() => {\n                    performSlice(0, 0, 100, 100); // Triggers diagonal 45-degree slice\n                }, 1200);\n            }\n\n            function performSlice(x1, y1, x2, y2) {\n                if (hasSliced) return;\n                hasSliced = true;\n                isSlicingAllowed = false;\n                \n                const dx = x2 - x1;\n                const dy = y2 - y1;\n                const angle = Math.atan2(dy, dx) * 180 / Math.PI;\n\n                // Trigger effects\n                knife.style.display = 'block';\n                knife.classList.add('slicing');\n                playSound('slice_sound', 1.0);\n                if (navigator.vibrate) navigator.vibrate(100);\n\n                // Split fruit and reveal surprise\n                setTimeout(() => {\n                    createFruitHalves(angle);\n                    revealSurprise();\n                    zoomContainer.style.opacity = '0';\n                    \n                    // Hide knife after animation\n                    setTimeout(() => {\n                        knife.style.display = 'none';\n                        knife.classList.remove('slicing');\n                    }, 400);\n                }, 150);\n\n                // Transition to menu\n                setTimeout(() => {\n                    zoomContainer.classList.remove('bounce-glow');\n                    zoomContainer.style.opacity = '1';\n                    document.querySelectorAll('.fruit-half, .surprise-reveal').forEach(el => el.remove());\n                    renderMenu();\n                }, 4000);\n            }\n\n            function createFruitHalves(sliceAngle) {\n                const rect = canvas.getBoundingClientRect();\n                \n                for (let i = 0; i < 2; i++) {\n                    const half = document.createElement('div');\n                    half.className = 'fruit-half';\n                    half.style.width = `${rect.width}px`;\n                    half.style.height = `${rect.height}px`;\n                    half.style.left = `${rect.left}px`;\n                    half.style.top = `${rect.top}px`;\n                    \n                    const halfCanvas = document.createElement('canvas');\n                    halfCanvas.width = canvas.width;\n                    halfCanvas.height = canvas.height;\n                    halfCanvas.style.width = '100%';\n                    halfCanvas.style.height = '100%';\n                    const hctx = halfCanvas.getContext('2d');\n                    \n                    const grid = currentLevel.grid;\n                    const rows = grid.length;\n                    const cols = grid[0].length;\n                    for (let row = 0; row < rows; row++) {\n                        for (let col = 0; col < cols; col++) {\n                            if (gridState[row][col]) {\n                                const gemAssetId = getGemAssetId(grid[row][col]);\n                                const gemImage = assetCache[gemAssetId];\n                                if (gemImage) {\n                                    const gemSize = cellSize * 0.8;\n                                    const gemX = col * cellSize + (cellSize - gemSize) / 2;\n                                    const gemY = row * cellSize + (cellSize - gemSize) / 2;\n                                    hctx.save();\n                                    const color = currentLevel.gemColors[grid[row][col] - 1]?.colorHex || '#FFF';\n                                    hctx.shadowColor = color;\n                                    hctx.shadowBlur = 10 * window.gameConfig.visual.gemShineIntensity;\n                                    hctx.drawImage(gemImage, gemX, gemY, gemSize, gemSize);\n                                    hctx.restore();\n                                }\n                            }\n                        }\n                    }\n\n                    half.appendChild(halfCanvas);\n                    \n                    // Dynamic clip path based on slice angle\n                    // We simplify: if angle is roughly horizontal, clip top/bottom. \n                    // If vertical, clip left/right.\n                    // For better visuals, we can rotate the clip.\n                    const normAngle = (sliceAngle + 360) % 360;\n                    \n                    // Calculate translation vector for split animation\n                    const moveAngle = (sliceAngle + (i === 0 ? -90 : 90)) * Math.PI / 180;\n                    const moveDist = 200;\n                    const tx = Math.cos(moveAngle) * moveDist;\n                    const ty = Math.sin(moveAngle) * moveDist;\n\n                    // Apply a clip path that follows the slice angle\n                    // This is a rough approximation using polygon vertices far outside\n                    // Angle in CSS polygon is not direct, so we use a large box\n                    const rad = sliceAngle * Math.PI / 180;\n                    const c = Math.cos(rad);\n                    const s = Math.sin(rad);\n                    \n                    // Define a large rectangle half-plane\n                    // side 1: i=0, side 2: i=1\n                    const side = i === 0 ? 1 : -1;\n                    \n                    // Simple approach for the prompt's request:\n                    // Use a rotated container to clip\n                    half.style.clipPath = i === 0 ? \n                        `polygon(-100% -100%, 200% -100%, 200% 50%, -100% 50%)` : \n                        `polygon(-100% 50%, 200% 50%, 200% 200%, -100% 200%)`;\n                    \n                    // Rotate the half to align the clip with the slice angle\n                    half.style.transformOrigin = 'center';\n                    half.style.transform = `rotate(${sliceAngle}deg)`;\n\n                    // Inner canvas needs to rotate back to stay upright\n                    halfCanvas.style.transform = `rotate(${-sliceAngle}deg)`;\n\n                    // Animation\n                    setTimeout(() => {\n                        half.style.transform = `rotate(${sliceAngle}deg) translate(0, ${side * moveDist}px) rotate(${side * 20}deg)`;\n                        half.style.opacity = '0';\n                    }, 50);\n                    \n                    document.body.appendChild(half);\n                }\n            }\n\n            function revealSurprise() {\n                const surpriseMap = {\n                    'strawberry': { emoji: '\ud83c\udf70', class: 'chick-bounce' }, // Strawberry shortcake\n                    'lemon': { emoji: '\ud83e\udd64', class: 'chick-bounce' }, // Lemonade stand\n                    'watermelon': { emoji: '\ud83c\udfd6\ufe0f', class: 'fire-pulse' }, // Beach scene\n                    'grape': { emoji: '\ud83c\udf77', class: 'disco-spin' }, // Wine glass\n                    'orange': { emoji: '\ud83c\udf05', class: 'fire-pulse' }, // Sunrise\n                    'cherry': { emoji: '\ud83e\udd67', class: 'chick-bounce' }, // Cherry pie\n                    'pineapple': { emoji: '\ud83c\udfdd\ufe0f', class: 'fire-pulse' }, // Tropical island\n                    'mango': { emoji: '\ud83e\udd64', class: 'chick-bounce' }, // Smoothie\n                    'kiwi': { emoji: '\ud83d\udc26', class: 'chick-bounce' }, // Tiny bird\n                    'apple': { emoji: '\ud83d\udc1b\ud83c\udfa9', class: 'eyes-wiggle' }, // Worm with top hat\n                    'banana': { emoji: '\ud83d\udc12', class: 'chick-bounce' }, // Monkey\n                    'blueberry': { emoji: '\ud83e\uddc1', class: 'chick-bounce' }, // Muffin\n                    'pear': { emoji: '\ud83d\udc8e', class: 'disco-spin' }, // Pear-shaped diamond\n                    'raspberry': { emoji: '\ud83d\udc51', class: 'fire-pulse' }, // Crown\n                    'coconut': { emoji: '\ud83d\uded6', class: 'fire-pulse' }, // Beach hut\n                    'dragonfruit': { emoji: '\ud83d\udc32', class: 'fire-pulse' }, // Dragon\n                    'lime': { emoji: '\ud83c\udf79', class: 'chick-bounce' }, // Margarita\n                    'pomegranate': { emoji: '\ud83d\udc8e', class: 'disco-spin' }, // Ruby gems\n                    'peach': { emoji: '\ud83c\udf51', class: 'chick-bounce' },\n                    'fig': { emoji: '\ud83c\udffa', class: 'chick-bounce' },\n                    'plum': { emoji: '\ud83c\udf6e', class: 'chick-bounce' },\n                    'papaya': { emoji: '\ud83e\udd9c', class: 'chick-bounce' },\n                    'passion_fruit': { emoji: '\ud83c\udf3a', class: 'rainbow-fade' },\n                    'starfruit': { emoji: '\u2b50', class: 'disco-spin' },\n                    'avocado': { emoji: '\ud83e\udd51', class: 'chick-bounce' },\n                    'melon': { emoji: '\ud83c\udf48', class: 'chick-bounce' },\n                    'tangerine': { emoji: '\ud83c\udf4a', class: 'chick-bounce' },\n                    'guava': { emoji: '\ud83e\udd9c', class: 'chick-bounce' },\n                    'lychee': { emoji: '\ud83c\udfee', class: 'chick-bounce' },\n                    'durian': { emoji: '\ud83d\udc51', class: 'fire-pulse' }\n                };\n                \n                const levelId = currentLevel.id;\n                const surprise = surpriseMap[levelId] || { emoji: '\ud83c\udf81', class: 'confetti-burst' };\n                \n                const el = document.createElement('div');\n                el.className = `surprise-reveal ${surprise.class}`;\n                el.textContent = surprise.emoji;\n                \n                playSound('reveal_sound', 0.8);\n\n                // Position it where the fruit was\n                const rect = canvas.getBoundingClientRect();\n                el.style.left = `${rect.left + rect.width / 2}px`;\n                el.style.top = `${rect.top + rect.height / 2}px`;\n                \n                document.body.appendChild(el);\n                \n                // Sparkle burst around the surprise\n                for(let i=0; i<20; i++) {\n                    setTimeout(() => {\n                        const x = rect.left + rect.width/2 + (Math.random() - 0.5) * 200;\n                        const y = rect.top + rect.height/2 + (Math.random() - 0.5) * 200;\n                        createSparkle(x, y);\n                    }, i * 50);\n                }\n            }\n\n            function playShimmerAnimation() {\n                const grid = currentLevel.grid;\n                const rows = grid.length;\n                const cols = grid[0].length;\n                let animationRow = 0;\n                function animateRow() {\n                    if (animationRow >= rows) return;\n                    ctx.save();\n                    for (let col = 0; col < cols; col++) {\n                        if (grid[animationRow][col] > 0 && gridState[animationRow][col]) {\n                            const x = col * cellSize;\n                            const y = animationRow * cellSize;\n                            const gradient = ctx.createLinearGradient(x, y, x + cellSize, y + cellSize);\n                            gradient.addColorStop(0, 'rgba(255, 0, 0, 0.4)');\n                            gradient.addColorStop(0.33, 'rgba(255, 255, 0, 0.4)');\n                            gradient.addColorStop(0.66, 'rgba(0, 255, 0, 0.4)');\n                            gradient.addColorStop(1, 'rgba(0, 0, 255, 0.4)');\n                            ctx.fillStyle = gradient;\n                            ctx.fillRect(x, y, cellSize, cellSize);\n                            ctx.shadowColor = '#FFFFFF';\n                            ctx.shadowBlur = 20;\n                            ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';\n                            ctx.lineWidth = 2;\n                            ctx.strokeRect(x, y, cellSize, cellSize);\n                        }\n                    }\n                    ctx.restore();\n                    animationRow++;\n                    setTimeout(animateRow, 50);\n                }\n                animateRow();\n            }\n\n            async function renderMenu() {\n                levelsGrid.innerHTML = '';\n                const progress = await loadPlayerProgress();\n                unlockedLevelsCount = progress?.unlockedLevelsCount || 1;\n\n                allLevels.forEach((level, index) => {\n                    const card = document.createElement('div');\n                    card.className = 'level-card';\n                    const isLocked = index >= unlockedLevelsCount;\n                    if (isLocked) card.classList.add('locked');\n                    \n                    // Thumbnail (mini canvas)\n                    const thumb = document.createElement('canvas');\n                    thumb.className = 'level-thumbnail';\n                    thumb.width = 40;\n                    thumb.height = 40;\n                    const tctx = thumb.getContext('2d');\n                    const g = level.grid;\n                    const r = g.length;\n                    const c = g[0].length;\n                    const s = Math.min(40/c, 40/r);\n                    for(let i=0; i<r; i++) {\n                        for(let j=0; j<c; j++) {\n                            if(g[i][j] > 0) {\n                                tctx.fillStyle = level.gemColors[g[i][j]-1]?.colorHex || '#FFF';\n                                tctx.fillRect(j*s, i*s, s, s);\n                            }\n                        }\n                    }\n                    \n                    card.appendChild(thumb);\n                    const name = document.createElement('div');\n                    name.className = 'level-name';\n                    name.textContent = level.name;\n                    card.appendChild(name);\n                    \n                    if (isLocked) {\n                        const lock = document.createElement('div');\n                        lock.className = 'lock-icon';\n                        lock.textContent = '\ud83d\udd12';\n                        card.appendChild(lock);\n                    } else {\n                        card.addEventListener('click', () => initLevel(index));\n                    }\n                    \n                    levelsGrid.appendChild(card);\n                });\n                \n                menuScreen.style.display = 'flex';\n                gameScreen.style.display = 'none';\n                mainMenuScreen.style.display = 'none';\n            }\n\n            // Initialization\n            // Create loading sparkles\n            for(let i=0; i<10; i++) {\n                const s = document.createElement('div');\n                s.className = 'loading-sparkle';\n                s.style.left = `${Math.random() * 80 + 10}%`;\n                s.style.top = `${Math.random() * 40 + 30}px`;\n                s.style.animationDelay = `${i * 0.2}s`;\n                loadingSparkleContainer.appendChild(s);\n            }\n\n            function createMenuBackground() {\n                const bg = document.getElementById('menu-background');\n                if (!bg) return;\n                \n                const fruitEmojis = ['\ud83c\udf53', '\ud83c\udf4b', '\ud83c\udf49', '\ud83c\udf47'];\n                const gemIds = ['gem_red', 'gem_blue', 'gem_purple', 'gem_orange', 'gem_yellow', 'gem_white'];\n\n                // Silhouettes\n                for (let i = 0; i < 10; i++) {\n                    const el = document.createElement('div');\n                    el.className = 'floating-silhouette';\n                    el.textContent = fruitEmojis[i % fruitEmojis.length];\n                    el.style.left = `${Math.random() * 120 - 10}%`;\n                    el.style.top = `${Math.random() * 120 - 10}%`;\n                    el.style.animationDelay = `${-Math.random() * 40}s`;\n                    el.style.fontSize = `${Math.random() * 80 + 120}px`;\n                    bg.appendChild(el);\n                }\n\n                // Gems\n                for (let i = 0; i < 18; i++) {\n                    addFloatingGem(bg, gemIds[i % gemIds.length]);\n                }\n            }\n\n            function addFloatingGem(container, gemId) {\n                const asset = lib.getAsset(gemId);\n                if (!asset) return;\n\n                const img = document.createElement('img');\n                img.className = 'floating-gem-menu';\n                img.src = asset.url;\n                img.style.left = `${Math.random() * 90 + 5}%`;\n                img.style.top = `${Math.random() * 90 + 5}%`;\n                img.style.animationDelay = `${-Math.random() * 25}s`;\n                const size = Math.random() * 25 + 35;\n                img.style.width = `${size}px`;\n\n                img.addEventListener('click', (e) => {\n                    e.stopPropagation();\n                    // Explosion effect\n                    const rect = img.getBoundingClientRect();\n                    const centerX = rect.left + rect.width / 2;\n                    const centerY = rect.top + rect.height / 2;\n                    \n                    // Burst of sparkles\n                    const sparkleImg = assetCache['sparkle_particle'];\n                    if (sparkleImg) {\n                        for (let i = 0; i < 12; i++) {\n                            const sparkle = document.createElement('div');\n                            sparkle.className = 'sparkle';\n                            // Random spread from center\n                            const angle = Math.random() * Math.PI * 2;\n                            const dist = Math.random() * 150;\n                            const vx = Math.cos(angle) * dist;\n                            const vy = Math.sin(angle) * dist;\n                            \n                            sparkle.style.left = `${centerX}px`;\n                            sparkle.style.top = `${centerY}px`;\n                            sparkle.style.width = `${Math.random() * 20 + 20}px`;\n                            sparkle.style.height = sparkle.style.width;\n                            sparkle.style.setProperty('--tx', `${vx}px`);\n                            sparkle.style.setProperty('--ty', `${vy}px`);\n                            \n                            // Custom animation for explosion movement\n                            sparkle.style.animation = 'sparkle-explode 0.6s ease-out forwards';\n                            \n                            const sImg = document.createElement('img');\n                            sImg.src = sparkleImg.src;\n                            sImg.style.width = '100%';\n                            sImg.style.height = '100%';\n                            sparkle.appendChild(sImg);\n                            document.body.appendChild(sparkle);\n                            setTimeout(() => sparkle.remove(), 600);\n                        }\n                    }\n\n                    const randomPitch = 0.9 + Math.random() * 0.4;\n                    playSound('gem_click_sound', 1.0, randomPitch);\n                    if (navigator.vibrate) navigator.vibrate(50);\n\n                    img.style.pointerEvents = 'none';\n                    img.style.opacity = '0';\n                    img.style.transform = 'scale(2)';\n                    \n                    setTimeout(() => {\n                        img.remove();\n                        const gemIds = ['gem_red', 'gem_blue', 'gem_purple', 'gem_orange', 'gem_yellow', 'gem_white'];\n                        addFloatingGem(container, gemIds[Math.floor(Math.random() * gemIds.length)]);\n                    }, 100);\n                });\n\n                container.appendChild(img);\n            }\n\n            // Wait a moment for the loading screen to be seen\n            const forceContinue = setTimeout(() => {\n                if (loadingScreen.style.display !== 'none') {\n                    lib.log('Loading timeout reached, forcing transition.');\n                    loadingScreen.style.display = 'none';\n                    mainMenuScreen.style.display = 'flex';\n                }\n            }, 2000);\n\n            await preloadAssets().catch(err => lib.log('Preload error: ' + err.message));\n            createMenuBackground();\n            \n            clearTimeout(forceContinue);\n            loadingScreen.style.display = 'none';\n            mainMenuScreen.style.display = 'flex';\n\n            startButton.addEventListener('click', () => {\n                initAudioContext();\n                playBackgroundMusic();\n                renderMenu();\n            });\n            \n            backBtn.addEventListener('click', renderMenu);\n\n            canvas.addEventListener('click', handleCanvasClick);\n            canvasSection.addEventListener('wheel', (e) => {\n                e.preventDefault();\n                const delta = -e.deltaY;\n                const factor = 1.1;\n                const newScale = delta > 0 ? zoomScale * factor : zoomScale / factor;\n                const rect = canvasSection.getBoundingClientRect();\n                const mouseX = e.clientX - rect.left - rect.width / 2;\n                const mouseY = e.clientY - rect.top - rect.height / 2;\n                setZoom(newScale, mouseX, mouseY);\n            }, { passive: false });\n\n            zoomInBtn.addEventListener('click', () => setZoom(zoomScale * 1.5, panX, panY));\n            zoomOutBtn.addEventListener('click', () => setZoom(zoomScale / 1.5, panX, panY));\n\n            canvasSection.addEventListener('touchstart', (e) => {\n                if (e.touches.length === 2) {\n                    isScaling = true;\n                    isPanning = false;\n                    lastPinchDistance = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY);\n                } else if (e.touches.length === 1) {\n                    isScaling = false;\n                    isPanning = false;\n                    lastTouchX = e.touches[0].clientX;\n                    lastTouchY = e.touches[0].clientY;\n                }\n            }, { passive: false });\n\n            canvasSection.addEventListener('touchmove', (e) => {\n                e.preventDefault();\n                if (e.touches.length === 2) {\n                    isScaling = true;\n                    const distance = Math.hypot(e.touches[0].clientX - e.touches[1].clientX, e.touches[0].clientY - e.touches[1].clientY);\n                    const delta = distance / lastPinchDistance;\n                    lastPinchDistance = distance;\n                    const rect = canvasSection.getBoundingClientRect();\n                    const centerX = (e.touches[0].clientX + e.touches[1].clientX) / 2 - rect.left - rect.width / 2;\n                    const centerY = (e.touches[0].clientY + e.touches[1].clientY) / 2 - rect.top - rect.height / 2;\n                    setZoom(zoomScale * delta, centerX, centerY);\n                } else if (e.touches.length === 1) {\n                    const dx = e.touches[0].clientX - lastTouchX;\n                    const dy = e.touches[0].clientY - lastTouchY;\n                    if (Math.abs(dx) > 5 || Math.abs(dy) > 5) isPanning = true;\n                    if (isPanning) {\n                        lastTouchX = e.touches[0].clientX; lastTouchY = e.touches[0].clientY;\n                        panX += dx; panY += dy; updateTransform();\n                    }\n                }\n            }, { passive: false });\n\n            canvasSection.addEventListener('touchend', (e) => {\n                if (e.touches.length === 0) {\n                    if (isPanning || isScaling) setTimeout(() => { isPanning = false; isScaling = false; }, 100);\n                } else {\n                    isScaling = false;\n                    lastTouchX = e.touches[0].clientX; lastTouchY = e.touches[0].clientY;\n                }\n            });\n\n            let isMouseDown = false;\n            canvasSection.addEventListener('mousedown', (e) => {\n                if (e.button === 0) { isMouseDown = true; lastTouchX = e.clientX; lastTouchY = e.clientY; isPanning = false; }\n            });\n\n            window.addEventListener('mousemove', (e) => {\n                if (isMouseDown) {\n                    const dx = e.clientX - lastTouchX;\n                    const dy = e.clientY - lastTouchY;\n                    if (Math.abs(dx) > 2 || Math.abs(dy) > 2) isPanning = true;\n                    if (isPanning) {\n                        lastTouchX = e.clientX; lastTouchY = e.clientY;\n                        panX += dx; panY += dy; updateTransform();\n                    }\n                }\n            });\n\n            window.addEventListener('mouseup', () => {\n                isMouseDown = false;\n                if (isPanning) setTimeout(() => isPanning = false, 50);\n            });\n\n            document.addEventListener('keydown', (e) => {\n                if (gameScreen.style.display === 'flex' && e.key >= '1' && e.key <= '9') {\n                    const idx = parseInt(e.key) - 1;\n                    if (idx < currentLevel.gemColors.length && !isColorFinished(idx + 1)) {\n                        selectedColorIndex = idx;\n                        createColorPalette();\n                    }\n                }\n            });\n\n            window.addEventListener('resize', () => {\n                if (gameScreen.style.display === 'flex') { calculateCanvasDimensions(); drawCanvas(); }\n            });\n\n            lib.showGameParameters({\n                name: 'Game Settings',\n                params: {\n                    'Background Color': { key: 'canvas.backgroundColor', type: 'color', onChange: (v) => document.getElementById('game-world').style.background = v },\n                    'Click Volume': { key: 'audio.clickVolume', type: 'slider', min: 0, max: 1, step: 0.1 },\n                    'Completion Volume': { key: 'audio.completionVolume', type: 'slider', min: 0, max: 1, step: 0.1 },\n                    'Gem Shine': { key: 'visual.gemShineIntensity', type: 'slider', min: 0.5, max: 1.5, step: 0.1, onChange: () => { if(currentLevel) drawCanvas(); } }\n                }\n            });\n            document.getElementById('game-world').style.background = window.gameConfig.canvas.backgroundColor;\n        }\n\n        // Helper persistence functions for save/load\n        async function loadPlayerProgress() {\n            try {\n                const response = await lib.getUserGameState();\n                // API returns {userId, gameId, state}, where state can be null if no saved data\n                return response.state || { unlockedLevelsCount: 1 };\n            } catch(e) {\n                // If error (e.g., guest user), return default\n                lib.log(`Failed to load progress: ${e.message}`);\n                return { unlockedLevelsCount: 1 };\n            }\n        }\n        async function savePlayerProgress(state) {\n            try {\n                await lib.saveUserGameState(state);\n                lib.log('Progress saved successfully');\n            } catch(e) {\n                lib.log(`Failed to save progress: ${e.message}`);\n            }\n        }\n    </script>\n</body>\n</html>", "game_config": "{\n  \"canvas\": {\n    \"fruitType\": \"strawberry\",\n    \"backgroundColor\": \"#0A1128\"\n  },\n  \"gemColors\": [\n    {\n      \"colorHex\": \"#FF1744\",\n      \"colorName\": \"Ruby Red\",\n      \"sparkleIntensity\": 1.0\n    },\n    {\n      \"colorHex\": \"#FF80AB\",\n      \"colorName\": \"Soft Pink\",\n      \"sparkleIntensity\": 1.0\n    },\n    {\n      \"colorHex\": \"#2E7D32\",\n      \"colorName\": \"Forest Green\",\n      \"sparkleIntensity\": 1.0\n    },\n    {\n      \"colorHex\": \"#81C784\",\n      \"colorName\": \"Spring Green\",\n      \"sparkleIntensity\": 1.0\n    },\n    {\n      \"colorHex\": \"#FFD600\",\n      \"colorName\": \"Golden Yellow\",\n      \"sparkleIntensity\": 1.0\n    }\n  ],\n  \"audio\": {\n    \"clickVolume\": 0.7,\n    \"completionVolume\": 0.8\n  },\n  \"visual\": {\n    \"gemShineIntensity\": 1.0,\n    \"progressBarColor\": \"#FF80AB\"\n  },\n  \"strawberryGrid\": [\n    [\n      0,\n      0,\n      0,\n      0,\n      0,\n      0,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      0,\n      0,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      0,\n      3,\n      3,\n      4,\n      4,\n      4,\n      4,\n      4,\n      4,\n      3,\n      3,\n      0,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      3,\n      3,\n      4,\n      4,\n      3,\n      3,\n      3,\n      3,\n      4,\n      4,\n      3,\n      3,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      3,\n      3,\n      4,\n      4,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      4,\n      4,\n      3,\n      3,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      3,\n      4,\n      4,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      3,\n      4,\n      4,\n      3,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1,\n      5,\n      1,\n      1,\n      5,\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0\n    ],\n    [\n      0,\n      1,\n      1,\n      2,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      2,\n      1,\n      1,\n      0\n    ],\n    [\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0\n    ],\n    [\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0\n    ],\n    [\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1\n    ],\n    [\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1\n    ],\n    [\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1\n    ],\n    [\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1\n    ],\n    [\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1\n    ],\n    [\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1\n    ],\n    [\n      0,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      0\n    ],\n    [\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0\n    ],\n    [\n      0,\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1,\n      0\n    ],\n    [\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      5,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      1,\n      1,\n      2,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      2,\n      1,\n      1,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0,\n      0,\n      0,\n      0\n    ],\n    [\n      0,\n      0,\n      0,\n      0,\n      0,\n      0,\n      0,\n      1,\n      1,\n      1,\n      1,\n      1,\n      1,\n      0,\n      0,\n      0,\n      0,\n      0,\n      0,\n      0\n    ]\n  ],\n  \"levels\": [\n    {\n      \"id\": \"strawberry\",\n      \"name\": \"Strawberry\",\n      \"gemColors\": [\n        {\n          \"colorHex\": \"#FF1744\",\n          \"colorName\": \"Ruby Red\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#FF80AB\",\n          \"colorName\": \"Soft Pink\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#2E7D32\",\n          \"colorName\": \"Forest Green\"\n        },\n        {\n          \"colorName\": \"Spring Green\",\n          \"colorHex\": \"#81C784\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Golden Yellow\",\n          \"colorHex\": \"#FFD600\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          3,\n          3,\n          3,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          3,\n          4,\n          4,\n          4,\n          3,\n          0,\n          0\n        ],\n        [\n          0,\n          3,\n          4,\n          3,\n          3,\n          3,\n          4,\n          3,\n          0\n        ],\n        [\n          3,\n          4,\n          3,\n          3,\n          3,\n          3,\n          3,\n          4,\n          3\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          5,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          5,\n          1,\n          5,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          0,\n          1,\n          1,\n          1,\n          0,\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"name\": \"Lemon\",\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          3,\n          3,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          0,\n          3,\n          3,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          4,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          4,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Lemon Yellow\",\n          \"colorHex\": \"#FFD600\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#FFF9C4\",\n          \"colorName\": \"Pale Yellow\"\n        },\n        {\n          \"colorHex\": \"#81C784\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Diamond White\",\n          \"colorHex\": \"#FFFFFF\",\n          \"sparkleIntensity\": 1.2\n        }\n      ],\n      \"id\": \"lemon\"\n    },\n    {\n      \"name\": \"Watermelon\",\n      \"grid\": [\n        [\n          0,\n          2,\n          2,\n          2,\n          2,\n          2,\n          0\n        ],\n        [\n          2,\n          3,\n          3,\n          3,\n          3,\n          3,\n          2\n        ],\n        [\n          3,\n          1,\n          1,\n          1,\n          1,\n          1,\n          3\n        ],\n        [\n          3,\n          1,\n          11,\n          1,\n          11,\n          1,\n          3\n        ],\n        [\n          3,\n          1,\n          1,\n          1,\n          1,\n          1,\n          3\n        ],\n        [\n          0,\n          3,\n          3,\n          3,\n          3,\n          3,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"colorHex\": \"#FF1744\",\n          \"colorName\": \"Watermelon Red\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Rind Green\",\n          \"colorHex\": \"#2E7D32\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#81C784\",\n          \"colorName\": \"Outer Green\"\n        },\n        {\n          \"sparkleIntensity\": 1.5,\n          \"colorHex\": \"#000000\",\n          \"colorName\": \"Seed Black\"\n        }\n      ],\n      \"id\": \"watermelon\"\n    },\n    {\n      \"name\": \"Grape\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Grape Purple\",\n          \"colorHex\": \"#7B1FA2\"\n        },\n        {\n          \"colorName\": \"Stem Green\",\n          \"colorHex\": \"#2E7D32\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          2,\n          2,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          0,\n          2,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          0,\n          1,\n          0,\n          0\n        ]\n      ],\n      \"id\": \"grape\"\n    },\n    {\n      \"name\": \"Orange\",\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          2,\n          2,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"colorName\": \"Orange Orange\",\n          \"colorHex\": \"#FF6D00\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Leaf Green\",\n          \"colorHex\": \"#2E7D32\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"id\": \"orange\"\n    },\n    {\n      \"id\": \"peach\",\n      \"name\": \"Peach\",\n      \"gemColors\": [\n        {\n          \"colorName\": \"Peach Pink\",\n          \"colorHex\": \"#F48FB1\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Peach Orange\",\n          \"colorHex\": \"#FFAB91\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#81C784\",\n          \"colorName\": \"Leaf Green\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          3,\n          3,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          2,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          2,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          2,\n          2,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"name\": \"Cherry\",\n      \"grid\": [\n        [\n          0,\n          0,\n          2,\n          2,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          2,\n          0,\n          0,\n          2,\n          0,\n          0\n        ],\n        [\n          2,\n          0,\n          0,\n          0,\n          0,\n          2,\n          0\n        ],\n        [\n          1,\n          1,\n          0,\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          0,\n          0,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Cherry Red\",\n          \"colorHex\": \"#B71C1C\"\n        },\n        {\n          \"colorName\": \"Stem Green\",\n          \"colorHex\": \"#2E7D32\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"id\": \"cherry\"\n    },\n    {\n      \"name\": \"Pineapple\",\n      \"gemColors\": [\n        {\n          \"colorName\": \"Gold Yellow\",\n          \"colorHex\": \"#FFD600\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Pine Brown\",\n          \"colorHex\": \"#795548\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Leaf Green\",\n          \"colorHex\": \"#2E7D32\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          3,\n          0,\n          3,\n          0,\n          3,\n          0\n        ],\n        [\n          0,\n          3,\n          3,\n          3,\n          3,\n          3,\n          0\n        ],\n        [\n          0,\n          3,\n          3,\n          3,\n          3,\n          3,\n          0\n        ],\n        [\n          1,\n          2,\n          1,\n          2,\n          1,\n          2,\n          1\n        ],\n        [\n          2,\n          1,\n          2,\n          1,\n          2,\n          1,\n          2\n        ],\n        [\n          1,\n          2,\n          1,\n          2,\n          1,\n          2,\n          1\n        ],\n        [\n          2,\n          1,\n          2,\n          1,\n          2,\n          1,\n          2\n        ],\n        [\n          0,\n          1,\n          2,\n          1,\n          2,\n          1,\n          0\n        ]\n      ],\n      \"id\": \"pineapple\"\n    },\n    {\n      \"id\": \"mango\",\n      \"name\": \"Mango\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Mango Orange\",\n          \"colorHex\": \"#FF6D00\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#FFD600\",\n          \"colorName\": \"Mango Yellow\"\n        },\n        {\n          \"colorHex\": \"#2E7D32\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          3,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          2,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          2,\n          2,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"kiwi\",\n      \"name\": \"Kiwi\",\n      \"gemColors\": [\n        {\n          \"colorName\": \"Kiwi Brown\",\n          \"colorHex\": \"#795548\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Kiwi Green\",\n          \"colorHex\": \"#81C784\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Center White\",\n          \"colorHex\": \"#FFFFFF\"\n        },\n        {\n          \"sparkleIntensity\": 1.5,\n          \"colorName\": \"Seed Black\",\n          \"colorHex\": \"#000000\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          4,\n          4,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          4,\n          3,\n          4,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          4,\n          4,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"apple\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Apple Red\",\n          \"colorHex\": \"#D50000\"\n        },\n        {\n          \"colorName\": \"Highlight White\",\n          \"colorHex\": \"#FFFFFF\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Leaf Green\",\n          \"colorHex\": \"#2E7D32\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Stem Brown\",\n          \"colorHex\": \"#795548\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          4,\n          3,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          0,\n          0,\n          4,\n          0,\n          0,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          1,\n          1,\n          0,\n          0\n        ]\n      ],\n      \"name\": \"Apple\"\n    },\n    {\n      \"id\": \"banana\",\n      \"name\": \"Banana\",\n      \"grid\": [\n        [\n          0,\n          0,\n          0,\n          0,\n          0,\n          2\n        ],\n        [\n          0,\n          0,\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          0,\n          0,\n          0\n        ],\n        [\n          1,\n          1,\n          0,\n          0,\n          0,\n          0\n        ],\n        [\n          2,\n          0,\n          0,\n          0,\n          0,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"colorHex\": \"#FFEA00\",\n          \"colorName\": \"Banana Yellow\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#795548\",\n          \"colorName\": \"Tip Brown\",\n          \"sparkleIntensity\": 1\n        }\n      ]\n    },\n    {\n      \"id\": \"blueberry\",\n      \"name\": \"Blueberry\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1.2,\n          \"colorName\": \"Berry Blue\",\n          \"colorHex\": \"#2962FF\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Deep Purple\",\n          \"colorHex\": \"#4A148C\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"name\": \"Pear\",\n      \"gemColors\": [\n        {\n          \"colorHex\": \"#AED581\",\n          \"colorName\": \"Pear Green\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Highlight White\",\n          \"colorHex\": \"#FFFFFF\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#795548\",\n          \"colorName\": \"Stem Brown\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          3,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"id\": \"pear\"\n    },\n    {\n      \"id\": \"raspberry\",\n      \"grid\": [\n        [\n          0,\n          3,\n          3,\n          0\n        ],\n        [\n          1,\n          2,\n          1,\n          2\n        ],\n        [\n          2,\n          1,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          1,\n          2\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"colorName\": \"Raspberry Pink\",\n          \"colorHex\": \"#C2185B\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#D50000\",\n          \"colorName\": \"Raspberry Red\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#2E7D32\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"name\": \"Raspberry\"\n    },\n    {\n      \"gemColors\": [\n        {\n          \"colorHex\": \"#5D4037\",\n          \"colorName\": \"Shell Brown\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#FFFFFF\",\n          \"colorName\": \"Meat White\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"name\": \"Coconut\",\n      \"id\": \"coconut\"\n    },\n    {\n      \"id\": \"dragonfruit\",\n      \"name\": \"Dragonfruit\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#F06292\",\n          \"colorName\": \"Dragon Pink\"\n        },\n        {\n          \"colorHex\": \"#FFFFFF\",\n          \"colorName\": \"Dragon White\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1.5,\n          \"colorHex\": \"#000000\",\n          \"colorName\": \"Dragon Seed\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Dragon Green\",\n          \"colorHex\": \"#81C784\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          4,\n          0,\n          4,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"fig\",\n      \"name\": \"Fig\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Fig Purple\",\n          \"colorHex\": \"#4A148C\"\n        },\n        {\n          \"colorHex\": \"#E91E63\",\n          \"colorName\": \"Fig Pink\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#2E7D32\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          3,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"lime\",\n      \"name\": \"Lime\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1.2,\n          \"colorHex\": \"#64DD17\",\n          \"colorName\": \"Lime Green\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#DCEDC8\",\n          \"colorName\": \"Pale Green\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          1,\n          2,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"grid\": [\n        [\n          0,\n          1,\n          0,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Pome Red\",\n          \"colorHex\": \"#B71C1C\"\n        },\n        {\n          \"colorName\": \"Pome Pink\",\n          \"colorHex\": \"#F06292\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Highlight White\",\n          \"colorHex\": \"#FFFFFF\"\n        }\n      ],\n      \"name\": \"Pomegranate\",\n      \"id\": \"pomegranate\"\n    },\n    {\n      \"id\": \"plum\",\n      \"name\": \"Plum\",\n      \"grid\": [\n        [\n          0,\n          0,\n          3,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"colorName\": \"Plum Purple\",\n          \"colorHex\": \"#311B92\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Plum Red\",\n          \"colorHex\": \"#880E4F\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Leaf Green\",\n          \"colorHex\": \"#2E7D32\"\n        }\n      ]\n    },\n    {\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Papaya Orange\",\n          \"colorHex\": \"#FF9100\"\n        },\n        {\n          \"colorName\": \"Papaya Seed\",\n          \"colorHex\": \"#000000\",\n          \"sparkleIntensity\": 1.5\n        }\n      ],\n      \"name\": \"Papaya\",\n      \"id\": \"papaya\"\n    },\n    {\n      \"id\": \"passion_fruit\",\n      \"name\": \"Passion Fruit\",\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          2,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Passion Purple\",\n          \"colorHex\": \"#4A148C\"\n        },\n        {\n          \"colorName\": \"Passion Yellow\",\n          \"colorHex\": \"#FFD600\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#000000\",\n          \"colorName\": \"Passion Seed\",\n          \"sparkleIntensity\": 1.5\n        }\n      ]\n    },\n    {\n      \"name\": \"Starfruit\",\n      \"gemColors\": [\n        {\n          \"colorName\": \"Star Yellow\",\n          \"colorHex\": \"#FFEA00\",\n          \"sparkleIntensity\": 1.3\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Star Green\",\n          \"colorHex\": \"#81C784\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          1,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          0,\n          0,\n          1,\n          0,\n          0\n        ]\n      ],\n      \"id\": \"starfruit\"\n    },\n    {\n      \"id\": \"avocado\",\n      \"name\": \"Avocado\",\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Avo Dark Green\",\n          \"colorHex\": \"#1B5E20\"\n        },\n        {\n          \"colorName\": \"Avo Light Green\",\n          \"colorHex\": \"#81C784\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#5D4037\",\n          \"colorName\": \"Avo Pit Brown\",\n          \"sparkleIntensity\": 1\n        }\n      ]\n    },\n    {\n      \"gemColors\": [\n        {\n          \"colorName\": \"Melon Green\",\n          \"colorHex\": \"#8BC34A\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Melon Orange\",\n          \"colorHex\": \"#FFCC80\"\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          2,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"name\": \"Melon\",\n      \"id\": \"melon\"\n    },\n    {\n      \"id\": \"tangerine\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Tang Orange\",\n          \"colorHex\": \"#FF6D00\"\n        },\n        {\n          \"colorHex\": \"#64DD17\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          0,\n          2,\n          0,\n          0\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"name\": \"Tangerine\"\n    },\n    {\n      \"name\": \"Guava\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorHex\": \"#9CCC65\",\n          \"colorName\": \"Guava Green\"\n        },\n        {\n          \"colorName\": \"Guava Pink\",\n          \"colorHex\": \"#F06292\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Guava Seed\",\n          \"colorHex\": \"#000000\",\n          \"sparkleIntensity\": 1.5\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"id\": \"guava\"\n    },\n    {\n      \"id\": \"lychee\",\n      \"name\": \"Lychee\",\n      \"gemColors\": [\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Lychee Pink\",\n          \"colorHex\": \"#D81B60\"\n        },\n        {\n          \"sparkleIntensity\": 1,\n          \"colorName\": \"Lychee White\",\n          \"colorHex\": \"#FFFFFF\"\n        },\n        {\n          \"colorName\": \"Lychee Pit Brown\",\n          \"colorHex\": \"#4E342E\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          1,\n          1,\n          0\n        ],\n        [\n          1,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          3,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"durian\",\n      \"gemColors\": [\n        {\n          \"colorName\": \"Durian Brownish\",\n          \"colorHex\": \"#AFB42B\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorName\": \"Durian Yellow\",\n          \"colorHex\": \"#FFEE58\",\n          \"sparkleIntensity\": 1\n        },\n        {\n          \"colorHex\": \"#2E7D32\",\n          \"colorName\": \"Leaf Green\",\n          \"sparkleIntensity\": 1\n        }\n      ],\n      \"grid\": [\n        [\n          0,\n          3,\n          0,\n          3,\n          0\n        ],\n        [\n          1,\n          1,\n          1,\n          1,\n          1\n        ],\n        [\n          1,\n          2,\n          2,\n          2,\n          1\n        ],\n        [\n          1,\n          2,\n          1,\n          2,\n          1\n        ],\n        [\n          0,\n          1,\n          1,\n          1,\n          0\n        ]\n      ],\n      \"name\": \"Durian\"\n    }\n  ]\n}", "game_design_document": "## Core Game Loop and Mechanics\n\n**ASMR Fruit Diamond Art** is a relaxing, meditative puzzle game where players fill fruit-shaped canvases with colorful diamond gems. The core experience focuses on the satisfying tactile and audio-visual feedback of each gem placement.\n\n**Moment-to-Moment Gameplay:**\n1. Player sees a fruit-shaped canvas divided into numbered cells\n2. Each cell number corresponds to a specific gem color\n3. Player selects a gem color from the palette at the bottom\n4. Player taps/clicks cells matching that color number\n5. Each placement triggers:\n   - A soft, satisfying crystal \"click\" sound\n   - A brief sparkle animation at the placement point\n   - The gem appears with a subtle shine effect\n6. Progress bar fills gradually as more gems are placed\n7. When canvas is complete, a rainbow shimmer animation plays across the entire fruit\n8. Player unlocks the next fruit canvas\n\n**What Makes It Compelling:**\n- **ASMR Satisfaction**: Every interaction provides immediate audio-visual reward\n- **Meditative Flow**: No time pressure, no failure - pure relaxation\n- **Visual Progress**: Watching the mosaic come to life is inherently satisfying\n- **Collection Aspect**: Unlocking new fruits provides gentle progression\n- **Completion Reward**: The final shimmer animation provides a dopamine hit\n\n## Starting Scope\n\n**First Implementation (Minimal Viable Product):**\n- **Single Fruit Canvas**: Implement one complete strawberry canvas (medium complexity - mix of red, pink, green gems)\n- **Core Placement Mechanic**: Tap/click to place gems with sparkle animation and sound\n- **Color Palette**: 4-5 gem colors displayed at bottom with selection state\n- **Progress Tracking**: Simple progress bar showing completion percentage\n- **Completion Animation**: Rainbow shimmer effect when canvas is filled\n- **Basic UI**: Title, progress bar, color palette, canvas\n\n**Defer to Later Iterations:**\n- Multiple fruit levels (lemon, grapes, watermelon, etc.)\n- Level selection screen\n- Undo/reset functionality\n- Hint system (highlight next cells of selected color)\n- Zoom/pan for larger canvases\n- Sound toggle\n- Save progress between sessions\n\n## Game Perspective\n\n**Fixed-screen** with a centered canvas view. The fruit canvas occupies the middle portion of the screen, with UI elements (progress bar at top, color palette at bottom) in fixed positions. No scrolling or camera movement - everything visible at once for a calm, focused experience.\n\n## Game World and Level Design\n\n**Canvas Structure:**\n- Fruit outline divided into a grid of cells (approximately 20x30 cells for strawberry)\n- Each cell contains a number (1-5) indicating which gem color belongs there\n- Cells are small enough to create detailed mosaic art but large enough for comfortable touch targets (minimum 36x36 pixels)\n- Canvas is centered vertically and horizontally with padding around edges\n\n**Strawberry Canvas (First Level):**\n- **Shape**: Classic strawberry silhouette with leaves at top\n- **Color Distribution**:\n  - Color 1 (Deep Red): Main body of strawberry (~60% of cells)\n  - Color 2 (Light Pink): Highlights and dimension (~15% of cells)\n  - Color 3 (Dark Green): Leaves (~15% of cells)\n  - Color 4 (Light Green): Leaf highlights (~5% of cells)\n  - Color 5 (Yellow): Tiny seeds scattered across body (~5% of cells)\n- **Grid Layout**: Numbers arranged to create natural shading and dimension\n- **Background**: Dark navy/black to make gems pop\n\n**Future Levels (Design Reference):**\n- **Lemon**: Yellows, whites, greens - oval shape with leaf\n- **Grapes**: Purples, deep blues, golds - cluster of circles\n- **Watermelon Slice**: Reds, pinks, greens, blacks (seeds) - semicircle shape\n\n## Edit Mode Design\n\n**What Users Can Customize:**\n\n**Canvas Properties:**\n- `fruitType`: Select which fruit canvas to display (strawberry, lemon, grapes, etc.)\n- `gridSize`: Adjust cell count (small: 15x20, medium: 20x30, large: 30x45)\n- `backgroundColor`: Change canvas background color (dark navy, black, deep purple)\n\n**Gem Properties:**\n- `gemColors`: Array of 5 color objects, each with:\n  - `colorHex`: The gem color (e.g., \"#FF1744\" for red)\n  - `colorName`: Display name (e.g., \"Ruby Red\")\n  - `sparkleIntensity`: How bright the sparkle effect is (0.5-1.5)\n\n**Audio Properties:**\n- `clickVolume`: Volume of gem placement sound (0.0-1.0)\n- `completionVolume`: Volume of completion shimmer sound (0.0-1.0)\n\n**Visual Properties:**\n- `gemShineIntensity`: How much gems glitter after placement (0.5-1.5)\n- `progressBarColor`: Color of the progress bar fill\n\n**Constraints:**\n- Grid size minimum: 10x15 (too small becomes trivial)\n- Grid size maximum: 40x60 (too large becomes tedious on mobile)\n- Must have at least 3 gem colors, maximum 8 (for visual variety without overwhelming)\n- Volume values clamped between 0.0-1.0\n- Color values must be valid hex codes\n\n## Control Design\n\n**Mobile (Touch) - Primary Design:**\n- **Gem Placement**: Single tap on any canvas cell to place the currently selected gem\n- **Color Selection**: Tap any color in the palette at bottom to select it\n- **Visual Feedback**: \n  - Selected color has a glowing border/highlight\n  - Tapped cell briefly scales up before gem appears\n  - Invalid taps (wrong color) show a gentle shake animation\n\n**Desktop (Mouse + Keyboard):**\n- **Gem Placement**: Click on canvas cells to place gems\n- **Color Selection**: Click colors in palette OR use number keys 1-5 to select colors\n- **Hover Feedback**: Cells highlight on hover to show they're interactive\n- **Keyboard Shortcuts**:\n  - Number keys 1-5: Select corresponding gem color\n  - Spacebar: Place gem on currently hovered cell (if valid)\n\n**Input Handling:**\n- Prevent placing gems in already-filled cells (show subtle shake)\n- Prevent placing wrong color in a cell (show subtle shake + soft error sound)\n- Clear hover states on touch devices\n- Prevent default browser behaviors for used keys\n\n**Accessibility:**\n- Large enough touch targets (minimum 36x36px per cell)\n- Clear visual distinction between selected/unselected colors\n- Color palette includes both color AND number labels\n- High contrast between gems and background\n\n## Win/Lose Conditions\n\n**Win Condition:**\n- Fill every cell on the canvas with the correct gem color\n- Triggers completion sequence:\n  1. Brief pause (0.3s)\n  2. Rainbow shimmer wave animation sweeps across the entire fruit (1.5s)\n  3. Satisfying completion sound (gentle chime with sparkle)\n  4. \"Complete!\" message appears\n  5. In future: \"Next Fruit\" button appears to continue\n\n**No Lose Condition:**\n- This is a purely relaxing experience with no failure state\n- Players can take as long as they want\n- No time limits, no mistakes that end the game\n- Wrong placements simply don't register (gentle feedback only)\n\n## Art Style and Visual Theme\n\n**Overall Aesthetic:**\n- **Soft, Dreamy, Cozy ASMR Vibes**: Gentle gradients, glowing effects, rounded shapes\n- **Dark Background**: Deep navy (#0A1128) or black (#000000) to make gems pop and create a calming nighttime atmosphere\n- **Pastel UI**: Soft pinks, purples, blues for UI elements - nothing harsh or bright\n- **Minimal Design**: Clean, uncluttered interface - the gems are the star\n\n**Gem Visual Style:**\n- **Diamond/Crystal Appearance**: Faceted look with multiple shine points\n- **Glow Effect**: Subtle outer glow in the gem's color\n- **Sparkle Animation**: Small star-burst particles on placement\n- **Shine Effect**: Tiny white highlight that occasionally glints\n\n**Canvas Style:**\n- **Grid Lines**: Very subtle, thin lines (#FFFFFF at 10% opacity) to separate cells\n- **Cell Numbers**: Small, light gray numbers in each empty cell\n- **Filled Cells**: Numbers disappear when gem is placed\n\n**Color Palette (Bottom UI):**\n- **Rounded Buttons**: Soft rounded squares (border-radius: 12px)\n- **Gem Preview**: Each button shows the gem color with a mini diamond icon\n- **Selected State**: Glowing border + slight scale increase\n- **Number Labels**: Small number badge on each color button\n\n**Progress Bar:**\n- **Soft Gradient Fill**: Gentle gradient in pastel colors\n- **Rounded Ends**: Fully rounded (border-radius: 20px)\n- **Subtle Animation**: Smooth fill animation with slight glow\n\n**Typography:**\n- **Soft, Rounded Font**: Use a gentle sans-serif (system fonts: -apple-system, \"Segoe UI\", Roboto)\n- **Minimal Text**: Only essential labels (progress percentage, color numbers)\n\n**Completion Animation:**\n- **Rainbow Shimmer**: Wave of rainbow gradient sweeps across fruit\n- **Particle Burst**: Small sparkle particles emit from center\n- **Glow Pulse**: Entire fruit pulses with soft white glow\n\n**Asset Rendering Strategy:**\n- **Generate Assets**: Fruit canvas templates, individual gem graphics\n- **Code Rendering (CSS/Canvas)**: \n  - Grid lines and cell structure\n  - Progress bar\n  - Color palette buttons\n  - Sparkle particle effects\n  - Shimmer animations", "persistent_storage_config": null, "game_metadata": {"game_id": "01KV46CG4X3FE893G3PEF26BX2", "title": "ASMR Fruit Diamond Art", "description": "Relax and create sparkling fruit mosaics by placing colorful diamond gems one satisfying tap at a time.", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_5efb2a86-0fb3-4d68-91c0-441e261cd60c.webp", "created_at": 1781478614.0, "updated_at": 1781537372152.5273, "art_style": null}, "task_plan": null}