Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" | |
| content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> | |
| <meta name="screen-orientation" content="portrait"> | |
| <meta name="x5-orientation" content="portrait"> | |
| <meta name="mobile-web-app-capable" content="yes"> | |
| <meta name="apple-mobile-web-app-capable" content="yes"> | |
| <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> | |
| <title>STEM Copilot</title> | |
| <meta name="description" content="AI-powered NCERT tutor for Class XI and XII Physics, Chemistry, and Mathematics."> | |
| <meta name="theme-color" content="#0a0a0a"> | |
| <link rel="icon" type="image/png" href="/assets/bot.png"> | |
| <link rel="manifest" href="/manifest.json"> | |
| <link rel="apple-touch-icon" href="/assets/stem_black.png"> | |
| <!-- Preconnect for faster font/CDN loading --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css"> | |
| <link rel="stylesheet" href="/static/style.css"> | |
| <!-- Google Identity Services: loaded dynamically by initGoogleAuth() in app.js --> | |
| </head> | |
| <body> | |
| <!-- ==================== LOGIN SCREEN ==================== --> | |
| <div class="login-screen" id="loginScreen"> | |
| <div class="login-top-actions"> | |
| <button class="login-theme-btn" id="loginThemeBtn" title="Toggle dark / light mode"> | |
| <svg class="icon-sun" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"> | |
| <circle cx="12" cy="12" r="5" /> | |
| <line x1="12" y1="1" x2="12" y2="3" /> | |
| <line x1="12" y1="21" x2="12" y2="23" /> | |
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" /> | |
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" /> | |
| <line x1="1" y1="12" x2="3" y2="12" /> | |
| <line x1="21" y1="12" x2="23" y2="12" /> | |
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" /> | |
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" /> | |
| </svg> | |
| <svg class="icon-moon" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="login-card"> | |
| <img src="/assets/stembotix.png" alt="STEM Copilot" class="login-logo-stembotix"> | |
| <h1 class="login-title">Welcome to STEM Copilot</h1> | |
| <p class="login-subtitle">Your personal NCERT tutor for Physics, Chemistry & Mathematics</p> | |
| <div id="gsi-hidden-btn" style="position:fixed;top:-9999px;left:-9999px;opacity:0;pointer-events:none;"> | |
| </div> | |
| <div class="google-btn-wrap"> | |
| <button id="customGoogleBtn" class="gsi-custom-btn" onclick="triggerGoogleSignIn()"> | |
| <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"> | |
| <path fill="#2231D4" | |
| d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.875 2.684-6.615z" /> | |
| <path fill="#34A853" | |
| d="M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z" /> | |
| <path fill="#FBBC05" | |
| d="M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z" /> | |
| <path fill="#EA4335" | |
| d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 6.29C4.672 4.163 6.656 3.58 9 3.58z" /> | |
| </svg> | |
| <span>Sign in with Google</span> | |
| </button> | |
| </div> | |
| <p class="login-footer">By signing in, you agree to our <a href="https://www.stembotix.com/terms-policy" target="_blank" rel="noopener" class="terms-link">Terms of Service</a>.</p> | |
| </div> | |
| </div> | |
| <!-- ==================== BYOK SCREEN ==================== --> | |
| <div class="byok-screen" id="byokScreen" style="display:none;"> | |
| <div class="byok-card"> | |
| <h2>One Last Step</h2> | |
| <p class="byok-desc"> | |
| STEM Copilot uses your own OpenRouter API key to power the tutor. | |
| It's free — takes 30 seconds to set up. | |
| </p> | |
| <ol class="byok-steps"> | |
| <li>Go to <a href="https://openrouter.ai/workspaces/default/keys" target="_blank" | |
| rel="noopener">openrouter.ai/keys</a></li> | |
| <li>Create a new key (free)</li> | |
| <li>Paste it below</li> | |
| </ol> | |
| <input type="text" id="byokInput" class="settings-input" placeholder="Paste your OpenRouter API key here" | |
| autocomplete="off" spellcheck="false"> | |
| <div class="byok-optional"> | |
| <p class="byok-optional-label">Tavily API key <span class="byok-optional-badge">Optional</span></p> | |
| <p class="byok-optional-desc">Add it to unlock live web search. Skip it and web search stays disabled.</p> | |
| <input type="text" id="byokTavilyInput" class="settings-input" placeholder="Paste your Tavily API key (optional)" | |
| autocomplete="off" spellcheck="false"> | |
| <p class="byok-optional-hint">Get a free Tavily key at | |
| <a href="https://app.tavily.com/home" target="_blank" rel="noopener">app.tavily.com</a> | |
| </p> | |
| </div> | |
| <button class="byok-submit-btn" id="byokSubmitBtn">Start Learning</button> | |
| <p class="byok-note">Your keys are stored securely and never shared.</p> | |
| </div> | |
| </div> | |
| <!-- ==================== PWA INSTALL BANNER ==================== --> | |
| <div class="install-banner" id="installBanner" style="display:none;"> | |
| <img src="/assets/bot.png" alt="" class="install-banner-icon"> | |
| <div class="install-banner-text"> | |
| <strong>STEM Copilot</strong> | |
| <span>Install as app for faster access</span> | |
| </div> | |
| <button class="install-banner-btn" id="installBtn">Install</button> | |
| <button class="install-banner-dismiss" id="installDismiss">×</button> | |
| </div> | |
| <!-- ==================== MOBILE TOP NAV BAR ==================== --> | |
| <div class="mobile-topbar" id="mobileTopbar"> | |
| <button class="topbar-profile-btn" id="topbarProfileBtn" title="Account"> | |
| <img id="topbarAvatar" class="topbar-avatar" src="/assets/bot.png" alt=""> | |
| </button> | |
| <img src="/assets/stembotix.png" alt="STEM Copilot" class="topbar-logo"> | |
| <div class="topbar-actions"> | |
| <button class="topbar-icon-btn" id="topbarHistoryBtn" title="Chat history"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| stroke-linecap="round" stroke-linejoin="round"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| </button> | |
| <button class="topbar-icon-btn" id="topbarNewChatBtn" title="New chat"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M12 5v14M5 12h14" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- ==================== MOBILE ACCOUNT OVERLAY ==================== --> | |
| <div class="fullscreen-overlay" id="accountOverlay"> | |
| <div class="overlay-header"> | |
| <h2>Account</h2> | |
| <button class="overlay-close-btn" id="accountOverlayClose">×</button> | |
| </div> | |
| <div class="overlay-body"> | |
| <div class="overlay-user-info" id="overlayUserInfo"> | |
| <img id="overlayUserAvatar" class="overlay-avatar" src="/assets/bot.png" alt=""> | |
| <div class="overlay-user-details"> | |
| <span class="overlay-user-name" id="overlayUserName">Student</span> | |
| <span class="overlay-user-email" id="overlayUserEmail"></span> | |
| </div> | |
| </div> | |
| <div class="overlay-menu"> | |
| <button class="overlay-menu-item" id="overlaySettingsBtn"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <circle cx="12" cy="12" r="3" /> | |
| <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /> | |
| </svg> | |
| Settings | |
| </button> | |
| <button class="overlay-menu-item overlay-menu-logout" id="overlayLogoutBtn"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /> | |
| <polyline points="16 17 21 12 16 7" /> | |
| <line x1="21" y1="12" x2="9" y2="12" /> | |
| </svg> | |
| Log out | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ==================== MOBILE HISTORY OVERLAY ==================== --> | |
| <div class="fullscreen-overlay" id="historyOverlay"> | |
| <div class="overlay-header"> | |
| <h2>Chat History</h2> | |
| <button class="overlay-close-btn" id="historyOverlayClose">×</button> | |
| </div> | |
| <div class="overlay-body"> | |
| <div class="overlay-history-list" id="overlayHistoryList"></div> | |
| <div class="overlay-empty-state" id="overlayHistoryEmpty"> | |
| <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" style="opacity:0.3"> | |
| <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/> | |
| </svg> | |
| <p>No conversations yet</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Mobile sidebar overlay (kept for edge-swipe on mobile) --> | |
| <div class="sidebar-overlay" id="sidebarOverlay"></div> | |
| <!-- ==================== MAIN APP ==================== --> | |
| <div class="app-container" id="appContainer" style="display:none;"> | |
| <!-- Sidebar (full — desktop only) --> | |
| <aside class="sidebar collapsed" id="sidebar"> | |
| <div class="sidebar-top"> | |
| <div class="sidebar-logo-row"> | |
| <img src="/assets/stembotix.png" alt="STEMbotix" class="sidebar-logo"> | |
| </div> | |
| <button class="new-chat-btn" id="newChatBtn"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M12 5v14M5 12h14" /> | |
| </svg> | |
| New Chat | |
| </button> | |
| <div class="chat-history" id="chatHistoryList"></div> | |
| </div> | |
| <div class="sidebar-bottom"> | |
| <div class="user-profile-btn" id="userProfileBtn"> | |
| <img id="userAvatar" class="user-avatar" src="" alt=""> | |
| <span id="userDisplayName" class="user-name">Student</span> | |
| </div> | |
| <!-- User menu popup --> | |
| <div class="user-menu" id="userMenu"> | |
| <div class="user-menu-item" id="openSettingsBtn"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <circle cx="12" cy="12" r="3" /> | |
| <path | |
| d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /> | |
| </svg> | |
| Settings | |
| </div> | |
| <div class="user-menu-item user-menu-logout" id="logoutBtn"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /> | |
| <polyline points="16 17 21 12 16 7" /> | |
| <line x1="21" y1="12" x2="9" y2="12" /> | |
| </svg> | |
| Log out | |
| </div> | |
| </div> | |
| </div> | |
| </aside> | |
| <!-- Sidebar rail (collapsed, desktop only) --> | |
| <aside class="sidebar-rail" id="sidebarRail"> | |
| <div class="rail-top"> | |
| <button class="rail-icon-btn" id="railExpandBtn" title="Open sidebar"> | |
| <img src="/assets/stem_transparent.png" alt="S" class="rail-logo"> | |
| </button> | |
| <button class="rail-icon-btn" id="railNewChatBtn" title="New chat"> | |
| <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M12 5v14M5 12h14" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="rail-bottom"> | |
| <button class="rail-icon-btn" id="railProfileBtn" title="Profile"> | |
| <img id="railAvatar" class="rail-avatar" src="" alt=""> | |
| </button> | |
| </div> | |
| </aside> | |
| <!-- Main --> | |
| <main class="main-chat"> | |
| <!-- Desktop header --> | |
| <header class="main-header" id="mainHeader"> | |
| <button class="toggle-sidebar-btn" id="toggleSidebarBtn" title="Toggle Sidebar"> | |
| <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| stroke-linecap="round" stroke-linejoin="round"> | |
| <rect x="3" y="3" width="18" height="18" rx="2" ry="2" /> | |
| <line x1="9" y1="3" x2="9" y2="21" /> | |
| </svg> | |
| </button> | |
| </header> | |
| <div class="chat-container" id="chatContainer"> | |
| <!-- Hero / Welcome screen --> | |
| <div class="hero-welcome" id="welcomeScreen"> | |
| <img src="/assets/bot.png" alt="STEM Copilot" class="hero-bot-icon"> | |
| <h1 class="hero-title" id="heroTitle">What should we study today?</h1> | |
| <div class="hero-input-wrap"> | |
| <!-- Image / Doc preview in hero --> | |
| <div class="hero-image-preview" id="heroImagePreview"> | |
| <div class="hero-image-preview-thumb" id="heroImagePreviewThumb"></div> | |
| <span class="image-preview-name" id="heroImagePreviewName"></span> | |
| <button class="hero-image-preview-remove" id="heroImagePreviewRemove">×</button> | |
| </div> | |
| <!-- Tool progress bar (hero) --> | |
| <div class="tool-progress-bar" id="heroToolProgressBar"> | |
| <div class="tool-progress-label" id="heroToolProgressLabel">Searching...</div> | |
| <div class="tool-progress-track"><div class="tool-progress-fill" id="heroToolProgressFill"></div></div> | |
| </div> | |
| <div class="hero-input-box" id="heroInputBox"> | |
| <!-- + Attach menu (Hero) --> | |
| <div class="attach-wrap" id="heroAttachWrap"> | |
| <button class="attach-plus-btn" id="heroAttachPlusBtn" title="Attach or search"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> | |
| <line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/> | |
| </svg> | |
| </button> | |
| <div class="attach-menu" id="heroAttachMenu"> | |
| <button class="attach-menu-item" id="heroWebSearchToggle" data-active="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> | |
| <span class="attach-menu-label">Web Search</span> | |
| <span class="attach-info" tabindex="0" role="button" aria-label="About web search" data-tip="Search the live web for current info and topics beyond Physics, Chemistry & Maths. Requires a Tavily API key."> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> | |
| </span> | |
| </button> | |
| <button class="attach-menu-item" id="heroYtSearchToggle" data-active="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg> | |
| <span class="attach-menu-label">YouTube Video</span> | |
| <span class="attach-info" tabindex="0" role="button" aria-label="About YouTube search" data-tip="Paste a YouTube link and I'll use the video's transcript to answer your questions about it."> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> | |
| </span> | |
| </button> | |
| <button class="attach-menu-item" id="heroAttachFileBtn"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg> | |
| <span class="attach-menu-label">Add Photos/Files</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Hidden file inputs --> | |
| <input type="file" id="heroImageInput" accept="image/*" style="display:none;"> | |
| <input type="file" id="heroDocInput" accept=".pdf,.doc,.docx,.txt,.md,.py,.js,.ts,.csv" style="display:none;"> | |
| <textarea id="heroInput" placeholder="Ask STEM Copilot..." rows="1"></textarea> | |
| <!-- Teaching style selector (scrollable) --> | |
| <div class="style-selector-wrap" id="heroStyleSelectorWrap"> | |
| <button class="style-selector-btn" id="heroStyleSelectorBtn" title="Teaching style"> | |
| <span id="heroStyleSelectorLabel">Vidyut</span> | |
| <svg viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9" /></svg> | |
| </button> | |
| <div class="style-dropdown" id="heroStyleDropdown"> | |
| <div class="style-option active" data-persona="vidyut"> | |
| <div class="style-option-name">Guru</div> | |
| <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div> | |
| </div> | |
| <div class="style-option" data-persona="nerd"> | |
| <div class="style-option-name">Nerd</div> | |
| <div class="style-option-desc">Deep, rigorous, first-principles. Goes beyond the textbook.</div> | |
| </div> | |
| <div class="style-option" data-persona="noob"> | |
| <div class="style-option-name">Beginner</div> | |
| <div class="style-option-desc">Patient, step-by-step. Explains like you're seeing it for the first time.</div> | |
| </div> | |
| <div class="style-option" data-persona="thoughtful"> | |
| <div class="style-option-name">Thoughtful</div> | |
| <div class="style-option-desc">Connects science to the real world. Every formula has a story.</div> | |
| </div> | |
| <div class="style-option" data-persona="panic"> | |
| <div class="style-option-name">Panic</div> | |
| <div class="style-option-desc">Exam tomorrow? Concise bullets, key formulas, no fluff.</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Adaptive action button: mic when empty, send when text present --> | |
| <button class="adaptive-action-btn" id="heroAdaptiveBtn" title="Voice input"> | |
| <svg class="icon-mic" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" /><path d="M19 10v2a7 7 0 0 1-14 0v-2" /><line x1="12" y1="19" x2="12" y2="23" /><line x1="8" y1="23" x2="16" y2="23" /></svg> | |
| <svg class="icon-send" viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Hero pills REMOVED per todo item 3 --> | |
| </div> | |
| </div> | |
| <!-- Bottom input (hidden during hero, shown during chat) --> | |
| <div class="input-container" id="bottomInputContainer" style="display:none;"> | |
| <!-- Tool progress bar (shown while web/yt tool is running) --> | |
| <div class="tool-progress-bar" id="toolProgressBar" style="display:none;"> | |
| <div class="tool-progress-label" id="toolProgressLabel">Searching...</div> | |
| <div class="tool-progress-track"><div class="tool-progress-fill" id="toolProgressFill"></div></div> | |
| </div> | |
| <!-- Image/Doc preview --> | |
| <div class="image-preview-bar" id="imagePreviewBar" style="display:none;"> | |
| <div class="image-preview-thumb" id="imagePreviewThumb"></div> | |
| <span class="image-preview-name" id="imagePreviewName"></span> | |
| <button class="image-preview-remove" id="imagePreviewRemove">×</button> | |
| </div> | |
| <div class="input-box" id="inputBox"> | |
| <!-- + Attach menu --> | |
| <div class="attach-wrap" id="attachWrap"> | |
| <button class="attach-plus-btn" id="attachPlusBtn" title="Attach or search"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> | |
| <line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/> | |
| </svg> | |
| </button> | |
| <div class="attach-menu" id="attachMenu"> | |
| <button class="attach-menu-item" id="webSearchToggle" data-active="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> | |
| <span class="attach-menu-label">Web Search</span> | |
| <span class="attach-info" tabindex="0" role="button" aria-label="About web search" data-tip="Search the live web for current info and topics beyond Physics, Chemistry & Maths. Requires a Tavily API key."> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> | |
| </span> | |
| </button> | |
| <button class="attach-menu-item" id="ytSearchToggle" data-active="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg> | |
| <span class="attach-menu-label">YouTube Video</span> | |
| <span class="attach-info" tabindex="0" role="button" aria-label="About YouTube search" data-tip="Paste a YouTube link and I'll use the video's transcript to answer your questions about it."> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg> | |
| </span> | |
| </button> | |
| <button class="attach-menu-item" id="attachFileBtn"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg> | |
| <span class="attach-menu-label">Add Photos/Files</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Hidden file inputs --> | |
| <input type="file" id="imageInput" accept="image/*" style="display:none;"> | |
| <input type="file" id="docInput" accept=".pdf,.doc,.docx,.txt,.md,.py,.js,.ts,.csv" style="display:none;"> | |
| <textarea id="userInput" placeholder="Ask STEM Copilot..." rows="1"></textarea> | |
| <!-- Teaching style selector --> | |
| <div class="style-selector-wrap" id="styleSelectorWrap"> | |
| <button class="style-selector-btn" id="styleSelectorBtn" title="Teaching style"> | |
| <span id="styleSelectorLabel">Guru</span> | |
| <svg viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9" /></svg> | |
| </button> | |
| <div class="style-dropdown" id="styleDropdown"> | |
| <div class="style-option active" data-persona="vidyut"> | |
| <div class="style-option-name">Guru</div> | |
| <div class="style-option-desc">Calm, clear, step-by-step master teacher. Makes hard concepts obvious.</div> | |
| </div> | |
| <div class="style-option" data-persona="nerd"> | |
| <div class="style-option-name">Nerd</div> | |
| <div class="style-option-desc">Deep, rigorous, first-principles. Goes beyond the textbook.</div> | |
| </div> | |
| <div class="style-option" data-persona="noob"> | |
| <div class="style-option-name">Beginner</div> | |
| <div class="style-option-desc">Patient, step-by-step. Explains like you're seeing it for the first time.</div> | |
| </div> | |
| <div class="style-option" data-persona="thoughtful"> | |
| <div class="style-option-name">Thoughtful</div> | |
| <div class="style-option-desc">Connects science to the real world. Every formula has a story.</div> | |
| </div> | |
| <div class="style-option" data-persona="panic"> | |
| <div class="style-option-name">Panic</div> | |
| <div class="style-option-desc">Exam tomorrow? Concise bullets, key formulas, no fluff.</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Adaptive action button + stop --> | |
| <button class="adaptive-action-btn" id="adaptiveBtn" title="Voice input"> | |
| <svg class="icon-mic" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" /><path d="M19 10v2a7 7 0 0 1-14 0v-2" /><line x1="12" y1="19" x2="12" y2="23" /><line x1="8" y1="23" x2="16" y2="23" /></svg> | |
| <svg class="icon-send" viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"></path></svg> | |
| </button> | |
| <button class="stop-btn" id="stopBtn" title="Stop generating"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"> | |
| <rect x="7" y="7" width="10" height="10" rx="1" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="disclaimer-text"> | |
| STEM Copilot is AI and can make mistakes. | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- ==================== SETTINGS MODAL ==================== --> | |
| <div class="modal-overlay" id="settingsOverlay"> | |
| <div class="settings-modal" id="settingsModal"> | |
| <div class="modal-header"> | |
| <h2>Settings</h2> | |
| <button class="modal-close" id="settingsCloseBtn">×</button> | |
| </div> | |
| <div class="modal-body settings-layout"> | |
| <!-- Vertical Tab Navigation --> | |
| <div class="settings-nav"> | |
| <button class="settings-nav-btn active" data-tab="general"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <circle cx="12" cy="12" r="3" /> | |
| <path | |
| d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.6 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" /> | |
| </svg> | |
| <span>General</span> | |
| </button> | |
| <button class="settings-nav-btn" data-tab="apikeys"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <path | |
| d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" /> | |
| </svg> | |
| <span>API Keys</span> | |
| </button> | |
| <button class="settings-nav-btn" data-tab="personalization"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" /> | |
| <circle cx="12" cy="7" r="4" /> | |
| </svg> | |
| <span>Profile</span> | |
| </button> | |
| <button class="settings-nav-btn" data-tab="feedback"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <path | |
| d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" /> | |
| </svg> | |
| <span>Feedback</span> | |
| </button> | |
| </div><!-- /settings-nav --> | |
| <!-- Settings Content Panel --> | |
| <div class="settings-panel"> | |
| <!-- General Tab --> | |
| <div class="tab-content active" id="tab-general"> | |
| <h3 class="settings-section-title">Language</h3> | |
| <select class="settings-select" id="languageSelect" style="display:none;"> | |
| <option value="auto">Auto-detect</option> | |
| <option value="english">English</option> | |
| <option value="hinglish">Hinglish</option> | |
| <option value="hindi">Hindi</option> | |
| <option value="gujarati">Gujarati</option> | |
| <option value="marathi">Marathi</option> | |
| <option value="french">French</option> | |
| </select> | |
| <div class="custom-select-wrap" id="languageSelectWrap"> | |
| <button type="button" class="custom-select-btn" id="languageSelectBtn"> | |
| <span>Auto-detect</span> | |
| <svg viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9" /></svg> | |
| </button> | |
| <div class="custom-select-list" id="languageSelectList"> | |
| <div class="custom-select-option active" data-value="auto">Auto-detect</div> | |
| <div class="custom-select-option" data-value="english">English</div> | |
| <div class="custom-select-option" data-value="hinglish">Hinglish</div> | |
| <div class="custom-select-option" data-value="hindi">Hindi</div> | |
| <div class="custom-select-option" data-value="gujarati">Gujarati</div> | |
| <div class="custom-select-option" data-value="marathi">Marathi</div> | |
| <div class="custom-select-option" data-value="french">French</div> | |
| </div> | |
| </div> | |
| <h3 class="settings-section-title">Theme</h3> | |
| <div class="theme-option-group"> | |
| <button class="theme-option-btn" data-theme-val="dark" id="themeDarkBtn"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" /> | |
| </svg> | |
| Dark | |
| </button> | |
| <button class="theme-option-btn" data-theme-val="light" id="themeLightBtn"> | |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <circle cx="12" cy="12" r="5" /> | |
| <line x1="12" y1="1" x2="12" y2="3" /> | |
| <line x1="12" y1="21" x2="12" y2="23" /> | |
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" /> | |
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" /> | |
| <line x1="1" y1="12" x2="3" y2="12" /> | |
| <line x1="21" y1="12" x2="23" y2="12" /> | |
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" /> | |
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" /> | |
| </svg> | |
| Light | |
| </button> | |
| </div> | |
| </div> | |
| <!-- API Keys Tab --> | |
| <div class="tab-content" id="tab-apikeys"> | |
| <div class="apikey-group"> | |
| <h3 class="settings-section-title">OpenRouter API Key</h3> | |
| <p class="settings-hint"> | |
| Powers the tutor. Get your free key at | |
| <a href="https://openrouter.ai/workspaces/default/keys" target="_blank" | |
| rel="noopener">openrouter.ai/keys</a> | |
| </p> | |
| <input type="password" class="settings-input" id="settingsApiKeyInput" placeholder="sk-or-..." | |
| autocomplete="off" spellcheck="false"> | |
| <button class="settings-save-btn" id="saveApiKeyBtn">Save Key</button> | |
| </div> | |
| <div class="apikey-group"> | |
| <h3 class="settings-section-title">Tavily API Key <span class="settings-optional-badge">Optional</span></h3> | |
| <p class="settings-hint"> | |
| Enables live web search. Get a free key at | |
| <a href="https://app.tavily.com/home" target="_blank" rel="noopener">app.tavily.com</a> | |
| </p> | |
| <input type="password" class="settings-input" id="settingsTavilyKeyInput" placeholder="tvly-..." | |
| autocomplete="off" spellcheck="false"> | |
| <button class="settings-save-btn" id="saveTavilyKeyBtn">Save Key</button> | |
| </div> | |
| </div> | |
| <!-- Profile Tab --> | |
| <div class="tab-content" id="tab-personalization"> | |
| <h3 class="settings-section-title">Your Name</h3> | |
| <input type="text" class="settings-input" id="usernameInput" | |
| placeholder="What should I call you?" maxlength="30" autocomplete="off"> | |
| <h3 class="settings-section-title" style="margin-top:20px;">About You</h3> | |
| <textarea class="settings-textarea" id="profileInput" | |
| placeholder="e.g. I'm in Class XII, preparing for JEE. Physics and Maths scare me. I'm good at Chemistry." | |
| rows="4"></textarea> | |
| <button class="settings-save-btn" id="saveProfileBtn">Save Profile</button> | |
| </div> | |
| <!-- Feedback Tab --> | |
| <div class="tab-content" id="tab-feedback"> | |
| <!-- Overall rating --> | |
| <h3 class="settings-section-title">Rate Your Experience</h3> | |
| <div class="fb-stars" id="fbStars"> | |
| <span class="fb-star" data-val="1"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> | |
| </span> | |
| <span class="fb-star" data-val="2"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> | |
| </span> | |
| <span class="fb-star" data-val="3"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> | |
| </span> | |
| <span class="fb-star" data-val="4"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> | |
| </span> | |
| <span class="fb-star" data-val="5"> | |
| <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg> | |
| </span> | |
| </div> | |
| <input type="hidden" id="fbOverall" value="0"> | |
| <!-- Sub-ratings row --> | |
| <div class="fb-subratings"> | |
| <div class="fb-subrating-group"> | |
| <span class="fb-subrating-label">Ease of Use</span> | |
| <div class="fb-emojis" id="fbEaseEmojis" data-field="fbEase"> | |
| <!-- Poor: frown face --> | |
| <span class="fb-emoji" data-val="1" title="Poor"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M16 16s-1.5-2-4-2-4 2-4 2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <!-- Fair: neutral/meh face --> | |
| <span class="fb-emoji" data-val="2" title="Fair"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="8" y1="15" x2="16" y2="15"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <!-- Good: smile face --> | |
| <span class="fb-emoji" data-val="3" title="Good"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 13s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <!-- Excellent: big smile / star-eyes --> | |
| <span class="fb-emoji" data-val="4" title="Excellent"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 13s1.5 3 4 3 4-3 4-3"/><path d="M9 9l.5.5-.5.5-.5-.5z" fill="currentColor"/><path d="M15 9l.5.5-.5.5-.5-.5z" fill="currentColor"/></svg> | |
| </span> | |
| </div> | |
| <input type="hidden" id="fbEase" value="0"> | |
| </div> | |
| <div class="fb-subrating-group"> | |
| <span class="fb-subrating-label">Response Quality</span> | |
| <div class="fb-emojis" id="fbQualityEmojis" data-field="fbQuality"> | |
| <span class="fb-emoji" data-val="1" title="Poor"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M16 16s-1.5-2-4-2-4 2-4 2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <span class="fb-emoji" data-val="2" title="Fair"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="8" y1="15" x2="16" y2="15"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <span class="fb-emoji" data-val="3" title="Good"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 13s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg> | |
| </span> | |
| <span class="fb-emoji" data-val="4" title="Excellent"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M8 13s1.5 3 4 3 4-3 4-3"/><path d="M9 9l.5.5-.5.5-.5-.5z" fill="currentColor"/><path d="M15 9l.5.5-.5.5-.5-.5z" fill="currentColor"/></svg> | |
| </span> | |
| </div> | |
| <input type="hidden" id="fbQuality" value="0"> | |
| </div> | |
| </div> | |
| <!-- Category --> | |
| <h3 class="settings-section-title" style="margin-top:18px;">Category</h3> | |
| <div class="fb-categories"> | |
| <button type="button" class="fb-cat-btn active" data-val="bug"> | |
| <svg class="fb-cat-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2l1.88 1.88"/><path d="M14.12 3.88L16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6z"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg> | |
| Bug Report | |
| </button> | |
| <button type="button" class="fb-cat-btn" data-val="feature"> | |
| <svg class="fb-cat-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="2" x2="12" y2="6"/><line x1="12" y1="18" x2="12" y2="22"/><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"/><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"/><line x1="2" y1="12" x2="6" y2="12"/><line x1="18" y1="12" x2="22" y2="12"/><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"/><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"/></svg> | |
| Feature | |
| </button> | |
| <button type="button" class="fb-cat-btn" data-val="iam"> | |
| <svg class="fb-cat-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg> | |
| IAM Policy | |
| </button> | |
| <button type="button" class="fb-cat-btn" data-val="documentation"> | |
| <svg class="fb-cat-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg> | |
| Docs | |
| </button> | |
| <button type="button" class="fb-cat-btn" data-val="other"> | |
| <svg class="fb-cat-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> | |
| Other | |
| </button> | |
| </div> | |
| <input type="hidden" id="fbCategory" value="bug"> | |
| <!-- Message --> | |
| <h3 class="settings-section-title" style="margin-top:18px;">Message <span style="color:var(--brand);font-size:11px;margin-left:4px;">required</span></h3> | |
| <textarea class="settings-textarea" id="feedbackMessage" rows="4" | |
| placeholder="Describe the issue, feature idea, or your thoughts..."></textarea> | |
| <!-- Image attachments --> | |
| <h3 class="settings-section-title" style="margin-top:14px;">Attach Screenshots <span style="color:var(--text-muted);font-size:11px;font-weight:400;margin-left:4px;">up to 5</span></h3> | |
| <div class="fb-attach-area" id="fbAttachArea"> | |
| <input type="file" id="fbImageInput" accept="image/*" multiple style="display:none;"> | |
| <div class="fb-attach-chips" id="fbAttachChips"></div> | |
| <button type="button" class="fb-attach-btn" id="fbAttachBtn"> | |
| <svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg> | |
| Add images | |
| </button> | |
| </div> | |
| <!-- Submit --> | |
| <button class="settings-save-btn" id="submitFeedbackBtn" style="width:100%;margin-top:18px;"> | |
| Send Feedback | |
| </button> | |
| <!-- Cooldown bar --> | |
| <div class="fb-cooldown-wrap" id="fbCooldownWrap" style="display:none;"> | |
| <div class="fb-cooldown-bar" id="fbCooldownBar"></div> | |
| <span class="fb-cooldown-label" id="fbCooldownLabel">Please wait 60s before sending again</span> | |
| </div> | |
| </div> | |
| </div><!-- /settings-panel --> | |
| </div><!-- /settings-layout --> | |
| </div><!-- /settings-modal --> | |
| </div><!-- /settingsOverlay --> | |
| <!-- ==================== PWA CONFIRM MODAL ==================== --> | |
| <div class="pwa-modal-overlay" id="pwaConfirmOverlay"> | |
| <div class="pwa-modal"> | |
| <p class="pwa-modal-message" id="pwaConfirmMessage">Are you sure?</p> | |
| <div class="pwa-modal-actions"> | |
| <button class="pwa-modal-btn pwa-modal-cancel" id="pwaConfirmCancel">No</button> | |
| <button class="pwa-modal-btn pwa-modal-ok" id="pwaConfirmOk">Yes</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ==================== PWA PROMPT MODAL ==================== --> | |
| <div class="pwa-modal-overlay" id="pwaPromptOverlay"> | |
| <div class="pwa-modal"> | |
| <p class="pwa-modal-message" id="pwaPromptMessage">Enter value:</p> | |
| <input type="text" class="pwa-modal-input" id="pwaPromptInput" autocomplete="off" spellcheck="false"> | |
| <div class="pwa-modal-actions"> | |
| <button class="pwa-modal-btn pwa-modal-cancel" id="pwaPromptCancel">Cancel</button> | |
| <button class="pwa-modal-btn pwa-modal-ok" id="pwaPromptOk">Save</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Dependencies --> | |
| <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script> | |
| <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"></script> | |
| <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/mhchem.min.js"></script> | |
| <script defer src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
| <script defer src="/static/app.js"></script> | |
| </body> | |
| </html> |