<GENERATED-CODE>
1. Update `app-store.js` to add project management state and actions.
2. Create `ds-project-selector.js` to handle project switching in the UI.
3. Create the 6 module placeholder files for the new architecture.
4. Update `router.js` to map routes to these new modules.
5. Update `ds-shell.js` to implement the new sidebar navigation and layout.

<UPDATED_EXISTING_FILE: admin-ui/js/stores/app-store.js>
/**
 * Design System Server (DSS) - App Store
 *
 * Centralized state management with reactive subscriptions
 * for managing application state across components and pages.
 */

class AppStore {
  constructor() {
    this.state = {
      // User & Auth
      user: null,
      team: null,
      role: null,

      // Navigation
      currentPage: 'dashboard',
      currentProject: null, // New: Selected Project Context
      sidebarOpen: true,

      // Data
      projects: [], // New: List of available projects
      tokens: [],
      components: [],
      styles: [],

      // Discovery
      discovery: null,
      health: null,
      activity: [],
      stats: null,

      // Figma
      figmaConnected: false,
      figmaFileKey: null,
      lastSync: null,

      // Configuration (loaded from server /api/config)
      serverConfig: null,
      isConfigLoading: true,
      configError: null,

      // UI State
      loading: {},
      errors: {},
      notifications: []
    };

    this.listeners = new Map();
    this.middleware = [];
  }

  // === State Access ===

  get(key) {
    return key ? this.state[key] : this.state;
  }

  // === State Updates ===

  set(updates, silent = false) {
    const prevState = { ...this.state };

    // Apply middleware
    for (const mw of this.middleware) {
      updates = mw(updates, prevState);
    }

    this.state = { ...this.state, ...updates };

    if (!silent) {
      this._notify(updates, prevState);
    }
  }

  // === Subscriptions ===

  subscribe(key, callback) {
    if (!this.listeners.has(key)) {
      this.listeners.set(key, new Set());
    }
    this.listeners.get(key).add(callback);

    // Return unsubscribe function
    return () => {
      this.listeners.get(key)?.delete(callback);
    };
  }

  subscribeAll(callback) {
    return this.subscribe('*', callback);
  }

  _notify(updates, prevState) {
    // Notify specific key listeners
    for (const key of Object.keys(updates)) {
      const listeners = this.listeners.get(key);
      if (listeners) {
        listeners.forEach(cb => cb(updates[key], prevState[key], key));
      }
    }

    // Notify global listeners
    const globalListeners = this.listeners.get('*');
    if (globalListeners) {
      globalListeners.forEach(cb => cb(this.state, prevState));
    }
  }

  // === Middleware ===

  use(middleware) {
    this.middleware.push(middleware);
  }

  // === Loading State ===

  setLoading(key, loading = true) {
    this.set({
      loading: { ...this.state.loading, [key]: loading }
    });
  }

  isLoading(key) {
    return this.state.loading[key] || false;
  }

  // === Error State ===

  setError(key, error) {
    this.set({
      errors: { ...this.state.errors, [key]: error }
    });
  }

  clearError(key) {
    const errors = { ...this.state.errors };
    delete errors[key];
    this.set({ errors });
  }

  // === Notifications ===

  notify(message, type = 'info', duration = 5000) {
    const notification = {
      id: Date.now(),
      message,
      type,
      timestamp: new Date()
    };

    this.set({
      notifications: [...this.state.notifications, notification]
    });

    if (duration > 0) {
      setTimeout(() => this.dismissNotification(notification.id), duration);
    }

    return notification.id;
  }

  dismissNotification(id) {
    this.set({
      notifications: this.state.notifications.filter(n => n.id !== id)
    });
  }

  // === User & Auth ===

  setUser(user, team = null, role = null) {
    this.set({ user, team, role });
  }

  logout() {
    this.set({
      user: null,
      team: null,
      role: null,
      projects: [],
      tokens: [],
      components: [],
      currentProject: null
    });
    localStorage.removeItem('currentProject');
  }

  hasPermission(permission) {
    const rolePermissions = {
      SUPER_ADMIN: ['*'],
      TEAM_LEAD: ['read', 'write', 'sync', 'manage_team'],
      DEVELOPER: ['read', 'write', 'sync'],
      VIEWER: ['read']
    };

    const perms = rolePermissions[this.state.role] || [];
    return perms.includes('*') || perms.includes(permission);
  }

  // === Projects (Enhanced for Phase 1) ===

  /**
   * Fetch all projects from API
   */
  async fetchProjects() {
    this.setLoading('projects', true);
    try {
      // Check for auth token (assuming basic auth structure or cookie based for now)
      // If a specific token property exists on the store, use it.
      // For now, we assume credentials are handled via cookies/standard fetch
      const headers = { 'Content-Type': 'application/json' };
      
      const response = await fetch('/api/projects', { headers });
      
      if (!response.ok) throw new Error(`API Error: ${response.status}`);
      
      const json = await response.json();
      
      if (json.status === 'success') {
        this.setProjects(json.data.projects || []);
        
        // Auto-select first project if none selected and projects exist
        if (!this.state.currentProject && json.data.projects.length > 0) {
            // Check localStorage first
            const stored = localStorage.getItem('currentProject');
            if (stored) {
                try {
                    const parsed = JSON.parse(stored);
                    const exists = json.data.projects.find(p => p.id === parsed.id);
                    if (exists) this.setProject(exists);
                } catch (e) {
                    console.warn('Invalid stored project', e);
                }
            }
        }
      } else {
        throw new Error(json.message || 'Failed to fetch projects');
      }
    } catch (error) {
      console.error('Project fetch error:', error);
      this.setError('projects', error.message);
      // Fallback for dev/demo mode if API fails
      if (window.location.hostname === 'localhost' && this.state.projects.length === 0) {
        console.warn('Using mock projects for development');
        this.setProjects([
            { id: 'proj_default', name: 'Default Design System' },
            { id: 'proj_mobile', name: 'Mobile App DS' }
        ]);
      }
    } finally {
      this.setLoading('projects', false);
    }
  }

  setProjects(projects) {
    this.set({ projects });
  }

  setProject(project) {
    this.set({ currentProject: project });
    if (project) {
        localStorage.setItem('currentProject', JSON.stringify(project));
    } else {
        localStorage.removeItem('currentProject');
    }
  }

  async getProjectConfig() {
    if (!this.state.currentProject) return null;
    
    this.setLoading('config', true);
    try {
        const response = await fetch(`/api/config/${this.state.currentProject.id}/resolved`);
        const json = await response.json();
        return json.status === 'success' ? json.data.config : null;
    } catch (error) {
        console.error('Config fetch error:', error);
        return null;
    } finally {
        this.setLoading('config', false);
    }
  }

  addProject(project) {
    this.set({
      projects: [...this.state.projects, project]
    });
  }

  updateProject(id, updates) {
    this.set({
      projects: this.state.projects.map(p =>
        p.id === id ? { ...p, ...updates } : p
      )
    });
  }

  // === Figma ===

  setFigmaConnected(connected, fileKey = null) {
    this.set({
      figmaConnected: connected,
      figmaFileKey: fileKey
    });
  }

  setLastSync(timestamp) {
    this.set({ lastSync: timestamp });
  }

  // === Tokens ===

  setTokens(tokens) {
    this.set({ tokens });
  }

  getTokensByCategory(category) {
    return this.state.tokens.filter(t => t.category === category);
  }

  // === Components ===

  setComponents(components) {
    this.set({ components });
  }

  // === Discovery ===

  setDiscovery(discovery) {
    this.set({ discovery });
  }

  setHealth(health) {
    this.set({ health });
  }

  setActivity(activity) {
    this.set({ activity });
  }

  setStats(stats) {
    this.set({ stats });
  }

  // === Persistence ===

  persist() {
    const toPersist = {
      user: this.state.user,
      team: this.state.team,
      role: this.state.role,
      figmaFileKey: this.state.figmaFileKey,
      sidebarOpen: this.state.sidebarOpen
      // Note: currentProject is persisted separately in setProject
    };
    localStorage.setItem('dss-store', JSON.stringify(toPersist));
  }

  hydrate() {
    try {
      // Hydrate general store data
      const stored = localStorage.getItem('dss-store');
      if (stored) {
        const data = JSON.parse(stored);
        this.set(data, true);
      }

      // Hydrate Project Context specifically
      const storedProject = localStorage.getItem('currentProject');
      if (storedProject) {
        const project = JSON.parse(storedProject);
        this.set({ currentProject: project }, true);
      }
    } catch (e) {
      console.warn('Failed to hydrate store:', e);
    }
  }

  // === Debug ===

  debug() {
    console.group('App Store State');
    console.log('State:', this.state);
    console.log('Listeners:', Array.from(this.listeners.keys()));
    console.groupEnd();
  }
}

// Logging middleware
const loggingMiddleware = (updates, prevState) => {
  if (window.DEBUG) {
    console.log('[Store Update]', updates);
  }
  return updates;
};

// Create and export singleton
const store = new AppStore();
store.use(loggingMiddleware);
store.hydrate();

// Auto-persist on important changes
store.subscribe('user', () => store.persist());
store.subscribe('team', () => store.persist());
store.subscribe('figmaFileKey', () => store.persist());

export { AppStore };
export default store;
</UPDATED_EXISTING_FILE>

<NEWFILE: admin-ui/js/components/layout/ds-project-selector.js>
/**
 * ds-project-selector.js
 * 
 * Dropdown component for switching between Design System projects.
 * Persists selection to AppStore and LocalStorage.
 */

import store from '../../stores/app-store.js';

class DSProjectSelector extends HTMLElement {
  constructor() {
    super();
    this.unsubscribe = null;
  }

  connectedCallback() {
    this.render();
    this.setupEventListeners();
    
    // Subscribe to store changes
    this.unsubscribe = store.subscribe('projects', () => this.updateOptions());
    store.subscribe('currentProject', () => this.updateSelection());
    store.subscribe('loading', () => this.updateLoadingState());
    
    // Initial fetch
    this.fetchProjects();
  }

  disconnectedCallback() {
    if (this.unsubscribe) this.unsubscribe();
  }

  async fetchProjects() {
    await store.fetchProjects();
  }

  render() {
    this.innerHTML = `
      <style>
        .project-selector-container {
          position: relative;
          display: flex;
          align-items: center;
          gap: 8px;
        }
        
        select.project-select {
          appearance: none;
          background-color: var(--vscode-dropdown-background, #252526);
          color: var(--vscode-dropdown-foreground, #cccccc);
          border: 1px solid var(--vscode-dropdown-border, #3c3c3c);
          padding: 4px 24px 4px 8px;
          border-radius: 3px;
          font-family: inherit;
          font-size: 13px;
          cursor: pointer;
          min-width: 150px;
          outline: none;
        }

        select.project-select:focus {
          border-color: var(--vscode-focusBorder, #007fd4);
        }

        /* Custom arrow implementation since we removed default appearance */
        .select-arrow {
          position: absolute;
          right: 8px;
          top: 50%;
          transform: translateY(-50%);
          pointer-events: none;
          font-size: 10px;
          color: var(--vscode-foreground, #cccccc);
        }

        .loading-spinner {
          width: 12px;
          height: 12px;
          border: 2px solid var(--vscode-text-dim, #666);
          border-top-color: var(--vscode-accent, #007fd4);
          border-radius: 50%;
          animation: spin 1s linear infinite;
          display: none;
        }

        @keyframes spin {
          to { transform: rotate(360deg); }
        }
      </style>
      
      <div class="project-selector-container">
        <select class="project-select" id="project-dropdown" aria-label="Select Project">
          <option value="" disabled selected>Select Project...</option>
        </select>
        <div class="select-arrow">▼</div>
        <div class="loading-spinner" id="project-loader"></div>
      </div>
    `;
    
    // Initial population if data exists
    this.updateOptions();
    this.updateSelection();
  }

  setupEventListeners() {
    const select = this.querySelector('#project-dropdown');
    if (select) {
      select.addEventListener('change', (e) => {
        const projectId = e.target.value;
        const projects = store.get('projects');
        const selectedProject = projects.find(p => p.id === projectId);
        
        if (selectedProject) {
          store.setProject(selectedProject);
          // Emit event for immediate listeners
          this.dispatchEvent(new CustomEvent('project-changed', {
            detail: { project: selectedProject },
            bubbles: true,
            composed: true
          }));
        }
      });
    }
  }

  updateOptions() {
    const select = this.querySelector('#project-dropdown');
    if (!select) return;

    const projects = store.get('projects');
    const currentProject = store.get('currentProject');

    // Keep the placeholder as first option
    select.innerHTML = '<option value="" disabled>Select Project...</option>';

    if (projects.length === 0) {
        const emptyOpt = document.createElement('option');
        emptyOpt.text = "No projects found";
        emptyOpt.disabled = true;
        select.appendChild(emptyOpt);
    } else {
        projects.forEach(proj => {
            const option = document.createElement('option');
            option.value = proj.id;
            option.textContent = proj.name;
            select.appendChild(option);
        });
    }

    // Re-apply selection if exists
    if (currentProject) {
        select.value = currentProject.id;
    } else {
        select.value = "";
    }
  }

  updateSelection() {
    const select = this.querySelector('#project-dropdown');
    const currentProject = store.get('currentProject');
    
    if (select && currentProject) {
      select.value = currentProject.id;
    }
  }

  updateLoadingState() {
    const isLoading = store.isLoading('projects');
    const loader = this.querySelector('#project-loader');
    const arrow = this.querySelector('.select-arrow');
    
    if (loader && arrow) {
      loader.style.display = isLoading ? 'block' : 'none';
      arrow.style.display = isLoading ? 'none' : 'block';
    }
  }
}

customElements.define('ds-project-selector', DSProjectSelector);
</NEWFILE>

<NEWFILE: admin-ui/js/modules/projects/ProjectsModule.js>
/**
 * ProjectsModule.js
 * Feature module for managing DSS projects, metadata, and selection.
 */

class ProjectsModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container {
          padding: 24px;
          color: var(--vscode-foreground);
        }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border, #3c3c3c);
          border-radius: 6px;
          background-color: var(--vscode-editor-background);
          margin-top: 24px;
        }
        h1 {
          font-size: 24px;
          font-weight: 500;
          margin-bottom: 8px;
        }
        .icon-large {
          font-size: 48px;
          margin-bottom: 16px;
          opacity: 0.8;
        }
        p {
          color: var(--vscode-descriptionForeground);
          max-width: 500px;
          text-align: center;
          line-height: 1.5;
        }
      </style>
      
      <div class="module-container">
        <h1>Projects</h1>
        <div class="empty-state">
          <div class="icon-large">📁</div>
          <h3>Projects Module Under Construction</h3>
          <p>
            This module will allow you to create new projects, edit project metadata, 
            and manage access controls. Currently, use the selector in the top bar to switch contexts.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-projects-module', ProjectsModule);
export default ProjectsModule;
</NEWFILE>

<NEWFILE: admin-ui/js/modules/config/ConfigModule.js>
/**
 * ConfigModule.js
 * Feature module for managing the 3-tier cascade configuration.
 */

class ConfigModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container { padding: 24px; color: var(--vscode-foreground); }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border);
          border-radius: 6px;
          margin-top: 24px;
        }
        .icon-large { font-size: 48px; margin-bottom: 16px; }
      </style>
      
      <div class="module-container">
        <h1>Configuration</h1>
        <div class="empty-state">
          <div class="icon-large">⚙️</div>
          <h3>Configuration Module Under Construction</h3>
          <p>
            Manage your 3-tier configuration cascade here (Base → Brand → Project).
            Future updates will include visual editors for JSON/YAML config files.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-config-module', ConfigModule);
export default ConfigModule;
</NEWFILE>

<NEWFILE: admin-ui/js/modules/components/ComponentsModule.js>
/**
 * ComponentsModule.js
 * Feature module for the Component Registry, search, and status tracking.
 */

class ComponentsModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container { padding: 24px; color: var(--vscode-foreground); }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border);
          border-radius: 6px;
          margin-top: 24px;
        }
        .icon-large { font-size: 48px; margin-bottom: 16px; }
      </style>
      
      <div class="module-container">
        <h1>Components</h1>
        <div class="empty-state">
          <div class="icon-large">🧩</div>
          <h3>Components Registry Under Construction</h3>
          <p>
            View component status, health, and documentation links.
            This module will interface with the registry to show what is available in your design system.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-components-module', ComponentsModule);
export default ComponentsModule;
</NEWFILE>

<NEWFILE: admin-ui/js/modules/translations/TranslationsModule.js>
/**
 * TranslationsModule.js
 * Feature module for managing Legacy → DSS token mappings (Principle #2).
 */

class TranslationsModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container { padding: 24px; color: var(--vscode-foreground); }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border);
          border-radius: 6px;
          margin-top: 24px;
        }
        .icon-large { font-size: 48px; margin-bottom: 16px; }
      </style>
      
      <div class="module-container">
        <h1>Translation Dictionaries</h1>
        <div class="empty-state">
          <div class="icon-large">🔄</div>
          <h3>Translations Module Under Construction</h3>
          <p>
            <b>Core DSS Principle #2:</b> Map legacy design tokens to modern DSS tokens.
            This interface will allow creation and validation of translation dictionaries.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-translations-module', TranslationsModule);
export default TranslationsModule;
</NEWFILE>

<NEWFILE: admin-ui/js/modules/discovery/DiscoveryModule.js>
/**
 * DiscoveryModule.js
 * Feature module for scanning projects, activity logs, and analysis.
 */

class DiscoveryModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container { padding: 24px; color: var(--vscode-foreground); }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border);
          border-radius: 6px;
          margin-top: 24px;
        }
        .icon-large { font-size: 48px; margin-bottom: 16px; }
      </style>
      
      <div class="module-container">
        <h1>Discovery</h1>
        <div class="empty-state">
          <div class="icon-large">🔍</div>
          <h3>Discovery Module Under Construction</h3>
          <p>
            Run scanners, view codebase analytics, and monitor system activity.
            Integration with the scanner backend is coming in the next phase.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-discovery-module', DiscoveryModule);
export default DiscoveryModule;
</NEWFILE>

<NEWFILE: admin-ui/js/modules/admin/AdminModule.js>
/**
 * AdminModule.js
 * Feature module for RBAC, user management, and system audit logs.
 */

class AdminModule extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    this.render();
  }

  render() {
    this.innerHTML = `
      <style>
        .module-container { padding: 24px; color: var(--vscode-foreground); }
        .empty-state {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          padding: 48px;
          border: 1px dashed var(--vscode-input-border);
          border-radius: 6px;
          margin-top: 24px;
        }
        .icon-large { font-size: 48px; margin-bottom: 16px; }
      </style>
      
      <div class="module-container">
        <h1>Administration</h1>
        <div class="empty-state">
          <div class="icon-large">👤</div>
          <h3>Admin Module Under Construction</h3>
          <p>
            Manage users, permissions (RBAC), and view audit logs.
            Only available to users with administrative privileges.
          </p>
        </div>
      </div>
    `;
  }
}

customElements.define('dss-admin-module', AdminModule);
export default AdminModule;
</NEWFILE>

<UPDATED_EXISTING_FILE: admin-ui/js/core/router.js>
/**
 * DSS Router
 *
 * Centralized hash-based routing with guards, lifecycle hooks, and
 * declarative route definitions for enterprise-grade navigation management.
 *
 * @module router
 */

import { notifyError, ErrorCode } from './messaging.js';

/**
 * Route configuration object
 * @typedef {Object} RouteConfig
 * @property {string} path - Route path (e.g., '/dashboard', '/projects')
 * @property {string} name - Route name for programmatic navigation
 * @property {Function} handler - Route handler function
 * @property {Function} [beforeEnter] - Guard called before entering route
 * @property {Function} [afterEnter] - Hook called after entering route
 * @property {Function} [onLeave] - Hook called when leaving route
 * @property {Object} [meta] - Route metadata
 */

/**
 * Router class for centralized route management
 */
class Router {
  constructor() {
    this.routes = new Map();
    this.currentRoute = null;
    this.previousRoute = null;
    this.defaultRoute = 'projects'; // Updated default route for new architecture
    this.isNavigating = false;

    // Bind handlers
    this.handleHashChange = this.handleHashChange.bind(this);
    this.handlePopState = this.handlePopState.bind(this);
  }

  /**
   * Initialize the router
   */
  init() {
    // Define Core Routes for New Architecture
    this.registerAll([
      {
        path: '/projects',
        name: 'Projects',
        handler: () => this.loadModule('dss-projects-module', () => import('../modules/projects/ProjectsModule.js'))
      },
      {
        path: '/config',
        name: 'Configuration',
        handler: () => this.loadModule('dss-config-module', () => import('../modules/config/ConfigModule.js'))
      },
      {
        path: '/components',
        name: 'Components',
        handler: () => this.loadModule('dss-components-module', () => import('../modules/components/ComponentsModule.js'))
      },
      {
        path: '/translations',
        name: 'Translations',
        handler: () => this.loadModule('dss-translations-module', () => import('../modules/translations/TranslationsModule.js'))
      },
      {
        path: '/discovery',
        name: 'Discovery',
        handler: () => this.loadModule('dss-discovery-module', () => import('../modules/discovery/DiscoveryModule.js'))
      },
      {
        path: '/admin',
        name: 'Admin',
        handler: () => this.loadModule('dss-admin-module', () => import('../modules/admin/AdminModule.js'))
      }
    ]);

    // Listen for hash changes
    window.addEventListener('hashchange', this.handleHashChange);
    window.addEventListener('popstate', this.handlePopState);

    // Handle initial route
    this.handleHashChange();
  }

  /**
   * Helper to load dynamic modules into the stage
   * @param {string} tagName - Custom element tag name
   * @param {Function} importFn - Dynamic import function
   */
  async loadModule(tagName, importFn) {
    try {
      // 1. Load the module file
      await importFn();
      
      // 2. Update the stage content
      const stageContent = document.querySelector('#stage-workdesk-content');
      if (stageContent) {
        stageContent.innerHTML = '';
        const element = document.createElement(tagName);
        stageContent.appendChild(element);
      }
    } catch (error) {
      console.error(`Failed to load module ${tagName}:`, error);
      notifyError(`Failed to load module`, ErrorCode.SYSTEM_UNEXPECTED);
    }
  }

  /**
   * Register a route
   * @param {RouteConfig} config - Route configuration
   */
  register(config) {
    if (!config.path) {
      throw new Error('Route path is required');
    }

    if (!config.handler) {
      throw new Error('Route handler is required');
    }

    // Normalize path (remove leading slash for hash routing)
    const path = config.path.replace(/^\//, '');

    this.routes.set(path, {
      path,
      name: config.name || path,
      handler: config.handler,
      beforeEnter: config.beforeEnter || null,
      afterEnter: config.afterEnter || null,
      onLeave: config.onLeave || null,
      meta: config.meta || {},
    });

    return this;
  }

  /**
   * Register multiple routes
   * @param {RouteConfig[]} routes - Array of route configurations
   */
  registerAll(routes) {
    routes.forEach(route => this.register(route));
    return this;
  }

  /**
   * Set default route
   * @param {string} path - Default route path
   */
  setDefaultRoute(path) {
    this.defaultRoute = path.replace(/^\//, '');
    return this;
  }

  /**
   * Navigate to a route
   * @param {string} path - Route path or name
   * @param {Object} [options] - Navigation options
   * @param {boolean} [options.replace] - Replace history instead of push
   * @param {Object} [options.state] - State to pass to route
   */
  navigate(path, options = {}) {
    const normalizedPath = path.replace(/^\//, '');

    // Update hash
    if (options.replace) {
      window.location.replace(`#${normalizedPath}`);
    } else {
      window.location.hash = normalizedPath;
    }

    return this;
  }

  /**
   * Navigate to a route by name
   * @param {string} name - Route name
   * @param {Object} [options] - Navigation options
   */
  navigateByName(name, options = {}) {
    const route = Array.from(this.routes.values()).find(r => r.name === name);

    if (!route) {
      notifyError(`Route not found: ${name}`, ErrorCode.SYSTEM_UNEXPECTED);
      return this;
    }

    return this.navigate(route.path, options);
  }

  /**
   * Handle hash change event
   */
  async handleHashChange() {
    if (this.isNavigating) return;

    this.isNavigating = true;

    try {
      // Get path from hash
      let path = window.location.hash.replace(/^#/, '') || this.defaultRoute;

      // Extract route and params
      const { routePath, params } = this.parseRoute(path);

      // Find route
      const route = this.routes.get(routePath);

      if (!route) {
        console.warn(`Route not registered: ${routePath}, falling back to default`);
        this.navigate(this.defaultRoute, { replace: true });
        return;
      }

      // Call onLeave hook for previous route
      if (this.currentRoute && this.currentRoute.onLeave) {
        await this.callHook(this.currentRoute.onLeave, { from: this.currentRoute, to: route });
      }

      // Call beforeEnter guard
      if (route.beforeEnter) {
        const canEnter = await this.callGuard(route.beforeEnter, { route, params });

        if (!canEnter) {
          // Guard rejected, stay on current route or go to default
          if (this.currentRoute) {
            this.navigate(this.currentRoute.path, { replace: true });
          } else {
            this.navigate(this.defaultRoute, { replace: true });
          }
          return;
        }
      }

      // Update route tracking
      this.previousRoute = this.currentRoute;
      this.currentRoute = route;

      // Call route handler
      await route.handler({ route, params, router: this });

      // Call afterEnter hook
      if (route.afterEnter) {
        await this.callHook(route.afterEnter, { route, params, from: this.previousRoute });
      }

      // Emit route change event
      this.emitRouteChange(route, params);

    } catch (error) {
      console.error('Router navigation error:', error);
      notifyError('Navigation failed', ErrorCode.SYSTEM_UNEXPECTED, {
        path: window.location.hash,
        error: error.message,
      });
    } finally {
      this.isNavigating = false;
    }
  }

  /**
   * Handle popstate event (browser back/forward)
   */
  handlePopState(event) {
    this.handleHashChange();
  }

  /**
   * Parse route path and extract params
   * @param {string} path - Route path
   * @returns {Object} Route path and params
   */
  parseRoute(path) {
    // For now, simple implementation - just return the path
    // Can be extended to support params like '/projects/:id'
    const [routePath, queryString] = path.split('?');

    const params = {};
    if (queryString) {
      new URLSearchParams(queryString).forEach((value, key) => {
        params[key] = value;
      });
    }

    return { routePath, params };
  }

  /**
   * Call a route guard
   * @param {Function} guard - Guard function
   * @param {Object} context - Guard context
   * @returns {Promise<boolean>} Whether navigation should proceed
   */
  async callGuard(guard, context) {
    try {
      const result = await guard(context);
      return result !== false; // Undefined or true = proceed
    } catch (error) {
      console.error('Route guard error:', error);
      return false;
    }
  }

  /**
   * Call a lifecycle hook
   * @param {Function} hook - Hook function
   * @param {Object} context - Hook context
   */
  async callHook(hook, context) {
    try {
      await hook(context);
    } catch (error) {
      console.error('Route hook error:', error);
    }
  }

  /**
   * Emit route change event
   * @param {Object} route - Current route
   * @param {Object} params - Route params
   */
  emitRouteChange(route, params) {
    window.dispatchEvent(new CustomEvent('route-changed', {
      detail: {
        route,
        params,
        previous: this.previousRoute,
      }
    }));
  }

  /**
   * Get current route
   * @returns {Object|null} Current route config
   */
  getCurrentRoute() {
    return this.currentRoute;
  }

  /**
   * Get previous route
   * @returns {Object|null} Previous route config
   */
  getPreviousRoute() {
    return this.previousRoute;
  }

  /**
   * Check if a route exists
   * @param {string} path - Route path
   * @returns {boolean} Whether route exists
   */
  hasRoute(path) {
    const normalizedPath = path.replace(/^\//, '');
    return this.routes.has(normalizedPath);
  }

  /**
   * Get route by path
   * @param {string} path - Route path
   * @returns {Object|null} Route config
   */
  getRoute(path) {
    const normalizedPath = path.replace(/^\//, '');
    return this.routes.get(normalizedPath) || null;
  }

  /**
   * Get all routes
   * @returns {Array} All registered routes
   */
  getAllRoutes() {
    return Array.from(this.routes.values());
  }

  /**
   * Go back in history
   */
  back() {
    window.history.back();
    return this;
  }

  /**
   * Go forward in history
   */
  forward() {
    window.history.forward();
    return this;
  }

  /**
   * Destroy the router (cleanup)
   */
  destroy() {
    window.removeEventListener('hashchange', this.handleHashChange);
    window.removeEventListener('popstate', this.handlePopState);
    this.routes.clear();
    this.currentRoute = null;
    this.previousRoute = null;
  }
}

// Singleton instance
const router = new Router();

// Export both the instance and the class
export { Router };
export default router;

/**
 * Common route guards
 */
export const guards = {
  /**
   * Require authentication
   */
  requireAuth({ route }) {
    // Check if user is authenticated
    // For now, always allow (implement auth later)
    return true;
  },

  /**
   * Require specific permission
   */
  requirePermission(permission) {
    return ({ route }) => {
      // Check if user has permission
      // For now, always allow (implement RBAC later)
      return true;
    };
  },

  /**
   * Require project selected
   */
  requireProject({ route, params }) {
    const projectId = localStorage.getItem('currentProject');

    if (!projectId) {
      notifyError('Please select a project first', ErrorCode.USER_ACTION_FORBIDDEN);
      return false;
    }

    return true;
  },
};
</UPDATED_EXISTING_FILE>

<UPDATED_EXISTING_FILE: admin-ui/js/components/layout/ds-shell.js>
/**
 * ds-shell.js
 * Main shell component - provides IDE-style grid layout
 * Refactored for Phase 1 Architecture (Feature-based Modules)
 */

import './ds-activity-bar.js';
import './ds-panel.js';
import './ds-project-selector.js'; // New Project Selector
import './ds-ai-chat-sidebar.js';
import '../admin/ds-user-settings.js'; 
import '../ds-notification-center.js'; 
import router from '../../core/router.js'; // Import Router
import layoutManager from '../../core/layout-manager.js';
import notificationService from '../../services/notification-service.js';
import { useAdminStore } from '../../stores/admin-store.js';
import { useProjectStore } from '../../stores/project-store.js';
import { useUserStore } from '../../stores/user-store.js';
import '../../config/component-registry.js';
import { authReady } from '../../utils/demo-auth-init.js';

class DSShell extends HTMLElement {
  constructor() {
    super();
    this.browserInitialized = false;
    this.currentView = 'module'; 

    // MVP2: Initialize stores
    this.adminStore = useAdminStore();
    this.projectStore = useProjectStore();
    this.userStore = useUserStore();
  }

  async connectedCallback() {
    // Render UI immediately (non-blocking)
    this.render();
    this.setupEventListeners();

    // Initialize layout manager
    // Keep this for now to maintain layout structure, though "workdesks" are being phased out
    if (layoutManager && typeof layoutManager.init === 'function') {
        layoutManager.init(this);
    }
    
    // Initialize Router
    router.init();

    // Wait for authentication
    console.log('[DSShell] Waiting for authentication...');
    const authResult = await authReady;
    console.log('[DSShell] Authentication complete:', authResult);

    // Initialize services
    notificationService.init();

    // Set initial active link
    this.updateActiveLink();
  }

  render() {
    this.innerHTML = `
      <ds-sidebar>
        <div class="sidebar-header" style="display: flex; flex-direction: column; gap: 8px; padding-bottom: 12px; border-bottom: 1px solid var(--vscode-border);">
          <div style="display: flex; align-items: center; gap: 8px;">
            <span style="font-size: 24px; font-weight: 700;">⬡</span>
            <div>
              <div style="font-size: 13px; font-weight: 700; color: var(--vscode-text);">DSS</div>
              <div style="font-size: 10px; color: var(--vscode-text-dim); line-height: 1.2;">Design System Studio</div>
            </div>
          </div>
        </div>
        
        <!-- NEW: Feature Module Navigation -->
        <div class="sidebar-content">
          <nav class="module-nav" style="display: flex; flex-direction: column; gap: 4px; padding-top: 12px;">
            <a href="#projects" class="nav-item" data-path="projects" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">📁</span> Projects
            </a>
            <a href="#config" class="nav-item" data-path="config" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">⚙️</span> Configuration
            </a>
            <a href="#components" class="nav-item" data-path="components" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">🧩</span> Components
            </a>
            <a href="#translations" class="nav-item" data-path="translations" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">🔄</span> Translations
            </a>
            <a href="#discovery" class="nav-item" data-path="discovery" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">🔍</span> Discovery
            </a>
            <div style="height: 1px; background: var(--vscode-border); margin: 8px 0;"></div>
            <a href="#admin" class="nav-item" data-path="admin" style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; color: var(--vscode-text-dim); text-decoration: none; border-radius: 4px; transition: all 0.1s; font-size: 13px;">
              <span style="font-size: 16px;">👤</span> Admin
            </a>
          </nav>
        </div>
      </ds-sidebar>

      <ds-stage>
        <div class="stage-header" style="display: flex; justify-content: space-between; align-items: center; padding: 0 16px; border-bottom: 1px solid var(--vscode-border); background: var(--vscode-bg); min-height: 44px;">
          <div class="stage-header-left" style="display: flex; align-items: center; gap: 12px;">
            <!-- Hamburger Menu (Mobile) -->
            <button id="hamburger-menu" class="hamburger-menu" style="display: none; padding: 6px 8px; background: transparent; border: none; color: var(--vscode-text-dim); cursor: pointer; font-size: 20px;" aria-label="Toggle sidebar">☰</button>

            <!-- NEW: Project Selector -->
            <ds-project-selector></ds-project-selector>
            
          </div>
          <div class="stage-header-right" id="stage-actions" style="display: flex; align-items: center; gap: 8px;">
            <!-- Action buttons will be populated here -->
          </div>
        </div>
        <div class="stage-content">
          <div id="stage-workdesk-content" style="height: 100%; overflow: auto;">
            <!-- Dynamic Module Content via Router -->
          </div>
        </div>
      </ds-stage>

      <ds-ai-chat-sidebar></ds-ai-chat-sidebar>
    `;
  }

  setupEventListeners() {
    this.setupMobileMenu();
    this.setupHeaderActions();
    this.setupNavigationHighlight();

    // Listen for route changes to update UI
    window.addEventListener('route-changed', (e) => {
        this.updateActiveLink(e.detail.route.path);
    });
  }

  setupNavigationHighlight() {
    const navItems = this.querySelectorAll('.nav-item');
    navItems.forEach(item => {
        item.addEventListener('mouseenter', (e) => {
            if (!e.target.classList.contains('active')) {
                e.target.style.background = 'var(--vscode-list-hoverBackground, rgba(255,255,255,0.1))';
                e.target.style.color = 'var(--vscode-text)';
            }
        });
        item.addEventListener('mouseleave', (e) => {
            if (!e.target.classList.contains('active')) {
                e.target.style.background = 'transparent';
                e.target.style.color = 'var(--vscode-text-dim)';
            }
        });
    });
  }

  updateActiveLink(path) {
    const currentPath = path || (window.location.hash.replace('#', '') || 'projects');
    const navItems = this.querySelectorAll('.nav-item');
    
    navItems.forEach(item => {
        const itemPath = item.dataset.path;
        if (itemPath === currentPath) {
            item.classList.add('active');
            item.style.background = 'var(--vscode-selection)';
            item.style.color = 'var(--vscode-accent)';
            item.style.fontWeight = '500';
        } else {
            item.classList.remove('active');
            item.style.background = 'transparent';
            item.style.color = 'var(--vscode-text-dim)';
            item.style.fontWeight = 'normal';
        }
    });
  }

  setupHeaderActions() {
    const stageActions = this.querySelector('#stage-actions');
    if (!stageActions) return;

    stageActions.innerHTML = `
        <button id="chat-toggle-btn" aria-label="Toggle AI Chat" title="Toggle Chat" style="background:transparent; border:none; color:var(--vscode-text-dim); cursor:pointer; padding:6px; font-size:16px;">💬</button>
        <div style="position: relative;">
          <button id="notification-toggle-btn" aria-label="Notifications" title="Notifications" style="background:transparent; border:none; color:var(--vscode-text-dim); cursor:pointer; padding:6px; font-size:16px;">🔔</button>
          <ds-notification-center></ds-notification-center>
        </div>
        <button id="settings-btn" aria-label="Settings" title="Settings" style="background:transparent; border:none; color:var(--vscode-text-dim); cursor:pointer; padding:6px; font-size:16px;">⚙️</button>
    `;

    // Re-attach listeners for these buttons similar to original implementation
    // Simplified for brevity, ensuring critical paths work
    const chatBtn = this.querySelector('#chat-toggle-btn');
    chatBtn?.addEventListener('click', () => {
        const sidebar = this.querySelector('ds-ai-chat-sidebar');
        if (sidebar && sidebar.toggleCollapse) sidebar.toggleCollapse();
    });

    const notifBtn = this.querySelector('#notification-toggle-btn');
    const notifCenter = this.querySelector('ds-notification-center');
    notifBtn?.addEventListener('click', (e) => {
        e.stopPropagation();
        if (notifCenter) {
            if (notifCenter.hasAttribute('open')) notifCenter.removeAttribute('open');
            else notifCenter.setAttribute('open', '');
        }
    });

    // Close notifications on outside click
    document.addEventListener('click', (e) => {
        if (notifCenter && !notifCenter.contains(e.target) && !notifBtn.contains(e.target)) {
            notifCenter.removeAttribute('open');
        }
    });

    const settingsBtn = this.querySelector('#settings-btn');
    settingsBtn?.addEventListener('click', () => {
        // Simple navigation to admin/settings
        router.navigate('admin');
    });
  }

  setupMobileMenu() {
    const hamburgerBtn = this.querySelector('#hamburger-menu');
    const sidebar = this.querySelector('ds-sidebar');

    if (hamburgerBtn && sidebar) {
        // Update visibility based on screen size
        const checkSize = () => {
            if (window.innerWidth <= 768) {
                hamburgerBtn.style.display = 'block';
            } else {
                hamburgerBtn.style.display = 'none';
                sidebar.classList.remove('mobile-open');
            }
        };
        
        window.addEventListener('resize', checkSize);
        checkSize();

        hamburgerBtn.addEventListener('click', () => {
            sidebar.classList.toggle('mobile-open');
        });
    }
  }

  // Getters for compatibility with any legacy code looking for these elements
  get sidebarContent() {
    return this.querySelector('.sidebar-content');
  }

  get stageContent() {
    return this.querySelector('#stage-workdesk-content');
  }
}

customElements.define('ds-shell', DSShell);
</UPDATED_EXISTING_FILE>
</GENERATED-CODE>
