Spaces:
Sleeping
Sleeping
| <html lang="en" dir="ltr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> | |
| <meta name="description" content="Arjun 2.O Advanced Artificial Intelligence System engineered by Abhay Kumar."> | |
| <meta name="theme-color" content="#FF9933"> | |
| <title>Arjun 2.O - Professional Advanced AI</title> | |
| <!-- ========================================================================================= | |
| 1. EXTERNAL RESOURCES & LIBRARIES (बाहरी स्रोत) | |
| ========================================================================================= --> | |
| <!-- Preconnect for Performance --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <!-- Professional Typography: Inter (Sans), Geist Mono (Code), Instrument Serif (Display) --> | |
| <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@300;400;500;600;700;800;900&family=Geist+Mono:wght@400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Syntax Highlighting Theme (Atom One Dark for Professional Coding Workspace) --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css"> | |
| <!-- Core External Scripts for Data Extraction and Rendering --> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script> | |
| <!-- ========================================================================================= | |
| 2. ENTERPRISE CSS ARCHITECTURE (विस्तृत स्टाइलिंग) | |
| ========================================================================================= --> | |
| <style> | |
| /* --------------------------------------------------------------------------------------- | |
| A. CSS VARIABLES & DESIGN TOKENS (TIRANGA THEME) | |
| --------------------------------------------------------------------------------------- */ | |
| :root { | |
| /* Branding: Professional Tiranga Theme */ | |
| --brand-saffron: #FF9933; | |
| --brand-saffron-light: rgba(255, 153, 51, 0.12); | |
| --brand-saffron-dark: #e68a2e; | |
| --brand-white: #FFFFFF; | |
| --brand-white-glass: rgba(255, 255, 255, 0.85); | |
| --brand-green: #138808; | |
| --brand-green-light: rgba(19, 136, 8, 0.12); | |
| --brand-green-dark: #0f6e06; | |
| /* Core UI Colors */ | |
| --bg-primary: #ffffff; | |
| --bg-secondary: #f8f9fa; | |
| --bg-tertiary: #f1f3f5; | |
| --bg-glass: rgba(255, 255, 255, 0.75); | |
| /* Text Hierarchy */ | |
| --text-primary: #111827; | |
| --text-secondary: #4b5563; | |
| --text-tertiary: #9ca3af; | |
| --text-inverse: #ffffff; | |
| /* Border & Shadows */ | |
| --border-light: rgba(0, 0, 0, 0.08); | |
| --border-medium: rgba(0, 0, 0, 0.15); | |
| --shadow-sm: 0 1px 3px rgba(0,0,0,0.05), 0 1px 2px rgba(0,0,0,0.03); | |
| --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.05), 0 2px 4px -1px rgba(0,0,0,0.03); | |
| --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.05), 0 4px 6px -2px rgba(0,0,0,0.025); | |
| --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.05), 0 10px 10px -5px rgba(0,0,0,0.02); | |
| /* Typography Scale */ | |
| --font-sans: 'Inter', sans-serif; | |
| --font-mono: 'Geist Mono', monospace; | |
| /* Radii */ | |
| --radius-sm: 8px; | |
| --radius-md: 12px; | |
| --radius-lg: 16px; | |
| --radius-xl: 24px; | |
| --radius-full: 9999px; | |
| /* Transitions */ | |
| --ease-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1); | |
| --ease-smooth: 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| --ease-spring: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); | |
| /* Z-Index */ | |
| --z-bg: -1; | |
| --z-base: 1; | |
| --z-overlay: 10; | |
| --z-dropdown: 50; | |
| --z-sidebar: 100; | |
| --z-modal: 5000; | |
| --z-toast: 9000; | |
| --z-live-mode: 9999; | |
| } | |
| /* --------------------------------------------------------------------------------------- | |
| B. RESET & GLOBAL BASE | |
| --------------------------------------------------------------------------------------- */ | |
| *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } | |
| html { font-size: 16px; -webkit-text-size-adjust: 100%; } | |
| body { | |
| height: 100dvh; width: 100vw; overflow: hidden; | |
| background-color: var(--bg-primary); color: var(--text-primary); | |
| font-family: var(--font-sans); line-height: 1.5; | |
| -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; | |
| } | |
| button, input, textarea { font-family: inherit; color: inherit; } | |
| a { color: inherit; text-decoration: none; } | |
| img { max-width: 100%; height: auto; display: block; } | |
| /* --------------------------------------------------------------------------------------- | |
| C. AMBIENT BACKGROUND EFFECTS | |
| --------------------------------------------------------------------------------------- */ | |
| .ambient-environment { | |
| position: fixed; inset: 0; z-index: var(--z-bg); overflow: hidden; pointer-events: none; | |
| background: linear-gradient(135deg, var(--brand-saffron-light) 0%, #ffffff 50%, var(--brand-green-light) 100%); | |
| } | |
| .ambient-orb { | |
| position: absolute; border-radius: 50%; filter: blur(120px); opacity: 0.45; | |
| animation: orbFloat 35s ease-in-out infinite alternate; will-change: transform; | |
| } | |
| .orb-top-left { width: 650px; height: 650px; background: radial-gradient(circle, rgba(255,153,51,0.25) 0%, transparent 70%); top: -200px; left: -150px; } | |
| .orb-bottom-right { width: 550px; height: 550px; background: radial-gradient(circle, rgba(19,136,8,0.2) 0%, transparent 70%); bottom: -150px; right: -100px; animation-delay: -15s; } | |
| @keyframes orbFloat { 0% { transform: translate(0, 0) scale(1); } 33% { transform: translate(60px, 80px) scale(1.1); } 66% { transform: translate(-40px, 50px) scale(0.95); } 100% { transform: translate(70px, -30px) scale(1.05); } } | |
| /* --------------------------------------------------------------------------------------- | |
| D. TOAST NOTIFICATION SYSTEM | |
| --------------------------------------------------------------------------------------- */ | |
| .toast-wrapper { position: absolute; top: 24px; left: 50%; transform: translateX(-50%); z-index: var(--z-toast); display: flex; flex-direction: column; gap: 12px; pointer-events: none; } | |
| .toast-notification { | |
| background: var(--text-primary); color: var(--text-inverse); padding: 14px 28px; | |
| border-radius: var(--radius-full); font-size: 14px; font-weight: 600; box-shadow: var(--shadow-lg); | |
| animation: toastSlideIn var(--ease-spring) forwards, toastFadeOut 0.4s 3.6s forwards; | |
| display: flex; align-items: center; gap: 10px; | |
| } | |
| @keyframes toastSlideIn { from { opacity: 0; transform: translateY(-30px) scale(0.9); } to { opacity: 1; transform: translateY(0) scale(1); } } | |
| @keyframes toastFadeOut { from { opacity: 1; transform: translateY(0); } to { opacity: 0; transform: translateY(-20px); } } | |
| /* --------------------------------------------------------------------------------------- | |
| E. INITIAL WELCOME OVERLAY | |
| --------------------------------------------------------------------------------------- */ | |
| .startup-overlay { | |
| position: fixed; inset: 0; background: var(--brand-white-glass); | |
| backdrop-filter: blur(25px); -webkit-backdrop-filter: blur(25px); z-index: calc(var(--z-toast) + 100); | |
| display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 24px; | |
| transition: opacity var(--ease-smooth), visibility var(--ease-smooth); | |
| } | |
| .startup-overlay.hidden { opacity: 0; visibility: hidden; pointer-events: none; } | |
| .startup-logo-container { position: relative; margin-bottom: 32px; animation: popIn var(--ease-spring) 0.2s both; } | |
| .startup-logo-container img { width: 140px; height: 140px; border-radius: var(--radius-xl); object-fit: cover; box-shadow: var(--shadow-xl); border: 3px solid var(--bg-primary); position: relative; z-index: 2; } | |
| .startup-logo-glow { position: absolute; inset: -15px; background: linear-gradient(135deg, var(--brand-saffron), var(--brand-green)); filter: blur(25px); opacity: 0.4; border-radius: var(--radius-full); z-index: 1; animation: pulseGlow 3s infinite alternate; } | |
| @keyframes pulseGlow { from { opacity: 0.3; transform: scale(0.95); } to { opacity: 0.6; transform: scale(1.05); } } | |
| @keyframes popIn { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } } | |
| .startup-title { font-family: var(--font-sans); font-size: 2.25rem; font-weight: 900; color: var(--text-primary); letter-spacing: -1.5px; margin-bottom: 16px; animation: slideUp var(--ease-smooth) 0.3s both; } | |
| .startup-desc { font-size: 1rem; color: var(--text-secondary); line-height: 1.6; max-width: 500px; margin-bottom: 40px; animation: slideUp var(--ease-smooth) 0.4s both; } | |
| .btn-startup-launch { padding: 18px 48px; background: var(--text-primary); color: var(--text-inverse); border: none; border-radius: var(--radius-xl); font-size: 1.125rem; font-weight: 700; cursor: pointer; transition: var(--ease-spring); box-shadow: 0 10px 25px rgba(0,0,0,0.15); animation: slideUp var(--ease-smooth) 0.5s both; display: flex; align-items: center; gap: 12px; } | |
| .btn-startup-launch:hover { background: #000000; transform: translateY(-4px) scale(1.02); box-shadow: 0 15px 35px rgba(0,0,0,0.25); } | |
| @keyframes slideUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } | |
| /* --------------------------------------------------------------------------------------- | |
| F. CORE APPLICATION LAYOUT & SIDEBAR | |
| --------------------------------------------------------------------------------------- */ | |
| .app-root { position: relative; z-index: var(--z-base); display: flex; height: 100dvh; width: 100vw; overflow: hidden; background: var(--bg-glass); backdrop-filter: blur(30px); -webkit-backdrop-filter: blur(30px); } | |
| .sidebar-container { width: 320px; display: flex; flex-direction: column; background: rgba(248, 249, 250, 0.85); border-right: 1px solid var(--border-light); flex-shrink: 0; z-index: var(--z-sidebar); transition: transform var(--ease-smooth); backdrop-filter: blur(15px); } | |
| .sidebar-header { padding: 28px 24px; border-bottom: 1px solid var(--border-light); display: flex; justify-content: space-between; align-items: center; } | |
| .brand-identity { display: flex; align-items: center; gap: 14px; text-decoration: none; } | |
| .brand-identity img { width: 52px; height: 52px; border-radius: var(--radius-md); object-fit: cover; box-shadow: var(--shadow-sm); border: 2px solid var(--bg-primary); transition: transform var(--ease-spring); } | |
| .brand-identity:hover img { transform: scale(1.08) rotate(-3deg); } | |
| .brand-typography { display: flex; flex-direction: column; } | |
| .brand-name { font-family: var(--font-sans); font-weight: 900; font-size: 20px; color: var(--text-primary); letter-spacing: -0.5px; line-height: 1.1; } | |
| .brand-edition { font-size: 11px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; background: linear-gradient(90deg, var(--brand-saffron), var(--brand-green)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-top: 4px; } | |
| .btn-mobile-close { display: none; background: rgba(0,0,0,0.05); border: none; width: 36px; height: 36px; border-radius: 50%; color: var(--text-primary); cursor: pointer; align-items: center; justify-content: center; transition: var(--ease-fast); } | |
| .btn-mobile-close:hover { background: rgba(239, 68, 68, 0.15); color: #ef4444; } | |
| .sidebar-body { flex: 1; overflow-y: auto; padding: 24px; display: flex; flex-direction: column; gap: 28px; } | |
| .sidebar-body::-webkit-scrollbar { width: 5px; } | |
| .sidebar-body::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.1); border-radius: 10px; } | |
| /* Auth UI */ | |
| .auth-widget { background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow-sm); } | |
| .btn-secure-connect { width: 100%; padding: 14px; background: var(--text-primary); color: var(--text-inverse); border: none; border-radius: var(--radius-md); font-size: 14px; font-weight: 700; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px; transition: var(--ease-fast); } | |
| .btn-secure-connect:hover { background: #000000; transform: translateY(-2px); box-shadow: var(--shadow-md); } | |
| .user-profile-display { display: none; align-items: center; gap: 14px; } | |
| .avatar-badge { width: 44px; height: 44px; border-radius: var(--radius-full); background: linear-gradient(135deg, var(--brand-saffron), var(--brand-green)); color: var(--brand-white); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 18px; box-shadow: var(--shadow-sm); border: 2px solid var(--bg-primary); } | |
| .user-details { flex: 1; overflow: hidden; } | |
| .user-email-id { font-size: 14px; font-weight: 700; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| .user-clearance-level { font-size: 11px; color: var(--brand-green); font-weight: 600; margin-top: 2px; display: flex; align-items: center; gap: 4px; } | |
| .user-clearance-level::before { content: ''; display: block; width: 6px; height: 6px; border-radius: 50%; background: var(--brand-green); } | |
| .btn-system-logout { background: rgba(239, 68, 68, 0.1); color: #ef4444; border: none; width: 36px; height: 36px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: var(--ease-fast); } | |
| .btn-system-logout:hover { background: #ef4444; color: #ffffff; } | |
| /* Developer Box */ | |
| .developer-credit-box { background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: var(--radius-lg); padding: 28px 20px; text-align: center; box-shadow: var(--shadow-sm); margin-top: auto; position: relative; overflow: hidden; } | |
| .developer-credit-box::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, var(--brand-saffron), var(--brand-white), var(--brand-green)); } | |
| .developer-credit-box img { width: 72px; height: 72px; border-radius: var(--radius-lg); object-fit: cover; margin-bottom: 16px; box-shadow: var(--shadow-md); border: 1px solid var(--border-light); } | |
| .dev-box-title { font-size: 18px; font-weight: 800; color: var(--text-primary); margin-bottom: 6px; } | |
| .dev-box-subtitle { font-size: 11px; font-weight: 800; color: var(--text-tertiary); letter-spacing: 1px; text-transform: uppercase; } | |
| .btn-erase-memory { width: 100%; padding: 16px; border-radius: var(--radius-md); background: var(--bg-primary); border: 1px solid var(--border-light); color: var(--text-secondary); font-size: 14px; font-weight: 700; cursor: pointer; transition: var(--ease-fast); display: flex; align-items: center; justify-content: center; gap: 10px; } | |
| .btn-erase-memory:hover { background: #fee2e2; color: #ef4444; border-color: #fca5a5; } | |
| /* --------------------------------------------------------------------------------------- | |
| G. MAIN CHAT AREA | |
| --------------------------------------------------------------------------------------- */ | |
| .main-chat-wrapper { flex: 1; display: flex; flex-direction: column; position: relative; min-width: 320px; transition: width var(--ease-smooth); background: transparent; } | |
| .chat-top-bar { padding: 18px 32px; border-bottom: 1px solid var(--border-light); background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(15px); display: flex; align-items: center; justify-content: space-between; z-index: var(--z-overlay); } | |
| .top-bar-left { display: flex; align-items: center; gap: 16px; } | |
| .btn-hamburger { display: none; background: var(--bg-primary); border: 1px solid var(--border-light); cursor: pointer; color: var(--text-primary); width: 40px; height: 40px; border-radius: var(--radius-sm); align-items: center; justify-content: center; box-shadow: var(--shadow-sm); } | |
| .system-status-pill { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700; color: var(--text-primary); padding: 8px 18px; background: var(--bg-secondary); border-radius: var(--radius-full); border: 1px solid var(--border-light); } | |
| .pulse-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--brand-green); box-shadow: 0 0 0 3px rgba(19, 136, 8, 0.2); animation: statusPulse 2s infinite; } | |
| @keyframes statusPulse { 0% { box-shadow: 0 0 0 0 rgba(19,136,8,0.4); } 70% { box-shadow: 0 0 0 6px rgba(19,136,8,0); } 100% { box-shadow: 0 0 0 0 rgba(19,136,8,0); } } | |
| .btn-activate-live { background: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%); color: white; border: none; padding: 10px 20px; border-radius: var(--radius-full); font-size: 14px; font-weight: 800; display: flex; align-items: center; gap: 8px; cursor: pointer; box-shadow: 0 4px 15px rgba(239, 68, 68, 0.35); transition: var(--ease-spring); } | |
| .btn-activate-live:hover { transform: translateY(-2px) scale(1.02); box-shadow: 0 8px 25px rgba(239, 68, 68, 0.45); } | |
| .btn-activate-live svg { width: 18px; height: 18px; animation: liveBlink 1.5s infinite; } | |
| @keyframes liveBlink { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } | |
| .chat-scroll-area { flex: 1; overflow-y: auto; padding: 40px 10%; display: flex; flex-direction: column; gap: 36px; scroll-behavior: smooth; position: relative; } | |
| .chat-scroll-area::-webkit-scrollbar { width: 6px; } | |
| .chat-scroll-area::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 10px; } | |
| /* Internal Welcome */ | |
| .chat-hero-section { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 60px 20px; margin: auto; animation: slideUpFade 0.7s var(--ease-spring) both; max-width: 750px; } | |
| .hero-avatar-wrapper { position: relative; margin-bottom: 36px; } | |
| .hero-avatar-wrapper img { width: 100px; height: 100px; border-radius: var(--radius-xl); object-fit: cover; box-shadow: var(--shadow-xl); border: 3px solid var(--bg-primary); position: relative; z-index: 2; } | |
| .hero-avatar-glow { position: absolute; inset: -12px; background: linear-gradient(135deg, var(--brand-saffron), var(--brand-green)); filter: blur(25px); opacity: 0.35; border-radius: 40px; z-index: 1; } | |
| .hero-greeting { font-size: 42px; font-weight: 900; letter-spacing: -1.5px; margin-bottom: 18px; color: var(--text-primary); } | |
| .hero-description { font-size: 17px; color: var(--text-secondary); line-height: 1.6; margin-bottom: 40px; font-weight: 400; } | |
| .guest-warning-badge { font-size: 13px; font-weight: 700; color: #ef4444; background: #fee2e2; padding: 8px 16px; border-radius: var(--radius-full); margin-bottom: 32px; display: none; align-items: center; gap: 8px; border: 1px solid #fca5a5; } | |
| .prompt-suggestions-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; width: 100%; } | |
| .prompt-card { background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(15px); border: 1px solid var(--border-light); border-radius: var(--radius-lg); padding: 24px; cursor: pointer; text-align: left; transition: var(--ease-smooth); box-shadow: var(--shadow-sm); } | |
| .prompt-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); border-color: var(--brand-saffron); background: rgba(255, 255, 255, 0.95); } | |
| .prompt-icon { font-size: 28px; margin-bottom: 14px; display: inline-block; } | |
| .prompt-title { font-size: 15px; font-weight: 800; color: var(--text-primary); margin-bottom: 8px; } | |
| .prompt-desc { font-size: 13px; color: var(--text-secondary); line-height: 1.5; } | |
| /* Messages */ | |
| .chat-message-row { display: flex; gap: 20px; max-width: 88%; animation: messagePopIn 0.5s var(--ease-spring) both; } | |
| @keyframes messagePopIn { from { opacity: 0; transform: translateY(25px) scale(0.97); } to { opacity: 1; transform: none; } } | |
| .chat-message-row.user-msg { flex-direction: row-reverse; align-self: flex-end; } | |
| .chat-message-row.bot-msg { align-self: flex-start; } | |
| .msg-avatar { width: 42px; height: 42px; border-radius: var(--radius-sm); flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 15px; font-weight: 800; box-shadow: var(--shadow-sm); } | |
| .user-msg .msg-avatar { background: var(--text-primary); color: var(--brand-white); } | |
| .bot-msg .msg-avatar { background: var(--bg-primary); border: 1px solid var(--border-light); padding: 3px; } | |
| .bot-msg .msg-avatar img { width: 100%; height: 100%; border-radius: 6px; object-fit: cover; } | |
| .msg-content-column { display: flex; flex-direction: column; gap: 8px; max-width: 100%; min-width: 0; } | |
| .user-msg .msg-content-column { align-items: flex-end; } | |
| .file-badge { font-size: 11px; font-weight: 600; color: var(--brand-saffron); background: var(--brand-saffron-light); padding: 4px 10px; border-radius: var(--radius-full); margin-bottom: 4px; display: inline-flex; align-items: center; gap: 4px; } | |
| /* File Preview in Chat */ | |
| .chat-in-bubble-img { max-width: 300px; max-height: 300px; border-radius: var(--radius-md); object-fit: cover; border: 2px solid rgba(255,255,255,0.2); box-shadow: var(--shadow-md); margin-bottom: 8px; } | |
| .chat-file-card { display: flex; align-items: center; gap: 12px; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.3); padding: 12px 16px; border-radius: var(--radius-md); margin-bottom: 8px; max-width: 350px; } | |
| .chat-file-card .icon { font-size: 24px; background: rgba(0,0,0,0.1); width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-sm); } | |
| .chat-file-card .name { font-size: 13px; font-weight: 600; color: var(--brand-white); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| .chat-bubble { padding: 18px 24px; font-size: 15px; line-height: 1.6; position: relative; word-wrap: break-word; overflow-wrap: anywhere; } | |
| .user-msg .chat-bubble { background: var(--text-primary); color: var(--text-inverse); border-radius: 24px 24px 6px 24px; box-shadow: var(--shadow-md); } | |
| .bot-msg .chat-bubble { background: var(--bg-primary); color: var(--text-primary); border: 1px solid var(--border-light); border-radius: 6px 24px 24px 24px; box-shadow: var(--shadow-sm); width: 100%; } | |
| /* Bot Actions */ | |
| .bot-actions-row { display: flex; gap: 10px; margin-top: 8px; padding-left: 14px; opacity: 0; transition: opacity var(--ease-smooth); flex-wrap: wrap; } | |
| .bot-msg:hover .bot-actions-row { opacity: 1; } | |
| .btn-bot-action { background: var(--bg-secondary); border: 1px solid var(--border-light); color: var(--text-secondary); font-size: 12px; font-weight: 700; cursor: pointer; display: flex; align-items: center; gap: 6px; padding: 8px 16px; border-radius: var(--radius-full); transition: var(--ease-fast); } | |
| .btn-bot-action:hover { background: var(--bg-primary); color: var(--text-primary); transform: translateY(-2px); box-shadow: var(--shadow-sm); } | |
| .btn-bot-action.action-tts { color: var(--brand-green-hover); border-color: rgba(19, 136, 8, 0.25); background: var(--brand-green-light); } | |
| .btn-bot-action.action-tts:hover { background: rgba(19, 136, 8, 0.2); } | |
| /* Markdown Styles */ | |
| .chat-bubble p { margin-bottom: 16px; } | |
| .chat-bubble p:last-child { margin-bottom: 0; } | |
| .chat-bubble strong { font-weight: 800; color: inherit; } | |
| .chat-bubble code { font-family: var(--font-mono); background: rgba(0,0,0,0.06); padding: 4px 8px; border-radius: 6px; font-size: 0.85em; color: #d946ef; font-weight: 600; } | |
| .user-msg .chat-bubble code { background: rgba(255,255,255,0.2); color: var(--brand-white); } | |
| .chat-bubble img { max-width: 100%; border-radius: var(--radius-md); margin: 16px 0; box-shadow: var(--shadow-lg); border: 1px solid var(--border-light); display: block; } | |
| .chat-bubble pre { background: #282c34; color: #abb2bf; padding: 20px; border-radius: var(--radius-md); overflow-x: auto; margin: 20px 0; font-family: var(--font-mono); font-size: 14px; line-height: 1.6; border: 1px solid #181a1f; } | |
| .chat-bubble pre code { background: transparent; color: inherit; padding: 0; font-weight: 400; } | |
| /* Generating Code UI */ | |
| .streaming-code-container { background: #1e1e2e; border-radius: var(--radius-md); border: 1px solid #313244; overflow: hidden; margin: 20px 0; box-shadow: var(--shadow-lg); } | |
| .streaming-code-header { background: #11111b; padding: 12px 20px; font-size: 12px; font-weight: 700; color: #a6adc8; display: flex; align-items: center; gap: 12px; border-bottom: 1px solid #313244; font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 1.5px; } | |
| .loading-ring { width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.1); border-top-color: var(--brand-saffron); border-radius: 50%; animation: ringSpin 1s cubic-bezier(0.68, -0.55, 0.265, 1.55) infinite; } | |
| @keyframes ringSpin { to { transform: rotate(360deg); } } | |
| .streaming-code-container pre { margin: 0; background: transparent; border: none; border-radius: 0; } | |
| /* Workspace Execute Card */ | |
| .workspace-execute-card { background: var(--bg-secondary); border: 1px solid var(--border-light); border-radius: var(--radius-md); padding: 20px; margin: 20px 0; display: flex; align-items: center; justify-content: space-between; box-shadow: var(--shadow-sm); transition: var(--ease-smooth); } | |
| .workspace-execute-card:hover { border-color: var(--border-medium); box-shadow: var(--shadow-md); } | |
| .ws-card-left { display: flex; align-items: center; gap: 16px; } | |
| .ws-card-icon-box { width: 54px; height: 54px; border-radius: var(--radius-sm); background: var(--bg-primary); display: flex; align-items: center; justify-content: center; font-size: 26px; box-shadow: var(--shadow-sm); border: 1px solid var(--border-light); color: var(--text-primary); } | |
| .ws-card-details h4 { font-size: 16px; font-weight: 800; margin-bottom: 4px; color: var(--text-primary); } | |
| .ws-card-details p { font-size: 12px; color: var(--text-secondary); font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600; } | |
| .btn-launch-workspace { padding: 12px 24px; background: var(--text-primary); color: var(--brand-white); border: none; border-radius: var(--radius-sm); font-size: 14px; font-weight: 700; cursor: pointer; transition: var(--ease-spring); } | |
| .btn-launch-workspace:hover { transform: scale(1.05); background: var(--brand-saffron); box-shadow: 0 6px 15px rgba(255,153,51,0.35); } | |
| /* --------------------------------------------------------------------------------------- | |
| H. INPUT AREA & ATTACHMENTS | |
| --------------------------------------------------------------------------------------- */ | |
| .input-dock { flex-shrink: 0; padding: 0 40px 32px; background: transparent; position: relative; z-index: 20; } | |
| .input-master-container { display: flex; flex-direction: column; background: var(--bg-glass); backdrop-filter: blur(30px); border: 1px solid var(--border-light); border-radius: var(--radius-2xl); box-shadow: var(--shadow-xl); transition: var(--ease-smooth); } | |
| .input-master-container:focus-within { border-color: var(--brand-saffron); box-shadow: 0 20px 40px -5px rgba(255,153,51,0.15), 0 0 0 4px var(--brand-saffron-light); } | |
| .upload-preview-bar { display: none; padding: 20px 28px 0; align-items: center; gap: 16px; } | |
| .upload-preview-bar.visible { display: flex; animation: fadeIn 0.3s ease; } | |
| .upload-thumb { width: 52px; height: 52px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border-light); display: flex; justify-content: center; align-items: center; background: var(--bg-tertiary); font-size: 24px; box-shadow: var(--shadow-sm); } | |
| .upload-meta { flex: 1; } | |
| .upload-filename { font-size: 14px; font-weight: 700; color: var(--text-primary); max-width: 250px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } | |
| .upload-status-text { font-size: 12px; color: var(--brand-green); font-weight: 600; margin-top: 2px; } | |
| .btn-discard-upload { background: rgba(239, 68, 68, 0.1); border: none; width: 32px; height: 32px; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; color: #ef4444; transition: var(--ease-fast); } | |
| .btn-discard-upload:hover { background: #ef4444; color: #fff; } | |
| .input-tools-row { display: flex; align-items: flex-end; gap: 12px; padding: 14px 20px 14px 24px; } | |
| .main-textarea { flex: 1; border: none; outline: none; background: transparent; font-family: var(--font-sans); font-size: 16px; color: var(--text-primary); line-height: 1.5; resize: none; max-height: 200px; min-height: 24px; padding: 12px 0; margin: 0 8px; font-weight: 500; } | |
| .main-textarea::placeholder { color: var(--text-tertiary); font-weight: 400; } | |
| /* Attachment Menu */ | |
| .attachment-module { position: relative; } | |
| .btn-tool-icon { width: 44px; height: 44px; border-radius: var(--radius-md); background: transparent; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text-secondary); transition: var(--ease-fast); } | |
| .btn-tool-icon:hover { background: var(--bg-tertiary); color: var(--text-primary); } | |
| .btn-tool-icon svg { width: 24px; height: 24px; stroke-width: 2; } | |
| .attachment-dropdown { position: absolute; bottom: 60px; left: 0; background: rgba(255,255,255,0.95); backdrop-filter: blur(25px); border: 1px solid var(--border-light); border-radius: var(--radius-lg); padding: 10px; box-shadow: var(--shadow-xl); display: none; flex-direction: column; gap: 6px; z-index: var(--z-dropdown); min-width: 220px; transform: translateY(15px) scale(0.95); opacity: 0; transition: all var(--ease-fast); transform-origin: bottom left; } | |
| .attachment-dropdown.visible { display: flex; transform: translateY(0) scale(1); opacity: 1; } | |
| .dropdown-item { display: flex; align-items: center; gap: 14px; padding: 14px 18px; border-radius: var(--radius-sm); cursor: pointer; font-size: 15px; font-weight: 600; color: var(--text-primary); transition: var(--ease-fast); } | |
| .dropdown-item:hover { background: var(--bg-tertiary); color: var(--brand-saffron-hover); } | |
| .dropdown-item span.emoji-icon { font-size: 20px; } | |
| .stealth-input { display: none; } | |
| /* Language Toggle & Send */ | |
| .language-toggle-chip { font-size: 13px; font-weight: 800; color: var(--text-secondary); border: 2px solid var(--border-light); background: var(--bg-primary); border-radius: 10px; padding: 6px 10px; cursor: pointer; transition: var(--ease-smooth); display: flex; align-items: center; gap: 6px; user-select: none; } | |
| .language-toggle-chip:hover { background: var(--brand-saffron-light); color: var(--brand-saffron-dark); border-color: var(--brand-saffron); } | |
| .language-toggle-chip.hindi-active { background: var(--brand-green-light); color: var(--brand-green-dark); border-color: var(--brand-green); } | |
| .btn-mic-tool.active-listening { color: #ffffff; background: #ef4444; animation: recordPulse 1.5s infinite; border-radius: var(--radius-full); } | |
| @keyframes recordPulse { 0% { box-shadow: 0 0 0 0 rgba(239,68,68,0.5); } 70% { box-shadow: 0 0 0 12px rgba(239,68,68,0); } 100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); } } | |
| .btn-master-send { width: 48px; height: 48px; border-radius: 16px; border: none; background: linear-gradient(135deg, var(--brand-saffron) 0%, var(--brand-green) 100%); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: var(--ease-spring); box-shadow: 0 6px 20px rgba(19, 136, 8, 0.25); } | |
| .btn-master-send svg { width: 20px; height: 20px; fill: white; transition: transform 0.2s; } | |
| .btn-master-send:hover { transform: translateY(-3px); box-shadow: 0 10px 25px rgba(255, 153, 51, 0.4); } | |
| .btn-master-send:hover svg { transform: translate(2px, -2px); } | |
| .btn-master-send:disabled { opacity: 0.4; cursor: not-allowed; filter: grayscale(100%); transform: none; box-shadow: none; } | |
| .bottom-branding-text { text-align: center; font-size: 12px; color: var(--text-tertiary); margin-top: 16px; font-weight: 600; letter-spacing: 0.5px; } | |
| /* --------------------------------------------------------------------------------------- | |
| I. LIVE MODE & WORKSPACE | |
| --------------------------------------------------------------------------------------- */ | |
| .live-mode-viewport { position: fixed; inset: 0; background: rgba(255, 255, 255, 0.98); z-index: var(--z-live-mode); display: flex; flex-direction: column; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity var(--ease-smooth); } | |
| .live-mode-viewport.active { opacity: 1; pointer-events: auto; } | |
| .btn-close-live { position: absolute; top: 40px; right: 40px; background: rgba(0,0,0,0.04); border: none; width: 56px; height: 56px; border-radius: 50%; font-size: 24px; cursor: pointer; transition: var(--ease-spring); display: flex; align-items: center; justify-content: center; color: var(--text-secondary); } | |
| .btn-close-live:hover { background: rgba(239, 68, 68, 0.15); color: #ef4444; transform: rotate(90deg); } | |
| .pulsing-orb-wrapper { position: relative; width: 250px; height: 250px; display: flex; align-items: center; justify-content: center; margin-bottom: 50px; } | |
| .energy-core { width: 120px; height: 120px; border-radius: 50%; background: linear-gradient(135deg, var(--brand-saffron), var(--brand-green)); box-shadow: 0 0 50px rgba(19, 136, 8, 0.5); position: relative; z-index: 2; transition: transform 0.15s ease-out; } | |
| .energy-ring { position: absolute; inset: 0; border: 3px solid var(--brand-saffron); border-radius: 50%; opacity: 0; animation: energyRipple 2.5s cubic-bezier(0.4, 0, 0.2, 1) infinite; } | |
| .energy-ring:nth-child(2) { animation-delay: 0.8s; border-color: var(--brand-green); } | |
| .energy-ring:nth-child(3) { animation-delay: 1.6s; border-color: var(--text-primary); } | |
| @keyframes energyRipple { 0% { transform: scale(0.4); opacity: 1; border-width: 6px; } 100% { transform: scale(1.6); opacity: 0; border-width: 1px; } } | |
| .live-feedback-status { font-size: 28px; font-weight: 900; color: var(--text-primary); margin-bottom: 16px; font-family: var(--font-sans); } | |
| .live-feedback-text { font-size: 18px; color: var(--text-secondary); max-width: 700px; text-align: center; line-height: 1.6; min-height: 60px; font-weight: 500; } | |
| .live-control-deck { display: flex; gap: 24px; margin-top: 50px; } | |
| .btn-live-deck { width: 76px; height: 76px; border-radius: 50%; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: var(--shadow-lg); transition: var(--ease-spring); } | |
| .btn-live-deck.mic-control { background: var(--bg-primary); border: 3px solid var(--border-light); color: var(--text-primary); } | |
| .btn-live-deck.mic-control:hover { transform: translateY(-6px); border-color: var(--brand-saffron); color: var(--brand-saffron); box-shadow: var(--shadow-xl); } | |
| .btn-live-deck.mic-control.is-recording { background: #ef4444; color: white; border-color: #ef4444; animation: pulseMicLive 1.2s infinite; } | |
| @keyframes pulseMicLive { 0% { box-shadow: 0 0 0 0 rgba(239,68,68,0.6); } 70% { box-shadow: 0 0 0 20px rgba(239,68,68,0); } 100% { box-shadow: 0 0 0 0 rgba(239,68,68,0); } } | |
| .code-workspace-panel { width: 0; background: var(--bg-primary); border-left: 1px solid var(--border-light); display: flex; flex-direction: column; transition: width var(--ease-smooth); overflow: hidden; box-shadow: -15px 0 40px rgba(0,0,0,0.04); z-index: 25; } | |
| .code-workspace-panel.expanded { width: 55%; } | |
| .workspace-header-bar { padding: 20px 28px; border-bottom: 1px solid var(--border-light); background: var(--bg-primary); display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; } | |
| .workspace-title-group { font-size: 16px; font-weight: 800; display: flex; align-items: center; gap: 12px; color: var(--text-primary); } | |
| .workspace-tools { display: flex; gap: 12px; } | |
| .btn-workspace-tool { padding: 10px 18px; border-radius: var(--radius-sm); background: var(--bg-secondary); border: 1px solid var(--border-light); cursor: pointer; display: flex; align-items: center; gap: 8px; color: var(--text-primary); transition: var(--ease-fast); font-size: 14px; font-weight: 700; } | |
| .btn-workspace-tool:hover { background: var(--bg-tertiary); border-color: var(--border-medium); } | |
| .btn-workspace-tool.close { padding: 10px; } | |
| .btn-workspace-tool.close:hover { color: #ef4444; background: #fee2e2; border-color: #fca5a5; } | |
| .workspace-editor-surface { flex: 1; overflow-y: auto; background: var(--bg-secondary); padding: 30px; } | |
| .workspace-editor-surface pre { margin: 0; padding: 28px; background: #282c34; border: 1px solid var(--border-light); border-radius: var(--radius-lg); font-family: var(--font-mono); font-size: 15px; line-height: 1.6; overflow-x: auto; box-shadow: var(--shadow-lg); color: #abb2bf; } | |
| /* Scroll Button */ | |
| .btn-scroll-trigger { position: absolute; bottom: 150px; left: 50%; width: 48px; height: 48px; border-radius: 50%; background: var(--bg-glass); backdrop-filter: blur(15px); border: 1px solid var(--border-light); box-shadow: var(--shadow-lg); display: flex; align-items: center; justify-content: center; cursor: pointer; color: var(--text-secondary); opacity: 0; pointer-events: none; transform: translateX(-50%) translateY(20px); transition: var(--ease-smooth); z-index: 20; } | |
| .btn-scroll-trigger.visible { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); } | |
| .btn-scroll-trigger:hover { background: var(--bg-primary); color: var(--text-primary); transform: translateX(-50%) translateY(-5px); box-shadow: var(--shadow-xl); } | |
| /* AUTH MODAL */ | |
| .secure-modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); backdrop-filter: blur(10px); z-index: var(--z-modal); display: none; justify-content: center; align-items: center; animation: fadeIn 0.3s ease; } | |
| .secure-modal-surface { background: var(--bg-primary); padding: 44px; border-radius: var(--radius-xl); width: 90%; max-width: 460px; box-shadow: var(--shadow-xl); position: relative; border: 1px solid rgba(255,255,255,0.4); } | |
| .btn-modal-dismiss { position: absolute; top: 24px; right: 24px; background: var(--bg-secondary); border: none; width: 36px; height: 36px; border-radius: 50%; font-size: 18px; color: var(--text-secondary); cursor: pointer; transition: 0.2s; display: flex; align-items: center; justify-content: center; } | |
| .btn-modal-dismiss:hover { background: #fee2e2; color: #ef4444; } | |
| .modal-brand-header { text-align: center; margin-bottom: 36px; font-family: var(--font-sans); font-size: 28px; font-weight: 900; color: var(--text-primary); letter-spacing: -0.5px; } | |
| .auth-tab-switch { display: flex; background: var(--bg-secondary); padding: 6px; border-radius: var(--radius-md); margin-bottom: 28px; } | |
| .auth-tab-item { flex: 1; padding: 14px; text-align: center; border-radius: var(--radius-sm); font-size: 15px; font-weight: 800; color: var(--text-secondary); cursor: pointer; transition: var(--ease-fast); } | |
| .auth-tab-item.active { background: var(--bg-primary); color: var(--text-primary); box-shadow: var(--shadow-sm); } | |
| .auth-form-view { display: none; flex-direction: column; animation: slideIn 0.3s ease; } | |
| .auth-form-view.active { display: flex; } | |
| .auth-input-element { width: 100%; padding: 18px; border: 2px solid var(--border-light); border-radius: var(--radius-md); font-size: 16px; outline: none; background: var(--bg-secondary); transition: var(--ease-fast); font-family: var(--font-sans); margin-bottom: 20px; font-weight: 500; } | |
| .auth-input-element:focus { border-color: var(--brand-saffron); background: var(--bg-primary); box-shadow: 0 0 0 4px var(--brand-saffron-light); } | |
| .btn-auth-execute { width: 100%; padding: 18px; background: var(--text-primary); color: var(--brand-white); border: none; border-radius: var(--radius-md); font-size: 16px; font-weight: 800; cursor: pointer; transition: var(--ease-fast); margin-top: 10px; } | |
| .btn-auth-execute:hover { background: #000000; transform: translateY(-2px); box-shadow: var(--shadow-md); } | |
| .btn-auth-return { width: 100%; padding: 14px; background: transparent; color: var(--text-tertiary); border: none; font-size: 15px; font-weight: 700; cursor: pointer; margin-top: 10px; transition: 0.2s; } | |
| .btn-auth-return:hover { color: var(--text-primary); } | |
| @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } | |
| @keyframes slideIn { from { opacity: 0; transform: translateX(25px); } to { opacity: 1; transform: none; } } | |
| .typing-cursor { display: inline-block; width: 10px; height: 18px; background: var(--brand-saffron); margin-left: 4px; animation: cursorBlink 1s step-end infinite; vertical-align: middle; } | |
| @keyframes cursorBlink { 50% { opacity: 0; } } | |
| .loading-dots-container { display: flex; align-items: center; gap: 6px; padding: 6px; } | |
| .loading-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-tertiary); opacity: 0.4; animation: dotBounce 1.4s infinite ease-in-out both; } | |
| .loading-dot:nth-child(1) { animation-delay: -0.32s; } .loading-dot:nth-child(2) { animation-delay: -0.16s; } | |
| @keyframes dotBounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } } | |
| /* Media Queries */ | |
| @media (max-width: 1024px) { .code-workspace-panel.expanded { width: 100%; position: absolute; top: 0; left: 0; height: 100%; z-index: 2000; } } | |
| @media (max-width: 900px) { | |
| .sidebar-container { position: absolute; left: -320px; z-index: 1000; height: 100%; box-shadow: var(--shadow-float); } | |
| .sidebar-container.active { left: 0; } | |
| .btn-hamburger { display: flex; } .btn-mobile-close { display: flex; } | |
| .chat-scroll-area { padding: 24px 15px; } .input-dock { padding: 10px 15px 20px; } | |
| .chat-message-row { max-width: 95%; } .btn-scroll-trigger { bottom: 130px; } | |
| .hero-greeting { font-size: 32px; } .prompt-suggestions-grid { grid-template-columns: 1fr; } | |
| .input-tools-row { flex-wrap: wrap; } .main-textarea { min-width: 100%; order: -1; margin-bottom: 10px; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- DOM: NOTIFICATIONS --> | |
| <div id="toast-container" class="toast-wrapper"></div> | |
| <!-- DOM: INITIAL STARTUP OVERLAY --> | |
| <div class="startup-overlay" id="welcomeOverlay"> | |
| <div class="startup-logo-container"> | |
| <div class="startup-logo-glow"></div> | |
| <img src="https://i.ibb.co/0y2sdbq6/PT-20260523-133251-0000.png" alt="Arjun Core Identity"> | |
| </div> | |
| <h1 class="startup-title">Welcome to Arjun 2.O</h1> | |
| <p class="startup-desc">Professional Enterprise Edition. Experience secure workspace logic generation, high-fidelity visual rendering, and zero-latency live conversational mode.</p> | |
| <button class="btn-startup-launch" id="btnLaunchSystem"> | |
| Initialize System | |
| <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg> | |
| </button> | |
| </div> | |
| <!-- DOM: LIVE MODE OVERLAY --> | |
| <div class="live-mode-viewport" id="liveOverlay"> | |
| <button class="btn-close-live" id="btnExitLiveMode" title="Exit Live Mode"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| <div class="pulsing-orb-wrapper"> | |
| <div class="energy-ring"></div><div class="energy-ring"></div><div class="energy-ring"></div> | |
| <div class="energy-core" id="liveOrb"></div> | |
| </div> | |
| <div class="live-feedback-status" id="liveStatusText">Initializing Audio Stream...</div> | |
| <div class="live-feedback-text" id="liveTranscriptText">Speak directly to Arjun. Natural language processing active.</div> | |
| <div class="live-control-deck"> | |
| <button class="btn-live-deck mic-control" id="liveMicBtn"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="12" x2="12" y1="19" y2="22"></line></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- DOM: AMBIENT BACKGROUND --> | |
| <div class="ambient-environment"> | |
| <div class="ambient-orb orb-top-left"></div> | |
| <div class="ambient-orb orb-bottom-right"></div> | |
| </div> | |
| <!-- DOM: MASTER APPLICATION CONTAINER --> | |
| <div class="app-root"> | |
| <!-- SIDEBAR --> | |
| <aside class="sidebar-container" id="sidebar"> | |
| <div class="sidebar-header"> | |
| <a href="#" class="brand-identity"> | |
| <img src="https://i.ibb.co/0y2sdbq6/PT-20260523-133251-0000.png" alt="Arjun Logo"> | |
| <div class="brand-typography"> | |
| <span class="brand-name">ARJUN 2.O</span> | |
| <span class="brand-edition">Professional</span> | |
| </div> | |
| </a> | |
| <button class="btn-mobile-close" id="btnSidebarClose"> | |
| <svg viewBox="0 0 24 24" width="20" height="20" stroke="currentColor" stroke-width="2.5" fill="none"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| <div class="sidebar-body"> | |
| <div class="auth-widget"> | |
| <button id="loginPromptBtn" class="btn-secure-connect"> | |
| <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg> | |
| Secure Login | |
| </button> | |
| <div id="userProfile" class="user-profile-display"> | |
| <div class="avatar-badge" id="uAvatar">U</div> | |
| <div class="user-details"> | |
| <div class="user-email-id" id="uEmail">user@network.com</div> | |
| <div class="user-clearance-level">Verified Clearance</div> | |
| </div> | |
| <button class="btn-system-logout" id="btnLogout" title="Terminate Session"> | |
| <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="developer-credit-box"> | |
| <img src="https://i.ibb.co/0y2sdbq6/PT-20260523-133251-0000.png" alt="Arjun Core Image"> | |
| <h3 class="dev-box-title">Arjun Intelligence</h3> | |
| <p class="dev-box-subtitle">ENGINEERED BY ABHAY KUMAR</p> | |
| </div> | |
| <button class="btn-erase-memory" id="btnClearMemory"> | |
| <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg> | |
| Wipe Memory Context | |
| </button> | |
| </div> | |
| </aside> | |
| <!-- MAIN CHAT ENGINE INTERFACE --> | |
| <main class="main-chat-wrapper"> | |
| <header class="chat-top-bar"> | |
| <div class="top-bar-left"> | |
| <button class="btn-hamburger" id="btnSidebarOpen"> | |
| <svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2.5" fill="none"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg> | |
| </button> | |
| <div class="system-status-pill"> | |
| <div class="pulse-dot"></div> | |
| System Online | |
| </div> | |
| </div> | |
| <button class="btn-activate-live" id="btnStartLiveMode"> | |
| <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5" fill="none"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="4" fill="currentColor"></circle></svg> | |
| LIVE MODE | |
| </button> | |
| </header> | |
| <div class="chat-scroll-area" id="msgs"> | |
| <div class="chat-hero-section" id="welcomeState"> | |
| <div class="hero-avatar-wrapper"> | |
| <div class="hero-avatar-glow"></div> | |
| <img src="https://i.ibb.co/0y2sdbq6/PT-20260523-133251-0000.png" alt="Arjun Logo Large"> | |
| </div> | |
| <h2 class="hero-greeting">How can I assist you today?</h2> | |
| <p class="hero-description">Experience next-generation reasoning, seamless multi-file analysis, and secure workspace code generation engineered by Abhay Kumar.</p> | |
| <div id="guestBadge" class="guest-warning-badge"> | |
| ⚠️ Guest Mode Active: <span id="guestCountDisplay">0</span>/3 Queries Used. Please login. | |
| </div> | |
| <div class="prompt-suggestions-grid"> | |
| <div class="prompt-card" id="suggCodeBtn"> | |
| <span class="prompt-icon">💻</span> | |
| <div class="prompt-title">Generate Production Code</div> | |
| <div class="prompt-desc">Create secure, workspace-ready architecture instantly.</div> | |
| </div> | |
| <div class="prompt-card" id="suggImgBtn"> | |
| <span class="prompt-icon">🎨</span> | |
| <div class="prompt-title">Render Stunning Visions</div> | |
| <div class="prompt-desc">Utilize advanced AI to paint your imagination.</div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <button class="btn-scroll-trigger" id="scrollTriggerBtn"> | |
| <svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="6 9 12 15 18 9"></polyline></svg> | |
| </button> | |
| <!-- Bottom Input Dock --> | |
| <div class="input-dock"> | |
| <div class="input-master-container"> | |
| <div class="upload-preview-bar" id="filePreviewBar"> | |
| <img class="upload-thumb" id="previewImgThumb" src="" style="display:none;"> | |
| <div class="upload-thumb" id="previewDocIcon" style="display:none;">📄</div> | |
| <div class="upload-meta"> | |
| <div class="upload-filename" id="previewFileName">document.pdf</div> | |
| <div class="upload-status-text">Your file is ready!</div> | |
| </div> | |
| <button class="btn-discard-upload" id="btnDiscardFile"> | |
| <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| <div class="input-tools-row"> | |
| <div class="attachment-module"> | |
| <button class="btn-tool-icon" id="btnAttachMenuToggle" title="Attach File"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" 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"></path></svg> | |
| </button> | |
| <div class="attachment-dropdown" id="attachDropdownMenu"> | |
| <div class="dropdown-item" id="opt-image"><span class="emoji-icon">🖼️</span> High-Res Image</div> | |
| <div class="dropdown-item" id="opt-video"><span class="emoji-icon">🎥</span> Video Media</div> | |
| <div class="dropdown-item" id="opt-audio"><span class="emoji-icon">🎵</span> Audio Track</div> | |
| <div class="dropdown-item" id="opt-document"><span class="emoji-icon">📄</span> Document / Code</div> | |
| </div> | |
| <input type="file" id="sys-inp-image" class="stealth-input" accept="image/*"> | |
| <input type="file" id="sys-inp-video" class="stealth-input" accept="video/*"> | |
| <input type="file" id="sys-inp-audio" class="stealth-input" accept="audio/*"> | |
| <input type="file" id="sys-inp-document" class="stealth-input" accept=".pdf,.doc,.docx,.txt,.md,.csv,.json,.py,.js,.html,.css,.cpp,.c,.java"> | |
| </div> | |
| <button class="language-toggle-chip" id="smartLangToggle" title="Switch Voice Engine Language"> | |
| 🌐 <span id="langDisplayBadge">EN</span> | |
| </button> | |
| <button class="btn-tool-icon btn-mic-tool" id="masterVoiceBtn" title="Voice Dictation"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"></path><path d="M19 10v2a7 7 0 0 1-14 0v-2"></path><line x1="12" x2="12" y1="19" y2="22"></line></svg> | |
| </button> | |
| <textarea class="main-textarea" id="mainChatInput" placeholder="Message Arjun Intelligence..." rows="1"></textarea> | |
| <button class="btn-master-send" id="masterSendBtn"> | |
| <svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="bottom-branding-text">Secured by Arjun Core Architecture • Developed by Abhay Kumar</div> | |
| </div> | |
| </main> | |
| <!-- WORKSPACE CODE EDITOR PANEL --> | |
| <aside class="code-workspace-panel" id="workspacePanel"> | |
| <div class="workspace-header-bar"> | |
| <div class="workspace-title-group"> | |
| <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg> | |
| <span id="wsTitleText">Workspace Logic</span> | |
| </div> | |
| <div class="workspace-tools"> | |
| <button class="btn-workspace-tool" id="btnWsCopy"> | |
| <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg> | |
| Copy Source | |
| </button> | |
| <button class="btn-workspace-tool close" id="btnWsClose" title="Close Editor"> | |
| <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="workspace-editor-surface"> | |
| <pre><code id="workspaceCodeBlock" class="hljs"></code></pre> | |
| </div> | |
| </aside> | |
| </div> | |
| <!-- SECURE AUTHENTICATION MODAL --> | |
| <div class="secure-modal-backdrop" id="secureAuthModal"> | |
| <div class="secure-modal-surface"> | |
| <button class="btn-modal-dismiss" id="btnAuthClose"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
| </button> | |
| <div class="modal-brand-header">Arjun Network</div> | |
| <div class="auth-tab-switch"> | |
| <div class="auth-tab-item active" id="btn-tab-login">Connect</div> | |
| <div class="auth-tab-item" id="btn-tab-register">Enroll</div> | |
| </div> | |
| <div id="auth-flow-login"> | |
| <div class="auth-form-view active" id="auth-log-phase-1"> | |
| <input type="email" class="auth-input-element" id="authLogEmail" placeholder="Authorized Email Address"> | |
| <button class="btn-auth-execute" id="btn-fire-log-otp">Generate Secure Token (OTP)</button> | |
| </div> | |
| <div class="auth-form-view" id="auth-log-phase-2"> | |
| <input type="number" class="auth-input-element" id="authLogOTP" placeholder="Validation Code (OTP)"> | |
| <button class="btn-auth-execute" id="btn-fire-log-verify">Authenticate Session</button> | |
| <button class="btn-auth-return" id="btnLogBack">← Return</button> | |
| </div> | |
| </div> | |
| <div id="auth-flow-register" style="display:none;"> | |
| <div class="auth-form-view active" id="auth-reg-phase-1"> | |
| <input type="text" class="auth-input-element" id="authRegName" placeholder="Full Legal Name"> | |
| <input type="email" class="auth-input-element" id="authRegEmail" placeholder="Communication Email"> | |
| <button class="btn-auth-execute" id="btn-fire-reg-otp">Verify Identity</button> | |
| </div> | |
| <div class="auth-form-view" id="auth-reg-phase-2"> | |
| <input type="number" class="auth-input-element" id="authRegOTP" placeholder="Identity Token (OTP)"> | |
| <button class="btn-auth-execute" id="btn-fire-reg-verify">Initialize Account</button> | |
| <button class="btn-auth-return" id="btnRegBack">← Return</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- ========================================================================================= | |
| 8. MASSIVE JAVASCRIPT ARCHITECTURE (MODULE TYPE FOR GRADIO INTEGRATION) | |
| ========================================================================================= --> | |
| <script type="module"> | |
| /** | |
| * GRADIO INTEGRATION FOR EDGE-TTS (प्रभात न्यूरल) | |
| * Loaded seamlessly inside the module. | |
| */ | |
| import { Client } from "https://cdn.jsdelivr.net/npm/@gradio/client/dist/index.min.js"; | |
| /** | |
| * System Configuration & State | |
| */ | |
| const Config = { | |
| GAS_URL: "https://script.google.com/macros/s/AKfycbzTsXGoVh97JjtFAAG825GF4WUZqf7FDB3Zbxyf0nrLXt_1HjJSSqA829UcdoamRPvg0A/exec", | |
| LOGO_URL: "https://i.ibb.co/0y2sdbq6/PT-20260523-133251-0000.png", | |
| PDF_WORKER: 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js', | |
| API_ENDPOINT: '/api/chat', // Change to 'http://localhost:7860/api/chat' if running UI separately | |
| }; | |
| pdfjsLib.GlobalWorkerOptions.workerSrc = Config.PDF_WORKER; | |
| const AppState = { | |
| currentUser: localStorage.getItem('arjun_user') || null, | |
| guestCount: parseInt(localStorage.getItem('arjun_guest') || '0', 10), | |
| history: [], | |
| pendingAttachment: null, | |
| isProcessing: false, | |
| isUserScrolling: false, | |
| generatedCodeBlocks: [], | |
| currentWorkspaceId: null, | |
| isStreamingActive: false, | |
| isLiveModeEngaged: false, | |
| gradioClient: null // Holds the connected TTS Client | |
| }; | |
| /** | |
| * UTILITY ENGINE (Robust Copy & Notifications) | |
| */ | |
| const Utils = { | |
| showToast: (message) => { | |
| const container = document.getElementById('toast-container'); | |
| const toast = document.createElement('div'); | |
| toast.className = 'toast-notification'; | |
| toast.innerHTML = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"><polyline points="20 6 9 17 4 12"></polyline></svg> ${message}`; | |
| container.appendChild(toast); | |
| setTimeout(() => toast.remove(), 3000); | |
| }, | |
| escapeHTML: (str) => { | |
| return str.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); | |
| }, | |
| executeFallbackCopy: (text, btnElement) => { | |
| const textArea = document.createElement("textarea"); | |
| textArea.value = text; | |
| textArea.style.top = "0"; textArea.style.left = "0"; textArea.style.position = "fixed"; | |
| document.body.appendChild(textArea); | |
| textArea.focus(); textArea.select(); | |
| try { | |
| const successful = document.execCommand('copy'); | |
| if (successful) { | |
| const originalHTML = btnElement.innerHTML; | |
| btnElement.innerHTML = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"></polyline></svg> Success`; | |
| setTimeout(() => { btnElement.innerHTML = originalHTML; }, 2500); | |
| } else { | |
| Utils.showToast("Clipboard access denied."); | |
| } | |
| } catch (err) { | |
| Utils.showToast("System error copying text."); | |
| } | |
| document.body.removeChild(textArea); | |
| }, | |
| copyToClipboard: (btnElement, textToCopy) => { | |
| if (!navigator.clipboard) { | |
| Utils.executeFallbackCopy(textToCopy, btnElement); | |
| return; | |
| } | |
| navigator.clipboard.writeText(textToCopy).then(() => { | |
| const originalHTML = btnElement.innerHTML; | |
| btnElement.innerHTML = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"></polyline></svg> Success`; | |
| setTimeout(() => { btnElement.innerHTML = originalHTML; }, 2500); | |
| }).catch((err) => { | |
| Utils.executeFallbackCopy(textToCopy, btnElement); | |
| }); | |
| } | |
| }; | |
| /** | |
| * AUTHENTICATION ENGINE (GAS Integration) | |
| */ | |
| const AuthManager = { | |
| initUI: () => { | |
| if (AppState.currentUser) { | |
| document.getElementById('loginPromptBtn').style.display = 'none'; | |
| document.getElementById('userProfile').style.display = 'flex'; | |
| document.getElementById('uEmail').innerText = AppState.currentUser; | |
| document.getElementById('uAvatar').innerText = AppState.currentUser.charAt(0).toUpperCase(); | |
| document.getElementById('guestBadge').style.display = 'none'; | |
| } else { | |
| document.getElementById('loginPromptBtn').style.display = 'flex'; | |
| document.getElementById('userProfile').style.display = 'none'; | |
| document.getElementById('guestBadge').style.display = 'inline-flex'; | |
| document.getElementById('guestCountDisplay').innerText = AppState.guestCount; | |
| } | |
| }, | |
| process: async (actionType) => { | |
| const payload = { action: actionType }; | |
| let buttonId = ''; | |
| if (actionType === 'register_send_otp') { | |
| payload.name = document.getElementById('authRegName').value.trim(); | |
| payload.email = document.getElementById('authRegEmail').value.trim(); | |
| payload.phone = "0000000000"; payload.organization = "Arjun Base"; | |
| if (!payload.email || !payload.name) return Utils.showToast("Identification details required."); | |
| buttonId = 'btn-fire-reg-otp'; | |
| } else if (actionType === 'login_send_otp') { | |
| payload.email = document.getElementById('authLogEmail').value.trim(); | |
| if (!payload.email) return Utils.showToast("Email required for validation."); | |
| buttonId = 'btn-fire-log-otp'; | |
| } else if (actionType === 'register_verify' || actionType === 'login_verify') { | |
| payload.email = document.getElementById(actionType === 'register_verify' ? 'authRegEmail' : 'authLogEmail').value.trim(); | |
| payload.otp = document.getElementById(actionType === 'register_verify' ? 'authRegOTP' : 'authLogOTP').value.trim(); | |
| if (!payload.otp) return Utils.showToast("Security token required."); | |
| buttonId = actionType === 'register_verify' ? 'btn-fire-reg-verify' : 'btn-fire-log-verify'; | |
| } | |
| const triggerBtn = document.getElementById(buttonId); | |
| const originalText = triggerBtn.innerHTML; | |
| triggerBtn.disabled = true; triggerBtn.innerText = 'Connecting...'; | |
| try { | |
| const response = await fetch(Config.GAS_URL, { | |
| method: 'POST', | |
| mode: 'cors', | |
| headers: { 'Content-Type': 'text/plain;charset=utf-8' }, // Prevent CORS preflight issues | |
| body: JSON.stringify(payload) | |
| }); | |
| const result = await response.json(); | |
| if (result.status === 'success') { | |
| Utils.showToast(result.message); | |
| if (actionType === 'register_send_otp') { | |
| document.getElementById('auth-reg-phase-1').classList.remove('active'); | |
| document.getElementById('auth-reg-phase-2').classList.add('active'); | |
| } else if (actionType === 'login_send_otp') { | |
| document.getElementById('auth-log-phase-1').classList.remove('active'); | |
| document.getElementById('auth-log-phase-2').classList.add('active'); | |
| } else if (actionType === 'register_verify' || actionType === 'login_verify') { | |
| AppState.currentUser = payload.email; | |
| localStorage.setItem('arjun_user', AppState.currentUser); | |
| document.getElementById('secureAuthModal').style.display = 'none'; | |
| AuthManager.initUI(); | |
| ChatEngine.syncHistoryFromCloud(); | |
| } | |
| } else { | |
| Utils.showToast(result.message); | |
| } | |
| } catch (error) { | |
| Utils.showToast("Network gateway error. Retrying recommended."); | |
| } | |
| triggerBtn.disabled = false; triggerBtn.innerHTML = originalText; | |
| }, | |
| logout: () => { localStorage.removeItem('arjun_user'); location.reload(); } | |
| }; | |
| /** | |
| * SPEECH AND VOICE ENGINE (Integration of Gradio Edge-TTS & Browser STT) | |
| */ | |
| const VoiceEngine = { | |
| recognition: null, | |
| currentLanguage: 'en-IN', | |
| init: async () => { | |
| // Pre-connect to Gradio Client in background | |
| try { | |
| AppState.gradioClient = await Client.connect("Vedika66/Edge-TTS"); | |
| console.log("Neural TTS Engine connected successfully."); | |
| } catch(err) { | |
| console.error("Gradio Connection Error:", err); | |
| } | |
| // Initialize STT | |
| const SR = window.SpeechRecognition || window.webkitSpeechRecognition; | |
| if (!SR) return; | |
| VoiceEngine.recognition = new SR(); | |
| VoiceEngine.recognition.continuous = false; | |
| VoiceEngine.recognition.interimResults = false; | |
| VoiceEngine.recognition.lang = VoiceEngine.currentLanguage; | |
| VoiceEngine.recognition.onstart = () => { | |
| document.getElementById('masterVoiceBtn').classList.add('active-listening'); | |
| if (AppState.isLiveModeEngaged) { | |
| document.getElementById('liveMicBtn').classList.add('is-recording'); | |
| document.getElementById('liveStatusText').innerText = "Listening..."; | |
| document.getElementById('liveOrb').style.transform = "scale(1.25)"; | |
| } | |
| }; | |
| VoiceEngine.recognition.onresult = (event) => { | |
| let transcript = ''; | |
| for (let i = event.resultIndex; i < event.results.length; ++i) transcript += event.results[i][0].transcript; | |
| transcript = transcript.trim(); | |
| if (transcript.length > 0) { | |
| transcript = transcript.charAt(0).toUpperCase() + transcript.slice(1); | |
| if (!/[.!?।]$/.test(transcript)) transcript += '.'; transcript += ' '; | |
| } | |
| if (AppState.isLiveModeEngaged) { | |
| document.getElementById('liveTranscriptText').innerText = `"${transcript}"`; | |
| document.getElementById('liveStatusText').innerText = "Synthesizing..."; | |
| document.getElementById('mainChatInput').value = transcript; | |
| ChatEngine.initiateDispatch(); | |
| } else { | |
| const inputField = document.getElementById('mainChatInput'); | |
| inputField.value = (inputField.value + ' ' + transcript).trim(); | |
| document.getElementById('mainChatInput').style.height = Math.min(inputField.scrollHeight, 200) + 'px'; | |
| } | |
| }; | |
| VoiceEngine.recognition.onend = () => { | |
| document.getElementById('masterVoiceBtn').classList.remove('active-listening'); | |
| if (AppState.isLiveModeEngaged && !AppState.isProcessing) { | |
| document.getElementById('liveMicBtn').classList.remove('is-recording'); | |
| document.getElementById('liveStatusText').innerText = "Tap mic to interact"; | |
| document.getElementById('liveOrb').style.transform = "scale(1)"; | |
| } | |
| }; | |
| VoiceEngine.recognition.onerror = (event) => { | |
| Utils.showToast("Mic Error: " + event.error); | |
| document.getElementById('masterVoiceBtn').classList.remove('active-listening'); | |
| if (AppState.isLiveModeEngaged) { | |
| document.getElementById('liveMicBtn').classList.remove('is-recording'); | |
| document.getElementById('liveStatusText').innerText = "Audio Failure."; | |
| } | |
| }; | |
| }, | |
| switchLanguage: () => { | |
| const btn = document.getElementById('smartLangToggle'); | |
| const badge = document.getElementById('langDisplayBadge'); | |
| if (VoiceEngine.currentLanguage === 'en-IN') { | |
| VoiceEngine.currentLanguage = 'hi-IN'; | |
| badge.innerText = 'हि'; | |
| btn.classList.add('hindi-active'); | |
| Utils.showToast("Listening Protocol: Hindi (देवनागरी)"); | |
| } else { | |
| VoiceEngine.currentLanguage = 'en-IN'; | |
| badge.innerText = 'EN'; | |
| btn.classList.remove('hindi-active'); | |
| Utils.showToast("Listening Protocol: English"); | |
| } | |
| if (VoiceEngine.recognition) VoiceEngine.recognition.lang = VoiceEngine.currentLanguage; | |
| }, | |
| executeTTS: async (text) => { | |
| const cleanText = text.replace(/[*_~`#]/g, '').replace(/<[^>]*>?/gm, ''); | |
| if(!cleanText.trim()) return; | |
| Utils.showToast("🔊 Linking with Neural Voice Matrix..."); | |
| try { | |
| // Gradio Client execution | |
| if(!AppState.gradioClient) { | |
| AppState.gradioClient = await Client.connect("Vedika66/Edge-TTS"); | |
| } | |
| const result = await AppState.gradioClient.predict("/smart_hybrid_tts", { | |
| text: cleanText, | |
| voice_type: "प्रभात (भारी और प्राकृतिक आवाज़ - हिंग्लिश के लिए)" | |
| }); | |
| if (result.data && result.data[0]) { | |
| const audioUrl = result.data[0].url || result.data[0]; | |
| const audio = new Audio(audioUrl); | |
| audio.play(); | |
| } else { | |
| throw new Error("No audio payload returned."); | |
| } | |
| } catch (error) { | |
| Utils.showToast("Voice Neural Matrix is currently overloaded."); | |
| console.error("TTS Error:", error); | |
| } | |
| } | |
| }; | |
| /** | |
| * FILE & DOCUMENT PROCESSOR | |
| */ | |
| const FileProcessor = { | |
| processFile: async (inputElement, typeContext) => { | |
| const file = inputElement.files[0]; | |
| if (!file) return; | |
| const fName = file.name.toLowerCase(); | |
| const mime = file.type; | |
| if (typeContext === 'image' && !mime.startsWith('image/')) { Utils.showToast("Visual media required."); inputElement.value=''; return; } | |
| if (typeContext === 'video' && !mime.startsWith('video/')) { Utils.showToast("Video media required."); inputElement.value=''; return; } | |
| if (typeContext === 'audio' && !mime.startsWith('audio/')) { Utils.showToast("Audio media required."); inputElement.value=''; return; } | |
| Utils.showToast(`Uploading ${file.name}...`); | |
| const thumbImg = document.getElementById('previewImgThumb'); | |
| const docIcon = document.getElementById('previewDocIcon'); | |
| thumbImg.style.display = 'none'; docIcon.style.display = 'none'; | |
| document.getElementById('previewFileName').innerText = file.name; | |
| document.getElementById('filePreviewBar').classList.add('visible'); | |
| const fileReader = new FileReader(); | |
| if (typeContext === 'image') { | |
| fileReader.onload = (e) => { | |
| AppState.pendingAttachment = { type: 'image', data: e.target.result.split(',')[1], name: file.name }; | |
| thumbImg.src = e.target.result; thumbImg.style.display = 'flex'; | |
| }; fileReader.readAsDataURL(file); | |
| } | |
| else if (typeContext === 'video' || typeContext === 'audio') { | |
| fileReader.onload = (e) => { | |
| AppState.pendingAttachment = { type: typeContext, data: e.target.result.split(',')[1], name: file.name }; | |
| docIcon.innerText = typeContext === 'video' ? '🎥' : '🎵'; docIcon.style.display = 'flex'; | |
| }; fileReader.readAsDataURL(file); | |
| } | |
| else if (typeContext === 'document') { | |
| docIcon.innerText = '📄'; docIcon.style.display = 'flex'; | |
| if (fName.endsWith('.pdf')) { | |
| fileReader.onload = async function() { | |
| try { | |
| const typedArray = new Uint8Array(this.result); | |
| const pdfDoc = await pdfjsLib.getDocument(typedArray).promise; | |
| let extractedText = ""; | |
| for (let i = 1; i <= pdfDoc.numPages; i++) { | |
| const page = await pdfDoc.getPage(i); | |
| const content = await page.getTextContent(); | |
| extractedText += content.items.map(s => s.str).join(' ') + "\n"; | |
| } | |
| AppState.pendingAttachment = { type: 'text', data: extractedText.trim(), name: file.name }; | |
| Utils.showToast("Your PDF is ready!"); | |
| } catch (e) { Utils.showToast("PDF analysis failed."); FileProcessor.discard(); } | |
| }; fileReader.readAsArrayBuffer(file); | |
| } | |
| else if (fName.endsWith('.docx') || fName.endsWith('.doc')) { | |
| fileReader.onload = async function() { | |
| try { | |
| const resultData = await mammoth.extractRawText({ arrayBuffer: this.result }); | |
| AppState.pendingAttachment = { type: 'text', data: resultData.value.trim(), name: file.name }; | |
| Utils.showToast("Your Document is ready!"); | |
| } catch(e) { Utils.showToast("Document analysis failed."); FileProcessor.discard(); } | |
| }; fileReader.readAsArrayBuffer(file); | |
| } | |
| else { | |
| fileReader.onload = (e) => { | |
| AppState.pendingAttachment = { type: 'text', data: e.target.result, name: file.name }; | |
| Utils.showToast("Your Code/Text is ready!"); | |
| }; fileReader.readAsText(file); | |
| } | |
| } | |
| inputElement.value = ''; | |
| }, | |
| discard: () => { | |
| AppState.pendingAttachment = null; | |
| document.getElementById('filePreviewBar').classList.remove('visible'); | |
| } | |
| }; | |
| /** | |
| * CHAT ENGINE & LLM LOGIC | |
| */ | |
| const ChatEngine = { | |
| syncHistoryFromCloud: async () => { | |
| const messageZone = document.getElementById('msgs'); | |
| document.getElementById('welcomeState').style.display = 'none'; | |
| messageZone.innerHTML = '<div style="text-align:center; padding:80px; font-weight:800; color:var(--brand-saffron); font-size:18px;">Decrypting Historic Archives...</div>'; | |
| try { | |
| const response = await fetch(Config.GAS_URL, { | |
| method: 'POST', | |
| mode: 'cors', | |
| headers: { 'Content-Type': 'text/plain;charset=utf-8' }, | |
| body: JSON.stringify({ action: "get_history", email: AppState.currentUser }) | |
| }); | |
| const resData = await response.json(); | |
| messageZone.innerHTML = ''; | |
| if (resData.status === 'success' && resData.historyJSON !== "[]") { | |
| AppState.history = JSON.parse(resData.historyJSON); | |
| AppState.history.forEach(msgObj => { | |
| if (msgObj.role === 'user') ChatEngine.renderUserMessage(msgObj.content, msgObj.badge, msgObj.previewHTML); | |
| else { AppState.isStreamingActive = false; ChatEngine.renderBotMessage(msgObj.content, true); } | |
| }); | |
| setTimeout(() => { | |
| messageZone.scrollTo({ top: messageZone.scrollHeight, behavior: 'smooth' }); | |
| }, 200); | |
| } else { document.getElementById('welcomeState').style.display = 'flex'; } | |
| } catch (err) { messageZone.innerHTML = ''; document.getElementById('welcomeState').style.display = 'flex'; } | |
| }, | |
| saveHistoryToCloud: () => { | |
| if (AppState.currentUser) { | |
| fetch(Config.GAS_URL, { | |
| method: 'POST', mode: 'cors', headers: { 'Content-Type': 'text/plain;charset=utf-8' }, | |
| body: JSON.stringify({ action: "save_history", email: AppState.currentUser, historyJSON: JSON.stringify(AppState.history) }) | |
| }); | |
| } | |
| }, | |
| buildPreviewHTML: (att) => { | |
| if (!att) return ''; | |
| if (att.type === 'image') return `<img src="data:image/jpeg;base64,${att.data}" class="chat-in-bubble-img">`; | |
| if (att.type === 'video') return `<div class="chat-file-card"><span class="icon">🎥</span><span class="name">${att.name}</span></div>`; | |
| if (att.type === 'audio') return `<div class="chat-file-card"><span class="icon">🎵</span><span class="name">${att.name}</span></div>`; | |
| return `<div class="chat-file-card"><span class="icon">📄</span><span class="name">${att.name}</span></div>`; | |
| }, | |
| renderUserMessage: (text, badgeText, previewHTMLString = '') => { | |
| let badgeNode = badgeText ? `<div class="file-badge">${Utils.escapeHTML(badgeText)}</div>` : ''; | |
| const bubble = document.createElement('div'); bubble.className = 'chat-message-row user-msg'; | |
| bubble.innerHTML = `<div class="msg-avatar">U</div><div class="msg-content-column">${badgeNode}<div class="chat-bubble">${previewHTMLString}${Utils.escapeHTML(text)}</div></div>`; | |
| document.getElementById('msgs').appendChild(bubble); | |
| }, | |
| renderBotMessage: (text, isComplete = false) => { | |
| const bubble = document.createElement('div'); bubble.className = 'chat-message-row bot-msg'; | |
| bubble.innerHTML = `<div class="msg-avatar"><img src="${Config.LOGO_URL}"></div><div class="msg-content-column"><div class="chat-bubble"></div></div>`; | |
| document.getElementById('msgs').appendChild(bubble); | |
| ChatEngine.updateBotBubble(bubble, text, !isComplete); | |
| return bubble; | |
| }, | |
| updateBotBubble: (bubbleDOM, rawMarkup, isCurrentlyStreaming) => { | |
| const target = bubbleDOM.querySelector('.chat-bubble'); | |
| const stripped = rawMarkup.replace(/<think>([\s\S]*?)(<\/think>|$)/gi, ''); | |
| let html = marked.parse(stripped.trim()); | |
| if (isCurrentlyStreaming) html += `<div class="loading-dots-container"><div class="loading-dot"></div><div class="loading-dot"></div><div class="loading-dot"></div></div>`; | |
| target.innerHTML = html; | |
| let tray = bubbleDOM.querySelector('.bot-actions-row'); | |
| if (!isCurrentlyStreaming && !tray && stripped.trim().length > 0) { | |
| const sCopy = stripped.replace(/"/g, '"').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, ''); | |
| const sTTS = stripped.replace(/"/g, '"').replace(/'/g, "\\'").replace(/\n/g, ' '); | |
| const acts = `<div class="bot-actions-row"><button class="btn-bot-action btn-cpy" data-cp="${sCopy}"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>Copy Source</button><button class="btn-bot-action action-tts btn-ts" data-ts="${sTTS}"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg>Listen</button></div>`; | |
| bubbleDOM.querySelector('.msg-content-column').insertAdjacentHTML('beforeend', acts); | |
| // Attach dynamic listeners safely | |
| bubbleDOM.querySelector('.btn-cpy').addEventListener('click', function() { Utils.copyToClipboard(this, this.getAttribute('data-cp')); }); | |
| bubbleDOM.querySelector('.btn-ts').addEventListener('click', function() { VoiceEngine.executeTTS(this.getAttribute('data-ts')); }); | |
| } | |
| }, | |
| initiateDispatch: async () => { | |
| if (AppState.isProcessing) return; | |
| const inp = document.getElementById('mainChatInput'); | |
| const rawUserText = inp.value.trim(); | |
| if (!rawUserText && !AppState.pendingAttachment) return; | |
| if (!AppState.currentUser) { | |
| if (AppState.guestCount >= 3) { document.getElementById('secureAuthModal').style.display='flex'; return Utils.showToast("Unregistered query limit reached. Secure Login required."); } | |
| AppState.guestCount++; localStorage.setItem('arjun_guest', AppState.guestCount.toString()); document.getElementById('guestCountDisplay').innerText = AppState.guestCount; | |
| } | |
| inp.value = ''; inp.style.height = 'auto'; document.getElementById('masterSendBtn').disabled = true; AppState.isProcessing = true; | |
| const wState = document.getElementById('welcomeState'); if (wState) wState.style.display = 'none'; | |
| let payloadStr = rawUserText; let payloadAtts = []; let visualBadge = null; let preHTML = ''; | |
| if (AppState.pendingAttachment) { | |
| preHTML = ChatEngine.buildPreviewHTML(AppState.pendingAttachment); | |
| if (AppState.pendingAttachment.type === 'text') { | |
| payloadStr = `[Document Analyzed: ${AppState.pendingAttachment.name}]\n\n---DATA BEGIN---\n${AppState.pendingAttachment.data}\n---DATA END---\n\nUser Prompt: ${rawUserText}`; | |
| visualBadge = '📄 File Appended'; | |
| } else { | |
| payloadAtts.push({ type: AppState.pendingAttachment.type, data: AppState.pendingAttachment.data, name: AppState.pendingAttachment.name }); | |
| visualBadge = ({ 'video': '🎥 ', 'audio': '🎵 ', 'image': '🖼️ ' }[AppState.pendingAttachment.type] || '📎 ') + "Media"; | |
| } | |
| ChatEngine.renderUserMessage(rawUserText || '[Transmitting Media Context]', visualBadge, preHTML); | |
| AppState.history.push({ role: 'user', content: payloadStr, badge: visualBadge, previewHTML: preHTML }); | |
| } else { | |
| ChatEngine.renderUserMessage(rawUserText, null, ''); | |
| AppState.history.push({ role: 'user', content: rawUserText }); | |
| } | |
| FileProcessor.discard(); ChatEngine.saveHistoryToCloud(); | |
| const activeBotBubble = ChatEngine.renderBotMessage('', false); | |
| const msgArea = document.getElementById('msgs'); msgArea.scrollTop = msgArea.scrollHeight; | |
| const cryptographicSeed = Math.floor(Math.random() * 999999999); | |
| let sysPrompt = `You are Arjun 2.O, a sophisticated enterprise AI system architected by Abhay Kumar. | |
| LANGUAGE REGULATION: Your default cognitive language is ENGLISH. If the user writes in English, reply in purely professional English. If the user writes in Hindi or Hinglish, reply gracefully in Hindi. Never force Hindi translation if the prompt is English. | |
| IMAGE SYNTHESIS: | |
| When commanded to render, generate, or create an image/photograph, you MUST reply with a precise markdown image node targeting Pollinations AI. | |
| Formula:  | |
| Models: flux, flux-realism, flux-anime, flux-3d. | |
| CRITICAL: The seed parameter is mandatory.`; | |
| if (AppState.isLiveModeEngaged) sysPrompt += `\n\n[LIVE ACOUSTIC OVERRIDE]: You are currently engaged in a LIVE, REAL-TIME VOCAL INTERFACE. MANDATORY direct answers. Maximum brevity. Eliminate complex markdown or massive code blocks. Respond exactly like a human on a brief phone call.`; | |
| const secureHistory = AppState.history.slice(0, -1).map(h => ({ role: h.role, content: h.content })); | |
| const transmissionPayload = { message: payloadStr, attachments: payloadAtts, system_prompt: sysPrompt, history: secureHistory, max_tokens: AppState.isLiveModeEngaged ? 120 : 4096, temperature: 0.75 }; | |
| try { | |
| const fetchOp = await fetch(Config.API_ENDPOINT, { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(transmissionPayload) }); | |
| if (!fetchOp.ok) throw new Error("API Matrix Disconnected."); | |
| const networkReader = fetchOp.body.getReader(); const textDecoder = new TextDecoder(); let responseBuffer = ""; | |
| AppState.isStreamingActive = true; | |
| while (true) { | |
| const { done, value } = await networkReader.read(); | |
| if (done) break; | |
| const decodedChunk = textDecoder.decode(value, { stream: true }); | |
| const lines = decodedChunk.split('\n'); | |
| for (let line of lines) { | |
| if (line.startsWith('data: ')) { | |
| const parseableStr = line.substring(6); | |
| if (parseableStr.trim() === '[DONE]') continue; | |
| try { | |
| const jsonSegment = JSON.parse(parseableStr); | |
| if (jsonSegment.choices && jsonSegment.choices[0].delta.content) { | |
| responseBuffer += jsonSegment.choices[0].delta.content; | |
| ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, true); | |
| if(!AppState.isUserScrolling) { msgArea.scrollTop = msgArea.scrollHeight; } | |
| } | |
| } catch (e) { } | |
| } | |
| } | |
| } | |
| AppState.isStreamingActive = false; | |
| ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, false); | |
| AppState.history.push({ role: 'bot', content: responseBuffer }); | |
| ChatEngine.saveHistoryToCloud(); | |
| if (AppState.isLiveModeEngaged) { | |
| document.getElementById('liveStatusText').innerText = "Arjun Transmitting..."; | |
| await VoiceEngine.executeTTS(responseBuffer); | |
| document.getElementById('liveStatusText').innerText = "Tap mic to respond"; | |
| } | |
| } catch(error) { | |
| AppState.isStreamingActive = false; | |
| ChatEngine.updateBotBubble(activeBotBubble, `**System Error:** Communication array offline. Check connection.`, false); | |
| if (AppState.isLiveModeEngaged) document.getElementById('liveStatusText').innerText = "Neural Link Severed."; | |
| } | |
| AppState.isProcessing = false; document.getElementById('masterSendBtn').disabled = false; | |
| if(!AppState.isUserScrolling) { msgArea.scrollTop = msgArea.scrollHeight; } | |
| } | |
| }; | |
| /** | |
| * MARKED.JS Workspace Renderer configuration | |
| */ | |
| const MD_Renderer = new marked.Renderer(); | |
| MD_Renderer.code = function(token) { | |
| const rawCode = typeof token === 'string' ? token : (token.text || ''); | |
| const langClass = typeof token === 'string' ? arguments[1] : (token.lang || ''); | |
| if (AppState.isStreamingActive) return `<div class="streaming-code-container"><div class="streaming-code-header"><div class="loading-ring"></div>Generating Architecture...</div><pre><code class="language-${langClass}">${Utils.escapeHTML(rawCode)}</code></pre></div>`; | |
| const internalId = AppState.generatedCodeBlocks.length; | |
| AppState.generatedCodeBlocks.push({ code: rawCode, lang: langClass }); | |
| return `<div class="workspace-execute-card"><div class="ws-card-left"><div class="ws-card-icon-box"><svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg></div><div class="ws-card-details"><h4>Code Module Compiled</h4><p>${langClass || 'Syntax Detected'}</p></div></div><button class="btn-launch-workspace btn-launch-ws" data-id="${internalId}">Open Workspace</button></div>`; | |
| }; | |
| marked.use({ renderer: MD_Renderer }); | |
| // Event delegation for workspace buttons | |
| document.getElementById('msgs').addEventListener('click', function(e) { | |
| if (e.target && e.target.classList.contains('btn-launch-ws')) { | |
| const blockId = e.target.getAttribute('data-id'); | |
| AppState.currentWorkspaceId = blockId; | |
| const codeData = AppState.generatedCodeBlocks[blockId]; | |
| document.getElementById('wsTitleText').innerText = codeData.lang ? `Generated ${codeData.lang.toUpperCase()}` : "Compiled Code"; | |
| const blockDisplay = document.getElementById('workspaceCodeBlock'); | |
| blockDisplay.className = `hljs language-${codeData.lang || 'plaintext'}`; | |
| blockDisplay.textContent = codeData.code; | |
| hljs.highlightElement(blockDisplay); | |
| document.getElementById('workspacePanel').classList.add('expanded'); | |
| if (window.innerWidth <= 1024) document.getElementById('sidebar').classList.remove('active'); | |
| } | |
| }); | |
| /** | |
| * EVENT LISTENERS BINDING | |
| */ | |
| // Startup | |
| document.getElementById('btnLaunchSystem').addEventListener('click', () => { document.getElementById('welcomeOverlay').classList.add('hidden'); localStorage.setItem('arjun_welcome_seen', 'true'); setTimeout(() => { document.getElementById('welcomeOverlay').style.display = 'none'; }, 400); }); | |
| // Sidebar | |
| document.getElementById('btnSidebarOpen').addEventListener('click', () => document.getElementById('sidebar').classList.add('active')); | |
| document.getElementById('btnSidebarClose').addEventListener('click', () => document.getElementById('sidebar').classList.remove('active')); | |
| // Auth Module | |
| document.getElementById('loginPromptBtn').addEventListener('click', () => document.getElementById('secureAuthModal').style.display = 'flex'); | |
| document.getElementById('btnAuthClose').addEventListener('click', () => document.getElementById('secureAuthModal').style.display = 'none'); | |
| document.getElementById('btn-tab-login').addEventListener('click', () => AuthManager.switchTab('login')); | |
| document.getElementById('btn-tab-register').addEventListener('click', () => AuthManager.switchTab('register')); | |
| document.getElementById('btn-fire-log-otp').addEventListener('click', () => AuthManager.process('login_send_otp')); | |
| document.getElementById('btn-fire-log-verify').addEventListener('click', () => AuthManager.process('login_verify')); | |
| document.getElementById('btn-fire-reg-otp').addEventListener('click', () => AuthManager.process('register_send_otp')); | |
| document.getElementById('btn-fire-reg-verify').addEventListener('click', () => AuthManager.process('register_verify')); | |
| document.getElementById('btnLogBack').addEventListener('click', () => AuthManager.switchPhase('auth-log-phase-2', 'auth-log-phase-1')); | |
| document.getElementById('btnRegBack').addEventListener('click', () => AuthManager.switchPhase('auth-reg-phase-2', 'auth-reg-phase-1')); | |
| document.getElementById('btnLogout').addEventListener('click', AuthManager.logout); | |
| document.getElementById('btnClearMemory').addEventListener('click', ChatEngine.clearMemory); | |
| // Chat Engine & Suggestions | |
| document.getElementById('masterSendBtn').addEventListener('click', ChatEngine.initiateDispatch); | |
| document.getElementById('mainChatInput').addEventListener('keydown', ChatEngine.handleKeyboard); | |
| document.getElementById('mainChatInput').addEventListener('input', function() { this.style.height = 'auto'; this.style.height = Math.min(this.scrollHeight, 200) + 'px'; }); | |
| document.getElementById('msgs').addEventListener('scroll', () => { | |
| const msgArea = document.getElementById('msgs'); | |
| const isAtBottom = Math.abs((msgArea.scrollHeight - msgArea.scrollTop) - msgArea.clientHeight) < 80; | |
| AppState.isUserScrolling = !isAtBottom; | |
| const scrollBtn = document.getElementById('scrollTriggerBtn'); | |
| if (AppState.isUserScrolling) scrollBtn.classList.add('visible'); else scrollBtn.classList.remove('visible'); | |
| }); | |
| document.getElementById('scrollTriggerBtn').addEventListener('click', () => { | |
| const msgArea = document.getElementById('msgs'); msgArea.scrollTo({ top: msgArea.scrollHeight, behavior: 'smooth' }); | |
| AppState.isUserScrolling = false; document.getElementById('scrollTriggerBtn').classList.remove('visible'); | |
| }); | |
| document.getElementById('suggCodeBtn').addEventListener('click', () => { document.getElementById('mainChatInput').value = "Write a secure python script for a modern Flask backend server."; ChatEngine.initiateDispatch(); }); | |
| document.getElementById('suggImgBtn').addEventListener('click', () => { document.getElementById('mainChatInput').value = "Create a hyper-realistic 8k image of a futuristic Indian smart city."; ChatEngine.initiateDispatch(); }); | |
| // Attachment Controls | |
| document.getElementById('btnAttachMenuToggle').addEventListener('click', () => document.getElementById('attachDropdownMenu').classList.toggle('visible')); | |
| document.addEventListener('click', (e) => { const wrapper = document.querySelector('.attachment-module'); if (!wrapper.contains(e.target)) document.getElementById('attachDropdownMenu').classList.remove('visible'); }); | |
| document.getElementById('opt-image').addEventListener('click', () => { document.getElementById('attachDropdownMenu').classList.remove('visible'); document.getElementById('sys-inp-image').click(); }); | |
| document.getElementById('opt-video').addEventListener('click', () => { document.getElementById('attachDropdownMenu').classList.remove('visible'); document.getElementById('sys-inp-video').click(); }); | |
| document.getElementById('opt-audio').addEventListener('click', () => { document.getElementById('attachDropdownMenu').classList.remove('visible'); document.getElementById('sys-inp-audio').click(); }); | |
| document.getElementById('opt-document').addEventListener('click', () => { document.getElementById('attachDropdownMenu').classList.remove('visible'); document.getElementById('sys-inp-document').click(); }); | |
| document.getElementById('sys-inp-image').addEventListener('change', function() { FileProcessor.processFile(this, 'image'); }); | |
| document.getElementById('sys-inp-video').addEventListener('change', function() { FileProcessor.processFile(this, 'video'); }); | |
| document.getElementById('sys-inp-audio').addEventListener('change', function() { FileProcessor.processFile(this, 'audio'); }); | |
| document.getElementById('sys-inp-document').addEventListener('change', function() { FileProcessor.processFile(this, 'document'); }); | |
| document.getElementById('btnDiscardFile').addEventListener('click', FileProcessor.discard); | |
| // Voice & Live Mode | |
| document.getElementById('smartLangToggle').addEventListener('click', VoiceEngine.switchLanguage); | |
| document.getElementById('masterVoiceBtn').addEventListener('click', () => { if(!VoiceEngine.recognition) return Utils.showToast("Voice unavailable."); if(isRecording) VoiceEngine.recognition.stop(); else VoiceEngine.recognition.start(); }); | |
| document.getElementById('btnStartLiveMode').addEventListener('click', () => { AppState.isLiveModeEngaged = true; document.getElementById('liveOverlay').classList.add('active'); if(VoiceEngine.recognition && !isRecording) setTimeout(()=>VoiceEngine.recognition.start(), 500); }); | |
| document.getElementById('btnExitLiveMode').addEventListener('click', () => { AppState.isLiveModeEngaged = false; document.getElementById('liveOverlay').classList.remove('active'); if(VoiceEngine.recognition && isRecording) VoiceEngine.recognition.stop(); }); | |
| document.getElementById('liveMicBtn').addEventListener('click', () => { if(!VoiceEngine.recognition) return Utils.showToast("Voice unavailable."); if(isRecording) VoiceEngine.recognition.stop(); else VoiceEngine.recognition.start(); }); | |
| // Workspace Events | |
| document.getElementById('btnWsClose').addEventListener('click', () => document.getElementById('workspacePanel').classList.remove('expanded')); | |
| document.getElementById('btnWsCopy').addEventListener('click', function() { if(AppState.currentWorkspaceId !== null) Utils.copyToClipboard(this, AppState.generatedCodeBlocks[AppState.currentWorkspaceId].code); }); | |
| // BOOTSTRAP TRIGGER | |
| VoiceEngine.init(); | |
| AuthManager.initUI(); | |
| </script> | |
| </body> | |
| </html> |