/**
 * Design System Server (DSS) - App Shell
 *
 * Main application controller.
 * Handles routing, state, and integration with services.
 */

import store from '../stores/app-store.js';
import figmaService from '../services/figma-service.js';
import discoveryService from '../services/discovery-service.js';
import teamService from '../services/team-service.js';
import toolsService from '../services/tools-service.js';
import claudeService from '../services/claude-service.js';
import DashboardService from '../services/dashboard-service.js';
import pluginService from '../services/plugin-service.js';
import { initializePlugins } from '../plugins/index.js';
import logger from './logger.js';
import themeManager from './theme.js';
import { UITeamDashboard, UXTeamDashboard, QATeamDashboard } from './team-dashboards.js';

// Enterprise Architecture Modules
import router from './router.js';
import { subscribe as subscribeToNotifications, notifySuccess, notifyError, notifyInfo, ErrorCode } from './messaging.js';
import { createProjectWorkflow } from './workflows.js';
import { handleError } from './error-handler.js';
import { loadConfig, getStorybookUrl, getDssHost } from './config-loader.js';
import { getEnabledComponents, getComponentSetting, setComponentSetting } from './component-config.js';
import { sanitizeHtml, setSafeHtml, sanitizeText, escapeHtml } from './sanitizer.js';
import LandingPage from './landing-page.js';
import themeLoader from './theme-loader.js';

class App {
  constructor() {
    this.store = store;
    this.services = {
      figma: figmaService,
      discovery: discoveryService,
      team: teamService
    };
    // Track listener setup to prevent duplicates
    this.listeners = {
      teamContextChanged: null,
      hasTeamContextListener: false
    };
  }

  // === Initialization ===

  async init() {
    logger.info('App', 'Initializing application...');

    // FIRST: Load server configuration (blocking operation)
    // This must complete before any component uses the config
    try {
      await loadConfig();
      this.store.set({ isConfigLoading: false });
      logger.info('App', 'Server configuration loaded');
    } catch (error) {
      this.store.set({
        isConfigLoading: false,
        configError: error.message
      });
      logger.error('App', 'Failed to load server configuration', { error: error.message });
      notifyError('Failed to load server configuration. Some features may not work correctly.', ErrorCode.SYSTEM_STARTUP_FAILED);
    }

    // Initialize DSS Theme Loader (validates CSS layers)
    try {
      await themeLoader.init();
      this.themeLoader = themeLoader;
      logger.info('App', 'DSS Theme Loader initialized');
    } catch (error) {
      logger.warn('App', 'Theme loader initialization failed, using fallback styles', { error: error.message });
    }

    // Initialize plugins
    initializePlugins();
    logger.info('App', 'Plugins initialized');

    // Initialize enterprise messaging system
    this.initializeMessaging();

    // Initialize router with route definitions
    this.initializeRouter();

    // Subscribe to state changes
    this.store.subscribe('currentPage', () => this.render());
    this.store.subscribe('notifications', (notifs) => this.renderNotifications(notifs));
    this.store.subscribe('currentProject', (projectId) => {
      if (projectId) {
        this.loadDashboardData(projectId);
      }
    });

    // Listen for team context changes from chat sidebar (only add listener once)
    if (!this.listeners.hasTeamContextListener) {
      this.listeners.teamContextChanged = (e) => {
        logger.info('App', 'Team context changed', { team: e.detail.team });
        this.store.set({ teamContext: e.detail.team });
        this.render();
      };
      window.addEventListener('team-context-changed', this.listeners.teamContextChanged);
      this.listeners.hasTeamContextListener = true;
    }

    // Load initial data
    await this.loadInitialData();

    // Update Storybook link with configured URL
    this.updateStorybookLink();

    // Initialize landing page with dashboard cards
    const appElement = document.getElementById('app');
    if (appElement) {
      this.landingPage = new LandingPage(appElement);
      logger.info('App', 'Landing page initialized');
    }

    // Render the app
    this.render();

    // Set up polling
    setInterval(() => this.refreshHealth(), 30000);

    logger.info('App', 'Application initialized successfully');
  }

  /**
   * Initialize enterprise messaging system
   */
  initializeMessaging() {
    // Subscribe to notification events
    subscribeToNotifications((notification) => {
      // Use the existing store notification system for UI display
      const duration = notification.duration || 5000;
      this.store.notify(notification.message, notification.type, duration);

      // Log to console for debugging
      logger.info('Notification', notification.message, {
        code: notification.code,
        correlationId: notification.correlationId,
      });
    });

    logger.info('App', 'Messaging system initialized');
  }

  /**
   * Initialize router with route definitions
   */
  initializeRouter() {
    // Register all application routes
    router.registerAll([
      {
        path: 'dashboard',
        name: 'dashboard',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'dashboard' });
          this.render();
        },
      },
      {
        path: 'projects',
        name: 'projects',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'projects' });
          this.render();
        },
      },
      {
        path: 'tokens',
        name: 'tokens',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'tokens' });
          this.render();
        },
      },
      {
        path: 'components',
        name: 'components',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'components' });
          this.render();
        },
      },
      {
        path: 'figma',
        name: 'figma',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'figma' });
          this.render();
        },
      },
      {
        path: 'docs',
        name: 'docs',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'docs' });
          this.render();
        },
      },
      {
        path: 'teams',
        name: 'teams',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'teams' });
          this.render();
        },
      },
      {
        path: 'audit',
        name: 'audit',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'audit' });
          this.render();
        },
      },
      {
        path: 'settings',
        name: 'settings',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'settings' });
          this.render();
        },
      },
      {
        path: 'services',
        name: 'services',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'services' });
          this.render();
        },
      },
      {
        path: 'quick-wins',
        name: 'quick-wins',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'quick-wins' });
          this.render();
        },
      },
      {
        path: 'chat',
        name: 'chat',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'chat' });
          this.render();
        },
      },
      {
        path: 'plugins',
        name: 'plugins',
        handler: ({ router }) => {
          this.store.set({ currentPage: 'plugins' });
          this.render();
        },
      },
      {
        path: 'workdesk',
        name: 'workdesk',
        handler: async ({ router }) => {
          logger.info('App', 'Mounting workdesk UI');

          // Get app container
          const appRoot = document.getElementById('app');
          if (!appRoot) {
            logger.error('App', 'Cannot mount workdesk: #app element not found');
            return;
          }

          // Full page takeover - clear legacy layout
          appRoot.innerHTML = '';

          // Dynamically import and mount ds-shell
          try {
            await import('../components/layout/ds-shell.js');

            const shell = document.createElement('ds-shell');
            shell.setAttribute('mode', 'production');
            appRoot.appendChild(shell);

            logger.info('App', 'Workdesk mounted successfully');
          } catch (error) {
            logger.error('App', 'Failed to mount workdesk', { error: error.message });
            appRoot.innerHTML = `
              <div style="padding: 48px; text-align: center; color: #f48771;">
                <h2>Failed to Load Workdesk</h2>
                <p style="margin-top: 16px;">Error: ${error.message}</p>
                <button onclick="window.location.hash='dashboard'" style="margin-top: 24px; padding: 8px 16px;">
                  Return to Dashboard
                </button>
              </div>
            `;
          }
        },
      },
    ]);

    // Set default route
    router.setDefaultRoute('dashboard');

    // Initialize router
    router.init();

    logger.info('App', 'Router initialized with 13 routes');
  }

  async loadInitialData() {
    this.store.setLoading('init', true);

    try {
      // Check API connection first
      const health = await this.services.discovery.getHealth();
      this.store.setHealth(health);
      this.store.set({ apiConnected: true });

      // Load runtime configuration and services
      await this.loadConfig();

      // Load discovery data
      const discovery = await this.services.discovery.discover('.', false);
      this.store.setDiscovery(discovery);

      // Load stats
      const stats = await this.services.discovery.getProjectStats();
      this.store.setStats(stats);

      // Load recent activity
      const activity = await this.services.discovery.getRecentActivity();
      this.store.setActivity(activity.items || []);

      // Load projects
      await this.loadProjects();

      // Set user from session or default
      this.store.setUser(
        { id: '1', name: 'User', email: 'user@local' },
        'team-1',
        'TEAM_LEAD'
      );

    } catch (error) {
      logger.error('App', 'Failed to load initial data', error);
      this.store.set({ apiConnected: false });
      this.store.setError('init', 'Cannot connect to DSS server. Run: python tools/api/server.py');
      this.store.notify('Server offline. Start DSS API first.', 'error', 0);
    }

    this.store.setLoading('init', false);
  }

  async refreshHealth() {
    try {
      const health = await this.services.discovery.getHealth();
      this.store.setHealth(health);
    } catch (error) {
      logger.error('App', 'Health check failed', error);
    }
  }

  // === Navigation ===

  navigate(page) {
    window.location.hash = page;
  }

  // === Figma Actions ===

  async extractTokens() {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    this.store.setLoading('extractTokens', true);

    try {
      const result = await this.services.figma.extractVariables(fileKey, 'css');
      this.store.setTokens(result.tokens);
      notifySuccess('Tokens extracted successfully!', ErrorCode.SUCCESS_OPERATION, {
        fileKey,
        tokenCount: result.tokens?.length || 0,
      });
      return result;
    } catch (error) {
      // Use enterprise error handler for user-friendly messages
      handleError(error, {
        operation: 'extract tokens',
        service: 'figma',
        fileKey,
      });
      throw error;
    } finally {
      this.store.setLoading('extractTokens', false);
    }
  }

  async extractComponents() {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    this.store.setLoading('extractComponents', true);

    try {
      const result = await this.services.figma.extractComponents(fileKey);
      this.store.setComponents(result.components);
      this.store.notify('Components extracted successfully', 'success');
      return result;
    } catch (error) {
      this.store.notify(`Failed to extract components: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('extractComponents', false);
    }
  }

  async syncTokens() {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    this.store.setLoading('syncTokens', true);

    try {
      const result = await this.services.figma.syncTokens(fileKey, './admin-ui/css/tokens.css');
      this.store.setLastSync(new Date().toISOString());
      const count = result?.tokens_synced ?? 0;
      this.store.notify(count > 0 ? `Synced ${count} tokens` : 'Sync complete', 'success');
      return result;
    } catch (error) {
      this.store.notify(`Sync failed: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('syncTokens', false);
    }
  }

  async runVisualDiff() {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    this.store.setLoading('visualDiff', true);

    try {
      const result = await this.services.figma.visualDiff(fileKey);
      if (result.changes_detected) {
        this.store.notify(`Visual diff: ${result.summary.changed} changes detected`, 'warning');
      } else {
        this.store.notify('No visual changes detected', 'success');
      }
      return result;
    } catch (error) {
      this.store.notify(`Visual diff failed: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('visualDiff', false);
    }
  }

  async validateComponents() {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    this.store.setLoading('validate', true);

    try {
      const result = await this.services.figma.validateComponents(fileKey);
      const { errors, warnings } = result.summary;
      if (errors > 0) {
        this.store.notify(`Validation: ${errors} errors, ${warnings} warnings`, 'error');
      } else if (warnings > 0) {
        this.store.notify(`Validation passed with ${warnings} warnings`, 'warning');
      } else {
        this.store.notify('All components valid', 'success');
      }
      return result;
    } catch (error) {
      this.store.notify(`Validation failed: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('validate', false);
    }
  }

  async generateCode(componentName, framework = null) {
    const fileKey = this.store.get('figmaFileKey') || 'demo';
    const targetFramework = framework || this.store.get('componentFramework') || 'react';
    this.store.setLoading('generateCode', true);

    try {
      const result = await this.services.figma.generateCode(fileKey, componentName, targetFramework);
      this.store.set({
        generatedCode: {
          component: componentName,
          framework: targetFramework,
          code: result.code || result.generated_code || '// Code generation in progress...'
        }
      });
      this.store.notify(`Generated ${componentName} for ${targetFramework}`, 'success');
      this.render();
      return result;
    } catch (error) {
      this.store.notify(`Code generation failed: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('generateCode', false);
    }
  }

  // === Discovery Actions ===

  getProjectRoot() {
    const project = this.store.get('selectedProject');
    return project?.root_path || project?.path || '.';
  }

  async runDiscovery(fullScan = false) {
    this.store.setLoading('discovery', true);
    const projectRoot = this.getProjectRoot();

    try {
      const result = await this.services.discovery.discover(projectRoot, fullScan);
      this.store.setDiscovery(result);
      const pathInfo = projectRoot !== '.' ? ` (${projectRoot})` : '';
      this.store.notify(`Discovery complete${pathInfo}`, 'success');
      return result;
    } catch (error) {
      this.store.notify(`Discovery failed: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('discovery', false);
    }
  }

  // === Rendering ===

  render() {
    const contentArea = document.getElementById('page-content');
    if (!contentArea) return;

    const page = this.store.get('currentPage');
    setSafeHtml(contentArea, this.getPageContent(page));

    // Update active nav item
    document.querySelectorAll('.nav-item[data-page]').forEach(item => {
      item.classList.toggle('active', item.dataset.page === page);
    });

    // Attach event handlers
    this.attachEventHandlers();
  }

  getPageContent(page) {
    switch (page) {
      case 'dashboard': return this.renderDashboard();
      case 'services': return this.renderServices();
      case 'quick-wins': return this.renderQuickWins();
      case 'chat': return this.renderChat();
      case 'projects': return this.renderProjects();
      case 'tokens': return this.renderTokens();
      case 'components': return this.renderComponents();
      case 'figma': return this.renderFigma();
      case 'docs': return this.renderDocs();
      case 'teams': return this.renderTeams();
      case 'plugins': return this.renderPlugins();
      case 'audit': return this.renderAuditLog();
      case 'settings': return this.renderSettings();
      default: return this.renderDashboard();
    }
  }

  renderDashboard() {
    const teamContext = this.store.get('teamContext') || localStorage.getItem('dss_team_context') || 'all';
    const health = this.store.get('health') || {};
    const stats = this.store.get('stats') || {};
    const discovery = this.store.get('discovery') || {};
    const activity = this.store.get('activity') || [];
    const dashboardData = this.store.get('dashboardData') || {
      ux: { figma_files_count: 0, figma_files: [] },
      ui: { token_drift: { total: 0, by_severity: {} }, code_metrics: {} },
      qa: { esre_count: 0, test_summary: {} }
    };

    const healthScore = discovery.health?.score || 0;
    const healthGrade = discovery.health?.grade || '-';

    const teamNames = {
      'all': 'All Teams',
      'ui': 'UI Team',
      'ux': 'UX Team',
      'qa': 'QA Team'
    };

    // Get current project
    const currentProjectId = this.store.get('currentProject');
    const projects = this.store.get('projects') || [];
    const currentProject = projects.find(p => p.id === currentProjectId);
    const projectName = currentProject?.name || 'No Project Selected';

    // Render team-specific dashboard
    switch(teamContext) {
      case 'ui':
        return UITeamDashboard(health, stats, discovery, activity, projectName, dashboardData, currentProjectId, this);
      case 'ux':
        return UXTeamDashboard(health, stats, discovery, activity, projectName, dashboardData, currentProjectId, this);
      case 'qa':
        return QATeamDashboard(health, stats, discovery, activity, projectName, dashboardData, currentProjectId, this);
      default:
        return this.renderAllTeamsDashboard(health, stats, discovery, activity, healthScore, healthGrade);
    }
  }

  renderAllTeamsDashboard(health, stats, discovery, activity, healthScore, healthGrade) {
    return `
      <div class="page-header">
        <h1>Dashboard</h1>
        <p class="text-muted">Design System Orchestrator Overview · <span class="text-primary">Select a team in chat panel →</span></p>
      </div>

      <!-- Stats Grid -->
      <div class="grid grid-cols-4 gap-4 mt-6">
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Health Score</div>
              <div class="stat__value flex items-center gap-2">
                <span class="status-dot ${healthScore >= 80 ? 'status-dot--success' : healthScore >= 60 ? 'status-dot--warning' : 'status-dot--error'}"></span>
                ${healthScore}% (${healthGrade})
              </div>
            </div>
          </ds-card-content>
        </ds-card>

        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Design Tokens</div>
              <div class="stat__value">${stats.tokens?.total || 0}</div>
            </div>
          </ds-card-content>
        </ds-card>

        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Components</div>
              <div class="stat__value">${stats.components?.total || discovery.files?.components || 0}</div>
            </div>
          </ds-card-content>
        </ds-card>

        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Syncs Today</div>
              <div class="stat__value">${stats.syncs?.today || 0}</div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Design System Ingestion -->
      <ds-card class="mt-6">
        <ds-card-header>
          <ds-card-title>Ingest Design System</ds-card-title>
          <ds-card-description>Add a design system using natural language</ds-card-description>
        </ds-card-header>
        <ds-card-content>
          <div class="flex gap-3">
            <input
              type="text"
              id="ingest-prompt"
              class="input flex-1"
              placeholder='Try: "add heroui", "ingest material ui", "use shadcn"...'
              style="font-size: 0.95rem; padding: 0.75rem 1rem;"
            />
            <ds-button data-variant="primary" data-action="parseIngestion" ${this.store.isLoading('ingestion') ? 'loading' : ''}>
              Ingest
            </ds-button>
            <ds-button data-variant="outline" data-action="browseDesignSystems">
              Browse
            </ds-button>
          </div>
          ${this.renderIngestionResult()}
        </ds-card-content>
      </ds-card>

      <!-- Main Content -->
      <div class="grid grid-cols-2 gap-6 mt-6">
        <!-- Quick Actions -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Quick Actions</ds-card-title>
            <ds-card-description>Common operations</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-wrap gap-3">
              <ds-button data-variant="primary" data-action="extractTokens" ${this.store.isLoading('extractTokens') ? 'loading' : ''}>
                Extract Tokens
              </ds-button>
              <ds-button data-variant="outline" data-action="syncTokens" ${this.store.isLoading('syncTokens') ? 'loading' : ''}>
                Sync Tokens
              </ds-button>
              <ds-button data-variant="outline" data-action="validateComponents" ${this.store.isLoading('validate') ? 'loading' : ''}>
                Validate
              </ds-button>
              <ds-button data-variant="outline" data-action="runVisualDiff" ${this.store.isLoading('visualDiff') ? 'loading' : ''}>
                Visual Diff
              </ds-button>
              <ds-button data-variant="ghost" data-action="runDiscovery">
                Re-scan Project
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Project Info -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Project Info</ds-card-title>
            <ds-card-description>Discovered configuration</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-2 text-sm">
              <div class="flex justify-between">
                <span class="text-muted">Project Types:</span>
                <span>${(discovery.project?.types || []).join(', ') || 'Unknown'}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Frameworks:</span>
                <span>${(discovery.project?.frameworks || []).join(', ') || 'None detected'}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Total Files:</span>
                <span>${discovery.files?.total || 0}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">CSS Files:</span>
                <span>${discovery.files?.css || 0}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Git Branch:</span>
                <span>${discovery.git?.branch || 'N/A'}</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Uncommitted:</span>
                <span>${discovery.git?.uncommitted_changes || 0} changes</span>
              </div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Recent Activity & Health Checks -->
      <div class="grid grid-cols-2 gap-6 mt-6">
        <ds-card>
          <ds-card-header>
            <ds-card-title>Recent Activity</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            ${activity.length > 0 ? `
              <div class="flex flex-col gap-3">
                ${activity.slice(0, 5).map(item => `
                  <div class="flex items-center gap-3 text-sm">
                    <span class="status-dot ${item.status === 'success' ? 'status-dot--success' : item.status === 'warning' ? 'status-dot--warning' : 'status-dot--error'}"></span>
                    <span class="flex-1">${item.message}</span>
                    <span class="text-muted text-xs">${this.formatTime(item.timestamp)}</span>
                  </div>
                `).join('')}
              </div>
            ` : '<p class="text-muted text-sm">No recent activity</p>'}
          </ds-card-content>
        </ds-card>

        <ds-card>
          <ds-card-header>
            <ds-card-title>System Health</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            ${health.checks ? `
              <div class="flex flex-col gap-3">
                ${health.checks.map(check => `
                  <div class="flex items-center gap-3 text-sm">
                    <span class="status-dot ${check.status === 'ok' ? 'status-dot--success' : check.status === 'warning' ? 'status-dot--warning' : 'status-dot--error'}"></span>
                    <span class="flex-1">${check.name}</span>
                    <span class="text-muted text-xs">${check.message || (check.latency ? `${check.latency}ms` : 'OK')}</span>
                  </div>
                `).join('')}
              </div>
            ` : '<p class="text-muted text-sm">Loading health status...</p>'}
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Health Issues -->
      ${discovery.health?.issues?.length > 0 ? `
        <ds-card class="mt-6">
          <ds-card-header>
            <ds-card-title>Improvement Suggestions</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-2">
              ${discovery.health.issues.map(issue => `
                <div class="flex items-center gap-3 text-sm">
                  <ds-badge data-variant="warning">Suggestion</ds-badge>
                  <span>${issue}</span>
                </div>
              `).join('')}
            </div>
          </ds-card-content>
        </ds-card>
      ` : ''}
    `;
  }

  renderTokens() {
    const tokens = this.store.get('tokens') || [];
    const selectedProject = this.store.get('selectedProject');
    const exportFormat = this.store.get('tokenExportFormat') || 'css';

    const byCategory = tokens.reduce((acc, t) => {
      const cat = t.category || 'other';
      if (!acc[cat]) acc[cat] = [];
      acc[cat].push(t);
      return acc;
    }, {});

    const categoryOrder = ['color', 'spacing', 'sizing', 'typography', 'radius', 'shadow', 'other'];
    const sortedCategories = Object.keys(byCategory).sort((a, b) => {
      return categoryOrder.indexOf(a) - categoryOrder.indexOf(b);
    });

    const stats = {
      total: tokens.length,
      colors: byCategory.color?.length || 0,
      spacing: byCategory.spacing?.length || 0,
      typography: byCategory.typography?.length || 0
    };

    return `
      <div class="page-header">
        <h1>Design Tokens</h1>
        <p class="text-muted">
          ${selectedProject ? `Tokens from ${selectedProject.name}` : 'Extract and manage design tokens from Figma'}
        </p>
      </div>

      <!-- Stats Row -->
      <div class="grid grid-cols-4 gap-4 mt-6">
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Total Tokens</div>
              <div class="stat__value">${stats.total}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Colors</div>
              <div class="stat__value">${stats.colors}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Spacing</div>
              <div class="stat__value">${stats.spacing}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Typography</div>
              <div class="stat__value">${stats.typography}</div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Actions -->
      <div class="flex justify-between items-center mt-6 mb-4">
        <div class="flex gap-3">
          <ds-button data-variant="primary" data-action="extractTokens" ${this.store.isLoading('extractTokens') ? 'loading' : ''}>
            Extract from Figma
          </ds-button>
          <ds-button data-variant="outline" data-action="syncTokens" ${this.store.isLoading('syncTokens') ? 'loading' : ''}>
            Sync to Files
          </ds-button>
        </div>
        <div class="flex gap-2 items-center">
          <span class="text-sm text-muted">Export as:</span>
          <ds-button data-variant="${exportFormat === 'css' ? 'primary' : 'ghost'}" data-size="sm" data-action="setExportFormat" data-format="css">CSS</ds-button>
          <ds-button data-variant="${exportFormat === 'scss' ? 'primary' : 'ghost'}" data-size="sm" data-action="setExportFormat" data-format="scss">SCSS</ds-button>
          <ds-button data-variant="${exportFormat === 'json' ? 'primary' : 'ghost'}" data-size="sm" data-action="setExportFormat" data-format="json">JSON</ds-button>
          <ds-button data-variant="${exportFormat === 'ts' ? 'primary' : 'ghost'}" data-size="sm" data-action="setExportFormat" data-format="ts">TypeScript</ds-button>
        </div>
      </div>

      ${tokens.length > 0 ? sortedCategories.map(category => {
        const categoryTokens = byCategory[category];
        const categoryName = category.charAt(0).toUpperCase() + category.slice(1);
        const isColor = category === 'color';

        return `
        <ds-card class="mt-4">
          <ds-card-header>
            <ds-card-title>${categoryName}</ds-card-title>
            <ds-badge data-variant="outline">${categoryTokens.length} tokens</ds-badge>
          </ds-card-header>
          <ds-card-content>
            ${isColor ? `
              <div class="grid grid-cols-6 gap-3">
                ${categoryTokens.map(token => `
                  <div class="token-swatch" title="${token.name}: ${token.value}">
                    <div class="token-swatch__color" style="background: ${token.value}; height: 48px; border-radius: var(--radius) var(--radius) 0 0; border: 1px solid var(--border);"></div>
                    <div class="token-swatch__info p-2 rounded-b text-center" style="background: var(--muted); border: 1px solid var(--border); border-top: 0;">
                      <div class="text-xs font-medium truncate">--${token.name}</div>
                      <div class="text-xs text-muted font-mono">${token.value}</div>
                    </div>
                  </div>
                `).join('')}
              </div>
            ` : `
              <div class="grid grid-cols-4 gap-3">
                ${categoryTokens.map(token => `
                  <div class="flex items-center gap-3 p-3 rounded" style="background: var(--muted)">
                    ${category === 'spacing' || category === 'sizing' ? `
                      <div style="width: ${Math.min(parseInt(token.value) || 16, 48)}px; height: 16px; background: var(--primary); border-radius: 2px; flex-shrink: 0;"></div>
                    ` : category === 'radius' ? `
                      <div style="width: 24px; height: 24px; background: var(--primary); border-radius: ${token.value}; flex-shrink: 0;"></div>
                    ` : category === 'shadow' ? `
                      <div style="width: 24px; height: 24px; background: var(--card); box-shadow: ${token.value}; border-radius: var(--radius-sm); flex-shrink: 0;"></div>
                    ` : ''}
                    <div class="flex flex-col min-w-0">
                      <span class="text-sm font-medium truncate">--${token.name}</span>
                      <span class="text-xs text-muted font-mono truncate">${token.value}</span>
                    </div>
                  </div>
                `).join('')}
              </div>
            `}
          </ds-card-content>
        </ds-card>
      `}).join('') : `
        <ds-card class="mt-4">
          <ds-card-content>
            <div class="text-center p-8">
              <svg class="mx-auto mb-4 opacity-50" width="48" height="48" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
                <circle cx="12" cy="12" r="10"/>
                <circle cx="12" cy="12" r="4"/>
              </svg>
              <p class="text-muted mb-4">No tokens extracted yet.</p>
              <p class="text-sm text-muted mb-4">Connect to Figma and extract design tokens to see them here.</p>
              <ds-button data-variant="primary" data-action="extractTokens">
                Extract Tokens from Figma
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>
      `}
    `;
  }

  renderComponents() {
    const components = this.store.get('components') || [];
    const selectedFramework = this.store.get('componentFramework') || 'react';
    const generatedCode = this.store.get('generatedCode');

    const frameworks = [
      { id: 'react', name: 'React', icon: 'R' },
      { id: 'vue', name: 'Vue', icon: 'V' },
      { id: 'webcomponent', name: 'Web Component', icon: 'W' },
      { id: 'svelte', name: 'Svelte', icon: 'S' }
    ];

    return `
      <div class="page-header">
        <h1>Components</h1>
        <p class="text-muted">View extracted components and generate code</p>
      </div>

      <!-- Stats -->
      <div class="grid grid-cols-4 gap-4 mt-6">
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Total Components</div>
              <div class="stat__value">${components.length}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">With Variants</div>
              <div class="stat__value">${components.filter(c => c.variants?.length > 0).length}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">With Properties</div>
              <div class="stat__value">${components.filter(c => c.properties?.length > 0).length}</div>
            </div>
          </ds-card-content>
        </ds-card>
        <ds-card>
          <ds-card-content>
            <div class="stat">
              <div class="stat__label">Target Framework</div>
              <div class="stat__value text-lg">${frameworks.find(f => f.id === selectedFramework)?.name || 'React'}</div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Actions -->
      <div class="flex justify-between items-center mt-6 mb-4">
        <div class="flex gap-3">
          <ds-button data-variant="primary" data-action="extractComponents" ${this.store.isLoading('extractComponents') ? 'loading' : ''}>
            Extract from Figma
          </ds-button>
          <ds-button data-variant="outline" data-action="validateComponents" ${this.store.isLoading('validate') ? 'loading' : ''}>
            Validate All
          </ds-button>
        </div>
        <div class="flex gap-2 items-center">
          <span class="text-sm text-muted">Generate for:</span>
          ${frameworks.map(fw => `
            <ds-button
              data-variant="${selectedFramework === fw.id ? 'primary' : 'ghost'}"
              data-size="sm"
              data-action="setFramework"
              data-framework="${fw.id}"
              title="${fw.name}"
            >${fw.icon}</ds-button>
          `).join('')}
        </div>
      </div>

      ${generatedCode ? `
        <ds-card class="mb-4">
          <ds-card-header>
            <ds-card-title>Generated Code: ${generatedCode.component}</ds-card-title>
            <ds-button data-variant="ghost" data-size="sm" data-action="closeGeneratedCode">Close</ds-button>
          </ds-card-header>
          <ds-card-content>
            <pre class="p-4 rounded overflow-x-auto text-sm" style="background: var(--muted); font-family: monospace; max-height: 400px;"><code>${this.escapeHtml(generatedCode.code)}</code></pre>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="outline" data-size="sm" data-action="copyCode">Copy to Clipboard</ds-button>
          </ds-card-footer>
        </ds-card>
      ` : ''}

      ${components.length > 0 ? `
        <div class="grid grid-cols-3 gap-4">
          ${components.map(comp => `
            <ds-card class="component-card">
              <ds-card-header>
                <div class="flex items-center gap-2">
                  <div class="w-8 h-8 rounded flex items-center justify-center text-sm font-bold" style="background: var(--primary); color: var(--primary-foreground);">
                    ${comp.name.charAt(0).toUpperCase()}
                  </div>
                  <ds-card-title>${comp.name}</ds-card-title>
                </div>
              </ds-card-header>
              <ds-card-content>
                <p class="text-sm text-muted mb-3">${comp.description || 'Component from Figma'}</p>

                ${comp.variants?.length > 0 ? `
                  <div class="mb-3">
                    <div class="text-xs text-muted mb-1">Variants:</div>
                    <div class="flex flex-wrap gap-1">
                      ${comp.variants.slice(0, 5).map(v => `<ds-badge data-variant="secondary" data-size="sm">${v}</ds-badge>`).join('')}
                      ${comp.variants.length > 5 ? `<ds-badge data-variant="outline" data-size="sm">+${comp.variants.length - 5}</ds-badge>` : ''}
                    </div>
                  </div>
                ` : ''}

                ${comp.properties?.length > 0 ? `
                  <div class="mb-3">
                    <div class="text-xs text-muted mb-1">Properties:</div>
                    <div class="flex flex-wrap gap-1">
                      ${comp.properties.slice(0, 4).map(p => `<ds-badge data-variant="outline" data-size="sm">${p.name}: ${p.type}</ds-badge>`).join('')}
                      ${comp.properties.length > 4 ? `<ds-badge data-variant="outline" data-size="sm">+${comp.properties.length - 4}</ds-badge>` : ''}
                    </div>
                  </div>
                ` : ''}

                <div class="flex justify-between text-xs text-muted">
                  <span>Key: ${comp.key?.slice(0, 8) || 'N/A'}...</span>
                </div>
              </ds-card-content>
              <ds-card-footer>
                <div class="flex gap-2">
                  <ds-button data-variant="primary" data-size="sm" data-action="generateCode" data-component="${comp.name}" ${this.store.isLoading('generateCode') ? 'loading' : ''}>
                    Generate ${frameworks.find(f => f.id === selectedFramework)?.name || 'Code'}
                  </ds-button>
                  <ds-button data-variant="ghost" data-size="sm" data-action="viewComponent" data-component="${comp.name}">
                    Details
                  </ds-button>
                </div>
              </ds-card-footer>
            </ds-card>
          `).join('')}
        </div>
      ` : `
        <ds-card>
          <ds-card-content>
            <div class="text-center p-8">
              <svg class="mx-auto mb-4 opacity-50" width="48" height="48" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
                <rect x="3" y="3" width="18" height="18" rx="2"/>
                <path d="M3 9h18"/>
                <path d="M9 21V9"/>
              </svg>
              <p class="text-muted mb-4">No components extracted yet.</p>
              <p class="text-sm text-muted mb-4">Extract components from your Figma file to generate code.</p>
              <ds-button data-variant="primary" data-action="extractComponents">
                Extract Components from Figma
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>
      `}
    `;
  }

  escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  renderFigma() {
    const figmaFileKey = this.store.get('figmaFileKey') || '';
    const selectedProject = this.store.get('selectedProject');
    const projectDescription = selectedProject?.description || '';
    const lastSync = this.store.get('lastSync');

    return `
      <div class="page-header">
        <h1>Project Settings</h1>
        <p class="text-muted">Configure your project and Figma integration</p>
      </div>

      <div class="grid grid-cols-2 gap-6 mt-6">
        <ds-card>
          <ds-card-header>
            <ds-card-title>Project Details</ds-card-title>
            <ds-card-description>Describe your design system project</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <ds-input
              id="project-description"
              label="Project Description"
              placeholder="Brief description of this design system"
              value="${this.escapeHtml(projectDescription)}"
            ></ds-input>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="primary" data-action="saveProjectDescription">
              Save Description
            </ds-button>
          </ds-card-footer>
        </ds-card>

        <ds-card>
          <ds-card-header>
            <ds-card-title>Figma Connection</ds-card-title>
            <ds-card-description>Configure your Figma file</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <ds-input
              id="figma-file-key"
              label="Figma File Key"
              placeholder="Enter your Figma file key"
              value="${figmaFileKey}"
            ></ds-input>
            <p class="text-xs text-muted mt-2">Find this in your Figma URL: figma.com/file/<strong>[FILE_KEY]</strong>/...</p>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="primary" data-action="saveFigmaKey">
              Save & Connect
            </ds-button>
          </ds-card-footer>
        </ds-card>

        <ds-card>
          <ds-card-header>
            <ds-card-title>Sync Status</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-3">
              <div class="flex justify-between items-center">
                <span>Connection:</span>
                <ds-badge data-variant="${figmaFileKey ? 'success' : 'secondary'}" dot>
                  ${figmaFileKey ? 'Connected' : 'Not configured'}
                </ds-badge>
              </div>
              <div class="flex justify-between items-center">
                <span>Last Sync:</span>
                <span class="text-muted">${lastSync ? this.formatTime(lastSync) : 'Never'}</span>
              </div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <ds-card class="mt-6">
        <ds-card-header>
          <ds-card-title>Available Tools</ds-card-title>
          <ds-card-description>Figma integration capabilities</ds-card-description>
        </ds-card-header>
        <ds-card-content>
          <div class="grid grid-cols-2 gap-4">
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Extract Variables</h4>
              <p class="text-sm text-muted">Pull design tokens from Figma variables</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Extract Components</h4>
              <p class="text-sm text-muted">Get component definitions and variants</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Extract Styles</h4>
              <p class="text-sm text-muted">Pull text, color, and effect styles</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Sync Tokens</h4>
              <p class="text-sm text-muted">Sync tokens to CSS/SCSS/JSON files</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Visual Diff</h4>
              <p class="text-sm text-muted">Compare visual changes between versions</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Validate Components</h4>
              <p class="text-sm text-muted">Check components against naming rules</p>
            </div>
            <div class="p-4 rounded" style="background: var(--muted)">
              <h4 class="font-medium mb-1">Generate Code</h4>
              <p class="text-sm text-muted">Create component code from designs</p>
            </div>
          </div>
        </ds-card-content>
      </ds-card>
    `;
  }

  renderTeams() {
    const user = this.store.get('user');
    const role = this.store.get('role');

    return `
      <div class="page-header">
        <h1>Team Management</h1>
        <p class="text-muted">Manage teams and permissions</p>
      </div>

      <div class="flex gap-3 mt-6 mb-4">
        ${this.store.hasPermission('manage_team_members') ? `
          <ds-button data-variant="primary" data-action="createTeam">
            Create Team
          </ds-button>
        ` : ''}
      </div>

      <div class="grid grid-cols-3 gap-4 mt-4">
        <ds-card>
          <ds-card-header>
            <ds-card-title>Design System Core</ds-card-title>
            <ds-badge data-variant="success" dot>Active</ds-badge>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-2 text-sm">
              <div class="flex justify-between">
                <span class="text-muted">Members:</span>
                <span>5</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Projects:</span>
                <span>3</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Your Role:</span>
                <ds-badge data-variant="outline">${role}</ds-badge>
              </div>
            </div>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="ghost" data-size="sm">View Details</ds-button>
          </ds-card-footer>
        </ds-card>

        <ds-card>
          <ds-card-header>
            <ds-card-title>Product Team A</ds-card-title>
            <ds-badge data-variant="secondary">Member</ds-badge>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-2 text-sm">
              <div class="flex justify-between">
                <span class="text-muted">Members:</span>
                <span>8</span>
              </div>
              <div class="flex justify-between">
                <span class="text-muted">Projects:</span>
                <span>2</span>
              </div>
            </div>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="ghost" data-size="sm">View Details</ds-button>
          </ds-card-footer>
        </ds-card>
      </div>

      <ds-card class="mt-6">
        <ds-card-header>
          <ds-card-title>Role Permissions</ds-card-title>
        </ds-card-header>
        <ds-card-content>
          <div class="grid grid-cols-4 gap-4 text-sm">
            <div>
              <h4 class="font-medium mb-2">Super Admin</h4>
              <p class="text-muted">Full system access</p>
            </div>
            <div>
              <h4 class="font-medium mb-2">Team Lead</h4>
              <p class="text-muted">Manage team, sync, generate</p>
            </div>
            <div>
              <h4 class="font-medium mb-2">Developer</h4>
              <p class="text-muted">Read, write, sync</p>
            </div>
            <div>
              <h4 class="font-medium mb-2">Viewer</h4>
              <p class="text-muted">Read-only access</p>
            </div>
          </div>
        </ds-card-content>
      </ds-card>
    `;
  }

  renderProjects() {
    const projects = this.store.get('projects') || [];
    const showCreateForm = this.store.get('showCreateProjectForm');

    return `
      <div class="page-header">
        <h1>Projects</h1>
        <p class="text-muted">Manage your design system projects</p>
      </div>

      <div class="flex justify-between items-center mt-6 mb-4">
        <ds-input icon="search" placeholder="Search projects..." id="project-search"></ds-input>
        <ds-button data-variant="primary" data-action="toggleCreateProject" ${this.store.isLoading('createProject') ? 'loading' : ''}>
          ${showCreateForm ? 'Cancel' : 'New Project'}
        </ds-button>
      </div>

      ${showCreateForm ? `
        <ds-card class="mb-6">
          <ds-card-header>
            <ds-card-title>Create New Project</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            <ds-input
              id="new-project-name"
              label="Project Name"
              placeholder="My Design System"
              required
            ></ds-input>
          </ds-card-content>
          <ds-card-footer>
            <ds-button data-variant="primary" data-action="submitCreateProject" ${this.store.isLoading('createProject') ? 'loading' : ''}>
              Create Project
            </ds-button>
          </ds-card-footer>
        </ds-card>
      ` : ''}

      ${projects.length > 0 ? `
        <div class="grid grid-cols-2 gap-4">
          ${projects.map(p => `
            <ds-card class="project-card" data-project-id="${p.id}">
              <ds-card-header>
                <ds-card-title>${p.name}</ds-card-title>
                <ds-badge data-variant="${p.status === 'active' ? 'success' : 'secondary'}" dot>
                  ${p.status || 'active'}
                </ds-badge>
              </ds-card-header>
              <ds-card-content>
                <p class="text-sm mb-3">${p.description || 'No description'}</p>
                <div class="flex flex-col gap-2 text-sm">
                  <div class="flex justify-between">
                    <span class="text-muted">Figma Key:</span>
                    <span class="font-mono text-xs">${p.figma_file_key || 'Not configured'}</span>
                  </div>
                  <div class="flex justify-between">
                    <span class="text-muted">Last Sync:</span>
                    <span>${p.last_sync ? this.formatTime(p.last_sync) : 'Never'}</span>
                  </div>
                  <div class="flex justify-between">
                    <span class="text-muted">Created:</span>
                    <span>${p.created_at ? this.formatTime(p.created_at) : 'Unknown'}</span>
                  </div>
                </div>
              </ds-card-content>
              <ds-card-footer>
                <div class="flex gap-2">
                  <ds-button data-variant="primary" data-size="sm" data-action="selectProject" data-project-id="${p.id}">
                    Open
                  </ds-button>
                  <ds-button data-variant="outline" data-size="sm" data-action="syncProject" data-project-id="${p.id}" data-figma-key="${p.figma_file_key || ''}">
                    Sync Tokens
                  </ds-button>
                  <ds-button data-variant="ghost" data-size="sm" data-action="deleteProject" data-project-id="${p.id}">
                    Delete
                  </ds-button>
                </div>
              </ds-card-footer>
            </ds-card>
          `).join('')}
        </div>
      ` : `
        <ds-card>
          <ds-card-content>
            <div class="text-center p-8">
              <svg class="mx-auto mb-4 opacity-50" width="48" height="48" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
                <path d="M3 3h18v18H3z"/>
                <path d="M21 9H3"/>
                <path d="M9 21V9"/>
              </svg>
              <p class="text-muted mb-4">No projects yet. Create your first project to get started.</p>
              <ds-button data-variant="primary" data-action="toggleCreateProject">
                Create Your First Project
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>
      `}
    `;
  }

  renderSettings() {
    const config = this.store.get('runtimeConfig') || {};
    const services = this.store.get('services') || {};
    const figmaConfig = this.store.get('figmaConfig') || {};
    const mode = config.mode || 'local';

    return `
      <div class="page-header">
        <h1>Settings</h1>
        <p class="text-muted">Configure your design system server</p>
      </div>

      <div class="mt-6 flex flex-col gap-6">
        <!-- DSS Mode -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Server Mode</ds-card-title>
            <ds-card-description>Choose how DSS operates</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex gap-4">
              <div class="flex-1 p-4 rounded cursor-pointer ${mode === 'local' ? 'ring-2 ring-primary' : ''}"
                   style="background: var(--muted)" data-action="setMode" data-mode="local">
                <h4 class="font-medium mb-1">Local Dev Companion</h4>
                <p class="text-sm text-muted">Run alongside your project, provides UI dev assistance, component preview, and local services.</p>
              </div>
              <div class="flex-1 p-4 rounded cursor-pointer ${mode === 'server' ? 'ring-2 ring-primary' : ''}"
                   style="background: var(--muted)" data-action="setMode" data-mode="server">
                <h4 class="font-medium mb-1">Remote Server</h4>
                <p class="text-sm text-muted">Deployed centrally, serves design systems to teams, multi-project management.</p>
              </div>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Figma Configuration -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Figma Integration</ds-card-title>
            <ds-card-description>Connect to Figma API</ds-card-description>
            <ds-badge data-variant="${figmaConfig.configured ? 'success' : 'secondary'}" dot>
              ${figmaConfig.configured ? 'Connected' : 'Not configured'}
            </ds-badge>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-4">
              <ds-input
                id="figma-token-input"
                label="Figma Personal Access Token"
                type="password"
                placeholder="figd_xxxxxxxxxx"
                value="${figmaConfig.configured ? '••••••••••••' : ''}"
              ></ds-input>
              <p class="text-xs text-muted">
                Get your token from <a href="https://www.figma.com/developers/api#access-tokens" target="_blank" class="text-primary">Figma Settings → Personal Access Tokens</a>
              </p>
              <div class="flex gap-2">
                <ds-button data-variant="primary" data-action="saveFigmaToken" ${this.store.isLoading('saveFigmaToken') ? 'loading' : ''}>
                  Save Token
                </ds-button>
                <ds-button data-variant="outline" data-action="testFigmaConnection" ${this.store.isLoading('testFigma') ? 'loading' : ''}>
                  Test Connection
                </ds-button>
              </div>
              ${this.store.get('figmaTestResult') ? `
                <div class="text-sm ${this.store.get('figmaTestResult').success ? 'text-success' : 'text-destructive'}">
                  ${this.store.get('figmaTestResult').success ?
                    `Connected as ${this.store.get('figmaTestResult').user}` :
                    `Error: ${this.store.get('figmaTestResult').error}`}
                </div>
              ` : ''}
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Component Settings (Dynamic from Registry) -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>External Tools & Integrations</ds-card-title>
            <ds-card-description>Configure connected tools and services</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-4">
              ${this.renderComponentSettings()}
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Services Discovery -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Companion Services</ds-card-title>
            <ds-card-description>Discovered and configured services</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="grid grid-cols-3 gap-4">
              ${this.renderServiceCard('storybook', 'Storybook', services)}
              ${this.renderServiceCard('vite', 'Vite Dev Server', services)}
              ${this.renderServiceCard('nextjs', 'Next.js', services)}
            </div>
            <div class="mt-4">
              <ds-button data-variant="ghost" data-action="refreshServices">
                Refresh Services
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Feature Toggles -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Features</ds-card-title>
            <ds-card-description>Enable or disable DSS features</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-3">
              ${this.renderFeatureToggle('visual_qa', 'Visual QA', 'Compare Figma designs with implementation', config.features)}
              ${this.renderFeatureToggle('token_sync', 'Token Sync', 'Sync design tokens to code', config.features)}
              ${this.renderFeatureToggle('code_gen', 'Code Generation', 'Generate component code from Figma', config.features)}
              ${this.renderFeatureToggle('ai_advisor', 'AI Advisor', 'Get AI suggestions for design system improvements', config.features)}
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Appearance -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Appearance</ds-card-title>
            <ds-card-description>Customize the interface</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex items-center justify-between">
              <span>Dark Mode</span>
              <ds-button data-variant="outline" data-size="sm" data-action="toggle-theme">
                Toggle Theme
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Output Configuration -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>Output Configuration</ds-card-title>
            <ds-card-description>Token and component generation settings</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="grid grid-cols-2 gap-4">
              <ds-input label="Token Output Path" value="./admin-ui/css/tokens.css"></ds-input>
              <ds-input label="Component Output Path" value="./admin-ui/js/components"></ds-input>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- Danger Zone -->
        <ds-card style="border-color: var(--destructive);">
          <ds-card-header>
            <ds-card-title style="color: var(--destructive);">⚠️ Danger Zone</ds-card-title>
            <ds-card-description>Irreversible operations - use with caution</ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-4">
              <div>
                <h4 class="font-medium mb-2">Reset DSS to Fresh State</h4>
                <p class="text-sm text-muted mb-3">
                  This will delete all user-created themes, cached data, and project databases.
                  The DSS structure and default themes will be preserved.
                </p>
                <ds-button data-variant="destructive" data-action="resetDSS" ${this.store.isLoading('resetDSS') ? 'loading' : ''}>
                  Reset DSS
                </ds-button>
              </div>
            </div>
          </ds-card-content>
        </ds-card>

        <!-- API Status -->
        <ds-card>
          <ds-card-header>
            <ds-card-title>API Status</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            <div class="flex flex-col gap-2 text-sm">
              <div class="flex justify-between">
                <span>API Mode:</span>
                <ds-badge data-variant="${this.store.get('useMock') ? 'warning' : 'success'}" dot>
                  ${this.store.get('useMock') ? 'Mock (Backend unavailable)' : 'Live'}
                </ds-badge>
              </div>
              <div class="flex justify-between">
                <span>Base URL:</span>
                <span class="text-muted">${window.location.hostname === 'localhost' ? 'http://localhost:3456/api' : '/api'}</span>
              </div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>
    `;
  }

  renderPlugins() {
    const plugins = pluginService.getAll();
    const enabledCount = plugins.filter(p => p.enabled).length;

    return `
      <div class="page-header">
        <h1>Plugins</h1>
        <p class="text-muted">${enabledCount} of ${plugins.length} plugins enabled</p>
      </div>

      <div class="plugins-grid">
        ${plugins.map(plugin => this.renderPluginCard(plugin)).join('')}
      </div>

      <style>
        .plugins-grid {
          display: grid;
          grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
          gap: 16px;
          margin-top: 24px;
        }
        .plugin-card {
          background: var(--card);
          border: 1px solid var(--border);
          border-radius: 8px;
          padding: 16px;
          transition: border-color 0.2s;
        }
        .plugin-card:hover {
          border-color: var(--primary);
        }
        .plugin-card.enabled {
          border-left: 3px solid var(--success);
        }
        .plugin-card__header {
          display: flex;
          align-items: center;
          gap: 12px;
          margin-bottom: 12px;
        }
        .plugin-card__icon {
          font-size: 24px;
          width: 40px;
          height: 40px;
          display: flex;
          align-items: center;
          justify-content: center;
          background: var(--muted);
          border-radius: 8px;
        }
        .plugin-card__title {
          flex: 1;
        }
        .plugin-card__name {
          font-weight: 600;
          font-size: 15px;
        }
        .plugin-card__version {
          font-size: 11px;
          color: var(--text-muted);
        }
        .plugin-card__desc {
          font-size: 13px;
          color: var(--text-secondary);
          margin-bottom: 12px;
          line-height: 1.4;
        }
        .plugin-card__meta {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding-top: 12px;
          border-top: 1px solid var(--border);
        }
        .plugin-card__author {
          font-size: 11px;
          color: var(--text-muted);
        }
        .plugin-toggle {
          position: relative;
          width: 40px;
          height: 22px;
          background: var(--muted);
          border-radius: 11px;
          cursor: pointer;
          transition: background 0.2s;
        }
        .plugin-toggle.enabled {
          background: var(--success);
        }
        .plugin-toggle::after {
          content: '';
          position: absolute;
          top: 2px;
          left: 2px;
          width: 18px;
          height: 18px;
          background: white;
          border-radius: 50%;
          transition: transform 0.2s;
        }
        .plugin-toggle.enabled::after {
          transform: translateX(18px);
        }
        .plugin-card__settings {
          margin-top: 12px;
          padding-top: 12px;
          border-top: 1px solid var(--border);
        }
        .plugin-setting {
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 8px 0;
        }
        .plugin-setting__label {
          font-size: 13px;
        }
        .plugin-setting select {
          padding: 4px 8px;
          border: 1px solid var(--border);
          border-radius: 4px;
          background: var(--background);
          font-size: 12px;
        }
      </style>
    `;
  }

  renderPluginCard(plugin) {
    const settings = pluginService.getPluginSettings(plugin.id);

    return `
      <div class="plugin-card ${plugin.enabled ? 'enabled' : ''}" data-plugin-id="${plugin.id}">
        <div class="plugin-card__header">
          <div class="plugin-card__icon">${plugin.icon}</div>
          <div class="plugin-card__title">
            <div class="plugin-card__name">${plugin.name}</div>
            <div class="plugin-card__version">v${plugin.version}</div>
          </div>
          <div class="plugin-toggle ${plugin.enabled ? 'enabled' : ''}"
               data-action="togglePlugin"
               data-plugin="${plugin.id}"
               title="${plugin.enabled ? 'Disable' : 'Enable'} plugin">
          </div>
        </div>
        <div class="plugin-card__desc">${plugin.description}</div>
        ${plugin.enabled && plugin.settings.length > 0 ? `
          <div class="plugin-card__settings">
            ${plugin.settings.map(setting => this.renderPluginSetting(plugin.id, setting, settings)).join('')}
          </div>
        ` : ''}
        <div class="plugin-card__meta">
          <span class="plugin-card__author">by ${plugin.author}</span>
          <ds-badge data-variant="${plugin.enabled ? 'success' : 'secondary'}" data-size="sm">
            ${plugin.enabled ? 'Enabled' : 'Disabled'}
          </ds-badge>
        </div>
      </div>
    `;
  }

  renderPluginSetting(pluginId, setting, currentSettings) {
    const value = currentSettings[setting.key] ?? setting.default;

    if (setting.type === 'select') {
      return `
        <div class="plugin-setting">
          <span class="plugin-setting__label">${setting.label}</span>
          <select data-action="setPluginSetting" data-plugin="${pluginId}" data-key="${setting.key}">
            ${setting.options.map(opt => `
              <option value="${opt.value}" ${value === opt.value ? 'selected' : ''}>${opt.label}</option>
            `).join('')}
          </select>
        </div>
      `;
    }

    if (setting.type === 'boolean') {
      return `
        <div class="plugin-setting">
          <span class="plugin-setting__label">${setting.label}</span>
          <div class="plugin-toggle ${value ? 'enabled' : ''}"
               data-action="setPluginSetting"
               data-plugin="${pluginId}"
               data-key="${setting.key}"
               data-type="boolean">
          </div>
        </div>
      `;
    }

    return '';
  }

  renderDocs() {
    return `
      <div class="page-header">
        <h1>Documentation</h1>
        <p class="text-muted">DSS usage guides for all teams</p>
      </div>

      <div class="docs-layout mt-6">
        <nav class="docs-nav">
          <div class="docs-nav__section">
            <div class="docs-nav__title">Getting Started</div>
            <a class="docs-nav__link active" data-doc="overview">Overview</a>
            <a class="docs-nav__link" data-doc="quickstart">Quick Start</a>
            <a class="docs-nav__link" data-doc="concepts">Key Concepts</a>
          </div>
          <div class="docs-nav__section">
            <div class="docs-nav__title">Team Guides</div>
            <a class="docs-nav__link" data-doc="ui-team">UI Team</a>
            <a class="docs-nav__link" data-doc="ux-team">UX Team</a>
            <a class="docs-nav__link" data-doc="qa-team">QA Team</a>
          </div>
          <div class="docs-nav__section">
            <div class="docs-nav__title">Features</div>
            <a class="docs-nav__link" data-doc="tokens">Design Tokens</a>
            <a class="docs-nav__link" data-doc="figma">Figma Integration</a>
            <a class="docs-nav__link" data-doc="components">Components</a>
            <a class="docs-nav__link" data-doc="ai-chat">AI Chat</a>
          </div>
          <div class="docs-nav__section">
            <div class="docs-nav__title">Reference</div>
            <a class="docs-nav__link" href="/api/docs" target="_blank">API Docs ↗</a>
            <a class="docs-nav__link" data-doc="cli">CLI Commands</a>
            <a class="docs-nav__link" data-doc="troubleshooting">Troubleshooting</a>
          </div>
        </nav>

        <div class="docs-content" id="docs-content">
          ${this.getDocContent('overview')}
        </div>
      </div>
    `;
  }

  getDocContent(docId) {
    const docs = {
      overview: `
        <h2>What is DSS?</h2>
        <p>Design System Server (DSS) is a platform that helps teams manage, sync, and evolve their design systems by connecting Figma designs to code.</p>

        <h3>Core Features</h3>
        <ul>
          <li><strong>Token Extraction</strong> — Pull design tokens from Figma variables</li>
          <li><strong>Token Sync</strong> — Generate CSS/JSON from Figma tokens</li>
          <li><strong>Component Analysis</strong> — Scan your codebase for components</li>
          <li><strong>Visual Diff</strong> — Detect changes between Figma versions</li>
          <li><strong>AI Assistant</strong> — Get help via the built-in chat</li>
        </ul>

        <h3>Architecture</h3>
        <ul>
          <li><strong>REST API</strong> — Port 3456 (python tools/api/server.py)</li>
          <li><strong>MCP Server</strong> — Port 3457 for AI tools</li>
          <li><strong>Admin UI</strong> — This dashboard</li>
          <li><strong>CLI</strong> — Command-line interface</li>
        </ul>
      `,

      quickstart: `
        <h2>Quick Start</h2>

        <h3>1. Start the Server</h3>
        <pre><code>cd apps/dss
python tools/api/server.py</code></pre>

        <h3>2. Create a Project</h3>
        <p>Go to <a href="#projects">Projects</a> → Create Project</p>

        <h3>3. Add Figma File</h3>
        <p>In your project settings, paste your Figma file key:</p>
        <pre><code>https://www.figma.com/file/<strong>FILE_KEY</strong>/...</code></pre>

        <h3>4. Extract Tokens</h3>
        <p>Use the dashboard or CLI:</p>
        <pre><code>dss ingest figma YOUR_FILE_KEY</code></pre>

        <h3>5. Sync to Code</h3>
        <p>Click "Sync Tokens" or:</p>
        <pre><code>dss sync tokens --output ./tokens.css</code></pre>
      `,

      concepts: `
        <h2>Key Concepts</h2>

        <h3>Design Tokens</h3>
        <p>Tokens are the atomic values of your design system: colors, spacing, typography. DSS extracts these from Figma variables and converts them to CSS custom properties or JSON.</p>

        <h3>Translation Dictionaries</h3>
        <p>DSS uses a canonical internal structure. When importing from external sources, translation dictionaries map external names to DSS standard names.</p>

        <h3>Token Drift</h3>
        <p>When code diverges from Figma designs, that's "drift". The UI Team dashboard tracks drift issues and helps resolve them.</p>

        <h3>ESRE (Expected State, Real State, Evidence)</h3>
        <p>QA team uses ESRE to define test cases: what should happen, what actually happens, and proof.</p>
      `,

      'ui-team': `
        <h2>UI Team Guide</h2>
        <p>As a UI developer, you'll use DSS to keep code in sync with designs.</p>

        <h3>Daily Workflow</h3>
        <ol>
          <li>Check the <a href="#dashboard">Dashboard</a> for token drift alerts</li>
          <li>Run token sync when Figma updates</li>
          <li>Generate component code from new Figma components</li>
          <li>Review and resolve drift issues</li>
        </ol>

        <h3>Key Tools</h3>
        <ul>
          <li><strong>Extract Tokens</strong> — Pull latest from Figma</li>
          <li><strong>Sync Tokens</strong> — Update CSS variables</li>
          <li><strong>Generate Code</strong> — Create React/Web Components</li>
          <li><strong>Token Drift</strong> — Track code/design mismatches</li>
        </ul>

        <h3>CLI Commands</h3>
        <pre><code>dss ingest figma FILE_KEY
dss sync tokens -o ./tokens.css
dss analyze ./src</code></pre>
      `,

      'ux-team': `
        <h2>UX Team Guide</h2>
        <p>As a UX designer, DSS helps you maintain design consistency and validate implementations.</p>

        <h3>Daily Workflow</h3>
        <ol>
          <li>Add Figma files to projects</li>
          <li>Run visual diff after design changes</li>
          <li>Review token consistency reports</li>
          <li>Validate component implementations</li>
        </ol>

        <h3>Key Tools</h3>
        <ul>
          <li><strong>Figma Files</strong> — Manage connected design files</li>
          <li><strong>Visual Diff</strong> — Compare Figma versions</li>
          <li><strong>Token Validation</strong> — Ensure token consistency</li>
          <li><strong>Component Validation</strong> — Check naming conventions</li>
        </ul>

        <h3>Best Practices</h3>
        <ul>
          <li>Use Figma variables for all tokens</li>
          <li>Follow component naming conventions</li>
          <li>Document component variants</li>
          <li>Run visual diff before handoff</li>
        </ul>
      `,

      'qa-team': `
        <h2>QA Team Guide</h2>
        <p>DSS helps QA teams validate design system implementations.</p>

        <h3>Daily Workflow</h3>
        <ol>
          <li>Review visual regression reports</li>
          <li>Define ESRE test cases for components</li>
          <li>Run component validation</li>
          <li>Export audit logs for compliance</li>
        </ol>

        <h3>ESRE Testing</h3>
        <p>Define expected behaviors:</p>
        <ul>
          <li><strong>Expected State</strong> — What should happen</li>
          <li><strong>Real State</strong> — What actually happens</li>
          <li><strong>Evidence</strong> — Screenshots, logs, recordings</li>
        </ul>

        <h3>Key Tools</h3>
        <ul>
          <li><strong>Component Validation</strong> — Automated checks</li>
          <li><strong>Visual Diff</strong> — Regression detection</li>
          <li><strong>Audit Log</strong> — Track all changes</li>
          <li><strong>ESRE Definitions</strong> — Test case management</li>
        </ul>
      `,

      tokens: `
        <h2>Design Tokens</h2>

        <h3>Token Categories</h3>
        <ul>
          <li><strong>Colors</strong> — Primary, secondary, semantic colors</li>
          <li><strong>Spacing</strong> — Margin, padding scales</li>
          <li><strong>Typography</strong> — Font sizes, weights, line heights</li>
          <li><strong>Radius</strong> — Border radius values</li>
          <li><strong>Shadows</strong> — Box shadow definitions</li>
        </ul>

        <h3>Export Formats</h3>
        <ul>
          <li><strong>CSS</strong> — Custom properties (:root { --color-primary: ... })</li>
          <li><strong>JSON</strong> — Structured token data</li>
          <li><strong>SCSS</strong> — Sass variables</li>
        </ul>

        <h3>Token Naming</h3>
        <pre><code>--{category}-{name}[-{variant}]

Examples:
--color-primary
--space-4
--text-lg
--radius-md</code></pre>
      `,

      figma: `
        <h2>Figma Integration</h2>

        <h3>Setup</h3>
        <ol>
          <li>Get a Personal Access Token from <a href="https://www.figma.com/developers/api#access-tokens" target="_blank">Figma Settings</a></li>
          <li>Go to <a href="#settings">Settings</a> → Figma Integration</li>
          <li>Paste and save your token</li>
          <li>Test the connection</li>
        </ol>

        <h3>File Key</h3>
        <p>Extract from your Figma URL:</p>
        <pre><code>https://www.figma.com/file/<strong>ABC123</strong>/My-Design
                              ↑ This is your file key</code></pre>

        <h3>What Gets Extracted</h3>
        <ul>
          <li><strong>Variables</strong> → Design tokens</li>
          <li><strong>Components</strong> → Component metadata</li>
          <li><strong>Styles</strong> → Text and color styles</li>
        </ul>
      `,

      components: `
        <h2>Components</h2>

        <h3>Component Analysis</h3>
        <p>DSS scans your codebase to find React and Web Components:</p>
        <pre><code>dss analyze ./src</code></pre>

        <h3>Code Generation</h3>
        <p>Generate component code from Figma:</p>
        <ul>
          <li><strong>React</strong> — Functional components with CSS modules</li>
          <li><strong>Web Components</strong> — Custom elements with Shadow DOM</li>
        </ul>

        <h3>Storybook Integration</h3>
        <p>Generate stories for your components:</p>
        <pre><code>dss storybook generate ./src/components</code></pre>
      `,

      'ai-chat': `
        <h2>AI Chat</h2>
        <p>The AI assistant helps with design system tasks.</p>

        <h3>What It Can Do</h3>
        <ul>
          <li>Answer questions about your design system</li>
          <li>Suggest improvements</li>
          <li>Help debug issues</li>
          <li>Execute DSS tools</li>
        </ul>

        <h3>Example Prompts</h3>
        <ul>
          <li>"Extract tokens from my Figma file"</li>
          <li>"Show me quick wins for my codebase"</li>
          <li>"What's the status of my project?"</li>
          <li>"Help me fix token drift issues"</li>
        </ul>

        <h3>Tool Execution</h3>
        <p>The AI can run DSS tools directly. Look for tool suggestions in responses and click to execute.</p>
      `,

      cli: `
        <h2>CLI Commands</h2>

        <h3>Installation</h3>
        <pre><code># Add to PATH
export PATH="$PATH:/path/to/dss/bin"

# Or use directly
./bin/dss --help</code></pre>

        <h3>Commands</h3>
        <pre><code><strong>dss init</strong>
  Initialize DSS in current directory

<strong>dss ingest figma FILE_KEY</strong>
  Extract tokens from Figma file

<strong>dss sync tokens -o PATH</strong>
  Sync tokens to CSS file

<strong>dss analyze PATH</strong>
  Analyze codebase for components

<strong>dss storybook generate PATH</strong>
  Generate Storybook stories

<strong>dss start</strong>
  Start DSS server</code></pre>
      `,

      troubleshooting: `
        <h2>Troubleshooting</h2>

        <h3>Server Won't Start</h3>
        <pre><code># Check Python version (need 3.10+)
python --version

# Install dependencies
pip install -r requirements.txt

# Check port availability
lsof -i :3456</code></pre>

        <h3>Figma Connection Failed</h3>
        <ul>
          <li>Verify token hasn't expired</li>
          <li>Check token has read access to the file</li>
          <li>Ensure file key is correct (not the full URL)</li>
        </ul>

        <h3>Tokens Not Syncing</h3>
        <ul>
          <li>Confirm Figma file has variables defined</li>
          <li>Check output path is writable</li>
          <li>Look for errors in browser console</li>
        </ul>

        <h3>API Errors</h3>
        <ul>
          <li>Check server is running: <code>curl http://localhost:3456/health</code></li>
          <li>Review server logs for details</li>
          <li>Verify CORS settings for remote access</li>
        </ul>

        <h3>Getting Help</h3>
        <ul>
          <li>Use the AI Chat for guidance</li>
          <li>Check logs: Settings → Debug Console</li>
          <li>Export logs for support</li>
        </ul>
      `
    };

    return docs[docId] || docs.overview;
  }

  renderServiceCard(serviceId, serviceName, services) {
    const discovered = services.discovered?.[serviceId] || {};
    const configured = services.configured?.[serviceId] || {};
    const running = discovered.running || false;

    return `
      <div class="p-4 rounded" style="background: var(--muted)">
        <div class="flex items-center justify-between mb-2">
          <h4 class="font-medium">${serviceName}</h4>
          <span class="status-dot ${running ? 'status-dot--success' : ''}"></span>
        </div>
        <p class="text-sm text-muted mb-2">
          ${running ? `Running on :${discovered.port}` : 'Not detected'}
        </p>
        ${running ? `
          <ds-button data-variant="ghost" data-size="sm" onclick="window.open('${discovered.url}', '_blank')">
            Open
          </ds-button>
        ` : ''}
      </div>
    `;
  }

  /**
   * Render component settings from the registry
   * Generates dynamic UI for all enabled components
   */
  renderComponentSettings() {
    let dssHost = 'localhost';
    try {
      dssHost = getDssHost();
    } catch {
      // Config not loaded yet
    }

    const components = getEnabledComponents();

    return components.map(component => `
      <div class="p-4 rounded border" style="background: var(--muted); border-color: var(--border)">
        <div class="flex items-center justify-between mb-3">
          <div class="flex items-center gap-2">
            <span class="font-medium">${component.name}</span>
            <ds-badge data-variant="secondary" data-size="sm">${component.category}</ds-badge>
          </div>
          ${component.getUrl() ? `
            <ds-button data-variant="ghost" data-size="sm" onclick="window.open('${component.getUrl()}', '_blank')">
              Open
            </ds-button>
          ` : ''}
        </div>
        <p class="text-sm text-muted mb-3">${component.description}</p>
        ${component.id === 'storybook' ? `
          <div class="text-xs text-muted mb-3">
            URL: <code>${component.getUrl() || 'Not configured'}</code>
            <br>Host from server config: <code>${dssHost}</code>
          </div>
          <div class="flex gap-2">
            <ds-button data-variant="primary" data-size="sm" data-action="initStorybook">
              Initialize Storybook
            </ds-button>
            <ds-button data-variant="outline" data-size="sm" data-action="clearStorybook">
              Clear Stories
            </ds-button>
          </div>
        ` : ''}
        ${component.id === 'figma' ? `
          <div class="text-xs text-muted">
            Token status: Check connection above
          </div>
        ` : ''}
      </div>
    `).join('');
  }

  renderFeatureToggle(featureId, name, description, features = {}) {
    const enabled = features?.[featureId] !== false;
    return `
      <div class="flex items-center justify-between p-3 rounded" style="background: var(--muted)">
        <div>
          <div class="font-medium">${name}</div>
          <div class="text-sm text-muted">${description}</div>
        </div>
        <ds-button
          data-variant="${enabled ? 'primary' : 'outline'}"
          data-size="sm"
          data-action="toggleFeature"
          data-feature="${featureId}"
        >
          ${enabled ? 'Enabled' : 'Disabled'}
        </ds-button>
      </div>
    `;
  }

  /**
   * Render ingestion result panel (after parsing a prompt)
   */
  renderIngestionResult() {
    const result = this.store.get('ingestionResult');
    const browsing = this.store.get('browsingDesignSystems');
    const systems = this.store.get('designSystems') || [];

    // If browsing design systems
    if (browsing) {
      return `
        <div class="mt-4 p-4 rounded border" style="background: var(--muted); border-color: var(--border)">
          <div class="flex items-center justify-between mb-3">
            <h4 class="font-medium">Available Design Systems</h4>
            <ds-button data-variant="ghost" data-size="sm" data-action="closeBrowse">Close</ds-button>
          </div>
          <div class="grid grid-cols-3 gap-3" style="max-height: 300px; overflow-y: auto;">
            ${systems.map(sys => `
              <div class="p-3 rounded border cursor-pointer hover:border-primary"
                   style="background: var(--background); border-color: var(--border)"
                   data-action="selectDesignSystem" data-system-id="${sys.id}">
                <div class="font-medium text-sm">${sys.name}</div>
                <div class="text-xs text-muted mt-1">${sys.description?.slice(0, 60) || ''}...</div>
                <div class="flex gap-1 mt-2">
                  <ds-badge data-variant="secondary" data-size="sm">${sys.category || 'library'}</ds-badge>
                  ${sys.framework ? `<ds-badge data-variant="outline" data-size="sm">${sys.framework}</ds-badge>` : ''}
                </div>
              </div>
            `).join('')}
          </div>
        </div>
      `;
    }

    if (!result) return '';

    const { intent, sources, next_steps, suggestions } = result;

    // Found a design system to ingest
    if (sources?.length > 0 && sources[0].matched_system) {
      const system = sources[0].matched_system;
      return `
        <div class="mt-4 p-4 rounded border" style="background: var(--muted); border-color: var(--border)">
          <div class="flex items-center justify-between mb-3">
            <div>
              <h4 class="font-medium">${system.name}</h4>
              <p class="text-sm text-muted">${system.description}</p>
            </div>
            <ds-badge data-variant="primary">${system.category || 'library'}</ds-badge>
          </div>

          <div class="grid grid-cols-2 gap-4 mb-4">
            <div>
              <div class="text-xs text-muted mb-1">npm packages</div>
              <code class="text-sm">${(system.npm_packages || []).join(', ') || 'N/A'}</code>
            </div>
            <div>
              <div class="text-xs text-muted mb-1">Primary method</div>
              <span class="text-sm">${system.primary_ingestion || 'npm'}</span>
            </div>
          </div>

          ${system.figma_community_url ? `
            <div class="text-xs mb-3">
              <a href="${system.figma_community_url}" target="_blank" class="text-primary">View Figma Community Kit</a>
            </div>
          ` : ''}

          <div class="flex gap-2">
            <ds-button data-variant="primary" data-size="sm" data-action="confirmIngestion" data-system-id="${system.id}">
              Ingest ${system.name}
            </ds-button>
            <ds-button data-variant="outline" data-size="sm" data-action="showAlternatives" data-system-id="${system.id}">
              Other Methods
            </ds-button>
            <ds-button data-variant="ghost" data-size="sm" data-action="clearIngestion">
              Cancel
            </ds-button>
          </div>
        </div>
      `;
    }

    // Show next steps or suggestions
    if (next_steps?.length > 0) {
      const step = next_steps[0];
      if (step.action === 'request_source') {
        return `
          <div class="mt-4 p-4 rounded border" style="background: var(--muted); border-color: var(--border)">
            <h4 class="font-medium mb-2">${step.message}</h4>
            <div class="grid grid-cols-2 gap-3">
              ${(step.alternatives || []).map(alt => `
                <div class="p-3 rounded border cursor-pointer hover:border-primary"
                     style="background: var(--background); border-color: var(--border)"
                     data-action="selectIngestionMethod" data-method="${alt.requires}">
                  <div class="font-medium text-sm">${alt.name}</div>
                  <div class="text-xs text-muted mt-1">${alt.description}</div>
                </div>
              `).join('')}
            </div>
            <ds-button data-variant="ghost" data-size="sm" class="mt-3" data-action="clearIngestion">
              Cancel
            </ds-button>
          </div>
        `;
      }

      if (step.action === 'search_npm') {
        return `
          <div class="mt-4 p-4 rounded border" style="background: var(--muted); border-color: var(--border)">
            <div class="flex items-center gap-2 mb-2">
              <span class="status-dot status-dot--warning"></span>
              <span class="font-medium">Not found in registry</span>
            </div>
            <p class="text-sm text-muted mb-3">${step.message}</p>
            <ds-button data-variant="primary" data-size="sm" data-action="searchNpm" data-query="${step.query || step.package}">
              Search npm
            </ds-button>
            <ds-button data-variant="ghost" data-size="sm" data-action="clearIngestion">
              Cancel
            </ds-button>
          </div>
        `;
      }
    }

    // Show suggestions
    if (suggestions?.length > 0) {
      return `
        <div class="mt-4 p-3 rounded" style="background: var(--muted)">
          <ul class="text-sm text-muted">
            ${suggestions.map(s => `<li class="mb-1">${s}</li>`).join('')}
          </ul>
        </div>
      `;
    }

    return '';
  }

  // === Event Handlers ===

  attachEventHandlers() {
    // Use event delegation for all [data-action] buttons
    // Only attach the listener once to prevent accumulation
    if (!this.listeners.hasActionListener) {
      document.addEventListener('click', (e) => {
        const btn = e.target.closest('[data-action]');
        if (!btn) return;

        e.preventDefault();
        e.stopPropagation();

        const action = btn.dataset.action;
        const component = btn.dataset.component;

        switch (action) {
          case 'extractTokens': this.extractTokens(); break;
          case 'extractComponents': this.extractComponents(); break;
          case 'syncTokens': this.syncTokens(); break;
          case 'runVisualDiff': this.runVisualDiff(); break;
          case 'validateComponents': this.validateComponents(); break;
          case 'runDiscovery': this.runDiscovery(true); break;
          case 'generateCode':
            if (component) this.generateCode(component);
            break;
          case 'saveFigmaKey':
            const input = document.getElementById('figma-file-key');
            if (input) {
              this.store.set({ figmaFileKey: input.value });
              this.store.notify('Figma connection saved', 'success');
            }
            break;
          case 'saveProjectDescription':
            const descInput = document.getElementById('project-description');
            const selectedProject = this.store.get('selectedProject');
            if (descInput && selectedProject) {
              this.updateProjectDescription(selectedProject.id, descInput.value);
            }
            break;
          // Settings actions
          case 'saveFigmaToken':
            this.saveFigmaToken();
            break;
          case 'testFigmaConnection':
            this.testFigmaConnection();
            break;
          case 'saveDssHost':
            this.saveDssHost();
            break;
          case 'setMode':
            const mode = btn.dataset.mode;
            if (mode) this.setServerMode(mode);
            break;
          case 'toggleFeature':
            const feature = btn.dataset.feature;
            if (feature) this.toggleFeature(feature);
            break;
          case 'refreshServices':
            this.loadServices();
            break;
          case 'initStorybook':
            this.initStorybook();
            break;
          case 'clearStorybook':
            this.clearStorybook();
            break;
          case 'resetDSS':
            this.resetDSS();
            break;
          // Ingestion actions
          case 'parseIngestion':
            this.parseIngestionPrompt();
            break;
          case 'browseDesignSystems':
            this.browseDesignSystems();
            break;
          case 'closeBrowse':
            this.store.set({ browsingDesignSystems: false });
            this.render();
            break;
          case 'selectDesignSystem':
            const systemId = btn.dataset.systemId;
            if (systemId) this.selectDesignSystem(systemId);
            break;
          case 'confirmIngestion':
            const confirmSystemId = btn.dataset.systemId;
            if (confirmSystemId) this.confirmIngestion(confirmSystemId);
            break;
          case 'showAlternatives':
            const altSystemId = btn.dataset.systemId;
            if (altSystemId) this.showIngestionAlternatives(altSystemId);
            break;
          case 'clearIngestion':
            this.store.set({ ingestionResult: null, browsingDesignSystems: false });
            this.render();
            break;
          case 'navigate-quick-wins':
            window.location.hash = 'quick-wins';
            break;
          case 'searchNpm':
            const npmQuery = btn.dataset.query;
            if (npmQuery) this.searchNpmPackages(npmQuery);
            break;
          case 'selectIngestionMethod':
            const methodType = btn.dataset.method;
            if (methodType) this.selectIngestionMethod(methodType);
            break;
          // Project actions
          case 'toggleCreateProject':
            this.store.set({ showCreateProjectForm: !this.store.get('showCreateProjectForm') });
            this.render();
            break;
          case 'submitCreateProject':
            const nameInput = document.getElementById('new-project-name');
            if (nameInput && nameInput.value) {
              this.createProject(
                nameInput.value,
                '', // description
                ''  // figma key
              );
            } else {
              this.store.notify('Please enter a project name', 'warning');
            }
            break;
          case 'selectProject':
            const selectProjectId = btn.dataset.projectId;
            if (selectProjectId) this.selectProject(selectProjectId);
            break;
          case 'syncProject':
            const syncProjectId = btn.dataset.projectId;
            const syncFigmaKey = btn.dataset.figmaKey;
            if (syncProjectId) this.syncProjectTokens(syncProjectId, syncFigmaKey);
            break;
          case 'deleteProject':
            const deleteProjectId = btn.dataset.projectId;
            if (deleteProjectId) this.deleteProject(deleteProjectId);
            break;
          // Token export format
          case 'setExportFormat':
            const format = btn.dataset.format;
            if (format) {
              this.store.set({ tokenExportFormat: format });
              this.render();
            }
            break;
          // Component actions
          case 'viewComponentCode':
            const compName = btn.dataset.component;
            const compFramework = btn.dataset.framework || 'react';
            if (compName) this.showComponentCode(compName, compFramework);
            break;
          case 'setFramework':
            const fw = btn.dataset.framework;
            if (fw) {
              this.store.set({ componentFramework: fw });
              this.render();
            }
            break;
          case 'closeGeneratedCode':
            this.store.set({ generatedCode: null });
            this.render();
            break;
          case 'copyCode':
            const code = this.store.get('generatedCode')?.code;
            if (code) {
              navigator.clipboard.writeText(code);
              this.store.notify('Code copied to clipboard', 'success');
            }
            break;
          // New services and quick wins actions
          case 'executeTool':
            const toolName = btn.dataset.tool;
            if (toolName) this.executeToolWithParams(toolName);
            break;
          case 'loadQuickWins':
            this.loadQuickWins();
            break;
          case 'investigateWin':
            const winId = btn.dataset.winId;
            if (winId) this.investigateWin(winId);
            break;
          case 'markDone':
            const doneWinId = btn.dataset.winId;
            if (doneWinId) this.markWinDone(doneWinId);
            break;
          // Chat actions
          case 'sendChatMessage':
            this.sendChatMessage({ target: btn });
            break;
          case 'clearChat':
            claudeService.clearHistory();
            this.render();
            break;
          case 'exportChat':
            claudeService.exportConversation();
            break;
          // Team Dashboard actions
          case 'sync-figma-file':
            const fileId = btn.dataset.fileId;
            if (fileId) this.syncFigmaFile(fileId);
            break;
          case 'delete-figma-file':
            const deleteFileId = btn.dataset.fileId;
            if (deleteFileId && confirm('Delete this Figma file?')) {
              this.deleteFigmaFile(deleteFileId);
            }
            break;
          // Plugin actions
          case 'togglePlugin':
            const pluginId = btn.dataset.plugin;
            if (pluginId) this.togglePlugin(pluginId);
            break;
          case 'setPluginSetting':
            const settingPluginId = btn.dataset.plugin;
            const settingKey = btn.dataset.key;
            const settingType = btn.dataset.type;
            if (settingPluginId && settingKey) {
              let settingValue;
              if (settingType === 'boolean') {
                const current = pluginService.getPluginSettings(settingPluginId)[settingKey];
                settingValue = !current;
              } else if (btn.tagName === 'SELECT') {
                settingValue = btn.value;
              }
              this.setPluginSetting(settingPluginId, settingKey, settingValue);
            }
            break;
          // Theme actions
          case 'toggle-theme':
            themeManager.toggle();
            this.render();
            break;
          // Audit actions
          case 'load-audit':
            this.loadAuditLog();
            break;
          case 'clear-audit-filters':
            this.clearAuditFilters();
            break;
          case 'export-audit':
            const exportFormat = btn.dataset.format || 'json';
            this.exportAuditLog(exportFormat);
            break;
          case 'prev-audit-page':
            this.prevAuditPage();
            break;
          case 'next-audit-page':
            this.nextAuditPage();
            break;
          case 'show-audit-details':
            const auditId = btn.dataset.auditId;
            if (auditId) this.showAuditDetails(parseInt(auditId));
            break;
        }
      });

      this.listeners.hasActionListener = true;
    }

    // Chat form submission
    const chatForm = document.getElementById('chatForm');
    if (chatForm) {
      chatForm.addEventListener('submit', (e) => {
        e.preventDefault();
        this.sendChatMessage(e);
      });
    }

    // Team Dashboard form submissions
    const addFigmaFileForm = document.getElementById('add-figma-file-form');
    if (addFigmaFileForm) {
      addFigmaFileForm.addEventListener('submit', (e) => {
        e.preventDefault();
        const formData = new FormData(e.target);
        this.addFigmaFile({
          file_name: formData.get('file_name'),
          figma_url: formData.get('figma_url'),
          file_key: formData.get('file_key')
        });
      });
    }

    const addESREForm = document.getElementById('add-esre-form');
    if (addESREForm) {
      addESREForm.addEventListener('submit', (e) => {
        e.preventDefault();
        const formData = new FormData(e.target);
        this.addESREDefinition({
          name: formData.get('name'),
          definition_text: formData.get('definition_text'),
          component_name: formData.get('component_name') || null,
          expected_value: formData.get('expected_value') || null
        });
      });
    }

    // Search and filter handlers for services page
    const toolSearch = document.getElementById('toolSearch');
    if (toolSearch) {
      toolSearch.addEventListener('input', (e) => {
        this.filterTools(e.target.value, document.getElementById('categoryFilter')?.value || '');
      });
    }

    const categoryFilter = document.getElementById('categoryFilter');
    if (categoryFilter) {
      categoryFilter.addEventListener('change', (e) => {
        this.filterTools(document.getElementById('toolSearch')?.value || '', e.target.value);
      });
    }

    // Docs navigation
    document.querySelectorAll('.docs-nav__link[data-doc]').forEach(link => {
      link.addEventListener('click', (e) => {
        e.preventDefault();
        const docId = e.currentTarget.dataset.doc;
        const content = document.getElementById('docs-content');
        if (content && docId) {
          setSafeHtml(content, this.getDocContent(docId));
          document.querySelectorAll('.docs-nav__link').forEach(l => l.classList.remove('active'));
          e.currentTarget.classList.add('active');
        }
      });
    });

    // Setup keyboard shortcuts
    this.setupKeyboardHandlers();
  }

  setupKeyboardHandlers() {
    // Handle global keyboard shortcuts
    if (!this.listeners.hasKeyboardListener) {
      this.listeners.keyboardHandler = (e) => {
        // Escape key: Close sidebars and modals
        if (e.key === 'Escape') {
          // Close AI sidebar if visible
          const aiSidebar = document.getElementById('ai-sidebar');
          const toggleBtn = document.getElementById('sidebar-toggle');
          if (aiSidebar && !aiSidebar.classList.contains('hidden')) {
            if (toggleBtn) {
              toggleBtn.click();
              // Update ARIA state
              setTimeout(() => {
                const isExpanded = !aiSidebar.classList.contains('hidden');
                toggleBtn.setAttribute('aria-expanded', isExpanded);
              }, 0);
            }
          }

          // Close any open details/summary elements
          document.querySelectorAll('details[open]').forEach(details => {
            details.open = false;
          });
        }

        // Alt+N: Navigate to next page
        if (e.altKey && e.key === 'n') {
          e.preventDefault();
          const navItems = Array.from(document.querySelectorAll('.nav-item'));
          const currentPage = this.store.get('currentPage');
          const currentIndex = navItems.findIndex(item => item.dataset.page === currentPage);
          if (currentIndex >= 0 && currentIndex < navItems.length - 1) {
            navItems[currentIndex + 1].focus();
            navItems[currentIndex + 1].click();
          }
        }

        // Alt+P: Navigate to previous page
        if (e.altKey && e.key === 'p') {
          e.preventDefault();
          const navItems = Array.from(document.querySelectorAll('.nav-item'));
          const currentPage = this.store.get('currentPage');
          const currentIndex = navItems.findIndex(item => item.dataset.page === currentPage);
          if (currentIndex > 0) {
            navItems[currentIndex - 1].focus();
            navItems[currentIndex - 1].click();
          }
        }
      };

      document.addEventListener('keydown', this.listeners.keyboardHandler);
      this.listeners.hasKeyboardListener = true;
    }
  }

  // === Settings Actions ===

  async saveFigmaToken() {
    const input = document.getElementById('figma-token-input');
    if (!input || !input.value || input.value.includes('••••')) {
      this.store.notify('Please enter a valid Figma token', 'warning');
      return;
    }

    this.store.setLoading('saveFigmaToken', true);
    try {
      const api = (await import('./api.js')).default;
      await api.setFigmaToken(input.value);
      this.store.set({ figmaConfig: { configured: true } });
      this.store.notify('Figma token saved', 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to save token: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('saveFigmaToken', false);
    }
  }

  async testFigmaConnection() {
    this.store.setLoading('testFigma', true);
    try {
      const api = (await import('./api.js')).default;
      const result = await api.testFigmaConnection();
      this.store.set({ figmaTestResult: result });
      if (result.success) {
        this.store.notify('Figma connection successful!', 'success');
      } else {
        this.store.notify(`Connection failed: ${result.error}`, 'error');
      }
      this.render();
    } catch (error) {
      this.store.set({ figmaTestResult: { success: false, error: error.message } });
      this.store.notify(`Test failed: ${error.message}`, 'error');
      this.render();
    } finally {
      this.store.setLoading('testFigma', false);
    }
  }

  async saveDssHost() {
    const input = document.getElementById('dss-host-input');
    if (!input) {
      notifyError('DSS host input not found', ErrorCode.SYSTEM_UNEXPECTED);
      return;
    }

    const newHost = input.value.trim() || 'localhost';

    this.store.setLoading('saveDssHost', true);
    try {
      // Validate hostname format (alphanumeric, dots, hyphens)
      if (!/^[a-zA-Z0-9.-]+$/.test(newHost)) {
        notifyError('Invalid hostname format', ErrorCode.VALIDATION_INVALID_FORMAT, {
          host: newHost
        });
        this.store.setLoading('saveDssHost', false);
        return;
      }

      // Save to store (will auto-persist via subscription)
      this.store.set({ dssHost: newHost });

      // Update the link immediately
      this.updateStorybookLink();

      // Notify success
      notifySuccess('Host configuration saved successfully!', ErrorCode.SUCCESS_UPDATED, {
        host: newHost,
        storybookUrl: `${window.location.protocol}//${newHost}:6006`
      });

      this.render();
    } catch (error) {
      handleError(error, {
        operation: 'save DSS host',
        host: newHost
      });
    } finally {
      this.store.setLoading('saveDssHost', false);
    }
  }

  async resetDSS() {
    // Confirm with user
    const confirmed = window.confirm(
      '⚠️ WARNING: This will delete all user-created themes, projects, cached data, and databases.\n\n' +
      'The DSS structure and default themes will be preserved.\n\n' +
      'Type "RESET" in the next prompt to confirm.'
    );

    if (!confirmed) {
      return;
    }

    const confirmText = window.prompt('Type RESET (all caps) to confirm:');
    if (confirmText !== 'RESET') {
      this.store.notify('Reset cancelled', 'info');
      return;
    }

    this.store.setLoading('resetDSS', true);
    try {
      this.store.notify('Resetting DSS... This may take a moment.', 'info');

      // Call Python reset command via shell
      const response = await fetch('/api/system/reset', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ confirm: 'RESET' })
      });

      if (!response.ok) {
        throw new Error('Reset command failed');
      }

      const result = await response.json();

      this.store.notify('✅ DSS has been reset to fresh state!', 'success');

      // Reload after a short delay
      setTimeout(() => {
        window.location.reload();
      }, 2000);

    } catch (error) {
      this.store.notify(`Reset failed: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('resetDSS', false);
    }
  }

  async setServerMode(mode) {
    try {
      const api = (await import('./api.js')).default;
      await api.setMode(mode);
      const config = this.store.get('runtimeConfig') || {};
      config.mode = mode;
      this.store.set({ runtimeConfig: config });
      this.store.notify(`Server mode set to ${mode}`, 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to set mode: ${error.message}`, 'error');
    }
  }

  async toggleFeature(featureId) {
    const config = this.store.get('runtimeConfig') || {};
    const features = config.features || {};
    const newValue = features[featureId] === false;

    try {
      const api = (await import('./api.js')).default;
      await api.updateConfig({ features: { [featureId]: newValue } });
      features[featureId] = newValue;
      config.features = features;
      this.store.set({ runtimeConfig: config });
      this.store.notify(`${featureId} ${newValue ? 'enabled' : 'disabled'}`, 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to toggle feature: ${error.message}`, 'error');
    }
  }

  async togglePlugin(pluginId) {
    try {
      await pluginService.toggle(pluginId);
      const plugin = pluginService.get(pluginId);
      this.store.notify(`${plugin.name} ${plugin.enabled ? 'enabled' : 'disabled'}`, 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to toggle plugin: ${error.message}`, 'error');
    }
  }

  setPluginSetting(pluginId, key, value) {
    pluginService.setPluginSetting(pluginId, key, value);
    this.store.notify('Setting updated', 'success');
    this.render();
  }

  async loadServices() {
    try {
      const api = (await import('./api.js')).default;
      const services = await api.getServices();
      this.store.set({ services });
      this.render();
    } catch (error) {
      console.error('Failed to load services:', error);
    }
  }

  async initStorybook() {
    try {
      this.store.notify('Initializing Storybook...', 'info');
      const api = (await import('./api.js')).default;
      const result = await api.post('/storybook/init', {});
      if (result.success) {
        this.store.notify(result.message || 'Storybook initialized', 'success');
      } else {
        this.store.notify('Failed to initialize Storybook', 'error');
      }
    } catch (error) {
      console.error('Failed to initialize Storybook:', error);
      this.store.notify(`Failed to initialize Storybook: ${error.message}`, 'error');
    }
  }

  async clearStorybook() {
    try {
      this.store.notify('Clearing Storybook stories...', 'info');
      const api = (await import('./api.js')).default;
      const result = await api.delete('/storybook/stories');
      if (result.success) {
        this.store.notify(result.message || 'Stories cleared', 'success');
      } else {
        this.store.notify('Failed to clear stories', 'error');
      }
    } catch (error) {
      console.error('Failed to clear Storybook:', error);
      this.store.notify(`Failed to clear stories: ${error.message}`, 'error');
    }
  }

  // === Design System Ingestion ===

  async parseIngestionPrompt() {
    const input = document.getElementById('ingest-prompt');
    if (!input || !input.value.trim()) {
      this.store.notify('Please enter a design system name or prompt', 'warning');
      return;
    }

    try {
      this.store.setLoading('ingestion', true);
      this.store.notify('Parsing ingestion prompt...', 'info');

      const api = (await import('./api.js')).default;
      const result = await api.post('/ingest/parse', {
        prompt: input.value.trim(),
        project_id: this.store.get('currentProject')
      });

      this.store.set({ ingestionResult: result });
      this.render();

      // Show helpful message
      if (result.sources?.length > 0 && result.sources[0].matched_system) {
        this.store.notify(`Found: ${result.sources[0].matched_system.name}`, 'success');
      } else if (result.next_steps?.length > 0) {
        this.store.notify(result.next_steps[0].message || 'Processing...', 'info');
      }
    } catch (error) {
      console.error('Ingestion parse failed:', error);
      this.store.notify(`Failed to parse: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('ingestion', false);
    }
  }

  async browseDesignSystems() {
    try {
      this.store.notify('Loading design systems...', 'info');

      const api = (await import('./api.js')).default;
      const result = await api.get('/ingest/systems');

      this.store.set({
        designSystems: result.systems || [],
        browsingDesignSystems: true,
        ingestionResult: null
      });
      this.render();
    } catch (error) {
      console.error('Failed to load design systems:', error);
      this.store.notify(`Failed to load: ${error.message}`, 'error');
    }
  }

  async selectDesignSystem(systemId) {
    try {
      const api = (await import('./api.js')).default;
      const result = await api.get(`/ingest/systems/${systemId}`);

      this.store.set({
        ingestionResult: {
          sources: [{ matched_system: result.system }],
          alternatives: result.alternatives
        },
        browsingDesignSystems: false
      });
      this.render();
    } catch (error) {
      console.error('Failed to select design system:', error);
      this.store.notify(`Failed: ${error.message}`, 'error');
    }
  }

  async confirmIngestion(systemId) {
    try {
      this.store.setLoading('ingestion', true);
      this.store.notify('Starting ingestion...', 'info');

      const api = (await import('./api.js')).default;
      const result = await api.post('/ingest/confirm', {
        system_id: systemId,
        method: 'npm' // Default to npm
      });

      if (result.success) {
        this.store.notify(`Queued: ${result.message}`, 'success');

        // Show next steps
        if (result.next_steps?.length > 0) {
          setTimeout(() => {
            this.store.notify(`Next: ${result.next_steps.join(' → ')}`, 'info');
          }, 1500);
        }

        // Clear ingestion UI
        this.store.set({ ingestionResult: null });
        this.render();
      } else {
        this.store.notify('Ingestion failed', 'error');
      }
    } catch (error) {
      console.error('Ingestion failed:', error);
      this.store.notify(`Failed: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('ingestion', false);
    }
  }

  async showIngestionAlternatives(systemId) {
    try {
      const api = (await import('./api.js')).default;
      const result = await api.get(`/ingest/alternatives?system_id=${systemId}`);

      // Update the ingestion result to show alternatives
      const currentResult = this.store.get('ingestionResult') || {};
      this.store.set({
        ingestionResult: {
          ...currentResult,
          next_steps: [{
            action: 'request_source',
            message: 'Choose an ingestion method:',
            alternatives: result.alternatives || []
          }]
        }
      });
      this.render();
    } catch (error) {
      console.error('Failed to get alternatives:', error);
      this.store.notify(`Failed: ${error.message}`, 'error');
    }
  }

  async searchNpmPackages(query) {
    try {
      this.store.notify(`Searching npm for "${query}"...`, 'info');

      const api = (await import('./api.js')).default;
      const result = await api.get(`/ingest/npm/search?query=${encodeURIComponent(query)}`);

      if (result.packages?.length > 0) {
        // Show npm results as design systems to choose from
        this.store.set({
          designSystems: result.packages.map(pkg => ({
            id: pkg.name,
            name: pkg.name,
            description: pkg.description,
            npm_packages: [pkg.name],
            category: pkg.is_design_system ? 'npm-design-system' : 'npm-package',
            homepage: pkg.homepage
          })),
          browsingDesignSystems: true,
          ingestionResult: null
        });
        this.store.notify(`Found ${result.packages.length} packages`, 'success');
      } else {
        this.store.notify('No packages found on npm', 'warning');
      }
      this.render();
    } catch (error) {
      console.error('npm search failed:', error);
      this.store.notify(`Search failed: ${error.message}`, 'error');
    }
  }

  selectIngestionMethod(methodType) {
    // Show appropriate UI for the selected method
    const prompts = {
      figma_url: 'Enter Figma file URL:',
      css_url: 'Enter CSS file URL:',
      github_url: 'Enter GitHub repository URL:',
      image_url: 'Upload or enter image URL:',
      text_description: 'Describe your design tokens:'
    };

    const prompt = prompts[methodType] || 'Enter source:';
    const value = window.prompt(prompt);

    if (value) {
      // Store the method and source for later use
      this.store.set({
        ingestionMethod: methodType,
        ingestionSource: value
      });
      this.store.notify(`Source saved. Click "Ingest" to proceed.`, 'success');
    }
  }

  async loadConfig() {
    try {
      const api = (await import('./api.js')).default;
      const [configData, figmaConfig, services] = await Promise.all([
        api.getConfig(),
        api.getFigmaConfig(),
        api.getServices()
      ]);
      this.store.set({
        runtimeConfig: configData.config || {},
        figmaConfig: figmaConfig || {},
        services: services || {}
      });
    } catch (error) {
      console.error('Failed to load config:', error);
    }
  }

  // === Project Management ===

  async loadProjects() {
    try {
      const api = (await import('./api.js')).default;
      const projects = await api.getProjects();
      this.store.setProjects(Array.isArray(projects) ? projects : []);
      // Render project selector after projects are loaded
      this.renderProjectSelector();
    } catch (error) {
      console.error('Failed to load projects:', error);
      this.store.setProjects([]);
      this.renderProjectSelector();
    }
  }

  async loadDashboardData(projectId) {
    if (!projectId) return;

    try {
      logger.info('App', 'Loading dashboard data', { projectId });
      const dashboardData = await DashboardService.getDashboardSummary(projectId);
      this.store.set({ dashboardData });
      this.render(); // Re-render to show updated data
    } catch (error) {
      logger.error('App', 'Failed to load dashboard data', error);
      // Set empty dashboard data on error
      this.store.set({
        dashboardData: {
          ux: { figma_files_count: 0, figma_files: [] },
          ui: { token_drift: { total: 0, by_severity: {} }, code_metrics: {} },
          qa: { esre_count: 0, test_summary: {} }
        }
      });
    }
  }

  renderProjectSelector() {
    const container = document.getElementById('project-selector-container');
    if (!container) return;

    const projects = this.store.get('projects') || [];
    const currentProject = this.store.get('currentProject') || (projects.length > 0 ? projects[0].id : null);

    // Restore from localStorage if available
    const savedProject = localStorage.getItem('dss_current_project');
    if (savedProject && projects.find(p => p.id === savedProject)) {
      this.store.set({ currentProject: savedProject });
    } else if (currentProject) {
      this.store.set({ currentProject });
    }

    const html = `
      <div class="project-selector">
        <svg class="project-selector__icon" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
          <path d="M3 3h18v18H3z"/>
          <path d="M21 9H3"/>
          <path d="M9 21V9"/>
        </svg>
        <span class="project-selector__label">Project:</span>
        <select class="project-selector__select" id="project-select">
          ${projects.length === 0
            ? '<option value="">No projects</option>'
            : projects.map(p => `
              <option value="${escapeHtml(p.id)}" ${p.id === (currentProject || savedProject) ? 'selected' : ''}>
                ${escapeHtml(p.name)}
              </option>
            `).join('')}
        </select>
      </div>
    `;

    setSafeHtml(container, html);

    // Attach event listener
    const select = document.getElementById('project-select');
    if (select) {
      select.addEventListener('change', (e) => {
        const projectId = e.target.value;
        this.handleProjectChange(projectId);
      });
    }
  }

  handleProjectChange(projectId) {
    logger.info('App', 'Project context changed', { projectId });

    // Save to store and localStorage
    this.store.set({ currentProject: projectId });
    localStorage.setItem('dss_current_project', projectId);

    // Get project details
    const projects = this.store.get('projects') || [];
    const project = projects.find(p => p.id === projectId);

    // Trigger refresh
    this.render();

    logger.info('App', 'Project context set', { project: project?.name });
  }

  // === Audit Log ===

  renderAuditLog() {
    // Load audit log data after render
    setTimeout(() => this.loadAuditLog(), 100);

    return `
      <div class="page-header">
        <h1>Audit Log</h1>
        <p class="text-muted">History of all user actions and system events</p>
      </div>

      <!-- Filters -->
      <div class="mt-6">
        <ds-card>
          <ds-card-header>
            <ds-card-title>Filters</ds-card-title>
          </ds-card-header>
          <ds-card-content>
            <div class="grid grid-cols-4 gap-4">
              <div>
                <label class="text-sm font-medium">Category</label>
                <select id="audit-category-filter" class="w-full mt-2 p-2 rounded border">
                  <option value="">All Categories</option>
                  <option value="design_system">Design System</option>
                  <option value="code">Code</option>
                  <option value="configuration">Configuration</option>
                  <option value="project">Project</option>
                  <option value="team">Team</option>
                  <option value="storybook">Storybook</option>
                </select>
              </div>

              <div>
                <label class="text-sm font-medium">Severity</label>
                <select id="audit-severity-filter" class="w-full mt-2 p-2 rounded border">
                  <option value="">All Severities</option>
                  <option value="info">Info</option>
                  <option value="warning">Warning</option>
                  <option value="critical">Critical</option>
                </select>
              </div>

              <div>
                <label class="text-sm font-medium">Start Date</label>
                <input type="date" id="audit-start-date" class="w-full mt-2 p-2 rounded border">
              </div>

              <div>
                <label class="text-sm font-medium">End Date</label>
                <input type="date" id="audit-end-date" class="w-full mt-2 p-2 rounded border">
              </div>
            </div>

            <div class="flex gap-3 mt-4">
              <ds-button data-variant="primary" data-action="load-audit">
                Apply Filters
              </ds-button>
              <ds-button data-variant="outline" data-action="clear-audit-filters">
                Clear Filters
              </ds-button>
              <ds-button data-variant="outline" data-action="export-audit" data-format="json">
                📥 Export JSON
              </ds-button>
              <ds-button data-variant="outline" data-action="export-audit" data-format="csv">
                📥 Export CSV
              </ds-button>
            </div>
          </ds-card-content>
        </ds-card>
      </div>

      <!-- Audit Log Table -->
      <div class="mt-6">
        <ds-card>
          <ds-card-header>
            <ds-card-title>Activity History</ds-card-title>
            <ds-card-description>
              <span id="audit-total-count">Loading...</span>
            </ds-card-description>
          </ds-card-header>
          <ds-card-content>
            <div id="audit-log-content">
              <div class="text-center py-8 text-muted">
                Loading audit log...
              </div>
            </div>

            <!-- Pagination -->
            <div class="flex justify-between items-center mt-6" id="audit-pagination" style="display: none;">
              <div class="text-sm text-muted">
                Showing <span id="audit-showing"></span> of <span id="audit-total"></span> entries
              </div>
              <div class="flex gap-2">
                <ds-button data-variant="outline" data-size="sm" id="audit-prev-btn" data-action="prev-audit-page">
                  Previous
                </ds-button>
                <ds-button data-variant="outline" data-size="sm" id="audit-next-btn" data-action="next-audit-page">
                  Next
                </ds-button>
              </div>
            </div>
          </ds-card-content>
        </ds-card>
      </div>
    `;
  }

  async loadAuditLog() {
    const auditService = (await import('../services/audit-service.js')).default;
    const content = document.getElementById('audit-log-content');
    if (!content) return;

    // Get filter values
    const filters = {
      category: document.getElementById('audit-category-filter')?.value || '',
      severity: document.getElementById('audit-severity-filter')?.value || '',
      start_date: document.getElementById('audit-start-date')?.value || '',
      end_date: document.getElementById('audit-end-date')?.value || '',
      limit: 50,
      offset: this.auditLogOffset || 0
    };

    // Add current project filter if set
    const currentProject = this.store.get('currentProject');
    if (currentProject) {
      filters.project_id = currentProject;
    }

    try {
      const result = await auditService.getAuditLog(filters);

      // Update total count
      const totalCount = document.getElementById('audit-total-count');
      if (totalCount) {
        totalCount.textContent = `${result.total} total events`;
      }

      // Render table
      if (result.activities && result.activities.length > 0) {
        const html = `
          <table class="w-full">
            <thead>
              <tr class="border-b">
                <th class="text-left p-3 text-sm font-medium">Time</th>
                <th class="text-left p-3 text-sm font-medium">User</th>
                <th class="text-left p-3 text-sm font-medium">Action</th>
                <th class="text-left p-3 text-sm font-medium">Category</th>
                <th class="text-left p-3 text-sm font-medium">Description</th>
                <th class="text-left p-3 text-sm font-medium">Severity</th>
              </tr>
            </thead>
            <tbody>
              ${result.activities.map(activity => `
                <tr class="border-b hover:bg-muted/50 cursor-pointer" data-action="show-audit-details" data-audit-id="${activity.id}">
                  <td class="p-3 text-sm text-muted">
                    ${escapeHtml(auditService.formatTimestamp(activity.created_at))}
                  </td>
                  <td class="p-3 text-sm">
                    ${escapeHtml(activity.user_name || activity.user_id || 'System')}
                  </td>
                  <td class="p-3 text-sm font-mono text-xs">
                    ${escapeHtml(activity.action)}
                  </td>
                  <td class="p-3 text-sm">
                    ${auditService.getCategoryIcon(activity.category)} ${escapeHtml(activity.category || 'other')}
                  </td>
                  <td class="p-3 text-sm">
                    ${escapeHtml(activity.description || '-')}
                  </td>
                  <td class="p-3">
                    <ds-badge data-variant="${escapeHtml(auditService.getSeverityClass(activity.severity))}">
                      ${escapeHtml(activity.severity)}
                    </ds-badge>
                  </td>
                </tr>
              `).join('')}
            </tbody>
          </table>
        `;
        setSafeHtml(content, html);
      } else {
        content.innerHTML = `
          <div class="text-center py-8 text-muted">
            No audit entries found
          </div>
        `;
      }

      // Update pagination
      const pagination = document.getElementById('audit-pagination');
      if (pagination && result.total > 0) {
        pagination.style.display = 'flex';

        const showing = document.getElementById('audit-showing');
        const total = document.getElementById('audit-total');
        const prevBtn = document.getElementById('audit-prev-btn');
        const nextBtn = document.getElementById('audit-next-btn');

        const start = filters.offset + 1;
        const end = Math.min(filters.offset + result.activities.length, result.total);

        if (showing) showing.textContent = `${start}-${end}`;
        if (total) total.textContent = result.total;

        if (prevBtn) {
          if (filters.offset === 0) {
            prevBtn.setAttribute('disabled', '');
          } else {
            prevBtn.removeAttribute('disabled');
          }
        }
        if (nextBtn) {
          if (!result.has_more) {
            nextBtn.setAttribute('disabled', '');
          } else {
            nextBtn.removeAttribute('disabled');
          }
        }

        this.auditLogData = result;
      }

    } catch (error) {
      content.innerHTML = `
        <div class="text-center py-8 text-destructive">
          Failed to load audit log: ${error.message}
        </div>
      `;
    }
  }

  clearAuditFilters() {
    document.getElementById('audit-category-filter').value = '';
    document.getElementById('audit-severity-filter').value = '';
    document.getElementById('audit-start-date').value = '';
    document.getElementById('audit-end-date').value = '';
    this.auditLogOffset = 0;
    this.loadAuditLog();
  }

  nextAuditPage() {
    const limit = 50;
    this.auditLogOffset = (this.auditLogOffset || 0) + limit;
    this.loadAuditLog();
  }

  prevAuditPage() {
    const limit = 50;
    this.auditLogOffset = Math.max(0, (this.auditLogOffset || 0) - limit);
    this.loadAuditLog();
  }

  async exportAuditLog(format = 'json') {
    const auditService = (await import('../services/audit-service.js')).default;

    const filters = {
      category: document.getElementById('audit-category-filter')?.value || '',
      start_date: document.getElementById('audit-start-date')?.value || '',
      end_date: document.getElementById('audit-end-date')?.value || ''
    };

    // Add current project filter
    const currentProject = this.store.get('currentProject');
    if (currentProject) {
      filters.project_id = currentProject;
    }

    await auditService.export(filters, format);
    this.store.notify(`Audit log export started (${format})`, 'success');
  }

  showAuditDetails(id) {
    // TODO: Show modal with full audit entry details
    console.log('Show audit details for:', id);
  }

  async createProject(name, description, figmaFileKey) {
    this.store.setLoading('createProject', true);
    try {
      const api = (await import('./api.js')).default;
      const project = await api.createProject({
        name,
        description,
        figma_file_key: figmaFileKey
      });
      this.store.addProject(project);
      this.store.set({ showCreateProjectForm: false });
      this.store.notify(`Project "${name}" created successfully`, 'success');
      this.render();
      return project;
    } catch (error) {
      this.store.notify(`Failed to create project: ${error.message}`, 'error');
      throw error;
    } finally {
      this.store.setLoading('createProject', false);
    }
  }

  async updateProjectDescription(projectId, description) {
    this.store.setLoading('updateProject', true);
    try {
      const api = (await import('./api.js')).default;
      await api.updateProject(projectId, { description });

      // Update project in store
      const projects = this.store.get('projects').map(p =>
        p.id === projectId ? { ...p, description } : p
      );
      this.store.setProjects(projects);

      // Update selected project
      const selectedProject = this.store.get('selectedProject');
      if (selectedProject && selectedProject.id === projectId) {
        this.store.set({ selectedProject: { ...selectedProject, description } });
      }

      this.store.notify('Project description updated', 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to update description: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('updateProject', false);
    }
  }

  async deleteProject(projectId) {
    if (!confirm('Are you sure you want to delete this project? This cannot be undone.')) {
      return;
    }

    this.store.setLoading('deleteProject', true);
    try {
      const api = (await import('./api.js')).default;
      await api.deleteProject(projectId);
      const projects = this.store.get('projects').filter(p => p.id !== projectId);
      this.store.setProjects(projects);
      this.store.notify('Project deleted', 'success');
      this.render();
    } catch (error) {
      this.store.notify(`Failed to delete project: ${error.message}`, 'error');
    } finally {
      this.store.setLoading('deleteProject', false);
    }
  }

  selectProject(projectId) {
    const project = this.store.get('projects').find(p => p.id === projectId);
    if (project) {
      this.store.set({
        selectedProject: project,
        figmaFileKey: project.figma_file_key
      });
      this.store.notify(`Selected project: ${project.name}`, 'info');
      // Navigate to dashboard with project context
      this.navigate('dashboard');
    }
  }

  async syncProjectTokens(projectId, figmaKey) {
    if (!figmaKey) {
      this.store.notify('No Figma file key configured for this project', 'warning');
      return;
    }

    this.store.set({ figmaFileKey: figmaKey });
    await this.extractTokens();
    await this.loadProjects(); // Refresh to get updated last_sync
  }

  // === Notifications ===

  renderNotifications(notifications) {
    let container = document.getElementById('notifications');
    if (!container) {
      container = document.createElement('div');
      container.id = 'notifications';
      container.className = 'notification-container';  // Use CSS class instead of inline styles
      document.body.appendChild(container);
    }

    const html = notifications.map(n => {
      const notificationType = escapeHtml(n.type);
      const notificationMessage = escapeHtml(n.message);
      return `
        <div class="notification notification--${notificationType}">
          ${notificationMessage}
        </div>
      `;
    }).join('');

    setSafeHtml(container, html);
  }

  // === Services Page ===

  renderServices() {
    const teamContext = this.store.get('teamContext') || localStorage.getItem('dss_team_context') || 'all';
    const tools = toolsService.getToolsByTeam(teamContext);
    const categories = toolsService.getCategories();

    const teamNames = {
      'all': 'All Tools',
      'ui': 'UI Team',
      'ux': 'UX Team',
      'qa': 'QA Team'
    };

    // Group tools by category
    const toolsByCategory = {};
    tools.forEach(tool => {
      if (!toolsByCategory[tool.category]) {
        toolsByCategory[tool.category] = [];
      }
      toolsByCategory[tool.category].push(tool);
    });

    // Category icons
    const categoryIcons = {
      'Projects': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>',
      'Figma': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 5.5A3.5 3.5 0 0 1 8.5 2H12v7H8.5A3.5 3.5 0 0 1 5 5.5z"/><path d="M12 2h3.5a3.5 3.5 0 1 1 0 7H12V2z"/><path d="M12 12.5a3.5 3.5 0 1 1 7 0 3.5 3.5 0 1 1-7 0z"/><path d="M5 19.5A3.5 3.5 0 0 1 8.5 16H12v3.5a3.5 3.5 0 1 1-7 0z"/><path d="M5 12.5A3.5 3.5 0 0 1 8.5 9H12v7H8.5A3.5 3.5 0 0 1 5 12.5z"/></svg>',
      'Ingestion': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>',
      'Analysis': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 21l-6-6m2-5a7 7 0 1 1-14 0 7 7 0 0 1 14 0z"/></svg>',
      'Storybook': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>',
      'Activity': '<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>'
    };

    logger.info('UI', 'Rendering services page', { toolCount: tools.length, teamContext, categories });

    return `
      <div class="page-header">
        <div class="flex items-center justify-between">
          <div>
            <h1>Services</h1>
            <p class="text-muted">${tools.length} tools available</p>
          </div>
          <input type="text" id="toolSearch" placeholder="Search..." class="input" style="width: 200px;" />
        </div>
      </div>

      <div id="toolsContainer" class="tools-container">
        ${categories.map(category => {
          const categoryTools = toolsByCategory[category] || [];
          if (categoryTools.length === 0) return '';

          return `
            <div class="tools-category" data-category="${category}">
              <div class="tools-category__header">
                <span class="tools-category__icon">${categoryIcons[category] || '📦'}</span>
                <span class="tools-category__name">${category}</span>
                <span class="tools-category__count">${categoryTools.length}</span>
              </div>
              <div class="tools-category__list">
                ${categoryTools.map(tool => this.renderToolCard(tool)).join('')}
              </div>
            </div>
          `;
        }).join('')}
      </div>

      <style>
        .tools-container { display: flex; flex-direction: column; gap: var(--space-4); }
        .tools-category { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
        .tools-category__header { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--muted); border-bottom: 1px solid var(--border); }
        .tools-category__icon { color: var(--primary); display: flex; }
        .tools-category__name { font-weight: var(--font-semibold); flex: 1; }
        .tools-category__count { font-size: var(--text-xs); color: var(--muted-foreground); background: var(--background); padding: 2px 8px; border-radius: var(--radius-full); }
        .tools-category__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
        .tool-item { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); cursor: pointer; transition: background 0.15s; }
        .tool-item:last-child { border-bottom: none; }
        .tool-item:hover { background: var(--accent); }
        .tool-item__icon { font-size: 1.25rem; width: 28px; text-align: center; }
        .tool-item__info { flex: 1; min-width: 0; }
        .tool-item__name { font-size: var(--text-sm); font-weight: var(--font-medium); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .tool-item__desc { font-size: var(--text-xs); color: var(--muted-foreground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .tool-item__action { opacity: 0; transition: opacity 0.15s; }
        .tool-item:hover .tool-item__action { opacity: 1; }
        .tool-item__params { font-size: 10px; color: var(--muted-foreground); }
      </style>
    `;
  }

  renderToolCard(tool) {
    return `
      <div class="tool-item" data-tool="${tool.name}" data-category="${tool.category}" data-action="executeTool" title="${tool.description}">
        <span class="tool-item__icon">${tool.icon}</span>
        <div class="tool-item__info">
          <div class="tool-item__name">${tool.name.replace(/_/g, ' ')}</div>
          <div class="tool-item__desc">${tool.description}</div>
        </div>
        ${tool.parameters.length > 0 ? `<span class="tool-item__params">${tool.parameters.length}p</span>` : ''}
        <svg class="tool-item__action" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
      </div>
    `;
  }

  // === Quick Wins Page ===

  renderQuickWins() {
    logger.info('UI', 'Rendering quick wins page');

    return `
      <div class="page-header">
        <h1>⚡ Quick Wins</h1>
        <p class="text-muted">Actionable improvements to empower your team</p>
      </div>

      <div class="card p-4 mb-6">
        <div class="flex gap-4">
          <input
            type="text"
            id="projectPath"
            placeholder="Project path (default: .)"
            value="."
            class="input flex-1"
          />
          <button
            class="btn btn-primary"
            data-action="loadQuickWins"
          >
            🔍 Analyze Project
          </button>
        </div>
      </div>

      <div id="quickWinsContainer">
        <div class="text-center text-muted py-8">
          <p>Click "Analyze Project" to discover quick wins</p>
        </div>
      </div>
    `;
  }

  async loadQuickWins() {
    const path = document.getElementById('projectPath')?.value || '.';
    const container = document.getElementById('quickWinsContainer');

    if (!container) return;

    logger.info('QuickWins', 'Loading quick wins', { path });

    container.innerHTML = '<div class="text-center py-8">Analyzing project...</div>';

    try {
      const result = await toolsService.executeTool('get_quick_wins', { path });
      const data = typeof result === 'string' ? JSON.parse(result) : result;

      logger.info('QuickWins', 'Quick wins loaded', data);

      container.innerHTML = this.renderQuickWinsResults(data);
    } catch (error) {
      logger.error('QuickWins', 'Failed to load quick wins', error);
      container.innerHTML = `
        <div class="card p-4 bg-destructive/10">
          <p class="text-destructive">Failed to load quick wins: ${error.message}</p>
        </div>
      `;
    }
  }

  renderQuickWinsResults(data) {
    const wins = data.wins || data.quick_wins || [];

    if (wins.length === 0) {
      return '<div class="card p-4"><p class="text-muted">No quick wins found. Great job!</p></div>';
    }

    const byPriority = {
      CRITICAL: wins.filter(w => w.priority === 'CRITICAL'),
      HIGH: wins.filter(w => w.priority === 'HIGH'),
      MEDIUM: wins.filter(w => w.priority === 'MEDIUM'),
      LOW: wins.filter(w => w.priority === 'LOW')
    };

    return `
      <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
        <div class="card p-4">
          <div class="stat">
            <div class="stat__label">Critical</div>
            <div class="stat__value text-destructive">${byPriority.CRITICAL.length}</div>
          </div>
        </div>
        <div class="card p-4">
          <div class="stat">
            <div class="stat__label">High</div>
            <div class="stat__value text-warning">${byPriority.HIGH.length}</div>
          </div>
        </div>
        <div class="card p-4">
          <div class="stat">
            <div class="stat__label">Medium</div>
            <div class="stat__value">${byPriority.MEDIUM.length}</div>
          </div>
        </div>
        <div class="card p-4">
          <div class="stat">
            <div class="stat__label">Low</div>
            <div class="stat__value text-muted">${byPriority.LOW.length}</div>
          </div>
        </div>
      </div>

      <div class="space-y-4">
        ${wins.map(win => this.renderQuickWinCard(win)).join('')}
      </div>
    `;
  }

  renderQuickWinCard(win) {
    const priorityColors = {
      CRITICAL: 'destructive',
      HIGH: 'warning',
      MEDIUM: 'primary',
      LOW: 'muted'
    };

    const color = priorityColors[win.priority] || 'muted';

    return `
      <div class="card p-4">
        <div class="flex items-start justify-between mb-3">
          <div>
            <span class="badge badge-${color}">${win.priority}</span>
            <span class="badge badge-outline ml-2">${win.type}</span>
          </div>
          ${win.effort ? `<span class="text-sm text-muted">Effort: ${win.effort}</span>` : ''}
        </div>

        <h3 class="text-lg font-semibold mb-2">${win.title}</h3>
        <p class="text-muted mb-3">${win.description}</p>

        ${win.file ? `
          <div class="text-sm text-muted mb-3">
            📄 ${win.file}
          </div>
        ` : ''}

        ${win.impact ? `
          <div class="text-sm mb-3">
            <span class="text-muted">Impact:</span> ${win.impact}
          </div>
        ` : ''}

        <div class="flex gap-2">
          <button class="btn btn-sm btn-primary" data-action="investigateWin" data-win-id="${win.id || Math.random()}">
            🔍 Investigate
          </button>
          <button class="btn btn-sm btn-outline" data-action="markDone" data-win-id="${win.id || Math.random()}">
            ✓ Mark Done
          </button>
        </div>
      </div>
    `;
  }

  // === Claude Chat Page ===

  renderChat() {
    const history = claudeService.getHistory();
    const selectedModel = this.store.get('selectedAIModel') || 'claude';

    logger.info('UI', 'Rendering chat page', { historyLength: history.length, model: selectedModel });

    return `
      <div class="page-header">
        <div class="flex items-center justify-between">
          <div>
            <h1>💬 AI Assistant</h1>
            <p class="text-muted">Ask questions about your design system</p>
          </div>
          <div class="flex gap-2">
            <select
              id="aiModelSelect"
              class="select select-sm"
              data-action="changeAIModel"
              style="padding: 4px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--background);"
            >
              <option value="claude" ${selectedModel === 'claude' ? 'selected' : ''}>🤖 Claude</option>
              <option value="gemini" ${selectedModel === 'gemini' ? 'selected' : ''}>✨ Gemini</option>
            </select>
            <button
              class="btn btn-outline btn-sm"
              data-action="exportChat"
            >
              📥 Export
            </button>
            <button
              class="btn btn-outline btn-sm"
              data-action="clearChat"
            >
              🗑️ Clear
            </button>
          </div>
        </div>
      </div>

      <div class="card flex flex-col" style="height: calc(100vh - 200px);">
        <!-- Chat messages -->
        <div id="chatMessages" class="flex-1 overflow-y-auto p-4 space-y-4">
          ${history.length === 0 ? `
            <div class="text-center text-muted py-12">
              <p class="text-lg mb-2">👋 Hi! I'm Claude</p>
              <p>Ask me anything about your design system, tokens, or code</p>
            </div>
          ` : history.map(msg => this.renderChatMessage(msg)).join('')}
        </div>

        <!-- Input form -->
        <div class="border-t p-4">
          <form id="chatForm" class="flex gap-2">
            <input
              type="text"
              id="chatInput"
              placeholder="Ask Claude something..."
              class="input flex-1"
              autocomplete="off"
            />
            <button
              type="submit"
              class="btn btn-primary"
              data-action="sendChatMessage"
            >
              Send
            </button>
          </form>
        </div>
      </div>
    `;
  }

  renderChatMessage(msg) {
    const isUser = msg.role === 'user';
    const bgColor = isUser ? 'bg-primary/10' : 'bg-card';
    const align = isUser ? 'ml-auto' : '';
    const icon = isUser ? '👤' : '🤖';

    return `
      <div class="flex ${isUser ? 'justify-end' : 'justify-start'}">
        <div class="${bgColor} rounded-lg p-4 max-w-[80%] ${align}">
          <div class="flex items-center gap-2 mb-2">
            <span>${icon}</span>
            <span class="text-sm font-medium">${isUser ? 'You' : 'Claude'}</span>
            <span class="text-xs text-muted">${this.formatTime(msg.timestamp)}</span>
          </div>
          <div class="text-sm whitespace-pre-wrap">${this.escapeHtml(msg.content)}</div>
        </div>
      </div>
    `;
  }

  async sendChatMessage(e) {
    if (e) e.preventDefault();

    const input = document.getElementById('chatInput');
    const message = input?.value.trim();

    if (!message) return;

    logger.info('Chat', 'Sending message', { message });

    // Clear input
    input.value = '';

    // Add user message to UI immediately
    const messagesContainer = document.getElementById('chatMessages');
    if (messagesContainer) {
      messagesContainer.innerHTML += this.renderChatMessage({
        role: 'user',
        content: message,
        timestamp: new Date().toISOString()
      });

      // Add loading indicator
      messagesContainer.innerHTML += `
        <div id="chatLoading" class="flex justify-start">
          <div class="bg-card rounded-lg p-4">
            <div class="flex items-center gap-2">
              <span>🤖</span>
              <span class="text-sm">Claude is typing...</span>
            </div>
          </div>
        </div>
      `;

      // Scroll to bottom
      messagesContainer.scrollTop = messagesContainer.scrollHeight;
    }

    try {
      const response = await claudeService.chat(message, {
        project: this.store.get('currentProject'),
        page: 'chat'
      });

      // Remove loading indicator
      document.getElementById('chatLoading')?.remove();

      // Add Claude's response
      if (messagesContainer) {
        messagesContainer.innerHTML += this.renderChatMessage({
          role: 'assistant',
          content: response,
          timestamp: new Date().toISOString()
        });

        messagesContainer.scrollTop = messagesContainer.scrollHeight;
      }
    } catch (error) {
      logger.error('Chat', 'Failed to send message', error);

      document.getElementById('chatLoading')?.remove();

      if (messagesContainer) {
        messagesContainer.innerHTML += `
          <div class="flex justify-start">
            <div class="bg-destructive/10 rounded-lg p-4">
              <div class="text-destructive text-sm">
                ❌ Failed to get response: ${error.message}
              </div>
            </div>
          </div>
        `;
      }

      this.store.notify(`Chat error: ${error.message}`, 'error');
    }
  }

  // === Tool Execution Actions ===

  async executeToolWithParams(toolName) {
    logger.info('ToolExecution', `Preparing to execute ${toolName}`);

    const tool = toolsService.toolsMetadata[toolName];
    if (!tool) {
      logger.error('ToolExecution', `Tool not found: ${toolName}`);
      return;
    }

    // For simple tools with no required params, execute directly
    if (tool.parameters.length === 0) {
      try {
        this.store.notify(`Executing ${toolName}...`, 'info');
        const result = await toolsService.executeTool(toolName, {});
        logger.info('ToolExecution', `Tool ${toolName} completed`, result);
        this.store.notify(`${toolName} completed successfully`, 'success');
        this.render();
      } catch (error) {
        logger.error('ToolExecution', `Tool ${toolName} failed`, error);
        this.store.notify(`${toolName} failed: ${error.message}`, 'error');
      }
      return;
    }

    // TODO: For tools with parameters, show a modal to collect params
    this.store.notify(`${toolName} requires parameters. Parameter input UI coming soon.`, 'info');
  }

  filterTools(searchTerm, category) {
    const cards = document.querySelectorAll('.tool-card');
    const search = searchTerm.toLowerCase();

    cards.forEach(card => {
      const toolName = card.dataset.tool?.toLowerCase() || '';
      const toolCategory = card.dataset.category || '';

      const matchesSearch = !search || toolName.includes(search);
      const matchesCategory = !category || toolCategory === category;

      card.style.display = (matchesSearch && matchesCategory) ? 'block' : 'none';
    });
  }

  investigateWin(winId) {
    logger.info('QuickWins', `Investigating win: ${winId}`);
    this.store.notify('Investigation feature coming soon', 'info');
  }

  markWinDone(winId) {
    logger.info('QuickWins', `Marking win as done: ${winId}`);
    this.store.notify('Win marked as done', 'success');
    // TODO: Persist to backend
  }

  // === Team Dashboard Actions ===

  async addFigmaFile(figmaData) {
    const projectId = this.store.get('currentProject');
    if (!projectId) {
      this.store.notify('Please select a project first', 'warning');
      return;
    }

    try {
      const result = await DashboardService.addFigmaFile(projectId, figmaData);
      this.store.notify('Figma file added successfully', 'success');
      await this.loadDashboardData(projectId);
    } catch (error) {
      this.store.notify(`Failed to add Figma file: ${error.message}`, 'error');
    }
  }

  async deleteFigmaFile(fileId) {
    const projectId = this.store.get('currentProject');
    if (!projectId) return;

    try {
      await DashboardService.deleteFigmaFile(projectId, fileId);
      this.store.notify('Figma file deleted', 'success');
      await this.loadDashboardData(projectId);
    } catch (error) {
      this.store.notify(`Failed to delete Figma file: ${error.message}`, 'error');
    }
  }

  async syncFigmaFile(fileId) {
    const projectId = this.store.get('currentProject');
    if (!projectId) return;

    try {
      await DashboardService.updateFigmaFileSync(projectId, fileId, 'syncing');
      this.store.notify('Syncing Figma file...', 'info');
      // TODO: Implement actual sync logic
      setTimeout(async () => {
        await DashboardService.updateFigmaFileSync(projectId, fileId, 'success');
        this.store.notify('Figma file synced successfully', 'success');
        await this.loadDashboardData(projectId);
      }, 2000);
    } catch (error) {
      this.store.notify(`Failed to sync Figma file: ${error.message}`, 'error');
    }
  }

  async addESREDefinition(esreData) {
    const projectId = this.store.get('currentProject');
    if (!projectId) {
      this.store.notify('Please select a project first', 'warning');
      return;
    }

    try {
      const result = await DashboardService.createESREDefinition(projectId, esreData);
      this.store.notify('ESRE definition added successfully', 'success');
      await this.loadDashboardData(projectId);
    } catch (error) {
      this.store.notify(`Failed to add ESRE definition: ${error.message}`, 'error');
    }
  }

  // === Utilities ===

  escapeHtml(text) {
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
  }

  formatTime(timestamp) {
    const date = new Date(timestamp);
    const now = new Date();
    const diff = now - date;

    if (diff < 60000) return 'Just now';
    if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
    if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
    return date.toLocaleDateString();
  }

  /**
   * Update Storybook link with configured URL
   * Called on init and when settings are saved
   */
  updateStorybookLink() {
    const link = document.getElementById('storybook-link');
    if (!link) return;

    try {
      // Get Storybook URL from server config (loaded from /api/config)
      const storybookUrl = getStorybookUrl();

      link.href = storybookUrl;
      link.style.pointerEvents = 'auto';
      link.style.opacity = '1';
      link.title = `Open Storybook at ${storybookUrl}`;
    } catch (error) {
      // Config not loaded yet or error occurred
      link.style.pointerEvents = 'none';
      link.style.opacity = '0.5';
      link.removeAttribute('href');
      link.title = 'Storybook URL not available';
      logger.warn('App', 'Could not update Storybook link', { error: error.message });
    }
  }
}

// Global instance
const app = new App();

export default app;
