<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Prism Installer</title>
    <link rel="icon" type="image/png" sizes="32x32" href="/assets/branding/prism_transparent_32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/assets/branding/prism_transparent_16.png">
    <style>
        :root {
            /* Defaults — overridden by package theme via JS */
            --gradient-1: #667eea;
            --gradient-2: #764ba2;
            --gradient-3: #f093fb;
            --gradient-4: #f5576c;
            --gradient-5: #4facfe;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: linear-gradient(135deg, 
                var(--gradient-1) 0%, 
                var(--gradient-2) 25%, 
                var(--gradient-3) 50%, 
                var(--gradient-4) 75%, 
                var(--gradient-5) 100%);
            background-size: 400% 400%;
            animation: gradientShift 15s ease infinite;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
            transition: background 0.5s ease;
        }
        
        @keyframes gradientShift {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }
        
        .container {
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3), 0 0 0 1px rgba(255,255,255,0.5) inset;
            max-width: 800px;
            width: 100%;
            padding: 40px;
        }
        
        .header {
            text-align: center;
            margin-bottom: 40px;
        }
        
        .header h1 {
            font-size: 2.5em;
            background: linear-gradient(135deg, 
                var(--gradient-1) 0%, 
                var(--gradient-2) 25%, 
                var(--gradient-3) 50%, 
                var(--gradient-4) 75%, 
                var(--gradient-5) 100%);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            margin-bottom: 10px;
        }
        
        .header .subtitle {
            color: #666;
            font-size: 1.1em;
        }
        
        .step {
            display: none;
        }
        
        .step.active {
            display: block;
            animation: fadeIn 0.5s;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        
        .form-group {
            margin-bottom: 25px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #333;
        }
        
        input[type="text"],
        input[type="email"],
        select {
            width: 100%;
            padding: 12px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 1em;
            transition: border-color 0.3s;
        }
        
        input:focus, select:focus {
            outline: none;
            border-color: #667eea;
        }
        
        .validation-error {
            color: #ef4444;
            font-size: 0.85em;
            margin-top: 4px;
            padding: 6px 10px;
            background: rgba(239, 68, 68, 0.08);
            border-left: 3px solid #ef4444;
            border-radius: 4px;
            animation: shake 0.3s ease-in-out;
        }
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            25% { transform: translateX(-4px); }
            75% { transform: translateX(4px); }
        }
        .field-error {
            border-color: #ef4444 !important;
            box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.2) !important;
        }
        .checkbox-group {
            margin-top: 10px;
        }
        
        .checkbox-item {
            display: flex;
            align-items: center;
            padding: 10px;
            background: #f5f5f5;
            border-radius: 6px;
            cursor: pointer;
            transition: background 0.3s;
        }
        
        .checkbox-item:hover {
            background: #e8e8e8;
        }
        
        .checkbox-item input[type="checkbox"] {
            margin-right: 10px;
        }
        
        .buttons {
            display: flex;
            justify-content: space-between;
            margin-top: 30px;
        }
        
        button {
            padding: 12px 30px;
            border: none;
            border-radius: 8px;
            font-size: 1em;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }
        
        .btn-primary {
            background: linear-gradient(135deg, 
                var(--gradient-1) 0%, 
                var(--gradient-2) 50%, 
                var(--gradient-3) 100%);
            color: white;
            position: relative;
            overflow: hidden;
        }
        
        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
        }
        
        .btn-secondary {
            background: rgba(224, 224, 224, 0.8);
            backdrop-filter: blur(10px);
            color: #333;
        }
        
        .btn-secondary:hover {
            background: rgba(208, 208, 208, 0.9);
        }

        .btn-danger {
            background: #ef4444;
            color: white;
            border: none;
            padding: 10px 24px;
            border-radius: 8px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 600;
            transition: all 0.2s;
        }

        .btn-danger:hover {
            background: #dc2626;
            transform: translateY(-1px);
        }

        .btn-danger:disabled {
            background: #9ca3af;
            cursor: not-allowed;
            transform: none;
        }

        .progress-bar {
            height: 6px;
            background: rgba(224, 224, 224, 0.5);
            border-radius: 3px;
            margin-bottom: 30px;
            overflow: hidden;
        }
        
        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg,
                var(--gradient-1) 0%, 
                var(--gradient-2) 25%, 
                var(--gradient-3) 50%, 
                var(--gradient-4) 75%, 
                var(--gradient-5) 100%);
            background-size: 200% 100%;
            animation: progressShimmer 2s ease infinite;
            transition: width 0.5s;
        }
        
        @keyframes progressShimmer {
            0% { background-position: 0% 0%; }
            50% { background-position: 100% 0%; }
            100% { background-position: 0% 0%; }
        }
        
        .alert {
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 20px;
        }
        
        .alert-info {
            background: #e3f2fd;
            border-left: 4px solid #2196f3;
            color: #1565c0;
        }
        
        .alert-warning {
            background: #fff3e0;
            border-left: 4px solid #ff9800;
            color: #e65100;
        }
        
        .installing {
            text-align: center;
        }
        
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid var(--gradient-1);
            border-radius: 50%;
            width: 50px;
            height: 50px;
            animation: spin 1s linear infinite;
            margin: 30px auto;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .log-output {
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 20px;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 0.9em;
            max-height: 400px;
            overflow-y: auto;
            margin-top: 20px;
        }
        
        .package-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0,0,0,0.1);
        }

        /* Tier Cards */
        .tier-section {
            margin-bottom: 25px;
        }
        .tier-section h3 {
            font-size: 1.1em;
            color: #333;
            margin-bottom: 12px;
            padding-bottom: 8px;
            border-bottom: 2px solid #f0f0f0;
        }
        .tier-cards {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 12px;
        }
        .tier-card {
            padding: 18px;
            border: 2px solid #e0e0e0;
            border-radius: 12px;
            cursor: pointer;
            transition: all 0.25s ease;
            background: white;
            position: relative;
        }
        .tier-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.08);
            border-color: #ccc;
        }
        .tier-card.selected {
            border-color: var(--gradient-1);
            background: linear-gradient(135deg, rgba(var(--gradient-1-rgb, 0,147,233), 0.05), rgba(var(--gradient-2-rgb, 128,208,199), 0.05));
            box-shadow: 0 4px 12px rgba(0,147,233,0.15);
        }
        .tier-card .tier-check {
            position: absolute;
            top: 10px;
            right: 10px;
            width: 22px;
            height: 22px;
            border-radius: 50%;
            background: var(--gradient-1);
            color: white;
            display: none;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            font-weight: bold;
        }
        .tier-card.selected .tier-check {
            display: flex;
        }
        .tier-card .tier-name {
            font-weight: 600;
            font-size: 1.05em;
            margin-bottom: 6px;
        }
        .tier-card .tier-desc {
            font-size: 0.88em;
            color: #666;
            line-height: 1.4;
        }
        
        /* Hamburger Menu */
        .hamburger-menu {
            position: fixed;
            top: 20px;
            left: 20px;
            z-index: 10000;
            background: rgba(255, 255, 255, 0.95);
            backdrop-filter: blur(10px);
            padding: 12px;
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
            cursor: pointer;
            transition: all 0.3s ease;
        }
        .hamburger-menu.open {
            display: none;
        }
        
        .hamburger-menu:hover {
            transform: scale(1.05);
            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
        }
        
        .hamburger-icon {
            width: 24px;
            height: 24px;
            display: flex;
            flex-direction: column;
            justify-content: space-around;
        }
        
        .hamburger-icon span {
            display: block;
            height: 3px;
            background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2));
            border-radius: 2px;
            transition: all 0.3s ease;
        }
        
        .hamburger-menu.open .hamburger-icon span:nth-child(1) {
            transform: rotate(45deg) translate(7px, 7px);
        }
        
        .hamburger-menu.open .hamburger-icon span:nth-child(2) {
            opacity: 0;
        }
        
        .hamburger-menu.open .hamburger-icon span:nth-child(3) {
            transform: rotate(-45deg) translate(7px, -7px);
        }
        
        /* Settings Panel */
        .settings-panel {
            position: fixed;
            top: 0;
            left: -450px;
            width: 450px;
            height: 100vh;
            background: rgba(255, 255, 255, 0.98);
            backdrop-filter: blur(20px);
            box-shadow: 4px 0 20px rgba(0, 0, 0, 0.2);
            transition: left 0.3s ease;
            z-index: 9999;
            overflow-y: auto;
            overflow-x: hidden;
            padding: 0;
            display: flex;
            flex-direction: column;
            scrollbar-width: thin;
        }
        .settings-panel::-webkit-scrollbar {
            width: 4px;
        }
        .settings-panel::-webkit-scrollbar-thumb {
            background: rgba(0,0,0,0.15);
            border-radius: 2px;
        }
        
        .settings-panel.open {
            left: 0;
        }
        
        .settings-header {
            padding: 20px;
            padding-top: 60px;
            background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2));
            color: white;
        }
        
        .settings-panel h2 {
            color: white;
            margin: 0 0 10px 0;
            font-size: 1.5em;
        }
        
        .settings-panel .subtitle {
            color: rgba(255, 255, 255, 0.9);
            font-size: 0.9em;
        }
        
        /* Step Navigation */
        .settings-steps {
            display: flex;
            padding: 15px 20px;
            background: rgba(0, 0, 0, 0.03);
            border-bottom: 1px solid #e0e0e0;
            overflow-x: auto;
            gap: 10px;
        }
        
        .settings-step-btn {
            padding: 8px 16px;
            background: white;
            border: 2px solid #e0e0e0;
            border-radius: 20px;
            cursor: pointer;
            white-space: nowrap;
            font-size: 0.85em;
            transition: all 0.3s ease;
            flex-shrink: 0;
        }
        
        .settings-step-btn:hover {
            border-color: var(--gradient-1);
            transform: translateY(-2px);
        }
        
        .settings-step-btn.active {
            background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2));
            color: white;
            border-color: transparent;
        }
        
        .settings-step-btn.completed {
            border-color: #10b981;
            background: #f0fdf4;
        }
        
        /* Settings Content */
        .settings-content {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
        }
        
        .settings-step-content {
            display: none;
        }
        
        .settings-step-content.active {
            display: block;
            animation: fadeIn 0.3s;
        }
        
        .settings-section {
            margin-bottom: 25px;
        }
        
        .settings-section h4 {
            color: #333;
            font-size: 1em;
            margin-bottom: 10px;
        }
        
        .settings-section p {
            color: #666;
            font-size: 0.9em;
            margin-bottom: 15px;
        }
        
        /* Theme Grid in Settings */
        .theme-grid {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 10px;
            margin-top: 10px;
        }
        
        .theme-option {
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            padding: 15px;
            cursor: pointer;
            transition: all 0.3s ease;
            text-align: center;
        }
        
        .theme-option:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }
        
        .theme-option.active {
            border-color: var(--gradient-1);
            box-shadow: 0 0 0 3px rgba(0, 147, 233, 0.2);
        }
        
        .theme-preview {
            width: 100%;
            height: 40px;
            border-radius: 6px;
            margin-bottom: 8px;
        }
        
        .theme-name {
            font-size: 0.85em;
            color: #666;
            font-weight: 600;
        }
        
        /* Prism Source Input */
        .prism-source-input {
            display: flex;
            gap: 8px;
            margin-top: 10px;
        }
        
        .prism-source-input input {
            flex: 1;
            padding: 10px;
            border: 2px solid #e0e0e0;
            border-radius: 6px;
            font-size: 0.9em;
        }
        
        .prism-source-input button {
            padding: 10px 20px;
            background: linear-gradient(135deg, var(--gradient-1), var(--gradient-2));
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
        }
        
        .prism-source-input button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
        }
        
        .prism-sources-list {
            margin-top: 15px;
        }
        
        .prism-source-item {
            background: #f5f5f5;
            padding: 10px;
            border-radius: 6px;
            margin-bottom: 8px;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        
        .prism-source-item .source-url {
            font-size: 0.85em;
            color: #666;
            font-family: 'Courier New', monospace;
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        
        .prism-source-item .remove-btn {
            background: #ef4444;
            color: white;
            border: none;
            padding: 4px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 0.8em;
            transition: all 0.2s ease;
        }
        
        .prism-source-item .remove-btn:hover {
            background: #dc2626;
        }
        
        /* Overlay for settings panel */
        .settings-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
            z-index: 9998;
        }
        
        .settings-overlay.open {
            opacity: 1;
            visibility: visible;
        }
        

    </style>
</head>
<body>
    <!-- Settings Overlay -->
    <div class="settings-overlay" id="settingsOverlay" onclick="toggleSettings()"></div>
    
    <!-- Hamburger Menu -->
    <div class="hamburger-menu" id="hamburgerMenu" onclick="toggleSettings()">
        <div class="hamburger-icon">
            <span></span>
            <span></span>
            <span></span>
        </div>
    </div>
    
    <!-- Settings Panel -->
    <div class="settings-panel" id="settingsPanel">
        <!-- Header -->
        <div class="settings-header">
            <h2>⚙️ Configure Prism</h2>
            <p class="subtitle">Set up your installation preferences</p>
        </div>
        
        <!-- Step Navigation -->
        <div class="settings-steps">
            <button class="settings-step-btn active" data-step="1" onclick="goToSettingsStep(1)">
                1. Select Prism
            </button>
            <button class="settings-step-btn" data-step="2" onclick="goToSettingsStep(2)">
                2. Package Repos
            </button>
            <button class="settings-step-btn" data-step="3" onclick="goToSettingsStep(3)">
                3. Theme
            </button>
            <button class="settings-step-btn" data-step="4" onclick="goToSettingsStep(4)">
                4. Advanced
            </button>
        </div>
        
        <!-- Settings Content -->
        <div class="settings-content">
            <!-- Step 1: Select Prism -->
            <div class="settings-step-content active" id="settingsStep1">
                <h3>🔷 Select Your Setup Prism</h3>
                <p style="color: #666; margin-bottom: 20px;">Choose which configuration prism to install. This will configure your development environment.</p>
                
                <div id="settingsPrismList" style="max-height: 400px; overflow-y: auto;">
                    <!-- Prisms will be loaded here -->
                    <p style="color: #999; text-align: center; padding: 40px;">Loading prisms...</p>
                </div>
                
                <div style="margin-top: 20px; padding: 15px; background: #f0f9ff; border-left: 4px solid #0093E9; border-radius: 4px;">
                    <p style="font-size: 0.9em; margin: 0;"><strong>💡 Tip:</strong> You can add more prism sources in the next step!</p>
                </div>
            </div>
            
            <!-- Step 2: Package Repositories -->
            <div class="settings-step-content" id="settingsStep2">
                <h3>📦 Package Repositories</h3>
                <p style="color: #666; margin-bottom: 20px;">Configure where to load prisms and packages from</p>
                
                <div class="settings-section">
                    <h4 style="font-size: 1em; margin-bottom: 10px;">🔷 Prism Sources</h4>
                    <p style="font-size: 0.9em; color: #666; margin-bottom: 15px;">Add registries or URLs to load additional setup prisms</p>
                    <div class="prism-source-input">
                        <input type="text" id="prismSourceUrl" placeholder="https://registry.example.com/prisms" />
                        <button onclick="addPrismSource()">Add</button>
                    </div>
                    <div class="prism-sources-list" id="prismSourcesList" style="margin-top: 15px;">
                        <!-- Sources populated by JS -->
                    </div>
                </div>
                
                <div class="settings-section" style="margin-top: 30px;">
                    <h4 style="font-size: 1em; margin-bottom: 10px;">📦 npm Registry</h4>
                    <p style="font-size: 0.9em; color: #666; margin-bottom: 15px;">Configure custom npm registry for corporate/air-gapped environments</p>
                    <div class="form-group">
                        <label for="settingsNpmRegistry">Registry URL</label>
                        <input type="text" id="settingsNpmRegistry" placeholder="https://registry.npmjs.org" />
                    </div>
                </div>
            </div>
            
            <!-- Step 3: Theme -->
            <div class="settings-step-content" id="settingsStep3">
                <h3>🎨 Choose Your Theme</h3>
                <p style="color: #666; margin-bottom: 20px;">Select your preferred color scheme</p>
                
                <div class="theme-grid" id="themeGrid">
                    <p style="color: #999; font-size: 0.85em;">Themes load from the selected package.</p>
                </div>
                
                <div style="margin-top: 20px; padding: 15px; background: #f0f9ff; border-left: 4px solid #0093E9; border-radius: 4px;">
                    <p style="font-size: 0.9em; margin: 0;"><strong>💡 Tip:</strong> Your theme choice is saved automatically and persists across sessions!</p>
                </div>
            </div>
            
            <!-- Step 4: Advanced -->
            <div class="settings-step-content" id="settingsStep4">
                <h3>⚙️ Advanced Configuration</h3>
                <p style="color: #666; margin-bottom: 20px;">Additional settings and information</p>
                
                <div class="settings-section">
                    <h4 style="font-size: 1em; margin-bottom: 10px;">💾 Configuration Export/Import</h4>
                    <p style="font-size: 0.9em; color: #666; margin-bottom: 15px;">Share your Prism configuration with others</p>
                    <div style="display: flex; gap: 10px;">
                        <button class="btn-secondary" onclick="exportPrismConfig()" style="flex: 1;">📤 Export Config</button>
                        <button class="btn-secondary" onclick="importPrismConfig()" style="flex: 1;">📥 Import Config</button>
                    </div>
                </div>
                
                <div class="settings-section" style="margin-top: 30px;">
                    <h4 style="font-size: 1em; margin-bottom: 10px;">🔄 Reset Configuration</h4>
                    <p style="font-size: 0.9em; color: #666; margin-bottom: 15px;">Reset all Prism settings to defaults</p>
                    <button class="btn-secondary" onclick="resetPrismConfig()" style="background: #ef4444; color: white; width: 100%;">Reset to Defaults</button>
                </div>
                
                <div class="settings-section" style="margin-top: 30px;">
                    <h4 style="font-size: 1em; margin-bottom: 10px;">ℹ️ About Prism</h4>
                    <p style="font-size: 0.85em; color: #666;">Light refracts through configuration - infinite possibilities</p>
                    <p style="font-size: 0.85em; color: #999;">Version: 1.0.0</p>
                    <p style="font-size: 0.85em; color: #999;">Architecture: Meta-Prism (Self-Configuring)</p>
                </div>
            </div>
        </div>
        
        <!-- Action Buttons -->
        <div style="padding: 20px; border-top: 1px solid #e0e0e0; background: white;">
            <div style="display: flex; gap: 10px;">
                <button class="btn-primary" onclick="toggleSettings()" style="flex: 1;">Close</button>
            </div>
        </div>
    </div>
    
    <div class="container">
        <div class="header">
            <img src="/assets/branding/prism_light_128.png" alt="Prism" id="brandingLogo" style="height: 36px; width: auto; margin-bottom: 8px;">
            <h1 id="brandingTitle" style="margin: 0;">Prism</h1>
            <p class="subtitle" id="brandingTagline">Refract complexity into clarity</p>
        </div>
        
        <div class="progress-bar">
            <div class="progress-fill" id="progressFill" style="width: 20%"></div>
        </div>
        
        <!-- Environments -->
        <div id="previousInstalls" style="display: none; margin-bottom: 20px; padding: 16px 20px; background: linear-gradient(135deg, rgba(102,126,234,0.06), rgba(118,75,162,0.06)); border: 1px solid rgba(102,126,234,0.15); border-radius: 10px;">
            <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px;">
                <h4 style="margin: 0; font-size: 0.95em; color: #444;">Your Environments</h4>
            </div>
            <div id="previousInstallsList"></div>
        </div>

        <!-- Step 1: Environment Selection (tiers from loaded prism) -->
        <div class="step active" id="step1">
            <h2 id="step1Title">Choose Your Setup</h2>
            <p id="step1Subtitle">Select the configuration that best fits your needs:</p>

            <div id="packagesList" style="margin-top: 30px;">
                <p style="color: #999; text-align: center; padding: 40px;">Loading configurations...</p>
            </div>

            <!-- Invalid packages section (hidden unless issues) -->
            <div id="invalidPackagesSection" style="margin-top: 30px; display: none;">
                <details style="padding: 15px; background: #fff3cd; border-left: 4px solid #ffc107; border-radius: 8px;">
                    <summary style="cursor: pointer; font-weight: 600; color: #856404;">
                        <span id="invalidPackagesCount">0</span> Invalid Prism(s) - Click to View
                    </summary>
                    <div id="invalidPackagesList" style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #ffeaa7;">
                        <!-- Populated by JS -->
                    </div>
                </details>
            </div>

            <div class="buttons">
                <div></div>
                <button class="btn-primary" onclick="nextStep()">Next</button>
            </div>
        </div>
        
        <!-- Step 2: User Info -->
        <div class="step" id="step2">
            <h2>Your Information</h2>
            
            <div id="userInfoFields">
                <!-- Fields populated dynamically based on selected package -->
            </div>
            
            <div class="buttons">
                <button class="btn-secondary" onclick="prevStep()">← Back</button>
                <button class="btn-primary" onclick="nextStep()">Next →</button>
            </div>
        </div>
        
        <!-- Step 3: Prism Tiers (bundled_prisms optional selections) -->
        <div class="step" id="step3">
            <h2>Configuration Tiers</h2>
            <p style="color: #666; margin-bottom: 20px;">Select your optional configuration layers. Required tiers are applied automatically.</p>

            <div id="prismTiersContainer">
                <!-- Populated dynamically by loadPrismTiers() -->
                <p style="color: #999;">Loading tier options...</p>
            </div>

            <div class="buttons">
                <button class="btn-secondary" onclick="prevStep()">← Back</button>
                <button class="btn-primary" onclick="nextStep()">Next →</button>
            </div>
        </div>
        
        <!-- Step 4: Tools -->
        <div class="step" id="step4">
            <h2>Select Tools</h2>
            <p>Choose optional tools to install (required tools are pre-selected)<br><span style="color: #999; font-size: 0.85em;">Hover over any tool for more details</span></p>
            
            <div class="checkbox-group" id="toolsList">
                <!-- Populated by JS -->
            </div>
            
            <div class="buttons">
                <button class="btn-secondary" onclick="prevStep()">← Back</button>
                <button class="btn-primary" onclick="nextStep()">Next →</button>
            </div>
        </div>
        
        <!-- Step 5: Confirm -->
        <div class="step" id="step5">
            <h2>✨ Ready to Refract!</h2>
            
            <div id="summary">
                <!-- Populated by JS -->
            </div>
            
            <!-- Configuration Validation Section -->
            <div id="configValidationSection" style="margin-top: 20px; display: none;">
                <h3>Configuration Validation</h3>
                <button class="btn-secondary" onclick="validateConfigs()" id="validateBtn">
                    🔍 Validate Configurations
                </button>
                <div id="validationResults" style="margin-top: 15px;">
                    <!-- Validation results will appear here -->
                </div>
            </div>
            
            <div class="form-group" style="margin-top: 20px;">
                <label for="targetDir">Install Directory</label>
                <p style="font-size: 0.85em; color: #666; margin: 5px 0;">Where to install the configuration files</p>
                <input type="text" id="targetDir" placeholder="~/prism-config" value="~/prism-config" style="font-family: monospace;">
            </div>

            <div class="buttons">
                <button class="btn-secondary" onclick="prevStep()">← Back</button>
                <button class="btn-primary" onclick="startInstall()">Install</button>
            </div>
        </div>
        
        <!-- Step 6: Installing -->
        <div class="step" id="step6">
            <div class="installing">
                <h2 id="installHeading">Installing...</h2>
                <div class="spinner" id="installSpinner"></div>
                <p id="installStatus">Setting up your environment...</p>

                <div class="log-output" id="logOutput">
                    <div>Starting installation...</div>
                </div>

                <button class="btn-danger" id="cancelInstallBtn" onclick="cancelInstall()" style="margin-top: 16px; display: inline-block;">
                    Cancel Installation
                </button>
            </div>
        </div>
        
        <!-- Step 7: Complete -->
        <div class="step" id="step7">
            <div style="text-align: center;">
                <h2>All Done!</h2>
                <p style="margin: 20px 0;">Your development environment is ready.</p>

                <div id="completionDetails" class="alert alert-info" style="text-align: left;">
                    <!-- Populated dynamically by showCompletion() -->
                </div>

                <div id="postInstallMessage" style="display: none; text-align: left; margin-top: 15px; padding: 20px; background: #f8f9fa; border-radius: 8px; white-space: pre-wrap; font-size: 0.95em; color: #333;">
                </div>

                <div style="margin-top: 20px; display: flex; gap: 12px; justify-content: center;">
                    <button class="btn-primary" onclick="location.reload()">Start Over</button>
                    <button class="btn-danger" onclick="rollbackFromUI()">Rollback Installation</button>
                </div>
            </div>
        </div>
    </div>
    
    <script>
        // ========================================
        // PRISM CONFIGURATION (Meta-Prism)
        // ========================================
        
        // Default Prism Configuration
        const DEFAULT_PRISM_CONFIG = {
            theme: null,
            sources: [
                { url: 'local', name: 'Built-in Prisms', type: 'local' }
            ],
            npmRegistry: '',
            unpkgUrl: ''
        };
        
        // Load Prism Configuration
        function loadPrismConfig() {
            const saved = localStorage.getItem('prismConfig');
            return saved ? JSON.parse(saved) : DEFAULT_PRISM_CONFIG;
        }
        
        // Save Prism Configuration
        function savePrismConfig(config) {
            localStorage.setItem('prismConfig', JSON.stringify(config));
        }
        
        // Current config
        let prismConfig = loadPrismConfig();
        let selectedPackage = null;
        
        // ========================================
        // SETTINGS PANEL
        // ========================================
        
        let currentSettingsStep = 1;
        
        function toggleSettings() {
            const panel = document.getElementById('settingsPanel');
            const overlay = document.getElementById('settingsOverlay');
            const hamburger = document.getElementById('hamburgerMenu');
            
            const isOpening = !panel.classList.contains('open');
            
            panel.classList.toggle('open');
            overlay.classList.toggle('open');
            hamburger.classList.toggle('open');
            
            // If opening, load prisms into step 1
            if (isOpening) {
                loadPrismsIntoSettings();
            }
        }
        
        function goToSettingsStep(stepNum) {
            currentSettingsStep = stepNum;
            
            // Update step buttons
            document.querySelectorAll('.settings-step-btn').forEach(btn => {
                const btnStep = parseInt(btn.dataset.step);
                if (btnStep === stepNum) {
                    btn.classList.add('active');
                } else {
                    btn.classList.remove('active');
                }
            });
            
            // Update step content
            document.querySelectorAll('.settings-step-content').forEach(content => {
                content.classList.remove('active');
            });
            document.getElementById('settingsStep' + stepNum).classList.add('active');
        }
        
        // Cache for environment counts per package
        let _envCounts = {};

        async function loadEnvCounts() {
            try {
                const resp = await fetch('/api/history');
                const data = await resp.json();
                _envCounts = {};
                (data.installs || []).forEach(inst => {
                    const pkg = inst.package || '';
                    _envCounts[pkg] = (_envCounts[pkg] || 0) + 1;
                });
            } catch (e) { /* ignore */ }
        }

        function loadPrismsIntoSettings() {
            const container = document.getElementById('settingsPrismList');

            if (typeof packages !== 'undefined' && packages.length > 0) {
                let html = '';
                const sorted = [...packages].sort((a, b) => {
                    if (a.name === selectedPackage) return -1;
                    if (b.name === selectedPackage) return 1;
                    return (b.default ? 1 : 0) - (a.default ? 1 : 0);
                });
                sorted.forEach(pkg => {
                    const isSelected = selectedPackage === pkg.name;
                    const defaultBadge = pkg.default ? '<span style="display:inline-block;background:var(--gradient-1);color:white;font-size:0.7em;padding:2px 8px;border-radius:10px;margin-left:8px;vertical-align:middle;">Default</span>' : '';
                    const envCount = _envCounts[pkg.name] || 0;
                    const envBadge = envCount > 0 ? `<span style="display:inline-block;background:#10b981;color:white;font-size:0.7em;padding:2px 8px;border-radius:10px;margin-left:6px;vertical-align:middle;">${envCount} env${envCount > 1 ? 's' : ''}</span>` : '';
                    html += `
                        <div onclick="selectPrismFromSettings('${pkg.name}')" style="margin-bottom: 10px; padding: 14px 16px; border: 2px solid ${isSelected ? 'var(--gradient-1)' : '#e0e0e0'}; border-radius: 10px; cursor: pointer; transition: all 0.2s ease; background: ${isSelected ? 'rgba(0,147,233,0.04)' : 'white'};">
                            <div style="display: flex; align-items: center; justify-content: space-between;">
                                <div>
                                    <span style="font-weight: 600; font-size: 1.05em;">${pkg.title}</span>${defaultBadge}${envBadge}
                                    <div style="font-size: 0.85em; color: #888; margin-top: 4px;">${pkg.description}</div>
                                </div>
                                ${isSelected ? '<span style="color: var(--gradient-1); font-size: 1.2em;">&#10003;</span>' : ''}
                            </div>
                        </div>
                    `;
                });
                container.innerHTML = html;
            } else {
                container.innerHTML = '<p style="color: #999; text-align: center; padding: 40px;">Loading prisms...</p>';
            }
        }
        
        async function selectPrismFromSettings(prismName) {
            await selectPackage(prismName);
            loadPrismsIntoSettings();
        }
        
        function applySettingsAndContinue() {
            // Save all settings
            const npmReg = document.getElementById('settingsNpmRegistry').value.trim();
            if (npmReg) {
                prismConfig.npmRegistry = npmReg;
            }
            // Preserve user's theme selection across package reload
            const userTheme = prismConfig.theme;
            savePrismConfig(prismConfig);

            // Close settings panel
            toggleSettings();

            // Reload package config (applies branding, tiers, etc.) without resetting theme
            if (selectedPackage) {
                selectPackage(selectedPackage, false);
            }
        }
        
        function exportPrismConfig() {
            const config = JSON.stringify(prismConfig, null, 2);
            const blob = new Blob([config], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'prism-config.json';
            a.click();
            URL.revokeObjectURL(url);
        }
        
        function importPrismConfig() {
            const input = document.createElement('input');
            input.type = 'file';
            input.accept = 'application/json';
            input.onchange = (e) => {
                const file = e.target.files[0];
                if (file) {
                    const reader = new FileReader();
                    reader.onload = (event) => {
                        try {
                            const config = JSON.parse(event.target.result);
                            prismConfig = config;
                            savePrismConfig(config);
                            
                            // Apply theme
                            document.documentElement.setAttribute('data-theme', config.theme);
                            
                            // Reload UI
                            location.reload();
                        } catch (err) {
                            alert('Invalid config file: ' + err.message);
                        }
                    };
                    reader.readAsText(file);
                }
            };
            input.click();
        }
        
        function resetPrismConfig() {
            if (confirm('Are you sure you want to reset all Prism settings to defaults? This cannot be undone.')) {
                prismConfig = {...DEFAULT_PRISM_CONFIG};
                savePrismConfig(prismConfig);
                location.reload();
            }
        }
        
        // Theme gradient definitions — populated entirely from the package config API
        let _themeGradients = {};

        function selectTheme(themeName) {
            document.documentElement.setAttribute('data-theme', themeName);

            // Apply gradients via inline styles — works for both built-in and custom
            const gradients = _themeGradients[themeName];
            if (gradients) {
                const root = document.documentElement.style;
                root.setProperty('--gradient-1', gradients.gradient_1);
                root.setProperty('--gradient-2', gradients.gradient_2);
                root.setProperty('--gradient-3', gradients.gradient_3 || gradients.gradient_1);
                root.setProperty('--gradient-4', gradients.gradient_4 || gradients.gradient_2);
                root.setProperty('--gradient-5', gradients.gradient_5 || gradients.gradient_1);
            }

            // Update active state in settings
            document.querySelectorAll('.theme-option').forEach(opt => {
                if (opt.dataset.theme === themeName) {
                    opt.classList.add('active');
                } else {
                    opt.classList.remove('active');
                }
            });

            // Save to config
            prismConfig.theme = themeName;
            // Save per-package theme
            if (selectedPackage) {
                if (!prismConfig.packageThemes) prismConfig.packageThemes = {};
                prismConfig.packageThemes[selectedPackage] = themeName;
            }
            // Save custom gradients for reload
            if (gradients) {
                prismConfig.customGradients = gradients;
            }
            savePrismConfig(prismConfig);
        }

        function renderThemeGrid(themes, currentTheme) {
            const grid = document.getElementById('themeGrid');
            if (!grid || !themes || themes.length === 0) return;

            // Cache custom theme gradients and inject CSS
            themes.forEach(t => {
                if (t.gradient_1) {
                    _themeGradients[t.id] = {
                        gradient_1: t.gradient_1,
                        gradient_2: t.gradient_2,
                        gradient_3: t.gradient_3,
                        gradient_4: t.gradient_4,
                        gradient_5: t.gradient_5,
                    };
                }
                if (t.gradient_1 && !document.querySelector(`style[data-theme-css="${t.id}"]`)) {
                    const style = document.createElement('style');
                    style.setAttribute('data-theme-css', t.id);
                    style.textContent = `[data-theme="${t.id}"] {
                        --gradient-1: ${t.gradient_1};
                        --gradient-2: ${t.gradient_2};
                        --gradient-3: ${t.gradient_3 || t.gradient_1};
                        --gradient-4: ${t.gradient_4 || t.gradient_2};
                        --gradient-5: ${t.gradient_5 || t.gradient_1};
                    }`;
                    document.head.appendChild(style);
                }
            });

            grid.innerHTML = themes.map(t => {
                const isActive = t.id === currentTheme ? ' active' : '';
                const previewStyle = t.gradient_1
                    ? `background: linear-gradient(135deg, ${t.gradient_1}, ${t.gradient_2});`
                    : '';
                return `<div class="theme-option${isActive}" data-theme="${t.id}" onclick="selectTheme('${t.id}')">
                    <div class="theme-preview ${t.id}" style="${previewStyle}"></div>
                    <div class="theme-name">${t.name}</div>
                </div>`;
            }).join('');
        }
        
        function addPrismSource() {
            const input = document.getElementById('prismSourceUrl');
            const url = input.value.trim();
            
            if (!url) {
                alert('Please enter a valid URL');
                return;
            }
            
            // Add to config
            prismConfig.sources.push({
                url: url,
                name: url,
                type: 'remote'
            });
            savePrismConfig(prismConfig);
            
            // Clear input
            input.value = '';
            
            // Refresh UI
            renderPrismSources();
            
            // Reload prisms from all sources
            loadPackages();
        }
        
        function removePrismSource(index) {
            prismConfig.sources.splice(index, 1);
            savePrismConfig(prismConfig);
            renderPrismSources();
            loadPackages();
        }
        
        function renderPrismSources() {
            const list = document.getElementById('prismSourcesList');
            list.innerHTML = '';
            
            prismConfig.sources.forEach((source, index) => {
                if (source.type === 'local') {
                    list.innerHTML += `
                        <div class="prism-source-item">
                            <span class="source-url">🔷 ${source.name}</span>
                            <span style="font-size: 0.75em; color: #10b981; font-weight: 600;">DEFAULT</span>
                        </div>
                    `;
                } else {
                    list.innerHTML += `
                        <div class="prism-source-item">
                            <span class="source-url">${source.url}</span>
                            <button class="remove-btn" onclick="removePrismSource(${index})">Remove</button>
                        </div>
                    `;
                }
            });
        }
        
        function saveRegistryConfig() {
            const el = document.getElementById('settingsNpmRegistry');
            const npmRegistry = el ? el.value.trim() : '';

            prismConfig.npmRegistry = npmRegistry;
            savePrismConfig(prismConfig);

            alert('Registry configuration saved!');
        }
        
        // Initialize Prism Configuration on load
        (function() {
            // Restore custom gradient cache if saved
            if (prismConfig.customGradients) {
                _themeGradients[prismConfig.theme] = prismConfig.customGradients;
            }

            // Apply saved theme (handles both built-in and custom)
            if (prismConfig.theme) {
                selectTheme(prismConfig.theme);
            }
            
            // Render prism sources
            renderPrismSources();
            
            // Set registry values (both in main UI and settings)
            if (prismConfig.npmRegistry) {
                const npmReg = document.getElementById('npmRegistry');
                if (npmReg) npmReg.value = prismConfig.npmRegistry;
                
                const settingsNpmReg = document.getElementById('settingsNpmRegistry');
                if (settingsNpmReg) settingsNpmReg.value = prismConfig.npmRegistry;
            }
        })();
        
        // ========================================
        // INSTALLATION FLOW
        // ========================================
        
        let currentStep = 1;
        const totalSteps = 7;
        let packages = [];
        let hasOrganizations = false;
        let hasTools = true;
        
        // Determine which steps are active
        function getNextActiveStep(current) {
            let next = current + 1;
            
            // Skip organization step if no organizations
            if (next === 3 && !hasOrganizations) next++;
            // Skip tools step if no tools
            if (next === 4 && !hasTools) next++;
            
            return next;
        }
        
        function getPrevActiveStep(current) {
            let prev = current - 1;
            
            // Skip tools step if no tools (going backwards)
            if (prev === 4 && !hasTools) prev--;
            // Skip organization step if no organizations (going backwards)
            if (prev === 3 && !hasOrganizations) prev--;
            
            return prev;
        }
        
        function updateProgress() {
            const progress = (currentStep / totalSteps) * 100;
            document.getElementById('progressFill').style.width = progress + '%';
        }
        
        function showValidationError(message, targetEl) {
            // Remove any existing error
            clearValidationErrors();
            const errorDiv = document.createElement('div');
            errorDiv.className = 'validation-error';
            errorDiv.textContent = message;
            if (targetEl) {
                targetEl.classList.add('field-error');
                targetEl.parentElement.appendChild(errorDiv);
                targetEl.focus();
            } else {
                // Show at top of current step
                const step = document.getElementById('step' + currentStep);
                step.insertBefore(errorDiv, step.children[1]);
            }
        }

        function clearValidationErrors() {
            document.querySelectorAll('.validation-error').forEach(el => el.remove());
            document.querySelectorAll('.field-error').forEach(el => el.classList.remove('field-error'));
        }

        function nextStep() {
            clearValidationErrors();

            // Validate package selection and tier choices on step 1
            if (currentStep === 1) {
                if (!selectedPackage) {
                    showValidationError('Select a prism to continue');
                    return;
                }
                const tierSections = document.querySelectorAll('.tier-section');
                if (tierSections.length > 0 && Object.keys(selectedSubPrisms).length === 0) {
                    showValidationError('Select at least one option from the configurations above');
                    return;
                }
            }

            // Validate required user info fields on step 2
            if (currentStep === 2) {
                const allFields = document.querySelectorAll('#userInfoFields input, #userInfoFields select');
                for (const field of allFields) {
                    if (field.required && !field.value.trim()) {
                        showValidationError('This field is required', field);
                        return;
                    }
                    if (field.type === 'email' && field.value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(field.value)) {
                        showValidationError('Enter a valid email address', field);
                        return;
                    }
                    const pattern = field.getAttribute('data-pattern');
                    if (pattern && field.value) {
                        const regex = new RegExp(pattern);
                        if (!regex.test(field.value)) {
                            const msg = field.getAttribute('data-pattern-message') || 'Invalid format';
                            showValidationError(msg, field);
                            return;
                        }
                    }
                }
            }

            document.getElementById('step' + currentStep).classList.remove('active');
            const next = getNextActiveStep(currentStep);
            currentStep = next;
            document.getElementById('step' + currentStep).classList.add('active');
            updateProgress();
            
            // Load data for specific steps
            if (currentStep === 2) loadUserInfoFields();
            if (currentStep === 3) loadPrismTiers();
            if (currentStep === 4) loadTools();
            if (currentStep === 5) showSummary();
        }
        
        function prevStep() {
            document.getElementById('step' + currentStep).classList.remove('active');
            const prev = getPrevActiveStep(currentStep);
            currentStep = prev;
            document.getElementById('step' + currentStep).classList.add('active');
            updateProgress();
        }
        
        // Track selected sub-prisms: { tierName: subPrismId }
        const selectedSubPrisms = {};

        async function loadPrismTiers() {
            const container = document.getElementById('prismTiersContainer');

            try {
                const response = await fetch(`/api/package/${selectedPackage}/tiers`);
                const data = await response.json();

                if (data.error || !data.optional_tiers || data.optional_tiers.length === 0) {
                    // No optional tiers — skip step automatically
                    hasOrganizations = false;
                    nextStep();
                    return;
                }

                hasOrganizations = true;
                container.innerHTML = '';

                data.optional_tiers.forEach(tier => {
                    const tierDiv = document.createElement('div');
                    tierDiv.className = 'form-group';

                    const label = document.createElement('label');
                    label.textContent = tier.label + (tier.required ? ' *' : '');
                    label.setAttribute('for', 'tier_' + tier.name);

                    const select = document.createElement('select');
                    select.id = 'tier_' + tier.name;
                    select.setAttribute('data-tier', tier.name);

                    const noneOpt = document.createElement('option');
                    noneOpt.value = '';
                    noneOpt.textContent = '(None)';
                    select.appendChild(noneOpt);

                    tier.options.forEach(opt => {
                        const o = document.createElement('option');
                        o.value = opt.id;
                        o.textContent = opt.name + (opt.description ? ' — ' + opt.description : '');
                        select.appendChild(o);
                    });

                    select.addEventListener('change', () => {
                        if (select.value) {
                            selectedSubPrisms[tier.name] = select.value;
                        } else {
                            delete selectedSubPrisms[tier.name];
                        }
                    });

                    tierDiv.appendChild(label);
                    tierDiv.appendChild(select);
                    container.appendChild(tierDiv);
                });
            } catch (err) {
                container.innerHTML = `<p style="color:#ef4444;">Failed to load tiers: ${err.message}</p>`;
            }
        }
        
        async function loadTools() {
            // Build query params from selected sub-prisms
            const params = new URLSearchParams(selectedSubPrisms);
            const response = await fetch(`/api/package/${selectedPackage}/tools?${params}`);
            const data = await response.json();

            hasTools = data.has_tools;

            if (!hasTools) {
                nextStep();
                return;
            }

            const toolsList = document.getElementById('toolsList');
            toolsList.innerHTML = '';

            if (data.tools && data.tools.length > 0) {
                // Group tools by category (from API, not hardcoded)
                const groups = {};
                const categoryOrder = [];
                data.tools.forEach(tool => {
                    const cat = tool.category || '';
                    if (!groups[cat]) {
                        groups[cat] = [];
                        categoryOrder.push(cat);
                    }
                    groups[cat].push(tool);
                });

                categoryOrder.forEach(cat => {
                    let sectionHTML = '';
                    if (cat) {
                        sectionHTML += `<h4 style="margin: 20px 0 10px; color: var(--gradient-1, #667eea); font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.1em; border-bottom: 1px solid rgba(102,126,234,0.2); padding-bottom: 6px;">${cat.charAt(0).toUpperCase() + cat.slice(1)}</h4>`;
                    }
                    sectionHTML += `<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px;">`;
                    groups[cat].forEach(tool => {
                        const checked = tool.required ? 'checked disabled' : '';
                        sectionHTML += `
                            <div class="checkbox-item" style="display: flex; align-items: center; gap: 10px; padding: 8px 0;" title="${tool.description || ''}">
                                <input type="checkbox" id="tool_${tool.id}" name="${tool.id}" ${checked}>
                                <label for="tool_${tool.id}" style="flex: 1; cursor: pointer;">
                                    <strong>${tool.name}</strong>
                                    ${tool.summary ? `<span style="color: #888; font-size: 0.85em;"> — ${tool.summary}</span>` : ''}
                                    ${tool.required ? '<span style="color: var(--gradient-1); font-size: 0.8em;"> (required)</span>' : ''}
                                </label>
                            </div>
                        `;
                    });
                    sectionHTML += `</div>`;
                    toolsList.innerHTML += sectionHTML;
                });
            }
        }
        
        async function showSummary() {
            // Fetch package metadata to know what to show
            const metadataResponse = await fetch(`/api/package/${selectedPackage}/metadata`);
            const metadata = await metadataResponse.json();
            
            // Collect all user info field values
            const userInfoFields = document.querySelectorAll('#userInfoFields input, #userInfoFields select');
            let userInfoHTML = '';
            userInfoFields.forEach(el => {
                if (el.value) {
                    const group = el.closest('.form-group');
                    const label = group?.querySelector('label')?.textContent.replace('*', '').trim() || el.name;
                    userInfoHTML += `<p><strong>${label}:</strong> ${el.value}</p>`;
                }
            });
            
            // Build summary based on what this prism actually has
            let summaryHTML = `
                <div style="background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(240, 147, 251, 0.05) 100%); padding: 20px; border-radius: 12px; border: 2px solid transparent; background-clip: padding-box; position: relative;">
                    <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 25%, #f093fb 50%, #4facfe 75%, #00f2fe 100%); border-radius: 10px; opacity: 0.1; z-index: -1;"></div>
                    <h3 style="margin-top: 0; background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #f093fb 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;">🔷 ${metadata.display_name || selectedPackage}</h3>
                    ${metadata.description ? `<p style="color: #666; margin-bottom: 20px;">${metadata.description}</p>` : ''}
                    <hr style="border-color: rgba(102, 126, 234, 0.2);">
            `;
            
            // User Information section (always shown if there are fields)
            if (userInfoHTML) {
                summaryHTML += `
                    <h4>👤 User Information:</h4>
                    <div style="background: white; padding: 15px; border-radius: 6px; margin-bottom: 15px;">
                        ${userInfoHTML}
                    </div>
                `;
            }
            
            // Configuration Tiers section
            if (Object.keys(selectedSubPrisms).length > 0) {
                let tierRows = '';
                for (const [tierName, subId] of Object.entries(selectedSubPrisms)) {
                    const tierLabel = tierName.charAt(0).toUpperCase() + tierName.slice(1).replace(/_/g, ' ');
                    // Look up the friendly name from the tier cards
                    const card = document.querySelector(`.tier-card.selected[onclick*="'${subId}'"]`);
                    const label = card ? card.querySelector('.tier-name')?.textContent || subId : subId;
                    tierRows += `<p><strong>${tierLabel}:</strong> ${label}</p>`;
                }
                summaryHTML += `
                    <h4>Configuration:</h4>
                    <div style="background: white; padding: 15px; border-radius: 6px; margin-bottom: 15px;">
                        ${tierRows}
                    </div>
                `;
            }

            // Tools section (only if package has tools)
            if (metadata.has_tools) {
                const toolCheckboxes = document.querySelectorAll('#toolsList input[type="checkbox"]:checked');
                const selectedTools = Array.from(toolCheckboxes).map(cb => cb.nextElementSibling?.textContent || '').filter(t => t);
                
                summaryHTML += `
                    <h4>🛠️ Tools:</h4>
                    <div style="background: white; padding: 15px; border-radius: 6px; margin-bottom: 15px;">
                        ${selectedTools.length > 0 ? 
                            `<p><strong>${selectedTools.length} tool(s) selected:</strong> ${selectedTools.join(', ')}</p>` : 
                            `<p style="color: #999;"><em>No tools selected</em></p>`
                        }
                    </div>
                `;
            }
            
            summaryHTML += '</div>';
            
            document.getElementById('summary').innerHTML = summaryHTML;
            
            // Show validation section
            document.getElementById('configValidationSection').style.display = 'block';
        }
        
        async function validateConfigs() {
            const btn = document.getElementById('validateBtn');
            const resultsDiv = document.getElementById('validationResults');
            
            // Show loading state
            btn.disabled = true;
            btn.textContent = '⏳ Validating...';
            resultsDiv.innerHTML = '<p style="color: #666;">Validating prism...</p>';
            
            try {
                const response = await fetch(`/api/package/${selectedPackage}/validate-configs`);
                const data = await response.json();
                
                if (data.error) {
                    resultsDiv.innerHTML = `
                        <div class="alert alert-warning">
                            <strong>❌ Validation Error</strong><br>
                            ${data.error}
                        </div>
                    `;
                    btn.disabled = false;
                    btn.textContent = '🔍 Validate Configurations';
                    return;
                }
                
                const summary = data.summary;
                
                if (data.valid) {
                    // All configs valid
                    resultsDiv.innerHTML = `
                        <div class="alert alert-info" style="background: #d4edda; border-color: #c3e6cb; color: #155724;">
                            <strong>✅ Prism Valid!</strong><br>
                            <div style="margin-top: 10px; font-size: 0.9em;">
                                📊 Validated ${summary.total_files} file(s)<br>
                                ${summary.total_warnings > 0 ? `⚠️ ${summary.total_warnings} warning(s) - review recommended` : ''}
                            </div>
                        </div>
                    `;
                } else {
                    // Some configs invalid
                    let errorDetails = '';
                    if (data.results) {
                        data.results.forEach(result => {
                            if (!result.valid) {
                                errorDetails += `
                                    <div style="margin-top: 10px; padding: 10px; background: #f8d7da; border-left: 3px solid #dc3545; border-radius: 4px;">
                                        <strong>📄 ${result.file}</strong>
                                        <ul style="margin: 5px 0 0 20px; font-size: 0.9em;">
                                            ${result.errors.map(err => `<li>${err}</li>`).join('')}
                                        </ul>
                                    </div>
                                `;
                            }
                        });
                    }
                    
                    resultsDiv.innerHTML = `
                        <div class="alert alert-warning" style="background: #fff3cd; border-color: #ffc107; color: #856404;">
                            <strong>⚠️ Configuration Validation Failed</strong><br>
                            <div style="margin-top: 10px; font-size: 0.9em;">
                                ❌ ${summary.invalid_files} of ${summary.total_files} files have errors<br>
                                📋 ${summary.total_errors} error(s) found
                            </div>
                            <details style="margin-top: 15px;">
                                <summary style="cursor: pointer; font-weight: 600;">📋 View Error Details</summary>
                                ${errorDetails}
                            </details>
                            <div style="margin-top: 15px; padding: 10px; background: #fff; border-radius: 4px;">
                                <strong>🔧 What to do:</strong><br>
                                These errors won't prevent installation, but may cause issues.<br>
                                Contact your admin or fix the prism files before installing.
                            </div>
                        </div>
                    `;
                }
            } catch (error) {
                resultsDiv.innerHTML = `
                    <div class="alert alert-warning">
                        <strong>❌ Failed to validate</strong><br>
                        ${error.message}
                    </div>
                `;
            }
            
            // Re-enable button
            btn.disabled = false;
            btn.textContent = '🔍 Validate Configurations';
        }
        
        let currentInstallId = null;

        async function startInstall() {
            currentStep = 6;
            document.querySelectorAll('.step').forEach(s => s.classList.remove('active'));
            document.getElementById('step6').classList.add('active');
            updateProgress();

            const logOutput = document.getElementById('logOutput');
            const cancelBtn = document.getElementById('cancelInstallBtn');
            const heading = document.getElementById('installHeading');
            const spinner = document.getElementById('installSpinner');

            cancelBtn.style.display = 'inline-block';
            cancelBtn.disabled = false;
            heading.textContent = 'Installing...';
            spinner.style.display = 'block';

            // Collect all form data
            const userInfo = {};
            document.querySelectorAll('#userInfoFields input, #userInfoFields select').forEach(el => {
                if (el.value) {
                    userInfo[el.name] = el.value;
                }
            });

            const registryEl = document.getElementById('settingsNpmRegistry');
            const registry = registryEl ? registryEl.value || null : null;
            const unpkgUrl = prismConfig.unpkgUrl || null;

            logOutput.innerHTML = '<div>Starting installation...</div>';

            // Collect selected tools from checkboxes
            const toolsSelected = [];
            document.querySelectorAll('#toolsList input[type="checkbox"]:checked').forEach(cb => {
                toolsSelected.push(cb.name);
            });

            const payload = {
                package: selectedPackage,
                userInfo: userInfo,
                registry: registry,
                unpkgUrl: unpkgUrl,
                selectedSubPrisms: selectedSubPrisms,
                toolsSelected: toolsSelected,
                targetDir: document.getElementById('targetDir').value || '~/prism-config'
            };

            try {
                // Try SSE streaming first
                const response = await fetch('/api/install/stream', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(payload)
                });

                if (!response.ok || !response.body) {
                    // Fallback to regular install
                    await fallbackInstall(payload, logOutput, cancelBtn, heading, spinner);
                    return;
                }

                const reader = response.body.getReader();
                const decoder = new TextDecoder();
                let buffer = '';

                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    buffer += decoder.decode(value, { stream: true });
                    const lines = buffer.split('\n');
                    buffer = lines.pop() || '';

                    for (const line of lines) {
                        if (!line.startsWith('data: ')) continue;
                        const data = JSON.parse(line.slice(6));

                        if (data.type === 'started') {
                            currentInstallId = data.install_id;
                        } else if (data.type === 'progress') {
                            appendLog(logOutput, data.message, data.level);
                        } else if (data.type === 'complete') {
                            cancelBtn.style.display = 'none';
                            spinner.style.display = 'none';
                            appendLog(logOutput, 'Installation complete!', 'success');
                            if (data.workspace) {
                                logOutput.innerHTML += `<div style="margin-top: 10px;">Workspace: ${data.workspace}</div>`;
                            }
                            await new Promise(r => setTimeout(r, 1000));
                            currentStep = 7;
                            document.getElementById('step6').classList.remove('active');
                            document.getElementById('step7').classList.add('active');
                            updateProgress();
                            showCompletion(data);
                        } else if (data.type === 'cancelled') {
                            spinner.style.display = 'none';
                            heading.textContent = 'Installation Cancelled';
                            cancelBtn.style.display = 'none';
                            appendLog(logOutput, 'Installation cancelled — changes rolled back.', 'warning');
                            if (data.rollback) {
                                for (const r of data.rollback) {
                                    const level = r.success ? 'success' : 'warning';
                                    appendLog(logOutput, `Rollback ${r.action}: ${r.detail}`, level);
                                }
                            }
                            showRetryButtons(logOutput);
                        } else if (data.type === 'error') {
                            spinner.style.display = 'none';
                            heading.textContent = 'Installation Failed';
                            cancelBtn.style.display = 'none';
                            appendLog(logOutput, data.error, 'error');
                            if (data.rollback) {
                                appendLog(logOutput, 'Auto-rollback executed:', 'warning');
                                for (const r of data.rollback) {
                                    const level = r.success ? 'success' : 'warning';
                                    appendLog(logOutput, `  ${r.action}: ${r.detail}`, level);
                                }
                            }
                            showRetryButtons(logOutput);
                        }
                    }
                }
            } catch (error) {
                // Fallback to regular install on SSE failure
                await fallbackInstall(payload, logOutput, cancelBtn, heading, spinner);
            }

            currentInstallId = null;
        }

        async function fallbackInstall(payload, logOutput, cancelBtn, heading, spinner) {
            cancelBtn.style.display = 'none';
            try {
                const response = await fetch('/api/install', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify(payload)
                });
                const result = await response.json();

                if (result.progress) {
                    for (let msg of result.progress) {
                        appendLog(logOutput, msg.message, msg.level);
                        await new Promise(r => setTimeout(r, 100));
                    }
                }

                if (result.success) {
                    spinner.style.display = 'none';
                    appendLog(logOutput, 'Installation complete!', 'success');
                    await new Promise(r => setTimeout(r, 1000));
                    currentStep = 7;
                    document.getElementById('step6').classList.remove('active');
                    document.getElementById('step7').classList.add('active');
                    updateProgress();
                    showCompletion(result);
                } else {
                    spinner.style.display = 'none';
                    heading.textContent = 'Installation Failed';
                    appendLog(logOutput, result.error, 'error');
                }
            } catch (error) {
                spinner.style.display = 'none';
                heading.textContent = 'Installation Failed';
                appendLog(logOutput, error.message, 'error');
            }
        }

        function appendLog(logOutput, message, level) {
            const emoji = {'success': '+', 'error': 'x', 'warning': '!', 'info': 'i'}[level] || 'i';
            const color = {'success': '#10b981', 'error': '#ef4444', 'warning': '#f59e0b', 'info': '#3b82f6'}[level] || '#3b82f6';
            logOutput.innerHTML += `<div style="color: ${color};">[${emoji}] ${message}</div>`;
            logOutput.scrollTop = logOutput.scrollHeight;
        }

        function showRetryButtons(logOutput) {
            // Remove any existing retry buttons
            const existing = document.getElementById('retryButtons');
            if (existing) existing.remove();

            const container = document.createElement('div');
            container.id = 'retryButtons';
            container.style.cssText = 'margin-top: 20px; display: flex; gap: 12px;';
            container.innerHTML = `
                <button class="btn-primary" onclick="goToStep(5)">← Back to Summary</button>
                <button class="btn-secondary" onclick="goToStep(1)">Start Over</button>
            `;
            logOutput.parentElement.appendChild(container);
        }

        async function rollbackFromUI() {
            const workspace = document.getElementById('targetDir')?.value || '';
            if (!confirm('This will undo the entire installation — uninstall tools, remove directories, and restore git config. Continue?')) return;

            const btn = event.target;
            btn.disabled = true;
            btn.textContent = 'Rolling back...';

            try {
                const resp = await fetch('/api/rollback', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ workspace: workspace })
                });
                const data = await resp.json();
                if (data.success) {
                    btn.textContent = 'Rolled back';
                    btn.style.background = '#10b981';
                    const details = document.getElementById('completionDetails');
                    if (details) {
                        details.innerHTML = `<h4>Rollback Complete</h4><p>${data.actions_undone} actions reversed.</p>`;
                    }
                } else {
                    btn.textContent = 'Rollback failed';
                    alert(data.error || 'Rollback failed');
                    btn.disabled = false;
                }
            } catch (e) {
                btn.textContent = 'Rollback failed';
                btn.disabled = false;
            }
        }

        function goToStep(step) {
            document.querySelectorAll('.step').forEach(s => s.classList.remove('active'));
            currentStep = step;
            document.getElementById('step' + step).classList.add('active');
            updateProgress();
        }

        async function cancelInstall() {
            if (!currentInstallId) return;
            const btn = document.getElementById('cancelInstallBtn');
            btn.disabled = true;
            btn.textContent = 'Cancelling...';

            try {
                await fetch('/api/install/cancel', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ install_id: currentInstallId })
                });
            } catch (e) {
                // SSE stream will handle the result
            }
        }
        
        function showCompletion(result) {
            const details = document.getElementById('completionDetails');
            const targetDir = document.getElementById('targetDir').value || '~/prism-config';
            const workspace = result.workspace || targetDir;

            let html = '<h3>What was set up:</h3><ul style="margin-left: 20px; margin-top: 10px;">';
            html += `<li>Configuration files installed to <code>${workspace}</code></li>`;

            // Show what the progress log tells us happened
            const progress = result.progress || [];
            const hasGit = progress.some(p => p.step === 'git_config' && p.level === 'success');
            const hasSSH = progress.some(p => p.step === 'ssh_keys' && p.level === 'success');
            const hasTools = progress.some(p => p.step === 'tools' && p.level === 'success');
            const hasRepos = progress.some(p => p.step === 'repositories' && p.message && !p.message.includes('No repositories'));

            if (hasGit) html += '<li>Git configured with your credentials</li>';
            if (hasSSH) html += '<li>SSH key generated (check <code>~/.ssh/</code>)</li>';
            if (hasTools) html += '<li>Development tools installed</li>';
            if (hasRepos) html += '<li>Repositories cloned</li>';

            html += '</ul>';
            details.innerHTML = html;

            // Show post-install message from the install progress if present
            const postMsg = progress.find(p => p.step === 'finalize' && p.message && p.message.length > 50);
            if (postMsg) {
                const el = document.getElementById('postInstallMessage');
                el.textContent = postMsg.message;
                el.style.display = 'block';
            }
        }

        // Test registry connection
        async function testRegistry() {
            const registryEl = document.getElementById('settingsNpmRegistry');
            const registry = registryEl ? registryEl.value : '';
            const unpkg = prismConfig.unpkgUrl || '';
            const result = document.getElementById('registryTestResult');
            
            if (!registry && !unpkg) {
                result.innerHTML = '<span style="color: #f59e0b;">⚠️ Enter a registry URL to test</span>';
                return;
            }
            
            result.innerHTML = '<span style="color: #667eea;">🔄 Testing...</span>';
            
            try {
                const testUrl = unpkg || registry || 'https://unpkg.com';
                const response = await fetch(testUrl + '/@prism-dx/prism-config@latest/package.json');
                
                if (response.ok) {
                    result.innerHTML = '<span style="color: #10b981;">✅ Connection successful!</span>';
                } else {
                    result.innerHTML = '<span style="color: #ef4444;">❌ Connection failed (status: ' + response.status + ')</span>';
                }
            } catch (error) {
                result.innerHTML = '<span style="color: #ef4444;">❌ Connection failed: ' + error.message + '</span>';
            }
        }
        
        // Load packages on page load
        async function loadPackages() {
            try {
                const response = await fetch('/api/packages');
                const data = await response.json();
                
                if (data.error) {
                    console.error('Error loading packages:', data.error);
                    document.getElementById('packagesList').innerHTML = `
                        <div class="alert alert-warning">
                            <strong>⚠️ Could not load prisms from registry</strong><br>
                            Using local prisms. Error: ${data.error}
                        </div>
                    `;
                }
                
                const packagesList = document.getElementById('packagesList');
                
                // Show stats if available
                if (data.stats) {
                    console.log(`📊 Package stats: ${data.stats.valid} valid, ${data.stats.invalid} invalid (${data.stats.total} total)`);
                }
                
                // Store globally for settings panel
                packages = (data.packages || []).map(pkg => ({
                    name: pkg.id,
                    title: pkg.displayName || pkg.id.replace(/[-_.]/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
                    description: pkg.description || '',
                    version: pkg.version,
                    source: pkg.source,
                    default: pkg.default,
                }));

                // Restore saved package or fall back to default
                const savedPkg = prismConfig.selectedPackage;
                const matchesSaved = savedPkg && data.packages.find(pkg => pkg.id === savedPkg || pkg.name === savedPkg);
                const defaultPkg = data.packages.find(pkg => pkg.default) || data.packages[0];
                const targetPkg = matchesSaved ? savedPkg : defaultPkg?.name;
                if (targetPkg) {
                    try {
                        await selectPackage(targetPkg, !matchesSaved);
                    } catch (e) {
                        console.error('Failed to select package, trying default:', e);
                        // Reset config and try default
                        prismConfig.selectedPackage = null;
                        prismConfig.theme = null;
                        savePrismConfig(prismConfig);
                        if (defaultPkg) {
                            await selectPackage(defaultPkg.name, true);
                        }
                    }
                    loadPrismsIntoSettings();
                } else {
                    packagesList.innerHTML = `
                        <div class="alert alert-warning">
                            <strong>No prisms found.</strong><br>
                            Check the settings menu to configure a prism source.
                        </div>
                    `;
                }
            } catch (error) {
                console.error('Failed to load packages:', error);
                document.getElementById('packagesList').innerHTML = `
                    <div class="alert alert-warning">
                        <strong>⚠️ Error loading packages</strong><br>
                        ${error.message}
                    </div>
                `;
            }
        }
        
        async function selectPackage(packageName, resetTheme = true) {
            const isNewPackage = selectedPackage !== packageName;

            // Save current package's theme before switching
            if (isNewPackage && selectedPackage && prismConfig.theme) {
                if (!prismConfig.packageThemes) prismConfig.packageThemes = {};
                prismConfig.packageThemes[selectedPackage] = prismConfig.theme;
            }

            selectedPackage = packageName;
            prismConfig.selectedPackage = packageName;
            // Clear previous tier selections
            Object.keys(selectedSubPrisms).forEach(k => delete selectedSubPrisms[k]);
            // Restore saved theme for this package, or null to use package default
            if (isNewPackage && resetTheme) {
                const savedThemeForPkg = (prismConfig.packageThemes || {})[packageName];
                prismConfig.theme = savedThemeForPkg || null;
                delete prismConfig.customGradients;
                _themeGradients = {};
            }
            savePrismConfig(prismConfig);
            // Apply config (theme, branding, sources) and re-render Step 1 tiers
            await loadAndApplyPrismConfig(packageName);
            await renderStep1Tiers(packageName);
            checkPreviousInstalls();
        }

        async function renderStep1Tiers(packageName) {
            const container = document.getElementById('packagesList');

            try {
                const response = await fetch(`/api/package/${packageName}/tiers`);
                const data = await response.json();

                if (data.error || !data.optional_tiers || data.optional_tiers.length === 0) {
                    // No tiers — show a simple confirmation
                    hasOrganizations = false;
                    container.innerHTML = `
                        <div style="text-align: center; padding: 30px; color: #666;">
                            <p style="font-size: 1.1em;">This prism will be applied with its default configuration.</p>
                            <p style="margin-top: 10px;">Click <strong>Next</strong> to continue.</p>
                        </div>
                    `;
                    return;
                }

                // Tiers handled in Step 1 — Step 3 always skipped
                hasOrganizations = false;
                let html = '';

                data.optional_tiers.forEach(tier => {
                    html += `<div class="tier-section">`;
                    html += `<h3>${tier.label}</h3>`;
                    html += `<div class="tier-cards">`;

                    tier.options.forEach(opt => {
                        const isSelected = selectedSubPrisms[tier.name] === opt.id;
                        html += `
                            <div class="tier-card ${isSelected ? 'selected' : ''}"
                                 onclick="selectTier('${tier.name}', '${opt.id}', this)">
                                <div class="tier-check">&#10003;</div>
                                <div class="tier-name">${opt.name}</div>
                                ${opt.description ? `<div class="tier-desc">${opt.description}</div>` : ''}
                            </div>
                        `;
                    });

                    html += `</div></div>`;
                });

                container.innerHTML = html;
            } catch (err) {
                container.innerHTML = `<p style="color:#ef4444;">Failed to load configurations: ${err.message}</p>`;
            }
        }

        function selectTier(tierName, optionId, cardEl) {
            // Toggle: if already selected, deselect
            if (selectedSubPrisms[tierName] === optionId) {
                delete selectedSubPrisms[tierName];
            } else {
                selectedSubPrisms[tierName] = optionId;
            }

            // Update card visuals within this tier section
            const section = cardEl.closest('.tier-section');
            section.querySelectorAll('.tier-card').forEach(c => c.classList.remove('selected'));
            if (selectedSubPrisms[tierName]) {
                cardEl.classList.add('selected');
            }
        }
        
        async function loadAndApplyPrismConfig(packageName) {
            try {
                const response = await fetch(`/api/package/${packageName}/config`);
                const data = await response.json();
                
                if (data.prism_config) {
                    console.log(`📦 Applying prism_config from ${packageName}:`, data.prism_config);

                    // Render available themes FIRST so custom gradients get cached
                    if (data.prism_config.available_themes) {
                        const currentTheme = prismConfig.theme || data.prism_config.theme;
                        renderThemeGrid(data.prism_config.available_themes, currentTheme);
                    }

                    // Apply theme — use saved preference if set, otherwise package default
                    const savedTheme = prismConfig.theme;
                    const packageTheme = data.prism_config.theme;
                    const themeToApply = savedTheme || packageTheme;

                    if (themeToApply) {
                        selectTheme(themeToApply);
                    }
                    
                    // Apply sources if specified
                    if (data.prism_config.sources && data.prism_config.sources.length > 0) {
                        // Merge with existing sources (don't duplicate)
                        data.prism_config.sources.forEach(newSource => {
                            const exists = prismConfig.sources.some(s => s.url === newSource.url);
                            if (!exists && newSource.type !== 'local') {  // Don't duplicate local
                                prismConfig.sources.push(newSource);
                            }
                        });
                        savePrismConfig(prismConfig);
                        renderPrismSources();
                    }
                    
                    // Apply npm registry if specified
                    if (data.prism_config.npm_registry) {
                        prismConfig.npmRegistry = data.prism_config.npm_registry;
                        savePrismConfig(prismConfig);
                        
                        const settingsNpmReg = document.getElementById('settingsNpmRegistry');
                        if (settingsNpmReg) settingsNpmReg.value = data.prism_config.npm_registry;
                    }
                    
                    // Apply branding if specified
                    if (data.prism_config.branding) {
                        const branding = data.prism_config.branding;

                        if (branding.name) {
                            document.getElementById('brandingTitle').textContent = branding.name;
                            document.title = branding.name + ' Installer';
                        }

                        if (branding.tagline) {
                            document.getElementById('brandingTagline').textContent = branding.tagline;
                        }

                        if (branding.primary_color) {
                            document.documentElement.style.setProperty('--gradient-1', branding.primary_color);
                            document.documentElement.style.setProperty('--gradient-4', branding.primary_color);
                        }

                        if (branding.secondary_color) {
                            document.documentElement.style.setProperty('--gradient-2', branding.secondary_color);
                        }
                    }

                    // Show notification that config was applied
                    console.log(`✅ Prism configuration from ${packageName} applied successfully`);
                } else {
                    console.log(`ℹ️ No prism_config found in ${packageName}, using default configuration`);
                }
            } catch (error) {
                console.error(`Failed to load prism_config for ${packageName}:`, error);
                // Don't block - just use default config
            }
        }
        
        // Load user info fields based on selected package
        let _userFieldMeta = [];

        async function loadUserInfoFields() {
            const response = await fetch(`/api/package/${selectedPackage}/user-fields`);
            const data = await response.json();
            _userFieldMeta = data.fields || [];

            const container = document.getElementById('userInfoFields');
            container.innerHTML = '';

            _userFieldMeta.forEach(field => {
                const req = field.required ? 'required' : '';
                const div = document.createElement('div');
                div.className = 'form-group';
                div.id = `group_${field.id}`;

                const label = document.createElement('label');
                label.setAttribute('for', `field_${field.id}`);
                label.innerHTML = `${field.label}${field.required ? ' <span style="color:red;">*</span>' : ''}`;
                div.appendChild(label);

                if (field.type === 'select' && field.options) {
                    const select = document.createElement('select');
                    select.id = `field_${field.id}`;
                    select.name = field.id;
                    if (field.required) select.required = true;
                    if (field.depends_on) {
                        select.setAttribute('data-depends-on', field.depends_on);
                    }
                    if (field.option_map) {
                        select.setAttribute('data-option-map', JSON.stringify(field.option_map));
                    }

                    populateSelect(select, field.options, field.placeholder);

                    select.addEventListener('change', () => handleCascadeChange(field.id));
                    div.appendChild(select);

                    // If depends on parent, hide until parent has value
                    if (field.depends_on) {
                        div.style.display = 'none';
                    }
                } else {
                    const input = document.createElement('input');
                    input.type = field.type || 'text';
                    input.id = `field_${field.id}`;
                    input.name = field.id;
                    input.placeholder = field.placeholder || '';
                    if (field.required) input.required = true;
                    if (field.validation && field.validation.pattern) {
                        input.setAttribute('data-pattern', field.validation.pattern);
                        input.setAttribute('data-pattern-message', field.validation.message || 'Invalid format');
                    }
                    div.appendChild(input);
                }

                container.appendChild(div);
            });
        }

        function populateSelect(select, options, placeholder) {
            select.innerHTML = '';
            const none = document.createElement('option');
            none.value = '';
            none.textContent = placeholder || '-- Select --';
            select.appendChild(none);
            options.forEach(opt => {
                const o = document.createElement('option');
                o.value = opt;
                o.textContent = opt;
                select.appendChild(o);
            });
        }

        function handleCascadeChange(changedFieldId) {
            _userFieldMeta.forEach(field => {
                if (field.depends_on !== changedFieldId) return;
                const parentEl = document.getElementById(`field_${changedFieldId}`);
                const childEl = document.getElementById(`field_${field.id}`);
                const group = document.getElementById(`group_${field.id}`);
                if (!parentEl || !childEl) return;

                const parentVal = parentEl.value;
                if (!parentVal) {
                    group.style.display = 'none';
                    childEl.value = '';
                    handleCascadeChange(field.id);
                    return;
                }

                group.style.display = '';
                const optionMap = field.option_map;
                const filteredOptions = (optionMap && optionMap[parentVal]) || field.options || [];
                populateSelect(childEl, filteredOptions, field.placeholder);

                // Recursively reset any children
                handleCascadeChange(field.id);
            });
        }
        
        // Check for previous installations
        async function checkPreviousInstalls() {
            try {
                const resp = await fetch('/api/history');
                const data = await resp.json();
                // Only show environments for the selected package
                const installs = (data.installs || []).filter(
                    inst => !selectedPackage || !inst.package || inst.package === selectedPackage
                );
                if (installs.length === 0) {
                    const wrapper = document.getElementById('previousInstalls');
                    wrapper.style.display = 'none';
                    return;
                }

                const container = document.getElementById('previousInstallsList');
                const wrapper = document.getElementById('previousInstalls');
                wrapper.style.display = 'block';

                container.innerHTML = installs.map((inst, i) => `
                    <div style="display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; background: white; border-radius: 8px; margin-bottom: 6px; border: 1px solid #eee;">
                        <div style="flex: 1;">
                            <strong style="font-size: 0.9em;">${inst.package || 'Unknown'}</strong>
                            <span style="color: #888; font-size: 0.8em; margin-left: 8px;">${inst.workspace}</span>
                            ${inst.installed_at ? `<span style="color: #aaa; font-size: 0.75em; margin-left: 8px;">${new Date(inst.installed_at).toLocaleDateString()}</span>` : ''}
                            ${inst.tools_installed ? `<div style="color: #888; font-size: 0.75em; margin-top: 2px;">${inst.tools_installed.length} tools installed</div>` : ''}
                        </div>
                        ${inst.has_rollback ? `
                            <button class="btn-danger" style="font-size: 0.8em; padding: 5px 14px;"
                                onclick="rollbackPrevious('${inst.workspace}', this)">Rollback</button>
                        ` : `
                            <span style="color: #aaa; font-size: 0.75em;">No rollback available</span>
                        `}
                    </div>
                `).join('');
            } catch (e) {
                // Silently fail — not critical
            }
        }

        async function rollbackPrevious(workspace, btn) {
            if (!confirm('Rollback this installation? This will uninstall tools and remove directories.')) return;
            btn.disabled = true;
            btn.textContent = 'Rolling back...';
            try {
                const resp = await fetch('/api/rollback', {
                    method: 'POST',
                    headers: {'Content-Type': 'application/json'},
                    body: JSON.stringify({ workspace })
                });
                const data = await resp.json();
                if (data.success) {
                    btn.textContent = 'Done';
                    btn.style.background = '#10b981';
                    setTimeout(() => checkPreviousInstalls(), 1000);
                } else {
                    btn.textContent = 'Failed';
                    btn.disabled = false;
                }
            } catch (e) {
                btn.textContent = 'Failed';
                btn.disabled = false;
            }
        }

        // Initialize
        updateProgress();
        loadEnvCounts();
        loadPackages();
        checkPreviousInstalls();
    </script>
</body>
</html>
