def extract_css_properties(html, url):
    """Extract CSS properties like colors and fonts from HTML"""
    if not BS4_AVAILABLE:
        print("BeautifulSoup not available, can't extract CSS properties")
        return {
            "colors": {
                "background": ["rgb(255, 255, 255)", "rgb(249, 250, 251)"],
                "text": ["rgb(31, 41, 55)", "rgb(55, 65, 81)"],
                "accent": ["rgb(37, 99, 235)", "rgb(59, 130, 246)"]
            },
            "fonts": ["Arial, sans-serif", "Helvetica, sans-serif"],
            "images": []
        }
    
    try:
        soup = BeautifulSoup(html, 'html.parser')
        base_url = url
        
        # Initialize results with default values to ensure they exist
        colors = {
            "background": ["rgb(255, 255, 255)", "rgb(249, 250, 251)"],
            "text": ["rgb(31, 41, 55)", "rgb(55, 65, 81)"],
            "accent": ["rgb(37, 99, 235)", "rgb(59, 130, 246)"]
        }
        fonts = ["Arial, sans-serif", "Helvetica, sans-serif"]
        
        # Track all colors found
        all_colors = []
        
        # Color patterns - enhanced with more CSS properties
        color_patterns = [
            # Text colors
            (re.compile(r'color\s*:\s*([^;]+)'), "text"),
            # Background colors
            (re.compile(r'background-color\s*:\s*([^;]+)'), "background"),
            (re.compile(r'background\s*:\s*([^;]+)'), "background"),
            # Accent/border colors
            (re.compile(r'border-color\s*:\s*([^;]+)'), "accent"),
            (re.compile(r'border\s*:\s*([^;]+)'), "accent"),
            (re.compile(r'outline-color\s*:\s*([^;]+)'), "accent"),
            # Button and interactive element colors
            (re.compile(r'fill\s*:\s*([^;]+)'), "accent"),
            (re.compile(r'stroke\s*:\s*([^;]+)'), "accent"),
            # Box shadow (might contain accent colors)
            (re.compile(r'box-shadow\s*:\s*([^;]+)'), "accent"),
        ]
        
        # CSS Variable patterns
        css_var_pattern = re.compile(r'--([a-zA-Z0-9_-]+):\s*([^;]+)')
        
        # Font patterns
        font_family_pattern = re.compile(r'font-family\s*:\s*([^;]+)')
        
        # For extracting colors from background property
        color_in_bg = re.compile(r'(#[0-9a-fA-F]{3,8}|rgba?\s*\([^)]+\)|hsla?\s*\([^)]+\))')
        
        # For extracting CSS variable names
        var_usage_pattern = re.compile(r'var\s*\(\s*--([a-zA-Z0-9_-]+)(?:[^)]*)\)')
        
        # Map of CSS variables and their values
        css_variables = {}
        
        # Common class name patterns for identifying color roles
        bg_class_pattern = re.compile(r'bg|background|container|wrapper|section|hero|header|footer|body', re.IGNORECASE)
        text_class_pattern = re.compile(r'text|font|title|heading|label|paragraph|content', re.IGNORECASE)
        accent_class_pattern = re.compile(r'accent|primary|secondary|highlight|button|btn|link|cta|action|border|active', re.IGNORECASE)
        
        # Extract brand colors from meta tags
        theme_color = None
        try:
            # Look for theme-color meta tag (used for mobile browsers)
            theme_meta = soup.find('meta', attrs={'name': 'theme-color'})
            if theme_meta and theme_meta.has_attr('content'):
                theme_color = theme_meta['content']
                if is_valid_color(theme_color) and theme_color not in colors["accent"]:
                    colors["accent"].append(theme_color)
                    all_colors.append(theme_color)
                    
            # Look for msapplication-TileColor (used for Windows tiles)
            ms_tile_meta = soup.find('meta', attrs={'name': 'msapplication-TileColor'})
            if ms_tile_meta and ms_tile_meta.has_attr('content'):
                ms_tile_color = ms_tile_meta['content']
                if is_valid_color(ms_tile_color) and ms_tile_color not in colors["accent"]:
                    colors["accent"].append(ms_tile_color)
                    all_colors.append(ms_tile_color)
        except Exception as e:
            print(f"Error extracting meta tag colors: {e}")
        
        # Extract colors from favicon links
        try:
            favicon_links = soup.find_all('link', rel=re.compile(r'icon|shortcut icon|apple-touch-icon'))
            for link in favicon_links:
                # Check if color is specified in the link
                if link.has_attr('color'):
                    favicon_color = link['color']
                    if is_valid_color(favicon_color) and favicon_color not in colors["accent"]:
                        colors["accent"].append(favicon_color)
                        all_colors.append(favicon_color)
        except Exception as e:
            print(f"Error extracting favicon colors: {e}")
        
        # Extract CSS variables from style tags
        for style_tag in soup.find_all('style'):
            if style_tag.string:
                css_content = style_tag.string
                # Extract CSS variables and their values
                for var_name, var_value in css_var_pattern.findall(css_content):
                    css_variables[var_name] = var_value.strip()
                    
                    # Categorize variable by name and add its color value if it's a color
                    if is_valid_color(var_value):
                        all_colors.append(var_value.strip())
                        if re.search(r'bg|background', var_name, re.IGNORECASE):
                            colors["background"].append(var_value.strip())
                        elif re.search(r'text|font|color', var_name, re.IGNORECASE):
                            colors["text"].append(var_value.strip())
                        elif re.search(r'accent|primary|secondary|highlight|button|border', var_name, re.IGNORECASE):
                            colors["accent"].append(var_value.strip())
        
        # Extract from inline styles and style tags
        def extract_colors_from_style(style_content, element_classes=None):
            # Extract colors based on patterns
            for pattern, color_type in color_patterns:
                matches = pattern.findall(style_content)
                for match in matches:
                    color_match = match.strip()
                    
                    # If it's a background property, extract just the color part
                    if pattern.pattern.startswith('background\\s*:'):
                        bg_color_match = color_in_bg.search(color_match)
                        if bg_color_match:
                            color_match = bg_color_match.group(0)
                    
                    # Check if it's a CSS variable
                    var_match = var_usage_pattern.search(color_match)
                    if var_match:
                        var_name = var_match.group(1)
                        if var_name in css_variables:
                            color_match = css_variables[var_name]
                    
                    # Only add valid colors
                    if is_valid_color(color_match):
                        all_colors.append(color_match)
                        
                        # Use element classes to help categorize if available
                        if element_classes:
                            if color_type == "background" or any(re.search(bg_class_pattern, cls) for cls in element_classes):
                                if color_match not in colors["background"]:
                                    colors["background"].append(color_match)
                            elif color_type == "text" or any(re.search(text_class_pattern, cls) for cls in element_classes):
                                if color_match not in colors["text"]:
                                    colors["text"].append(color_match)
                            elif color_type == "accent" or any(re.search(accent_class_pattern, cls) for cls in element_classes):
                                if color_match not in colors["accent"]:
                                    colors["accent"].append(color_match)
                        else:
                            # Fallback to pattern-based categorization
                            if color_type == "background" and color_match not in colors["background"]:
                                colors["background"].append(color_match)
                            elif color_type == "text" and color_match not in colors["text"]:
                                colors["text"].append(color_match)
                            elif color_type == "accent" and color_match not in colors["accent"]:
                                colors["accent"].append(color_match)
        
        # Extract colors from style tags
        for style_tag in soup.find_all('style'):
            if style_tag.string:
                extract_colors_from_style(style_tag.string)
        
        # Extract from inline styles with element context
        for element in soup.find_all(lambda tag: tag.has_attr('style')):
            style = element.get('style', '')
            element_classes = element.get('class', [])
            extract_colors_from_style(style, element_classes)
            
            # Extract fonts
            font_matches = font_family_pattern.findall(style)
            for match in font_matches:
                font = match.strip().strip("'").strip('"')
                if font and font not in fonts:
                    fonts.append(font)
        
        # Specifically target buttons and interactive elements for accent colors - Enhanced
        button_elements = soup.find_all(['button', 'a', 'input', 'div', 'span'])
        for button in button_elements:
            # Check for common button classes or roles
            is_button = (
                button.name == 'button' or 
                (button.has_attr('type') and button['type'] in ['button', 'submit', 'reset']) or
                (button.has_attr('role') and button['role'] == 'button') or
                (button.has_attr('class') and any(cls.lower() for cls in button.get('class', []) 
                                               if any(term in cls.lower() for term in 
                                                   ['btn', 'button', 'cta', 'primary', 'secondary', 'action'])))
            )
            
            # Process if it's a button or has button-like attributes
            if is_button:
                # Get inline style
                if button.has_attr('style'):
                    style = button.get('style', '')
                    extract_colors_from_style(style, ["button"])  # Force "button" class to categorize as accent
                
                # Get background-color from computed style if available
                bg_color = None
                if button.has_attr('style') and re.search(r'background', button.get('style')):
                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', button.get('style'))
                    if bg_match:
                        bg_color = bg_match.group(1).strip()
                        # Extract just the color if it's a complex background
                        if 'url(' in bg_color:
                            color_match = color_in_bg.search(bg_color)
                            if color_match:
                                bg_color = color_match.group(0)
                        
                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                            colors["accent"].append(bg_color)
                            all_colors.append(bg_color)
                
                # Get text color from computed style if available
                text_color = None
                if button.has_attr('style') and re.search(r'color\s*:', button.get('style')):
                    color_match = re.search(r'color\s*:\s*([^;]+)', button.get('style'))
                    if color_match:
                        text_color = color_match.group(1).strip()
                        if is_valid_color(text_color) and text_color not in colors["accent"]:
                            colors["accent"].append(text_color)
                            all_colors.append(text_color)
                
                # Get border color from computed style if available
                border_color = None
                if button.has_attr('style') and re.search(r'border', button.get('style')):
                    border_match = re.search(r'border(?:-color)?\s*:\s*([^;]+)', button.get('style'))
                    if border_match:
                        border_str = border_match.group(1).strip()
                        # Extract just the color from border shorthand
                        color_match = color_in_bg.search(border_str)
                        if color_match:
                            border_color = color_match.group(0)
                            if is_valid_color(border_color) and border_color not in colors["accent"]:
                                colors["accent"].append(border_color)
                                all_colors.append(border_color)
                
                # Process class-based styling (both standard and framework-specific)
                if button.has_attr('class'):
                    classes = button.get('class', [])
                    
                    # Check for common framework button classes
                    framework_classes = []
                    
                    # Bootstrap buttons
                    bootstrap_patterns = ['btn-primary', 'btn-secondary', 'btn-success', 'btn-danger', 
                                         'btn-warning', 'btn-info', 'btn-light', 'btn-dark', 'btn-link']
                    
                    # Tailwind CSS buttons and common color classes
                    tailwind_patterns = ['bg-blue-', 'bg-red-', 'bg-green-', 'bg-yellow-', 'bg-purple-', 
                                        'bg-pink-', 'bg-indigo-', 'text-blue-', 'text-red-', 'border-blue-']
                    
                    # Foundation buttons
                    foundation_patterns = ['button', 'primary', 'secondary', 'success', 'alert', 'warning']
                    
                    # Materialize CSS
                    materialize_patterns = ['btn', 'btn-large', 'btn-small', 'btn-flat', 'red', 'blue', 'green']
                    
                    # WordPress button classes
                    wordpress_patterns = ['wp-block-button', 'wp-element-button', 'button-primary', 'button-secondary']
                    
                    # Shopify button classes
                    shopify_patterns = ['shopify-payment-button', 'product-form__cart-submit', 'btn--secondary', 'cart__submit']
                    
                    # Wix button classes
                    wix_patterns = ['wix-button', '_1fbEI', '_1Qjd7']
                    
                    # Weebly button classes
                    weebly_patterns = ['wsite-button', 'wsite-button-inner']
                    
                    # Squarespace button classes
                    squarespace_patterns = ['sqs-block-button', 'sqs-button-element']
                    
                    # Enterprise specific button classes (commonly used in business sites)
                    enterprise_patterns = ['contact-btn', 'learn-more', 'get-quote', 'request-demo', 'schedule-meeting',
                                         'download-pdf', 'signup-button', 'login-button', 'read-more', 'view-details',
                                         'add-to-cart', 'checkout', 'subscribe', 'submit-form', 'start-trial']
                    
                    # Direct enterprise class name tests (case insensitive)
                    for cls in classes:
                        lower_cls = cls.lower()
                        if any(pattern in lower_cls for pattern in ['button', 'btn', 'cta']):
                            # This is almost certainly a button - prioritize any colors here
                            if button.has_attr('style'):
                                style = button.get('style', '')
                                for color_prop in ['background', 'background-color', 'color', 'border-color']:
                                    prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), style)
                                    if prop_match:
                                        color_val = prop_match.group(1).strip()
                                        # Extract just the color if it's a complex background
                                        if 'url(' in color_val:
                                            color_match = color_in_bg.search(color_val)
                                            if color_match:
                                                color_val = color_match.group(0)
                                        
                                        if is_valid_color(color_val):
                                            # Mark this as a high-priority accent color by adding it in front
                                            if color_val not in colors["accent"]:
                                                colors["accent"].insert(0, color_val)
                                            all_colors.append(color_val)

                        # Check framework patterns - collect in framework_classes
                        # Check Bootstrap patterns
                        if any(pattern in lower_cls for pattern in bootstrap_patterns):
                            framework_classes.append(cls)
                        # Check Tailwind patterns
                        elif any(pattern in lower_cls for pattern in tailwind_patterns):
                            framework_classes.append(cls)
                        # Check Foundation patterns
                        elif any(pattern in lower_cls for pattern in foundation_patterns):
                            framework_classes.append(cls)
                        # Check Materialize patterns
                        elif any(pattern in lower_cls for pattern in materialize_patterns):
                            framework_classes.append(cls)
                        # Check WordPress patterns
                        elif any(pattern in lower_cls for pattern in wordpress_patterns):
                            framework_classes.append(cls)
                        # Check Shopify patterns
                        elif any(pattern in lower_cls for pattern in shopify_patterns):
                            framework_classes.append(cls)
                        # Check Wix patterns
                        elif any(pattern in lower_cls for pattern in wix_patterns):
                            framework_classes.append(cls)
                        # Check Weebly patterns
                        elif any(pattern in lower_cls for pattern in weebly_patterns):
                            framework_classes.append(cls)
                        # Check Squarespace patterns
                        elif any(pattern in lower_cls for pattern in squarespace_patterns):
                            framework_classes.append(cls)
                        # Check Enterprise patterns
                        elif any(pattern in lower_cls for pattern in enterprise_patterns):
                            framework_classes.append(cls)
                    
                    # General button classes (not framework-specific)
                    color_classes = [cls for cls in classes if any(term in cls.lower() for term in 
                                                                ['btn', 'button', 'primary', 'secondary',
                                                                'accent', 'cta', 'action', 'color'])]
                    
                    # Combine all relevant classes
                    all_button_classes = list(set(framework_classes + color_classes))
                    
                    # Look for these classes in style tags
                    for button_class in all_button_classes:
                        for style_tag in soup.find_all('style'):
                            if style_tag.string:
                                # Convert class to proper CSS selector
                                css_class = button_class.replace(' ', '.')
                                class_selector = r'\.{}\s*{{([^}}]+)}}'.format(re.escape(css_class))
                                class_matches = re.findall(class_selector, style_tag.string, re.DOTALL)
                                
                                # Also try with just the first class if there are multiple
                                if ' ' in button_class and not class_matches:
                                    first_class = button_class.split(' ')[0]
                                    class_selector = r'\.{}\s*{{([^}}]+)}}'.format(re.escape(first_class))
                                    class_matches = re.findall(class_selector, style_tag.string, re.DOTALL)
                                
                                for match in class_matches:
                                    # Extract background-color
                                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', match)
                                    if bg_match:
                                        bg_color = bg_match.group(1).strip()
                                        # Extract just the color if it's a complex background
                                        if 'url(' in bg_color:
                                            color_match = color_in_bg.search(bg_color)
                                            if color_match:
                                                bg_color = color_match.group(0)
                                        
                                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                                            colors["accent"].append(bg_color)
                                            all_colors.append(bg_color)
                                    
                                    # Extract text color
                                    color_match = re.search(r'color\s*:\s*([^;]+)', match)
                                    if color_match:
                                        text_color = color_match.group(1).strip()
                                        if is_valid_color(text_color) and text_color not in colors["accent"]:
                                            colors["accent"].append(text_color)
                                            all_colors.append(text_color)
                                            
                                    # Extract border color
                                    border_match = re.search(r'border(?:-color)?\s*:\s*([^;]+)', match)
                                    if border_match:
                                        border_str = border_match.group(1).strip()
                                        # Extract just the color from border shorthand
                                        color_match = color_in_bg.search(border_str)
                                        if color_match:
                                            border_color = color_match.group(0)
                                            if is_valid_color(border_color) and border_color not in colors["accent"]:
                                                colors["accent"].append(border_color)
                                                all_colors.append(border_color)
                                
                                # Look for hover/focus/active states
                                for state in [':hover', ':focus', ':active', '.active', '.hover']:
                                    hover_selector = r'\.{}(?:{})\s*{{([^}}]+)}}'.format(
                                        re.escape(css_class), re.escape(state))
                                    hover_matches = re.findall(hover_selector, style_tag.string, re.DOTALL)
                                    
                                    for match in hover_matches:
                                        # Extract hover colors (typically accent colors)
                                        for prop in ['background', 'background-color', 'color', 'border-color']:
                                            prop_match = re.search(r'{}s*:\s*([^;]+)'.format(prop), match)
                                            if prop_match:
                                                color_val = prop_match.group(1).strip()
                                                if is_valid_color(color_val) and color_val not in colors["accent"]:
                                                    colors["accent"].append(color_val)
                                                    all_colors.append(color_val)
                
        # Also check specifically for header elements that might contain brand colors
        try:
            headers = soup.find_all(['header', 'nav', 'div'], class_=re.compile(r'header|nav|navbar', re.IGNORECASE))
            for header in headers:
                # Get background color of headers (often brand colors)
                if header.has_attr('style') and 'background' in header.get('style'):
                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', header.get('style'))
                    if bg_match:
                        bg_color = bg_match.group(1).strip()
                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                            colors["accent"].append(bg_color)
                            all_colors.append(bg_color)
                
                # Check header's class for CSS definitions
                if header.has_attr('class'):
                    for cls in header.get('class', []):
                        # Look for this class in style tags
                        for style_tag in soup.find_all('style'):
                            if style_tag.string:
                                class_selector = r'\.{}\s*{{([^}}]+)}}'.format(re.escape(cls))
                                class_matches = re.findall(class_selector, style_tag.string, re.DOTALL)
                                
                                for match in class_matches:
                                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', match)
                                    if bg_match:
                                        bg_color = bg_match.group(1).strip()
                                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                                            colors["accent"].append(bg_color)
                                            all_colors.append(bg_color)
        except Exception as e:
            print(f"Error extracting header colors: {e}")
                    
        # Look for logo elements (often contain brand colors)
        try:
            # Common logo selectors
            logo_elements = soup.find_all(['img', 'svg', 'div'], 
                                        class_=re.compile(r'logo|brand', re.IGNORECASE))
            logo_elements += soup.find_all(['img', 'svg', 'div'], 
                                         id=re.compile(r'logo|brand', re.IGNORECASE))
            
            for logo in logo_elements:
                # If it's an image with src, try to consider it for brand colors
                if logo.name == 'img' and logo.has_attr('src'):
                    logo_src = logo.get('src', '')
                    if logo_src:
                        # Make the URL absolute if it's relative
                        if not logo_src.startswith(('http://', 'https://')):
                            logo_src = urljoin(base_url, logo_src)
                        
                        # Try to download the logo image
                        try:
                            img_req = urllib.request.Request(
                                logo_src,
                                headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
                            )
                            with urllib.request.urlopen(img_req, timeout=5) as response:
                                # We just mark it as a potential logo which could be analyzed for color extraction
                                # For now, we'll just add a note
                                print(f"Found logo image: {logo_src}")
                        except Exception as e:
                            print(f"Failed to fetch logo from {logo_src}: {e}")
                
                # Get inline style colors from the logo element
                if logo.has_attr('style'):
                    style = logo.get('style', '')
                    for color_prop in ['color', 'background', 'background-color', 'fill', 'stroke']:
                        prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), style)
                        if prop_match:
                            color_val = prop_match.group(1).strip()
                            if is_valid_color(color_val) and color_val not in colors["accent"]:
                                colors["accent"].append(color_val)
                                all_colors.append(color_val)
        except Exception as e:
            print(f"Error extracting logo colors: {e}")
        
        # Look for SVG elements with fill attributes (often used for icons)
        for svg in soup.find_all('svg'):
            if svg.has_attr('fill'):
                fill_color = svg.get('fill')
                if is_valid_color(fill_color) and fill_color not in colors["accent"]:
                    colors["accent"].append(fill_color)
                    all_colors.append(fill_color)
            
            # Check for path elements with fill attribute
            for path in svg.find_all('path'):
                if path.has_attr('fill'):
                    fill_color = path.get('fill')
                    if is_valid_color(fill_color) and fill_color not in colors["accent"]:
                        colors["accent"].append(fill_color)
                        all_colors.append(fill_color)
        
        # Look for link elements with rel="stylesheet" to get external CSS files
        try:
            for link in soup.find_all('link', rel='stylesheet'):
                href = link.get('href')
                if href:
                    # Make the URL absolute if it's relative
                    if not href.startswith(('http://', 'https://')):
                        href = urljoin(base_url, href)
                    
                    try:
                        # Try to fetch the CSS file
                        css_req = urllib.request.Request(
                            href,
                            headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
                        )
                        with urllib.request.urlopen(css_req, timeout=5) as response:
                            css_content = response.read().decode('utf-8', errors='replace')
                            extract_colors_from_style(css_content)
                            
                            # Also look for button-specific styles in external CSS
                            button_selectors = [r'button\s*{([^}]+)}', r'\.btn\s*{([^}]+)}', r'\.button\s*{([^}]+)}', 
                                              r'a\s*{([^}]+)}', r'input\[type="button"\]\s*{([^}]+)}', 
                                              r'input\[type="submit"\]\s*{([^}]+)}']
                            
                            for selector in button_selectors:
                                button_matches = re.findall(selector, css_content, re.DOTALL)
                                for match in button_matches:
                                    # Extract background-color
                                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', match)
                                    if bg_match:
                                        bg_color = bg_match.group(1).strip()
                                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                                            colors["accent"].append(bg_color)
                                            all_colors.append(bg_color)
                                    
                                    # Extract text color
                                    color_match = re.search(r'color\s*:\s*([^;]+)', match)
                                    if color_match:
                                        text_color = color_match.group(1).strip()
                                        if is_valid_color(text_color) and text_color not in colors["accent"]:
                                            colors["accent"].append(text_color)
                                            all_colors.append(text_color)
                            
                            # Look for hover states in external CSS
                            hover_selectors = [r'button:hover\s*{([^}]+)}', r'\.btn:hover\s*{([^}]+)}', 
                                            r'\.button:hover\s*{([^}]+)}', r'a:hover\s*{([^}]+)}']
                            
                            for selector in hover_selectors:
                                hover_matches = re.findall(selector, css_content, re.DOTALL)
                                for match in hover_matches:
                                    # Extract background-color
                                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', match)
                                    if bg_match:
                                        bg_color = bg_match.group(1).strip()
                                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                                            colors["accent"].append(bg_color)
                                            all_colors.append(bg_color)
                                    
                                    # Extract text color
                                    color_match = re.search(r'color\s*:\s*([^;]+)', match)
                                    if color_match:
                                        text_color = color_match.group(1).strip()
                                        if is_valid_color(text_color) and text_color not in colors["accent"]:
                                            colors["accent"].append(text_color)
                                            all_colors.append(text_color)
                    except Exception as e:
                        print(f"Failed to fetch external CSS from {href}: {e}")
        except Exception as e:
            print(f"Error processing stylesheets: {e}")
        
        # Detect elements with CSS transitions (often indicate interactive elements with color changes)
        try:
            elements_with_transitions = soup.find_all(lambda tag: tag.has_attr('style') and 'transition' in tag.get('style', ''))
            for element in elements_with_transitions:
                style = element.get('style', '')
                # Extract colors from elements with transitions (likely to have hover states)
                for prop in ['color', 'background', 'background-color', 'border-color']:
                    prop_match = re.search(r'{}s*:\s*([^;]+)'.format(prop), style)
                    if prop_match:
                        color_val = prop_match.group(1).strip()
                        if is_valid_color(color_val):
                            if prop in ['background', 'background-color']:
                                if color_val not in colors["background"]:
                                    colors["background"].append(color_val)
                            elif prop == 'color':
                                if color_val not in colors["text"]:
                                    colors["text"].append(color_val)
                            else:
                                if color_val not in colors["accent"]:
                                    colors["accent"].append(color_val)
                            all_colors.append(color_val)
                
                # Also check style tags for transition rules for this element's classes
                if element.has_attr('class'):
                    classes = element.get('class', [])
                    for cls in classes:
                        for style_tag in soup.find_all('style'):
                            if style_tag.string:
                                # Look for transition definitions
                                transition_selector = r'\.{}\s*{{[^}}]*transition[^}}]*}}'.format(re.escape(cls))
                                transition_matches = re.findall(transition_selector, style_tag.string, re.DOTALL)
                                
                                # If we find transitions, also look for hover states
                                if transition_matches:
                                    hover_selector = r'\.{}:hover\s*{{([^}}]+)}}'.format(re.escape(cls))
                                    hover_matches = re.findall(hover_selector, style_tag.string, re.DOTALL)
                                    
                                    for match in hover_matches:
                                        for prop in ['background', 'background-color', 'color', 'border-color']:
                                            prop_match = re.search(r'{}s*:\s*([^;]+)'.format(prop), match)
                                            if prop_match:
                                                color_val = prop_match.group(1).strip()
                                                if is_valid_color(color_val) and color_val not in colors["accent"]:
                                                    colors["accent"].append(color_val)
                                                    all_colors.append(color_val)
        except Exception as e:
            print(f"Error detecting transition elements: {e}")
            
        # Also look for color CSS custom properties (variables) with clear names indicating buttons or links
        try:
            for style_tag in soup.find_all('style'):
                if style_tag.string:
                    # Look for CSS variables related to buttons or interactive elements
                    button_var_pattern = re.compile(r'--([a-zA-Z0-9-_]*(?:btn|button|link|cta|action|primary|secondary|accent|hover|active)[a-zA-Z0-9-_]*)\s*:\s*([^;]+)', re.IGNORECASE)
                    button_vars = button_var_pattern.findall(style_tag.string)
                    
                    for var_name, var_value in button_vars:
                        if is_valid_color(var_value) and var_value not in colors["accent"]:
                            colors["accent"].append(var_value)
                            all_colors.append(var_value)
        except Exception as e:
            print(f"Error extracting button CSS variables: {e}")
            
        # Look for enterprise-specific elements like call-to-action sections
        try:
            cta_sections = soup.find_all(['div', 'section'], class_=re.compile(r'cta|call-to-action|contact-us|get-started', re.IGNORECASE))
            for cta in cta_sections:
                # Extract background colors of CTA sections
                if cta.has_attr('style') and 'background' in cta.get('style'):
                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', cta.get('style'))
                    if bg_match:
                        bg_color = bg_match.group(1).strip()
                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                            colors["accent"].append(bg_color)
                            all_colors.append(bg_color)
                
                # Also look for buttons within these sections
                buttons = cta.find_all(['button', 'a', 'input'], class_=re.compile(r'btn|button|submit|cta', re.IGNORECASE))
                for button in buttons:
                    if button.has_attr('style'):
                        # Extract background color
                        if 'background' in button.get('style'):
                            bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', button.get('style'))
                            if bg_match:
                                bg_color = bg_match.group(1).strip()
                                if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                                    colors["accent"].append(bg_color)
                                    all_colors.append(bg_color)
                        
                        # Extract text color
                        if 'color' in button.get('style'):
                            color_match = re.search(r'color\s*:\s*([^;]+)', button.get('style'))
                            if color_match:
                                text_color = color_match.group(1).strip()
                                if is_valid_color(text_color) and text_color not in colors["accent"]:
                                    colors["accent"].append(text_color)
                                    all_colors.append(text_color)
        except Exception as e:
            print(f"Error extracting CTA section colors: {e}")
        
        # Perform direct scan for common button elements across the entire document
        try:
            # Look for direct button elements and a, div, span with common button classes
            all_buttons = []
            for tag in ['button', 'a', 'input[type="button"]', 'input[type="submit"]']:
                all_buttons.extend(soup.select(tag))
            
            # Look for div/span with button classes
            for tag in ['div', 'span']:
                for cls_pattern in ['btn', 'button', 'cta']:
                    all_buttons.extend(soup.select(f'{tag}[class*="{cls_pattern}"]'))
            
            # Process these buttons separately
            for button in all_buttons:
                # 1. Extract inline styles
                if button.has_attr('style'):
                    style = button.get('style', '')
                    for color_prop in ['background', 'background-color', 'color', 'border-color']:
                        prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), style)
                        if prop_match:
                            color_val = prop_match.group(1).strip()
                            # Extract just the color if it's a complex background
                            if 'url(' in color_val:
                                color_match = color_in_bg.search(color_val)
                                if color_match:
                                    color_val = color_match.group(0)
                            
                            if is_valid_color(color_val):
                                # Add to accent colors with high priority
                                if color_val not in colors["accent"]:
                                    colors["accent"].insert(0, color_val)
                                all_colors.append(color_val)
                
                # 2. Look for common class-based styling
                if button.has_attr('class'):
                    classes = button.get('class', [])
                    for cls in classes:
                        # Check for class-based color styles in style tags
                        for style_tag in soup.find_all('style'):
                            if style_tag.string:
                                # Button class selector
                                selector = r'\.{}\s*{{([^}}]+)}}'.format(re.escape(cls))
                                matches = re.findall(selector, style_tag.string, re.DOTALL)
                                
                                # Process color properties in the matches
                                for match in matches:
                                    for color_prop in ['background', 'background-color', 'color', 'border-color']:
                                        prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), match)
                                        if prop_match:
                                            color_val = prop_match.group(1).strip()
                                            if is_valid_color(color_val):
                                                # Add to accent colors with high priority
                                                if color_val not in colors["accent"]:
                                                    colors["accent"].insert(0, color_val)
                                                all_colors.append(color_val)
                                
                                # Check for hover states too
                                hover_selector = r'\.{}:hover\s*{{([^}}]+)}}'.format(re.escape(cls))
                                hover_matches = re.findall(hover_selector, style_tag.string, re.DOTALL)
                                
                                for match in hover_matches:
                                    for color_prop in ['background', 'background-color', 'color', 'border-color']:
                                        prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), match)
                                        if prop_match:
                                            color_val = prop_match.group(1).strip()
                                            if is_valid_color(color_val):
                                                # Add to accent colors with high priority
                                                if color_val not in colors["accent"]:
                                                    colors["accent"].insert(0, color_val)
                                                all_colors.append(color_val)
            
            # 3. Also look for elements with onclick attributes or javascript:void(0) hrefs (likely buttons)
            onclick_elements = soup.find_all(lambda tag: tag.has_attr('onclick'))
            js_link_elements = soup.find_all('a', href=lambda href: href and 'javascript:' in href)
            
            for element in list(onclick_elements) + list(js_link_elements):
                if element.has_attr('style'):
                    style = element.get('style', '')
                    for color_prop in ['background', 'background-color', 'color', 'border-color']:
                        prop_match = re.search(r'{}s*:\s*([^;]+)'.format(color_prop), style)
                        if prop_match:
                            color_val = prop_match.group(1).strip()
                            if is_valid_color(color_val):
                                # Add to accent colors
                                if color_val not in colors["accent"]:
                                    colors["accent"].append(color_val)
                                all_colors.append(color_val)
        except Exception as e:
            print(f"Error scanning for button elements: {e}")
            
        # Also scan for call-to-action sections which often contain brand colors
        try:
            cta_sections = soup.find_all(['section', 'div'], class_=re.compile(r'cta|action|contact|signup', re.IGNORECASE))
            for section in cta_sections:
                # Get background color
                if section.has_attr('style') and 'background' in section.get('style'):
                    bg_match = re.search(r'background(?:-color)?\s*:\s*([^;]+)', section.get('style'))
                    if bg_match:
                        bg_color = bg_match.group(1).strip()
                        # Extract just the color if it's a complex background
                        if 'url(' in bg_color:
                            color_match = color_in_bg.search(bg_color)
                            if color_match:
                                bg_color = color_match.group(0)
                        
                        if is_valid_color(bg_color) and bg_color not in colors["accent"]:
                            colors["accent"].append(bg_color)
                            all_colors.append(bg_color)
        except Exception as e:
            print(f"Error scanning for CTA sections: {e}")
        
        # Check if we have enough accent colors - otherwise try to infer from other data
        if len(colors["accent"]) < 3:
            # Look at heading elements - often use accent colors
            try:
                # Check h1, h2, h3 elements for color
                heading_elements = soup.find_all(['h1', 'h2', 'h3'])
                for heading in heading_elements:
                    if heading.has_attr('style') and 'color' in heading.get('style'):
                        color_match = re.search(r'color\s*:\s*([^;]+)', heading.get('style'))
                        if color_match:
                            color_val = color_match.group(1).strip()
                            if is_valid_color(color_val) and color_val not in colors["accent"]:
                                colors["accent"].append(color_val)
                                all_colors.append(color_val)
            except Exception as e:
                print(f"Error extracting heading colors: {e}")
            
            # If still not enough accent colors, look for link colors
            if len(colors["accent"]) < 3:
                try:
                    # Look for link color definitions in style tags
                    for style_tag in soup.find_all('style'):
                        if style_tag.string:
                            # Match a { color: ... } syntax
                            link_color_match = re.search(r'a\s*{[^}]*color\s*:\s*([^;]+)', style_tag.string, re.DOTALL)
                            if link_color_match:
                                link_color = link_color_match.group(1).strip()
                                if is_valid_color(link_color) and link_color not in colors["accent"]:
                                    colors["accent"].append(link_color)
                                    all_colors.append(link_color)
                except Exception as e:
                    print(f"Error extracting link colors: {e}")
            
            # If still no accent colors, use a sampling of non-grayscale colors
            if len(colors["accent"]) < 3:
                for color in all_colors:
                    # Skip if already in accent colors
                    if color in colors["accent"]:
                        continue
                    
                    try:
                        # Analyze if it's potentially an accent color (non-grayscale)
                        is_grayscale = False
                        
                        # For hex colors
                        if color.startswith('#'):
                            # Remove # and normalize format
                            hex_color = color[1:]
                            if len(hex_color) == 3:  # Shorthand hex
                                r = int(hex_color[0] + hex_color[0], 16)
                                g = int(hex_color[1] + hex_color[1], 16)
                                b = int(hex_color[2] + hex_color[2], 16)
                            else:  # Full hex
                                r = int(hex_color[0:2], 16)
                                g = int(hex_color[2:4], 16)
                                b = int(hex_color[4:6], 16)
                            
                            # Check if it's a grayscale color (all RGB values are equal or very close)
                            is_grayscale = abs(r - g) < 20 and abs(g - b) < 20 and abs(r - b) < 20
                        
                        # For rgb/rgba colors
                        elif color.startswith('rgb'):
                            # Extract RGB values
                            rgb_match = re.search(r'rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)', color)
                            if rgb_match:
                                r = int(rgb_match.group(1))
                                g = int(rgb_match.group(2))
                                b = int(rgb_match.group(3))
                                
                                # Check if it's grayscale
                                is_grayscale = abs(r - g) < 20 and abs(g - b) < 20 and abs(r - b) < 20
                        
                        # If it's not grayscale, add it to accent colors
                        if not is_grayscale and len(colors["accent"]) < 5:
                            colors["accent"].append(color)
                    except Exception:
                        # If any error in analysis, just skip this color
                        pass
                    
                    # Stop if we have enough colors
                    if len(colors["accent"]) >= 5:
                        break
        
        # Remove duplicate colors
        for category in colors:
            colors[category] = list(dict.fromkeys(colors[category]))
        
        # Ensure we have each required key with at least some values
        for key in ["background", "text", "accent"]:
            if not colors[key]:
                # If we have collected colors but haven't categorized them, use them
                if all_colors:
                    colors[key] = all_colors[:3]  # Use first few colors
                else:
                    # Default fallbacks
                    if key == "background":
                        colors[key] = ["rgb(255, 255, 255)", "rgb(249, 250, 251)"]
                    elif key == "text":
                        colors[key] = ["rgb(31, 41, 55)", "rgb(55, 65, 81)"]
                    elif key == "accent":
                        colors[key] = ["rgb(37, 99, 235)", "rgb(59, 130, 246)"]
        
        # Extract image paths
        images = []
        try:
            # Find all img tags
            img_tags = soup.find_all('img')
            for img in img_tags:
                if img.has_attr('src'):
                    img_src = img.get('src', '')
                    if img_src:
                        # Skip base64 encoded images and data URLs
                        if not img_src.startswith('data:'):
                            # Make relative URLs absolute
                            if not img_src.startswith(('http://', 'https://')):
                                img_src = urljoin(base_url, img_src)
                            
                            # Get additional metadata
                            alt_text = img.get('alt', '')
                            width = img.get('width', '')
                            height = img.get('height', '')
                            img_class = img.get('class', [])
                            img_id = img.get('id', '')
                            
                            # Create image info object
                            img_info = {
                                'src': img_src,
                                'alt': alt_text,
                                'width': width,
                                'height': height,
                                'class': ' '.join(img_class) if isinstance(img_class, list) else img_class,
                                'id': img_id
                            }
                            
                            images.append(img_info)
            
            # Also find background images in CSS
            elements_with_bg = soup.find_all(lambda tag: tag.has_attr('style') and 'background' in tag.get('style', ''))
            for element in elements_with_bg:
                style = element.get('style', '')
                bg_match = re.search(r'background(?:-image)?\s*:\s*url\([\'"]?([^\'"]*)[\'"]?\)', style)
                if bg_match:
                    bg_src = bg_match.group(1).strip()
                    if bg_src and not bg_src.startswith('data:'):
                        # Make relative URLs absolute
                        if not bg_src.startswith(('http://', 'https://')):
                            bg_src = urljoin(base_url, bg_src)
                        
                        # Create image info object
                        img_info = {
                            'src': bg_src,
                            'alt': 'Background image',
                            'type': 'background',
                            'element_tag': element.name,
                            'element_class': ' '.join(element.get('class', [])) if element.has_attr('class') else ''
                        }
                        
                        images.append(img_info)
            
            # Look for background images in CSS style tags
            for style_tag in soup.find_all('style'):
                if style_tag.string:
                    # Find all url() references in the CSS
                    url_matches = re.findall(r'url\([\'"]?([^\'"]*)[\'"]?\)', style_tag.string)
                    for url_match in url_matches:
                        if url_match and not url_match.startswith('data:'):
                            # Skip font files and other non-image resources
                            if not any(ext in url_match.lower() for ext in ['.woff', '.woff2', '.ttf', '.eot', '.svg']):
                                # Make relative URLs absolute
                                if not url_match.startswith(('http://', 'https://')):
                                    url_match = urljoin(base_url, url_match)
                                
                                # Create image info object
                                img_info = {
                                    'src': url_match,
                                    'alt': 'CSS background image',
                                    'type': 'css-background'
                                }
                                
                                images.append(img_info)
        except Exception as e:
            print(f"Error extracting image paths: {e}")
        
        # Remove duplicate images based on src
        unique_images = []
        seen_srcs = set()
        for img in images:
            if img['src'] not in seen_srcs:
                unique_images.append(img)
                seen_srcs.add(img['src'])
        
        return {
            "colors": colors,
            "fonts": fonts,
            "images": unique_images
        }
    
    except Exception as e:
        print(f"Error extracting CSS properties: {e}")
        # Return default values if there's an error
        return {
            "colors": {
                "background": ["rgb(255, 255, 255)", "rgb(249, 250, 251)"],
                "text": ["rgb(31, 41, 55)", "rgb(55, 65, 81)"],
                "accent": ["rgb(37, 99, 235)", "rgb(59, 130, 246)"]
            },
            "fonts": ["Arial, sans-serif", "Helvetica, sans-serif"],
            "images": []
        }

def is_valid_color(color):
    """Check if a string represents a valid CSS color"""
    # Skip if None
    if color is None:
        return False
        
    # Remove whitespace
    color = color.strip()
    
    # Skip empty strings
    if not color:
        return False
    
    # Skip 'inherit', 'transparent', etc.
    if color.lower() in ['inherit', 'transparent', 'initial', 'currentcolor', 'none', 'auto', 'unset', 'revert', 'revert-layer']:
        return False
    
    # CSS named colors including newer CSS Color Module Level 4 colors
    named_colors = set([
        'black', 'silver', 'gray', 'white', 'maroon', 'red', 'purple', 'fuchsia', 
        'green', 'lime', 'olive', 'yellow', 'navy', 'blue', 'teal', 'aqua', 'orange',
        'aliceblue', 'antiquewhite', 'aquamarine', 'azure', 'beige', 'bisque', 'blanchedalmond',
        'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral',
        'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod',
        'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen',
        'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
        'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue',
        'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'gainsboro',
        'ghostwhite', 'gold', 'goldenrod', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred',
        'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon',
        'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen',
        'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray',
        'lightslategrey', 'lightsteelblue', 'lightyellow', 'limegreen', 'linen', 'magenta',
        'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen',
        'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue',
        'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'oldlace', 'olivedrab', 'orangered',
        'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip',
        'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'rosybrown', 'royalblue', 'saddlebrown',
        'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'skyblue', 'slateblue', 'slategray',
        'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'thistle', 'tomato', 'turquoise',
        'violet', 'wheat', 'whitesmoke', 'yellowgreen', 'rebeccapurple',
        # CSS Color Module Level 4 colors
        'tomato', 'orange', 'darkorange', 'gold', 'papayawhip', 'moccasin', 'bisque', 'mistyrose',
        'pink', 'lightpink', 'hotpink', 'deeppink', 'palevioletred', 'mediumvioletred', 'lavender',
        'thistle', 'plum', 'violet', 'orchid', 'fuchsia', 'magenta', 'mediumorchid', 'mediumpurple',
        'blueviolet', 'darkviolet', 'darkorchid', 'darkmagenta', 'purple', 'indigo', 'slateblue',
        'darkslateblue', 'mediumslateblue', 'greenyellow', 'chartreuse', 'lawngreen', 'lime',
        'limegreen', 'palegreen', 'lightgreen', 'mediumspringgreen', 'springgreen', 'mediumseagreen',
        'seagreen', 'forestgreen', 'green', 'darkgreen', 'yellowgreen', 'olivedrab', 'olive',
        'darkolivegreen', 'mediumaquamarine', 'darkseagreen', 'lightseagreen', 'darkcyan', 'teal',
        'cyan', 'aqua', 'lightcyan', 'paleturquoise', 'aquamarine', 'turquoise', 'mediumturquoise',
        'darkturquoise', 'cadetblue', 'steelblue', 'lightsteelblue', 'powderblue', 'lightblue',
        'skyblue', 'lightskyblue', 'deepskyblue', 'dodgerblue', 'cornflowerblue', 'royalblue',
        'blue', 'mediumblue', 'darkblue', 'navy', 'midnightblue', 'cornsilk', 'blanchedalmond',
        'navajowhite', 'wheat', 'burlywood', 'tan', 'rosybrown', 'sandybrown', 'goldenrod',
        'darkgoldenrod', 'peru', 'chocolate', 'saddlebrown', 'sienna', 'brown', 'maroon',
        'white', 'snow', 'honeydew', 'mintcream', 'azure', 'aliceblue', 'ghostwhite', 'whitesmoke',
        'seashell', 'beige', 'oldlace', 'floralwhite', 'ivory', 'antiquewhite', 'linen',
        'lavenderblush', 'peachpuff', 'gainsboro', 'lightgray', 'silver', 'darkgray', 'gray',
        'dimgray', 'lightslategray', 'slategray', 'darkslategray', 'black'
    ])
    
    if color.lower() in named_colors:
        return True
    
    # Remove any surrounding quotes
    if (color.startswith('"') and color.endswith('"')) or (color.startswith("'") and color.endswith("'")):
        color = color[1:-1].strip()
    
    # Check for hex colors (3, 4, 6, or 8 digits)
    if re.match(r'^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$', color):
        return True
    
    # Check for rgb/rgba with percentage or number values
    if re.match(r'^rgba?\s*\(\s*(?:\d+%?\s*,\s*){2}\d+%?(?:\s*,\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for CSS modern rgb/rgba syntax (with space separators and / for alpha)
    if re.match(r'^rgba?\s*\(\s*(?:\d+%?\s+){2}\d+%?(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for hsl/hsla with percentage or number/angle values
    if re.match(r'^hsla?\s*\(\s*\d+(?:deg|grad|rad|turn)?\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for CSS modern hsl/hsla syntax (with space separators and / for alpha)
    if re.match(r'^hsla?\s*\(\s*\d+(?:deg|grad|rad|turn)?\s+\d+%\s+\d+%(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for hwb format (Hue, Whiteness, Blackness)
    if re.match(r'^hwb\s*\(\s*\d+(?:deg|grad|rad|turn)?\s+\d+%\s+\d+%(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for lab format (CIE Lab color space)
    if re.match(r'^lab\s*\(\s*\d+%?\s+[-+]?\d+\s+[-+]?\d+(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for lch format (CIE Cylindrical color space)
    if re.match(r'^lch\s*\(\s*\d+%?\s+\d+\s+\d+(?:deg|grad|rad|turn)?(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    # Check for color() function (for color spaces like display-p3, etc.)
    if re.match(r'^color\s*\(\s*[a-z0-9-]+\s+(?:[-+]?\d+%?\s+){2}[-+]?\d+%?(?:\s*\/\s*(?:0?\.)?\d+)?\s*\)$', color):
        return True
    
    return False 