CodeVed / index.html
Vedika
Update index.html
3aa6701 verified
Raw
History Blame
120 kB
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Viewport settings strictly structured to prevent mobile keyboard layout shifting -->
<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">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<title>Arjun 2.O - Professional Advanced AI</title>
<!-- =========================================================================================
1. EXTERNAL RESOURCES & LIBRARIES
========================================================================================= -->
<!-- Preconnect for Performance Optimization -->
<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. MASSIVE CSS ARCHITECTURE (ENTERPRISE SCALED)
========================================================================================= -->
<style>
/* ---------------------------------------------------------------------------------------
A. CSS VARIABLES & DESIGN TOKENS
--------------------------------------------------------------------------------------- */
:root {
/* Branding: Professional Theme (Arjun Base) */
--brand-saffron: #FF9933;
--brand-saffron-light: rgba(255, 153, 51, 0.12);
--brand-saffron-hover: #e68a2e;
--brand-saffron-active: #cc7a29;
--brand-saffron-glow: rgba(255, 153, 51, 0.4);
--brand-white: #FFFFFF;
--brand-white-glass: rgba(255, 255, 255, 0.85);
--brand-white-dim: rgba(255, 255, 255, 0.6);
--brand-green: #138808;
--brand-green-light: rgba(19, 136, 8, 0.12);
--brand-green-hover: #0f6e06;
--brand-green-active: #0c5905;
--brand-green-glow: rgba(19, 136, 8, 0.4);
/* Core UI Colors */
--bg-primary: #ffffff;
--bg-secondary: #f8f9fa;
--bg-tertiary: #f1f3f5;
--bg-glass: rgba(255, 255, 255, 0.75);
--bg-overlay: rgba(0, 0, 0, 0.5);
--bg-workspace: #282c34;
/* Text Hierarchy */
--text-primary: #111827;
--text-secondary: #4b5563;
--text-tertiary: #9ca3af;
--text-inverse: #ffffff;
--text-danger: #ef4444;
/* Border & Dividers */
--border-light: rgba(0, 0, 0, 0.08);
--border-medium: rgba(0, 0, 0, 0.15);
--border-strong: rgba(0, 0, 0, 0.25);
--border-focus: rgba(255, 153, 51, 0.4);
/* Depth & Elevation (Shadows) */
--shadow-xs: 0 1px 2px rgba(0,0,0,0.04);
--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);
--shadow-float: 0 25px 50px -12px rgba(0,0,0,0.15);
/* Typography Scale */
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-mono: 'Geist Mono', Consolas, Monaco, "Ubuntu Mono", monospace;
--font-serif: 'Instrument Serif', Georgia, serif;
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 1.875rem;
--text-4xl: 2.25rem;
/* Border Radii */
--radius-xs: 4px;
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 24px;
--radius-2xl: 32px;
--radius-full: 9999px;
/* Transitions & Easing */
--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);
--ease-bounce: 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* Z-Index Hierarchy */
--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%; height: 100%; }
/* Ensures the body takes up exactly the visible screen, fixing mobile keyboard shift */
body {
height: 100%;
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;
display: flex;
flex-direction: column;
}
button, input, textarea, select { font-family: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; height: auto; display: block; }
ul, ol { list-style: none; }
/* ---------------------------------------------------------------------------------------
C. AMBIENT BACKGROUND EFFECTS
--------------------------------------------------------------------------------------- */
.ambient-environment {
position: fixed; top: 0; left: 0; right: 0; bottom: 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; animation-duration: 40s;
}
@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: var(--text-sm); font-weight: 600;
box-shadow: var(--shadow-lg); animation: toastSlideIn var(--ease-spring) forwards, toastFadeOut 0.4s 2.6s forwards;
display: flex; align-items: center; gap: 10px;
}
.toast-notification svg { width: 18px; height: 18px; stroke-width: 2.5; }
@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: var(--text-4xl); 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: var(--text-lg); 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: var(--text-lg); 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 (FLEX ARCHITECTURE)
--------------------------------------------------------------------------------------- */
.app-root {
position: relative; z-index: var(--z-base); display: flex;
height: 100%; width: 100vw; overflow: hidden; background: var(--bg-glass);
backdrop-filter: blur(30px); -webkit-backdrop-filter: blur(30px); flex: 1;
}
/* ---------------------------------------------------------------------------------------
G. SIDEBAR NAVIGATION
--------------------------------------------------------------------------------------- */
.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); height: 100%;
}
.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; }
.sidebar-body::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.2); }
/* Auth Widget */
.auth-widget { background: var(--bg-primary); border: 1px solid var(--border-light); border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow-sm); position: relative; overflow: hidden; }
.btn-secure-connect { width: 100%; padding: 14px; background: var(--text-primary); color: var(--text-inverse); border: none; border-radius: var(--radius-md); font-size: var(--text-sm); 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; }
/* Branding 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: var(--text-sm); 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; }
/* ---------------------------------------------------------------------------------------
H. MAIN CHAT INTERFACE
--------------------------------------------------------------------------------------- */
.main-chat-wrapper { flex: 1; display: flex; flex-direction: column; position: relative; min-width: 320px; transition: width var(--ease-smooth); background: transparent; height: 100%; }
.chat-top-bar { padding: 18px 32px; border-bottom: 1px solid var(--border-light); background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px); display: flex; align-items: center; justify-content: space-between; z-index: var(--z-overlay); flex-shrink:0; }
.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: var(--text-sm); 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); box-shadow: inset 0 1px 2px rgba(255,255,255,0.5); }
.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); letter-spacing: 0.5px; }
.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; } }
/* ---------------------------------------------------------------------------------------
I. CONVERSATION SCROLL AREA & WELCOME
--------------------------------------------------------------------------------------- */
.chat-scroll-area { flex: 1; overflow-y: auto; padding: 40px 10%; display: flex; flex-direction: column; gap: 36px; scroll-behavior: smooth; position: relative; min-height: 0; }
.chat-scroll-area::-webkit-scrollbar { width: 6px; }
.chat-scroll-area::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); border-radius: 10px; }
.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; }
/* ---------------------------------------------------------------------------------------
J. CHAT MESSAGE BUBBLES
--------------------------------------------------------------------------------------- */
.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 Preview Cards within bubble */
.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; backdrop-filter: blur(5px); 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 Action Buttons */
.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); }
/* ---------------------------------------------------------------------------------------
K. MARKDOWN & CODE RENDERING 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; }
/* Standard Pre Code Block */
.chat-bubble pre { background: var(--bg-workspace); 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; }
/* Streaming Code Container */
.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; }
/* Final 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); }
/* ---------------------------------------------------------------------------------------
L. INPUT AREA & CONTROLS (BOTTOM BAR)
--------------------------------------------------------------------------------------- */
.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); -webkit-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-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); position: relative; }
.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); -webkit-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 & Mic */
.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); } }
/* Primary Send Button */
.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; }
/* ---------------------------------------------------------------------------------------
M. LIVE MODE FULLSCREEN OVERLAY
--------------------------------------------------------------------------------------- */
.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); letter-spacing: -0.5px; }
.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); } }
.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); }
/* ---------------------------------------------------------------------------------------
N. WORKSPACE (CODE EXECUTION PANEL)
--------------------------------------------------------------------------------------- */
.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: var(--bg-workspace); 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; }
/* ---------------------------------------------------------------------------------------
O. AUTHENTICATION MODAL (SECURE GATEWAY)
--------------------------------------------------------------------------------------- */
.secure-modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.5); backdrop-filter: blur(10px); -webkit-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); }
/* Core Animations */
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes slideIn { from { opacity: 0; transform: translateX(25px); } to { opacity: 1; transform: none; } }
.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); } }
/* ---------------------------------------------------------------------------------------
P. RESPONSIVE 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, .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 ELEMENT 1: GLOBAL NOTIFICATIONS
========================================================================================= -->
<div id="toast-container" class="toast-wrapper"></div>
<!-- =========================================================================================
DOM ELEMENT 2: 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" onclick="ApplicationCore.launchSystem()">
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 ELEMENT 3: LIVE MODE FULLSCREEN OVERLAY
========================================================================================= -->
<div class="live-mode-viewport" id="liveOverlay">
<button class="btn-close-live" onclick="LiveModeController.terminate()" 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" onclick="VoiceEngine.toggleLive()">
<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 ELEMENT 4: AMBIENT BACKGROUND
========================================================================================= -->
<div class="ambient-environment">
<div class="ambient-orb orb-top-left"></div>
<div class="ambient-orb orb-bottom-right"></div>
</div>
<!-- =========================================================================================
DOM ELEMENT 5: MASTER APPLICATION CONTAINER
========================================================================================= -->
<div class="app-root">
<!-- -------------------------------------------------------------------------------------
A. NAVIGATION 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" onclick="UIManager.toggleSidebar()">
<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">
<!-- Authentication Widget -->
<div class="auth-widget">
<button id="loginPromptBtn" class="btn-secure-connect" onclick="AuthManager.openModal()">
<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" onclick="AuthManager.logout()" 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>
<!-- Branding & Developer Info -->
<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>
<!-- Clear Memory Context -->
<button class="btn-erase-memory" onclick="ChatEngine.clearMemory()">
<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>
<!-- -------------------------------------------------------------------------------------
B. MAIN CHAT ENGINE INTERFACE
------------------------------------------------------------------------------------- -->
<main class="main-chat-wrapper">
<!-- Top Status Bar -->
<header class="chat-top-bar">
<div class="top-bar-left">
<button class="btn-hamburger" onclick="UIManager.toggleSidebar()">
<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>
<!-- LIVE MODE ACTIVATOR -->
<button class="btn-activate-live" onclick="LiveModeController.initialize()">
<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>
<!-- Scrollable Conversation Area -->
<div class="chat-scroll-area" id="msgs" onscroll="UIManager.checkScrollState()">
<!-- Internal Welcome / Empty State -->
<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" onclick="ChatEngine.sendExample('Write a secure python script for a modern Flask backend server.')">
<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" onclick="ChatEngine.sendExample('Create a hyper-realistic 8k image of a futuristic Indian smart city.')">
<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>
<!-- Dynamic Chat Bubbles will be appended here -->
</div>
<!-- Floating Scroll Down Button -->
<button class="btn-scroll-trigger" id="scrollTriggerBtn" onclick="UIManager.forceScrollDown()">
<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">
<!-- File Preview Component -->
<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">File ready to analyze</div>
</div>
<button class="btn-discard-upload" onclick="FileProcessor.discardFile()">
<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>
<!-- Main Tool & Input Row -->
<div class="input-tools-row">
<!-- Attachment Dropdown Module -->
<div class="attachment-module">
<button class="btn-tool-icon" onclick="UIManager.toggleAttachMenu()" 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" onclick="FileProcessor.triggerFileSelector('image')">
<span class="emoji-icon">🖼️</span> High-Res Image
</div>
<div class="dropdown-item" onclick="FileProcessor.triggerFileSelector('video')">
<span class="emoji-icon">🎥</span> Video Media
</div>
<div class="dropdown-item" onclick="FileProcessor.triggerFileSelector('audio')">
<span class="emoji-icon">🎵</span> Audio Track
</div>
<div class="dropdown-item" onclick="FileProcessor.triggerFileSelector('document')">
<span class="emoji-icon">📄</span> Document / Code
</div>
</div>
<!-- Hidden File Inputs -->
<input type="file" id="sys-inp-image" class="stealth-input" accept="image/*" onchange="FileProcessor.processFile(this, 'image')">
<input type="file" id="sys-inp-video" class="stealth-input" accept="video/*" onchange="FileProcessor.processFile(this, 'video')">
<input type="file" id="sys-inp-audio" class="stealth-input" accept="audio/*" onchange="FileProcessor.processFile(this, '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" onchange="FileProcessor.processFile(this, 'document')">
</div>
<!-- Smart Language Toggle Button -->
<button class="language-toggle-chip" id="smartLangToggle" onclick="VoiceEngine.switchLanguage()" title="Switch Voice Engine Language">
🌐 <span id="langDisplayBadge">EN</span>
</button>
<!-- Voice Dictation Button -->
<button class="btn-tool-icon btn-mic-tool" id="masterVoiceBtn" onclick="VoiceEngine.toggleDictation()" 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>
<!-- Expanding Text Area -->
<textarea class="main-textarea" id="mainChatInput" placeholder="Message Arjun Intelligence..." rows="1" onkeydown="ChatEngine.handleKeyboard(event)" oninput="UIManager.autoGrowTextArea(this)"></textarea>
<!-- Master Send Button -->
<button class="btn-master-send" id="masterSendBtn" onclick="ChatEngine.initiateDispatch()">
<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>
<!-- -------------------------------------------------------------------------------------
C. 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="workspaceTitleBadge">Workspace</span>
</div>
<div class="workspace-tools">
<button class="btn-workspace-tool" onclick="WorkspaceEngine.executeCopy(this)">
<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" onclick="WorkspaceEngine.closePanel()" 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>
<!-- =========================================================================================
DOM ELEMENT 6: SECURE AUTHENTICATION MODAL
========================================================================================= -->
<div class="secure-modal-backdrop" id="secureAuthModal">
<div class="secure-modal-surface">
<button class="btn-modal-dismiss" onclick="AuthManager.closeModal()">
<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" onclick="AuthManager.switchTab('login')">Connect</div>
<div class="auth-tab-item" id="btn-tab-register" onclick="AuthManager.switchTab('register')">Enroll</div>
</div>
<!-- Login Flow -->
<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" onclick="AuthManager.process('login_send_otp')">Generate 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" onclick="AuthManager.process('login_verify')">Authenticate</button>
<button class="btn-auth-return" onclick="AuthManager.switchPhase('auth-log-phase-2', 'auth-log-phase-1')">← Go Back</button>
</div>
</div>
<!-- Register Flow -->
<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="Email Address">
<button class="btn-auth-execute" id="btn-fire-reg-otp" onclick="AuthManager.process('register_send_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" onclick="AuthManager.process('register_verify')">Initialize Account</button>
<button class="btn-auth-return" onclick="AuthManager.switchPhase('auth-reg-phase-2', 'auth-reg-phase-1')">← Go Back</button>
</div>
</div>
</div>
</div>
<!-- =========================================================================================
7. ENTERPRISE JAVASCRIPT LOGIC (ROBUST GRADIO INTEGRATION)
========================================================================================= -->
<script>
/**
* System Configuration & Global Variables
*/
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'
};
// Strict mapping of global application state
window.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
};
// Initialize PDF worker
pdfjsLib.GlobalWorkerOptions.workerSrc = Config.PDF_WORKER;
/**
* Core Utilities
*/
window.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,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
},
copyToClipboard: (btnElement, textToCopy) => {
const textArea = document.createElement("textarea");
textArea.value = textToCopy;
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 {
window.Utils.showToast("Clipboard access denied.");
}
} catch (err) {
window.Utils.showToast("System error copying text.");
}
document.body.removeChild(textArea);
}
};
/**
* Authentication Manager (GAS Integration)
*/
window.AuthManager = {
initUI: () => {
const promptBtn = document.getElementById('loginPromptBtn');
const profileCard = document.getElementById('userProfile');
const guestBadge = document.getElementById('guestBadge');
if (window.AppState.currentUser) {
promptBtn.style.display = 'none';
profileCard.style.display = 'flex';
document.getElementById('uEmail').innerText = window.AppState.currentUser;
document.getElementById('uAvatar').innerText = window.AppState.currentUser.charAt(0).toUpperCase();
if(guestBadge) guestBadge.style.display = 'none';
} else {
promptBtn.style.display = 'flex';
profileCard.style.display = 'none';
if(guestBadge) {
guestBadge.style.display = 'inline-flex';
document.getElementById('guestCountDisplay').innerText = window.AppState.guestCount;
}
}
},
openModal: () => document.getElementById('secureAuthModal').style.display = 'flex',
closeModal: () => document.getElementById('secureAuthModal').style.display = 'none',
switchTab: (tabName) => {
document.querySelectorAll('.auth-tab-item').forEach(el => el.classList.remove('active'));
document.getElementById(`btn-tab-${tabName}`).classList.add('active');
document.getElementById('auth-flow-login').style.display = tabName === 'login' ? 'block' : 'none';
document.getElementById('auth-flow-register').style.display = tabName === 'register' ? 'block' : 'none';
},
switchPhase: (currentId, nextId) => {
document.getElementById(currentId).classList.remove('active');
document.getElementById(nextId).classList.add('active');
},
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 window.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 window.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 window.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 = 'Establishing Connection...';
try {
const response = await fetch(Config.GAS_URL, { method: 'POST', body: JSON.stringify(payload) });
const result = await response.json();
if (result.status === 'success') {
window.Utils.showToast(result.message);
if (actionType === 'register_send_otp') window.AuthManager.switchPhase('auth-reg-phase-1', 'auth-reg-phase-2');
else if (actionType === 'login_send_otp') window.AuthManager.switchPhase('auth-log-phase-1', 'auth-log-phase-2');
else if (actionType === 'register_verify' || actionType === 'login_verify') {
window.AppState.currentUser = payload.email;
localStorage.setItem('arjun_user', window.AppState.currentUser);
window.AuthManager.closeModal();
window.AuthManager.initUI();
window.ChatEngine.syncHistoryFromCloud();
}
} else {
window.Utils.showToast(result.message);
}
} catch (error) {
window.Utils.showToast("Encrypted gateway error. Check network.");
}
triggerBtn.disabled = false;
triggerBtn.innerHTML = originalText;
},
logout: () => {
localStorage.removeItem('arjun_user');
location.reload();
}
};
/**
* UI Layout Management
*/
window.UIManager = {
toggleSidebar: () => {
document.getElementById('sidebar').classList.toggle('active');
},
checkScrollState: () => {
const msgArea = document.getElementById('msgs');
const isAtBottom = Math.abs((msgArea.scrollHeight - msgArea.scrollTop) - msgArea.clientHeight) < 80;
window.AppState.isUserScrolling = !isAtBottom;
const scrollBtn = document.getElementById('scrollTriggerBtn');
if (window.AppState.isUserScrolling) scrollBtn.classList.add('visible');
else scrollBtn.classList.remove('visible');
},
forceScrollDown: () => {
const msgArea = document.getElementById('msgs');
msgArea.scrollTo({ top: msgArea.scrollHeight, behavior: 'smooth' });
window.AppState.isUserScrolling = false;
document.getElementById('scrollTriggerBtn').classList.remove('visible');
},
autoScroll: () => {
if (!window.AppState.isUserScrolling) {
const msgArea = document.getElementById('msgs');
msgArea.scrollTop = msgArea.scrollHeight;
}
},
autoGrowTextArea: (element) => {
element.style.height = 'auto';
element.style.height = Math.min(element.scrollHeight, 200) + 'px';
},
toggleAttachMenu: () => {
document.getElementById('attachDropdownMenu').classList.toggle('visible');
}
};
// Attach global listener to close menus
document.addEventListener('click', (event) => {
const wrapper = document.querySelector('.attachment-module');
if (wrapper && !wrapper.contains(event.target)) {
const menu = document.getElementById('attachDropdownMenu');
if(menu) menu.classList.remove('visible');
}
});
/**
* Voice & Speech Engine (Includes Gradio Edge-TTS)
*/
window.VoiceEngine = {
recognition: null,
currentLanguage: 'en-IN',
currentAudioNode: null,
init: () => {
const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SR) return;
window.VoiceEngine.recognition = new SR();
window.VoiceEngine.recognition.continuous = false;
window.VoiceEngine.recognition.interimResults = false;
window.VoiceEngine.recognition.lang = window.VoiceEngine.currentLanguage;
window.VoiceEngine.recognition.onstart = () => {
document.getElementById('masterVoiceBtn').classList.add('active-listening');
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveMicBtn').classList.add('is-recording');
document.getElementById('liveStatusText').innerText = "Analyzing Input...";
document.getElementById('liveOrb').style.transform = "scale(1.25)";
}
};
window.VoiceEngine.recognition.onresult = (event) => {
let transcript = '';
for (let i = event.resultIndex; i < event.results.length; ++i) {
transcript += event.results[i].transcript;
}
transcript = transcript.trim();
if (transcript.length > 0) {
transcript = transcript.charAt(0).toUpperCase() + transcript.slice(1);
if (!/[.!?।]$/.test(transcript)) transcript += '.';
transcript += ' ';
}
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveTranscriptText').innerText = `"${transcript}"`;
document.getElementById('liveStatusText').innerText = "Synthesizing Response...";
document.getElementById('mainChatInput').value = transcript;
window.ChatEngine.initiateDispatch();
} else {
const inputField = document.getElementById('mainChatInput');
inputField.value = (inputField.value + ' ' + transcript).trim();
window.UIManager.autoGrowTextArea(inputField);
}
};
window.VoiceEngine.recognition.onend = () => {
document.getElementById('masterVoiceBtn').classList.remove('active-listening');
if (window.AppState.isLiveModeEngaged && !window.AppState.isProcessing) {
document.getElementById('liveMicBtn').classList.remove('is-recording');
document.getElementById('liveStatusText').innerText = "Tap mic to interact";
document.getElementById('liveOrb').style.transform = "scale(1)";
}
};
window.VoiceEngine.recognition.onerror = (event) => {
window.Utils.showToast("Voice module error.");
document.getElementById('masterVoiceBtn').classList.remove('active-listening');
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveMicBtn').classList.remove('is-recording');
document.getElementById('liveStatusText').innerText = "Audio Failure. Retry.";
}
};
},
switchLanguage: () => {
const btn = document.getElementById('smartLangToggle');
const badge = document.getElementById('langDisplayBadge');
if (window.VoiceEngine.currentLanguage === 'en-IN') {
window.VoiceEngine.currentLanguage = 'hi-IN';
badge.innerText = 'HI';
btn.classList.add('hindi-active');
window.Utils.showToast("Acoustic Protocol: Pure Hindi / Hinglish");
} else {
window.VoiceEngine.currentLanguage = 'en-IN';
badge.innerText = 'EN';
btn.classList.remove('hindi-active');
window.Utils.showToast("Acoustic Protocol: English / Hybrid");
}
if (window.VoiceEngine.recognition) {
window.VoiceEngine.recognition.lang = window.VoiceEngine.currentLanguage;
}
},
toggleDictation: () => {
if (!window.VoiceEngine.recognition) return window.Utils.showToast("Hardware dictation unsupported.");
try { window.VoiceEngine.recognition.start(); } catch (e) { window.VoiceEngine.recognition.stop(); }
},
toggleLive: () => {
if (!window.VoiceEngine.recognition) return window.Utils.showToast("Hardware dictation unsupported.");
try { window.VoiceEngine.recognition.start(); } catch (e) { window.VoiceEngine.recognition.stop(); }
},
// Gradio TTS Module Integration
executeTTS: async (text) => {
return new Promise(async (resolve) => {
const cleanText = text.replace(/[*_~`#]/g, '').replace(/<[^>]*>?/gm, '').trim();
if (!cleanText) return resolve();
if (window.VoiceEngine.currentAudioNode) {
window.VoiceEngine.currentAudioNode.pause();
window.VoiceEngine.currentAudioNode = null;
}
window.Utils.showToast("🔊 Connecting to Neural Voice Matrix (Gradio)...");
try {
// Dynamic import of Gradio Client to avoid broken native module support
const { Client } = await import('https://cdn.jsdelivr.net/npm/@gradio/client/+esm');
const client = await Client.connect("Vedika66/Edge-TTS");
const assignedVoice = window.VoiceEngine.currentLanguage === 'hi-IN'
? "प्रभात (भारी और प्राकृतिक आवाज़ - हिंग्लिश के लिए)"
: "Christopher (Professional and Natural - US English)";
const result = await client.predict("/smart_hybrid_tts", {
text: cleanText,
voice_type: assignedVoice,
});
if (result && result.data && result.data.length > 0) {
const audioResponseData = result.data;
const targetAudioUrl = typeof audioResponseData === 'object' && audioResponseData !== null
? audioResponseData.url : audioResponseData;
const playbackAudio = new Audio(targetAudioUrl);
window.VoiceEngine.currentAudioNode = playbackAudio;
playbackAudio.onplay = () => {
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveStatusText').innerText = "Arjun Transmitting...";
} else {
window.Utils.showToast("🔊 Neural audio playback active...");
}
};
playbackAudio.onended = () => {
window.VoiceEngine.currentAudioNode = null;
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveStatusText').innerText = "Tap mic to respond";
}
resolve();
};
playbackAudio.onerror = () => {
window.Utils.showToast("Audio playback stream encountered an anomaly.");
resolve();
};
await playbackAudio.play();
} else {
throw new Error("Invalid Output from Gradio Node.");
}
} catch (error) {
console.error("Gradio Integration Error:", error);
window.Utils.showToast("Neural link failed. Verify Gradio Edge-TTS server.");
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveStatusText').innerText = "Acoustic Module Offline.";
}
resolve();
}
});
}
};
// Initialize voice API if available
window.VoiceEngine.init();
/**
* Live Mode Controller
*/
window.LiveModeController = {
initialize: () => {
window.AppState.isLiveModeEngaged = true;
document.getElementById('liveOverlay').classList.add('active');
if (window.VoiceEngine.recognition) {
setTimeout(() => {
try { window.VoiceEngine.recognition.start(); } catch(e){}
}, 600);
}
},
terminate: () => {
window.AppState.isLiveModeEngaged = false;
document.getElementById('liveOverlay').classList.remove('active');
if (window.VoiceEngine.currentAudioNode) {
window.VoiceEngine.currentAudioNode.pause();
window.VoiceEngine.currentAudioNode = null;
}
if (window.VoiceEngine.recognition) {
try { window.VoiceEngine.recognition.stop(); } catch(e){}
}
}
};
/**
* File & Attachment Processor
*/
window.FileProcessor = {
triggerFileSelector: (type) => {
document.getElementById('attachDropdownMenu').classList.remove('visible');
document.getElementById('sys-inp-' + type).click();
},
processFile: async (inputElement, typeContext) => {
const file = inputElement.files;
if (!file) return;
const fName = file.name.toLowerCase();
const mime = file.type;
if (typeContext === 'image' && !mime.startsWith('image/')) { window.Utils.showToast("Format Rejected."); inputElement.value=''; return; }
if (typeContext === 'video' && !mime.startsWith('video/')) { window.Utils.showToast("Format Rejected."); inputElement.value=''; return; }
if (typeContext === 'audio' && !mime.startsWith('audio/')) { window.Utils.showToast("Format Rejected."); inputElement.value=''; return; }
window.Utils.showToast("Uploading your file, please wait...");
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) => {
window.AppState.pendingAttachment = { type: 'image', data: e.target.result.split(','), name: file.name };
thumbImg.src = e.target.result;
thumbImg.style.display = 'flex';
};
fileReader.readAsDataURL(file);
}
else if (typeContext === 'video' || typeContext === 'audio') {
fileReader.onload = (e) => {
window.AppState.pendingAttachment = { type: typeContext, data: e.target.result.split(','), 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";
}
window.AppState.pendingAttachment = { type: 'text', data: extractedText.trim() || "No readable text found.", name: file.name };
window.Utils.showToast("Your PDF is ready!");
} catch (e) {
window.Utils.showToast("PDF parsing encountered an error.");
window.FileProcessor.discardFile();
}
};
fileReader.readAsArrayBuffer(file);
}
else if (fName.endsWith('.docx') || fName.endsWith('.doc')) {
fileReader.onload = async function() {
try {
const buffer = this.result;
const resultData = await mammoth.extractRawText({ arrayBuffer: buffer });
window.AppState.pendingAttachment = { type: 'text', data: resultData.value.trim() || "No readable text found.", name: file.name };
window.Utils.showToast("Your Word document is ready!");
} catch(e) {
window.Utils.showToast("Document parsing encountered an error.");
window.FileProcessor.discardFile();
}
};
fileReader.readAsArrayBuffer(file);
}
else {
fileReader.onload = (e) => {
window.AppState.pendingAttachment = { type: 'text', data: e.target.result, name: file.name };
window.Utils.showToast("Your file is ready!");
};
fileReader.readAsText(file);
}
}
inputElement.value = '';
},
discardFile: () => {
window.AppState.pendingAttachment = null;
document.getElementById('filePreviewBar').classList.remove('visible');
}
};
/**
* Workspace Code Engine
*/
window.WorkspaceEngine = {
launch: (codeBlockId) => {
window.AppState.currentWorkspaceId = codeBlockId;
const codeData = window.AppState.generatedCodeBlocks[codeBlockId];
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');
}
},
closePanel: () => {
document.getElementById('workspacePanel').classList.remove('expanded');
},
executeCopy: (btnElement) => {
if (window.AppState.currentWorkspaceId !== null) {
const srcCode = window.AppState.generatedCodeBlocks[window.AppState.currentWorkspaceId].code;
window.Utils.copyToClipboard(btnElement, srcCode);
}
}
};
/**
* Marked.js Custom Renderer & Configuration
*/
const MD_Renderer = new marked.Renderer();
MD_Renderer.code = function(token) {
const rawCode = typeof token === 'string' ? token : (token.text || '');
// Critical Syntax Fix for proper marked.js API integration avoiding crash
const langClass = typeof token === 'string'
? (arguments.length > 1 ? arguments : '')
: (token.lang || '');
// STREAMING STATE GUARD
if (window.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}">${window.Utils.escapeHTML(rawCode)}</code></pre>
</div>`;
}
// MOUNT BUTTON ONLY WHEN COMPLETED
const internalId = window.AppState.generatedCodeBlocks.length;
window.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" onclick="WorkspaceEngine.launch(${internalId})">Open Workspace</button>
</div>`;
};
marked.use({ renderer: MD_Renderer });
/**
* Core Chat Processing Engine
*/
window.ChatEngine = {
handleKeyboard: (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
window.ChatEngine.initiateDispatch();
}
},
sendExample: (queryText) => {
document.getElementById('mainChatInput').value = queryText;
window.ChatEngine.initiateDispatch();
},
clearMemory: async () => {
if (window.AppState.currentUser) {
window.Utils.showToast("Purging neural link memory...");
await fetch(Config.GAS_URL, {
method: 'POST',
body: JSON.stringify({ action: "delete_history", email: window.AppState.currentUser })
});
}
location.reload();
},
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(--text-tertiary); font-size:18px;">Decrypting Historic Archives...</div>';
try {
const response = await fetch(Config.GAS_URL, {
method: 'POST',
body: JSON.stringify({ action: "get_history", email: window.AppState.currentUser })
});
const resData = await response.json();
messageZone.innerHTML = '';
if (resData.status === 'success' && resData.historyJSON !== "[]") {
window.AppState.history = JSON.parse(resData.historyJSON);
window.AppState.history.forEach(msgObj => {
if (msgObj.role === 'user') {
window.ChatEngine.renderUserMessage(msgObj.content, msgObj.badge, msgObj.previewHTML);
} else {
window.AppState.isStreamingActive = false;
window.ChatEngine.renderBotMessage(msgObj.content, true);
}
});
setTimeout(window.UIManager.forceScrollDown, 150);
} else {
document.getElementById('welcomeState').style.display = 'flex';
}
} catch (err) {
messageZone.innerHTML = '';
document.getElementById('welcomeState').style.display = 'flex';
}
},
saveHistoryToCloud: () => {
if (window.AppState.currentUser) {
fetch(Config.GAS_URL, {
method: 'POST',
body: JSON.stringify({ action: "save_history", email: window.AppState.currentUser, historyJSON: JSON.stringify(window.AppState.history) })
});
}
},
buildPreviewHTML: (attachmentObj) => {
if (!attachmentObj) return '';
if (attachmentObj.type === 'image') {
return `<img src="data:image/jpeg;base64,${attachmentObj.data}" class="chat-in-bubble-img" alt="Attached Image">`;
} else if (attachmentObj.type === 'video') {
return `<div class="chat-file-card"><span class="icon">🎥</span><span class="name">${attachmentObj.name}</span></div>`;
} else if (attachmentObj.type === 'audio') {
return `<div class="chat-file-card"><span class="icon">🎵</span><span class="name">${attachmentObj.name}</span></div>`;
} else {
return `<div class="chat-file-card"><span class="icon">📄</span><span class="name">${attachmentObj.name}</span></div>`;
}
},
renderUserMessage: (textContent, badgeText, previewHTMLString = '') => {
let badgeNode = badgeText ? `<div style="font-size:11px;font-weight:700;color:var(--brand-saffron);margin-bottom:6px;">${window.Utils.escapeHTML(badgeText)}</div>` : '';
const bubbleBox = document.createElement('div');
bubbleBox.className = 'chat-message-row user-msg';
bubbleBox.innerHTML = `
<div class="msg-avatar">U</div>
<div class="msg-content-column">
${badgeNode}
<div class="chat-bubble">
${previewHTMLString}
${window.Utils.escapeHTML(textContent)}
</div>
</div>`;
document.getElementById('msgs').appendChild(bubbleBox);
},
renderBotMessage: (textContent, bypassStreamFormatting = false) => {
const bubbleBox = document.createElement('div');
bubbleBox.className = 'chat-message-row bot-msg';
bubbleBox.innerHTML = `
<div class="msg-avatar"><img src="${Config.LOGO_URL}" alt="AI"></div>
<div class="msg-content-column">
<div class="chat-bubble"></div>
</div>`;
document.getElementById('msgs').appendChild(bubbleBox);
window.ChatEngine.updateBotBubble(bubbleBox, textContent, !bypassStreamFormatting);
return bubbleBox;
},
updateBotBubble: (bubbleDOM, rawMarkup, isCurrentlyStreaming) => {
const contentTarget = bubbleDOM.querySelector('.chat-bubble');
const strippedMarkup = rawMarkup.replace(/<think>([\s\S]*?)(<\/think>|$)/gi, '');
let renderHTML = marked.parse(strippedMarkup.trim());
if (isCurrentlyStreaming) {
renderHTML += `<div class="loading-dots-container"><div class="loading-dot"></div><div class="loading-dot"></div><div class="loading-dot"></div></div>`;
}
contentTarget.innerHTML = renderHTML;
let actionTray = bubbleDOM.querySelector('.bot-actions-row');
if (!isCurrentlyStreaming && !actionTray && strippedMarkup.trim().length > 0) {
const safeRawCopy = strippedMarkup.replace(/"/g, '&quot;').replace(/'/g, "\\'").replace(/\n/g, '\\n').replace(/\r/g, '');
const safeRawTTS = strippedMarkup.replace(/"/g, '&quot;').replace(/'/g, "\\'").replace(/\n/g, ' ');
const actionsHTML = `
<div class="bot-actions-row">
<button class="btn-bot-action" onclick="Utils.copyToClipboard(this, \`${safeRawCopy}\`)">
<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 Logic
</button>
<button class="btn-bot-action action-tts" onclick="VoiceEngine.executeTTS(\`${safeRawTTS}\`)">
<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>
Neural Voice
</button>
</div>`;
bubbleDOM.querySelector('.msg-content-column').insertAdjacentHTML('beforeend', actionsHTML);
}
},
initiateDispatch: async () => {
if (window.AppState.isProcessing) return;
const inputField = document.getElementById('mainChatInput');
const rawUserText = inputField.value.trim();
if (!rawUserText && !window.AppState.pendingAttachment) return;
if (!window.AppState.currentUser) {
if (window.AppState.guestCount >= 3) {
window.AuthManager.openModal();
return window.Utils.showToast("Unregistered query limit reached. Secure Login required.");
}
window.AppState.guestCount++;
localStorage.setItem('arjun_guest', window.AppState.guestCount.toString());
document.getElementById('guestCountDisplay').innerText = window.AppState.guestCount;
}
inputField.value = '';
inputField.style.height = 'auto';
document.getElementById('masterSendBtn').disabled = true;
window.AppState.isProcessing = true;
const wState = document.getElementById('welcomeState');
if (wState) wState.style.display = 'none';
let payloadStr = rawUserText;
let payloadAttachments = [];
let visualBadge = null;
let previewHTMLForChat = '';
if (window.AppState.pendingAttachment) {
previewHTMLForChat = window.ChatEngine.buildPreviewHTML(window.AppState.pendingAttachment);
if (window.AppState.pendingAttachment.type === 'text') {
payloadStr = `[Document Analyzed: ${window.AppState.pendingAttachment.name}]\n\n---DATA BEGIN---\n${window.AppState.pendingAttachment.data}\n---DATA END---\n\nUser Prompt: ${rawUserText}`;
visualBadge = '📄 File Appended';
} else {
payloadAttachments.push({
type: window.AppState.pendingAttachment.type,
data: window.AppState.pendingAttachment.data,
name: window.AppState.pendingAttachment.name
});
const icoMap = { 'video': '🎥 ', 'audio': '🎵 ', 'image': '🖼️ ' };
visualBadge = (icoMap[window.AppState.pendingAttachment.type] || '📎 ') + "Media Appended";
}
window.ChatEngine.renderUserMessage(rawUserText || '[Transmitting Media Context]', visualBadge, previewHTMLForChat);
window.AppState.history.push({ role: 'user', content: payloadStr, badge: visualBadge, previewHTML: previewHTMLForChat });
} else {
window.ChatEngine.renderUserMessage(rawUserText, null, '');
window.AppState.history.push({ role: 'user', content: rawUserText });
}
window.FileProcessor.discardFile();
window.ChatEngine.saveHistoryToCloud();
const activeBotBubble = window.ChatEngine.renderBotMessage('', false);
window.UIManager.forceScrollDown();
const cryptographicSeed = Math.floor(Math.random() * 999999999);
let cognitivePrompt = `You are Arjun 2.O, a sophisticated enterprise AI system architected by Abhay Kumar.
LANGUAGE REGULATION: You possess strict bilingual fluency. You MUST analyze the user's language and respond seamlessly in BOTH English and Hindi.
- If the prompt is purely English, output pure English.
- If the prompt contains Hindi (Devanagari or Hinglish), respond in natural Hindi.
- Adapt tone to be highly professional, intelligent, and authoritative.
IMAGE SYNTHESIS OVERRIDE:
When commanded to render, generate, or create an image/photograph, you MUST reply with a precise markdown image node targeting Pollinations AI.
Formula: ![Generating Vision...](https://image.pollinations.ai/prompt/{URL_ENCODED_PROMPT_DETAIL}?width=1024&height=1024&nologo=true&model={MODEL}&seed=${cryptographicSeed})
Available Models: flux, flux-realism, flux-anime, flux-3d.
CRITICAL: The seed parameter is mandatory to bypass cache mechanics. Always render this markdown node.`;
if (window.AppState.isLiveModeEngaged) {
cognitivePrompt += `\n\n[LIVE ACOUSTIC OVERRIDE]: You are currently engaged in a LIVE, REAL-TIME VOCAL INTERFACE. MANDATORY direct answers. Maximum brevity. Eliminate complex markdown, massive code blocks, or extended lists. Replicate human telephonic brevity perfectly.`;
}
// SECURE PAYLOAD PREP - Fixes HuggingFace crash by strictly formatting history array
const secureHistory = window.AppState.history.slice(0, -1).map(h => ({ role: h.role, content: h.content }));
const transmissionPayload = {
message: payloadStr,
attachments: payloadAttachments,
system_prompt: cognitivePrompt,
history: secureHistory,
max_tokens: window.AppState.isLiveModeEngaged ? 150 : 4096,
temperature: 0.75
};
try {
const fetchOp = await fetch('/api/chat', {
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 = "";
window.AppState.isStreamingActive = true;
while (true) {
const { done, value } = await networkReader.read();
if (done) break;
const decodedChunk = textDecoder.decode(value, { stream: true });
const fragmentedLines = decodedChunk.split('\n');
for (let line of fragmentedLines) {
if (line.startsWith('data: ')) {
const parseableStr = line.substring(6);
if (parseableStr.trim() === '[DONE]') continue;
try {
const jsonSegment = JSON.parse(parseableStr);
// CRITICAL BUG FIX: Correct array targeting (choices) prevents silent crash during stream iteration
if (jsonSegment.choices && jsonSegment.choices.length > 0 && jsonSegment.choices.delta && jsonSegment.choices.delta.content) {
responseBuffer += jsonSegment.choices.delta.content;
window.ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, true);
window.UIManager.autoScroll();
}
} catch (e) {
// Silently catch fragmented packets
}
}
}
}
window.AppState.isStreamingActive = false;
window.ChatEngine.updateBotBubble(activeBotBubble, responseBuffer, false);
window.AppState.history.push({ role: 'bot', content: responseBuffer });
window.ChatEngine.saveHistoryToCloud();
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveStatusText').innerText = "Synthesizing Audio...";
await window.VoiceEngine.executeTTS(responseBuffer);
}
} catch(error) {
console.error(error);
window.AppState.isStreamingActive = false;
window.ChatEngine.updateBotBubble(activeBotBubble, `**System Error:** Communication array offline. Verification needed.`, false);
if (window.AppState.isLiveModeEngaged) {
document.getElementById('liveStatusText').innerText = "Neural Link Severed.";
}
}
window.AppState.isProcessing = false;
document.getElementById('masterSendBtn').disabled = false;
window.UIManager.autoScroll();
}
};
// Bootstrap the System
window.ApplicationCore = {
launchSystem: startArjunApp
};
// Start initialization process automatically upon module mount completion
function startArjunApp() {
const overlay = document.getElementById('welcomeOverlay');
if(overlay) {
overlay.classList.add('hidden');
localStorage.setItem('arjun_welcome_seen', 'true');
setTimeout(() => { overlay.style.display = 'none'; }, 400);
}
}
// Final Document Ready Catch to ensure bindings
document.addEventListener('DOMContentLoaded', () => {
window.AuthManager.initUI();
if(window.AppState.currentUser) {
window.ChatEngine.syncHistoryFromCloud();
} else {
const guestBadge = document.getElementById('guestBadge');
if(guestBadge) guestBadge.style.display = 'inline-flex';
const guestDisplay = document.getElementById('guestCountDisplay');
if(guestDisplay) guestDisplay.innerText = window.AppState.guestCount;
}
});
</script>
</body>
</html>