#
tokens: 45837/50000 13/64 files (page 2/3)
lines: off (toggle) GitHub
raw markdown copy
This is page 2 of 3. Use http://codebase.md/mhmzdev/figma-flutter-mcp?page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   └── config.json
├── .github
│   └── workflows
│       └── release.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── docs
│   ├── cursor_rules_example.md
│   ├── figma-flutter-mcp.md
│   ├── figma-framework-mcp.md
│   ├── getting-started.md
│   └── images
│       ├── button.png
│       ├── figma-flutter-mcp.png
│       ├── screen.png
│       ├── svg.gif
│       ├── svgs_clean.gif
│       ├── text-style-frame.png
│       └── theme-frame.png
├── LICENSE.md
├── package.json
├── README.ja.md
├── README.ko.md
├── README.md
├── README.zh-cn.md
├── README.zh-tw.md
├── src
│   ├── cli.ts
│   ├── config.ts
│   ├── extractors
│   │   ├── colors
│   │   │   ├── core.ts
│   │   │   ├── extractor.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   ├── components
│   │   │   ├── core.ts
│   │   │   ├── deduplicated-extractor.ts
│   │   │   ├── extractor.ts
│   │   │   ├── index.ts
│   │   │   ├── types.ts
│   │   │   └── variant-analyzer.ts
│   │   ├── flutter
│   │   │   ├── global-vars.ts
│   │   │   ├── index.ts
│   │   │   ├── style-library.ts
│   │   │   └── style-merger.ts
│   │   ├── screens
│   │   │   ├── core.ts
│   │   │   ├── extractor.ts
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   └── typography
│   │       ├── core.ts
│   │       ├── extractor.ts
│   │       ├── index.ts
│   │       └── types.ts
│   ├── figma-config.ts
│   ├── server.ts
│   ├── services
│   │   └── figma.ts
│   ├── tools
│   │   ├── flutter
│   │   │   ├── assets
│   │   │   │   ├── asset-manager.ts
│   │   │   │   ├── assets.ts
│   │   │   │   └── svg-assets.ts
│   │   │   ├── components
│   │   │   │   ├── component-tool.ts
│   │   │   │   ├── deduplicated-helpers.ts
│   │   │   │   └── helpers.ts
│   │   │   ├── index.ts
│   │   │   ├── screens
│   │   │   │   ├── helpers.ts
│   │   │   │   └── screen-tool.ts
│   │   │   ├── semantic-detection.ts
│   │   │   ├── theme
│   │   │   │   ├── colors
│   │   │   │   │   ├── theme-generator.ts
│   │   │   │   │   └── theme-tool.ts
│   │   │   │   └── typography
│   │   │   │       ├── typography-generator.ts
│   │   │   │       └── typography-tool.ts
│   │   │   └── visual-context.ts
│   │   └── index.ts
│   ├── types
│   │   ├── errors.ts
│   │   ├── figma.ts
│   │   └── flutter.ts
│   └── utils
│       ├── figma-url-parser.ts
│       ├── helpers.ts
│       ├── logger.ts
│       ├── retry.ts
│       └── validation.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/src/extractors/components/variant-analyzer.ts:
--------------------------------------------------------------------------------

```typescript
// src/extractors/components/variant-analyzer.mts

import type {FigmaNode} from '../../types/figma.js';
import type {ComponentVariant} from './types.js';

/**
 * Variant analysis for ComponentSets
 */
export class VariantAnalyzer {

    /**
     * Analyze component set and extract all variants
     */
    async analyzeComponentSet(componentSetNode: FigmaNode): Promise<ComponentVariant[]> {
        if (componentSetNode.type !== 'COMPONENT_SET') {
            throw new Error('Node is not a COMPONENT_SET');
        }

        const variants: ComponentVariant[] = [];

        if (!componentSetNode.children || componentSetNode.children.length === 0) {
            return variants;
        }

        // Process each variant (child component)
        componentSetNode.children.forEach(child => {
            if (child.type === 'COMPONENT') {
                const variant = this.extractVariantInfo(child);
                variants.push(variant);
            }
        });

        // Determine default variant
        const defaultVariant = this.determineDefaultVariant(variants);
        if (defaultVariant) {
            variants.forEach(variant => {
                variant.isDefault = variant.nodeId === defaultVariant.nodeId;
            });
        }

        return variants;
    }

    /**
     * Extract variant information from a component node
     */
    private extractVariantInfo(componentNode: FigmaNode): ComponentVariant {
        const nodeAny = componentNode as any;

        return {
            nodeId: componentNode.id,
            name: componentNode.name,
            properties: this.parseVariantProperties(componentNode.name),
            isDefault: false // Will be set later by determineDefaultVariant
        };
    }

    /**
     * Parse variant properties from component name
     * Figma variant names are typically in format: "Property=Value, Property2=Value2"
     */
    private parseVariantProperties(componentName: string): Record<string, string> {
        const properties: Record<string, string> = {};

        try {
            // Split by comma to get individual property=value pairs
            const pairs = componentName.split(',').map(pair => pair.trim());

            pairs.forEach(pair => {
                const [property, value] = pair.split('=').map(str => str.trim());
                if (property && value) {
                    properties[property] = value;
                }
            });

            // If no properties found, treat the whole name as a single property
            if (Object.keys(properties).length === 0) {
                properties['variant'] = componentName;
            }

        } catch (error) {
            // Fallback: treat component name as single variant property
            properties['variant'] = componentName;
        }

        return properties;
    }

    /**
     * Determine which variant should be considered the default
     */
    determineDefaultVariant(variants: ComponentVariant[]): ComponentVariant | null {
        if (variants.length === 0) {
            return null;
        }

        // Strategy 1: Look for variants with "default" in name or properties
        const defaultByName = variants.find(variant =>
            variant.name.toLowerCase().includes('default') ||
            Object.values(variant.properties).some(value =>
                value.toLowerCase().includes('default')
            )
        );

        if (defaultByName) {
            return defaultByName;
        }

        // Strategy 2: Look for variants with "primary" in name or properties
        const primaryVariant = variants.find(variant =>
            variant.name.toLowerCase().includes('primary') ||
            Object.values(variant.properties).some(value =>
                value.toLowerCase().includes('primary')
            )
        );

        if (primaryVariant) {
            return primaryVariant;
        }

        // Strategy 3: Look for common default-like values
        const defaultValues = ['normal', 'regular', 'medium', 'enabled', 'active', 'standard'];
        const defaultByValue = variants.find(variant =>
            Object.values(variant.properties).some(value =>
                defaultValues.includes(value.toLowerCase())
            )
        );

        if (defaultByValue) {
            return defaultByValue;
        }

        // Strategy 4: Look for first variant that has state=enabled, type=primary, etc.
        const prioritizedVariant = variants.find(variant => {
            const props = variant.properties;
            return (
                (props.state && props.state.toLowerCase() === 'enabled') ||
                (props.type && props.type.toLowerCase() === 'primary') ||
                (props.size && props.size.toLowerCase() === 'medium')
            );
        });

        if (prioritizedVariant) {
            return prioritizedVariant;
        }

        // Fallback: Return first variant
        return variants[0];
    }

    /**
     * Check if variant selection should be prompted to user
     */
    shouldPromptForVariantSelection(variants: ComponentVariant[]): boolean {
        return variants.length > 3;
    }

    /**
     * Get variant selection prompt information
     */
    getVariantSelectionInfo(variants: ComponentVariant[]): {
        totalCount: number;
        variantNames: string[];
        variantProperties: Record<string, Set<string>>;
        defaultVariant?: ComponentVariant;
    } {
        const variantNames = variants.map(v => v.name);
        const defaultVariant = variants.find(v => v.isDefault);

        // Collect all unique property keys and their possible values
        const variantProperties: Record<string, Set<string>> = {};

        variants.forEach(variant => {
            Object.entries(variant.properties).forEach(([key, value]) => {
                if (!variantProperties[key]) {
                    variantProperties[key] = new Set();
                }
                variantProperties[key].add(value);
            });
        });

        return {
            totalCount: variants.length,
            variantNames,
            variantProperties,
            defaultVariant
        };
    }

    /**
     * Filter variants by user selection criteria
     */
    filterVariantsBySelection(
        variants: ComponentVariant[],
        selection: {
            variantNames?: string[];
            properties?: Record<string, string>;
            includeDefault?: boolean;
        }
    ): ComponentVariant[] {
        let filtered = variants;

        // Filter by variant names if specified
        if (selection.variantNames && selection.variantNames.length > 0) {
            filtered = filtered.filter(variant =>
                selection.variantNames!.some(name =>
                    variant.name.toLowerCase().includes(name.toLowerCase())
                )
            );
        }

        // Filter by specific properties if specified
        if (selection.properties && Object.keys(selection.properties).length > 0) {
            filtered = filtered.filter(variant => {
                return Object.entries(selection.properties!).every(([key, value]) => {
                    return variant.properties[key] &&
                        variant.properties[key].toLowerCase() === value.toLowerCase();
                });
            });
        }

        // Include default if requested
        if (selection.includeDefault) {
            const defaultVariant = variants.find(v => v.isDefault);
            if (defaultVariant && !filtered.includes(defaultVariant)) {
                filtered.push(defaultVariant);
            }
        }

        return filtered;
    }

    /**
     * Compare variants to identify differences
     * Useful for understanding what changes between variants
     */
    compareVariants(variants: ComponentVariant[]): {
        commonProperties: Record<string, string>;
        differentProperties: Record<string, Set<string>>;
        uniqueProperties: Record<string, Record<string, string>>;
    } {
        const commonProperties: Record<string, string> = {};
        const differentProperties: Record<string, Set<string>> = {};
        const uniqueProperties: Record<string, Record<string, string>> = {};

        if (variants.length === 0) {
            return {commonProperties, differentProperties, uniqueProperties};
        }

        // Get all property keys from all variants
        const allPropertyKeys = new Set<string>();
        variants.forEach(variant => {
            Object.keys(variant.properties).forEach(key => allPropertyKeys.add(key));
        });

        // Analyze each property
        allPropertyKeys.forEach(propertyKey => {
            const values = new Set<string>();
            const variantsByValue: Record<string, string[]> = {};

            variants.forEach(variant => {
                const value = variant.properties[propertyKey];
                if (value) {
                    values.add(value);
                    if (!variantsByValue[value]) {
                        variantsByValue[value] = [];
                    }
                    variantsByValue[value].push(variant.name);
                }
            });

            // If all variants have the same value for this property, it's common
            if (values.size === 1 && variants.every(v => v.properties[propertyKey])) {
                commonProperties[propertyKey] = Array.from(values)[0];
            }
            // If variants have different values, it's a differentiating property
            else if (values.size > 1) {
                differentProperties[propertyKey] = values;
            }
            // If only some variants have this property, it's unique to those variants
            else {
                variants.forEach(variant => {
                    if (variant.properties[propertyKey]) {
                        if (!uniqueProperties[variant.name]) {
                            uniqueProperties[variant.name] = {};
                        }
                        uniqueProperties[variant.name][propertyKey] = variant.properties[propertyKey];
                    }
                });
            }
        });

        return {commonProperties, differentProperties, uniqueProperties};
    }

    /**
     * Generate summary of variant analysis
     */
    generateVariantSummary(variants: ComponentVariant[]): string {
        if (variants.length === 0) {
            return 'No variants found in component set.';
        }

        const defaultVariant = variants.find(v => v.isDefault);
        const comparison = this.compareVariants(variants);

        let summary = `Found ${variants.length} variants:\n`;

        // List all variants
        variants.forEach((variant, index) => {
            const defaultMark = variant.isDefault ? ' (default)' : '';
            summary += `${index + 1}. ${variant.name}${defaultMark}\n`;
        });

        // Show differentiating properties
        if (Object.keys(comparison.differentProperties).length > 0) {
            summary += '\nVariant properties:\n';
            Object.entries(comparison.differentProperties).forEach(([prop, values]) => {
                summary += `- ${prop}: ${Array.from(values).join(', ')}\n`;
            });
        }

        // Show common properties
        if (Object.keys(comparison.commonProperties).length > 0) {
            summary += '\nShared properties:\n';
            Object.entries(comparison.commonProperties).forEach(([prop, value]) => {
                summary += `- ${prop}: ${value}\n`;
            });
        }

        return summary;
    }
}
```

--------------------------------------------------------------------------------
/src/tools/flutter/theme/typography/typography-tool.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/typography-tool.mts

import {z} from "zod";
import type {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js";
import {FigmaService} from "../../../../services/figma.js";
import {extractThemeTypography} from "../../../../extractors/typography/index.js";
import {TypographyGenerator} from "./typography-generator.js";
import {join} from 'path';

export function registerTypographyTools(server: McpServer, figmaApiKey: string) {
    server.registerTool(
        "extract_theme_typography",
        {
            title: "Extract Theme Typography from Frame",
            description: "Extract typography styles from a Figma theme frame containing text samples with different styles",
            inputSchema: {
                fileId: z.string().describe("Figma file ID"),
                nodeId: z.string().describe("Theme frame node ID containing text style samples"),
                projectPath: z.string().optional().describe("Path to Flutter project (defaults to current directory)"),
                generateTextTheme: z.boolean().optional().describe("Generate Flutter TextTheme class (defaults to false)"),
                familyVariableName: z.string().optional().describe("Name for shared font family variable (defaults to 'fontFamily')")
            }
        },
        async ({fileId, nodeId, projectPath = process.cwd(), generateTextTheme = false, familyVariableName = 'fontFamily'}) => {
            const token = figmaApiKey;
            if (!token) {
                return {
                    content: [{
                        type: "text",
                        text: "Error: Figma access token not configured."
                    }]
                };
            }

            try {
                // Initialize services
                const figmaService = new FigmaService(token);
                const generator = new TypographyGenerator();

                // Get the specific theme frame node
                const themeFrame = await figmaService.getNode(fileId, nodeId);

                if (!themeFrame) {
                    return {
                        content: [{
                            type: "text",
                            text: `Theme frame with node ID "${nodeId}" not found.`
                        }]
                    };
                }

                // Extract typography from the theme frame
                const themeTypography = extractThemeTypography(themeFrame);

                if (themeTypography.length === 0) {
                    return {
                        content: [{
                            type: "text",
                            text: `No typography styles found in theme frame "${themeFrame.name}". Make sure the frame contains text nodes with different styles.`
                        }]
                    };
                }

                // Generate AppText class
                const outputPath = join(projectPath, 'lib', 'theme');
                const generatedFilePath = await generator.generateAppText(themeTypography, outputPath, {
                    generateTextTheme,
                    familyVariableName,
                    includeLineHeight: true,
                    includeLetterSpacing: true
                });

                // Determine primary font family
                const fontFamilies = new Set(themeTypography.map(t => t.fontFamily));
                const primaryFontFamily = themeTypography.length > 0 ? 
                    [...fontFamilies].reduce((a, b) => 
                        themeTypography.filter(t => t.fontFamily === a).length > 
                        themeTypography.filter(t => t.fontFamily === b).length ? a : b
                    ) : 'Roboto';

                // Create success report
                let output = `Successfully extracted theme typography!\n\n`;
                output += `Theme Frame: ${themeFrame.name}\n`;
                output += `Node ID: ${nodeId}\n`;
                output += `Typography styles found: ${themeTypography.length}\n`;
                output += `Primary font family: ${primaryFontFamily}\n`;
                output += `Generated: ${generatedFilePath}\n`;
                if (generateTextTheme) {
                    output += `Text Theme: ${join(outputPath, 'text_theme.dart')}\n`;
                }
                output += `\n`;

                output += `Extracted Typography Styles:\n`;
                themeTypography.forEach((style, index) => {
                    output += `${index + 1}. ${style.name}:\n`;
                    output += `   Font: ${style.fontFamily}\n`;
                    output += `   Size: ${style.fontSize}px\n`;
                    output += `   Weight: ${style.fontWeight}\n`;
                    output += `   Line Height: ${style.lineHeight}px\n`;
                    if (style.letterSpacing) {
                        output += `   Letter Spacing: ${style.letterSpacing}px\n`;
                    }
                    output += `\n`;
                });

                output += `Generated Files:\n`;
                output += `• app_text.dart - Typography style constants\n`;
                if (generateTextTheme) {
                    output += `• text_theme.dart - Material Design TextTheme\n`;
                }

                output += `\nUsage Examples:\n`;
                output += `// Typography:\n`;
                const firstStyle = themeTypography[0];
                const dartName = firstStyle.name.charAt(0).toLowerCase() + firstStyle.name.slice(1).replace(/[^a-zA-Z0-9]/g, '');
                output += `Text('Hello World', style: AppText.${dartName})\n`;
                
                if (generateTextTheme) {
                    output += `\n// Material Design Theme:\n`;
                    output += `MaterialApp(\n`;
                    output += `  theme: ThemeData(\n`;
                    output += `    textTheme: AppTextTheme.textTheme,\n`;
                    output += `  ),\n`;
                    output += `  // ... your app\n`;
                    output += `)\n`;
                }

                output += `\n// Font Family Variable:\n`;
                output += `Container(\n`;
                output += `  child: Text(\n`;
                output += `    'Custom Text',\n`;
                output += `    style: TextStyle(\n`;
                output += `      fontFamily: AppText.${familyVariableName},\n`;
                output += `      fontSize: 16,\n`;
                output += `    ),\n`;
                output += `  ),\n`;
                output += `)\n`;

                return {
                    content: [{type: "text", text: output}]
                };

            } catch (error) {
                return {
                    content: [{
                        type: "text",
                        text: `Error extracting theme typography: ${error instanceof Error ? error.message : String(error)}`
                    }]
                };
            }
        }
    );

    // Helper tool to inspect a frame structure for typography
    server.registerTool(
        "inspect_typography_frame",
        {
            title: "Inspect Typography Frame Structure",
            description: "Inspect the structure of a typography frame to understand its text contents before extraction",
            inputSchema: {
                fileId: z.string().describe("Figma file ID"),
                nodeId: z.string().describe("Frame node ID to inspect")
            }
        },
        async ({fileId, nodeId}) => {
            const token = figmaApiKey;
            if (!token) {
                return {
                    content: [{
                        type: "text",
                        text: "Error: Figma access token not configured."
                    }]
                };
            }

            try {
                const figmaService = new FigmaService(token);
                const frameNode = await figmaService.getNode(fileId, nodeId);

                if (!frameNode) {
                    return {
                        content: [{
                            type: "text",
                            text: `Frame with node ID "${nodeId}" not found.`
                        }]
                    };
                }

                let output = `Typography Frame Inspection Report\n\n`;
                output += `Frame Name: ${frameNode.name}\n`;
                output += `Frame Type: ${frameNode.type}\n`;
                output += `Node ID: ${nodeId}\n`;
                output += `Children: ${frameNode.children?.length || 0}\n\n`;

                if (frameNode.children && frameNode.children.length > 0) {
                    output += `Frame Contents:\n`;
                    let textNodesFound = 0;
                    
                    frameNode.children.forEach((child, index) => {
                        output += `${index + 1}. ${child.name} (${child.type})\n`;

                        // Show text style if it has one
                        if (child.type === 'TEXT' && child.style) {
                            textNodesFound++;
                            output += `   Font: ${child.style.fontFamily || 'default'}\n`;
                            output += `   Size: ${child.style.fontSize || 16}px\n`;
                            output += `   Weight: ${child.style.fontWeight || 400}\n`;
                            if (child.style.lineHeightPx) {
                                output += `   Line Height: ${child.style.lineHeightPx}px\n`;
                            }
                            if (child.style.letterSpacing) {
                                output += `   Letter Spacing: ${child.style.letterSpacing}px\n`;
                            }
                        }

                        // Check for nested text nodes
                        if (child.children) {
                            const nestedTextNodes = findTextNodes(child);
                            if (nestedTextNodes.length > 0) {
                                textNodesFound += nestedTextNodes.length;
                                output += `   Contains ${nestedTextNodes.length} text node(s)\n`;
                            }
                        }
                    });

                    output += `\nText nodes found: ${textNodesFound}\n`;
                } else {
                    output += `Frame is empty or has no children.\n`;
                }

                const canExtract = frameNode.children && frameNode.children.some(child => 
                    child.type === 'TEXT' || (child.children && findTextNodes(child).length > 0)
                );

                output += `\nThis frame ${canExtract ? 'can' : 'cannot'} be used for typography extraction.\n`;

                if (canExtract) {
                    output += `\nRecommendations:\n`;
                    output += `• Make sure text samples represent your design system typography\n`;
                    output += `• Use meaningful names for text layers (e.g., "Heading Large", "Body Text")\n`;
                    output += `• Include different font weights and sizes you want to capture\n`;
                }

                return {
                    content: [{type: "text", text: output}]
                };

            } catch (error) {
                return {
                    content: [{
                        type: "text",
                        text: `Error inspecting frame: ${error instanceof Error ? error.message : String(error)}`
                    }]
                };
            }
        }
    );
}

// Helper method to find text nodes recursively
function findTextNodes(node: any): any[] {
    const textNodes: any[] = [];
    
    if (node.type === 'TEXT') {
        textNodes.push(node);
    }
    
    if (node.children) {
        node.children.forEach((child: any) => {
            textNodes.push(...findTextNodes(child));
        });
    }
    
    return textNodes;
}

```

--------------------------------------------------------------------------------
/docs/getting-started.md:
--------------------------------------------------------------------------------

```markdown
# Getting Started with Figma Flutter MCP

Welcome to Figma Flutter MCP! This guide will walk you through setting up and using the MCP server to convert Figma designs into Flutter code using AI-powered tools like Cursor.

## 🚀 Quick Setup in Cursor

### 1. Get Your Figma API Key

First, you'll need a Figma access token:

1. Go to [Figma Account Settings](https://www.figma.com/settings)
2. Scroll down to "Personal access tokens"
3. Click "Create new token"
4. Give it a name (e.g., "Flutter MCP")
5. Copy the token (keep it secure!)

> 📋 **Note**: You only need a free Figma account - no Dev Mode subscription required!

### 2. Configure MCP in Cursor

1. Open Cursor
2. Press `Cmd + Shift + P` (or `Ctrl + Shift + P` on Windows)
3. Type "Open MCP Settings" and select it
4. Click "Add new MCP"
5. Paste the configuration below:

#### For macOS/Linux:
```json
{
  "mcpServers": {
    "Figma Flutter MCP": {
      "command": "npx",
      "args": ["-y", "figma-flutter-mcp", "--figma-api-key=YOUR-API-KEY-HERE", "--stdio"]
    }
  }
}
```

#### For Windows:
```json
{
  "mcpServers": {
    "Figma Flutter MCP": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "figma-flutter-mcp", "--figma-api-key=YOUR-API-KEY-HERE", "--stdio"]
    }
  }
}
```

**Important**: Replace `YOUR-API-KEY-HERE` with your actual Figma API key.

### 3. Verify Setup

1. Restart Cursor
2. Open a new chat
3. You should see "Figma Flutter MCP" in the available tools
4. Test with: "Can you help me convert Figma designs to Flutter?"

---

## ⚠️ Important Note
As you'll follow through we are NOT generating Flutter Code, we're actually letting AI do that for us. So, keyword here would be "Good Prompt". The more informative your prompt is, the better the results will be. Of course, there's always a room for improvement in MCP itself but when it comes to implementation in Flutter, its all up to AI (Cursor in this case).

---

## 🤖 AI Coding Agent Assistance

For better results, you can setup some instructions in following files as per your AI Coding Agent:

### Setting Up AI Agent Instructions

Different AI coding agents use different configuration files to understand your project requirements and coding standards:

- **Cursor**: `.cursor/rules/fluttering.mdc`
- **Claude**: `CLAUDE.md`
- **Gemini CLI**: `GEMINI.md`

This way your AI agent will use the MCP's output and ensure the Flutter code is as per your project requirements and structure.

### Example Cursor Rules

You can checkout an example of [cursor rules](cursor_rules_example.md) that can be used for testing. Create a `.cursor/rules/fluttering.mdc` file in your project root with instructions like:

```markdown
# Flutter Development Rules

## Code Style
- Use Material 3 design principles
- Follow Flutter best practices for widget composition
- Implement proper state management (specify your preference: Provider, Riverpod, Bloc)
- Use meaningful variable and function names
- Add proper documentation and comments

## File Organization
- Break complex widgets into smaller, reusable components
- Use proper folder structure (lib/widgets/, lib/screens/, lib/models/, etc.)
- Create separate files for different concerns
- Use barrel exports for cleaner imports

## Figma Integration
- When analyzing Figma components, focus on reusability
- Extract design tokens (colors, typography, spacing) into theme files
- Export assets to appropriate directories (assets/images/, assets/svg/)
- Update pubspec.yaml automatically when adding assets

## Performance
- Use const constructors where possible
- Implement proper widget keys for list items
- Avoid unnecessary rebuilds with proper state management
- Consider using Builder widgets for complex layouts
```

### Benefits of AI Agent Configuration

When you configure your AI agent properly:

1. **Consistent Code Style**: Your AI will generate code that follows your project's conventions
2. **Better Architecture**: AI understands your preferred patterns and structures
3. **Automated Best Practices**: AI applies Flutter best practices automatically
4. **Project-Specific Requirements**: AI considers your specific needs (state management, design system, etc.)

---

## 🎨 Setting Up Theme Colors

The most efficient way to generate Flutter themes is to create a dedicated theme frame in Figma.

### Create Your Theme Frame

1. **In Figma**: Create a frame with your color palette
2. **Organize colors** by purpose (primary, secondary, background, etc.)
3. **Add labels** to identify each color's purpose

![Theme Setup Example](images/theme-frame.png)

### Get the Figma Link

**Figma Desktop**: 
- Select your theme frame
- Press `Cmd + L` (or `Ctrl + L`)

**Figma Web**: 
- Select your theme frame  
- Copy the URL from your browser

### Generate Flutter Theme

Use this prompt in Cursor:

```
Setup Flutter theme from <figma_link> including all colors. 
Create a comprehensive ColorScheme and ThemeData that follows Material Design 3 principles.
Organize the colors by their semantic meaning (primary, secondary, surface, etc.).
```

**Example Result**: You'll get a complete Flutter theme with:
- `ColorScheme` with proper semantic color assignments
- `ThemeData` configuration
- Custom color extensions if needed
- Usage examples for each color

---

## ✍️ Setting Up Typography

Create a typography system that matches your design language.

### Create Your Typography Frame

1. **In Figma**: Create a frame with text samples
2. **Include different styles**: Headlines, body text, captions, etc.
3. **Show hierarchy**: H1, H2, H3, body, small text
4. **Add style names** for clarity

![Typography Setup Example](images/text-style-frame.png)

### Get the Figma Link

Same process as theme colors - select the frame and copy the link.

### Generate Flutter Typography

Use this prompt in Cursor:

```
Setup Flutter typography theme from <figma_link>. 
Create a complete TextTheme with all the text styles shown.
Include font weights, sizes, and letter spacing that match the design.
Provide usage examples for each text style.
```

**Example Result**: You'll get:
- Complete `TextTheme` configuration
- Proper Material Design text style assignments
- Custom text styles if your design uses unique typography
- Code examples showing how to use each style

---

## 🧩 Single Widget Creation

Convert individual Figma components into reusable Flutter widgets.

### Best Practices for Widget Design

1. **Use Figma Components** when possible (creates variants automatically)
2. **Name your components** descriptively 
3. **Create variants** for different states (enabled/disabled, light/dark)
4. **Include all interactive states**

![Button Component Example](images/button.png)

### Get the Component Link

**For Components**:
- Select the component or component set
- Copy the link (`Cmd + L` or `Ctrl + L`)

**For Frames** (if you don't have components):
- Select any frame you want to convert to a widget
- Copy the link

### Generate Flutter Widget

Use this prompt in Cursor:

```
Create this widget in Flutter from <figma_link>. 
Include 2-3 main variants and break the code into smaller, readable files.
Make it a reusable component with proper state management.
Include documentation and usage examples.
```

**Example Result**: You'll get:
- Main widget file with clean, readable code
- Separate files for complex sub-components
- Proper state management (StatefulWidget if needed)
- Variant handling (different styles/states)
- Documentation and usage examples
- Proper Flutter best practices

### Advanced Widget Prompts

**For Complex Components**:
```
Analyze this complex component from <figma_link>. 
Break it down into smaller sub-widgets for better maintainability.
Include proper state management and animation support where appropriate.
```

**For Component Sets with Many Variants**:
```
Create this component set from <figma_link> with all variants.
Use enums for variant selection and ensure type safety.
Optimize for performance and reusability.
```

---

## 📱 Full Screen Generation

Convert entire Figma screens into complete Flutter screens with proper structure.

### Prepare Your Screen Design

1. **Use Frames** for full screens
2. **Include navigation elements** (app bars, bottom navigation)
3. **Add realistic content** (not just placeholder text)
4. **Consider responsive design** for different screen sizes

### Get the Screen Link

- Select the main screen frame
- Copy the Figma link

### Generate Flutter Screen

Use this prompt in Cursor:

```
Create a complete Flutter screen from this Figma design: <figma_link>
Ensure the code is well-organized with smaller, readable files.
Include proper navigation structure and responsive design.
Export any image assets automatically.
```

**Example Result**: You'll get:
- Main screen file with `Scaffold` structure
- Separate widget files for complex sections
- Proper navigation setup (AppBar, BottomNavigationBar, etc.)
- Responsive design considerations
- Automatic image asset export to `assets/` folder
- Updated `pubspec.yaml` with asset references
- Clean, maintainable code structure

### Advanced Screen Prompts

**For Complex Layouts**:
```
Analyze this complex screen layout from <figma_link>.
Create a responsive design that works on both mobile and tablet.
Use proper Flutter layout widgets and ensure good performance.
```

**For Screens with Navigation**:
```
Create this screen from <figma_link> with proper navigation integration.
Include route definitions and navigation logic.
Ensure it fits well within a larger app structure.
```

**For Data-Driven Screens**:
```
Convert this screen from <figma_link> into a Flutter screen.
Make it data-driven with proper model classes and state management.
Include loading states and error handling.
```

---

## 💡 Pro Tips for Better Results

### 1. **Be Specific in Your Prompts**

❌ **Vague**: "Convert this Figma design"
✅ **Specific**: "Create a reusable login form widget from this Figma component with validation states"

### 2. **Mention Your Requirements**

- Target platform (mobile, web, desktop)
- State management preference (Provider, Riverpod, Bloc)
- Design system (Material 3, Cupertino, custom)
- Performance considerations

### 3. **Iterative Refinement**

Start with basic conversion, then refine:
```
1. "Convert this basic button from <figma_link>"
2. "Add animation and haptic feedback to the button"
3. "Make it accessible with proper semantics"
```

### 4. **Asset Management**

- **Images**: Automatically exported with screen generation
- **SVGs**: Export separately using: `"Export this as SVG asset from <figma_link>"`
- **Icons**: Consider using Flutter's built-in icons or icon fonts

### 5. **Code Organization**

Always request:
- Separate files for complex components
- Proper folder structure
- Clear naming conventions
- Documentation and comments

---

## 🔧 Troubleshooting

### Common Issues

**"MCP Server Not Found"**
- Restart Cursor after adding MCP configuration
- Check that your API key is correct
- Ensure you have internet connection for `npx` to download the package

**"Figma API Error"**
- Verify your API key is valid
- Check that the Figma file is accessible with your account
- Ensure the Figma link contains both file ID and node ID

**"Rate Limiting"**
- Wait a few minutes between large requests
- Analyze one component/screen at a time
- Avoid rapid-fire requests

### Getting Help

1. **Check the [Issues](https://github.com/mhmzdev/figma-flutter-mcp/issues)** on GitHub
2. **Read the detailed [documentation](figma-flutter-mcp.md)**
3. **Join the community** discussions
4. **Report bugs** with specific examples

---

## 🎯 Next Steps

Now that you're set up, try these workflows:

1. **Start with Theme**: Set up your app's color scheme and typography
2. **Create Components**: Build a library of reusable widgets
3. **Build Screens**: Convert full designs into complete Flutter screens
4. **Iterate and Refine**: Use AI to improve and optimize your code

Remember: The better your Figma designs are organized and the more specific your prompts are, the better results you'll get!

---

**Happy coding! 🚀**

*Built with ❤️ for designers and developers who want to bridge the gap between design and code.*

```

--------------------------------------------------------------------------------
/src/tools/flutter/theme/typography/typography-generator.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/typography-generator.mts

import {mkdir, writeFile} from 'fs/promises';
import {join} from 'path';
import type {
    TypographyStyle,
    TypographyDefinition,
    TypographyGenerationOptions
} from '../../../../extractors/typography/types.js';

/**
 * Flutter typography generator for AppText classes
 */
export class TypographyGenerator {
    /**
     * Generate AppText class from theme typography
     */
    async generateAppText(
        typography: TypographyStyle[],
        outputDir: string,
        options: TypographyGenerationOptions = {}
    ): Promise<string> {
        // Ensure output directory exists
        await mkdir(outputDir, {recursive: true});

        // Determine primary font family
        const fontFamilies = new Set(typography.map(t => t.fontFamily));
        const primaryFontFamily = this.determinePrimaryFontFamily(typography);
        const familyVariableName = options.familyVariableName || 'fontFamily';

        // Generate AppText class
        const appTextContent = this.generateAppTextClass(
            typography,
            primaryFontFamily,
            familyVariableName,
            options
        );

        // Write AppText file
        const appTextPath = join(outputDir, 'app_text.dart');
        await writeFile(appTextPath, appTextContent);

        // Generate text theme if requested
        if (options.generateTextTheme) {
            const textThemeContent = this.generateTextThemeClass(
                typography,
                primaryFontFamily,
                familyVariableName,
                options
            );
            const textThemePath = join(outputDir, 'text_theme.dart');
            await writeFile(textThemePath, textThemeContent);
        }

        return appTextPath;
    }

    /**
     * Generate AppText class from typography library
     */
    async generateAppTextFromLibrary(
        typographyLibrary: TypographyDefinition[],
        outputDir: string,
        options: TypographyGenerationOptions = {}
    ): Promise<string> {
        // Convert TypographyDefinition to TypographyStyle format
        const typography: TypographyStyle[] = typographyLibrary.map(def => ({
            name: def.name,
            fontFamily: def.fontFamily,
            fontSize: def.fontSize,
            fontWeight: def.fontWeight,
            lineHeight: def.lineHeight,
            letterSpacing: def.letterSpacing,
            nodeId: def.id
        }));

        return this.generateAppText(typography, outputDir, options);
    }

    /**
     * Generate AppText class content
     */
    private generateAppTextClass(
        typography: TypographyStyle[],
        primaryFontFamily: string,
        familyVariableName: string,
        options: TypographyGenerationOptions
    ): string {
        const className = 'AppText';
        const imports = new Set(['package:flutter/material.dart']);

        let content = '';

        // File header
        content += this.generateFileHeader('AppText - Typography styles for the app');

        // Imports
        imports.forEach(imp => {
            content += `import '${imp}';\n`;
        });
        content += '\n';

        // Class definition
        content += `/// Typography styles for the app\n`;
        content += `/// Generated from Figma design system\n`;
        content += `class ${className} {\n`;
        content += `  ${className}._();\n\n`;

        // Font family variable
        if (primaryFontFamily && primaryFontFamily !== 'default') {
            content += `  /// Primary font family used throughout the app\n`;
            content += `  static const String ${familyVariableName} = '${primaryFontFamily}';\n\n`;
        }

        // Generate text styles
        typography.forEach(style => {
            const dartName = this.generateDartPropertyName(style.name);
            content += this.generateTextStyleProperty(style, dartName, familyVariableName, options);
        });

        content += '}\n';

        return content;
    }

    /**
     * Generate TextTheme class content
     */
    private generateTextThemeClass(
        typography: TypographyStyle[],
        primaryFontFamily: string,
        familyVariableName: string,
        options: TypographyGenerationOptions
    ): string {
        let content = '';

        // File header
        content += this.generateFileHeader('TextTheme - Material Design text theme');

        // Imports
        content += "import 'package:flutter/material.dart';\n";
        content += "import 'app_text.dart';\n\n";

        // Class definition
        content += `/// Material Design text theme\n`;
        content += `/// Generated from Figma design system\n`;
        content += `class AppTextTheme {\n`;
        content += `  AppTextTheme._();\n\n`;

        // Generate text theme
        content += `  /// Get Material Design text theme\n`;
        content += `  static TextTheme get textTheme {\n`;
        content += `    return TextTheme(\n`;

        // Map typography to Material Design text theme properties
        const materialMapping = this.mapToMaterialTextTheme(typography);
        Object.entries(materialMapping).forEach(([materialProperty, style], index, entries) => {
            if (style) {
                const dartName = this.generateDartPropertyName(style.name);
                content += `      ${materialProperty}: AppText.${dartName},\n`;
            }
        });

        content += `    );\n`;
        content += `  }\n`;
        content += '}\n';

        return content;
    }

    /**
     * Generate individual text style property
     */
    private generateTextStyleProperty(
        style: TypographyStyle,
        dartName: string,
        familyVariableName: string,
        options: TypographyGenerationOptions
    ): string {
        let content = '';

        // Documentation comment
        content += `  /// ${style.name} text style\n`;
        content += `  /// Font: ${style.fontFamily}, Size: ${style.fontSize}px, Weight: ${style.fontWeight}\n`;
        content += `  static const TextStyle ${dartName} = TextStyle(\n`;

        // Font family
        if (style.fontFamily && style.fontFamily !== 'default') {
            if (familyVariableName && style.fontFamily === this.determinePrimaryFontFamily([style])) {
                content += `    fontFamily: ${familyVariableName},\n`;
            } else {
                content += `    fontFamily: '${style.fontFamily}',\n`;
            }
        }

        // Font size
        content += `    fontSize: ${style.fontSize},\n`;

        // Font weight
        const flutterWeight = this.mapFontWeightToFlutter(style.fontWeight);
        content += `    fontWeight: ${flutterWeight},\n`;

        // Line height (if different from default and option enabled)
        if (options.includeLineHeight !== false && style.lineHeight) {
            const lineHeightRatio = style.lineHeight / style.fontSize;
            if (lineHeightRatio !== 1.2) { // Only include if not default
                content += `    height: ${lineHeightRatio.toFixed(2)},\n`;
            }
        }

        // Letter spacing (if not zero and option enabled)
        if (options.includeLetterSpacing !== false && style.letterSpacing && style.letterSpacing !== 0) {
            content += `    letterSpacing: ${style.letterSpacing},\n`;
        }

        content += `  );\n\n`;

        return content;
    }

    /**
     * Generate file header with documentation
     */
    private generateFileHeader(description: string): string {
        const timestamp = new Date().toISOString();
        return `// ${description}\n// Generated on ${timestamp}\n// This file was automatically generated from Figma design system\n\n`;
    }

    /**
     * Generate Dart-safe property name
     */
    private generateDartPropertyName(styleName: string): string {
        return styleName
            .charAt(0).toLowerCase() + styleName.slice(1)
            .replace(/[^a-zA-Z0-9]/g, '')
            .replace(/^\d/, '_$&'); // Prefix with underscore if starts with number
    }

    /**
     * Map font weight to Flutter FontWeight
     */
    private mapFontWeightToFlutter(weight: number): string {
        const weightMap: {[key: number]: string} = {
            100: 'FontWeight.w100',
            200: 'FontWeight.w200',
            300: 'FontWeight.w300',
            400: 'FontWeight.w400',
            500: 'FontWeight.w500',
            600: 'FontWeight.w600',
            700: 'FontWeight.w700',
            800: 'FontWeight.w800',
            900: 'FontWeight.w900'
        };

        // Find closest weight
        const weights = Object.keys(weightMap).map(Number).sort((a, b) => a - b);
        let closestWeight = weights[0];
        let minDiff = Math.abs(weight - closestWeight);

        for (const w of weights) {
            const diff = Math.abs(weight - w);
            if (diff < minDiff) {
                minDiff = diff;
                closestWeight = w;
            }
        }

        return weightMap[closestWeight] || 'FontWeight.w400';
    }

    /**
     * Determine primary font family from typography list
     */
    private determinePrimaryFontFamily(typography: TypographyStyle[]): string {
        if (typography.length === 0) return 'default';

        // Count usage of each font family
        const familyCount = new Map<string, number>();
        typography.forEach(style => {
            const count = familyCount.get(style.fontFamily) || 0;
            familyCount.set(style.fontFamily, count + 1);
        });

        // Find most used font family
        let maxCount = 0;
        let primaryFamily = typography[0].fontFamily;
        familyCount.forEach((count, family) => {
            if (count > maxCount) {
                maxCount = count;
                primaryFamily = family;
            }
        });

        return primaryFamily === 'default' ? 'Roboto' : primaryFamily;
    }

    /**
     * Map typography styles to Material Design text theme properties
     */
    private mapToMaterialTextTheme(typography: TypographyStyle[]): {[key: string]: TypographyStyle | null} {
        const mapping: {[key: string]: TypographyStyle | null} = {
            displayLarge: null,
            displayMedium: null,
            displaySmall: null,
            headlineLarge: null,
            headlineMedium: null,
            headlineSmall: null,
            titleLarge: null,
            titleMedium: null,
            titleSmall: null,
            bodyLarge: null,
            bodyMedium: null,
            bodySmall: null,
            labelLarge: null,
            labelMedium: null,
            labelSmall: null
        };

        // Sort typography by size (largest first)
        const sortedTypography = [...typography].sort((a, b) => b.fontSize - a.fontSize);

        // Map based on size and name patterns
        sortedTypography.forEach(style => {
            const name = style.name.toLowerCase();
            const size = style.fontSize;

            if (size >= 32 && !mapping.displayLarge) {
                mapping.displayLarge = style;
            } else if (size >= 28 && !mapping.displayMedium) {
                mapping.displayMedium = style;
            } else if (size >= 24 && !mapping.displaySmall) {
                mapping.displaySmall = style;
            } else if (size >= 22 && !mapping.headlineLarge) {
                mapping.headlineLarge = style;
            } else if (size >= 20 && !mapping.headlineMedium) {
                mapping.headlineMedium = style;
            } else if (size >= 18 && !mapping.headlineSmall) {
                mapping.headlineSmall = style;
            } else if (size >= 16) {
                if (name.includes('title') && !mapping.titleLarge) {
                    mapping.titleLarge = style;
                } else if (!mapping.bodyLarge) {
                    mapping.bodyLarge = style;
                }
            } else if (size >= 14) {
                if (name.includes('title') && !mapping.titleMedium) {
                    mapping.titleMedium = style;
                } else if (!mapping.bodyMedium) {
                    mapping.bodyMedium = style;
                }
            } else if (size >= 12) {
                if (name.includes('title') && !mapping.titleSmall) {
                    mapping.titleSmall = style;
                } else if (name.includes('label') && !mapping.labelLarge) {
                    mapping.labelLarge = style;
                } else if (!mapping.bodySmall) {
                    mapping.bodySmall = style;
                }
            } else if (size >= 11 && !mapping.labelMedium) {
                mapping.labelMedium = style;
            } else if (!mapping.labelSmall) {
                mapping.labelSmall = style;
            }
        });

        return mapping;
    }
}

```

--------------------------------------------------------------------------------
/docs/figma-flutter-mcp.md:
--------------------------------------------------------------------------------

```markdown
# Figma Flutter MCP: Why I Don't Rely Solely on Figma API
This explains why I didn't fork the existing [Figma Context MCP](https://github.com/GLips/Figma-Context-MCP) or rely on Figma's API alone.

## Overview

This project uses a **hybrid approach** that combines Figma API data extraction with intelligent analysis and Flutter-specific guidance generation. I deliberately avoid relying entirely on Figma's API endpoints for several critical reasons.

## The Problem with Pure Figma API Approach

### 1. Published Resources Limitation

Figma's API has significant limitations when it comes to accessing design resources:

```typescript
// ❌ Figma API only returns PUBLISHED resources
GET /v1/files/{file_key}/styles
// Returns: Only published color styles, text styles, effects
```

**Reality Check:**
- Most internal design work is NOT published
- Designers often work with local styles and components
- Publishing requires additional workflow steps that many teams skip
- Internal/confidential projects cannot be published publicly

### 2. Dev Mode Requirement

Figma's Dev Resources endpoints provide richer data but come with restrictions:

```typescript
// ❌ Requires Dev Mode subscription
GET /v1/files/{file_key}/dev_resources
// Returns: Detailed component specs, but only with Dev Mode access
```

**Barriers:**
- Dev Mode is a paid feature - not available to all users
- Freelancers and small teams often don't have Dev Mode access
- Client projects may not provide Dev Mode access to external developers
- Educational/personal projects can't justify the cost

### 3. Framework Agnostic vs Flutter Specific

Figma's API returns generic design tokens:

```json
{
  "fills": [{"type": "SOLID", "color": {"r": 0.2, "g": 0.4, "b": 0.8}}],
  "effects": [{"type": "DROP_SHADOW", "radius": 4, "offset": {"x": 2, "y": 2}}]
}
```

This requires additional translation to Flutter-specific implementations:

```dart
// Manual translation needed:
Container(
  decoration: BoxDecoration(
    color: Color.fromRGBO(51, 102, 204, 1.0),
    boxShadow: [BoxShadow(
      offset: Offset(2, 2),
      blurRadius: 4,
      color: Colors.black26,
    )],
  ),
)
```

### 4. Why I Didn't Fork Figma Context MCP

Instead of forking the existing [Figma Context MCP](https://github.com/GLips/Figma-Context-MCP), I built from scratch because:

**Architectural Incompatibility:**
- Framework-agnostic design creates abstraction layers I don't need
- Generic output format returns CSS-like properties instead of Flutter widgets
- Complex extractor system designed for flexibility adds overhead for Flutter-specific use cases
- Global style deduplication creates variable references instead of direct Flutter code

**Different Goals:**
- **Figma Context MCP** focuses on comprehensive design system analysis across frameworks
- **My approach** focuses on direct Flutter development with immediate actionable guidance
- **Figma Context MCP** optimizes for design token extraction and reuse
- **My approach** optimizes for Flutter widget generation and semantic understanding

**Code Structure Mismatch:**
```typescript
// Figma Context MCP approach - Generic abstraction
const layout = buildSimplifiedLayout(node, context.parent);
result.layout = findOrCreateVar(context.globalVars, layout, "layout");

// My approach - Direct Flutter guidance
if (isButton(node)) {
  guidance += generateElevatedButton(textContent, styling);
}
```

## My Hybrid Solution

### 1. Direct Node Access

I use Figma's basic node API to access any design, regardless of publication status:

```typescript
// ✅ Works with ANY Figma file (public or private)
GET /v1/files/{file_key}/nodes?ids={node_ids}
// Returns: Complete node structure with all properties
```

**Benefits:**
- Access to unpublished designs
- Works with internal/confidential projects
- No Dev Mode requirement
- Real design data, not just published libraries

### 2. Intelligent Analysis Layer

Instead of relying on Figma's interpretation, I analyze the raw node data:

```typescript
// My intelligent analysis
function detectSemanticType(content: string, nodeName: string): SemanticType {
  // Detects: button, heading, body, link, error, success, etc.
  // Based on content analysis, not just Figma's classification
}

function generateFlutterTextWidget(textInfo: TextInfo): string {
  // Generates Flutter-specific widget suggestions
  // Considers semantic meaning, not just visual properties
}
```

**Advantages:**
- Semantic understanding of design intent
- Flutter-optimized suggestions
- Context-aware recommendations
- Handles edge cases that Figma API misses

### 3. Flutter-First Architecture

My output is specifically tailored for Flutter development:

```typescript
// ✅ Flutter-specific guidance
guidance += `Container(\n`;
guidance += `  decoration: BoxDecoration(\n`;
guidance += `    color: Color(0xFF${fill.hex.substring(1)}),\n`;
guidance += `    borderRadius: BorderRadius.circular(${cornerRadius}),\n`;
guidance += `  ),\n`;
```

**vs Generic Figma API:**
```json
{
  "cornerRadius": 8,
  "fills": [{"color": {"r": 0.2, "g": 0.4, "b": 0.8}}]
}
```

**vs Figma Context MCP:**
```yaml
layout: layout_ABC123
fills: fill_DEF456
globalVars:
  styles:
    layout_ABC123: { mode: "column", gap: "8px" }
    fill_DEF456: "#1976D2"
```

## Advanced Style Deduplication System

One of the key innovations in this MCP is the **advanced style deduplication system** that goes far beyond simple hash-based matching.

### Semantic Style Matching
The system recognizes semantically equivalent styles even when they're represented differently:

```typescript
// ✅ These are recognized as equivalent:
{ fills: [{ hex: '#000000' }] }  // Full hex notation
{ fills: [{ hex: '#000' }] }     // Short hex notation
{ fills: [{ hex: '#000000', normalized: 'black' }] }  // With normalization

// All generate the same style ID and are deduplicated
```

### Style Hierarchy Detection
The system automatically detects relationships between similar styles:

```typescript
// Parent style: Base button
{ fills: [{ hex: '#007AFF' }], cornerRadius: 8, padding: { all: 12 } }

// Child style: Primary button variant (87% similar)
{ fills: [{ hex: '#007AFF' }], cornerRadius: 8, padding: { all: 16 } }
// ↳ Detected as variant with 13% variance from parent
```

### Intelligent Style Merging
The system analyzes merge opportunities:

```typescript
// Merge candidates detected:
// Score: 75% - 3 styles with 2 common properties
// Common: { cornerRadius: 8, padding: { all: 12 } }
// Differences: { fills: ['#007AFF', '#FF3B30', '#34C759'] }
// Recommendation: Create base style + color variants
```

### Optimization Benefits
- **30-50% reduction** in total unique styles
- **Improved reusability** through semantic matching
- **Style hierarchy** for better maintainability
- **Memory efficiency** with detailed optimization reports

### Automatic Optimization
- **Transparent operation** - Optimization happens automatically in the background
- **Smart thresholds** - Auto-optimizes after every 20 new styles
- **Configurable** - Use `autoOptimize: false` to disable if needed
- **Enhanced reporting** - `style_library_status` shows hierarchy and relationships

### Comprehensive Logging
The system provides detailed logging to track deduplication performance:

```
[MCP Server INFO] 🎨 Adding decoration style with properties: {...}
[MCP Server INFO] 🔍 Semantic match found! Reusing style decorationABC123 (usage: 2)
[MCP Server INFO] 🚀 Auto-optimization triggered! (20 new styles since last optimization)
[MCP Server INFO] ✅ Auto-optimization complete: { totalStyles: 45, duplicatesRemoved: 3, ... }
```

**Logging Categories:**
- **🎨 Style Creation** - New style generation with properties and hashes
- **🔍 Semantic Matching** - When equivalent styles are detected and reused
- **🌳 Hierarchy Detection** - Parent-child relationships and variance calculations
- **⚡ Auto-optimization** - Automatic optimization triggers and results
- **📊 Analysis Results** - Component analysis statistics and performance metrics

## Real-World Compatibility

| Scenario | Pure Figma API | Figma Context MCP | My Hybrid Approach |
|----------|----------------|-------------------|---------------------|
| **Internal Company Designs** | ❌ Not published | ✅ Full access | ✅ Full access |
| **Freelancer Projects** | ❌ No Dev Mode | ✅ Works | ✅ Works perfectly |
| **Client Confidential Work** | ❌ Cannot publish | ✅ Private access | ✅ Private access |
| **Personal/Learning Projects** | ❌ Cost prohibitive | ✅ Free to use | ✅ Free to use |
| **Rapid Prototyping** | ❌ Requires setup | ❌ Complex processing | ✅ Instant analysis |
| **Flutter Development** | ❌ Generic output | ❌ Requires translation | ✅ Direct Flutter code |

## Flutter Optimization Example

```typescript
// My approach generates Flutter-ready code
if (textInfo.semanticType === 'button') {
  return `ElevatedButton(
    onPressed: () {
      // TODO: Implement ${textInfo.content} action
    },
    child: Text('${textInfo.content}'),
  )`;
}

// vs Figma Context MCP generic response
{
  layout: "layout_ABC123",
  textStyle: "style_DEF456",
  fills: "fill_GHI789",
  globalVars: {
    styles: {
      layout_ABC123: { mode: "row", alignItems: "center" },
      style_DEF456: { fontSize: 16, fontWeight: 500 },
      fill_GHI789: "#2196F3"
    }
  }
}
```

## What I DON'T Do vs What I DO

### ❌ What I DON'T Do:
- Create `.dart` files - I don't generate actual Flutter code files
- Generate complete Flutter projects - No project scaffolding or structure creation
- Write executable Flutter applications - No runnable app generation
- Manage Flutter project structure - No file organization or dependency management

### ✅ What I DO:
- Extract design data from Figma - Comprehensive analysis of layouts, styling, and content
- Generate text-based guidance with Flutter syntax - Structured recommendations for AI consumption
- Provide copy-paste ready snippets - Ready-to-use Flutter widget patterns with real design values
- Structure information for AI consumption - Organized data that AI models can use to generate actual code
- Export and manage assets - Automatic image export with Flutter integration

### The AI Workflow:
1. **My Tool**: Figma Design → Structured Analysis + Flutter Guidance Text
2. **AI Model**: Reads Guidance → Generates Actual Flutter Code Files
3. **Developer**: Gets Complete Flutter Widgets/Screens

## Why Not Figma Context MCP?

**Technical Reasons:**
- Over-engineered for Flutter use case - Complex extractor system adds overhead
- Framework-agnostic abstraction - Creates additional translation layers
- CSS-focused output - Requires conversion to Flutter concepts
- Global variable system - Adds complexity for single-component analysis
- Generic design tokens - Don't map directly to Flutter widgets

**Practical Reasons:**
- Different target audience - Design system managers vs Flutter developers
- Different workflow - Comprehensive analysis vs rapid prototyping
- Different output goals - Reusable tokens vs direct implementation
- Maintenance overhead - Forking adds complexity and maintenance burden

**Strategic Reasons:**
- Flutter-specific optimization - My architecture is purpose-built for Flutter
- Simpler codebase - Easier to maintain and extend for Flutter needs
- Direct control - No need to work around framework-agnostic abstractions
- Faster iteration - No need to coordinate with upstream changes

## Why This Matters

**For Developers:**
- No barriers to entry - works with any Figma file
- Flutter-optimized guidance reduces development time
- Semantic understanding provides better widget suggestions
- Asset management handles images automatically

**For Designers:**
- No publishing required - analyze any design
- Works with internal files - no need to make designs public
- Preserves design intent through semantic analysis
- Handles real-world design patterns

**For Teams:**
- Cost-effective - no Dev Mode subscription needed
- Flexible - works with any Figma access level
- Secure - handles confidential designs
- Efficient - structured guidance for AI code generation

## Optimization Tips

- **Better prompts = Better results** - Be specific about what you want to analyze
- **Detailed requests** - "Analyze this login form component" vs "Analyze this"
- **Context matters** - Mention the component type, expected behavior, or specific concerns

### Example of Good vs Poor Prompts

**❌ Poor Prompt:**
```
Analyze this Figma link: https://figma.com/...
```

**✅ Good Prompt:**
```
Analyze this login form component from Figma: https://figma.com/...
Focus on the input field styling, button states, and form validation patterns.
I need Flutter widgets for a mobile app with Material Design.
```

## Conclusion

My hybrid approach solves real-world problems that both pure Figma API solutions and existing framework-agnostic tools cannot address effectively:

1. **Accessibility**: Works with any Figma file, regardless of publication status
2. **Cost-effectiveness**: No premium subscriptions required
3. **Flutter-first**: Purpose-built for Flutter development, not adapted from generic solutions
4. **Intelligence**: Semantic analysis beyond basic API data
5. **Practicality**: Handles real-world design workflows without abstraction overhead
6. **AI-Ready**: Structured guidance for intelligent code generation
7. **Focused scope**: Optimized specifically for Flutter rather than trying to support all frameworks

This architecture ensures that **any developer** can convert **any Figma design** into **Flutter-ready guidance**, regardless of their Figma subscription level or the design's publication status. By building specifically for Flutter rather than adapting existing framework-agnostic solutions, I provide a more direct, efficient, and maintainable path from design to code.
```

--------------------------------------------------------------------------------
/src/tools/flutter/assets/svg-assets.ts:
--------------------------------------------------------------------------------

```typescript
// tools/flutter/svg-assets.mts
import {z} from "zod";
import type {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js";
import {FigmaService} from "../../../services/figma.js";
import {join} from 'path';
import {
    createSvgAssetsDirectory,
    generateSvgFilename,
    downloadImage,
    getFileStats,
    updatePubspecAssets,
    type AssetInfo,
    generateSvgAssetConstants
} from "./asset-manager.js";

export function registerSvgAssetTools(server: McpServer, figmaApiKey: string) {
    // Tool: Export SVG Flutter Assets
    server.registerTool(
        "export_svg_flutter_assets",
        {
            title: "Export SVG Flutter Assets",
            description: "Export SVG assets from Figma nodes. Detects SVG content by analyzing vector percentage - nodes with >30% vector content are considered SVG assets. Handles nested GROUP/FRAME structures with mixed content.",
            inputSchema: {
                fileId: z.string().describe("Figma file ID"),
                nodeIds: z.array(z.string()).describe("Array of node IDs to export as SVG assets"),
                projectPath: z.string().optional().describe("Path to Flutter project (defaults to current directory)")
            }
        },
        async ({fileId, nodeIds, projectPath = process.cwd()}) => {
            const token = figmaApiKey;
            if (!token) {
                return {
                    content: [{
                        type: "text",
                        text: "Error: Figma access token not configured."
                    }]
                };
            }

            try {
                const figmaService = new FigmaService(token);

                // Filter for SVG nodes (groups with vector children)
                const svgNodes = await filterSvgNodes(fileId, nodeIds, figmaService);

                if (svgNodes.length === 0) {
                    return {
                        content: [{
                            type: "text",
                            text: "No SVG assets found in the specified nodes. SVG detection looks for:\n" +
                                  "- Direct VECTOR or BOOLEAN_OPERATION nodes\n" +
                                  "- GROUP/FRAME/COMPONENT/INSTANCE nodes with ≥30% vector content\n" +
                                  "- Nodes created with pen tool\n\n" +
                                  "Check the console logs for detailed analysis of each node's vector percentage."
                        }]
                    };
                }

                // Create SVG assets directory structure
                const assetsDir = await createSvgAssetsDirectory(projectPath);

                let downloadedAssets: AssetInfo[] = [];

                // Export each SVG node
                const imageUrls = await figmaService.getImageExportUrls(fileId, svgNodes.map(n => n.id), {
                    format: 'svg',
                    scale: 1 // SVGs don't need multiple scales
                });

                for (const node of svgNodes) {
                    const imageUrl = imageUrls[node.id];
                    if (!imageUrl) continue;

                    const filename = generateSvgFilename(node.name);
                    const filepath = join(assetsDir, filename);

                    // Download the SVG
                    await downloadImage(imageUrl, filepath);

                    // Get file size for reporting
                    const stats = await getFileStats(filepath);

                    downloadedAssets.push({
                        nodeId: node.id,
                        nodeName: node.name,
                        filename,
                        path: `assets/svgs/${filename}`,
                        size: stats.size
                    });
                }

                // Update pubspec.yaml with SVG assets
                const pubspecPath = join(projectPath, 'pubspec.yaml');
                await updatePubspecAssets(pubspecPath, downloadedAssets);

                // Generate SVG asset constants file
                const constantsFile = await generateSvgAssetConstants(downloadedAssets, projectPath);

                let output = `Successfully exported ${svgNodes.length} SVG assets to Flutter project!\n\n`;
                output += `SVG Assets Directory: ${assetsDir}\n\n`;
                output += `Downloaded SVG Assets:\n`;

                downloadedAssets.forEach((asset, index) => {
                    const svgNode = svgNodes.find(n => n.id === asset.nodeId);
                    const vectorInfo = svgNode?.vectorPercentage ? ` | Vector: ${(svgNode.vectorPercentage * 100).toFixed(1)}%` : '';
                    output += `- ${asset.filename} (${asset.size})${vectorInfo}\n`;
                });

                output += `\nPubspec Configuration:\n`;
                output += `- Merged SVG asset declarations into pubspec.yaml\n`;
                output += `- SVG assets available under: assets/svgs/\n\n`;

                output += `Generated Code:\n`;
                output += `- Merged SVG asset constants into: ${constantsFile}\n`;
                output += `- Import in your Flutter code: import 'package:your_app/constants/svg_assets.dart';\n\n`;

                output += `Usage Note:\n`;
                output += `- Use flutter_svg package to display SVG assets\n`;
                output += `- Add 'flutter_svg: ^2.0.0' to your pubspec.yaml dependencies if not already added\n`;

                return {
                    content: [{type: "text", text: output}]
                };
            } catch (error) {
                return {
                    content: [{
                        type: "text",
                        text: `Error exporting SVG assets: ${error instanceof Error ? error.message : String(error)}`
                    }]
                };
            }
        }
    );
}

// Helper function to filter SVG nodes with enhanced detection
async function filterSvgNodes(fileId: string, targetNodeIds: string[], figmaService: any): Promise<Array<{id: string, name: string, node: any, vectorPercentage?: number}>> {
    // Get the target nodes
    const targetNodes = await figmaService.getNodes(fileId, targetNodeIds);
    
    const svgNodes: Array<{id: string, name: string, node: any, vectorPercentage?: number}> = [];
    const analysisResults: Array<{id: string, name: string, type: string, vectorPercentage: number, isSvg: boolean}> = [];

    for (const nodeId of targetNodeIds) {
        const node = targetNodes[nodeId];
        if (!node) continue;

        // Calculate vector percentage for analysis
        let vectorPercentage = 0;
        if (node.type === 'VECTOR' || node.type === 'BOOLEAN_OPERATION') {
            vectorPercentage = 1.0; // 100% vector
        } else if (node.type === 'GROUP' || node.type === 'FRAME' || node.type === 'COMPONENT' || node.type === 'INSTANCE') {
            vectorPercentage = calculateVectorPercentage(node);
        }

        const isSvg = isSvgNode(node);
        
        // Store analysis results for debugging
        analysisResults.push({
            id: nodeId,
            name: node.name,
            type: node.type,
            vectorPercentage: Math.round(vectorPercentage * 100) / 100, // Round to 2 decimal places
            isSvg
        });

        // Check if this is a potential SVG node
        if (isSvg) {
            svgNodes.push({
                id: nodeId,
                name: node.name,
                node: node,
                vectorPercentage
            });
        }
    }

    // Log analysis results for debugging (this will help users understand why nodes were/weren't selected)
    console.log('SVG Node Analysis Results:');
    analysisResults.forEach(result => {
        const status = result.isSvg ? '✓ SVG' : '✗ Not SVG';
        console.log(` 🎨 ${status} | ${result.name} (${result.type}) | Vector: ${(result.vectorPercentage * 100).toFixed(1)}%`);
    });

    return svgNodes;
}

function isSvgNode(node: any): boolean {
    // Direct vector nodes are always SVG
    if (node.type === 'VECTOR' || node.type === 'BOOLEAN_OPERATION') {
        return true;
    }

    // Check if the node itself is created with pen tool
    if (isPenToolNode(node)) {
        return true;
    }

    // For container nodes (GROUP, FRAME, COMPONENT, INSTANCE), calculate vector percentage
    if (node.type === 'GROUP' || node.type === 'FRAME' || node.type === 'COMPONENT' || node.type === 'INSTANCE') {
        const vectorPercentage = calculateVectorPercentage(node);
        
        // Consider it SVG if more than 25% of the content is vector-based
        return vectorPercentage >= 0.25;
    }

    return false;
}

/**
 * Calculate the percentage of vector content in a node and its descendants
 * @param node The node to analyze
 * @returns A number between 0 and 1 representing the percentage of vector content
 */
function calculateVectorPercentage(node: any): number {
    const nodeStats = analyzeNodeComposition(node);
    
    if (nodeStats.totalNodes === 0) {
        return 0;
    }
    
    return nodeStats.vectorNodes / nodeStats.totalNodes;
}

/**
 * Recursively analyze the composition of a node and its descendants
 * @param node The node to analyze
 * @returns Object with counts of total nodes and vector nodes
 */
function analyzeNodeComposition(node: any): { totalNodes: number; vectorNodes: number } {
    let totalNodes = 1; // Count the current node
    let vectorNodes = 0;
    
    // Check if current node is vector-based
    if (isVectorBasedNode(node)) {
        vectorNodes = 1;
    }
    
    // Recursively analyze children
    if (node.children && Array.isArray(node.children)) {
        for (const child of node.children) {
            const childStats = analyzeNodeComposition(child);
            totalNodes += childStats.totalNodes;
            vectorNodes += childStats.vectorNodes;
        }
    }
    
    return { totalNodes, vectorNodes };
}

/**
 * Check if a single node is vector-based (without considering children)
 * @param node The node to check
 * @returns True if the node is vector-based
 */
function isVectorBasedNode(node: any): boolean {
    // Direct vector types
    if (node.type === 'VECTOR' || node.type === 'BOOLEAN_OPERATION') {
        return true;
    }
    
    // Pen tool created nodes
    if (isPenToolNode(node)) {
        return true;
    }
    
    // Some instances might be vector-based components
    if (node.type === 'INSTANCE') {
        // If an instance has vector-like properties, consider it vector-based
        return hasVectorLikeProperties(node);
    }
    
    return false;
}

/**
 * Check if a node has vector-like properties (for instances and other edge cases)
 * @param node The node to check
 * @returns True if the node has vector-like properties
 */
function hasVectorLikeProperties(node: any): boolean {
    // Check for vector-like fills or strokes
    const hasVectorFills = node.fills && node.fills.some((fill: any) => 
        fill.type === 'SOLID' || fill.type === 'GRADIENT_LINEAR' || fill.type === 'GRADIENT_RADIAL'
    );
    
    const hasVectorStrokes = node.strokes && node.strokes.some((stroke: any) => 
        stroke.type === 'SOLID' && stroke.visible !== false
    );
    
    // Check for vector network or path data
    const hasVectorNetwork = node.vectorNetwork && 
        node.vectorNetwork.vertices && 
        node.vectorNetwork.segments;
    
    return hasVectorNetwork || (hasVectorFills && hasVectorStrokes);
}


function isPenToolNode(node: any): boolean {
    // Check if this node was created with the pen tool
    // Pen tool nodes are typically VECTOR nodes with specific characteristics:
    
    if (node.type !== 'VECTOR') {
        return false;
    }
    
    // Check for vector network (pen tool creates vector paths)
    if (node.vectorNetwork && node.vectorNetwork.vertices && node.vectorNetwork.segments) {
        const vertices = node.vectorNetwork.vertices;
        const segments = node.vectorNetwork.segments;
        
        // Pen tool creates paths with multiple vertices and segments
        if (vertices.length > 2 && segments.length > 0) {
            // Check if segments have bezier curves (common in pen tool usage)
            const hasBezierCurves = segments.some((segment: any) => 
                segment.tangentStart || segment.tangentEnd
            );
            
            // Check if vertices have handle positions (pen tool characteristic)
            const hasHandles = vertices.some((vertex: any) => 
                vertex.tangentStart || vertex.tangentEnd
            );
            
            return hasBezierCurves || hasHandles || vertices.length > 3;
        }
    }
    
    // Check for fills that indicate custom drawn paths
    if (node.fills && node.fills.length > 0) {
        const hasCustomFill = node.fills.some((fill: any) => 
            fill.type === 'SOLID' || fill.type === 'GRADIENT_LINEAR' || fill.type === 'GRADIENT_RADIAL'
        );
        
        // If it has custom fills and no strokes, likely a pen tool shape
        const hasStrokes = node.strokes && node.strokes.length > 0;
        if (hasCustomFill && !hasStrokes && node.vectorNetwork) {
            return true;
        }
    }
    
    // Check for custom strokes (pen tool often used for line art)
    if (node.strokes && node.strokes.length > 0 && node.vectorNetwork) {
        const hasCustomStroke = node.strokes.some((stroke: any) => 
            stroke.type === 'SOLID' && stroke.visible !== false
        );
        
        if (hasCustomStroke && node.vectorNetwork.vertices && node.vectorNetwork.vertices.length > 1) {
            return true;
        }
    }
    
    return false;
}

function hasPenToolDescendants(node: any): boolean {
    // Check if this node or any of its descendants were created with pen tool
    if (isPenToolNode(node)) {
        return true;
    }
    
    if (node.children) {
        return node.children.some((child: any) => hasPenToolDescendants(child));
    }
    
    return false;
}

```

--------------------------------------------------------------------------------
/src/tools/flutter/components/deduplicated-helpers.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/components/deduplicated-helpers.mts

import type { DeduplicatedComponentAnalysis } from '../../../extractors/components/deduplicated-extractor.js';
import { FlutterStyleLibrary } from '../../../extractors/flutter/style-library.js';
import { generateComponentVisualContext } from '../visual-context.js';
import type { ComponentAnalysis } from '../../../extractors/components/types.js';

export function generateDeduplicatedReport(analysis: DeduplicatedComponentAnalysis): string {
  let output = `Component Analysis (Deduplicated)\n\n`;
  
  output += `Component: ${analysis.metadata.name}\n`;
  output += `Type: ${analysis.metadata.type}\n`;
  output += `Node ID: ${analysis.metadata.nodeId}\n\n`;
  
  // Style references
  if (Object.keys(analysis.styleRefs).length > 0) {
    output += `Style References:\n`;
    Object.entries(analysis.styleRefs).forEach(([category, styleId]) => {
      output += `- ${category}: ${styleId}\n`;
    });
    output += `\n`;
  }
  
  // Children with their style references
  if (analysis.children.length > 0) {
    output += `Children (${analysis.children.length}):\n`;
    analysis.children.forEach((child, index) => {
      const semanticMark = child.semanticType ? ` [${child.semanticType.toUpperCase()}]` : '';
      output += `${index + 1}. ${child.name} (${child.type})${semanticMark}\n`;
      
      if (child.textContent) {
        output += `   Text: "${child.textContent}"\n`;
      }
      
      if (child.styleRefs.length > 0) {
        output += `   Styles: ${child.styleRefs.join(', ')}\n`;
      }
    });
    output += `\n`;
  }
  
  // New style definitions (only show if this analysis created new styles)
  if (analysis.newStyleDefinitions && Object.keys(analysis.newStyleDefinitions).length > 0) {
    output += `New Style Definitions:\n`;
    Object.entries(analysis.newStyleDefinitions).forEach(([id, definition]) => {
      output += `${id}: ${definition.category} style\n`;
    });
    output += `\nUse generate_flutter_implementation tool for complete Flutter code.\n`;
  }
  
  return output;
}

export function generateFlutterImplementation(analysis: DeduplicatedComponentAnalysis): string {
  const styleLibrary = FlutterStyleLibrary.getInstance();
  let implementation = `Flutter Implementation:\n\n`;
  
  // Widget composition guidance
  implementation += `🏗️  Widget Composition Guidelines:\n`;
  implementation += `- Build the complete widget tree inline in build() method first\n`;
  implementation += `- Keep composing until you reach ~200 lines, then extract private widgets\n`;
  implementation += `- Use private StatelessWidget classes (prefix with _) for breakdown\n`;
  implementation += `- Avoid functional widgets - always use proper StatelessWidget classes\n\n`;
  
  // Widget structure
  const widgetName = toPascalCase(analysis.metadata.name);
  implementation += `class ${widgetName} extends StatelessWidget {\n`;
  implementation += `  const ${widgetName}({Key? key}) : super(key: key);\n\n`;
  implementation += `  @override\n`;
  implementation += `  Widget build(BuildContext context) {\n`;
  implementation += `    return Container(\n`;
  
  // Apply decoration if exists
  if (analysis.styleRefs.decoration) {
    implementation += `      decoration: ${analysis.styleRefs.decoration},\n`;
  }
  
  // Apply padding if exists
  if (analysis.styleRefs.padding) {
    implementation += `      padding: ${analysis.styleRefs.padding},\n`;
  }
  
  // Add child widget structure
  if (analysis.children.length > 0) {
    implementation += `      child: Column(\n`;
    implementation += `        children: [\n`;
    
    analysis.children.forEach(child => {
      if (child.semanticType === 'button' && child.textContent) {
        implementation += `          ElevatedButton(\n`;
        implementation += `            onPressed: () {},\n`;
        implementation += `            child: Text('${child.textContent}'),\n`;
        implementation += `          ),\n`;
      } else if (child.type === 'TEXT' && child.textContent) {
        implementation += `          Text('${child.textContent}'),\n`;
      }
    });
    
    implementation += `        ],\n`;
    implementation += `      ),\n`;
  }
  
  implementation += `    );\n`;
  implementation += `  }\n`;
  implementation += `}\n`;
  
  return implementation;
}

/**
 * Generate comprehensive deduplicated report with style library statistics
 */
export function generateComprehensiveDeduplicatedReport(
  analysis: DeduplicatedComponentAnalysis,
  includeStyleStats: boolean = true
): string {
  let output = `📊 Comprehensive Component Analysis (Deduplicated)\n`;
  output += `${'='.repeat(60)}\n\n`;

  // Component metadata
  output += `🏷️  Component Metadata:\n`;
  output += `   • Name: ${analysis.metadata.name}\n`;
  output += `   • Type: ${analysis.metadata.type}\n`;
  output += `   • Node ID: ${analysis.metadata.nodeId}\n`;
  if (analysis.metadata.componentKey) {
    output += `   • Component Key: ${analysis.metadata.componentKey}\n`;
  }
  output += `\n`;

  // Style references with usage information
  if (Object.keys(analysis.styleRefs).length > 0) {
    output += `🎨 Style References (Deduplicated):\n`;
    const styleLibrary = FlutterStyleLibrary.getInstance();
    
    Object.entries(analysis.styleRefs).forEach(([category, styleId]) => {
      const style = styleLibrary.getStyle(styleId);
      if (style) {
        output += `   • ${category}: ${styleId} (used ${style.usageCount} times)\n`;
      } else {
        output += `   • ${category}: ${styleId} (style not found)\n`;
      }
    });
    output += `\n`;
  } else {
    output += `🎨 Style References: None detected\n\n`;
  }

  // Children analysis with enhanced details
  if (analysis.children.length > 0) {
    output += `👶 Children Analysis (${analysis.children.length} children):\n`;
    analysis.children.forEach((child, index) => {
      const semanticMark = child.semanticType ? ` [${child.semanticType.toUpperCase()}]` : '';
      output += `   ${index + 1}. ${child.name} (${child.type})${semanticMark}\n`;
      
      if (child.textContent) {
        output += `      📝 Text: "${child.textContent}"\n`;
      }
      
      if (child.styleRefs.length > 0) {
        output += `      🎨 Style refs: ${child.styleRefs.join(', ')}\n`;
      }
      
      if (child.semanticType) {
        output += `      🏷️  Semantic type: ${child.semanticType}\n`;
      }
    });
    output += `\n`;
  } else {
    output += `👶 Children: No children detected\n\n`;
  }

  // Nested components
  if (analysis.nestedComponents.length > 0) {
    output += `🔗 Nested Components (${analysis.nestedComponents.length}):\n`;
    analysis.nestedComponents.forEach((nested, index) => {
      output += `   ${index + 1}. ${nested.name}\n`;
      output += `      🆔 Node ID: ${nested.nodeId}\n`;
      if (nested.componentKey) {
        output += `      🔑 Component Key: ${nested.componentKey}\n`;
      }
      output += `      🔧 Needs separate analysis: ${nested.needsSeparateAnalysis ? 'Yes' : 'No'}\n`;
    });
    output += `\n`;
  }

  // New style definitions created in this analysis
  if (analysis.newStyleDefinitions && Object.keys(analysis.newStyleDefinitions).length > 0) {
    output += `✨ New Style Definitions Created:\n`;
    Object.entries(analysis.newStyleDefinitions).forEach(([id, definition]) => {
      output += `   • ${id} (${definition.category})\n`;
      output += `     Usage count: ${definition.usageCount}\n`;
      output += `     Properties: ${Object.keys(definition.properties).join(', ')}\n`;
    });
    output += `\n`;
  }

  // Style library statistics (if requested)
  if (includeStyleStats) {
    const styleLibrary = FlutterStyleLibrary.getInstance();
    const allStyles = styleLibrary.getAllStyles();
    
    output += `📚 Style Library Summary:\n`;
    output += `   • Total unique styles: ${allStyles.length}\n`;
    
    if (allStyles.length > 0) {
      const categoryStats = allStyles.reduce((acc, style) => {
        acc[style.category] = (acc[style.category] || 0) + 1;
        return acc;
      }, {} as Record<string, number>);
      
      Object.entries(categoryStats).forEach(([category, count]) => {
        output += `   • ${category}: ${count} style(s)\n`;
      });
      
      const totalUsage = allStyles.reduce((sum, style) => sum + style.usageCount, 0);
      output += `   • Total style usage: ${totalUsage}\n`;
      
      if (totalUsage > allStyles.length) {
        const efficiency = ((totalUsage - allStyles.length) / totalUsage * 100).toFixed(1);
        output += `   • Deduplication efficiency: ${efficiency}% reduction\n`;
      }
    }
    output += `\n`;
  }

  // Quick actions
  output += `🚀 Quick Actions:\n`;
  output += `   • Use 'generate_flutter_implementation' tool for complete Flutter code\n`;
  output += `   • Use 'analyze_figma_component' with different components to build style library\n`;
  output += `   • Use 'resetStyleLibrary: true' to start fresh analysis\n\n`;
  
  output += `🏗️  Widget Composition Reminder:\n`;
  output += `   • Build complete widget tree inline first (~200 lines max)\n`;
  output += `   • Extract to private StatelessWidget classes only when needed\n`;
  output += `   • Avoid functional widgets - use proper StatelessWidget classes\n`;

  return output;
}

/**
 * Add visual context to comprehensive deduplicated report
 */
export function addVisualContextToDeduplicatedReport(
  analysis: DeduplicatedComponentAnalysis,
  figmaUrl?: string,
  nodeId?: string
): string {
  // Convert deduplicated analysis to component analysis format for visual context
  const componentAnalysis: ComponentAnalysis = {
    metadata: analysis.metadata,
    layout: {
      type: 'auto-layout', // Default assumption
      dimensions: { width: 400, height: 200 }, // Default dimensions
      direction: 'vertical',
      spacing: undefined,
      padding: undefined,
      alignItems: undefined,
      justifyContent: undefined
    },
    styling: {
      fills: [],
      strokes: [],
      cornerRadius: undefined,
      opacity: 1,
      effects: { dropShadows: [], innerShadows: [], blurs: [] }
    },
    children: analysis.children.map((child, index) => ({
      name: child.name,
      type: child.type,
      nodeId: `node_${index}`,
      isNestedComponent: false,
      visualImportance: 5,
      basicInfo: {
        layout: { 
          type: 'auto-layout',
          dimensions: { width: 100, height: 50 },
          direction: 'vertical'
        },
        styling: { 
          fills: [], 
          strokes: [], 
          opacity: 1,
          effects: { dropShadows: [], innerShadows: [], blurs: [] }
        },
        text: child.textContent ? {
          content: child.textContent,
          isPlaceholder: false,
          fontFamily: undefined,
          fontSize: undefined,
          fontWeight: undefined,
          textCase: 'mixed' as const,
          semanticType: (child.semanticType === 'button' || child.semanticType === 'link' || 
                       child.semanticType === 'heading' || child.semanticType === 'body' ||
                       child.semanticType === 'label' || child.semanticType === 'caption' ||
                       child.semanticType === 'error' || child.semanticType === 'success' ||
                       child.semanticType === 'warning') ? child.semanticType : 'other' as const
        } : undefined
      }
    })),
    nestedComponents: analysis.nestedComponents,
    skippedNodes: []
  };

  return generateComponentVisualContext(componentAnalysis, figmaUrl, nodeId);
}

/**
 * Generate style library status report
 */
export function generateStyleLibraryReport(): string {
  const styleLibrary = FlutterStyleLibrary.getInstance();
  const allStyles = styleLibrary.getAllStyles();
  
  let output = `📚 Style Library Status Report\n`;
  output += `${'='.repeat(40)}\n\n`;

  if (allStyles.length === 0) {
    output += `⚠️  Style library is empty.\n`;
    output += `   • Analyze components with 'useDeduplication: true' to populate\n`;
    output += `   • Use 'analyze_figma_component' tool to start building your style library\n`;
    return output;
  }

  output += `📊 Library Statistics:\n`;
  output += `   • Total unique styles: ${allStyles.length}\n`;
  
  // Show optimization info
  const hierarchy = styleLibrary.getStyleHierarchy();
  const hierarchyCount = Object.keys(hierarchy).filter(id => 
    hierarchy[id].parentId || hierarchy[id].childIds.length > 0
  ).length;
  
  if (hierarchyCount > 0) {
    output += `   • Styles with relationships: ${hierarchyCount}\n`;
  }
  
  // Category breakdown
  const categoryStats = allStyles.reduce((acc, style) => {
    acc[style.category] = (acc[style.category] || 0) + 1;
    return acc;
  }, {} as Record<string, number>);
  
  output += `   • Style categories:\n`;
  Object.entries(categoryStats).forEach(([category, count]) => {
    output += `     - ${category}: ${count} style(s)\n`;
  });

  // Usage statistics
  const totalUsage = allStyles.reduce((sum, style) => sum + style.usageCount, 0);
  output += `   • Total style usage: ${totalUsage}\n`;
  
  if (totalUsage > allStyles.length) {
    const efficiency = ((totalUsage - allStyles.length) / totalUsage * 100).toFixed(1);
    output += `   • Deduplication efficiency: ${efficiency}% reduction\n`;
  }

  // Most used styles
  const sortedByUsage = [...allStyles].sort((a, b) => b.usageCount - a.usageCount);
  const topStyles = sortedByUsage.slice(0, 5);
  
  if (topStyles.length > 0) {
    output += `\n🔥 Most Used Styles:\n`;
    topStyles.forEach((style, index) => {
      output += `   ${index + 1}. ${style.id} (${style.category}) - used ${style.usageCount} times\n`;
    });
  }

  // Detailed style list
  output += `\n📋 All Styles:\n`;
  Object.entries(categoryStats).forEach(([category, count]) => {
    const categoryStyles = allStyles.filter(s => s.category === category);
    output += `\n   ${category.toUpperCase()} (${count}):\n`;
    categoryStyles.forEach(style => {
      output += `   • ${style.id} (used ${style.usageCount} times)\n`;
    });
  });

  return output;
}

function toPascalCase(str: string): string {
  return str
    .replace(/[^a-zA-Z0-9]/g, ' ')
    .replace(/\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
    .replace(/\s/g, '');
}

```

--------------------------------------------------------------------------------
/src/tools/flutter/screens/screen-tool.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/screens/screen-tool.mts

import {z} from "zod";
import type {McpServer} from "@modelcontextprotocol/sdk/server/mcp.js";
import {FigmaService} from "../../../services/figma.js";
import {
    ScreenExtractor,
    parseComponentInput,
    type ScreenAnalysis
} from "../../../extractors/screens/index.js";

import {
    generateScreenAnalysisReport,
    generateScreenStructureReport
} from "./helpers.js";

import {
    createAssetsDirectory,
    generateAssetFilename,
    downloadImage,
    getFileStats,
    updatePubspecAssets,
    generateAssetConstants,
    groupAssetsByBaseName,
    type AssetInfo
} from "../assets/asset-manager.js";
import {join} from 'path';

export function registerScreenTools(server: McpServer, figmaApiKey: string) {

    // Main screen analysis tool
    server.registerTool(
        "analyze_full_screen",
        {
            title: "Analyze Full Screen",
            description: "Analyze a complete Figma screen/frame to extract layout, sections, navigation, and structure information for Flutter screen implementation",
            inputSchema: {
                input: z.string().describe("Figma screen URL or file ID"),
                nodeId: z.string().optional().describe("Node ID (if providing file ID separately)"),
                maxSections: z.number().optional().describe("Maximum sections to analyze (default: 15)"),
                extractNavigation: z.boolean().optional().describe("Extract navigation elements (default: true)"),
                extractAssets: z.boolean().optional().describe("Extract and export screen assets (default: true)"),
                projectPath: z.string().optional().describe("Path to Flutter project for asset export (defaults to current directory)"),
                deviceTypeDetection: z.boolean().optional().describe("Detect device type and orientation (default: true)")
            }
        },
        async ({input, nodeId, maxSections = 15, extractNavigation = true, extractAssets = true, projectPath = process.cwd(), deviceTypeDetection = true}) => {
            const token = figmaApiKey;
            if (!token) {
                return {
                    content: [{
                        type: "text",
                        text: "Error: Figma access token not configured. Please set FIGMA_API_KEY environment variable."
                    }]
                };
            }

            try {
                // Parse input to get file ID and node ID
                const parsedInput = parseComponentInput(input, nodeId);

                if (!parsedInput.isValid) {
                    return {
                        content: [{
                            type: "text",
                            text: `Error parsing input: ${parsedInput.error || 'Invalid input format'}`
                        }]
                    };
                }

                const figmaService = new FigmaService(token);
                const screenExtractor = new ScreenExtractor({
                    maxSections,
                    extractNavigation,
                    extractAssets: false, // We'll handle asset export separately
                    deviceTypeDetection
                });

                // Get the screen node
                const screenNode = await figmaService.getNode(parsedInput.fileId, parsedInput.nodeId);

                if (!screenNode) {
                    return {
                        content: [{
                            type: "text",
                            text: `Screen with node ID "${parsedInput.nodeId}" not found in file.`
                        }]
                    };
                }

                // Analyze the screen
                const screenAnalysis = await screenExtractor.analyzeScreen(screenNode);

                // Detect and export screen assets if enabled
                let assetExportInfo = '';
                if (extractAssets) {
                    try {
                        const imageNodes = await filterImageNodesInScreen(parsedInput.fileId, [parsedInput.nodeId], figmaService);
                        if (imageNodes.length > 0) {
                            const exportedAssets = await exportScreenAssets(
                                imageNodes,
                                parsedInput.fileId,
                                figmaService,
                                projectPath
                            );
                            assetExportInfo = generateAssetExportReport(exportedAssets);
                        }
                    } catch (assetError) {
                        assetExportInfo = `\nAsset Export Warning: ${assetError instanceof Error ? assetError.message : String(assetError)}\n`;
                    }
                }

                // Generate analysis report
                const analysisReport = generateScreenAnalysisReport(screenAnalysis, parsedInput);

                return {
                    content: [{
                        type: "text",
                        text: analysisReport + assetExportInfo
                    }]
                };

            } catch (error) {
                return {
                    content: [{
                        type: "text",
                        text: `Error analyzing screen: ${error instanceof Error ? error.message : String(error)}`
                    }]
                };
            }
        }
    );

    // Screen structure inspection tool
    server.registerTool(
        "inspect_screen_structure",
        {
            title: "Inspect Screen Structure",
            description: "Get a quick overview of screen structure, sections, and navigation elements",
            inputSchema: {
                input: z.string().describe("Figma screen URL or file ID"),
                nodeId: z.string().optional().describe("Node ID (if providing file ID separately)"),
                showAllSections: z.boolean().optional().describe("Show all sections regardless of limits (default: false)")
            }
        },
        async ({input, nodeId, showAllSections = false}) => {
            const token = figmaApiKey;
            if (!token) {
                return {
                    content: [{
                        type: "text",
                        text: "Error: Figma access token not configured."
                    }]
                };
            }

            try {
                const parsedInput = parseComponentInput(input, nodeId);

                if (!parsedInput.isValid) {
                    return {
                        content: [{
                            type: "text",
                            text: `Error parsing input: ${parsedInput.error}`
                        }]
                    };
                }

                const figmaService = new FigmaService(token);
                const screenNode = await figmaService.getNode(parsedInput.fileId, parsedInput.nodeId);

                if (!screenNode) {
                    return {
                        content: [{
                            type: "text",
                            text: `Screen with node ID "${parsedInput.nodeId}" not found.`
                        }]
                    };
                }

                const output = generateScreenStructureReport(screenNode, showAllSections);

                return {
                    content: [{type: "text", text: output}]
                };

            } catch (error) {
                return {
                    content: [{
                        type: "text",
                        text: `Error inspecting screen structure: ${error instanceof Error ? error.message : String(error)}`
                    }]
                };
            }
        }
    );
}

/**
 * OPTIMIZED: Filter image nodes within a screen - only searches within target nodes
 */
async function filterImageNodesInScreen(fileId: string, targetNodeIds: string[], figmaService: FigmaService): Promise<Array<{id: string, name: string, node: any}>> {
    // OPTIMIZED: Only get the target nodes instead of the entire file (massive performance improvement)
    const targetNodes = await figmaService.getNodes(fileId, targetNodeIds);

    const allNodesWithImages: Array<{id: string, name: string, node: any}> = [];

    function extractImageNodes(node: any, nodeId: string = node.id): void {
        // Check if this node has image fills
        if (node.fills && node.fills.some((fill: any) => fill.type === 'IMAGE' && fill.visible !== false)) {
            allNodesWithImages.push({
                id: nodeId,
                name: node.name,
                node: node
            });
        }

        // Check if this is a vector/illustration that should be exported
        if (node.type === 'VECTOR' && node.name) {
            const name = node.name.toLowerCase();
            if ((name.includes('image') || name.includes('illustration') || name.includes('graphic') ||
                 name.includes('photo') || name.includes('picture') || name.includes('asset') ||
                 name.includes('logo') || name.includes('icon')) &&
                !name.includes('button')) {
                allNodesWithImages.push({
                    id: nodeId,
                    name: node.name,
                    node: node
                });
            }
        }

        // Check for large frames that might be image placeholders
        if ((node.type === 'RECTANGLE' || node.type === 'FRAME') && node.name) {
            const name = node.name.toLowerCase();
            const hasImageKeywords = name.includes('image') || name.includes('photo') || 
                                   name.includes('picture') || name.includes('banner') ||
                                   name.includes('hero') || name.includes('thumbnail') ||
                                   name.includes('background') || name.includes('cover');
            
            // Check if it has image fills or is large enough to be an image placeholder
            const hasImageFills = node.fills && node.fills.some((fill: any) => fill.type === 'IMAGE');
            const isLargeEnough = node.absoluteBoundingBox && 
                                (node.absoluteBoundingBox.width > 80 && node.absoluteBoundingBox.height > 80);
            
            if (hasImageKeywords && (hasImageFills || isLargeEnough)) {
                allNodesWithImages.push({
                    id: nodeId,
                    name: node.name,
                    node: node
                });
            }
        }

        // Recursively check children
        if (node.children) {
            node.children.forEach((child: any) => {
                extractImageNodes(child, child.id);
            });
        }
    }

    // OPTIMIZED: Extract only from target nodes instead of entire file
    // This eliminates the need for expensive boundary checking since we only search within target nodes
    Object.values(targetNodes).forEach((node: any) => {
        extractImageNodes(node);
    });

    // OPTIMIZED: No filtering needed since we only searched within target nodes
    return allNodesWithImages;
}

// REMOVED: isNodeWithinTarget function no longer needed since we only search within target nodes

/**
 * Export screen assets to Flutter project
 */
async function exportScreenAssets(
    imageNodes: Array<{id: string, name: string, node: any}>,
    fileId: string,
    figmaService: FigmaService,
    projectPath: string
): Promise<AssetInfo[]> {
    if (imageNodes.length === 0) {
        return [];
    }

    // Create assets directory structure
    const assetsDir = await createAssetsDirectory(projectPath);
    const downloadedAssets: AssetInfo[] = [];

    // Export images at 2x scale (standard for Flutter)
    const imageUrls = await figmaService.getImageExportUrls(fileId, imageNodes.map(n => n.id), {
        format: 'png',
        scale: 2
    });

    for (const imageNode of imageNodes) {
        const imageUrl = imageUrls[imageNode.id];
        if (!imageUrl) continue;

        const filename = generateAssetFilename(imageNode.name, 'png', 2, false);
        const filepath = join(assetsDir, filename);

        try {
            // Download the image
            await downloadImage(imageUrl, filepath);

            // Get file size for reporting
            const stats = await getFileStats(filepath);

            downloadedAssets.push({
                nodeId: imageNode.id,
                nodeName: imageNode.name,
                filename,
                path: `assets/images/${filename}`,
                size: stats.size
            });
        } catch (downloadError) {
            console.warn(`Failed to download image ${imageNode.name}:`, downloadError);
        }
    }

    if (downloadedAssets.length > 0) {
        // Update pubspec.yaml
        const pubspecPath = join(projectPath, 'pubspec.yaml');
        await updatePubspecAssets(pubspecPath, downloadedAssets);

        // Generate asset constants file
        await generateAssetConstants(downloadedAssets, projectPath);
    }

    return downloadedAssets;
}

/**
 * Generate asset export report for screens
 */
function generateAssetExportReport(exportedAssets: AssetInfo[]): string {
    if (exportedAssets.length === 0) {
        return '';
    }

    let report = `\n${'='.repeat(50)}\n`;
    report += `🖼️  SCREEN ASSET EXPORT\n`;
    report += `${'='.repeat(50)}\n\n`;
    
    report += `Found and exported ${exportedAssets.length} screen asset(s):\n\n`;

    // Group by base name for cleaner output
    const groupedAssets = groupAssetsByBaseName(exportedAssets);
    Object.entries(groupedAssets).forEach(([baseName, assets]) => {
        report += `📁 ${baseName}:\n`;
        assets.forEach(asset => {
            report += `   • ${asset.filename} (${asset.size})\n`;
        });
    });

    report += `\n✅ Assets Configuration:\n`;
    report += `   • Images saved to: assets/images/\n`;
    report += `   • pubspec.yaml updated with asset declarations\n`;
    report += `   • Asset constants generated in: lib/constants/assets.dart\n\n`;

    report += `🚀 Usage in Flutter Screen:\n`;
    report += `   import 'package:your_app/constants/assets.dart';\n\n`;
    
    exportedAssets.forEach(asset => {
        const constantName = asset.filename
            .replace(/\.[^/.]+$/, '') // Remove extension
            .replace(/[^a-zA-Z0-9]/g, '_') // Replace special chars with underscore
            .replace(/_+/g, '_') // Replace multiple underscores with single
            .replace(/^_|_$/g, '') // Remove leading/trailing underscores
            .toLowerCase();
        
        report += `   Image.asset(Assets.${constantName}) // ${asset.nodeName}\n`;
    });

    report += `\n${'='.repeat(50)}\n`;

    return report;
}

```

--------------------------------------------------------------------------------
/src/extractors/flutter/style-library.ts:
--------------------------------------------------------------------------------

```typescript
// src/extractors/flutter/style-library.mts

import { Logger } from '../../utils/logger.js';

export interface FlutterStyleDefinition {
  id: string;
  category: 'decoration' | 'text' | 'layout' | 'padding';
  properties: Record<string, any>;
  flutterCode: string;
  hash: string;
  semanticHash: string;
  usageCount: number;
  parentId?: string;
  childIds: string[];
  variance?: number; // How different from parent (0-1)
}

export interface StyleRelationship {
  parentId?: string;
  childIds: string[];
  variance: number; // How different from parent (0-1)
}

export interface OptimizationReport {
  totalStyles: number;
  duplicatesRemoved: number;
  variantsCreated: number;
  hierarchyDepth: number;
  memoryReduction: string;
}

export class FlutterStyleLibrary {
  private static instance: FlutterStyleLibrary;
  private styles = new Map<string, FlutterStyleDefinition>();
  private hashToId = new Map<string, string>();
  private semanticHashToId = new Map<string, string>();
  private autoOptimizeEnabled = true;
  private optimizationThreshold = 20; // Auto-optimize after every N styles
  private lastOptimizationCount = 0;
  
  static getInstance(): FlutterStyleLibrary {
    if (!this.instance) {
      this.instance = new FlutterStyleLibrary();
    }
    return this.instance;
  }
  
  addStyle(category: string, properties: any, context?: string): string {
    const hash = this.generateHash(properties);
    const semanticHash = this.generateSemanticHash(properties);
    
    Logger.info(`🎨 Adding ${category} style with properties:`, JSON.stringify(properties, null, 2));
    Logger.info(`📝 Generated hashes - Exact: ${hash.substring(0, 20)}..., Semantic: ${semanticHash.substring(0, 20)}...`);
    
    // Check for exact matches first
    if (this.hashToId.has(hash)) {
      const existingId = this.hashToId.get(hash)!;
      const style = this.styles.get(existingId)!;
      style.usageCount++;
      Logger.info(`✅ Exact match found! Reusing style ${existingId} (usage: ${style.usageCount})`);
      return existingId;
    }
    
    // Check for semantic equivalents
    if (this.semanticHashToId.has(semanticHash)) {
      const existingId = this.semanticHashToId.get(semanticHash)!;
      const style = this.styles.get(existingId)!;
      style.usageCount++;
      Logger.info(`🔍 Semantic match found! Reusing style ${existingId} (usage: ${style.usageCount})`);
      return existingId;
    }
    
    // Check if this should be a variant of existing style
    const parentStyle = this.findPotentialParent(properties);
    
    if (parentStyle) {
      const variance = this.calculateVariance(properties, parentStyle.properties);
      Logger.info(`🌳 Parent style found: ${parentStyle.id} (variance: ${(variance * 100).toFixed(1)}%)`);
    }
    
    const generatedId = this.generateId();
    const styleId = `${category}${generatedId.charAt(0).toUpperCase()}${generatedId.slice(1)}`;
    const definition: FlutterStyleDefinition = {
      id: styleId,
      category: category as any,
      properties,
      flutterCode: this.generateFlutterCode(category, properties),
      hash,
      semanticHash,
      usageCount: 1,
      parentId: parentStyle?.id,
      childIds: [],
      variance: parentStyle ? this.calculateVariance(properties, parentStyle.properties) : undefined
    };
    
    // Update parent-child relationships
    if (parentStyle) {
      parentStyle.childIds.push(styleId);
      Logger.info(`🔗 Updated parent ${parentStyle.id} with child ${styleId}`);
    }
    
    Logger.info(`✨ Created new style: ${styleId} (total styles: ${this.styles.size + 1})`);
    
    this.styles.set(styleId, definition);
    this.hashToId.set(hash, styleId);
    this.semanticHashToId.set(semanticHash, styleId);
    
    // Auto-optimize if threshold is reached
    this.checkAutoOptimization();
    
    return styleId;
  }
  
  getStyle(id: string): FlutterStyleDefinition | undefined {
    return this.styles.get(id);
  }
  
  getAllStyles(): FlutterStyleDefinition[] {
    return Array.from(this.styles.values());
  }
  
  findSimilarStyles(properties: any, threshold: number = 0.8): string[] {
    const similarStyles: string[] = [];
    
    for (const [id, style] of this.styles) {
      const similarity = this.calculateSimilarity(properties, style.properties);
      if (similarity >= threshold && similarity < 1.0) {
        similarStyles.push(id);
      }
    }
    
    return similarStyles;
  }
  
  getStyleHierarchy(): Record<string, StyleRelationship> {
    const hierarchy: Record<string, StyleRelationship> = {};
    
    for (const [id, style] of this.styles) {
      hierarchy[id] = {
        parentId: style.parentId,
        childIds: style.childIds,
        variance: style.variance || 0
      };
    }
    
    return hierarchy;
  }
  
  optimizeLibrary(): OptimizationReport {
    const beforeCount = this.styles.size;
    let duplicatesRemoved = 0;
    let variantsCreated = 0;
    let hierarchyDepth = 0;
    
    // Find and merge exact duplicates (shouldn't happen with current logic, but safety check)
    const hashGroups = new Map<string, string[]>();
    for (const [id, style] of this.styles) {
      const group = hashGroups.get(style.hash) || [];
      group.push(id);
      hashGroups.set(style.hash, group);
    }
    
    // Remove duplicates (keep first, redirect others)
    for (const [hash, ids] of hashGroups) {
      if (ids.length > 1) {
        const keepId = ids[0];
        const keepStyle = this.styles.get(keepId)!;
        
        for (let i = 1; i < ids.length; i++) {
          const removeId = ids[i];
          const removeStyle = this.styles.get(removeId)!;
          
          // Merge usage counts
          keepStyle.usageCount += removeStyle.usageCount;
          
          // Remove duplicate
          this.styles.delete(removeId);
          this.hashToId.delete(removeStyle.hash);
          this.semanticHashToId.delete(removeStyle.semanticHash);
          duplicatesRemoved++;
        }
      }
    }
    
    // Calculate hierarchy depth
    for (const style of this.styles.values()) {
      if (style.childIds.length > 0) {
        variantsCreated += style.childIds.length;
      }
      
      // Calculate depth from this node
      let depth = 0;
      let currentStyle = style;
      while (currentStyle.parentId) {
        depth++;
        currentStyle = this.styles.get(currentStyle.parentId)!;
        if (!currentStyle) break; // Safety check
      }
      hierarchyDepth = Math.max(hierarchyDepth, depth);
    }
    
    const afterCount = this.styles.size;
    const memoryReduction = beforeCount > 0 
      ? `${((beforeCount - afterCount) / beforeCount * 100).toFixed(1)}%`
      : '0%';
    
    return {
      totalStyles: afterCount,
      duplicatesRemoved,
      variantsCreated,
      hierarchyDepth,
      memoryReduction
    };
  }
  
  reset(): void {
    this.styles.clear();
    this.hashToId.clear();
    this.semanticHashToId.clear();
    this.lastOptimizationCount = 0;
  }
  
  setAutoOptimization(enabled: boolean, threshold: number = 20): void {
    this.autoOptimizeEnabled = enabled;
    this.optimizationThreshold = threshold;
    Logger.info(`⚙️  Auto-optimization ${enabled ? 'enabled' : 'disabled'} (threshold: ${threshold})`);
  }
  
  private checkAutoOptimization(): void {
    if (!this.autoOptimizeEnabled) return;
    
    const currentCount = this.styles.size;
    const stylesSinceLastOptimization = currentCount - this.lastOptimizationCount;
    
    if (stylesSinceLastOptimization >= this.optimizationThreshold) {
      Logger.info(`🚀 Auto-optimization triggered! (${stylesSinceLastOptimization} new styles since last optimization)`);
      this.runAutoOptimization();
      this.lastOptimizationCount = currentCount;
    }
  }
  
  private runAutoOptimization(): OptimizationReport {
    Logger.info(`⚡ Running auto-optimization...`);
    const report = this.optimizeLibrary();
    Logger.info(`✅ Auto-optimization complete:`, {
      totalStyles: report.totalStyles,
      duplicatesRemoved: report.duplicatesRemoved,
      variantsCreated: report.variantsCreated,
      hierarchyDepth: report.hierarchyDepth,
      memoryReduction: report.memoryReduction
    });
    return report;
  }
  
  private generateHash(properties: any): string {
    // Use a more robust hash generation that preserves nested object properties
    return JSON.stringify(properties, (key, value) => {
      if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
        // Sort object keys for consistent hashing
        const sortedObj: any = {};
        Object.keys(value).sort().forEach(k => {
          sortedObj[k] = value[k];
        });
        return sortedObj;
      }
      return value;
    });
  }
  
  private generateSemanticHash(properties: any): string {
    // Normalize property values before hashing
    const normalized = this.normalizeProperties(properties);
    Logger.info(`🔄 Normalized properties:`, JSON.stringify(normalized, null, 2));
    
    // Create semantic fingerprint that catches equivalent styles
    const semanticKey = this.createSemanticKey(normalized);
    Logger.info(`🔑 Semantic key:`, JSON.stringify(semanticKey, null, 2));
    
    return this.hashObject(semanticKey);
  }
  
  private normalizeProperties(properties: any): any {
    const normalized = JSON.parse(JSON.stringify(properties)); // Deep copy
    
    // Normalize color representations
    if (normalized.fills) {
      normalized.fills = normalized.fills.map((fill: any) => {
        if (fill.hex) {
          // Normalize hex colors (e.g., #000000 -> #000000, #000 -> #000000)
          let hex = fill.hex.toLowerCase();
          if (hex === '#000') hex = '#000000';
          if (hex === '#fff') hex = '#ffffff';
          
          const normalizedFill = { ...fill, hex };
          if (hex === '#000000') normalizedFill.normalized = 'black';
          if (hex === '#ffffff') normalizedFill.normalized = 'white';
          
          return normalizedFill;
        }
        return fill;
      });
    }
    
    // Normalize padding representations
    if (normalized.padding) {
      const p = normalized.padding;
      // EdgeInsets.all(8) === EdgeInsets.fromLTRB(8,8,8,8)
      if (p.top === p.right && p.right === p.bottom && p.bottom === p.left) {
        normalized.padding = { uniform: p.top, isUniform: true };
      }
    }
    
    // Normalize border radius
    if (normalized.cornerRadius && typeof normalized.cornerRadius === 'object') {
      const r = normalized.cornerRadius;
      if (r.topLeft === r.topRight && r.topRight === r.bottomLeft && r.bottomLeft === r.bottomRight) {
        normalized.cornerRadius = r.topLeft;
      }
    }
    
    return normalized;
  }
  
  private createSemanticKey(properties: any): any {
    // Create a semantic representation that focuses on visual impact
    const key: any = {};
    
    // Group similar properties - be more specific to avoid false matches
    if (properties.fills && properties.fills.length > 0) {
      // Use the actual hex value to distinguish different colors
      key.color = properties.fills[0].hex?.toLowerCase();
    }
    
    if (properties.cornerRadius !== undefined) {
      key.borderRadius = typeof properties.cornerRadius === 'number' 
        ? properties.cornerRadius 
        : JSON.stringify(properties.cornerRadius);
    }
    
    if (properties.padding) {
      key.padding = properties.padding.isUniform 
        ? properties.padding.uniform 
        : JSON.stringify(properties.padding);
    }
    
    if (properties.effects?.dropShadows?.length > 0) {
      key.hasShadow = true;
      key.shadowIntensity = properties.effects.dropShadows.length;
      // Include shadow details for more specificity
      key.shadowDetails = properties.effects.dropShadows.map((s: any) => ({
        color: s.hex,
        blur: s.radius,
        offset: s.offset
      }));
    }
    
    return key;
  }
  
  private hashObject(obj: any): string {
    return JSON.stringify(obj, Object.keys(obj).sort());
  }
  
  private findPotentialParent(properties: any, threshold: number = 0.8): FlutterStyleDefinition | undefined {
    const allStyles = Array.from(this.styles.values());
    
    for (const style of allStyles) {
      const similarity = this.calculateSimilarity(properties, style.properties);
      if (similarity >= threshold && similarity < 1.0) {
        return style;
      }
    }
    
    return undefined;
  }
  
  private calculateSimilarity(props1: any, props2: any): number {
    const keys1 = new Set(Object.keys(props1));
    const keys2 = new Set(Object.keys(props2));
    const allKeys = new Set([...keys1, ...keys2]);
    
    let matches = 0;
    let total = allKeys.size;
    
    for (const key of allKeys) {
      if (keys1.has(key) && keys2.has(key)) {
        // Both have the key, check if values are similar
        if (this.areValuesSimilar(props1[key], props2[key])) {
          matches++;
        }
      }
      // If only one has the key, it's a difference (no match)
    }
    
    return total > 0 ? matches / total : 0;
  }
  
  private areValuesSimilar(val1: any, val2: any): boolean {
    if (val1 === val2) return true;
    
    // Handle arrays (like fills)
    if (Array.isArray(val1) && Array.isArray(val2)) {
      if (val1.length !== val2.length) return false;
      return val1.every((item, index) => this.areValuesSimilar(item, val2[index]));
    }
    
    // Handle objects
    if (typeof val1 === 'object' && typeof val2 === 'object' && val1 !== null && val2 !== null) {
      const keys1 = Object.keys(val1);
      const keys2 = Object.keys(val2);
      if (keys1.length !== keys2.length) return false;
      return keys1.every(key => this.areValuesSimilar(val1[key], val2[key]));
    }
    
    // Handle numbers with tolerance
    if (typeof val1 === 'number' && typeof val2 === 'number') {
      return Math.abs(val1 - val2) < 0.01;
    }
    
    return false;
  }
  
  private calculateVariance(childProps: any, parentProps: any): number {
    const similarity = this.calculateSimilarity(childProps, parentProps);
    return 1 - similarity; // Variance is inverse of similarity
  }
  
  private generateId(): string {
    return Date.now().toString(36) + Math.random().toString(36).substr(2, 4);
  }
  
  private generateFlutterCode(category: string, properties: any): string {
    switch (category) {
      case 'decoration':
        return FlutterCodeGenerator.generateDecoration(properties);
      case 'text':
        return FlutterCodeGenerator.generateTextStyle(properties);
      case 'padding':
        return FlutterCodeGenerator.generatePadding(properties);
      case 'layout':
        // Layout code generation can be added later
        return `// ${category} implementation`;
      default:
        return `// ${category} implementation`;
    }
  }
}

export class FlutterCodeGenerator {
  static generateDecoration(properties: any): string {
    let code = 'BoxDecoration(\n';
    
    if (properties.fills?.length > 0) {
      const fill = properties.fills[0];
      if (fill.hex) {
        code += `  color: Color(0xFF${fill.hex.substring(1)}),\n`;
      }
    }
    
    if (properties.cornerRadius !== undefined) {
      if (typeof properties.cornerRadius === 'number') {
        code += `  borderRadius: BorderRadius.circular(${properties.cornerRadius}),\n`;
      } else {
        const r = properties.cornerRadius;
        code += `  borderRadius: BorderRadius.only(\n`;
        code += `    topLeft: Radius.circular(${r.topLeft}),\n`;
        code += `    topRight: Radius.circular(${r.topRight}),\n`;
        code += `    bottomLeft: Radius.circular(${r.bottomLeft}),\n`;
        code += `    bottomRight: Radius.circular(${r.bottomRight}),\n`;
        code += `  ),\n`;
      }
    }
    
    if (properties.effects?.dropShadows?.length > 0) {
      code += `  boxShadow: [\n`;
      properties.effects.dropShadows.forEach((shadow: any) => {
        code += `    BoxShadow(\n`;
        code += `      color: Color(0xFF${shadow.hex.substring(1)}).withOpacity(${shadow.opacity}),\n`;
        code += `      offset: Offset(${shadow.offset.x}, ${shadow.offset.y}),\n`;
        code += `      blurRadius: ${shadow.radius},\n`;
        if (shadow.spread) {
          code += `      spreadRadius: ${shadow.spread},\n`;
        }
        code += `    ),\n`;
      });
      code += `  ],\n`;
    }
    
    code += ')';
    return code;
  }
  
  static generatePadding(properties: any): string {
    const p = properties.padding;
    if (!p) return 'EdgeInsets.zero';
    
    if (p.isUniform) {
      return `EdgeInsets.all(${p.top})`;
    }
    return `EdgeInsets.fromLTRB(${p.left}, ${p.top}, ${p.right}, ${p.bottom})`;
  }
  
  static generateTextStyle(properties: any): string {
    const parts: string[] = [];
    
    if (properties.fontFamily) {
      parts.push(`fontFamily: '${properties.fontFamily}'`);
    }
    if (properties.fontSize) {
      parts.push(`fontSize: ${properties.fontSize}`);
    }
    if (properties.fontWeight && properties.fontWeight !== 400) {
      const weight = properties.fontWeight >= 700 ? 'FontWeight.bold' : 
                    properties.fontWeight >= 600 ? 'FontWeight.w600' :
                    properties.fontWeight >= 500 ? 'FontWeight.w500' :
                    'FontWeight.normal';
      parts.push(`fontWeight: ${weight}`);
    }
    
    return `TextStyle(${parts.join(', ')})`;
  }
}

```

--------------------------------------------------------------------------------
/src/tools/flutter/screens/helpers.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/screens/helpers.mts

import type {ScreenAnalysis, ScreenSection, NavigationElement, ScreenAssetInfo} from "../../../extractors/screens/types.js";
import {generateScreenVisualContext} from "../visual-context.js";

/**
 * Generate comprehensive screen analysis report
 */
export function generateScreenAnalysisReport(
    analysis: ScreenAnalysis,
    parsedInput?: any
): string {
    let output = `Screen Analysis Report\n\n`;

    // Screen metadata
    output += `Screen: ${analysis.metadata.name}\n`;
    output += `Type: ${analysis.metadata.type}\n`;
    output += `Node ID: ${analysis.metadata.nodeId}\n`;
    output += `Device Type: ${analysis.metadata.deviceType}\n`;
    output += `Orientation: ${analysis.metadata.orientation}\n`;
    output += `Dimensions: ${Math.round(analysis.metadata.dimensions.width)}×${Math.round(analysis.metadata.dimensions.height)}px\n`;
    if (parsedInput) {
        output += `Source: ${parsedInput.source === 'url' ? 'Figma URL' : 'Direct input'}\n`;
    }
    output += `\n`;

    // Screen layout information
    output += `Screen Layout:\n`;
    output += `- Layout Type: ${analysis.layout.type}\n`;
    if (analysis.layout.scrollable) {
        output += `- Scrollable: Yes\n`;
    }
    if (analysis.layout.hasHeader) {
        output += `- Has Header: Yes\n`;
    }
    if (analysis.layout.hasFooter) {
        output += `- Has Footer: Yes\n`;
    }
    if (analysis.layout.hasNavigation) {
        output += `- Has Navigation: Yes\n`;
    }
    if (analysis.layout.contentArea) {
        const area = analysis.layout.contentArea;
        output += `- Content Area: ${Math.round(area.width)}×${Math.round(area.height)}px at (${Math.round(area.x)}, ${Math.round(area.y)})\n`;
    }
    output += `\n`;

    // Screen sections
    if (analysis.sections.length > 0) {
        output += `Screen Sections (${analysis.sections.length} identified):\n`;
        analysis.sections.forEach((section, index) => {
            output += `${index + 1}. ${section.name} (${section.type.toUpperCase()})\n`;
            output += `   Priority: ${section.importance}/10\n`;
            
            if (section.layout.dimensions) {
                const dims = section.layout.dimensions;
                output += `   Size: ${Math.round(dims.width)}×${Math.round(dims.height)}px\n`;
            }
            
            if (section.children.length > 0) {
                output += `   Contains: ${section.children.length} elements\n`;
            }
            
            if (section.components.length > 0) {
                output += `   Components: ${section.components.length} nested component(s)\n`;
            }
        });
        output += `\n`;
    }

    // Navigation information
    if (analysis.navigation.navigationElements.length > 0) {
        output += `Navigation Elements:\n`;
        
        if (analysis.navigation.hasTabBar) output += `- Has Tab Bar\n`;
        if (analysis.navigation.hasAppBar) output += `- Has App Bar\n`;
        if (analysis.navigation.hasDrawer) output += `- Has Drawer\n`;
        if (analysis.navigation.hasBottomSheet) output += `- Has Bottom Sheet\n`;
        
        output += `\nNavigation Items (${analysis.navigation.navigationElements.length}):\n`;
        analysis.navigation.navigationElements.forEach((nav, index) => {
            const activeMark = nav.isActive ? ' [ACTIVE]' : '';
            const iconMark = nav.icon ? ' 🎯' : '';
            output += `${index + 1}. ${nav.name} (${nav.type.toUpperCase()})${activeMark}${iconMark}\n`;
            if (nav.text) {
                output += `   Text: "${nav.text}"\n`;
            }
        });
        output += `\n`;
    }

    // Assets information
    if (analysis.assets.length > 0) {
        output += `Screen Assets (${analysis.assets.length} found):\n`;
        
        const assetsByType = groupAssetsByType(analysis.assets);
        Object.entries(assetsByType).forEach(([type, assets]) => {
            output += `${type.toUpperCase()} (${assets.length}):\n`;
            assets.forEach(asset => {
                output += `- ${asset.name} (${asset.size}, ${asset.usage})\n`;
            });
        });
        output += `\n`;
    }

    // Nested components for separate analysis
    if (analysis.components.length > 0) {
        output += `Nested Components Found (${analysis.components.length}):\n`;
        output += `These components should be analyzed separately:\n`;
        analysis.components.forEach((comp, index) => {
            output += `${index + 1}. ${comp.name}\n`;
            output += `   Node ID: ${comp.nodeId}\n`;
            output += `   Type: ${comp.instanceType || 'COMPONENT'}\n`;
            if (comp.componentKey) {
                output += `   Component Key: ${comp.componentKey}\n`;
            }
        });
        output += `\n`;
    }

    // Skipped nodes report
    if (analysis.skippedNodes && analysis.skippedNodes.length > 0) {
        output += `Analysis Limitations:\n`;
        
        const deviceUISkipped = analysis.skippedNodes.filter(node => node.reason === 'device_ui_element');
        const limitSkipped = analysis.skippedNodes.filter(node => node.reason === 'max_sections');
        
        if (deviceUISkipped.length > 0) {
            output += `${deviceUISkipped.length} device UI elements were automatically filtered out:\n`;
            deviceUISkipped.forEach((skipped, index) => {
                output += `${index + 1}. ${skipped.name} (${skipped.type}) - device UI placeholder\n`;
            });
            output += `\n`;
        }
        
        if (limitSkipped.length > 0) {
            output += `${limitSkipped.length} sections were skipped due to limits:\n`;
            limitSkipped.forEach((skipped, index) => {
                output += `${index + 1}. ${skipped.name} (${skipped.type}) - ${skipped.reason}\n`;
            });
            output += `\nTo analyze all sections, increase the maxSections parameter.\n`;
        }
        
        output += `\n`;
    }

    // Visual context for AI implementation
    if (parsedInput?.source === 'url') {
        // Reconstruct the Figma URL from the parsed input
        const figmaUrl = `https://www.figma.com/design/${parsedInput.fileId}/?node-id=${parsedInput.nodeId}`;
        output += generateScreenVisualContext(analysis, figmaUrl, parsedInput.nodeId);
        output += `\n`;
    }

    // Flutter implementation guidance
    output += generateFlutterScreenGuidance(analysis);

    return output;
}

/**
 * Generate screen structure inspection report
 */
export function generateScreenStructureReport(node: any, showAllSections: boolean): string {
    let output = `Screen Structure Inspection\n\n`;

    output += `Screen: ${node.name}\n`;
    output += `Type: ${node.type}\n`;
    output += `Node ID: ${node.id}\n`;
    output += `Sections: ${node.children?.length || 0}\n`;

    if (node.absoluteBoundingBox) {
        const bbox = node.absoluteBoundingBox;
        output += `Dimensions: ${Math.round(bbox.width)}×${Math.round(bbox.height)}px\n`;
        
        // Device type detection
        const deviceType = bbox.width > bbox.height ? 'Landscape' : 'Portrait';
        const screenSize = Math.max(bbox.width, bbox.height) > 1200 ? 'Desktop' : 
                          Math.max(bbox.width, bbox.height) > 800 ? 'Tablet' : 'Mobile';
        output += `Device: ${screenSize} ${deviceType}\n`;
    }

    output += `\n`;

    if (!node.children || node.children.length === 0) {
        output += `This screen has no sections.\n`;
        return output;
    }

    output += `Screen Structure:\n`;

    const sectionsToShow = showAllSections ? node.children : node.children.slice(0, 20);
    const hasMore = node.children.length > sectionsToShow.length;

    sectionsToShow.forEach((section: any, index: number) => {
        const isComponent = section.type === 'COMPONENT' || section.type === 'INSTANCE';
        const componentMark = isComponent ? ' [COMPONENT]' : '';
        const hiddenMark = section.visible === false ? ' [HIDDEN]' : '';
        
        // Detect section type
        const sectionType = detectSectionTypeFromName(section.name);
        const typeMark = sectionType !== 'content' ? ` [${sectionType.toUpperCase()}]` : '';

        output += `${index + 1}. ${section.name} (${section.type})${componentMark}${typeMark}${hiddenMark}\n`;

        if (section.absoluteBoundingBox) {
            const bbox = section.absoluteBoundingBox;
            output += `   Size: ${Math.round(bbox.width)}×${Math.round(bbox.height)}px\n`;
            output += `   Position: (${Math.round(bbox.x)}, ${Math.round(bbox.y)})\n`;
        }

        if (section.children && section.children.length > 0) {
            output += `   Contains: ${section.children.length} child elements\n`;
            
            // Show component count
            const componentCount = section.children.filter((child: any) => 
                child.type === 'COMPONENT' || child.type === 'INSTANCE'
            ).length;
            if (componentCount > 0) {
                output += `   Components: ${componentCount} nested component(s)\n`;
            }
        }

        // Show basic styling info
        if (section.fills && section.fills.length > 0) {
            const fill = section.fills[0];
            if (fill.color) {
                const hex = rgbaToHex(fill.color);
                output += `   Background: ${hex}\n`;
            }
        }
    });

    if (hasMore) {
        output += `\n... and ${node.children.length - sectionsToShow.length} more sections.\n`;
        output += `Use showAllSections: true to see all sections.\n`;
    }

    // Analysis recommendations
    output += `\nAnalysis Recommendations:\n`;
    
    const componentSections = node.children.filter((section: any) =>
        section.type === 'COMPONENT' || section.type === 'INSTANCE'
    );
    if (componentSections.length > 0) {
        output += `- Found ${componentSections.length} component sections for separate analysis\n`;
    }

    const largeSections = node.children.filter((section: any) => {
        const bbox = section.absoluteBoundingBox;
        return bbox && (bbox.width * bbox.height) > 20000;
    });
    if (largeSections.length > 5) {
        output += `- Screen has ${largeSections.length} large sections - consider increasing maxSections\n`;
    }

    // Detect navigation elements
    const navSections = node.children.filter((section: any) => {
        const name = section.name.toLowerCase();
        return name.includes('nav') || name.includes('tab') || name.includes('menu') || 
               name.includes('header') || name.includes('footer');
    });
    if (navSections.length > 0) {
        output += `- Found ${navSections.length} navigation-related sections\n`;
    }

    return output;
}

/**
 * Generate Flutter screen implementation guidance
 */
export function generateFlutterScreenGuidance(analysis: ScreenAnalysis): string {
    let guidance = `Flutter Screen Implementation Guidance:\n\n`;

    // Widget composition best practices
    guidance += `🏗️  Widget Composition Best Practices:\n`;
    guidance += `- Start by building the complete screen widget tree in a single build() method\n`;
    guidance += `- Keep composing widgets inline until you reach ~250 lines of code\n`;
    guidance += `- Only then break down into private StatelessWidget classes for sections\n`;
    guidance += `- Use private widgets (prefix with _) for internal screen component breakdown\n`;
    guidance += `- Avoid functional widgets - always use StatelessWidget classes\n\n`;
    
    guidance += `📱 Device UI Filtering:\n`;
    guidance += `- Status bars, battery icons, wifi indicators are automatically filtered out\n`;
    guidance += `- Home indicators, notches, and device bezels are ignored during analysis\n`;
    guidance += `- Only actual app design content is analyzed for Flutter implementation\n`;
    guidance += `- Use SafeArea widget in Flutter to handle device-specific insets\n\n`;

    // Main scaffold structure
    guidance += `Main Screen Structure:\n`;
    guidance += `Scaffold(\n`;
    
    // App bar
    if (analysis.navigation.hasAppBar) {
        guidance += `  appBar: AppBar(\n`;
        guidance += `    title: Text('${analysis.metadata.name}'),\n`;
        guidance += `    // Add app bar actions and styling\n`;
        guidance += `  ),\n`;
    }
    
    // Drawer
    if (analysis.navigation.hasDrawer) {
        guidance += `  drawer: Drawer(\n`;
        guidance += `    // Add drawer content\n`;
        guidance += `  ),\n`;
    }
    
    // Body structure
    guidance += `  body: `;
    
    if (analysis.layout.scrollable) {
        guidance += `SingleChildScrollView(\n`;
        guidance += `    child: Column(\n`;
        guidance += `      children: [\n`;
    } else {
        guidance += `Column(\n`;
        guidance += `    children: [\n`;
    }
    
    // Add sections
    analysis.sections.forEach((section, index) => {
        const widgetName = toPascalCase(section.name);
        guidance += `        ${widgetName}(), // ${section.type} section\n`;
    });
    
    guidance += `      ],\n`;
    guidance += `    ),\n`;
    
    if (analysis.layout.scrollable) {
        guidance += `  ),\n`;
    }
    
    // Bottom navigation
    if (analysis.navigation.hasTabBar) {
        guidance += `  bottomNavigationBar: BottomNavigationBar(\n`;
        guidance += `    items: [\n`;
        
        const tabItems = analysis.navigation.navigationElements.filter(nav => nav.type === 'tab');
        tabItems.slice(0, 5).forEach(tab => {
            guidance += `      BottomNavigationBarItem(\n`;
            guidance += `        icon: Icon(Icons.${tab.icon ? 'placeholder' : 'home'}),\n`;
            guidance += `        label: '${tab.text || tab.name}',\n`;
            guidance += `      ),\n`;
        });
        
        guidance += `    ],\n`;
        guidance += `  ),\n`;
    }
    
    guidance += `)\n\n`;

    // Section widgets guidance
    if (analysis.sections.length > 0) {
        guidance += `Section Widgets:\n`;
        analysis.sections.forEach((section, index) => {
            const widgetName = toPascalCase(section.name);
            guidance += `${index + 1}. ${widgetName}() - ${section.type} section\n`;
            guidance += `   Elements: ${section.children.length} child elements\n`;
            if (section.components.length > 0) {
                guidance += `   Components: ${section.components.length} nested components\n`;
            }
        });
        guidance += `\n`;
    }

    // Navigation guidance
    if (analysis.navigation.navigationElements.length > 0) {
        guidance += `Navigation Implementation:\n`;
        
        const buttons = analysis.navigation.navigationElements.filter(nav => nav.type === 'button');
        const tabs = analysis.navigation.navigationElements.filter(nav => nav.type === 'tab');
        const links = analysis.navigation.navigationElements.filter(nav => nav.type === 'link');
        
        if (buttons.length > 0) {
            guidance += `Buttons (${buttons.length}):\n`;
            buttons.forEach(button => {
                guidance += `- ElevatedButton(onPressed: () {}, child: Text('${button.text || button.name}'))\n`;
            });
        }
        
        if (tabs.length > 0) {
            guidance += `Tab Navigation (${tabs.length}):\n`;
            guidance += `- Use TabBar with ${tabs.length} tabs\n`;
            guidance += `- Consider TabBarView for content switching\n`;
        }
        
        if (links.length > 0) {
            guidance += `Links (${links.length}):\n`;
            links.forEach(link => {
                guidance += `- TextButton(onPressed: () {}, child: Text('${link.text || link.name}'))\n`;
            });
        }
        
        guidance += `\n`;
    }

    // Asset guidance
    if (analysis.assets.length > 0) {
        guidance += `Assets Implementation:\n`;
        
        const images = analysis.assets.filter(asset => asset.type === 'image');
        const icons = analysis.assets.filter(asset => asset.type === 'icon');
        const illustrations = analysis.assets.filter(asset => asset.type === 'illustration');
        
        if (images.length > 0) {
            guidance += `Images (${images.length}): Use Image.asset() or Image.network()\n`;
        }
        
        if (icons.length > 0) {
            guidance += `Icons (${icons.length}): Use Icon() widget with appropriate IconData\n`;
        }
        
        if (illustrations.length > 0) {
            guidance += `Illustrations (${illustrations.length}): Use SvgPicture or Image.asset()\n`;
        }
        
        guidance += `\n`;
    }

    // Responsive design guidance
    guidance += `Responsive Design:\n`;
    guidance += `- Device Type: ${analysis.metadata.deviceType}\n`;
    guidance += `- Orientation: ${analysis.metadata.orientation}\n`;
    
    if (analysis.metadata.deviceType === 'mobile') {
        guidance += `- Optimize for mobile: Use SingleChildScrollView, consider bottom navigation\n`;
    } else if (analysis.metadata.deviceType === 'tablet') {
        guidance += `- Tablet layout: Consider using NavigationRail or side navigation\n`;
    } else if (analysis.metadata.deviceType === 'desktop') {
        guidance += `- Desktop layout: Use NavigationRail, consider multi-column layouts\n`;
    }

    return guidance;
}

// Helper functions
function groupAssetsByType(assets: ScreenAssetInfo[]): Record<string, ScreenAssetInfo[]> {
    return assets.reduce((acc, asset) => {
        if (!acc[asset.type]) {
            acc[asset.type] = [];
        }
        acc[asset.type].push(asset);
        return acc;
    }, {} as Record<string, ScreenAssetInfo[]>);
}

function detectSectionTypeFromName(name: string): string {
    const lowerName = name.toLowerCase();
    
    if (lowerName.includes('header') || lowerName.includes('app bar')) return 'header';
    if (lowerName.includes('footer') || lowerName.includes('bottom')) return 'footer';
    if (lowerName.includes('nav') || lowerName.includes('menu')) return 'navigation';
    if (lowerName.includes('modal') || lowerName.includes('dialog')) return 'modal';
    if (lowerName.includes('sidebar')) return 'sidebar';
    
    return 'content';
}

function toPascalCase(str: string): string {
    return str
        .replace(/[^a-zA-Z0-9]/g, ' ')
        .replace(/\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
        .replace(/\s/g, '');
}

function rgbaToHex(color: {r: number; g: number; b: number; a?: number}): string {
    const r = Math.round(color.r * 255);
    const g = Math.round(color.g * 255);
    const b = Math.round(color.b * 255);

    return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toUpperCase();
}

```

--------------------------------------------------------------------------------
/src/tools/flutter/visual-context.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/visual-context.ts

import type { ComponentAnalysis } from '../../extractors/components/types.js';
import type { ScreenAnalysis } from '../../extractors/screens/types.js';

/**
 * Generate visual context for component analysis
 */
export function generateComponentVisualContext(
    analysis: ComponentAnalysis, 
    figmaUrl?: string,
    nodeId?: string
): string {
    let context = `📐 Visual Context for AI Implementation:\n`;
    context += `${'='.repeat(50)}\n\n`;

    // Design reference
    if (figmaUrl) {
        context += `🎨 Design Reference:\n`;
        context += `   • Figma URL: ${figmaUrl}\n`;
        if (nodeId) {
            context += `   • Node ID: ${nodeId}\n`;
        }
        context += `   • Component: ${analysis.metadata.name}\n`;
        context += `   • Type: ${analysis.metadata.type}\n\n`;
    }

    // ASCII layout representation
    context += `📏 Layout Structure:\n`;
    context += generateComponentAsciiLayout(analysis);
    context += `\n`;

    // Spatial relationships
    context += `📍 Spatial Relationships:\n`;
    context += generateComponentSpatialDescription(analysis);
    context += `\n`;

    // Visual patterns
    context += `🎯 Visual Design Patterns:\n`;
    context += generateComponentPatternDescription(analysis);
    context += `\n`;

    // Implementation guidance
    context += `💡 Implementation Guidance:\n`;
    context += generateComponentImplementationHints(analysis);
    
    // Semantic detection information
    context += `\n🧠 Enhanced Semantic Detection:\n`;
    context += `   • Multi-factor analysis with confidence scoring\n`;
    context += `   • Context-aware classification using position and parent information\n`;
    context += `   • Design pattern recognition for improved accuracy\n`;
    context += `   • Fallback to legacy detection for low-confidence classifications\n`;
    context += `   • Reduced false positives through evidence-based classification\n`;

    return context;
}

/**
 * Generate visual context for screen analysis
 */
export function generateScreenVisualContext(
    analysis: ScreenAnalysis,
    figmaUrl?: string,
    nodeId?: string
): string {
    let context = `📱 Screen Visual Context for AI Implementation:\n`;
    context += `${'='.repeat(55)}\n\n`;

    // Design reference
    if (figmaUrl) {
        context += `🎨 Design Reference:\n`;
        context += `   • Figma URL: ${figmaUrl}\n`;
        if (nodeId) {
            context += `   • Node ID: ${nodeId}\n`;
        }
        context += `   • Screen: ${analysis.metadata.name}\n`;
        context += `   • Device: ${analysis.metadata.deviceType} (${analysis.metadata.orientation})\n\n`;
    }

    // Screen layout with ASCII representation
    context += `📏 Screen Layout Structure:\n`;
    context += generateScreenAsciiLayout(analysis);
    context += `\n`;

    // Visual hierarchy
    context += `📊 Visual Hierarchy (top to bottom):\n`;
    context += generateScreenHierarchy(analysis);
    context += `\n`;

    // Spatial relationships
    context += `📍 Component Spatial Relationships:\n`;
    context += generateScreenSpatialDescription(analysis);
    context += `\n`;

    // Design patterns
    context += `🎯 Visual Design Patterns Detected:\n`;
    context += generateScreenPatternDescription(analysis);
    context += `\n`;

    // Implementation guidance
    context += `💡 Flutter Implementation Strategy:\n`;
    context += generateScreenImplementationHints(analysis);
    
    // Semantic detection information
    context += `\n🧠 Enhanced Semantic Detection:\n`;
    context += `   • Advanced section type detection with confidence scoring\n`;
    context += `   • Multi-factor analysis for text element classification\n`;
    context += `   • Context-aware position and styling analysis\n`;
    context += `   • Improved navigation and interactive element detection\n`;
    context += `   • Reduced misclassification through evidence-based decisions\n`;

    if (figmaUrl) {
        context += `\n🔗 Reference for Verification:\n`;
        context += `   View the original design at: ${figmaUrl}\n`;
        context += `   Use this to verify your implementation matches the intended visual design.\n`;
    }

    return context;
}

/**
 * Generate ASCII layout for component
 */
function generateComponentAsciiLayout(analysis: ComponentAnalysis): string {
    const width = Math.min(Math.max(Math.round(analysis.layout.dimensions.width / 20), 10), 50);
    const height = Math.min(Math.max(Math.round(analysis.layout.dimensions.height / 20), 3), 10);
    
    let ascii = `┌${'─'.repeat(width)}┐\n`;
    
    // Add component name in the middle
    const nameLines = Math.floor(height / 2);
    for (let i = 0; i < height; i++) {
        if (i === nameLines) {
            const name = analysis.metadata.name.substring(0, width - 2);
            const padding = Math.max(0, Math.floor((width - name.length) / 2));
            ascii += `│${' '.repeat(padding)}${name}${' '.repeat(width - padding - name.length)}│\n`;
        } else {
            ascii += `│${' '.repeat(width)}│\n`;
        }
    }
    
    ascii += `└${'─'.repeat(width)}┘\n`;
    ascii += `Dimensions: ${Math.round(analysis.layout.dimensions.width)}×${Math.round(analysis.layout.dimensions.height)}px\n`;
    
    // Add layout type indicator
    if (analysis.layout.type === 'auto-layout') {
        const direction = analysis.layout.direction === 'horizontal' ? '↔' : '↕';
        ascii += `Layout: Auto-layout ${direction} (${analysis.layout.direction})\n`;
        if (analysis.layout.spacing) {
            ascii += `Spacing: ${analysis.layout.spacing}px\n`;
        }
    }

    return ascii;
}

/**
 * Generate ASCII layout for screen
 */
function generateScreenAsciiLayout(analysis: ScreenAnalysis): string {
    const screenWidth = Math.min(Math.max(Math.round(analysis.metadata.dimensions.width / 30), 15), 40);
    const screenHeight = Math.min(Math.max(Math.round(analysis.metadata.dimensions.height / 40), 8), 20);
    
    let ascii = `📱 Screen Layout Map:\n`;
    ascii += `┌${'─'.repeat(screenWidth)}┐\n`;
    
    // Categorize sections by position
    const headerSections = analysis.sections.filter(s => s.type === 'header');
    const contentSections = analysis.sections.filter(s => s.type === 'content');
    const footerSections = analysis.sections.filter(s => s.type === 'footer');
    const navSections = analysis.sections.filter(s => s.type === 'navigation');
    
    let currentLine = 0;
    
    // Header area
    if (headerSections.length > 0) {
        const headerLines = Math.ceil(screenHeight * 0.15);
        for (let i = 0; i < headerLines && currentLine < screenHeight; i++) {
            if (i === Math.floor(headerLines / 2)) {
                const text = 'HEADER';
                const padding = Math.max(0, Math.floor((screenWidth - text.length) / 2));
                ascii += `│${' '.repeat(padding)}${text}${' '.repeat(screenWidth - padding - text.length)}│\n`;
            } else {
                ascii += `│${' '.repeat(screenWidth)}│\n`;
            }
            currentLine++;
        }
    }
    
    // Content area
    const contentLines = screenHeight - currentLine - (footerSections.length > 0 ? Math.ceil(screenHeight * 0.15) : 0);
    for (let i = 0; i < contentLines && currentLine < screenHeight; i++) {
        if (i === Math.floor(contentLines / 2)) {
            const text = 'CONTENT';
            const padding = Math.max(0, Math.floor((screenWidth - text.length) / 2));
            ascii += `│${' '.repeat(padding)}${text}${' '.repeat(screenWidth - padding - text.length)}│\n`;
        } else {
            ascii += `│${' '.repeat(screenWidth)}│\n`;
        }
        currentLine++;
    }
    
    // Footer area
    if (footerSections.length > 0) {
        const remainingLines = screenHeight - currentLine;
        for (let i = 0; i < remainingLines; i++) {
            if (i === Math.floor(remainingLines / 2)) {
                const text = navSections.length > 0 ? 'NAVIGATION' : 'FOOTER';
                const padding = Math.max(0, Math.floor((screenWidth - text.length) / 2));
                ascii += `│${' '.repeat(padding)}${text}${' '.repeat(screenWidth - padding - text.length)}│\n`;
            } else {
                ascii += `│${' '.repeat(screenWidth)}│\n`;
            }
        }
    }
    
    ascii += `└${'─'.repeat(screenWidth)}┘\n`;
    ascii += `Screen: ${Math.round(analysis.metadata.dimensions.width)}×${Math.round(analysis.metadata.dimensions.height)}px (${analysis.metadata.deviceType})\n`;

    return ascii;
}

/**
 * Generate component spatial description
 */
function generateComponentSpatialDescription(analysis: ComponentAnalysis): string {
    let description = '';
    
    // Layout analysis
    if (analysis.layout.type === 'auto-layout') {
        description += `   • Layout flow: ${analysis.layout.direction} auto-layout\n`;
        if (analysis.layout.spacing) {
            description += `   • Element spacing: ${analysis.layout.spacing}px consistent\n`;
        }
        if (analysis.layout.alignItems) {
            description += `   • Cross-axis alignment: ${analysis.layout.alignItems}\n`;
        }
        if (analysis.layout.justifyContent) {
            description += `   • Main-axis alignment: ${analysis.layout.justifyContent}\n`;
        }
    } else {
        description += `   • Layout flow: absolute positioning\n`;
    }

    // Padding analysis
    if (analysis.layout.padding) {
        const p = analysis.layout.padding;
        if (p.isUniform) {
            description += `   • Internal padding: ${p.top}px uniform\n`;
        } else {
            description += `   • Internal padding: ${p.top}px ${p.right}px ${p.bottom}px ${p.left}px (TRBL)\n`;
        }
    }

    // Children positioning
    if (analysis.children.length > 0) {
        description += `   • Contains ${analysis.children.length} child elements\n`;
        const highImportanceChildren = analysis.children.filter(c => c.visualImportance >= 7);
        if (highImportanceChildren.length > 0) {
            description += `   • ${highImportanceChildren.length} high-priority elements (visual weight ≥7)\n`;
        }
    }

    return description;
}

/**
 * Generate screen spatial description
 */
function generateScreenSpatialDescription(analysis: ScreenAnalysis): string {
    let description = '';
    
    // Screen zones
    const screenHeight = analysis.metadata.dimensions.height;
    description += `   • Header zone: Y < ${Math.round(screenHeight * 0.15)}px (top 15%)\n`;
    description += `   • Content zone: Y ${Math.round(screenHeight * 0.15)}px - ${Math.round(screenHeight * 0.85)}px\n`;
    description += `   • Footer zone: Y > ${Math.round(screenHeight * 0.85)}px (bottom 15%)\n`;

    // Content area
    if (analysis.layout.contentArea) {
        const area = analysis.layout.contentArea;
        description += `   • Primary content area: ${Math.round(area.width)}×${Math.round(area.height)}px\n`;
        description += `   • Content position: (${Math.round(area.x)}, ${Math.round(area.y)})\n`;
    }

    // Section distribution
    if (analysis.sections.length > 0) {
        const sectionsByType = analysis.sections.reduce((acc, section) => {
            acc[section.type] = (acc[section.type] || 0) + 1;
            return acc;
        }, {} as Record<string, number>);
        
        description += `   • Section distribution: `;
        Object.entries(sectionsByType).forEach(([type, count], index) => {
            description += `${count} ${type}${index < Object.keys(sectionsByType).length - 1 ? ', ' : ''}`;
        });
        description += `\n`;
    }

    return description;
}

/**
 * Generate screen hierarchy
 */
function generateScreenHierarchy(analysis: ScreenAnalysis): string {
    let hierarchy = '';
    
    // Sort sections by importance and position
    const sortedSections = [...analysis.sections].sort((a, b) => {
        // First by type priority (header > content > footer)
        const typePriority = { header: 3, navigation: 2, content: 1, footer: 0, sidebar: 1, modal: 2, other: 0 };
        const aPriority = typePriority[a.type] || 0;
        const bPriority = typePriority[b.type] || 0;
        if (aPriority !== bPriority) return bPriority - aPriority;
        
        // Then by importance score
        return b.importance - a.importance;
    });

    sortedSections.forEach((section, index) => {
        const position = section.layout.dimensions ? 
            `${Math.round(section.layout.dimensions.width)}×${Math.round(section.layout.dimensions.height)}px` : 
            'auto';
        hierarchy += `   ${index + 1}. ${section.name} (${section.type.toUpperCase()}) - ${position}\n`;
        hierarchy += `      Priority: ${section.importance}/10`;
        if (section.children.length > 0) {
            hierarchy += `, Contains: ${section.children.length} elements`;
        }
        if (section.components.length > 0) {
            hierarchy += `, Components: ${section.components.length}`;
        }
        hierarchy += `\n`;
    });

    return hierarchy;
}

/**
 * Generate component pattern description
 */
function generateComponentPatternDescription(analysis: ComponentAnalysis): string {
    let patterns = '';
    
    // Layout pattern
    patterns += `   • Layout type: ${analysis.layout.type}\n`;
    
    // Spacing pattern
    if (analysis.layout.spacing !== undefined) {
        patterns += `   • Spacing system: ${analysis.layout.spacing}px consistent\n`;
    }
    
    // Visual styling patterns
    if (analysis.styling.fills && analysis.styling.fills.length > 0) {
        const primaryColor = analysis.styling.fills[0].hex;
        patterns += `   • Color pattern: Primary ${primaryColor}\n`;
    }
    
    if (analysis.styling.cornerRadius !== undefined) {
        const radius = typeof analysis.styling.cornerRadius === 'number' 
            ? analysis.styling.cornerRadius 
            : `${analysis.styling.cornerRadius.topLeft}px mixed`;
        patterns += `   • Border radius: ${radius}px consistent\n`;
    }
    
    // Component grouping
    if (analysis.children.length > 0) {
        const componentChildren = analysis.children.filter(c => c.isNestedComponent).length;
        if (componentChildren > 0) {
            patterns += `   • Component composition: ${componentChildren}/${analysis.children.length} nested components\n`;
        }
    }

    // Visual weight
    const textElements = analysis.children.filter(c => c.type === 'TEXT').length;
    const visualElements = analysis.children.length - textElements;
    patterns += `   • Content balance: ${textElements} text, ${visualElements} visual elements\n`;

    return patterns;
}

/**
 * Generate screen pattern description
 */
function generateScreenPatternDescription(analysis: ScreenAnalysis): string {
    let patterns = '';
    
    // Overall layout pattern
    patterns += `   • Layout type: ${analysis.layout.type}\n`;
    if (analysis.layout.scrollable) {
        patterns += `   • Scroll behavior: vertical scrolling enabled\n`;
    }
    
    // Section patterns
    const sectionTypes = analysis.sections.map(s => s.type);
    const hasStandardLayout = sectionTypes.includes('header') && sectionTypes.includes('content');
    patterns += `   • Screen structure: ${hasStandardLayout ? 'standard' : 'custom'} layout pattern\n`;
    
    // Navigation patterns
    if (analysis.navigation.hasTabBar) patterns += `   • Navigation: bottom tab bar\n`;
    if (analysis.navigation.hasAppBar) patterns += `   • Navigation: top app bar\n`;
    if (analysis.navigation.hasDrawer) patterns += `   • Navigation: side drawer\n`;
    
    // Visual weight distribution
    const headerSections = analysis.sections.filter(s => s.type === 'header').length;
    const contentSections = analysis.sections.filter(s => s.type === 'content').length;
    const footerSections = analysis.sections.filter(s => s.type === 'footer' || s.type === 'navigation').length;
    
    if (headerSections > contentSections) {
        patterns += `   • Visual weight: header-heavy design\n`;
    } else if (footerSections > contentSections) {
        patterns += `   • Visual weight: bottom-heavy design\n`;
    } else {
        patterns += `   • Visual weight: content-focused design\n`;
    }

    return patterns;
}

/**
 * Generate component implementation hints
 */
function generateComponentImplementationHints(analysis: ComponentAnalysis): string {
    let hints = '';
    
    // Main container suggestion
    if (analysis.layout.type === 'auto-layout') {
        const widget = analysis.layout.direction === 'horizontal' ? 'Row' : 'Column';
        hints += `   • Main container: Use ${widget}() for ${analysis.layout.direction} layout\n`;
        if (analysis.layout.spacing) {
            hints += `   • Spacing: Add SizedBox gaps of ${analysis.layout.spacing}px\n`;
        }
    } else {
        hints += `   • Main container: Use Stack() or Container() for absolute positioning\n`;
    }
    
    // Styling approach
    if (analysis.styling.fills || analysis.styling.strokes || analysis.styling.cornerRadius !== undefined) {
        hints += `   • Styling: Implement BoxDecoration for visual styling\n`;
    }
    
    // Text handling
    const textChildren = analysis.children.filter(c => c.type === 'TEXT');
    if (textChildren.length > 0) {
        hints += `   • Text elements: ${textChildren.length} Text() widgets with custom styling\n`;
    }
    
    // Component composition
    const nestedComponents = analysis.children.filter(c => c.isNestedComponent);
    if (nestedComponents.length > 0) {
        hints += `   • Component structure: Break down ${nestedComponents.length} nested components\n`;
    }
    
    // Responsive considerations
    if (analysis.layout.dimensions.width > 400) {
        hints += `   • Responsive: Consider MediaQuery for larger screens\n`;
    }

    return hints;
}

/**
 * Generate screen implementation hints
 */
function generateScreenImplementationHints(analysis: ScreenAnalysis): string {
    let hints = '';
    
    // Main scaffold structure
    hints += `   • Main structure: Scaffold with systematic layout\n`;
    
    // App bar recommendation
    if (analysis.navigation.hasAppBar) {
        hints += `   • App bar: AppBar widget for top navigation\n`;
    }
    
    // Body structure
    if (analysis.layout.scrollable) {
        hints += `   • Body: SingleChildScrollView with Column layout\n`;
    } else {
        hints += `   • Body: Column layout for fixed content\n`;
    }
    
    // Navigation recommendation
    if (analysis.navigation.hasTabBar) {
        hints += `   • Bottom navigation: BottomNavigationBar for tab switching\n`;
    }
    if (analysis.navigation.hasDrawer) {
        hints += `   • Side navigation: Drawer widget for menu access\n`;
    }
    
    // Section breakdown
    if (analysis.sections.length > 3) {
        hints += `   • Widget organization: Break into ${analysis.sections.length} section widgets\n`;
    }
    
    // Device considerations
    if (analysis.metadata.deviceType === 'mobile') {
        hints += `   • Mobile optimization: Use SafeArea and responsive sizing\n`;
    } else if (analysis.metadata.deviceType === 'tablet') {
        hints += `   • Tablet layout: Consider NavigationRail for wider screens\n`;
    }
    
    // Asset handling
    if (analysis.assets.length > 0) {
        hints += `   • Assets: ${analysis.assets.length} image/icon assets to implement\n`;
    }

    return hints;
}

```

--------------------------------------------------------------------------------
/src/tools/flutter/components/helpers.ts:
--------------------------------------------------------------------------------

```typescript
import type {ComponentVariant} from "../../../extractors/components/types.js";
import type {ComponentAnalysis} from "../../../extractors/components/types.js";
import {generateFlutterTextWidget} from "../../../extractors/components/extractor.js";
import {generateComponentVisualContext} from "../visual-context.js";

/**
 * Generate variant selection prompt when there are more than 3 variants
 */
export function generateVariantSelectionPrompt(
    componentName: string,
    selectionInfo: any,
    variants: ComponentVariant[]
): string {
    let output = `Component Set "${componentName}" has ${selectionInfo.totalCount} variants.\n\n`;
    output += `Since there are more than 3 variants, please specify which ones to analyze.\n\n`;

    output += `Available variants:\n`;
    variants.forEach((variant, index) => {
        const defaultMark = variant.isDefault ? ' (default)' : '';
        output += `${index + 1}. ${variant.name}${defaultMark}\n`;
    });

    output += `\nVariant properties:\n`;
    Object.entries(selectionInfo.variantProperties).forEach(([prop, values]: [string, any]) => {
        output += `- ${prop}: ${Array.from(values).join(', ')}\n`;
    });

    if (selectionInfo.defaultVariant) {
        output += `\nDefault variant: ${selectionInfo.defaultVariant.name}\n`;
    }

    output += `\nTo analyze specific variants, run the tool again with:\n`;
    output += `variantSelection: ["variant name 1", "variant name 2"]\n\n`;
    output += `Or to analyze all variants (may be token-intensive):\n`;
    output += `variantSelection: ${JSON.stringify(variants.slice(0, 3).map(v => v.name))}\n`;

    return output;
}

/**
 * Generate comprehensive component analysis report
 */
export function generateComponentAnalysisReport(
    analysis: ComponentAnalysis,
    variantAnalysis?: ComponentVariant[],
    selectedVariants?: ComponentVariant[],
    parsedInput?: any
): string {
    let output = `Component Analysis Report\n\n`;

    // Component metadata
    output += `Component: ${analysis.metadata.name}\n`;
    output += `Type: ${analysis.metadata.type}\n`;
    output += `Node ID: ${analysis.metadata.nodeId}\n`;
    if (parsedInput) {
        output += `Source: ${parsedInput.source === 'url' ? 'Figma URL' : 'Direct input'}\n`;
    }
    output += `\n`;

    // Variant information
    if (variantAnalysis && variantAnalysis.length > 0) {
        output += `Variants Analysis:\n`;
        if (selectedVariants && selectedVariants.length > 0) {
            output += `Analyzed variants (${selectedVariants.length} of ${variantAnalysis.length}):\n`;
            selectedVariants.forEach(variant => {
                const defaultMark = variant.isDefault ? ' (default)' : '';
                output += `- ${variant.name}${defaultMark}\n`;
            });
        } else {
            output += `Total variants: ${variantAnalysis.length}\n`;
        }
        output += `\n`;
    }

    // Layout information
    output += `Layout Structure:\n`;
    output += `- Type: ${analysis.layout.type}\n`;
    output += `- Dimensions: ${Math.round(analysis.layout.dimensions.width)}×${Math.round(analysis.layout.dimensions.height)}px\n`;

    if (analysis.layout.direction) {
        output += `- Direction: ${analysis.layout.direction}\n`;
    }
    if (analysis.layout.spacing !== undefined) {
        output += `- Spacing: ${analysis.layout.spacing}px\n`;
    }
    if (analysis.layout.padding) {
        const p = analysis.layout.padding;
        if (p.isUniform) {
            output += `- Padding: ${p.top}px (uniform)\n`;
        } else {
            output += `- Padding: ${p.top}px ${p.right}px ${p.bottom}px ${p.left}px\n`;
        }
    }
    if (analysis.layout.alignItems) {
        output += `- Align Items: ${analysis.layout.alignItems}\n`;
    }
    if (analysis.layout.justifyContent) {
        output += `- Justify Content: ${analysis.layout.justifyContent}\n`;
    }
    output += `\n`;

    // Styling information
    output += `Visual Styling:\n`;
    if (analysis.styling.fills && analysis.styling.fills.length > 0) {
        const fill = analysis.styling.fills[0];
        output += `- Background: ${fill.hex || fill.type}`;
        if (fill.opacity && fill.opacity !== 1) {
            output += ` (${Math.round(fill.opacity * 100)}% opacity)`;
        }
        output += `\n`;
    }
    if (analysis.styling.strokes && analysis.styling.strokes.length > 0) {
        const stroke = analysis.styling.strokes[0];
        output += `- Border: ${stroke.weight}px solid ${stroke.hex}\n`;
    }
    if (analysis.styling.cornerRadius !== undefined) {
        if (typeof analysis.styling.cornerRadius === 'number') {
            output += `- Corner radius: ${analysis.styling.cornerRadius}px\n`;
        } else {
            const r = analysis.styling.cornerRadius;
            output += `- Corner radius: ${r.topLeft}px ${r.topRight}px ${r.bottomRight}px ${r.bottomLeft}px\n`;
        }
    }
    if (analysis.styling.opacity && analysis.styling.opacity !== 1) {
        output += `- Opacity: ${Math.round(analysis.styling.opacity * 100)}%\n`;
    }

    // Effects (shadows, blurs)
    if (analysis.styling.effects) {
        const effects = analysis.styling.effects;
        if (effects.dropShadows.length > 0) {
            effects.dropShadows.forEach((shadow, index) => {
                output += `- Drop shadow ${index + 1}: ${shadow.hex} offset(${shadow.offset.x}, ${shadow.offset.y}) blur ${shadow.radius}px`;
                if (shadow.spread) {
                    output += ` spread ${shadow.spread}px`;
                }
                output += `\n`;
            });
        }
        if (effects.innerShadows.length > 0) {
            output += `- Inner shadows: ${effects.innerShadows.length} effect(s)\n`;
        }
        if (effects.blurs.length > 0) {
            output += `- Blur effects: ${effects.blurs.length} effect(s)\n`;
        }
    }
    output += `\n`;

    // Children information
    if (analysis.children.length > 0) {
        output += `Child Elements (${analysis.children.length} analyzed):\n`;
        analysis.children.forEach((child, index) => {
            const componentMark = child.isNestedComponent ? ' [COMPONENT]' : '';
            const importanceMark = ` (priority: ${child.visualImportance}/10)`;
            output += `${index + 1}. ${child.name} (${child.type})${componentMark}${importanceMark}\n`;

            if (child.basicInfo?.layout?.dimensions) {
                const dims = child.basicInfo.layout.dimensions;
                output += `   Size: ${Math.round(dims.width)}×${Math.round(dims.height)}px\n`;
            }

            if (child.basicInfo?.styling?.fills && child.basicInfo.styling.fills.length > 0) {
                output += `   Background: ${child.basicInfo.styling.fills[0].hex}\n`;
            }

            if (child.basicInfo?.text) {
                const textInfo = child.basicInfo.text;
                const placeholderMark = textInfo.isPlaceholder ? ' [PLACEHOLDER]' : '';
                const semanticMark = textInfo.semanticType && textInfo.semanticType !== 'other' ? ` [${textInfo.semanticType.toUpperCase()}]` : '';

                output += `   Text Content: "${textInfo.content}"${placeholderMark}${semanticMark}\n`;

                if (textInfo.fontFamily || textInfo.fontSize || textInfo.fontWeight) {
                    const fontParts = [];
                    if (textInfo.fontFamily) fontParts.push(textInfo.fontFamily);
                    if (textInfo.fontSize) fontParts.push(`${textInfo.fontSize}px`);
                    if (textInfo.fontWeight && textInfo.fontWeight !== 400) fontParts.push(`weight: ${textInfo.fontWeight}`);
                    output += `   Typography: ${fontParts.join(' ')}\n`;
                }

                if (textInfo.textCase && textInfo.textCase !== 'mixed') {
                    output += `   Text Case: ${textInfo.textCase}\n`;
                }
            }
        });
        output += `\n`;
    }

    // Nested components for separate analysis
    if (analysis.nestedComponents.length > 0) {
        output += `Nested Components Found (${analysis.nestedComponents.length}):\n`;
        output += `These components should be analyzed separately to maintain reusability:\n`;
        analysis.nestedComponents.forEach((comp, index) => {
            output += `${index + 1}. ${comp.name}\n`;
            output += `   Node ID: ${comp.nodeId}\n`;
            output += `   Type: ${comp.instanceType || 'COMPONENT'}\n`;
            if (comp.componentKey) {
                output += `   Component Key: ${comp.componentKey}\n`;
            }
        });
        output += `\n`;
    }

    // Skipped nodes report
    if (analysis.skippedNodes && analysis.skippedNodes.length > 0) {
        output += `Analysis Limitations:\n`;
        output += `${analysis.skippedNodes.length} nodes were skipped due to the maxChildNodes limit:\n`;
        analysis.skippedNodes.forEach((skipped, index) => {
            output += `${index + 1}. ${skipped.name} (${skipped.type})\n`;
        });
        output += `\nTo analyze all nodes, increase the maxChildNodes parameter.\n\n`;
    }

    // Visual context for AI implementation
    if (parsedInput?.source === 'url') {
        // Reconstruct the Figma URL from the parsed input
        const figmaUrl = `https://www.figma.com/design/${parsedInput.fileId}/?node-id=${parsedInput.nodeId}`;
        output += generateComponentVisualContext(analysis, figmaUrl, parsedInput.nodeId);
        output += `\n`;
    }

    // Flutter implementation guidance
    output += generateFlutterGuidance(analysis);

    return output;
}

/**
 * Generate Flutter implementation guidance
 */
export function generateFlutterGuidance(analysis: ComponentAnalysis): string {
    let guidance = `Flutter Implementation Guidance:\n\n`;

    // Widget composition best practices
    guidance += `🏗️  Widget Composition Best Practices:\n`;
    guidance += `- Start by building the complete widget tree in a single build() method\n`;
    guidance += `- Keep composing widgets inline until you reach ~200 lines of code\n`;
    guidance += `- Only then extract reusable parts into private StatelessWidget classes\n`;
    guidance += `- Use private widgets (prefix with _) for internal component breakdown\n`;
    guidance += `- Avoid functional widgets - always use StatelessWidget classes\n\n`;

    // Main container guidance
    guidance += `Main Widget Structure:\n`;
    if (analysis.layout.type === 'auto-layout') {
        const containerWidget = analysis.layout.direction === 'horizontal' ? 'Row' : 'Column';
        guidance += `- Use ${containerWidget}() as the main layout widget\n`;

        if (analysis.layout.spacing && analysis.layout.spacing > 0) {
            const spacingWidget = analysis.layout.direction === 'horizontal' ? 'width' : 'height';
            guidance += `- Add spacing with SizedBox(${spacingWidget}: ${analysis.layout.spacing})\n`;
        }

        if (analysis.layout.alignItems) {
            guidance += `- CrossAxisAlignment: ${mapFigmaToFlutterAlignment(analysis.layout.alignItems)}\n`;
        }
        if (analysis.layout.justifyContent) {
            guidance += `- MainAxisAlignment: ${mapFigmaToFlutterAlignment(analysis.layout.justifyContent)}\n`;
        }
    } else {
        guidance += `- Use Container() or Stack() for layout\n`;
    }

    // Styling guidance
    if (hasVisualStyling(analysis.styling)) {
        guidance += `\nContainer Decoration:\n`;
        guidance += `Container(\n`;
        guidance += `  decoration: BoxDecoration(\n`;

        if (analysis.styling.fills && analysis.styling.fills.length > 0) {
            const fill = analysis.styling.fills[0];
            if (fill.hex) {
                guidance += `    color: Color(0xFF${fill.hex.substring(1)}),\n`;
            }
        }

        if (analysis.styling.strokes && analysis.styling.strokes.length > 0) {
            const stroke = analysis.styling.strokes[0];
            guidance += `    border: Border.all(\n`;
            guidance += `      color: Color(0xFF${stroke.hex.substring(1)}),\n`;
            guidance += `      width: ${stroke.weight},\n`;
            guidance += `    ),\n`;
        }

        if (analysis.styling.cornerRadius !== undefined) {
            if (typeof analysis.styling.cornerRadius === 'number') {
                guidance += `    borderRadius: BorderRadius.circular(${analysis.styling.cornerRadius}),\n`;
            } else {
                const r = analysis.styling.cornerRadius;
                guidance += `    borderRadius: BorderRadius.only(\n`;
                guidance += `      topLeft: Radius.circular(${r.topLeft}),\n`;
                guidance += `      topRight: Radius.circular(${r.topRight}),\n`;
                guidance += `      bottomLeft: Radius.circular(${r.bottomLeft}),\n`;
                guidance += `      bottomRight: Radius.circular(${r.bottomRight}),\n`;
                guidance += `    ),\n`;
            }
        }

        if (analysis.styling.effects?.dropShadows.length) {
            guidance += `    boxShadow: [\n`;
            analysis.styling.effects.dropShadows.forEach(shadow => {
                guidance += `      BoxShadow(\n`;
                guidance += `        color: Color(0xFF${shadow.hex.substring(1)}).withOpacity(${shadow.opacity.toFixed(2)}),\n`;
                guidance += `        offset: Offset(${shadow.offset.x}, ${shadow.offset.y}),\n`;
                guidance += `        blurRadius: ${shadow.radius},\n`;
                if (shadow.spread) {
                    guidance += `        spreadRadius: ${shadow.spread},\n`;
                }
                guidance += `      ),\n`;
            });
            guidance += `    ],\n`;
        }

        guidance += `  ),\n`;

        if (analysis.layout.padding) {
            const p = analysis.layout.padding;
            if (p.isUniform) {
                guidance += `  padding: EdgeInsets.all(${p.top}),\n`;
            } else {
                guidance += `  padding: EdgeInsets.fromLTRB(${p.left}, ${p.top}, ${p.right}, ${p.bottom}),\n`;
            }
        }

        guidance += `  child: /* Your content here */\n`;
        guidance += `)\n\n`;
    }

    // Component organization guidance
    if (analysis.nestedComponents.length > 0) {
        guidance += `Component Architecture:\n`;
        guidance += `Create separate widget classes for reusability:\n`;
        analysis.nestedComponents.forEach((comp, index) => {
            const widgetName = toPascalCase(comp.name);
            guidance += `${index + 1}. ${widgetName}() - Node ID: ${comp.nodeId}\n`;
        });
        guidance += `\nAnalyze each nested component separately using the analyze_figma_component tool.\n\n`;
    }

    // Text widget guidance with enhanced Flutter suggestions
    const textChildren = analysis.children.filter(child => child.type === 'TEXT');
    if (textChildren.length > 0) {
        guidance += `Text Elements & Flutter Widgets:\n`;
        textChildren.forEach((textChild, index) => {
            const textInfo = textChild.basicInfo?.text;
            if (textInfo) {
                // Import the generateFlutterTextWidget function result
                const widgetSuggestion = generateFlutterTextWidget(textInfo);
                const placeholderNote = textInfo.isPlaceholder ? ' // Placeholder text - replace with actual content' : '';
                const semanticNote = textInfo.semanticType && textInfo.semanticType !== 'other' ? ` // Detected as ${textInfo.semanticType}` : '';

                guidance += `${index + 1}. "${textInfo.content}"${placeholderNote}${semanticNote}\n`;
                guidance += `   Flutter Widget:\n`;

                // Indent the widget suggestion
                const indentedWidget = widgetSuggestion.split('\n').map(line => `   ${line}`).join('\n');
                guidance += `${indentedWidget}\n\n`;
            } else {
                guidance += `${index + 1}. Text('${textChild.name}') // No text info available\n\n`;
            }
        });
    }

    return guidance;
}

/**
 * Generate structure inspection report
 */
export function generateStructureInspectionReport(node: any, showAllChildren: boolean): string {
    let output = `Component Structure Inspection\n\n`;

    output += `Component: ${node.name}\n`;
    output += `Type: ${node.type}\n`;
    output += `Node ID: ${node.id}\n`;
    output += `Children: ${node.children?.length || 0}\n`;

    if (node.absoluteBoundingBox) {
        const bbox = node.absoluteBoundingBox;
        output += `Dimensions: ${Math.round(bbox.width)}×${Math.round(bbox.height)}px\n`;
    }

    output += `\n`;

    if (!node.children || node.children.length === 0) {
        output += `This component has no children.\n`;
        return output;
    }

    output += `Child Structure:\n`;

    const childrenToShow = showAllChildren ? node.children : node.children.slice(0, 15);
    const hasMore = node.children.length > childrenToShow.length;

    childrenToShow.forEach((child: any, index: number) => {
        const isComponent = child.type === 'COMPONENT' || child.type === 'INSTANCE';
        const componentMark = isComponent ? ' [COMPONENT]' : '';
        const hiddenMark = child.visible === false ? ' [HIDDEN]' : '';

        output += `${index + 1}. ${child.name} (${child.type})${componentMark}${hiddenMark}\n`;

        if (child.absoluteBoundingBox) {
            const bbox = child.absoluteBoundingBox;
            output += `   Size: ${Math.round(bbox.width)}×${Math.round(bbox.height)}px\n`;
        }

        if (child.children && child.children.length > 0) {
            output += `   Contains: ${child.children.length} child nodes\n`;
        }

        // Show basic styling info
        if (child.fills && child.fills.length > 0) {
            const fill = child.fills[0];
            if (fill.color) {
                const hex = rgbaToHex(fill.color);
                output += `   Background: ${hex}\n`;
            }
        }
    });

    if (hasMore) {
        output += `\n... and ${node.children.length - childrenToShow.length} more children.\n`;
        output += `Use showAllChildren: true to see all children.\n`;
    }

    // Analysis recommendations
    output += `\nAnalysis Recommendations:\n`;
    const componentChildren = node.children.filter((child: any) =>
        child.type === 'COMPONENT' || child.type === 'INSTANCE'
    );

    if (componentChildren.length > 0) {
        output += `- Found ${componentChildren.length} nested components for separate analysis\n`;
    }

    const largeChildren = node.children.filter((child: any) => {
        const bbox = child.absoluteBoundingBox;
        return bbox && (bbox.width * bbox.height) > 5000;
    });

    if (largeChildren.length > 3) {
        output += `- Component has ${largeChildren.length} large children - consider increasing maxChildNodes\n`;
    }

    const textChildren = node.children.filter((child: any) => child.type === 'TEXT');
    if (textChildren.length > 0) {
        output += `- Found ${textChildren.length} text nodes for content extraction\n`;
    }

    return output;
}

// Helper functions
export function mapFigmaToFlutterAlignment(alignment: string): string {
    const alignmentMap: Record<string, string> = {
        'MIN': 'CrossAxisAlignment.start',
        'CENTER': 'CrossAxisAlignment.center',
        'MAX': 'CrossAxisAlignment.end',
        'SPACE_BETWEEN': 'MainAxisAlignment.spaceBetween',
        'SPACE_AROUND': 'MainAxisAlignment.spaceAround',
        'SPACE_EVENLY': 'MainAxisAlignment.spaceEvenly'
    };

    return alignmentMap[alignment] || 'CrossAxisAlignment.center';
}

export function hasVisualStyling(styling: any): boolean {
    return !!(styling.fills?.length || styling.strokes?.length ||
        styling.cornerRadius !== undefined || styling.effects?.dropShadows?.length);
}

export function toPascalCase(str: string): string {
    return str
        .replace(/[^a-zA-Z0-9]/g, ' ')
        .replace(/\w+/g, (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
        .replace(/\s/g, '');
}

export function rgbaToHex(color: {r: number; g: number; b: number; a?: number}): string {
    const r = Math.round(color.r * 255);
    const g = Math.round(color.g * 255);
    const b = Math.round(color.b * 255);

    return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toUpperCase();
}
```

--------------------------------------------------------------------------------
/src/tools/flutter/semantic-detection.ts:
--------------------------------------------------------------------------------

```typescript
// src/tools/flutter/semantic-detection.ts

/**
 * Advanced semantic detection with multi-factor analysis and confidence scoring
 * Based on heuristics improvement recommendations
 */

export interface SemanticContext {
    parentType?: string;
    siblingTypes: string[];
    screenPosition: 'header' | 'content' | 'footer' | 'unknown';
    componentType: 'form' | 'navigation' | 'content' | 'card' | 'button-group' | 'unknown';
    layoutDirection?: 'horizontal' | 'vertical';
    isInteractive?: boolean;
    hasActionableNeighbors?: boolean;
}

export interface SemanticClassification {
    type: 'heading' | 'body' | 'label' | 'button' | 'link' | 'caption' | 'error' | 'success' | 'warning' | 'other';
    confidence: number; // 0-1
    alternatives: Array<{type: string; confidence: number}>;
    reasoning: string[];
}

export interface PositionContext {
    isTopLevel: boolean;
    isBottomLevel: boolean;
    isIsolated: boolean;
    visualWeight: number;
    relativeSize: number;
    hasNearbyInteractive: boolean;
}

export interface TextAnalysis {
    isActionable: boolean;
    isDescriptive: boolean;
    isNavigational: boolean;
    isStatusMessage: boolean;
    length: number;
    structure: 'imperative' | 'declarative' | 'question' | 'fragment' | 'mixed';
    hasActionWords: boolean;
    hasImperativeForm: boolean;
}

export interface DesignPattern {
    name: string;
    confidence: number;
    indicators: string[];
}

/**
 * Enhanced semantic type detection with multi-factor analysis
 */
export function detectSemanticTypeAdvanced(
    content: string,
    nodeName: string,
    context: SemanticContext,
    nodeProperties?: any
): SemanticClassification {
    const factors = {
        textContent: analyzeTextContent(content),
        nodeName: analyzeNodeName(nodeName),
        position: nodeProperties ? analyzePosition(nodeProperties, context) : null,
        styling: nodeProperties ? analyzeStyling(nodeProperties) : null,
        patterns: detectDesignPatterns(content, nodeName, nodeProperties, context)
    };

    return weightedClassification(factors, context);
}

/**
 * Analyze text content for semantic clues
 */
function analyzeTextContent(content: string): TextAnalysis {
    const lowerContent = content.toLowerCase().trim();
    
    // Check for action words
    const actionWords = [
        'click', 'tap', 'press', 'submit', 'send', 'save', 'cancel', 'continue',
        'next', 'back', 'close', 'start', 'begin', 'try', 'get', 'download',
        'upload', 'buy', 'purchase', 'add', 'remove', 'edit', 'delete', 'create'
    ];
    
    const hasActionWords = actionWords.some(word => lowerContent.includes(word));
    
    // Check for imperative form (simplified detection)
    const hasImperativeForm = /^(let's|please|go|try|get|make|do|use|see|find|learn|discover)/.test(lowerContent) ||
                             /^[a-z]+ (now|here|more|started)$/i.test(lowerContent);
    
    // Check for navigational keywords
    const navKeywords = ['home', 'back', 'next', 'previous', 'menu', 'settings', 'profile', 'about', 'contact', 'help'];
    const isNavigational = navKeywords.some(word => lowerContent.includes(word));
    
    // Check for status messages
    const statusKeywords = ['error', 'success', 'warning', 'complete', 'failed', 'loading', 'pending'];
    const isStatusMessage = statusKeywords.some(word => lowerContent.includes(word));
    
    // Determine structure
    let structure: TextAnalysis['structure'] = 'mixed';
    if (content.endsWith('?')) structure = 'question';
    else if (hasImperativeForm || hasActionWords) structure = 'imperative';
    else if (content.length > 50 && content.includes('.')) structure = 'declarative';
    else if (content.length < 30 && !content.includes('.')) structure = 'fragment';
    
    return {
        isActionable: hasActionWords || hasImperativeForm,
        isDescriptive: content.length > 50 && !hasActionWords,
        isNavigational,
        isStatusMessage,
        length: content.length,
        structure,
        hasActionWords,
        hasImperativeForm
    };
}

/**
 * Analyze node name for semantic clues
 */
function analyzeNodeName(nodeName: string): {type: string; confidence: number} {
    const lowerName = nodeName.toLowerCase();
    
    // High confidence name patterns
    if (lowerName.includes('button') || lowerName.includes('btn')) {
        return {type: 'button', confidence: 0.9};
    }
    if (lowerName.includes('heading') || lowerName.includes('title') || /h[1-6]/.test(lowerName)) {
        return {type: 'heading', confidence: 0.9};
    }
    if (lowerName.includes('label') || lowerName.includes('field')) {
        return {type: 'label', confidence: 0.8};
    }
    if (lowerName.includes('link') || lowerName.includes('nav')) {
        return {type: 'link', confidence: 0.8};
    }
    if (lowerName.includes('caption') || lowerName.includes('subtitle')) {
        return {type: 'caption', confidence: 0.8};
    }
    if (lowerName.includes('error') || lowerName.includes('warning') || lowerName.includes('success')) {
        return {type: lowerName.includes('error') ? 'error' : lowerName.includes('warning') ? 'warning' : 'success', confidence: 0.9};
    }
    
    return {type: 'unknown', confidence: 0.0};
}

/**
 * Analyze position context
 */
function analyzePosition(nodeProperties: any, context: SemanticContext): PositionContext {
    const bounds = nodeProperties.absoluteBoundingBox;
    const parentBounds = nodeProperties.parent?.absoluteBoundingBox;
    
    if (!bounds || !parentBounds) {
        return {
            isTopLevel: false,
            isBottomLevel: false,
            isIsolated: false,
            visualWeight: 1,
            relativeSize: 1,
            hasNearbyInteractive: false
        };
    }
    
    const relativeY = (bounds.y - parentBounds.y) / parentBounds.height;
    const relativeSize = (bounds.width * bounds.height) / (parentBounds.width * parentBounds.height);
    
    return {
        isTopLevel: relativeY < 0.2,
        isBottomLevel: relativeY > 0.8,
        isIsolated: calculateIsolation(bounds, nodeProperties.siblings || []),
        visualWeight: calculateVisualWeight(nodeProperties),
        relativeSize,
        hasNearbyInteractive: context.hasActionableNeighbors || false
    };
}

/**
 * Analyze styling patterns
 */
function analyzeStyling(nodeProperties: any): {buttonLike: number; textLike: number; statusLike: number} {
    const styling = nodeProperties.styling || {};
    
    let buttonLike = 0;
    let textLike = 0;
    let statusLike = 0;
    
    // Button-like characteristics
    if (styling.fills?.length > 0) buttonLike += 0.3;
    if (styling.strokes?.length > 0) buttonLike += 0.2;
    if (styling.cornerRadius !== undefined && styling.cornerRadius > 4) buttonLike += 0.3;
    if (nodeProperties.layout?.padding) buttonLike += 0.2;
    
    // Text-like characteristics
    if (!styling.fills || styling.fills.length === 0) textLike += 0.3;
    if (!styling.strokes || styling.strokes.length === 0) textLike += 0.2;
    if (!styling.cornerRadius || styling.cornerRadius === 0) textLike += 0.3;
    
    // Status-like characteristics (color-based)
    if (styling.fills?.length > 0) {
        const primaryColor = styling.fills[0].hex?.toLowerCase();
        if (primaryColor?.includes('red') || primaryColor?.includes('ff')) statusLike += 0.4;
        if (primaryColor?.includes('green') || primaryColor?.includes('0f')) statusLike += 0.4;
        if (primaryColor?.includes('orange') || primaryColor?.includes('yellow')) statusLike += 0.4;
    }
    
    return {buttonLike, textLike, statusLike};
}

/**
 * Detect design patterns
 */
function detectDesignPatterns(
    content: string,
    nodeName: string,
    nodeProperties: any,
    context: SemanticContext
): DesignPattern[] {
    const patterns: DesignPattern[] = [];
    
    // Button pattern
    const buttonPattern = detectButtonPattern(content, nodeName, nodeProperties, context);
    if (buttonPattern.confidence > 0.5) patterns.push(buttonPattern);
    
    // Heading pattern
    const headingPattern = detectHeadingPattern(content, nodeName, nodeProperties, context);
    if (headingPattern.confidence > 0.5) patterns.push(headingPattern);
    
    // Form label pattern
    const labelPattern = detectLabelPattern(content, nodeName, nodeProperties, context);
    if (labelPattern.confidence > 0.5) patterns.push(labelPattern);
    
    // Navigation pattern
    const navPattern = detectNavigationPattern(content, nodeName, nodeProperties, context);
    if (navPattern.confidence > 0.5) patterns.push(navPattern);
    
    return patterns;
}

/**
 * Detect button pattern
 */
function detectButtonPattern(content: string, nodeName: string, nodeProperties: any, context: SemanticContext): DesignPattern {
    const indicators: string[] = [];
    let confidence = 0;
    
    // Content analysis
    const textAnalysis = analyzeTextContent(content);
    if (textAnalysis.isActionable) {
        confidence += 0.4;
        indicators.push('actionable text');
    }
    
    // Visual characteristics
    const styling = analyzeStyling(nodeProperties);
    if (styling.buttonLike > 0.6) {
        confidence += 0.3;
        indicators.push('button-like styling');
    }
    
    // Context analysis
    if (context.componentType === 'form' && textAnalysis.hasActionWords) {
        confidence += 0.2;
        indicators.push('form context with action words');
    }
    
    // Name analysis
    if (nodeName.toLowerCase().includes('button')) {
        confidence += 0.1;
        indicators.push('button in name');
    }
    
    return {
        name: 'button',
        confidence: Math.min(confidence, 1),
        indicators
    };
}

/**
 * Detect heading pattern
 */
function detectHeadingPattern(content: string, nodeName: string, nodeProperties: any, context: SemanticContext): DesignPattern {
    const indicators: string[] = [];
    let confidence = 0;
    
    // Size and typography
    const fontSize = nodeProperties.text?.fontSize || 0;
    const fontWeight = nodeProperties.text?.fontWeight || 400;
    
    if (fontSize > 18) {
        confidence += 0.3;
        indicators.push('large font size');
    }
    if (fontWeight >= 600) {
        confidence += 0.2;
        indicators.push('bold font weight');
    }
    
    // Content structure
    if (content.length < 80 && !content.endsWith('.')) {
        confidence += 0.2;
        indicators.push('short non-sentence text');
    }
    
    // Position context
    const position = analyzePosition(nodeProperties, context);
    if (position.isTopLevel) {
        confidence += 0.2;
        indicators.push('top-level position');
    }
    
    // Context analysis
    if (context.screenPosition === 'header') {
        confidence += 0.1;
        indicators.push('header context');
    }
    
    return {
        name: 'heading',
        confidence: Math.min(confidence, 1),
        indicators
    };
}

/**
 * Detect label pattern
 */
function detectLabelPattern(content: string, nodeName: string, nodeProperties: any, context: SemanticContext): DesignPattern {
    const indicators: string[] = [];
    let confidence = 0;
    
    // Content characteristics
    if (content.length < 40 && content.endsWith(':')) {
        confidence += 0.4;
        indicators.push('short text ending with colon');
    }
    
    // Context analysis
    if (context.componentType === 'form') {
        confidence += 0.3;
        indicators.push('form context');
    }
    
    // Name analysis
    if (nodeName.toLowerCase().includes('label')) {
        confidence += 0.3;
        indicators.push('label in name');
    }
    
    return {
        name: 'label',
        confidence: Math.min(confidence, 1),
        indicators
    };
}

/**
 * Detect navigation pattern
 */
function detectNavigationPattern(content: string, nodeName: string, nodeProperties: any, context: SemanticContext): DesignPattern {
    const indicators: string[] = [];
    let confidence = 0;
    
    // Content analysis
    const textAnalysis = analyzeTextContent(content);
    if (textAnalysis.isNavigational) {
        confidence += 0.4;
        indicators.push('navigational content');
    }
    
    // Context analysis
    if (context.componentType === 'navigation' || context.screenPosition === 'header') {
        confidence += 0.3;
        indicators.push('navigation context');
    }
    
    // Layout analysis
    if (context.hasActionableNeighbors) {
        confidence += 0.2;
        indicators.push('near other actionable elements');
    }
    
    return {
        name: 'navigation',
        confidence: Math.min(confidence, 1),
        indicators
    };
}

/**
 * Weighted classification based on all factors
 */
function weightedClassification(factors: any, context: SemanticContext): SemanticClassification {
    const candidates: Array<{type: string; confidence: number; reasoning: string[]}> = [];
    
    // Pattern-based classification (highest priority)
    if (factors.patterns) {
        factors.patterns.forEach((pattern: DesignPattern) => {
            if (pattern.confidence > 0.6) {
                candidates.push({
                    type: pattern.name,
                    confidence: pattern.confidence,
                    reasoning: [`Strong ${pattern.name} pattern: ${pattern.indicators.join(', ')}`]
                });
            }
        });
    }
    
    // Text content analysis
    if (factors.textContent) {
        const textAnalysis = factors.textContent as TextAnalysis;
        
        if (textAnalysis.isActionable && textAnalysis.length < 50) {
            candidates.push({
                type: 'button',
                confidence: 0.7,
                reasoning: ['Actionable short text content']
            });
        }
        
        if (textAnalysis.isNavigational) {
            candidates.push({
                type: 'link',
                confidence: 0.6,
                reasoning: ['Navigational text content']
            });
        }
        
        if (textAnalysis.isStatusMessage) {
            const statusType = determineStatusType(factors.textContent, factors.styling);
            candidates.push({
                type: statusType,
                confidence: 0.8,
                reasoning: ['Status message detected']
            });
        }
        
        if (textAnalysis.length > 80 || textAnalysis.structure === 'declarative') {
            candidates.push({
                type: 'body',
                confidence: 0.6,
                reasoning: ['Long descriptive text']
            });
        }
    }
    
    // Name-based classification
    if (factors.nodeName && factors.nodeName.confidence > 0.7) {
        candidates.push({
            type: factors.nodeName.type,
            confidence: factors.nodeName.confidence,
            reasoning: ['Node name indicates type']
        });
    }
    
    // Apply confidence threshold - only return high confidence classifications
    const highConfidenceCandidates = candidates.filter(c => c.confidence >= 0.6);
    
    if (highConfidenceCandidates.length === 0) {
        return {
            type: 'other',
            confidence: 0.0,
            alternatives: candidates.map(c => ({type: c.type, confidence: c.confidence})),
            reasoning: ['Low confidence in all classifications - deferring to AI interpretation']
        };
    }
    
    // Sort by confidence and return the best match
    highConfidenceCandidates.sort((a, b) => b.confidence - a.confidence);
    const bestMatch = highConfidenceCandidates[0];
    
    return {
        type: bestMatch.type as any,
        confidence: bestMatch.confidence,
        alternatives: highConfidenceCandidates.slice(1).map(c => ({type: c.type, confidence: c.confidence})),
        reasoning: bestMatch.reasoning
    };
}

/**
 * Helper functions
 */
function calculateIsolation(bounds: any, siblings: any[]): boolean {
    if (!siblings || siblings.length === 0) return true;
    
    const minDistance = 50; // pixels
    return !siblings.some((sibling: any) => {
        if (!sibling.absoluteBoundingBox) return false;
        
        const distance = Math.sqrt(
            Math.pow(bounds.x - sibling.absoluteBoundingBox.x, 2) +
            Math.pow(bounds.y - sibling.absoluteBoundingBox.y, 2)
        );
        
        return distance < minDistance;
    });
}

function calculateVisualWeight(nodeProperties: any): number {
    let weight = 1;
    
    // Size contribution
    const area = (nodeProperties.absoluteBoundingBox?.width || 0) * (nodeProperties.absoluteBoundingBox?.height || 0);
    if (area > 10000) weight += 2;
    else if (area > 5000) weight += 1;
    
    // Styling contribution
    if (nodeProperties.styling?.fills?.length > 0) weight += 1;
    if (nodeProperties.styling?.strokes?.length > 0) weight += 0.5;
    if (nodeProperties.text?.fontWeight >= 600) weight += 1;
    
    return weight;
}

function determineStatusType(textAnalysis: TextAnalysis, styling: any): string {
    const content = textAnalysis;
    // This is a simplified version - in practice you'd analyze the content more thoroughly
    if (styling?.statusLike > 0.5) {
        // Could analyze color to determine if error, warning, or success
        return 'error'; // simplified
    }
    return 'other';
}

/**
 * Enhanced section type detection with confidence scoring
 */
export function detectSectionTypeAdvanced(
    node: any,
    parent?: any,
    siblings?: any[]
): {type: 'header' | 'navigation' | 'content' | 'footer' | 'sidebar' | 'modal' | 'other'; confidence: number; reasoning: string[]} {
    const factors = {
        nodeName: analyzeNodeName(node.name),
        position: parent ? analyzePosition(node, generateSemanticContext(node, parent, siblings)) : null,
        styling: analyzeStyling(node),
        siblings: siblings ? analyzeSiblingContext(siblings) : null
    };

    return classifySection(factors);
}

/**
 * Classify section based on multiple factors
 */
function classifySection(factors: any): {type: 'header' | 'navigation' | 'content' | 'footer' | 'sidebar' | 'modal' | 'other'; confidence: number; reasoning: string[]} {
    const candidates: Array<{type: 'header' | 'navigation' | 'content' | 'footer' | 'sidebar' | 'modal' | 'other'; confidence: number; reasoning: string[]}> = [];
    
    // Name-based classification
    if (factors.nodeName.confidence > 0.7) {
        const nameType = factors.nodeName.type;
        const sectionType = (['header', 'navigation', 'content', 'footer', 'sidebar', 'modal'].includes(nameType)) 
            ? nameType as 'header' | 'navigation' | 'content' | 'footer' | 'sidebar' | 'modal'
            : 'other' as const;
        
        candidates.push({
            type: sectionType,
            confidence: factors.nodeName.confidence,
            reasoning: ['Node name indicates section type']
        });
    }
    
    // Position-based classification
    if (factors.position) {
        if (factors.position.isTopLevel) {
            candidates.push({
                type: 'header',
                confidence: 0.7,
                reasoning: ['Positioned in top area of screen']
            });
        } else if (factors.position.isBottomLevel) {
            candidates.push({
                type: 'footer',
                confidence: 0.7,
                reasoning: ['Positioned in bottom area of screen']
            });
        }
    }
    
    // Styling-based classification
    if (factors.styling.buttonLike > 0.6 && factors.siblings?.hasMultipleButtons) {
        candidates.push({
            type: 'navigation',
            confidence: 0.6,
            reasoning: ['Multiple button-like elements suggest navigation']
        });
    }
    
    // Apply confidence threshold
    const highConfidenceCandidates = candidates.filter(c => c.confidence >= 0.6);
    
    if (highConfidenceCandidates.length === 0) {
        return {
            type: 'content',
            confidence: 0.5,
            reasoning: ['Default classification - insufficient confidence in alternatives']
        };
    }
    
    // Return best match
    highConfidenceCandidates.sort((a, b) => b.confidence - a.confidence);
    const bestMatch = highConfidenceCandidates[0];
    
    return {
        type: bestMatch.type,
        confidence: bestMatch.confidence,
        reasoning: bestMatch.reasoning
    };
}

/**
 * Analyze sibling context for section detection
 */
function analyzeSiblingContext(siblings: any[]): {hasMultipleButtons: boolean; hasNavigation: boolean} {
    const buttonLikeSiblings = siblings.filter(sibling => {
        const name = sibling.name?.toLowerCase() || '';
        return name.includes('button') || name.includes('btn') || name.includes('tab');
    });
    
    const navigationSiblings = siblings.filter(sibling => {
        const name = sibling.name?.toLowerCase() || '';
        return name.includes('nav') || name.includes('menu') || name.includes('link');
    });
    
    return {
        hasMultipleButtons: buttonLikeSiblings.length >= 2,
        hasNavigation: navigationSiblings.length > 0
    };
}

/**
 * Generate semantic context from component hierarchy
 */
export function generateSemanticContext(
    node: any,
    parent?: any,
    siblings?: any[]
): SemanticContext {
    const parentName = parent?.name?.toLowerCase() || '';
    const siblingTypes = siblings?.map(s => s.type) || [];
    
    // Determine screen position
    let screenPosition: SemanticContext['screenPosition'] = 'unknown';
    if (parent?.absoluteBoundingBox) {
        const relativeY = (node.absoluteBoundingBox?.y || 0) - parent.absoluteBoundingBox.y;
        const parentHeight = parent.absoluteBoundingBox.height;
        
        if (relativeY < parentHeight * 0.15) screenPosition = 'header';
        else if (relativeY > parentHeight * 0.85) screenPosition = 'footer';
        else screenPosition = 'content';
    }
    
    // Determine component type
    let componentType: SemanticContext['componentType'] = 'unknown';
    if (parentName.includes('form') || parentName.includes('input')) componentType = 'form';
    else if (parentName.includes('nav') || parentName.includes('menu')) componentType = 'navigation';
    else if (parentName.includes('card') || parentName.includes('item')) componentType = 'card';
    else if (parentName.includes('button') && siblings?.length) componentType = 'button-group';
    else componentType = 'content';
    
    // Detect actionable neighbors
    const hasActionableNeighbors = siblings?.some(sibling => {
        const name = sibling.name?.toLowerCase() || '';
        return name.includes('button') || name.includes('link') || name.includes('nav');
    }) || false;
    
    return {
        parentType: parent?.type,
        siblingTypes,
        screenPosition,
        componentType,
        layoutDirection: parent?.layoutMode === 'HORIZONTAL' ? 'horizontal' : 'vertical',
        hasActionableNeighbors
    };
}

```
Page 2/3FirstPrevNextLast