diff --git a/analyze_key_images.py b/analyze_key_images.py new file mode 100644 index 0000000..a4c5022 --- /dev/null +++ b/analyze_key_images.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +from PIL import Image +import numpy as np +from collections import Counter +import colorsys + +def rgb_to_hex(rgb): + return '#{:02x}{:02x}{:02x}'.format(rgb[0], rgb[1], rgb[2]) + +def get_dominant_colors(image_path, num_colors=8): + try: + # Open image and convert to RGB + img = Image.open(image_path).convert('RGB') + + # Resize image to make processing faster + img = img.resize((150, 150)) + + # Get colors + pixels = np.array(img) + pixels = pixels.reshape(-1, 3) + + # Count most common colors + count = Counter(map(tuple, pixels)) + most_common = count.most_common(num_colors) + + # Convert to hex + return [rgb_to_hex(color) for color, count in most_common] + except Exception as e: + print(f"Error processing {image_path}: {e}") + return [] + +# List of key images to analyze +key_images = [ + "/home/billy/code/viber/src/assets/logo.png", + "/home/billy/code/viber/src/assets/mouse.png", + "/home/billy/code/viber/src/assets/keyboard.png", + "/home/billy/code/viber/src/assets/monitor.png", + "/home/billy/code/viber/src/assets/data center.png", + "/home/billy/code/viber/src/assets/galaxy.png" +] + +print("Key Image Analysis:\n") + +for image_path in key_images: + image_name = image_path.split("/")[-1] + colors = get_dominant_colors(image_path) + + print(f"{image_name}:") + for color in colors: + # Convert to RGB for displaying color names + h = color.lstrip('#') + r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) + h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255) + + # Determine color category + category = "unknown" + if s < 0.15: + if v < 0.15: + category = "black" + elif v > 0.85: + category = "white" + else: + category = "gray" + else: + if h < 0.05 or h > 0.95: + category = "red" + elif 0.05 <= h < 0.15: + category = "orange" + elif 0.15 <= h < 0.25: + category = "yellow" + elif 0.25 <= h < 0.5: + category = "green" + elif 0.5 <= h < 0.65: + category = "cyan" + elif 0.65 <= h < 0.75: + category = "blue" + elif 0.75 <= h < 0.95: + category = "purple" + + print(f" {color} - {category} (HSV: {h*360:.1f}, {s*100:.1f}%, {v*100:.1f}%)") + print("") \ No newline at end of file diff --git a/color_analysis.py b/color_analysis.py new file mode 100644 index 0000000..6720b2b --- /dev/null +++ b/color_analysis.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +from PIL import Image +import numpy as np +import os +from collections import Counter +import colorsys + +def rgb_to_hex(rgb): + return '#{:02x}{:02x}{:02x}'.format(rgb[0], rgb[1], rgb[2]) + +def get_dominant_colors(image_path, num_colors=5): + # Open image and convert to RGB + img = Image.open(image_path).convert('RGB') + + # Resize image to make processing faster + img = img.resize((100, 100)) + + # Get colors + pixels = np.array(img) + pixels = pixels.reshape(-1, 3) + + # Count most common colors + count = Counter(map(tuple, pixels)) + most_common = count.most_common(num_colors) + + # Convert to hex + return [rgb_to_hex(color) for color, count in most_common] + +def get_color_stats(hex_color): + # Convert hex to RGB + h = hex_color.lstrip('#') + r, g, b = tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) + + # Convert RGB to HSV + h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255) + + # Determine if color is dark or light + is_dark = v < 0.5 + + # Determine if color is vibrant + is_vibrant = s > 0.5 and v > 0.5 + + # Determine basic color category + if s < 0.15: + if v < 0.15: + category = "black" + elif v > 0.85: + category = "white" + else: + category = "gray" + else: + if h < 0.05 or h > 0.95: + category = "red" + elif 0.05 <= h < 0.15: + category = "orange" + elif 0.15 <= h < 0.25: + category = "yellow" + elif 0.25 <= h < 0.5: + category = "green" + elif 0.5 <= h < 0.65: + category = "cyan" + elif 0.65 <= h < 0.75: + category = "blue" + elif 0.75 <= h < 0.95: + category = "purple" + + return { + "hex": hex_color, + "rgb": (r, g, b), + "hsv": (h*360, s*100, v*100), + "is_dark": is_dark, + "is_vibrant": is_vibrant, + "category": category + } + +def analyze_assets(directory): + assets = [] + + # Find all PNG files + for file in os.listdir(directory): + if file.endswith('.png'): + assets.append(os.path.join(directory, file)) + + # Get color data + color_data = {} + all_colors = [] + + for asset in assets: + name = os.path.basename(asset) + dominant_colors = get_dominant_colors(asset) + color_data[name] = dominant_colors + all_colors.extend(dominant_colors) + + # Count most common colors across all assets + color_counter = Counter(all_colors) + most_common_colors = color_counter.most_common(10) + + # Get stats for most common colors + color_stats = [get_color_stats(color) for color, _ in most_common_colors] + + # Find primary and accent colors + primary_colors = [] + accent_colors = [] + + for stat in color_stats: + if stat["category"] not in ["black", "white", "gray"]: + if stat["is_vibrant"]: + accent_colors.append(stat) + else: + primary_colors.append(stat) + + # Find background colors (darker colors) + background_colors = [stat for stat in color_stats if stat["is_dark"]] + + return { + "individual_assets": color_data, + "most_common_colors": [color for color, _ in most_common_colors], + "color_stats": color_stats, + "primary_colors": primary_colors[:3], + "accent_colors": accent_colors[:3], + "background_colors": background_colors[:3] + } + +if __name__ == "__main__": + assets_dir = "/home/billy/code/viber/src/assets" + results = analyze_assets(assets_dir) + + print("Color Analysis Results:\n") + + print("Most Common Colors:") + for color in results["most_common_colors"]: + print(f" {color}") + + print("\nPrimary Colors:") + for color in results["primary_colors"]: + print(f" {color['hex']} - {color['category']}") + + print("\nAccent Colors:") + for color in results["accent_colors"]: + print(f" {color['hex']} - {color['category']}") + + print("\nBackground Colors:") + for color in results["background_colors"]: + print(f" {color['hex']} - {color['category']}") + + print("\nDetailed Color Stats:") + for i, stat in enumerate(results["color_stats"][:5]): + print(f"Color {i+1}:") + print(f" Hex: {stat['hex']}") + print(f" RGB: {stat['rgb']}") + print(f" HSV: {stat['hsv']}") + print(f" Category: {stat['category']}") + print(f" Dark: {stat['is_dark']}") + print(f" Vibrant: {stat['is_vibrant']}") + print("") \ No newline at end of file diff --git a/public/favicon.png b/public/favicon.png new file mode 100644 index 0000000..9e33e8b Binary files /dev/null and b/public/favicon.png differ diff --git a/src/App.tsx b/src/App.tsx index 9b61f79..9476bf6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -88,7 +88,7 @@ function App() { - - + + Welcome to ClickerCorp™ - + Employment Agreement @@ -149,7 +149,7 @@ function App() { - + Controls & Operations @@ -158,13 +158,13 @@ function App() { - + (Please note: This position is unpaid and offers exposure as compensation) setAgreedToTerms(e.target.checked)} > @@ -172,9 +172,9 @@ function App() { - + diff --git a/src/components/NextBuildingPreview.tsx b/src/components/NextBuildingPreview.tsx index ea8bfb9..4c2b08f 100644 --- a/src/components/NextBuildingPreview.tsx +++ b/src/components/NextBuildingPreview.tsx @@ -34,27 +34,28 @@ export function NextBuildingPreview() { return ( - {info.title} - Locked + {info.title} + Locked - {info.description} + {info.description} - Cost: {formatNumber(info.cost)} points - Level Required: {info.levelRequirement} + Cost: {formatNumber(info.cost)} points + Level Required: {info.levelRequirement} - - Production: - Points: {formatNumber(info.production.points || 0)}/s + + Production: + Points: {formatNumber(info.production.points || 0)}/s diff --git a/src/components/ResetButton.tsx b/src/components/ResetButton.tsx index 685e316..f5e3c1c 100644 --- a/src/components/ResetButton.tsx +++ b/src/components/ResetButton.tsx @@ -38,8 +38,8 @@ export function ResetButton() { onClose={onClose} > - - + + Reset Game @@ -48,7 +48,7 @@ export function ResetButton() { - @@ -118,27 +120,27 @@ export function ResourceDisplay() { - + {/* Level */} - Level - {playerLevel} + Level + {playerLevel} {/* Progress to next level */} - Level {playerLevel} - Level {playerLevel + 1} + Level {playerLevel} + Level {playerLevel + 1} diff --git a/src/components/SoundToggleButton.tsx b/src/components/SoundToggleButton.tsx index 13ffec0..99087d5 100644 --- a/src/components/SoundToggleButton.tsx +++ b/src/components/SoundToggleButton.tsx @@ -20,7 +20,7 @@ export function SoundToggleButton() { icon={{soundOn ? '🔊' : '🔇'}} onClick={handleToggle} variant="ghost" - colorScheme="cyan" + colorScheme="brand" size="md" /> diff --git a/src/theme.ts b/src/theme.ts index cb852aa..e9a29b7 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -1,22 +1,145 @@ import { extendTheme } from '@chakra-ui/react' +// Color palette based on asset analysis but with improved contrast +const colors = { + brand: { + // Main teal/cyan color found in assets + 50: '#e3f9fb', + 100: '#c5eef1', + 200: '#a1e0e5', + 300: '#7ad0d7', + 400: '#51bec7', + 500: '#29686c', // Our primary accent from analysis + 600: '#1c5458', // Darker variant + 700: '#183d3f', // From keyboard.png + 800: '#113738', // From mouse.png + 900: '#0f1e41', // From logo.png - more blue variant + }, + background: { + primary: '#000101', // Almost black with slight cyan tint + secondary: '#0a141e', // Darker blue for better contrast + tertiary: '#122c2e', // Darker cyan for cards + card: '#112233', // Darker blue to contrast with teal images + highlight: '#1d4244', // For hover states and highlights + cardOverlay: 'rgba(17, 34, 51, 0.85)', // Semi-transparent overlay for text on images + }, + text: { + primary: '#ffffff', + secondary: '#a1e0e5', // Light brand color for secondary text + accent: '#51bec7', // Brighter cyan for accents and highlights + muted: '#718096', // For less important text + dark: '#0a141e', // Dark text for light backgrounds + } +} + const theme = extendTheme({ config: { initialColorMode: 'dark', useSystemColorMode: false, }, + colors, styles: { global: { body: { - bg: 'gray.900', - color: 'white', + bg: colors.background.primary, + color: colors.text.primary, }, }, }, components: { Button: { defaultProps: { - colorScheme: 'blue', + colorScheme: 'brand', + }, + variants: { + solid: { + bg: 'brand.500', + color: 'white', + _hover: { + bg: 'brand.600', + }, + }, + outline: { + borderColor: 'brand.300', + color: 'text.primary', + _hover: { + bg: 'background.highlight', + }, + }, + ghost: { + color: 'brand.300', + _hover: { + bg: 'background.highlight', + } + } + }, + }, + Box: { + variants: { + card: { + bg: 'background.card', + borderRadius: 'lg', + boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.24)', + borderColor: 'brand.700', + borderWidth: '1px', + transition: 'all 0.2s ease-in-out', + _hover: { + transform: 'translateY(-2px)', + boxShadow: '0 6px 10px -1px rgba(0, 0, 0, 0.4), 0 4px 6px -1px rgba(0, 0, 0, 0.3)', + }, + }, + }, + }, + Progress: { + baseStyle: { + filledTrack: { + bg: 'brand.400', + }, + track: { + bg: 'background.highlight', + }, + }, + }, + Tooltip: { + baseStyle: { + bg: 'background.secondary', + color: 'text.secondary', + borderColor: 'brand.700', + borderWidth: '1px', + }, + }, + Heading: { + baseStyle: { + color: 'text.secondary', + }, + }, + Text: { + variants: { + accent: { + color: 'text.accent', + }, + secondary: { + color: 'text.secondary', + }, + muted: { + color: 'text.muted', + }, + }, + }, + Modal: { + baseStyle: { + dialog: { + bg: 'background.secondary', + boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.5), 0 4px 6px -2px rgba(0, 0, 0, 0.4)', + borderWidth: '1px', + borderColor: 'brand.700', + }, + header: { + color: 'text.secondary', + }, + body: { + color: 'text.primary', + }, }, }, },