{"asset_map": {"wig_bob": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_bob_c7c8ba43-c807-4d6f-a2fc-cde8f57e25e5.webp", "type": "image", "prompt": "Generate a professional game asset of a short bob-style wig illustration, neutral gray color, viewed from the front. Clean blunt cut at chin length with straight bangs. Cartoon/illustrated art style, smooth shading, visible hair texture. Mannequin-head shape silhouette, transparent background, cute and modern style, clean lines.", "description": "Short bob-style wig in neutral gray for coloring, front view.", "subtype": "object", "aspect_ratio": [717, 906], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "wig_wavy": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_wavy_05a5dc9d-5cc5-431e-8b97-5ffda2a23078.webp", "type": "image", "prompt": "Generate a professional game asset of a long wavy-style wig illustration, neutral gray color, viewed from the front. Flowing waves cascading past shoulders, side part. Cartoon/illustrated art style, smooth shading showing wave texture and volume. Mannequin-head shape silhouette, transparent background, cute and modern style, clean lines.", "description": "Long wavy wig in neutral gray for coloring, front view.", "subtype": "object", "aspect_ratio": [785, 925], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "wig_curly": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_curly_e1b9ebcf-c905-4503-aac6-4ad43be3a36c.webp", "type": "image", "prompt": "Generate a professional game asset of a curly afro-style wig illustration, neutral gray color, viewed from the front. Voluminous, bouncy curls in a rounded afro shape. Cartoon/illustrated art style, smooth shading showing curl texture and volume. Mannequin-head shape silhouette, transparent background, cute and modern style, clean lines.", "description": "Curly afro-style wig in neutral gray for coloring, front view.", "subtype": "object", "aspect_ratio": [806, 940], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "customer_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_1_63b393c8-7756-4eba-a559-c0d93e781ca0.webp", "type": "image", "prompt": "Generate a front-facing bust portrait of a cheerful young woman, head and shoulders. Friendly excited expression, bright eyes, warm smile. Medium skin tone, casual colorful top. Cute modern cartoon art style, clean lines, soft shading, transparent background, high resolution.", "description": "Cheerful young woman customer portrait.", "subtype": "character", "aspect_ratio": [804, 1018], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_2_3ac85d88-1034-41a7-9b62-dfd0505a318b.webp", "type": "image", "prompt": "Generate a front-facing bust portrait of a sophisticated middle-aged woman, head and shoulders. Confident pleased expression, kind eyes, gentle smile. Light skin tone, elegant attire. Cute modern cartoon art style, clean lines, soft shading, transparent background, high resolution.", "description": "Sophisticated middle-aged woman customer portrait.", "subtype": "character", "aspect_ratio": [829, 986], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_3_5839c395-9747-43fd-a81f-9d74f917af4f.webp", "type": "image", "prompt": "Generate a front-facing bust portrait of a trendy young person, head and shoulders. Enthusiastic excited expression, sparkling eyes, big smile. Dark skin tone, stylish modern outfit. Cute modern cartoon art style, clean lines, soft shading, transparent background, high resolution.", "description": "Trendy young energetic customer portrait.", "subtype": "character", "aspect_ratio": [813, 1018], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_4_5d7ab92d-913d-483a-b85f-6ab93b6733bf.webp", "type": "image", "prompt": "Generate a front-facing bust portrait of a creative artistic woman, head and shoulders. Thoughtful imaginative expression, dreamy eyes, soft smile. Medium-light skin tone, artsy colorful clothing. Cute modern cartoon art style, clean lines, soft shading, transparent background, high resolution.", "description": "Creative artistic woman customer portrait.", "subtype": "character", "aspect_ratio": [819, 1018], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_5": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_5_ea89cb91-2c37-4c80-9103-7525ecb55bc2.webp", "type": "image", "prompt": "Generate a front-facing bust portrait of a glamorous fashionable woman, head and shoulders. Confident sophisticated expression, striking eyes, elegant smile. Tan skin tone, chic high-fashion attire. Cute modern cartoon art style, clean lines, soft shading, transparent background, high resolution.", "description": "Glamorous high-fashion woman customer portrait.", "subtype": "character", "aspect_ratio": [775, 1008], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "accessory_bow": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_bow_17cf3622-ab0a-4619-ad36-66771131e807.webp", "type": "image", "prompt": "Generate a cute decorative hair bow game asset. Classic ribbon bow shape with two loops and trailing ribbons. Bright pink color, soft shading for dimension, clean lines, slight shine. Cartoon/illustrated style, transparent background.", "description": "Pink ribbon bow hair accessory.", "subtype": "object", "aspect_ratio": [865, 860], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "accessory_flower": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_flower_3fda1699-5593-44ff-8d7b-c0627e913aad.webp", "type": "image", "prompt": "Generate a cute decorative flower hair accessory game asset. Stylized bloom (hibiscus or daisy) with 5-6 petals. Bright yellow and orange color, contrasting center. Cartoon/illustrated style, clean lines, soft shading, transparent background.", "description": "Yellow/orange flower hair accessory.", "subtype": "object", "aspect_ratio": [903, 912], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "accessory_star": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_star_f599eaf8-3bcc-4e40-9ddc-eb883ae507f2.webp", "type": "image", "prompt": "Generate a cute decorative star hair clip game asset. 5-pointed star shape with slight 3D appearance. Bright sparkly blue/purple color, glossy finish with highlights. Cartoon/illustrated style, clean lines, transparent background.", "description": "Blue/purple star hair clip accessory.", "subtype": "object", "aspect_ratio": [934, 725], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "salon_background": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/salon_background_3e282c6a-f4e9-4352-94fd-ba35872752e9.webp", "type": "image", "prompt": "Generate a 9:16 tall image of a cheerful salon interior. Soft cartoon/illustrated style, pastel colors (pink, lavender, mint). Blurred simplified background showing mirrors and product shelves. Dreamy welcoming atmosphere, soft bokeh focus, high quality.", "description": "Cozy salon interior background for portrait orientation.", "subtype": "background", "aspect_ratio": [1024, 1536], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "success_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/success_sound_247377e8-a24e-4b74-a450-6c3a17fcf3f7.mp3", "type": "audio", "prompt": "A cheerful and satisfying success chime, bright magical ding with a sparkling bell tone, high-pitched and uplifting, clean digital synthesis, short tail, perfect for a rewarding mobile game feedback moment.", "description": "A bright, rewarding chime for a happy customer feedback.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.86, "loop": false, "animation": null}, "place_accessory_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/place_accessory_sound_4f7fe728-131e-412d-8ba7-c4396a0fabe7.mp3", "type": "audio", "prompt": "A soft, cute 'pop' or light 'click' sound effect, tactile and organic like a gentle snap, very short duration, clean and crisp, suitable for user interface interactions in a casual game.", "description": "A light, snappy sound effect for attaching accessories to the wig.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 0.39, "loop": false, "animation": null}, "color_apply_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/color_apply_sound_11878cbe-8978-4a61-9c01-29a51acf4606.mp3", "type": "audio", "prompt": "Soft airy whoosh sound, gentle paintbrush stroke on hair, smooth and pleasant texture, light foley, non-metallic, subtle and satisfying feedback for a creative action.", "description": "A smooth, airy sound effect representing a brush stroke or color application.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.72, "loop": false, "animation": null}, "customer_unhappy_sound": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/customer_unhappy_sound_fd8fe149-aeb8-4cf8-a05d-0639fd04c597.mp3", "type": "audio", "prompt": "A gentle descending musical motif, 2-3 notes, soft woodwind or mellow synth, conveying a mild 'oh no' feeling without being harsh, whimsical and cartoonish disappointment.", "description": "A gentle descending tone for a disappointed customer reaction.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.65, "loop": false, "animation": null}, "background_music": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/background_music_8edd3d54-ea88-4ffe-abae-31beaf080535.mp3", "type": "audio", "prompt": "Upbeat and cheerful background music for a cozy salon game, light pop and bossa nova influence, featuring a playful electric piano, soft acoustic guitar strums, and a gentle shaker rhythm. Mid-tempo around 110 BPM, creative and relaxing vibe, bright major key, smooth transitions, loopable, instrumental only, high-quality production for a mobile casual game.", "description": "Main gameplay music: upbeat, cheerful, and creative salon atmosphere.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 30, "loop": true, "animation": null}, "wig_pixie": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_pixie_0007ec5d-c806-4f3f-8d8a-0be1bc8ea6fb.webp", "type": "image", "prompt": "Generate an extremely sharp, high-definition short pixie cut wig. Front-view, centered composition. The hair should be a neutral light gray base color suitable for color tinting. Ensure every hair strand is clearly defined with perfectly clean, crisp edges and no blurriness. Professional game asset quality, isolated on a transparent background, high resolution and polished.", "description": "High-definition, sharp-edged short pixie cut wig in neutral gray for in-game coloring.", "subtype": "object", "aspect_ratio": [676, 936], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "wig_braids": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_braids_9096169f-3f6e-4e10-819c-edadb881eb0c.webp", "type": "image", "prompt": "Generate a long box braids wig in a neutral light gray color, designed for coloring in a game. Full front view, symmetrical arrangement, professional clean lines, high resolution game asset, transparent background. Match the artistic style, scale, and lighting of wig_bob and wig_curly.", "description": "Long box braids wig in neutral gray for coloring, front view.", "subtype": "object", "aspect_ratio": [714, 998], "compression_suggestion": "original", "duration_secs": null, "loop": null, "animation": null}, "wig_ponytail": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_ponytail_d07b22fc-8be4-4c7b-b0de-20c52d290b58.webp", "type": "image", "prompt": "Generate a high-definition, professional game-ready wig asset featuring a classic high ponytail hairstyle. Front-facing view, where the ponytail is clearly visible behind the head. The hair should be a solid, neutral mid-gray color with clean, sharp edges and clear linework to facilitate in-game color multiplication. Studio lighting, flat lighting to avoid deep shadows, transparent background.", "description": "A high ponytail hairstyle wig in neutral gray for in-game customization.", "subtype": "object", "aspect_ratio": [522, 1052], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "wig_space_buns": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/wig_space_buns_faaa7be4-f549-4f52-a7dd-9a05514fd256.webp", "type": "image", "prompt": "Generate a high-definition, sharp-edged space buns hairstyle wig featuring two symmetrical high buns on either side of the head. Front view, clean digital illustration, neutral light gray color for later in-game recoloring. Match the artistic style and line work of `wig_pixie` and `wig_bob`. Standing illustration, transparent background.", "description": "A trendy double-bun hairstyle wig in neutral gray for in-game customization.", "subtype": "object", "aspect_ratio": [825, 1057], "compression_suggestion": "low", "duration_secs": null, "loop": null, "animation": null}, "accessory_crown": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_crown_d2181e3f-e5e0-46c5-a621-d3b130befb1a.webp", "type": "image", "prompt": "Generate a small, shiny gold princess crown hair clip, high-definition with sharp polished edges. The crown should be a jewelry-grade accessory, sparkling and isolated on a transparent background. Front-facing orientation, game-ready asset, clean professional quality to match the style of a hair salon makeover game.", "description": "A small, shiny gold princess crown hair clip for hair placement.", "subtype": "ui", "aspect_ratio": [1056, 744], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "accessory_heart": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_heart_d0f0fce4-98fa-4109-8615-ab30f305f61f.webp", "type": "image", "prompt": "Generate a vibrant red heart-shaped hair clip, cute and glossy finish, high-definition with sharp edges, professional game asset, front view, isolated on a transparent background.", "description": "A vibrant red heart-shaped hair clip with a glossy finish for character customization.", "subtype": "ui", "aspect_ratio": [961, 674], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "accessory_butterfly": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_butterfly_79a844a4-d169-44ad-a426-8cedaaa466d8.webp", "type": "image", "prompt": "Generate a high-definition, sharp-edged delicate blue butterfly-shaped hair accessory. The butterfly should have shimmering, iridescent wings with fine details. Front-facing orientation, clean polished game-ready asset, isolated on a transparent background, matching the artistic style of accessory_bow and accessory_star.", "description": "A delicate blue butterfly hair clip with shimmering wings for character customization.", "subtype": "ui", "aspect_ratio": [1162, 826], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "accessory_pearl": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/accessory_pearl_d5638f08-58ec-485e-85ec-cc4acd85b481.webp", "type": "image", "prompt": "Generate a high-definition, professional-quality classic white pearl hair pin. The asset should feature a single, perfectly round pearl with a realistic iridescent luster on a simple silver pin. Elegant and simple aesthetic, clean sharp edges, isolated on a transparent background, front-facing view to match other hair accessories like the accessory_crown.", "description": "A classic and elegant white pearl hair pin for character customization.", "subtype": "ui", "aspect_ratio": [191, 779], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_6": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_6_98ff2af1-43fa-4023-af78-372555589d8f.webp", "type": "image", "prompt": "Generate a portrait headshot of an elegant woman with a vintage 1950s aesthetic for a mobile salon game. She has very short, slicked-back hair and a neutral expression to allow for wig overlays. Style: vibrant, polished digital art, clean lines, friendly and colorful. Front-facing view, centered composition. Match the artistic style and lighting of customer_1, customer_2, and customer_3. Transparent background.", "description": "An elegant vintage-style woman customer portrait with slicked-back hair to accommodate wig overlays.", "subtype": "character", "aspect_ratio": [832, 1051], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_7": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_7_492aef82-3d32-4eae-b65b-fa011ef3d79f.webp", "type": "image", "prompt": "Generate a high-quality digital art portrait of a cool, edgy woman with a street-style aesthetic. She should have very short, slicked-back neutral hair to serve as a base for wig overlays. The style must be a polished, vibrant, and friendly cartoon illustration consistent with the portraits of customer_1 and customer_2. Front-facing headshot, neutral expression, clean lines, professional game-ready asset, transparent background.", "description": "A cool, edgy street-style woman portrait designed as a base for wig overlays.", "subtype": "character", "aspect_ratio": [862, 1019], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_8": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_8_5e8cd05a-61e9-42d5-8014-46f0397c632a.webp", "type": "image", "prompt": "Generate a high-quality, front-facing portrait of a kind and friendly woman with a bohemian aesthetic for a mobile wig salon game. She has a warm expression and subtle boho jewelry like small feather earrings. Her hair is very short or slicked back tightly in a neutral tone to allow for wig overlays. Use a vibrant, polished digital art style consistent with a friendly cartoon aesthetic. 9:16 aspect ratio, clean lines, professional quality, matching the style of customer_1 and customer_5.", "description": "A kind, bohemian-style woman customer portrait with minimal hair for wig overlays.", "subtype": "character", "aspect_ratio": [832, 1060], "compression_suggestion": "high", "duration_secs": null, "loop": null, "animation": null}, "customer_9": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_9_c7f2c26e-455a-4bc7-b7a7-b3953221f2e4.webp", "type": "image", "prompt": "Generate a high-quality digital art portrait of a professional business woman for a mobile wig salon game. She should be wearing elegant corporate attire like a blazer and have very short or slicked-back neutral hair to accommodate wig overlays. Front-facing headshot, friendly and confident expression. Vibrant, polished style, clean lines, and consistent lighting to match the aesthetic of image 1 and image 2. Transparent background.", "description": "A professional business woman character portrait with slicked-back hair for wig overlays.", "subtype": "character", "aspect_ratio": [863, 1022], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "customer_10": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/customer_10_c1fb8ee1-4b18-4a3a-bc27-855ef33a1b19.webp", "type": "image", "prompt": "Generate a high-quality digital art portrait of a fun-loving woman with a retro pop style. The character should have very short, slicked-back neutral hair to allow for wig overlays. Front-facing headshot, vibrant colors, polished finish, friendly expression. Ensure the art style, lighting, and composition are perfectly consistent with the existing characters customer_1 and customer_5. Transparent background, game-ready character asset.", "description": "A fun-loving woman portrait with a retro pop aesthetic for the wig salon game.", "subtype": "character", "aspect_ratio": [765, 1078], "compression_suggestion": "medium", "duration_secs": null, "loop": null, "animation": null}, "voice_happy_1": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_1_224d7a95-e1d6-43fd-bc8a-3a19cfbcf2f2.mp3", "type": "audio", "prompt": "A clear, high-quality recording of a friendly young adult female voice saying the phrase 'Oh, I love it!' with a bright, enthusiastic, and genuinely excited tone. The performance should be expressive and cheerful, suitable for a happy customer in a boutique hair salon. Dry recording with minimal room reverb, no background noise, professional voice-over quality.", "description": "A cheerful female voice clip expressing delight, used when a customer is satisfied with their hairstyle.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.96, "loop": false, "animation": null}, "voice_happy_2": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_2_83f7ddb1-a6fd-4d5a-8844-1eb070fa3e58.mp3", "type": "audio", "prompt": "A clear, high-quality recording of a sophisticated adult female voice saying 'This is fabulous!' with a tone of genuine delight and elegance. The performance should be expressive and cheerful, fitting a high-end hair salon setting. Clean studio audio, no background noise, dry signal, perfect for a character reaction in a creative simulation game.", "description": "A sophisticated female voice expressing delight with the phrase 'This is fabulous!' for a positive salon customer reaction.", "subtype": "music", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 3, "loop": false, "animation": null}, "voice_happy_3": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_3_2a928bcc-d101-4e8d-8ddd-37c2d0023250.mp3", "type": "audio", "prompt": "A trendy, energetic young female voice saying 'It's perfect! Thank you!' with a bright, enthusiastic, and joyful tone. Clear studio quality, dry recording with no background noise, expressive and friendly delivery suitable for a casual mobile game character.", "description": "An energetic female voice expressing gratitude and satisfaction, used for positive customer feedback.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.82, "loop": false, "animation": null}, "voice_happy_4": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_4_cc22e3e9-6362-41e7-be33-51257f52ce6e.mp3", "type": "audio", "prompt": "A high-quality, dry vocal recording of an enthusiastic young woman saying the phrase 'Love it!'. The delivery is very snappy, quick, and bursting with genuine excitement. High energy, bright tone, suitable for a mobile game feedback sound. No background music, clear articulation, close-mic studio quality.", "description": "Short and excited female voice saying 'Love it!' for positive gameplay feedback.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.23, "loop": false, "animation": null}, "voice_happy_5": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_5_c780ff30-f31d-4aaa-9f6c-a3ef45a0dd5b.mp3", "type": "audio", "prompt": "A high-quality recording of a young woman's voice saying the word 'Amazing!' with extreme enthusiasm and a bright, cheerful tone. The delivery is quick and energetic, rising in pitch slightly at the end to express genuine delight. Clean studio recording, no background noise, dry signal, suitable for a casual salon game UI feedback.", "description": "Short, enthusiastic female voice saying 'Amazing!' for positive feedback.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 2.26, "loop": false, "animation": null}, "voice_happy_6": {"url": "https://d2oir5eh8rty2e.cloudfront.net/assets/sounds/effect/voice_happy_6_6524cc52-13ef-4901-b579-8a14aa818807.mp3", "type": "audio", "prompt": "Sound effect of a perky female voice enthusiastically saying 'Perfect!' to express satisfaction. High energy, bright tone, quick delivery, professional voice acting quality. No background music or noise, clean audio, suitable for a cheerful salon game UI feedback.", "description": "A short, perky female voice saying 'Perfect!' to express delight with a hair makeover.", "subtype": "effect", "aspect_ratio": null, "compression_suggestion": "original", "duration_secs": 1.22, "loop": false, "animation": null}}, "game_code": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Wig Whimsy Salon</title>\n    <link href=\"https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Inter:wght@400;500;600&display=swap\" rel=\"stylesheet\">\n    <style>\n        :root {\n            --transition-fast: 150ms;\n            --transition-normal: 300ms;\n            --transition-slow: 500ms;\n            --ease-out: cubic-bezier(0.0, 0, 0.2, 1);\n            --ease-bounce: cubic-bezier(0.68, -0.6, 0.32, 1.6);\n            --space-xs: 8px;\n            --space-sm: 16px;\n            --space-md: 24px;\n            --space-lg: 32px;\n            --space-xl: 48px;\n            --pink: #FF6B9D;\n            --pink-light: #FFB3D1;\n            --purple: #9B59B6;\n            --purple-light: #D2B4DE;\n            --mint: #A8E6CF;\n            --yellow: #FFD93D;\n            --bg-panel: rgba(255, 255, 255, 0.7);\n            --shadow: 0 4px 16px rgba(0,0,0,0.12);\n            --radius: 16px;\n        }\n\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: 'Inter', sans-serif;\n        }\n\n        #game-world {\n            position: relative;\n            width: 720px;\n            height: 1280px;\n            overflow: hidden;\n            background: #F8E8F0;\n        }\n\n        #bg-image {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            object-fit: cover;\n            z-index: 0;\n        }\n\n        .ui-overlay {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            z-index: 10;\n            pointer-events: none;\n            display: flex;\n            flex-direction: column;\n        }\n\n        .ui-overlay > * {\n            pointer-events: auto;\n        }\n\n        /* Customer Area */\n        .customer-area {\n            height: 380px;\n            display: flex;\n            flex-direction: column;\n            align-items: center;\n            padding: 16px;\n            position: relative;\n        }\n\n        .score-bar {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            width: 100%;\n            padding: 8px 16px;\n        }\n\n        .score-text {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 28px;\n            font-weight: 600;\n            color: #fff;\n            text-shadow: 0 2px 4px rgba(0,0,0,0.3);\n        }\n\n        .hearts {\n            font-size: 28px;\n        }\n\n        .customer-display {\n            display: flex;\n            align-items: center;\n            gap: 16px;\n            background: var(--bg-panel);\n            border-radius: var(--radius);\n            padding: 16px;\n            box-shadow: var(--shadow);\n            max-width: 680px;\n            width: calc(100% - 32px);\n        }\n\n        .customer-avatar {\n            width: 120px;\n            height: 120px;\n            border-radius: 50%;\n            overflow: hidden;\n            border: 4px solid var(--pink-light);\n            flex-shrink: 0;\n        }\n\n        .customer-avatar img {\n            width: 100%; height: 100%;\n            object-fit: contain;\n            background: #fff;\n        }\n\n        .speech-bubble {\n            background: #fff;\n            border-radius: 16px;\n            padding: 12px 16px;\n            position: relative;\n            border: 3px solid var(--pink-light);\n            flex: 1;\n        }\n\n        .speech-bubble::before {\n            content: '';\n            position: absolute;\n            left: -14px;\n            top: 50%;\n            transform: translateY(-50%);\n            border: 8px solid transparent;\n            border-right-color: var(--pink-light);\n        }\n\n        .request-label {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 20px;\n            font-weight: 500;\n            color: #666;\n            margin-bottom: 8px;\n        }\n\n        .request-details {\n            display: flex;\n            align-items: center;\n            gap: 8px;\n            flex-wrap: wrap;\n        }\n\n        .request-wig-icon {\n            width: 60px; height: 60px;\n            object-fit: contain;\n        }\n\n        .request-color-swatch {\n            width: 36px; height: 36px;\n            border-radius: 50%;\n            border: 3px solid #ddd;\n        }\n\n        .request-accessory-icon {\n            width: 36px; height: 36px;\n            object-fit: contain;\n        }\n\n        /* Work Area */\n        .work-area {\n            flex: 1;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            position: relative;\n        }\n\n        .wig-display {\n            width: 500px;\n            height: 500px;\n            position: relative;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            background: rgba(255,255,255,0.5);\n            border-radius: 50%;\n            box-shadow: 0 0 40px rgba(255,107,157,0.2);\n            margin-bottom: 40px; /* Move it up from the bottom palette */\n        }\n\n        .wig-image {\n            width: 450px;\n            height: 450px;\n            object-fit: contain;\n            transition: filter var(--transition-fast);\n            image-rendering: -webkit-optimize-contrast;\n            image-rendering: high-quality;\n        }\n\n        .wig-accessory {\n            position: absolute;\n            width: 56px;\n            height: 56px;\n            object-fit: contain;\n            cursor: pointer;\n            transition: transform var(--transition-fast);\n        }\n\n        .wig-accessory:hover {\n            transform: scale(1.2);\n        }\n\n        .wig-style-selector {\n            position: absolute;\n            top: 8px;\n            left: 50%;\n            transform: translateX(-50%);\n            display: flex;\n            gap: 12px;\n            background: var(--bg-panel);\n            padding: 8px 16px;\n            border-radius: 40px;\n            box-shadow: var(--shadow);\n        }\n\n        .wig-style-btn {\n            width: 72px;\n            height: 72px;\n            border-radius: 50%;\n            border: 3px solid #ddd;\n            background: #fff;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n        }\n\n        .wig-style-btn.selected {\n            border-color: var(--pink);\n            box-shadow: 0 0 12px rgba(255,107,157,0.4);\n        }\n\n        .wig-style-btn:active {\n            transform: scale(0.9);\n        }\n\n        .wig-style-btn img {\n            width: 52px; height: 52px;\n            object-fit: contain;\n        }\n\n        /* Tool Palette */\n        .tool-palette {\n            background: var(--bg-panel);\n            border-radius: 24px 24px 0 0;\n            padding: 20px 16px;\n            box-shadow: 0 -4px 20px rgba(0,0,0,0.1);\n        }\n\n        .palette-section {\n            margin-bottom: 16px;\n        }\n\n        .palette-label {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 18px;\n            font-weight: 500;\n            color: #888;\n            margin-bottom: 8px;\n        }\n\n        .color-grid {\n            display: flex;\n            gap: 8px;\n            flex-wrap: wrap;\n            justify-content: center;\n        }\n\n        .color-swatch {\n            width: 72px;\n            height: 72px;\n            border-radius: 50%;\n            border: 4px solid transparent;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n            box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n        }\n\n        .color-swatch.selected {\n            border-color: #333;\n            transform: scale(1.15);\n            box-shadow: 0 4px 12px rgba(0,0,0,0.3);\n        }\n\n        .color-swatch:active {\n            transform: scale(0.9);\n        }\n\n        .accessory-grid {\n            display: flex;\n            gap: 12px;\n            justify-content: center;\n            flex-wrap: wrap;\n        }\n\n        .accessory-btn {\n            width: 80px;\n            height: 80px;\n            border-radius: 16px;\n            border: 3px solid #ddd;\n            background: #fff;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n        }\n\n        .accessory-btn.selected {\n            border-color: var(--purple);\n            background: var(--purple-light);\n        }\n\n        .accessory-btn:active {\n            transform: scale(0.9);\n        }\n\n        .accessory-btn img {\n            width: 52px; height: 52px;\n            object-fit: contain;\n        }\n\n        .action-buttons {\n            display: flex;\n            gap: 12px;\n            margin-top: 12px;\n        }\n\n        .btn {\n            flex: 1;\n            height: 64px;\n            border-radius: 32px;\n            border: none;\n            font-family: 'Fredoka', sans-serif;\n            font-size: 24px;\n            font-weight: 600;\n            cursor: pointer;\n            transition: all var(--transition-fast);\n        }\n\n        .btn:active {\n            transform: scale(0.95);\n        }\n\n        .btn-clear {\n            background: #eee;\n            color: #666;\n        }\n\n        .btn-clear:hover {\n            background: #ddd;\n        }\n\n        .btn-present {\n            background: linear-gradient(135deg, var(--pink), var(--purple));\n            color: #fff;\n            box-shadow: 0 4px 16px rgba(255,107,157,0.4);\n        }\n\n        .btn-present:hover {\n            box-shadow: 0 6px 20px rgba(255,107,157,0.6);\n        }\n\n        .btn-present:disabled {\n            opacity: 0.5;\n            cursor: not-allowed;\n        }\n\n        /* Overlays */\n        .game-overlay {\n            position: absolute;\n            top: 0; left: 0;\n            width: 100%; height: 100%;\n            background: rgba(0,0,0,0.6);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 100;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity var(--transition-normal);\n        }\n\n        .game-overlay.visible {\n            opacity: 1;\n            pointer-events: auto;\n        }\n\n        .overlay-card {\n            background: #fff;\n            border-radius: 24px;\n            padding: 40px;\n            text-align: center;\n            max-width: 560px;\n            width: calc(100% - 80px);\n            box-shadow: 0 16px 48px rgba(0,0,0,0.3);\n            animation: float 3s ease-in-out infinite;\n        }\n\n        .rainbow-text {\n            background: linear-gradient(to right, #FF6B9D, #FFD93D, #A8E6CF, #9B59B6);\n            -webkit-background-clip: text;\n            -webkit-text-fill-color: transparent;\n            animation: rainbow 4s linear infinite;\n        }\n\n        @keyframes rainbow {\n            0% { background-position: 0% 50%; }\n            100% { background-position: 100% 50%; }\n        }\n\n        @keyframes float {\n            0% { transform: translateY(0px); }\n            50% { transform: translateY(-10px); }\n            100% { transform: translateY(0px); }\n        }\n\n        .overlay-title {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 48px;\n            font-weight: 700;\n            margin-bottom: 16px;\n        }\n\n        .overlay-subtitle {\n            font-size: 24px;\n            color: #666;\n            margin-bottom: 32px;\n        }\n\n        .overlay-btn {\n            display: inline-block;\n            padding: 16px 48px;\n            border-radius: 32px;\n            border: none;\n            font-family: 'Fredoka', sans-serif;\n            font-size: 28px;\n            font-weight: 600;\n            color: #fff;\n            background: linear-gradient(135deg, var(--pink), var(--purple));\n            cursor: pointer;\n            box-shadow: 0 4px 16px rgba(255,107,157,0.4);\n            transition: all var(--transition-fast);\n        }\n\n        .overlay-btn:active {\n            transform: scale(0.95);\n        }\n\n        /* Feedback animation */\n        .feedback-popup {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            font-family: 'Fredoka', sans-serif;\n            font-size: 56px;\n            font-weight: 700;\n            pointer-events: none;\n            z-index: 50;\n            opacity: 0;\n            transition: all 0.6s var(--ease-out);\n        }\n\n        .feedback-popup.show {\n            opacity: 1;\n            transform: translate(-50%, -80%);\n        }\n\n        /* Timer bar */\n        .timer-bar {\n            width: calc(100% - 32px);\n            height: 8px;\n            background: #eee;\n            border-radius: 4px;\n            margin: 8px 16px 0;\n            overflow: hidden;\n        }\n\n        .timer-fill {\n            height: 100%;\n            background: linear-gradient(90deg, var(--mint), var(--pink));\n            border-radius: 4px;\n            transition: width 0.5s linear;\n        }\n\n        /* Customer counter */\n        .customer-counter {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 22px;\n            color: #fff;\n            text-shadow: 0 2px 4px rgba(0,0,0,0.3);\n        }\n\n        /* Edit mode styles */\n        .edit-overlay {\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            transform: translate(-50%, -50%);\n            background: var(--bg-panel);\n            border-radius: 24px;\n            padding: 32px;\n            text-align: center;\n            z-index: 200;\n            box-shadow: var(--shadow);\n        }\n\n        .edit-overlay h2 {\n            font-family: 'Fredoka', sans-serif;\n            font-size: 32px;\n            color: var(--purple);\n            margin-bottom: 16px;\n        }\n\n        .edit-overlay p {\n            font-size: 20px;\n            color: #666;\n        }\n\n        @media (prefers-reduced-motion: reduce) {\n            * {\n                transition-duration: 0ms !important;\n                animation-duration: 0ms !important;\n            }\n        }\n    </style>\n</head>\n<body>\n    <div id=\"game-world\"></div>\n\n    <script>\n    /*\n     * WIG WHIMSY SALON\n     * A creative wig styling game where players color and decorate wigs\n     * to match customer requests. Features endless customers with\n     * increasing complexity.\n     */\n    async function run(mode) {\n        const gameWorld = document.getElementById('game-world');\n        gameWorld.innerHTML = '';\n\n        const config = window.gameConfig;\n\n        // Asset loading\n        const imageCache = {};\n        const audioBuffers = {};\n        let audioCtx = null;\n\n        function getAudioContext() {\n            if (!audioCtx) audioCtx = new (window.AudioContext || window.webkitAudioContext)();\n            return audioCtx;\n        }\n\n        function playSound(id) {\n            try {\n                const ctx = getAudioContext();\n                if (ctx.state === 'suspended') ctx.resume();\n                if (audioBuffers[id]) {\n                    const source = ctx.createBufferSource();\n                    source.buffer = audioBuffers[id];\n                    source.connect(ctx.destination);\n                    if (id === 'background_music') {\n                        source.loop = true;\n                        bgMusicSource = source;\n                    }\n                    source.start(0);\n                    return source;\n                }\n            } catch(e) { lib.log('Audio error: ' + e.message); }\n            return null;\n        }\n\n        let bgMusicSource = null;\n\n        async function preloadAssets() {\n            const imageIds = ['wig_bob', 'wig_wavy', 'wig_curly', 'wig_pixie', 'wig_braids', 'wig_ponytail', 'wig_space_buns', 'customer_1', 'customer_2', 'customer_3', 'customer_4', 'customer_5', 'customer_6', 'customer_7', 'customer_8', 'customer_9', 'customer_10', 'accessory_bow', 'accessory_flower', 'accessory_star', 'accessory_crown', 'accessory_heart', 'accessory_butterfly', 'accessory_pearl', 'salon_background'];\n            const audioIds = ['success_sound', 'place_accessory_sound', 'color_apply_sound', 'customer_unhappy_sound', 'background_music', 'voice_happy_1', 'voice_happy_2', 'voice_happy_3', 'voice_happy_4', 'voice_happy_5', 'voice_happy_6'];\n\n            const imagePromises = imageIds.map(id => {\n                return new Promise((resolve) => {\n                    const info = lib.getAsset(id);\n                    if (info && info.url) {\n                        const img = new Image();\n                        img.crossOrigin = 'anonymous';\n                        img.onload = () => { imageCache[id] = img; resolve(); };\n                        img.onerror = () => resolve();\n                        img.src = info.url;\n                    } else resolve();\n                });\n            });\n\n            const audioPromises = audioIds.map(id => {\n                return new Promise((resolve) => {\n                    const info = lib.getAsset(id);\n                    if (info && info.url) {\n                        fetch(info.url)\n                            .then(r => r.arrayBuffer())\n                            .then(buf => getAudioContext().decodeAudioData(buf))\n                            .then(decoded => { audioBuffers[id] = decoded; resolve(); })\n                            .catch(() => resolve());\n                    } else resolve();\n                });\n            });\n\n            await Promise.all([...imagePromises, ...audioPromises]);\n        }\n\n        await preloadAssets();\n        lib.showGameParameters({\n            name: 'Wig Whimsy Salon',\n            params: {\n                'Time per Customer (s)': { key: 'settings.timePerCustomer', type: 'slider', min: 0, max: 120, step: 10 },\n                'Mistakes Allowed': { key: 'settings.mistakesAllowed', type: 'slider', min: 1, max: 5, step: 1 },\n                'Perfect Match Bonus': { key: 'settings.perfectMatchBonus', type: 'slider', min: 50, max: 200, step: 25 },\n                'Show Color Hint': { key: 'settings.showColorHint', type: 'checkbox' },\n                'Show Accessory Hint': { key: 'settings.showAccessoryHint', type: 'checkbox' }\n            }\n        });\n\n        if (mode === 'edit') {\n            setupEditMode();\n        } else {\n            setupPlayMode();\n        }\n\n        function setupEditMode() {\n            // Render background\n            if (imageCache['salon_background']) {\n                const bg = document.createElement('img');\n                bg.id = 'bg-image';\n                bg.src = imageCache['salon_background'].src;\n                gameWorld.appendChild(bg);\n            }\n\n            const editDiv = document.createElement('div');\n            editDiv.className = 'edit-overlay';\n            editDiv.innerHTML = `\n                <h2>\u2702\ufe0f Wig Whimsy Salon</h2>\n                <p>Use the settings panel to customize<br>customers, colors, and difficulty!</p>\n                <p style=\"margin-top:16px;font-size:18px;color:#999;\">Switch to Play mode to start the game.</p>\n            `;\n            gameWorld.appendChild(editDiv);\n        }\n\n        function setupPlayMode() {\n            // Game state\n            let servedCount = 0;\n            let score = 0;\n            let mistakes = 0;\n            let combo = 0;\n            let selectedColor = null;\n            let selectedAccessory = null;\n            let selectedWigStyle = null;\n            let appliedColor = null;\n            let placedAccessories = [];\n            let timerInterval = null;\n            let timeRemaining = config.settings.timePerCustomer;\n            let gameOver = false;\n            let currentCustomer = null;\n            let lastVoiceId = null;\n\n            const maxMistakes = config.settings.mistakesAllowed;\n            const wigStyles = ['bob', 'wavy', 'curly', 'pixie', 'braids', 'ponytail', 'space_buns'];\n            const accessoriesList = ['bow', 'flower', 'star', 'crown', 'heart', 'butterfly', 'pearl'];\n            const namesPool = [\"Lily\", \"Grace\", \"Zara\", \"Mia\", \"Sofia\", \"Ruby\", \"Chloe\", \"Emma\", \"Luna\", \"Aria\", \"Willow\", \"Harper\", \"Maya\", \"Ivy\", \"Nova\"];\n\n            function generateRandomCustomer() {\n                const style = wigStyles[Math.floor(Math.random() * wigStyles.length)];\n                const color = config.availableColors[Math.floor(Math.random() * config.availableColors.length)];\n                \n                // Difficulty scaling: more accessories as you serve more customers\n                const maxAcc = servedCount < 5 ? 1 : (servedCount < 12 ? 2 : 3);\n                const accCount = Math.floor(Math.random() * (maxAcc + 1));\n                const selectedAcc = [];\n                const pool = [...accessoriesList];\n                for (let i = 0; i < accCount; i++) {\n                    const idx = Math.floor(Math.random() * pool.length);\n                    selectedAcc.push(pool.splice(idx, 1)[0]);\n                }\n\n                return {\n                    customerName: namesPool[Math.floor(Math.random() * namesPool.length)],\n                    avatarId: 'customer_' + (Math.floor(Math.random() * 10) + 1),\n                    wigStyle: style,\n                    wigColor: color,\n                    accessories: selectedAcc\n                };\n            }\n\n            async function showGameOver() {\n                if (bgMusicSource) { \n                    try { bgMusicSource.stop(); } catch(e){} \n                    bgMusicSource = null; \n                }\n\n                const emoji = '\ud83d\ude22';\n                const title = 'Salon Closed';\n                const subtitle = `You served ${servedCount} customers!<br>Final Score: \u2b50 ${score}`;\n                \n                // Show initial overlay immediately with a loading state for the leaderboard\n                gameOverlay.innerHTML = `\n                    <div class=\"overlay-card\">\n                        <div class=\"overlay-title\">${emoji} ${title}</div>\n                        <div class=\"overlay-subtitle\">${subtitle}</div>\n                        <div id=\"leaderboard-display\" style=\"margin: 20px 0; min-height: 100px;\">\n                            <p style=\"font-family: 'Fredoka', sans-serif; color: #888;\">Fetching leaderboard...</p>\n                        </div>\n                        <button class=\"overlay-btn\" id=\"btn-restart\">Try Again</button>\n                    </div>\n                `;\n                gameOverlay.classList.add('visible');\n\n                document.getElementById('btn-restart').addEventListener('click', () => {\n                    gameOverlay.classList.remove('visible');\n                    restartGame();\n                });\n\n                // Fetch and update leaderboard status directly\n                try {\n                    const response = await lib.addPlayerScoreToLeaderboard(score, 10);\n                    const container = document.getElementById('leaderboard-display');\n                    if (!container) return;\n\n                    let leaderboardHtml = '';\n                    if (response.success) {\n                        leaderboardHtml += `<p style=\"font-family: 'Fredoka', sans-serif; font-size: 20px; color: var(--purple); margin-bottom: 12px;\">Your Rank: ${response.userRank !== null ? '#' + response.userRank : 'N/A'}</p>`;\n                        if (response.entries && response.entries.length > 0) {\n                            leaderboardHtml += `<h3 style=\"font-family: 'Fredoka', sans-serif; margin-bottom: 10px;\">Top Stylists</h3>\n                                <div style=\"text-align: left; max-height: 250px; overflow-y: auto; background: #FFF5F8; border-radius: 12px; padding: 12px; border: 2px solid var(--pink-light);\">\n                                    <ol style=\"margin: 0; padding-left: 24px; font-family: 'Inter', sans-serif;\">`;\n                            response.entries.forEach(entry => {\n                                const isUser = entry.username === 'You' || (response.userRank && entry.rank === response.userRank);\n                                leaderboardHtml += `<li style=\"padding: 6px 0; font-size: 18px; color: #444; border-bottom: 1px dashed #FFD1E1; ${isUser ? 'font-weight: bold; color: var(--pink);' : ''}\">\n                                    <span style=\"display:inline-block; min-width: 140px;\">${entry.username}</span> \n                                    <span style=\"color: var(--purple);\">\u2b50 ${entry.score}</span>\n                                </li>`;\n                            });\n                            leaderboardHtml += `</ol></div>`;\n                        }\n                    } else {\n                        leaderboardHtml = `<p style=\"color: #999;\">Could not load leaderboard.</p>`;\n                    }\n                    container.innerHTML = leaderboardHtml;\n                } catch (error) {\n                    lib.log(`Failed to submit score or fetch leaderboard: ${error.message}`);\n                    const container = document.getElementById('leaderboard-display');\n                    if (container) container.innerHTML = `<p style=\"color: #999;\">Leaderboard unavailable.</p>`;\n                }\n            }\n\n            async function showLeaderboard() {\n                gameOverlay.classList.add('visible');\n                gameOverlay.innerHTML = `\n                    <div class=\"overlay-card\">\n                        <div class=\"overlay-title\">\ud83c\udfc6 Leaderboard</div>\n                        <div id=\"leaderboard-display-full\" style=\"margin: 20px 0;\">\n                            <p>Loading...</p>\n                        </div>\n                        <button class=\"overlay-btn\" id=\"btn-back-to-game\" style=\"margin-top: 20px;\">Back to Game</button>\n                    </div>\n                `;\n\n                document.getElementById('btn-back-to-game').addEventListener('click', () => {\n                    gameOverlay.classList.remove('visible');\n                    restartGame();\n                });\n\n                try {\n                    const response = await lib.getTopNEntriesFromLeaderboard(10);\n                    const container = document.getElementById('leaderboard-display-full');\n                    if (!container) return;\n\n                    let leaderboardHtml = `<p style=\"font-family: 'Fredoka'; font-size: 20px; color: var(--purple);\">Your Rank: ${response.userRank !== null ? '#' + response.userRank : 'N/A'}</p>`;\n                    if (response.entries && response.entries.length > 0) {\n                        leaderboardHtml += `<div style=\"text-align: left; max-height: 400px; overflow-y: auto; background: #FFF5F8; border-radius: 12px; padding: 12px; border: 2px solid var(--pink-light); margin-top: 15px;\">\n                                <ol style=\"margin: 0; padding-left: 24px;\">`;\n                        response.entries.forEach(entry => {\n                            leaderboardHtml += `<li style=\"padding: 8px 0; font-size: 18px; color: #444; border-bottom: 1px dashed #FFD1E1;\">\n                                <span style=\"display:inline-block; min-width: 160px;\">${entry.username}</span> \n                                <span style=\"color: var(--purple);\">\u2b50 ${entry.score}</span>\n                            </li>`;\n                        });\n                        leaderboardHtml += `</ol></div>`;\n                    }\n                    container.innerHTML = leaderboardHtml;\n                } catch (error) {\n                    lib.log(`Failed to fetch leaderboard: ${error.message}`);\n                }\n            }\n\n            currentCustomer = generateRandomCustomer();\n\n            // Build DOM\n            if (imageCache['salon_background']) {\n                const bg = document.createElement('img');\n                bg.id = 'bg-image';\n                bg.src = imageCache['salon_background'].src;\n                gameWorld.appendChild(bg);\n            }\n\n            const overlay = document.createElement('div');\n            overlay.className = 'ui-overlay';\n            gameWorld.appendChild(overlay);\n\n            // Customer Area\n            const customerArea = document.createElement('div');\n            customerArea.className = 'customer-area';\n            overlay.appendChild(customerArea);\n\n            // Work Area\n            const workArea = document.createElement('div');\n            workArea.className = 'work-area';\n            overlay.appendChild(workArea);\n\n            // Tool Palette\n            const toolPalette = document.createElement('div');\n            toolPalette.className = 'tool-palette';\n            overlay.appendChild(toolPalette);\n\n            // Game Over Overlay\n            const gameOverlay = document.createElement('div');\n            gameOverlay.className = 'game-overlay';\n            gameWorld.appendChild(gameOverlay);\n\n            // Feedback popup\n            const feedback = document.createElement('div');\n            feedback.className = 'feedback-popup';\n            gameWorld.appendChild(feedback);\n\n            function showFeedback(text, color) {\n                feedback.textContent = text;\n                feedback.style.color = color || '#FFD93D';\n                feedback.classList.add('show');\n                setTimeout(() => feedback.classList.remove('show'), 1200);\n            }\n\n            function renderCustomerArea() {\n                const customer = currentCustomer;\n                const customerAssetId = customer.avatarId;\n                const wigAssetId = 'wig_' + customer.wigStyle;\n\n                const heartsStr = '\u2764\ufe0f'.repeat(Math.max(0, maxMistakes - mistakes)) + '\ud83d\udda4'.repeat(mistakes);\n\n                let accessoriesHtml = '';\n                if (customer.accessories && customer.accessories.length > 0) {\n                    customer.accessories.forEach(acc => {\n                        const accId = 'accessory_' + acc;\n                        if (imageCache[accId]) {\n                            accessoriesHtml += `<img src=\"${imageCache[accId].src}\" class=\"request-accessory-icon\" alt=\"${acc}\">`;\n                        }\n                    });\n                }\n\n                customerArea.innerHTML = `\n                    <div class=\"score-bar\">\n                        <span class=\"score-text\">\u2b50 ${score}</span>\n                        <span class=\"customer-counter\">Served: ${servedCount}</span>\n                        <span class=\"hearts\">${heartsStr}</span>\n                    </div>\n                    ${config.settings.timePerCustomer > 0 ? `<div class=\"timer-bar\"><div class=\"timer-fill\" id=\"timer-fill\" style=\"width:100%\"></div></div>` : ''}\n                    <div class=\"customer-display\">\n                        <div class=\"customer-avatar\">\n                            ${imageCache[customerAssetId] ? `<img src=\"${imageCache[customerAssetId].src}\" alt=\"Customer\">` : ''}\n                        </div>\n                        <div class=\"speech-bubble\">\n                            <div class=\"request-label\">${customer.customerName || 'Customer'} wants:</div>\n                            <div class=\"request-details\">\n                                ${imageCache[wigAssetId] ? `<img src=\"${imageCache[wigAssetId].src}\" class=\"request-wig-icon\">` : ''}\n                                <div class=\"request-color-swatch\" style=\"background:${customer.wigColor}\"></div>\n                                ${accessoriesHtml}\n                            </div>\n                        </div>\n                    </div>\n                `;\n            }\n\n            function renderWorkArea() {\n                const wigId = selectedWigStyle ? 'wig_' + selectedWigStyle : null;\n\n\n                let accessoriesHtml = '';\n                placedAccessories.forEach((acc, i) => {\n                    const accId = 'accessory_' + acc.type;\n                    if (imageCache[accId]) {\n                        accessoriesHtml += `<img src=\"${imageCache[accId].src}\" class=\"wig-accessory\" data-index=\"${i}\" style=\"top:${acc.y}px;left:${acc.x}px;\">`;\n                    }\n                });\n\n                let colorFilter = '';\n                if (appliedColor && wigId) {\n                    colorFilter = getColorFilter(appliedColor);\n                }\n\n                workArea.innerHTML = `\n                    <div class=\"wig-display\" id=\"wig-display\">\n                    ${wigId && imageCache[wigId] ? `<img src=\"${imageCache[wigId].src}\" class=\"wig-image\" style=\"${colorFilter}\">` : '<span style=\"font-family:Fredoka;font-size:24px;color:#aaa;\">Select a hair style</span>'}\n                        ${accessoriesHtml}\n                    </div>\n                `;\n\n\n                // Click on wig display to apply color or place accessory\n                const wigDisplay = workArea.querySelector('#wig-display');\n                if (wigDisplay) {\n                    wigDisplay.addEventListener('click', (e) => {\n                        if (selectedAccessory && selectedWigStyle) {\n                            const rect = wigDisplay.getBoundingClientRect();\n                            const x = e.clientX - rect.left - 28;\n                            const y = e.clientY - rect.top - 28;\n                            placedAccessories.push({ type: selectedAccessory, x, y });\n                            playSound('place_accessory_sound');\n                            renderWorkArea();\n                        } else if (selectedColor && selectedWigStyle) {\n                            appliedColor = selectedColor;\n                            playSound('color_apply_sound');\n                            renderWorkArea();\n                        }\n                    });\n                }\n\n                // Remove accessories on click\n                workArea.querySelectorAll('.wig-accessory').forEach(el => {\n                    el.addEventListener('click', (e) => {\n                        e.stopPropagation();\n                        const idx = parseInt(el.dataset.index);\n                        placedAccessories.splice(idx, 1);\n                        renderWorkArea();\n                    });\n                });\n            }\n\n            function getColorFilter(hexColor) {\n                // Convert hex to RGB\n                const r = parseInt(hexColor.slice(1, 3), 16) / 255;\n                const g = parseInt(hexColor.slice(3, 5), 16) / 255;\n                const b = parseInt(hexColor.slice(5, 7), 16) / 255;\n\n                // Create a color matrix that maps grayscale to the target color\n                // Brighter and shinier version: boost luminosity and contrast\n                const matrix = `\n                    ${r * 1.2} 0 0 0 0.05\n                    0 ${g * 1.2} 0 0 0.05\n                    0 0 ${b * 1.2} 0 0.05\n                    0 0 0 1 0\n                `;\n\n                // Generate a unique ID for the filter\n                const filterId = `colorFilter-${hexColor.replace('#', '')}`;\n\n                // Append SVG filter to the DOM if it doesn't exist\n                if (!document.getElementById(filterId)) {\n                    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n                    svg.style.position = 'absolute';\n                    svg.style.width = '0';\n                    svg.style.height = '0';\n                    svg.innerHTML = `\n                        <filter id=\"${filterId}\" color-interpolation-filters=\"sRGB\">\n                            <feColorMatrix type=\"matrix\" values=\"${matrix}\"/>\n                        </filter>\n                    `;\n                    gameWorld.appendChild(svg);\n                }\n\n                return `filter: url(#${filterId});`;\n            }\n\n            function renderToolPalette() {\n                const colors = config.availableColors;\n\n                let colorsHtml = '<div class=\"color-grid\">';\n                colors.forEach(color => {\n                    const sel = selectedColor === color ? 'selected' : '';\n                    colorsHtml += `<div class=\"color-swatch ${sel}\" data-color=\"${color}\" style=\"background:${color}\"></div>`;\n                });\n                colorsHtml += '</div>';\n\n                let wigStylesHtml = '<div class=\"accessory-grid\">'; // Reusing accessory-grid for similar layout\n                ['bob', 'wavy', 'curly', 'pixie', 'braids', 'ponytail', 'space_buns'].forEach(style => {\n                    const id = 'wig_' + style;\n                    const selected = selectedWigStyle === style ? 'selected' : '';\n                    wigStylesHtml += `<div class=\"accessory-btn ${selected}\" data-style=\"${style}\">\n                        ${imageCache[id] ? `<img src=\"${imageCache[id].src}\">` : style}\n                    </div>`;\n                });\n                wigStylesHtml += '</div>';\n\n                let accessoriesHtml = '<div class=\"accessory-grid\">';\n                ['bow', 'flower', 'star', 'crown', 'heart', 'butterfly', 'pearl'].forEach(acc => {\n                    const accId = 'accessory_' + acc;\n                    const sel = selectedAccessory === acc ? 'selected' : '';\n                    accessoriesHtml += `<div class=\"accessory-btn ${sel}\" data-accessory=\"${acc}\">\n                        ${imageCache[accId] ? `<img src=\"${imageCache[accId].src}\">` : acc}\n                    </div>`;\n                });\n                accessoriesHtml += '</div>';\n\n                toolPalette.innerHTML = `\n                    <div class=\"palette-section\">\n                        <div class=\"palette-label\">Hair Style</div>\n                        ${wigStylesHtml}\n                    </div>\n                    <div class=\"palette-section\">\n                        <div class=\"palette-label\">Colors</div>\n                        ${colorsHtml}\n                    </div>\n                    <div class=\"palette-section\">\n                        <div class=\"palette-label\">Accessories</div>\n                        ${accessoriesHtml}\n                    </div>\n                    <div class=\"action-buttons\">\n                        <button class=\"btn btn-clear\" id=\"btn-clear\">Clear</button>\n                        <button class=\"btn btn-present\" id=\"btn-present\">Complete Look \u2728</button>\n                    </div>\n                `;\n\n                // Events\n                toolPalette.querySelectorAll('.color-swatch').forEach(sw => {\n                    sw.addEventListener('click', () => {\n                        selectedColor = sw.dataset.color;\n                        selectedAccessory = null;\n                        \n                        // Apply color instantly if a wig is selected\n                        if (selectedWigStyle) {\n                            appliedColor = selectedColor;\n                            playSound('color_apply_sound');\n                            renderWorkArea();\n                        }\n                        \n                        renderToolPalette();\n                    });\n                });\n\n                toolPalette.querySelectorAll('.accessory-btn').forEach(btn => {\n                    btn.addEventListener('click', () => {\n                        if (btn.dataset.accessory) {\n                            if (selectedAccessory === btn.dataset.accessory) {\n                                selectedAccessory = null;\n                            } else {\n                                selectedAccessory = btn.dataset.accessory;\n                                selectedColor = null;\n                            }\n                        } else if (btn.dataset.style) {\n                            if (selectedWigStyle === btn.dataset.style) {\n                                selectedWigStyle = null;\n                            } else {\n                                selectedWigStyle = btn.dataset.style;\n                                selectedColor = null;\n                                selectedAccessory = null;\n                            }\n                        }\n                        renderToolPalette();\n                        renderWorkArea();\n                    });\n                });\n\n                document.getElementById('btn-clear').addEventListener('click', clearWig);\n                document.getElementById('btn-present').addEventListener('click', presentWig);\n            }\n\n            function clearWig() {\n                appliedColor = null;\n                placedAccessories = [];\n                selectedWigStyle = null;\n                renderWorkArea();\n            }\n\n            function playRandomHappyVoice() {\n                const voices = ['voice_happy_1', 'voice_happy_2', 'voice_happy_3', 'voice_happy_5', 'voice_happy_6'];\n                let availableVoices = voices.filter(v => v !== lastVoiceId);\n                const randomVoice = availableVoices[Math.floor(Math.random() * availableVoices.length)];\n                lastVoiceId = randomVoice;\n                const voiceSource = playSound(randomVoice);\n                // Keep the slightly faster playback for excitement as requested previously\n                if (voiceSource) voiceSource.playbackRate.value = 1.25;\n            }\n\n            function presentWig() {\n                if (gameOver) return;\n                const customer = currentCustomer;\n\n                // Score calculation\n                let points = 0;\n                let perfect = true;\n\n                // Check wig style\n                if (selectedWigStyle === customer.wigStyle) {\n                    points += 100;\n                } else {\n                    perfect = false;\n                }\n\n                // Check color\n                if (appliedColor && appliedColor.toLowerCase() === customer.wigColor.toLowerCase()) {\n                    points += 100;\n                } else if (appliedColor) {\n                    // Partial credit for having a color\n                    points += 30;\n                    perfect = false;\n                } else {\n                    perfect = false;\n                }\n\n                // Check accessories\n                const requiredAcc = customer.accessories || [];\n                const placedTypes = placedAccessories.map(a => a.type);\n                let accMatch = 0;\n                requiredAcc.forEach(acc => {\n                    if (placedTypes.includes(acc)) accMatch++;\n                });\n                if (requiredAcc.length > 0) {\n                    if (accMatch === requiredAcc.length && placedTypes.length === requiredAcc.length) {\n                        points += 100;\n                    } else {\n                        points += Math.round((accMatch / requiredAcc.length) * 60);\n                        perfect = false;\n                    }\n                } else if (placedAccessories.length > 0) {\n                    // Penalize extra accessories when none needed\n                    perfect = false;\n                }\n\n                // Perfect bonus\n                if (perfect) {\n                    combo++;\n                    points += config.settings.perfectMatchBonus;\n                    points *= (1 + combo * 0.1);\n                    points = Math.round(points);\n                    showFeedback('\ud83d\udc96 PERFECT!', '#FF6B9D');\n                    playSound('success_sound');\n                    playRandomHappyVoice();\n                    servedCount++;\n                } else if (points >= 100) {\n                    combo = 0;\n                    showFeedback('\ud83d\udc4d Nice!', '#FFD93D');\n                    playSound('success_sound');\n                    playRandomHappyVoice();\n                    servedCount++;\n                } else {\n                    combo = 0;\n                    mistakes++;\n                    showFeedback('Try harder!', '#FF6347');\n                    playSound('customer_unhappy_sound');\n                }\n\n                score += points;\n\n                // Stop timer\n                if (timerInterval) { clearInterval(timerInterval); timerInterval = null; }\n\n                // Check game over\n                if (mistakes >= maxMistakes) {\n                    gameOver = true;\n                    showGameOver();\n                    return;\n                }\n\n                // Reset for next customer\n                setTimeout(() => {\n                    currentCustomer = generateRandomCustomer();\n                    resetForNextCustomer();\n                }, 1000);\n            }\n\n            function resetForNextCustomer() {\n                selectedColor = null;\n                selectedAccessory = null;\n                selectedWigStyle = null;\n                appliedColor = null;\n                placedAccessories = [];\n                timeRemaining = config.settings.timePerCustomer;\n\n                renderCustomerArea();\n                renderWorkArea();\n                renderToolPalette();\n                startTimer();\n            }\n\n            function startTimer() {\n                if (config.settings.timePerCustomer <= 0) return;\n                timeRemaining = config.settings.timePerCustomer;\n\n                if (timerInterval) clearInterval(timerInterval);\n                timerInterval = setInterval(() => {\n                    timeRemaining--;\n                    const pct = (timeRemaining / config.settings.timePerCustomer) * 100;\n                    const fill = document.getElementById('timer-fill');\n                    if (fill) fill.style.width = pct + '%';\n\n                    if (timeRemaining <= 0) {\n                        clearInterval(timerInterval);\n                        timerInterval = null;\n                        // Time up - customer unhappy\n                        mistakes++;\n                        showFeedback('\u23f0 Too slow!', '#FF6347');\n                        playSound('customer_unhappy_sound');\n\n                        if (mistakes >= maxMistakes) {\n                            gameOver = true;\n                            showGameOver();\n                            return;\n                        }\n                        \n                        setTimeout(() => {\n                            currentCustomer = generateRandomCustomer();\n                            resetForNextCustomer();\n                        }, 1000);\n                    }\n                }, 1000);\n            }\n\n            function restartGame() {\n                servedCount = 0;\n                score = 0;\n                mistakes = 0;\n                combo = 0;\n                gameOver = false;\n                currentCustomer = generateRandomCustomer();\n                resetForNextCustomer();\n                // Ensure music restarts if it was stopped\n                if (!bgMusicSource) {\n                    playSound('background_music');\n                }\n            }\n\n            // Keyboard shortcuts\n            document.addEventListener('keydown', (e) => {\n                if (gameOver) return;\n                const num = parseInt(e.key);\n                if (num >= 1 && num <= config.availableColors.length) {\n                    selectedColor = config.availableColors[num - 1];\n                    selectedAccessory = null;\n                    renderToolPalette();\n                }\n                if (e.key === ' ' || e.key === 'Enter') {\n                    e.preventDefault();\n                    presentWig();\n                }\n                if (e.key === 'r' || e.key === 'R') clearWig();\n            });\n\n            function showIntro() {\n                gameOverlay.innerHTML = `\n                    <div class=\"overlay-card\">\n                        <div class=\"overlay-title rainbow-text\">\u2728 Hair Makeover \u2728</div>\n                        <div class=\"overlay-subtitle\">Welcome to your fabulous salon! \ud83d\udc87\u200d\u2640\ufe0f<br>Ready to create stunning looks for our stylish clients?</div>\n                        <button class=\"overlay-btn\" id=\"btn-start-game\">Start Styling</button>\n                    </div>\n                `;\n                gameOverlay.classList.add('visible');\n\n                document.getElementById('btn-start-game').addEventListener('click', () => {\n                    gameOverlay.classList.remove('visible');\n                    startTimer();\n                    playSound('background_music');\n                });\n            }\n\n            // Initial render\n            renderCustomerArea();\n            renderWorkArea();\n            renderToolPalette();\n            showIntro();\n        }\n    }\n    </script>\n</body>\n</html>", "game_config": "{\n  \"settings\": {\n    \"customerCount\": 5,\n    \"timePerCustomer\": 60,\n    \"mistakesAllowed\": 3,\n    \"perfectMatchBonus\": 100,\n    \"showColorHint\": true,\n    \"showAccessoryHint\": true\n  },\n  \"availableColors\": [\n    \"#E8E8E8\",\n    \"#8B4513\",\n    \"#D4A574\",\n    \"#C04000\",\n    \"#FF69B4\",\n    \"#9B59B6\",\n    \"#800020\"\n  ],\n  \"customers\": [\n    {\n      \"customerName\": \"Lily\",\n      \"wigStyle\": \"bob\",\n      \"wigColor\": \"#FF69B4\",\n      \"accessories\": [\n        \"heart\"\n      ]\n    },\n    {\n      \"customerName\": \"Grace\",\n      \"wigStyle\": \"wavy\",\n      \"wigColor\": \"#D4A574\",\n      \"accessories\": [\n        \"bow\"\n      ]\n    },\n    {\n      \"customerName\": \"Zara\",\n      \"wigStyle\": \"space_buns\",\n      \"wigColor\": \"#9B59B6\",\n      \"accessories\": []\n    },\n    {\n      \"customerName\": \"Mia\",\n      \"wigStyle\": \"braids\",\n      \"wigColor\": \"#800020\",\n      \"accessories\": [\n        \"flower\",\n        \"star\"\n      ]\n    },\n    {\n      \"customerName\": \"Sofia\",\n      \"wigStyle\": \"ponytail\",\n      \"wigColor\": \"#E74C3C\",\n      \"accessories\": [\n        \"crown\",\n        \"pearl\"\n      ]\n    }\n  ]\n}", "game_design_document": "## Core Game Loop and Mechanics\n\n**Wig Whimsy Salon** is a creative styling game where players run a wig salon, fulfilling customer orders by selecting, coloring, and decorating wigs to match specific requests.\n\n### Moment-to-Moment Gameplay\n1. **Customer Arrival**: A customer enters with a speech bubble showing their desired wig (style, color, and optional accessories)\n2. **Wig Selection**: Player taps/clicks to select the matching wig style from available options\n3. **Coloring**: Player applies colors using a palette - can paint different sections of the wig\n4. **Decoration**: Player adds optional accessories (bows, flowers, clips) if requested\n5. **Presentation**: Player presents the finished wig to the customer\n6. **Feedback**: Customer rates the wig based on accuracy (hearts/stars), player earns points\n7. **Next Customer**: New customer arrives with a new request\n\n### Progression & Engagement\n- **Score System**: Points awarded based on accuracy (correct style, color matching, accessories)\n- **Combo System**: Consecutive perfect wigs increase score multiplier\n- **Time Pressure**: Gentle timer creates urgency without stress (customers get slightly impatient)\n- **Increasing Complexity**: Later customers request more complex color patterns and multiple accessories\n\n### Win/Lose Conditions\n- **Win**: Successfully serve a target number of customers (e.g., 10 customers) with a minimum average satisfaction\n- **Lose**: Three customers leave unhappy (due to wrong wig or timeout), or fail to meet the target score\n- **Replayability**: Try to beat high scores, achieve perfect ratings, or complete orders faster\n\n### What Makes It Compelling\n- **Creative Expression**: Freedom to experiment with colors and styles\n- **Satisfying Feedback**: Immediate visual results and happy customer reactions\n- **Accessible Challenge**: Easy to learn, but mastering color matching and speed takes skill\n- **Relaxing Pace**: No harsh penalties, focus on creativity and fun\n\n## Starting Scope\n\nThe first iteration will focus on a **simple, polished core experience**:\n\n### Implement First (V1)\n- **3 wig styles**: Short bob, long wavy, curly afro\n- **Basic color palette**: 8 colors (natural tones + fun colors like pink, blue, purple)\n- **Simple coloring mechanic**: Tap/click to fill entire wig with selected color\n- **3 accessory types**: Bow, flower, star clip (optional additions)\n- **5 customers**: Sequential customers with clear visual requests\n- **Basic scoring**: Points for correct style, color match, and accessories\n- **Simple UI**: Customer display area (top), work area (middle), tool palette (bottom)\n- **Win condition**: Successfully serve all 5 customers\n- **Lose condition**: 2 customers leave unhappy\n\n### Save for Later Iterations\n- Multi-section coloring (highlights, tips, roots)\n- More wig styles and accessories\n- Timed challenge mode\n- Customer personality types with special preferences\n- Salon upgrades and unlockables\n- Advanced color mixing\n\n## Game Perspective\n\n**Fixed-screen** perspective with a clear vertical layout optimized for mobile portrait:\n- Top third: Customer display with speech bubble showing their request\n- Middle third: Wig styling work area (large, interactive)\n- Bottom third: Tool palette (color swatches, accessories, action buttons)\n\n## Game World and Level Design\n\n### Setting\nA cozy, colorful wig salon with a cheerful atmosphere. The game takes place entirely within the salon workspace.\n\n### Layout\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502   CUSTOMER AREA         \u2502\n\u2502   [Customer Avatar]     \u2502\n\u2502   [Speech Bubble:       \u2502\n\u2502    Desired Wig]         \u2502\n\u2502                         \u2502\n\u2502   Score: XXX  \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f    \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502   WORK AREA             \u2502\n\u2502                         \u2502\n\u2502   [Large Wig Display]   \u2502\n\u2502   (Interactive)         \u2502\n\u2502                         \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502   TOOL PALETTE          \u2502\n\u2502   [Color Swatches]      \u2502\n\u2502   [Accessories]         \u2502\n\u2502   [Present Button]      \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### Single Level Structure\nSince this is a salon management game, there's one continuous level with 5 sequential customers:\n1. **Customer 1**: Simple request (one solid color, no accessories)\n2. **Customer 2**: Solid color + one accessory\n3. **Customer 3**: Different wig style, solid color\n4. **Customer 4**: Solid color + two accessories\n5. **Customer 5**: Most complex - specific style, color, and accessories\n\n## Edit Mode Design\n\nPlayers can customize various aspects of the salon experience:\n\n### Editable Properties\n\n**Customer Requests** (per customer):\n- `wigStyle`: Choice of available wig styles (\"bob\", \"wavy\", \"curly\")\n- `wigColor`: Hex color code for desired wig color\n- `accessories`: Array of accessory types requested ([\"bow\"], [\"flower\", \"star\"], etc.)\n- `customerName`: Name displayed for the customer\n- `customerAvatar`: Reference to customer character asset\n\n**Game Settings**:\n- `customerCount`: Number of customers to serve (3-10)\n- `timePerCustomer`: Seconds allowed per customer (30-120, or 0 for no timer)\n- `mistakesAllowed`: How many unhappy customers before game over (1-5)\n- `perfectMatchBonus`: Extra points for exact matches (50-200)\n\n**Color Palette**:\n- `availableColors`: Array of hex color codes players can use\n- Can add/remove colors or change the palette entirely\n\n**Difficulty Settings**:\n- `showColorHint`: Boolean - whether to show the exact color name\n- `showAccessoryHint`: Boolean - whether to highlight required accessories\n\n### Constraints\n- Must have at least 2 wig styles available\n- Must have at least 4 colors in palette\n- Customer count minimum of 3, maximum of 15\n- Time per customer: minimum 20 seconds if enabled\n- At least 1 mistake allowed before game over\n\n## Control Design\n\n### Mobile (Touch) Controls\n**Primary Interaction**: Tap-based interface optimized for portrait mode\n\n1. **Wig Style Selection**:\n   - Tap wig style icons at the start of each customer\n   - Selected style appears in work area\n\n2. **Color Selection**:\n   - Tap color swatch in bottom palette to select\n   - Selected color shows highlight/border\n   - Tap the wig in work area to apply color\n\n3. **Accessory Placement**:\n   - Tap accessory icon to select\n   - Tap location on wig to place accessory\n   - Tap placed accessory to remove it\n\n4. **Action Buttons**:\n   - Large \"Present Wig\" button to submit to customer\n   - \"Clear\" button to reset current wig\n\n### Desktop (Keyboard/Mouse) Controls\n**Primary Interaction**: Click-based, identical to touch\n\n1. **Wig Style Selection**:\n   - Click wig style icons\n\n2. **Color Selection**:\n   - Click color swatch to select\n   - Click wig to apply color\n\n3. **Accessory Placement**:\n   - Click accessory icon to select\n   - Click on wig to place\n   - Click placed accessory to remove\n\n4. **Action Buttons**:\n   - Click \"Present Wig\" to submit\n   - Click \"Clear\" to reset\n\n**Optional Keyboard Shortcuts**:\n- Number keys 1-8: Quick select colors\n- Space: Present wig\n- R: Reset/clear current wig\n\n### UI Layout (Bottom Third - Touch Optimized)\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Color Palette           \u2502\n\u2502 [\u25a0][\u25a0][\u25a0][\u25a0][\u25a0][\u25a0][\u25a0][\u25a0]\u2502 (96x96px swatches)\n\u2502                         \u2502\n\u2502 Accessories             \u2502\n\u2502 [\ud83c\udf80][\ud83c\udf38][\u2b50]            \u2502 (96x96px buttons)\n\u2502                         \u2502\n\u2502 [  Clear  ][Present Wig]\u2502 (Large buttons)\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\nAll interactive elements are minimum 96x96 pixels for easy touch targeting.\n\n## Art Style and Visual Theme\n\n### Overall Style\n**Cute, colorful cartoon aesthetic** with a modern, playful salon vibe. Think bright pastels, smooth shapes, and cheerful characters.\n\n### Visual Direction\n- **Art Style**: Cartoon/illustrated style with clean lines and soft shading\n- **Color Palette**: Bright, saturated colors with pastel backgrounds\n- **Mood**: Cheerful, welcoming, creative, and fun\n- **Character Design**: Diverse, friendly customers with expressive faces\n\n### Asset Specifications\n\n**Wigs**:\n- Large, detailed illustrations showing texture and volume\n- Transparent backgrounds for easy color application\n- Consistent size (~400x400px in work area)\n- Clear silhouettes for each style\n\n**Customers**:\n- Bust portraits showing head and shoulders\n- Diverse representation (various skin tones, features, ages)\n- Friendly, expressive faces\n- Consistent cartoon style\n\n**Accessories**:\n- Small, decorative items that stand out against wigs\n- Cute, stylized designs\n- Clear shapes for easy recognition\n\n**UI Elements**:\n- Soft rounded buttons\n- Pastel background colors\n- Clear, readable fonts (playful but legible)\n\n### Technical Rendering\n- **Wigs**: Generated image assets (complex shapes, need texture)\n- **Customers**: Generated image assets (character illustrations)\n- **Accessories**: Generated image assets (detailed decorative items)\n- **UI Backgrounds**: CSS (simple rounded rectangles, gradients)\n- **Buttons**: CSS with generated icon assets\n- **Color Swatches**: CSS (simple colored circles/squares)", "persistent_storage_config": {"leaderboard": {"sort_ascending": false}}, "game_metadata": {"game_id": "01KVEQVAYQ9TH5WEET175ZG512", "title": "Hair Makeover ", "description": "Design and color fabulous styles for demanding clients in your very own salon, mixing and matching styles and hues!", "thumbnail_url": "https://d2oir5eh8rty2e.cloudfront.net/assets/images/thumbnail_2a4a1f82-82b9-4d10-bf75-b763d9e59e83.webp", "created_at": 1781832502, "updated_at": 1781871568053.482, "art_style": null}, "task_plan": null}