<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Studio · IO Suite</title>

    <!-- Swiss Design System -->
    <link rel="stylesheet" href="{{ url_for('studio.static', filename='swiss-design.css') }}">

    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        :root {
            /* Swiss Design Variables */
            --bg-primary: var(--swiss-white);
            --bg-secondary: var(--swiss-gray-100);
            --bg-tertiary: var(--swiss-gray-200);
            --bg-hover: var(--swiss-gray-200);
            --text-primary: var(--swiss-black);
            --text-secondary: var(--swiss-gray-700);
            --text-tertiary: var(--swiss-gray-500);
            --accent-color: var(--swiss-red);
            --border-color: var(--swiss-black);
            --border-light: var(--swiss-gray-300);
            --border-medium: var(--swiss-gray-400);
            --success: var(--swiss-black);
            --error: var(--swiss-red);
            --warning: var(--swiss-red-dark);
        }

        body {
            font-family: var(--swiss-font-sans);
            background: var(--swiss-gray-100);
            color: var(--text-primary);
            line-height: var(--swiss-leading-normal);
            min-height: 100vh;
            padding: var(--swiss-unit-6) var(--swiss-unit-4);
        }

        .container {
            max-width: 1500px;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            gap: var(--swiss-unit-6);
        }

        .card {
            background: var(--swiss-white);
            border: 2px solid var(--border-color);
            border-radius: 0;
        }

        .section {
            display: flex;
            flex-direction: column;
            gap: var(--swiss-unit-2);
        }

        .hero {
            padding: var(--swiss-unit-4);
            border-bottom-width: 6px;
        }

        .hero-grid {
            display: grid;
            grid-template-columns: 2fr 1fr;
            gap: var(--swiss-unit-6);
        }

        .hero-title h1 {
            font-size: clamp(2.25rem, 4vw, 3.5rem);
            font-weight: var(--swiss-weight-bold);
            letter-spacing: -0.02em;
            text-transform: uppercase;
            margin-bottom: var(--swiss-unit);
        }

        .eyebrow {
            text-transform: uppercase;
            letter-spacing: 0.3em;
            font-size: 0.75rem;
            color: var(--text-secondary);
            margin-bottom: var(--swiss-unit);
        }

        .subtitle {
            color: var(--text-secondary);
            font-size: var(--swiss-text-md);
            max-width: 60ch;
        }

        .hero-stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
            gap: var(--swiss-unit-3);
        }

        .stat-block {
            border-left: 4px solid var(--border-color);
            padding-left: var(--swiss-unit-3);
        }

        .stat-label {
            text-transform: uppercase;
            letter-spacing: 0.2em;
            font-size: 0.75rem;
            color: var(--text-secondary);
        }

        .stat-value {
            font-size: var(--swiss-text-3xl);
            line-height: 1;
            margin: var(--swiss-unit) 0;
        }

        .stat-detail {
            font-size: var(--swiss-text-sm);
            color: var(--text-secondary);
        }

        .hero-actions {
            grid-column: 1 / -1;
            display: flex;
            justify-content: space-between;
            align-items: flex-end;
            border-top: 2px solid var(--border-color);
            padding-top: var(--swiss-unit-3);
            margin-top: var(--swiss-unit-4);
        }

        .tagline {
            max-width: 480px;
            text-transform: uppercase;
            letter-spacing: 0.18em;
            font-size: 0.78rem;
            color: var(--text-secondary);
        }

        .logout-btn {
            padding: var(--swiss-unit-2) var(--swiss-unit-4);
            background: var(--swiss-white);
            color: var(--text-primary);
            text-decoration: none;
            border-radius: 0;
            border: 2px solid var(--border-color);
            transition: var(--swiss-transition);
            font-weight: var(--swiss-weight-bold);
            letter-spacing: 0.18em;
        }

        .logout-btn:hover {
            background: var(--swiss-black);
            color: var(--swiss-white);
        }

        .section-heading {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            text-transform: uppercase;
            letter-spacing: 0.15em;
            border-top: 2px solid var(--border-color);
            padding-top: var(--swiss-unit-2);
        }

        .section-heading .section-subtitle {
            font-size: 0.85rem;
            color: var(--text-secondary);
            letter-spacing: 0.2em;
        }

        .provider-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
            gap: var(--swiss-unit-2);
            padding: var(--swiss-unit-3);
        }

        .provider-card {
            padding: var(--swiss-unit-3);
            background: var(--swiss-white);
            border: 2px solid var(--border-light);
            border-left: 4px solid var(--border-color);
            cursor: pointer;
            transition: var(--swiss-transition);
            min-height: 140px;
            display: flex;
            flex-direction: column;
            justify-content: space-between;
        }

        .provider-card:hover {
            border-color: var(--border-color);
            border-left-color: var(--swiss-red);
        }

        .provider-card.active {
            background: var(--swiss-black);
            color: var(--swiss-white);
            border-color: var(--swiss-black);
            border-left-color: var(--swiss-red);
        }

        .provider-card.active .provider-name,
        .provider-card.active .provider-stats {
            color: var(--swiss-white);
        }

        .provider-card.disabled {
            opacity: 0.35;
            cursor: not-allowed;
            pointer-events: none;
        }

        .provider-name {
            font-size: var(--swiss-text-lg);
            font-weight: var(--swiss-weight-bold);
            text-transform: uppercase;
            letter-spacing: 0.1em;
        }

        .provider-stats {
            display: flex;
            align-items: center;
            gap: var(--swiss-unit);
            color: var(--text-secondary);
            font-size: var(--swiss-text-sm);
            text-transform: uppercase;
            letter-spacing: 0.18em;
        }

        .status-dot {
            width: 10px;
            height: 10px;
            background: var(--swiss-black);
        }

        .mode-selector {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: var(--swiss-unit-2);
            padding: var(--swiss-unit-3);
            border-top: 6px solid var(--border-color);
        }

        .mode-btn {
            padding: var(--swiss-unit-3);
            background: var(--swiss-white);
            border: 2px solid var(--border-light);
            border-left: 4px solid transparent;
            color: var(--text-primary);
            font-size: var(--swiss-text-base);
            font-weight: var(--swiss-weight-bold);
            cursor: pointer;
            border-radius: 0;
            transition: var(--swiss-transition);
            text-align: left;
            text-transform: uppercase;
            letter-spacing: 0.12em;
            display: flex;
            flex-direction: column;
            gap: var(--swiss-unit);
        }

        .mode-btn:hover {
            border-color: var(--border-color);
            border-left-color: var(--swiss-red);
        }

        .mode-btn.active {
            background: var(--swiss-black);
            color: var(--swiss-white);
            border-color: var(--swiss-black);
            border-left-color: var(--swiss-red);
        }

        .mode-index {
            font-size: var(--swiss-text-sm);
            color: var(--text-secondary);
        }

        .mode-btn.active .mode-index {
            color: var(--swiss-white);
        }

        .mode-label {
            font-size: var(--swiss-text-lg);
            letter-spacing: 0.18em;
        }

        .mode-notes {
            font-size: 0.8rem;
            letter-spacing: 0.12em;
            color: var(--text-secondary);
        }

        .mode-btn.active .mode-notes {
            color: var(--swiss-white);
        }

        .mode-content {
            display: none;
        }

        .mode-content.active {
            display: block;
        }

        .controls {
            padding: var(--swiss-unit-4);
            margin-bottom: var(--swiss-unit-4);
        }

        .control-group {
            margin-bottom: var(--swiss-unit-3);
        }

        label {
            display: block;
            margin-bottom: var(--swiss-unit);
            color: var(--text-primary);
            font-size: var(--swiss-text-sm);
            font-weight: var(--swiss-weight-bold);
            text-transform: uppercase;
            letter-spacing: var(--swiss-tracking-wide);
        }

        select, textarea, input[type="text"], input[type="file"] {
            width: 100%;
            padding: var(--swiss-unit-2);
            background: var(--swiss-white);
            border: var(--swiss-border-width) solid var(--border-color);
            border-radius: 0;
            color: var(--swiss-black);
            font-size: var(--swiss-text-base);
            font-family: var(--swiss-font-sans);
            transition: var(--swiss-transition);
        }

        select:focus, textarea:focus, input:focus {
            outline: var(--swiss-border-width-thick) solid var(--swiss-black);
            outline-offset: 2px;
        }

        textarea {
            resize: vertical;
            min-height: 120px;
            line-height: var(--swiss-leading-normal);
        }

        .btn {
            padding: var(--swiss-unit-2) var(--swiss-unit-4);
            border: var(--swiss-border-width) solid var(--border-color);
            border-radius: 0;
            font-size: var(--swiss-text-base);
            font-weight: var(--swiss-weight-bold);
            cursor: pointer;
            transition: var(--swiss-transition);
            display: inline-flex;
            align-items: center;
            gap: var(--swiss-unit);
            text-transform: uppercase;
            letter-spacing: var(--swiss-tracking-wide);
        }

        .btn-primary {
            background: var(--swiss-black);
            color: var(--swiss-white);
            border-color: var(--swiss-black);
        }

        .btn-primary:hover:not(:disabled) {
            background: var(--swiss-red);
            border-color: var(--swiss-red);
        }

        .btn-primary:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .btn-secondary {
            background: var(--bg-primary);
            color: var(--text-primary);
            border-color: var(--border-color);
        }

        .btn-secondary:hover {
            background: var(--swiss-black);
            color: var(--swiss-white);
        }

        .chat-container {
            height: 600px;
            display: flex;
            flex-direction: column;
            border-radius: 0;
            overflow: hidden;
            border: var(--swiss-border-width) solid var(--border-color);
        }

        .chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: var(--swiss-unit-4);
            display: flex;
            flex-direction: column;
            gap: var(--swiss-unit-2);
            background: var(--bg-tertiary);
        }

        .chat-messages::-webkit-scrollbar {
            width: 8px;
        }

        .chat-messages::-webkit-scrollbar-track {
            background: var(--bg-secondary);
        }

        .chat-messages::-webkit-scrollbar-thumb {
            background: var(--swiss-black);
            border-radius: 0;
        }

        .chat-message {
            padding: var(--swiss-unit-2) var(--swiss-unit-3);
            border-radius: 0;
            max-width: 80%;
            word-wrap: break-word;
        }

        .chat-message.user {
            background: var(--swiss-black);
            color: var(--swiss-white);
            margin-left: auto;
            border: var(--swiss-border-width) solid var(--swiss-black);
        }

        .chat-message.assistant {
            background: var(--swiss-white);
            color: var(--text-primary);
            border: var(--swiss-border-width) solid var(--border-color);
        }

        .chat-input-area {
            padding: var(--swiss-unit-3);
            border-top: var(--swiss-border-width) solid var(--border-color);
            background: var(--bg-secondary);
            display: flex;
            gap: var(--swiss-unit-2);
        }

        .chat-input-area input {
            flex: 1;
        }

        .image-preview {
            max-width: 100%;
            max-height: 500px;
            border-radius: 0;
            margin-top: var(--swiss-unit-3);
            display: none;
            border: var(--swiss-border-width) solid var(--border-color);
        }

        .image-preview.visible {
            display: block;
        }

        .upload-area {
            border: var(--swiss-border-width-thick) solid var(--border-color);
            padding: var(--swiss-unit-8);
            text-align: center;
            border-radius: 0;
            cursor: pointer;
            transition: var(--swiss-transition);
            background: var(--bg-tertiary);
        }

        .upload-area:hover {
            background: var(--swiss-black);
            color: var(--swiss-white);
        }

        .upload-area:hover .upload-icon {
            opacity: 1;
        }

        .upload-icon {
            font-size: var(--swiss-text-3xl);
            margin-bottom: var(--swiss-unit-2);
            opacity: 0.6;
            transition: var(--swiss-transition);
        }

        .status {
            margin-top: var(--swiss-unit-3);
            padding: var(--swiss-unit-2) var(--swiss-unit-3);
            border-radius: 0;
            display: none;
            align-items: center;
            gap: var(--swiss-unit);
            font-weight: var(--swiss-weight-medium);
            border: var(--swiss-border-width) solid var(--border-color);
        }

        .status.success {
            background: var(--bg-primary);
            color: var(--swiss-black);
        }

        .status.error {
            background: var(--swiss-red);
            color: var(--swiss-white);
            border-color: var(--swiss-red);
        }

        .status.visible {
            display: flex;
        }

        .loading {
            display: none;
            align-items: center;
            gap: var(--swiss-unit-2);
            margin-top: var(--swiss-unit-3);
            padding: var(--swiss-unit-2) var(--swiss-unit-3);
            background: var(--bg-secondary);
            border-radius: 0;
            border: var(--swiss-border-width) solid var(--border-color);
            color: var(--text-primary);
        }

        .loading.visible {
            display: flex;
        }

        .spinner {
            width: 24px;
            height: 24px;
            border: var(--swiss-border-width-thick) solid var(--border-light);
            border-top-color: var(--swiss-black);
            border-radius: 0; /* Swiss: square spinner */
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        .output-area {
            padding: var(--swiss-unit-4);
            min-height: 200px;
            margin-top: var(--swiss-unit-3);
            border-radius: 0;
            line-height: var(--swiss-leading-relaxed);
            background: var(--bg-tertiary);
            border: var(--swiss-border-width) solid var(--border-color);
        }

        /* Range Slider Styling */
        input[type="range"] {
            -webkit-appearance: none;
            appearance: none;
            background: var(--bg-tertiary);
            border: var(--swiss-border-width) solid var(--border-color);
            height: 32px;
            border-radius: 0;
            padding: 0;
        }

        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 16px;
            height: 32px;
            background: var(--swiss-black);
            cursor: pointer;
            border-radius: 0;
        }

        input[type="range"]::-moz-range-thumb {
            width: 16px;
            height: 32px;
            background: var(--swiss-black);
            cursor: pointer;
            border-radius: 0;
            border: none;
        }

        input[type="range"]:focus {
            outline: var(--swiss-border-width-thick) solid var(--swiss-black);
            outline-offset: 2px;
        }

        /* Audio/Video Player Styling */
        audio, video {
            border-radius: 0;
            background: var(--swiss-black);
        }

        audio::-webkit-media-controls-panel {
            background-color: var(--bg-secondary);
        }

        video::-webkit-media-controls-panel {
            background-color: var(--bg-secondary);
        }

        /* Responsive */
        @media (max-width: 768px) {
            body {
                padding: var(--swiss-unit-4) var(--swiss-unit-2);
            }

            .container {
                gap: var(--swiss-unit-4);
            }

            .hero-grid {
                grid-template-columns: 1fr;
            }

            .hero-actions {
                flex-direction: column;
                align-items: flex-start;
                gap: var(--swiss-unit-2);
            }

            .provider-grid {
                grid-template-columns: 1fr;
            }

            .mode-selector {
                grid-template-columns: 1fr;
            }

            .chat-container {
                height: 500px;
            }

            .chat-message {
                max-width: 90%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header class="hero card">
            <div class="hero-grid">
                <div class="hero-title">
                    <p class="eyebrow">Swiss AI Studio</p>
                    <h1>Multiprovider Control Room</h1>
                    <p class="subtitle">Disciplined operations for chat, imagery, video, and speech across every configured provider.</p>
                </div>
                <div class="hero-stats">
                    <div class="stat-block">
                        <p class="stat-label">Providers</p>
                        <p class="stat-value">{{ provider_info|length }}</p>
                        <p class="stat-detail">Integrated endpoints</p>
                    </div>
                    <div class="stat-block">
                        <p class="stat-label">Modes</p>
                        <p class="stat-value">06</p>
                        <p class="stat-detail">Chat · Image · Audio</p>
                    </div>
                </div>
                <div class="hero-actions">
                    <p class="tagline">Swiss grid discipline keeps interactions deliberate, focused, and quick to audit.</p>
                    <a href="{{ logout_url }}" class="logout-btn">Logout</a>
                </div>
            </div>
        </header>

        <!-- Provider Selection -->
        <section class="section">
            <div class="section-heading">
                <p class="eyebrow">Provider Matrix</p>
                <p class="section-subtitle">Route every request with intent</p>
            </div>
            <div class="provider-grid card">
            {% for provider_name, info in provider_info.items() %}
                <div class="provider-card {% if info.available %}{% else %}disabled{% endif %}"
                     data-provider="{{ provider_name }}"
                     {% if info.available %}onclick="selectProvider('{{ provider_name }}')"{% endif %}>
                    <div class="provider-name">{{ provider_name|title }}</div>
                    <div class="provider-stats">
                        {% if info.available %}
                            <div class="status-dot"></div>
                            <span>{{ info.models|length }} models</span>
                        {% else %}
                            <span style="color: var(--error);">● Offline</span>
                        {% endif %}
                    </div>
                </div>
            {% endfor %}
            </div>
        </section>

        <!-- Mode Selection -->
        <section class="section">
            <div class="section-heading">
                <p class="eyebrow">Operational Modes</p>
                <p class="section-subtitle">Select an interface</p>
            </div>
            <div class="mode-selector card">
                <button class="mode-btn active" data-mode="chat" onclick="selectMode('chat')">
                    <span class="mode-index">01</span>
                    <span class="mode-label">Chat</span>
                    <span class="mode-notes">Conversational control room</span>
                </button>
                <button class="mode-btn" data-mode="image-gen" onclick="selectMode('image-gen')">
                    <span class="mode-index">02</span>
                    <span class="mode-label">Image Generation</span>
                    <span class="mode-notes">Swiss grid prompts</span>
                </button>
                <button class="mode-btn" data-mode="image-analysis" onclick="selectMode('image-analysis')">
                    <span class="mode-index">03</span>
                    <span class="mode-label">Image Analysis</span>
                    <span class="mode-notes">Structured inspection</span>
                </button>
                <button class="mode-btn" data-mode="video-gen" onclick="selectMode('video-gen')">
                    <span class="mode-index">04</span>
                    <span class="mode-label">Video Generation</span>
                    <span class="mode-notes">Storyboard to frames</span>
                </button>
                <button class="mode-btn" data-mode="speech-recognition" onclick="selectMode('speech-recognition')">
                    <span class="mode-index">05</span>
                    <span class="mode-label">Speech Recognition</span>
                    <span class="mode-notes">Live transcription</span>
                </button>
                <button class="mode-btn" data-mode="text-to-speech" onclick="selectMode('text-to-speech')">
                    <span class="mode-index">06</span>
                    <span class="mode-label">Text-to-Speech</span>
                    <span class="mode-notes">Voices + narration</span>
                </button>
            </div>
        </section>

        <!-- Chat Mode -->
        <div class="mode-content active" id="chat-mode">
            <div class="controls card">
                <div class="control-group">
                    <label for="chat-model">Select Model</label>
                    <select id="chat-model"></select>
                </div>
            </div>

            <div class="chat-container">
                <div class="chat-messages" id="chat-messages"></div>
                <div class="chat-input-area">
                    <input type="text" id="chat-input" placeholder="Type your message..." />
                    <button class="btn btn-primary" onclick="sendChat()">Send</button>
                    <button class="btn btn-secondary" onclick="clearChat()">Clear</button>
                </div>
            </div>

            <div class="loading" id="chat-loading">
                <div class="spinner"></div>
                <span>Thinking...</span>
            </div>
        </div>

        <!-- Image Generation Mode -->
        <div class="mode-content" id="image-gen-mode">
            <div class="controls card">
                <div class="control-group">
                    <label for="image-gen-model">Select Model</label>
                    <select id="image-gen-model"></select>
                </div>
                <div class="control-group">
                    <label for="image-gen-prompt">Describe Your Image</label>
                    <textarea id="image-gen-prompt" placeholder="A serene sunset over mountains with vibrant colors..."></textarea>
                </div>
                <button class="btn btn-primary" onclick="generateImage()">Generate Image</button>
            </div>

            <div class="loading" id="image-gen-loading">
                <div class="spinner"></div>
                <span>Generating your masterpiece...</span>
            </div>

            <div class="status" id="image-gen-status"></div>

            <div class="output-area">
                <img id="generated-image" class="image-preview" alt="Generated image" />
            </div>
        </div>

        <!-- Image Analysis Mode -->
        <div class="mode-content" id="image-analysis-mode">
            <div class="controls card">
                <div class="control-group">
                    <label for="analysis-model">Select Model</label>
                    <select id="analysis-model"></select>
                </div>
                <div class="control-group">
                    <label>Upload Image</label>
                    <div class="upload-area" onclick="document.getElementById('analysis-image').click()">
                        <div class="upload-icon">🖼️</div>
                        <p style="font-size: 1.1rem; margin-bottom: 0.5rem; color: var(--text-primary);">Drop your image here or click to browse</p>
                        <p style="font-size: 0.9rem; color: var(--text-secondary);">
                            PNG, JPG, GIF up to 10MB
                        </p>
                    </div>
                    <input type="file" id="analysis-image" accept="image/*" style="display: none;" onchange="previewAnalysisImage(event)" />
                </div>
                <img id="analysis-preview" class="image-preview" alt="Preview" />
                <div class="control-group">
                    <label for="analysis-prompt">What would you like to know?</label>
                    <textarea id="analysis-prompt" placeholder="Describe this image in detail...">Generate detailed alt text for this image suitable for screen readers and social media.</textarea>
                </div>
                <button class="btn btn-primary" onclick="analyzeImage()">Analyze Image</button>
            </div>

            <div class="loading" id="analysis-loading">
                <div class="spinner"></div>
                <span>Analyzing your image...</span>
            </div>

            <div class="status" id="analysis-status"></div>

            <div class="output-area" id="analysis-output"></div>
        </div>

        <!-- Video Generation Mode -->
        <div class="mode-content" id="video-gen-mode">
            <div class="controls card">
                <div class="control-group">
                    <label for="video-gen-model">Select Model</label>
                    <select id="video-gen-model"></select>
                </div>
                <div class="control-group">
                    <label for="video-gen-prompt">Describe Your Video</label>
                    <textarea id="video-gen-prompt" placeholder="A serene forest with sunlight filtering through trees..."></textarea>
                </div>
                <div class="control-group" style="display: grid; grid-template-columns: 1fr 1fr; gap: var(--swiss-unit-2);">
                    <div>
                        <label for="video-duration">Duration</label>
                        <select id="video-duration">
                            <option value="5">5 seconds</option>
                            <option value="10">10 seconds</option>
                        </select>
                    </div>
                    <div>
                        <label for="video-aspect">Aspect Ratio</label>
                        <select id="video-aspect">
                            <option value="16:9">16:9 (Landscape)</option>
                            <option value="9:16">9:16 (Portrait)</option>
                            <option value="1:1">1:1 (Square)</option>
                        </select>
                    </div>
                </div>
                <button class="btn btn-primary" onclick="generateVideo()">Generate Video</button>
            </div>

            <div class="loading" id="video-gen-loading">
                <div class="spinner"></div>
                <span>Generating video (this may take 1-2 minutes)...</span>
            </div>

            <div class="status" id="video-gen-status"></div>

            <div class="output-area" id="video-gen-output">
                <video id="generated-video" class="image-preview" controls style="width: 100%;"></video>
                <div style="margin-top: var(--swiss-unit-3); display: none;" id="video-actions">
                    <button class="btn btn-secondary" onclick="downloadVideo()">Download Video</button>
                </div>
            </div>
        </div>

        <!-- Speech Recognition Mode -->
        <div class="mode-content" id="speech-recognition-mode">
            <div class="controls card">
                <div class="control-group">
                    <label for="speech-model">Select Model</label>
                    <select id="speech-model"></select>
                </div>
                <div class="control-group">
                    <label>Upload Audio File</label>
                    <div class="upload-area" onclick="document.getElementById('speech-audio').click()">
                        <div class="upload-icon">🎤</div>
                        <p style="font-size: 1.1rem; margin-bottom: 0.5rem; color: var(--text-primary);">Drop audio file here or click to browse</p>
                        <p style="font-size: 0.9rem; color: var(--text-secondary);">
                            MP3, WAV, M4A, WEBM up to 25MB
                        </p>
                    </div>
                    <input type="file" id="speech-audio" accept="audio/*,.mp3,.wav,.m4a,.webm" style="display: none;" onchange="previewAudioFile(event)" />
                </div>
                <div id="audio-file-info" style="display: none; padding: var(--swiss-unit-2); background: var(--bg-tertiary); border: var(--swiss-border-width) solid var(--border-color); margin-top: var(--swiss-unit-2);">
                    <strong>Selected:</strong> <span id="audio-file-name"></span>
                </div>
                <div class="control-group">
                    <label for="speech-language">Language (Optional)</label>
                    <select id="speech-language">
                        <option value="">Auto-detect</option>
                        <option value="en">English</option>
                        <option value="es">Spanish</option>
                        <option value="fr">French</option>
                        <option value="de">German</option>
                        <option value="it">Italian</option>
                        <option value="pt">Portuguese</option>
                        <option value="ru">Russian</option>
                        <option value="ja">Japanese</option>
                        <option value="zh">Chinese</option>
                    </select>
                </div>
                <button class="btn btn-primary" onclick="transcribeAudio()">Transcribe Audio</button>
            </div>

            <div class="loading" id="speech-loading">
                <div class="spinner"></div>
                <span>Transcribing audio...</span>
            </div>

            <div class="status" id="speech-status"></div>

            <div class="output-area" id="speech-output-container" style="display: none;">
                <div style="margin-bottom: var(--swiss-unit-2); padding: var(--swiss-unit-2); background: var(--bg-secondary); border: var(--swiss-border-width) solid var(--border-color);">
                    <strong>Transcription:</strong>
                    <span id="speech-detected-language" style="margin-left: var(--swiss-unit-2); color: var(--text-secondary);"></span>
                </div>
                <div id="speech-output" style="white-space: pre-wrap;"></div>
                <div style="margin-top: var(--swiss-unit-3); display: flex; gap: var(--swiss-unit-2);">
                    <button class="btn btn-secondary" onclick="copyTranscription()">Copy</button>
                    <button class="btn btn-secondary" onclick="sendToChat()">Send to Chat</button>
                </div>
            </div>
        </div>

        <!-- Text-to-Speech Mode -->
        <div class="mode-content" id="text-to-speech-mode">
            <div class="controls card">
                <div class="control-group" style="display: grid; grid-template-columns: 2fr 1fr; gap: var(--swiss-unit-2);">
                    <div>
                        <label for="tts-provider">Provider</label>
                        <select id="tts-provider" onchange="updateTTSVoices()">
                            <option value="openai">OpenAI</option>
                            <option value="elevenlabs">ElevenLabs</option>
                        </select>
                    </div>
                    <div>
                        <label for="tts-voice">Voice</label>
                        <select id="tts-voice"></select>
                    </div>
                </div>
                <div class="control-group">
                    <label for="tts-speed">Speed: <span id="tts-speed-value">1.0x</span></label>
                    <input type="range" id="tts-speed" min="0.25" max="4.0" step="0.05" value="1.0"
                           oninput="document.getElementById('tts-speed-value').textContent = this.value + 'x'"
                           style="width: 100%; cursor: pointer;">
                </div>
                <div class="control-group">
                    <label for="tts-text">Text to Speak <span id="tts-char-count" style="font-weight: normal; text-transform: none; letter-spacing: normal;">(0 chars)</span></label>
                    <textarea id="tts-text" placeholder="Enter the text you want to convert to speech..."
                              oninput="updateCharCount()" style="min-height: 150px;"></textarea>
                </div>
                <button class="btn btn-primary" onclick="generateSpeech()">Generate Speech</button>
            </div>

            <div class="loading" id="tts-loading">
                <div class="spinner"></div>
                <span>Generating speech...</span>
            </div>

            <div class="status" id="tts-status"></div>

            <div id="tts-player-container" style="display: none; margin-top: var(--swiss-unit-4);">
                <div class="controls card">
                    <label>Audio Player</label>
                    <div style="background: var(--bg-tertiary); padding: var(--swiss-unit-3); border: var(--swiss-border-width) solid var(--border-color);">
                        <audio id="tts-audio" controls style="width: 100%; margin-bottom: var(--swiss-unit-2);"></audio>
                        <div style="display: flex; gap: var(--swiss-unit-2);">
                            <button class="btn btn-secondary" onclick="downloadAudio()">Download</button>
                            <button class="btn btn-secondary" onclick="regenerateSpeech()">Regenerate</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        const providerInfo = {{ provider_info | tojson }};
        const apiEndpoints = {{ api_endpoints | tojson }};

        let currentProvider = null;
        let currentMode = 'chat';

        const providerCapabilities = {
            'anthropic': { chat: true, imageGen: false, imageAnalysis: true, videoGen: false, speech: false, tts: false },
            'openai': { chat: true, imageGen: true, imageAnalysis: true, videoGen: true, speech: true, tts: true },
            'cohere': { chat: true, imageGen: false, imageAnalysis: false, videoGen: false, speech: false, tts: false },
            'mistral': { chat: true, imageGen: false, imageAnalysis: true, videoGen: false, speech: false, tts: false },
            'perplexity': { chat: true, imageGen: false, imageAnalysis: false, videoGen: false, speech: false, tts: false },
            'xai': { chat: true, imageGen: true, imageAnalysis: true, videoGen: false, speech: false, tts: false },
            'gemini': { chat: true, imageGen: false, imageAnalysis: true, videoGen: false, speech: false, tts: false },
            'huggingface': { chat: true, imageGen: true, imageAnalysis: true, videoGen: false, speech: false, tts: false },
            'groq': { chat: true, imageGen: false, imageAnalysis: false, videoGen: false, speech: false, tts: false },
            'manus': { chat: true, imageGen: false, imageAnalysis: true, videoGen: false, speech: false, tts: false }
        };

        // TTS voice options
        const ttsVoices = {
            openai: ['alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'],
            elevenlabs: ['rachel', 'clyde', 'domi', 'dave', 'fin', 'bella', 'antoni', 'thomas', 'charlie', 'emily', 'elli', 'callum', 'patrick', 'harry', 'liam', 'dorothy', 'josh', 'arnold', 'charlotte', 'alice', 'matilda', 'matthew', 'james', 'joseph', 'jeremy', 'michael', 'ethan', 'chris', 'gigi', 'freya', 'lily', 'serena', 'adam', 'nicole', 'jessie', 'ryan', 'sam', 'glinda', 'giovanni', 'mimi']
        };

        document.addEventListener('DOMContentLoaded', () => {
            const firstAvailable = Object.keys(providerInfo).find(p => providerInfo[p].available);
            if (firstAvailable) {
                selectProvider(firstAvailable);
            }
            // Initialize TTS voices
            updateTTSVoices();
        });

        function selectProvider(providerName) {
            if (!providerInfo[providerName] || !providerInfo[providerName].available) {
                return;
            }

            currentProvider = providerName;

            document.querySelectorAll('.provider-card').forEach(card => {
                card.classList.toggle('active', card.dataset.provider === providerName);
            });

            updateModelsForMode();
        }

        function selectMode(mode) {
            currentMode = mode;

            document.querySelectorAll('.mode-btn').forEach(btn => {
                btn.classList.toggle('active', btn.dataset.mode === mode);
            });

            document.querySelectorAll('.mode-content').forEach(content => {
                content.classList.remove('active');
            });
            document.getElementById(mode + '-mode').classList.add('active');

            updateModelsForMode();
        }

        function updateModelsForMode() {
            if (!currentProvider || !providerInfo[currentProvider]) return;

            const models = providerInfo[currentProvider].models || [];
            let selectElement;

            switch(currentMode) {
                case 'chat':
                    selectElement = document.getElementById('chat-model');
                    break;
                case 'image-gen':
                    selectElement = document.getElementById('image-gen-model');
                    break;
                case 'image-analysis':
                    selectElement = document.getElementById('analysis-model');
                    break;
                case 'video-gen':
                    selectElement = document.getElementById('video-gen-model');
                    break;
                case 'speech-recognition':
                    selectElement = document.getElementById('speech-model');
                    break;
                default:
                    return;
            }

            if (!selectElement) return;

            selectElement.innerHTML = '';

            models.forEach(model => {
                const option = document.createElement('option');
                // Handle both string arrays and object arrays
                if (typeof model === 'string') {
                    option.value = model;
                    option.textContent = model;
                } else {
                    option.value = model.id;
                    option.textContent = model.name || model.id;
                }
                selectElement.appendChild(option);
            });

            if (models.length > 0) {
                selectElement.value = typeof models[0] === 'string' ? models[0] : models[0].id;
            }
        }

        async function sendChat() {
            const input = document.getElementById('chat-input');
            const message = input.value.trim();
            if (!message || !currentProvider) return;

            const model = document.getElementById('chat-model').value;

            addChatMessage('user', message);
            input.value = '';

            document.getElementById('chat-loading').classList.add('visible');

            try {
                const response = await fetch(apiEndpoints.chat, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        message: message,
                        provider: currentProvider,
                        model: model
                    })
                });

                const data = await response.json();

                if (response.ok) {
                    addChatMessage('assistant', data.response);
                } else {
                    addChatMessage('assistant', '❌ Error: ' + (data.error || 'Unknown error'));
                }
            } catch (error) {
                addChatMessage('assistant', '❌ Error: ' + error.message);
            } finally {
                document.getElementById('chat-loading').classList.remove('visible');
            }
        }

        function addChatMessage(role, content) {
            const messagesDiv = document.getElementById('chat-messages');
            const messageDiv = document.createElement('div');
            messageDiv.className = 'chat-message ' + role;
            messageDiv.textContent = content;
            messagesDiv.appendChild(messageDiv);
            messagesDiv.scrollTop = messagesDiv.scrollHeight;
        }

        function clearChat() {
            document.getElementById('chat-messages').innerHTML = '';
            if (currentProvider) {
                fetch(apiEndpoints.clear_chat, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ provider: currentProvider })
                });
            }
        }

        async function generateImage() {
            const prompt = document.getElementById('image-gen-prompt').value.trim();
            if (!prompt || !currentProvider) return;

            const statusEl = document.getElementById('image-gen-status');
            const loadingEl = document.getElementById('image-gen-loading');
            const imageEl = document.getElementById('generated-image');

            loadingEl.classList.add('visible');
            statusEl.classList.remove('visible');
            imageEl.classList.remove('visible');

            try {
                const response = await fetch(apiEndpoints.generate_image, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        prompt: prompt,
                        provider: currentProvider
                    })
                });

                const data = await response.json();

                if (response.ok) {
                    imageEl.src = 'data:image/png;base64,' + data.image;
                    imageEl.classList.add('visible');
                    showStatus('image-gen-status', 'success', '✅ Image generated successfully!');
                } else {
                    showStatus('image-gen-status', 'error', '❌ ' + (data.error || 'Failed to generate image'));
                }
            } catch (error) {
                showStatus('image-gen-status', 'error', '❌ ' + error.message);
            } finally {
                loadingEl.classList.remove('visible');
            }
        }

        function previewAnalysisImage(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const preview = document.getElementById('analysis-preview');
                    preview.src = e.target.result;
                    preview.classList.add('visible');
                };
                reader.readAsDataURL(file);
            }
        }

        async function analyzeImage() {
            const fileInput = document.getElementById('analysis-image');
            const prompt = document.getElementById('analysis-prompt').value.trim();

            if (!fileInput.files[0] || !prompt || !currentProvider) {
                showStatus('analysis-status', 'error', '❌ Please select an image and enter a prompt');
                return;
            }

            const model = document.getElementById('analysis-model').value;
            const formData = new FormData();
            formData.append('image', fileInput.files[0]);
            formData.append('prompt', prompt);
            formData.append('provider', currentProvider);
            formData.append('model', model);

            const statusEl = document.getElementById('analysis-status');
            const loadingEl = document.getElementById('analysis-loading');
            const outputEl = document.getElementById('analysis-output');

            loadingEl.classList.add('visible');
            statusEl.classList.remove('visible');
            outputEl.textContent = '';

            try {
                const response = await fetch(apiEndpoints.analyze_image, {
                    method: 'POST',
                    body: formData
                });

                const data = await response.json();

                if (response.ok) {
                    outputEl.textContent = data.response;
                    showStatus('analysis-status', 'success', '✅ Image analyzed successfully!');
                } else {
                    showStatus('analysis-status', 'error', '❌ ' + (data.error || 'Failed to analyze image'));
                }
            } catch (error) {
                showStatus('analysis-status', 'error', '❌ ' + error.message);
            } finally {
                loadingEl.classList.remove('visible');
            }
        }

        function showStatus(elementId, type, message) {
            const statusEl = document.getElementById(elementId);
            statusEl.className = 'status visible ' + type;
            statusEl.textContent = message;
        }

        document.getElementById('chat-input').addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                sendChat();
            }
        });

        // Video Generation Functions
        async function generateVideo() {
            const prompt = document.getElementById('video-gen-prompt').value.trim();
            if (!prompt || !currentProvider) return;

            const duration = document.getElementById('video-duration').value;
            const aspect = document.getElementById('video-aspect').value;
            const loadingEl = document.getElementById('video-gen-loading');
            const statusEl = document.getElementById('video-gen-status');
            const videoEl = document.getElementById('generated-video');
            const actionsEl = document.getElementById('video-actions');

            loadingEl.classList.add('visible');
            statusEl.classList.remove('visible');
            videoEl.classList.remove('visible');
            actionsEl.style.display = 'none';

            try {
                const response = await fetch(apiEndpoints.generate_video || '/studio/generate-video', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        prompt: prompt,
                        provider: currentProvider,
                        duration: duration,
                        aspect_ratio: aspect
                    })
                });

                const data = await response.json();

                if (response.ok) {
                    videoEl.src = 'data:video/mp4;base64,' + data.video;
                    videoEl.classList.add('visible');
                    actionsEl.style.display = 'block';
                    showStatus('video-gen-status', 'success', '✅ Video generated successfully!');
                } else {
                    showStatus('video-gen-status', 'error', '❌ ' + (data.error || 'Failed to generate video'));
                }
            } catch (error) {
                showStatus('video-gen-status', 'error', '❌ ' + error.message);
            } finally {
                loadingEl.classList.remove('visible');
            }
        }

        function downloadVideo() {
            const videoEl = document.getElementById('generated-video');
            const link = document.createElement('a');
            link.href = videoEl.src;
            link.download = 'studio-video-' + Date.now() + '.mp4';
            link.click();
        }

        // Speech Recognition Functions
        function previewAudioFile(event) {
            const file = event.target.files[0];
            if (file) {
                document.getElementById('audio-file-name').textContent = file.name;
                document.getElementById('audio-file-info').style.display = 'block';
            }
        }

        async function transcribeAudio() {
            const fileInput = document.getElementById('speech-audio');
            if (!fileInput.files[0]) {
                showStatus('speech-status', 'error', '❌ Please select an audio file');
                return;
            }

            const language = document.getElementById('speech-language').value;
            const formData = new FormData();
            formData.append('audio_file', fileInput.files[0]);
            if (language) formData.append('language', language);

            const loadingEl = document.getElementById('speech-loading');
            const statusEl = document.getElementById('speech-status');
            const outputContainer = document.getElementById('speech-output-container');
            const outputEl = document.getElementById('speech-output');

            loadingEl.classList.add('visible');
            statusEl.classList.remove('visible');
            outputContainer.style.display = 'none';

            try {
                const response = await fetch(apiEndpoints.transcribe || '/studio/transcribe', {
                    method: 'POST',
                    body: formData
                });

                const data = await response.json();

                if (response.ok) {
                    outputEl.textContent = data.text;
                    if (data.language) {
                        document.getElementById('speech-detected-language').textContent =
                            '(Detected: ' + data.language + ')';
                    }
                    outputContainer.style.display = 'block';
                    showStatus('speech-status', 'success', '✅ Audio transcribed successfully!');
                } else {
                    showStatus('speech-status', 'error', '❌ ' + (data.error || 'Failed to transcribe audio'));
                }
            } catch (error) {
                showStatus('speech-status', 'error', '❌ ' + error.message);
            } finally {
                loadingEl.classList.remove('visible');
            }
        }

        function copyTranscription() {
            const text = document.getElementById('speech-output').textContent;
            navigator.clipboard.writeText(text).then(() => {
                showStatus('speech-status', 'success', '✅ Copied to clipboard!');
            });
        }

        function sendToChat() {
            const text = document.getElementById('speech-output').textContent;
            selectMode('chat');
            document.getElementById('chat-input').value = text;
        }

        // Text-to-Speech Functions
        function updateTTSVoices() {
            const provider = document.getElementById('tts-provider').value;
            const voiceSelect = document.getElementById('tts-voice');
            voiceSelect.innerHTML = '';

            const voices = ttsVoices[provider] || [];
            voices.forEach(voice => {
                const option = document.createElement('option');
                option.value = voice;
                option.textContent = voice.charAt(0).toUpperCase() + voice.slice(1);
                voiceSelect.appendChild(option);
            });
        }

        function updateCharCount() {
            const text = document.getElementById('tts-text').value;
            document.getElementById('tts-char-count').textContent = `(${text.length} chars)`;
        }

        async function generateSpeech() {
            const text = document.getElementById('tts-text').value.trim();
            if (!text) {
                showStatus('tts-status', 'error', '❌ Please enter text to convert to speech');
                return;
            }

            const provider = document.getElementById('tts-provider').value;
            const voice = document.getElementById('tts-voice').value;
            const speed = document.getElementById('tts-speed').value;

            const loadingEl = document.getElementById('tts-loading');
            const statusEl = document.getElementById('tts-status');
            const playerContainer = document.getElementById('tts-player-container');
            const audioEl = document.getElementById('tts-audio');

            loadingEl.classList.add('visible');
            statusEl.classList.remove('visible');
            playerContainer.style.display = 'none';

            try {
                const response = await fetch(apiEndpoints.generate_speech || '/studio/generate-speech', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        text: text,
                        provider: provider,
                        voice: voice,
                        speed: parseFloat(speed)
                    })
                });

                if (response.ok) {
                    // Backend returns binary audio file, convert to blob URL
                    const audioBlob = await response.blob();
                    const audioUrl = URL.createObjectURL(audioBlob);
                    audioEl.src = audioUrl;
                    playerContainer.style.display = 'block';

                    // Check if cached
                    const cacheHit = response.headers.get('X-Cache-Hit') === 'true';
                    const statusMsg = cacheHit
                        ? '✅ Speech generated (from cache)'
                        : '✅ Speech generated successfully!';
                    showStatus('tts-status', 'success', statusMsg);
                } else {
                    const data = await response.json();
                    showStatus('tts-status', 'error', '❌ ' + (data.error || 'Failed to generate speech'));
                }
            } catch (error) {
                showStatus('tts-status', 'error', '❌ ' + error.message);
            } finally {
                loadingEl.classList.remove('visible');
            }
        }

        function downloadAudio() {
            const audioEl = document.getElementById('tts-audio');
            const link = document.createElement('a');
            link.href = audioEl.src;
            link.download = 'studio-speech-' + Date.now() + '.mp3';
            link.click();
        }

        function regenerateSpeech() {
            document.getElementById('tts-player-container').style.display = 'none';
            generateSpeech();
        }
    </script>
    <!-- GoatCounter Analytics -->
    <script data-goatcounter="https://dr.eamer.dev/analytics/count"
            async src="https://dr.eamer.dev/analytics/count.js"></script>
</body>
</html>
