ada-web

Ada AI is a specialized coding...
Log | Files | Refs | README | LICENSE

index.html (105788B)


      1 <!DOCTYPE html>
      2 <html lang="en" class="dark">
      3 <head>
      4     <meta charset="UTF-8">
      5     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
      6     <title>Ada AI</title>
      7     <link rel="icon" type="image/png" href="logo.png">
      8     
      9     <!-- Tailwind CSS -->
     10     <script src="https://cdn.tailwindcss.com"></script>
     11     <script>
     12         tailwind.config = {
     13             darkMode: 'class',
     14             theme: {
     15                 extend: {
     16                     colors: {
     17                         gemini: {
     18                             bg: '#131314',        // Deepest charcoal
     19                             surface: '#1E1F20',   // Sidebar/Panels
     20                             surfaceHover: '#28292A',
     21                             accent: '#444746',    // Borders/Icons
     22                             text: '#E3E3E3',      // Primary text
     23                             textSecondary: '#C4C7C5',
     24                             blue: '#A8C7FA',      // Google Blue
     25                             purple: '#D0BCFF'     // Google Purple
     26                         }
     27                     },
     28                     fontFamily: {
     29                         sans: ['Inter', 'sans-serif'],
     30                         mono: ['JetBrains Mono', 'monospace'],
     31                     },
     32                     animation: {
     33                         'fade-in': 'fadeIn 0.4s ease-out forwards',
     34                         'slide-up': 'slideUp 0.5s cubic-bezier(0.2, 0.0, 0, 1.0) forwards',
     35                         'spin-slow-entry': 'spinSlowEntry 1.2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards',
     36                         'shimmer': 'shimmer 2s linear infinite',
     37                     },
     38                     keyframes: {
     39                         fadeIn: {
     40                             '0%': { opacity: '0' },
     41                             '100%': { opacity: '1' },
     42                         },
     43                         slideUp: {
     44                             '0%': { opacity: '0', transform: 'translateY(20px)' },
     45                             '100%': { opacity: '1', transform: 'translateY(0)' },
     46                         },
     47                         spinSlowEntry: {
     48                             '0%': { opacity: '0', transform: 'rotate(-180deg) scale(0.5)' },
     49                             '100%': { opacity: '1', transform: 'rotate(0deg) scale(1)' }
     50                         },
     51                         shimmer: {
     52                             '0%': { backgroundPosition: '-1000px 0' },
     53                             '100%': { backgroundPosition: '1000px 0' }
     54                         }
     55                     }
     56                 }
     57             }
     58         }
     59     </script>
     60 
     61     <!-- Google Fonts -->
     62     <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
     63     
     64     <!-- Icons -->
     65     <script src="https://unpkg.com/lucide@latest"></script>
     66     <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
     67 
     68     <!-- CodeMirror (Editor) -->
     69     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css">
     70     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css">
     71     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
     72     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/javascript/javascript.min.js"></script>
     73     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/python/python.min.js"></script>
     74     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/xml/xml.min.js"></script>
     75     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/css/css.min.js"></script>
     76 
     77     <!-- Firebase SDKs -->
     78     <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-app-compat.js"></script>
     79     <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-auth-compat.js"></script>
     80     <script src="https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore-compat.js"></script>
     81 
     82     <style>
     83         body {
     84             background-color: #131314;
     85             color: #E3E3E3;
     86             font-family: 'Inter', sans-serif;
     87             overflow: hidden;
     88             -webkit-font-smoothing: antialiased;
     89         }
     90 
     91         /* Custom Scrollbar */
     92         ::-webkit-scrollbar { width: 6px; height: 6px; }
     93         ::-webkit-scrollbar-track { background: transparent; }
     94         ::-webkit-scrollbar-thumb { background: #444746; border-radius: 3px; }
     95         ::-webkit-scrollbar-thumb:hover { background: #5E5E5E; }
     96 
     97         /* Prose / Markdown Styles */
     98         .prose p { margin-bottom: 0.8rem; line-height: 1.6; color: #E3E3E3; font-weight: 300; }
     99         .prose strong { color: #fff; font-weight: 600; }
    100         .prose ul { list-style-type: disc; padding-left: 1.5rem; margin-bottom: 1rem; }
    101         .prose ol { list-style-type: decimal; padding-left: 1.5rem; margin-bottom: 1rem; }
    102         .prose code {
    103             font-family: 'JetBrains Mono', monospace;
    104             background: #28292A;
    105             padding: 2px 6px;
    106             border-radius: 4px;
    107             color: #A8C7FA;
    108             font-size: 0.85em;
    109         }
    110         .prose pre { display: none; } /* Hidden in chat, shown in Artifact Panel */
    111         .prose h1, .prose h2, .prose h3 { margin-top: 1.5rem; margin-bottom: 0.5rem; font-weight: 500; color: white; }
    112         .prose a { color: #A8C7FA; text-decoration: none; }
    113         .prose a:hover { text-decoration: underline; }
    114 
    115         /* Message Bubbles */
    116         .msg-user {
    117             background-color: #28292A;
    118             color: #E3E3E3;
    119             border-radius: 20px;
    120             padding: 12px 20px;
    121             max-width: 80%;
    122             font-weight: 400;
    123         }
    124         .msg-ai {
    125             background: transparent;
    126             color: #E3E3E3;
    127             padding: 0;
    128             max-width: 100%;
    129         }
    130 
    131         /* Code Block Card in Chat */
    132         .code-card {
    133             background: #1E1F20;
    134             border: 1px solid #444746;
    135             border-radius: 12px;
    136             overflow: hidden;
    137             margin: 1rem 0;
    138             transition: all 0.2s;
    139             cursor: pointer;
    140             position: relative;
    141         }
    142         .code-card:hover { 
    143             border-color: #A8C7FA; 
    144             transform: translateY(-1px);
    145         }
    146 
    147         /* CodeMirror Customization */
    148         .CodeMirror {
    149             height: 100% !important;
    150             font-family: 'JetBrains Mono', monospace;
    151             font-size: 14px;
    152             background-color: #1e1e1e !important;
    153         }
    154         .cm-s-dracula.CodeMirror {
    155             background-color: #1e1e1e !important;
    156         }
    157 
    158         /* Typing Indicator */
    159         .typing-dot {
    160             width: 6px; height: 6px;
    161             background: #E3E3E3;
    162             border-radius: 50%;
    163             animation: bounce 1.4s infinite ease-in-out both;
    164         }
    165         .typing-dot:nth-child(1) { animation-delay: -0.32s; }
    166         .typing-dot:nth-child(2) { animation-delay: -0.16s; }
    167         @keyframes bounce { 0%, 80%, 100% { transform: scale(0); } 40% { transform: scale(1); } }
    168 
    169         /* Mobile Height Fix */
    170         .mobile-height { height: 100vh; height: calc(var(--vh, 1vh) * 100); }
    171 
    172         /* Hide Scrollbar for Inputs */
    173         .no-scrollbar::-webkit-scrollbar { display: none; }
    174         .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
    175 
    176         /* Drawer Transitions */
    177         .drawer { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); }
    178         
    179         /* Custom Ada Icon Animation */
    180         .ada-icon path { transform-origin: center; }
    181 
    182         /* Shimmer Effect for Skeletons */
    183         .skeleton-shimmer {
    184             background: #1E1F20;
    185             background-image: linear-gradient(to right, #1E1F20 0%, #28292A 20%, #1E1F20 40%, #1E1F20 100%);
    186             background-repeat: no-repeat;
    187             background-size: 1000px 100%;
    188             animation: shimmer 1.5s infinite linear forwards;
    189         }
    190 
    191         /* Context Menu */
    192         .context-menu {
    193             position: fixed; /* Changed from absolute to fixed for better mobile handling */
    194             background: #28292A;
    195             border: 1px solid #444746;
    196             border-radius: 12px; /* Slightly more rounded */
    197             padding: 4px;
    198             z-index: 9999;
    199             box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
    200             min-width: 180px;
    201             animation: menuFadeIn 0.15s ease-out;
    202         }
    203         @keyframes menuFadeIn {
    204             from { opacity: 0; transform: scale(0.95); }
    205             to { opacity: 1; transform: scale(1); }
    206         }
    207         .context-menu-item {
    208             display: flex;
    209             align-items: center;
    210             gap: 12px;
    211             padding: 12px 16px; /* Larger tap targets for mobile */
    212             cursor: pointer;
    213             border-radius: 8px;
    214             color: #E3E3E3;
    215             font-size: 14px;
    216             transition: background 0.2s;
    217         }
    218         .context-menu-item:hover {
    219             background: #3C4043;
    220         }
    221         .context-menu-item.danger { color: #ff8b8b; }
    222         .context-menu-item.danger:hover { background: rgba(255, 139, 139, 0.1); }
    223 
    224         /* Custom Switch (From Uiverse.io by Galahhad) */
    225         .switch {
    226             /* switch */
    227             --switch-width: 46px;
    228             --switch-height: 24px;
    229             --switch-bg: rgb(68, 71, 70);
    230             --switch-checked-bg: #A8C7FA;
    231             --switch-offset: calc((var(--switch-height) - var(--circle-diameter)) / 2);
    232             --switch-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
    233             /* circle */
    234             --circle-diameter: 18px;
    235             --circle-bg: #fff;
    236             --circle-shadow: 1px 1px 2px rgba(146, 146, 146, 0.45);
    237             --circle-checked-shadow: -1px 1px 2px rgba(163, 163, 163, 0.45);
    238             --circle-transition: var(--switch-transition);
    239             /* icon */
    240             --icon-transition: all .2s cubic-bezier(0.27, 0.2, 0.25, 1.51);
    241             --icon-cross-color: var(--switch-bg);
    242             --icon-cross-size: 6px;
    243             --icon-checkmark-color: var(--switch-checked-bg);
    244             --icon-checkmark-size: 10px;
    245             /* effect line */
    246             --effect-width: calc(var(--circle-diameter) / 2);
    247             --effect-height: calc(var(--effect-width) / 2 - 1px);
    248             --effect-bg: var(--circle-bg);
    249             --effect-border-radius: 1px;
    250             --effect-transition: all .2s ease-in-out;
    251             
    252             display: inline-block;
    253             position: relative;
    254         }
    255 
    256         .switch input { display: none; }
    257 
    258         .switch svg {
    259             -webkit-transition: var(--icon-transition);
    260             -o-transition: var(--icon-transition);
    261             transition: var(--icon-transition);
    262             position: absolute;
    263             height: auto;
    264         }
    265 
    266         .switch .checkmark {
    267             width: var(--icon-checkmark-size);
    268             color: var(--icon-checkmark-color);
    269             -webkit-transform: scale(0);
    270             -ms-transform: scale(0);
    271             transform: scale(0);
    272         }
    273 
    274         .switch .cross {
    275             width: var(--icon-cross-size);
    276             color: var(--icon-cross-color);
    277         }
    278 
    279         .slider {
    280             -webkit-box-sizing: border-box;
    281             box-sizing: border-box;
    282             width: var(--switch-width);
    283             height: var(--switch-height);
    284             background: var(--switch-bg);
    285             border-radius: 999px;
    286             display: -webkit-box;
    287             display: -ms-flexbox;
    288             display: flex;
    289             -webkit-box-align: center;
    290             -ms-flex-align: center;
    291             align-items: center;
    292             position: relative;
    293             -webkit-transition: var(--switch-transition);
    294             -o-transition: var(--switch-transition);
    295             transition: var(--switch-transition);
    296             cursor: pointer;
    297         }
    298 
    299         .circle {
    300             width: var(--circle-diameter);
    301             height: var(--circle-diameter);
    302             background: var(--circle-bg);
    303             border-radius: inherit;
    304             -webkit-box-shadow: var(--circle-shadow);
    305             box-shadow: var(--circle-shadow);
    306             display: -webkit-box;
    307             display: -ms-flexbox;
    308             display: flex;
    309             -webkit-box-align: center;
    310             -ms-flex-align: center;
    311             align-items: center;
    312             -webkit-box-pack: center;
    313             -ms-flex-pack: center;
    314             justify-content: center;
    315             -webkit-transition: var(--circle-transition);
    316             -o-transition: var(--circle-transition);
    317             transition: var(--circle-transition);
    318             z-index: 1;
    319             position: absolute;
    320             left: var(--switch-offset);
    321         }
    322 
    323         .slider::before {
    324             content: "";
    325             position: absolute;
    326             width: var(--effect-width);
    327             height: var(--effect-height);
    328             left: calc(var(--switch-offset) + (var(--effect-width) / 2));
    329             background: var(--effect-bg);
    330             border-radius: var(--effect-border-radius);
    331             -webkit-transition: var(--effect-transition);
    332             -o-transition: var(--effect-transition);
    333             transition: var(--effect-transition);
    334         }
    335 
    336         .switch input:checked+.slider {
    337             background: var(--switch-checked-bg);
    338         }
    339 
    340         .switch input:checked+.slider .checkmark {
    341             -webkit-transform: scale(1);
    342             -ms-transform: scale(1);
    343             transform: scale(1);
    344         }
    345 
    346         .switch input:checked+.slider .cross {
    347             -webkit-transform: scale(0);
    348             -ms-transform: scale(0);
    349             transform: scale(0);
    350         }
    351 
    352         .switch input:checked+.slider::before {
    353             left: calc(100% - var(--effect-width) - (var(--effect-width) / 2) - var(--switch-offset));
    354         }
    355 
    356         .switch input:checked+.slider .circle {
    357             left: calc(100% - var(--circle-diameter) - var(--switch-offset));
    358             -webkit-box-shadow: var(--circle-checked-shadow);
    359             box-shadow: var(--circle-checked-shadow);
    360         }
    361         
    362         /* Command Palette */
    363         #command-palette {
    364             transition: opacity 0.15s ease-out;
    365         }
    366         .cmd-item {
    367             display: flex;
    368             align-items: center;
    369             justify-content: space-between;
    370             padding: 10px 16px;
    371             cursor: pointer;
    372             border-radius: 8px;
    373             color: #E3E3E3;
    374         }
    375         .cmd-item:hover, .cmd-item.selected {
    376             background: #28292A;
    377         }
    378         .cmd-shortcut {
    379             font-size: 10px;
    380             background: #3C4043;
    381             padding: 2px 6px;
    382             border-radius: 4px;
    383             color: #C4C7C5;
    384             font-family: sans-serif;
    385         }
    386     </style>
    387 </head>
    388 <body class="mobile-height flex text-sm selection:bg-gemini-blue selection:text-black bg-gemini-bg">
    389 
    390     <!-- SVG Definitions -->
    391     <svg style="display: none;">
    392         <symbol id="icon-ada" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
    393             <defs>
    394                 <linearGradient id="ada-gradient" x1="0" y1="0" x2="24" y2="24" gradientUnits="userSpaceOnUse">
    395                     <stop offset="0%" stop-color="#4facfe" />
    396                     <stop offset="50%" stop-color="#00f2fe" />
    397                     <stop offset="100%" stop-color="#a8c7fa" />
    398                 </linearGradient>
    399             </defs>
    400             <path d="M12 2L14.4 9.6L22 12L14.4 14.4L12 22L9.6 14.4L2 12L9.6 9.6L12 2Z" fill="url(#ada-gradient)" />
    401             <path d="M12 6L13.2 10.8L18 12L13.2 13.2L12 18L10.8 13.2L6 12L10.8 10.8L12 6Z" fill="white" fill-opacity="0.3" />
    402         </symbol>
    403     </svg>
    404 
    405     <!-- Full Screen Loading/Verifying Overlay -->
    406     <div id="loading-overlay" class="fixed inset-0 z-[200] flex flex-col items-center justify-center bg-[#131314] transition-opacity duration-500">
    407         <div class="w-16 h-16 mb-4 relative">
    408             <div class="absolute inset-0 bg-blue-500/20 blur-xl rounded-full"></div>
    409             <svg class="w-full h-full animate-spin-slow-entry"><use href="#icon-ada"></use></svg>
    410         </div>
    411         <p class="text-gemini-textSecondary text-sm font-medium animate-pulse">Verifying Identity...</p>
    412     </div>
    413 
    414     <!-- Command Palette -->
    415     <div id="command-palette" class="fixed inset-0 z-[150] bg-black/50 backdrop-blur-sm hidden flex items-start justify-center pt-24 opacity-0 pointer-events-none">
    416         <div class="bg-gemini-surface w-full max-w-lg rounded-xl shadow-2xl border border-gemini-surfaceHover overflow-hidden flex flex-col max-h-[60vh]">
    417             <div class="p-4 border-b border-gemini-surfaceHover flex items-center gap-3">
    418                 <i data-lucide="search" class="w-5 h-5 text-gemini-textSecondary"></i>
    419                 <input type="text" id="cmd-input" class="bg-transparent border-none outline-none text-white w-full placeholder-gemini-textSecondary/50" placeholder="Type a command...">
    420                 <span class="text-xs text-gemini-textSecondary border border-gemini-surfaceHover px-1.5 py-0.5 rounded">ESC</span>
    421             </div>
    422             <div id="cmd-list" class="p-2 overflow-y-auto">
    423                 <!-- Commands injected via JS -->
    424             </div>
    425         </div>
    426     </div>
    427 
    428     <!-- Confirm Dialog -->
    429     <div id="confirm-modal" class="fixed inset-0 z-[210] flex items-center justify-center bg-black/70 backdrop-blur-sm hidden opacity-0 transition-opacity">
    430         <div class="bg-gemini-surface p-6 rounded-2xl w-full max-w-sm border border-gemini-surfaceHover transform scale-95 transition-transform" id="confirm-modal-content">
    431             <h3 class="text-lg font-semibold text-white mb-2" id="confirm-title">Confirm</h3>
    432             <p class="text-gemini-textSecondary text-sm mb-4" id="confirm-message">Are you sure?</p>
    433             
    434             <div id="confirm-input-container" class="hidden mb-4">
    435                 <label class="block text-xs text-gemini-textSecondary mb-1">Type <span class="font-mono text-white select-all" id="confirm-match-text"></span> to confirm:</label>
    436                 <input type="text" id="confirm-input" class="w-full bg-[#131314] border border-gemini-surfaceHover rounded-lg p-2 text-white text-sm focus:outline-none focus:border-gemini-blue" placeholder="">
    437             </div>
    438 
    439             <div class="flex justify-end gap-3">
    440                 <button onclick="closeConfirmModal()" class="px-4 py-2 rounded-lg text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover transition-colors">Cancel</button>
    441                 <button id="confirm-action-btn" class="px-4 py-2 rounded-lg bg-red-500/10 text-red-400 hover:bg-red-500/20 transition-colors font-medium">Confirm</button>
    442             </div>
    443         </div>
    444     </div>
    445 
    446     <!-- Toast Notification (Custom Popups) -->
    447     <div id="toast" class="fixed bottom-24 md:bottom-10 left-1/2 -translate-x-1/2 bg-gemini-surface border border-gemini-surfaceHover text-white px-6 py-3 rounded-full shadow-2xl z-[220] transition-all duration-300 transform translate-y-20 opacity-0 pointer-events-none flex items-center gap-2 max-w-[90vw] w-max">
    448         <i data-lucide="info" class="w-4 h-4 text-gemini-blue flex-shrink-0"></i>
    449         <span id="toast-message" class="text-sm font-medium whitespace-normal text-center">Notification</span>
    450     </div>
    451 
    452     <!-- Auth Modal (Updated for Email/Pass + Verification) -->
    453     <div id="auth-modal" class="fixed inset-0 z-[100] flex items-center justify-center bg-[#131314] transition-opacity duration-300 hidden opacity-0 pointer-events-none">
    454         <div class="w-full max-w-md p-8 text-center bg-[#131314] rounded-2xl md:bg-[#131314] md:border-none relative max-h-[90vh] overflow-y-auto">
    455             <div class="mx-auto w-20 h-20 mb-6 rounded-full bg-gemini-surface flex items-center justify-center relative overflow-hidden group">
    456                 <div class="absolute inset-0 bg-gradient-to-tr from-blue-500/20 to-purple-500/20 opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
    457                 <svg class="w-10 h-10 animate-spin-slow-entry drop-shadow-lg"><use href="#icon-ada"></use></svg>
    458             </div>
    459             
    460             <h1 id="auth-title" class="text-3xl font-medium text-white mb-2">Welcome to Ada</h1>
    461             <p id="auth-subtitle" class="text-gemini-textSecondary mb-8 text-sm">Sign in to access your workspace.</p>
    462             
    463             <form id="auth-form" onsubmit="handleAuthSubmit(event)" class="space-y-4 text-left">
    464                 <input type="email" id="auth-email" placeholder="Email" autocomplete="email" required class="w-full bg-gemini-surface border border-gemini-surfaceHover rounded-xl p-3 text-white focus:outline-none focus:border-gemini-blue placeholder-gemini-textSecondary">
    465                 
    466                 <div class="relative">
    467                     <input type="password" id="auth-password" placeholder="Password" autocomplete="current-password" required class="w-full bg-gemini-surface border border-gemini-surfaceHover rounded-xl p-3 pr-10 text-white focus:outline-none focus:border-gemini-blue placeholder-gemini-textSecondary">
    468                     <button type="button" onclick="togglePasswordVisibility()" class="absolute right-3 top-1/2 -translate-y-1/2 text-gemini-textSecondary hover:text-white focus:outline-none">
    469                         <i id="password-toggle-icon" data-lucide="eye" class="w-5 h-5"></i>
    470                     </button>
    471                 </div>
    472                 
    473                 <div id="auth-feedback" class="hidden text-center text-sm mt-2"></div>
    474 
    475                 <div id="signin-extras" class="flex justify-end">
    476                     <button type="button" onclick="handleForgotPassword()" class="text-xs text-gemini-textSecondary hover:text-gemini-blue hover:underline">Forgot Password?</button>
    477                 </div>
    478 
    479                 <button type="submit" id="auth-submit-btn" class="w-full bg-gemini-blue text-black font-semibold py-3 rounded-xl hover:bg-white transition-colors">
    480                     Sign In
    481                 </button>
    482             </form>
    483 
    484             <div class="mt-6">
    485                 <button type="button" id="toggle-auth-mode" onclick="toggleAuthMode()" class="text-sm text-gemini-blue hover:underline">
    486                     Don't have an account? Create one
    487                 </button>
    488             </div>
    489 
    490             <div class="relative my-8">
    491                 <div class="absolute inset-0 flex items-center"><div class="w-full border-t border-gemini-surfaceHover"></div></div>
    492                 <span class="relative px-3 bg-[#131314] text-xs text-gemini-textSecondary uppercase tracking-widest">Or</span>
    493             </div>
    494 
    495             <div class="space-y-3">
    496                 <button onclick="signInWithGoogle()" class="w-full bg-white text-[#131314] hover:bg-gray-100 font-medium py-3 px-6 rounded-full flex items-center justify-center gap-3 transition-colors">
    497                     <img src="https://www.google.com/favicon.ico" class="w-5 h-5" alt="G">
    498                     <span>Sign In with Google</span>
    499                 </button>
    500                 <button onclick="signInAsGuest()" class="w-full bg-[#3C4043] text-white hover:bg-[#494c50] font-medium py-3 px-6 rounded-full flex items-center justify-center gap-3 transition-colors">
    501                     <i data-lucide="user" class="w-5 h-5"></i>
    502                     <span>Continue as Guest</span>
    503                 </button>
    504             </div>
    505         </div>
    506     </div>
    507 
    508     <!-- Profile Modal -->
    509     <div id="profile-modal" onclick="toggleProfileModal()" class="fixed inset-0 z-[110] flex items-center justify-center bg-black/60 backdrop-blur-sm transition-opacity duration-300 hidden opacity-0 pointer-events-none">
    510         <div onclick="event.stopPropagation()" class="w-full max-w-sm bg-gemini-surface p-6 rounded-2xl shadow-2xl border border-gemini-surfaceHover transform scale-95 transition-transform duration-300" id="profile-modal-content">
    511             <div class="flex flex-col items-center">
    512                 <div class="w-20 h-20 rounded-full bg-gradient-to-tr from-blue-500 to-purple-500 flex items-center justify-center text-2xl font-bold text-white mb-4 overflow-hidden border-4 border-gemini-surfaceHover relative shadow-lg">
    513                     <img id="profile-avatar" class="w-full h-full object-cover hidden" src="" alt="User">
    514                     <span id="profile-initial">U</span>
    515                 </div>
    516                 <h2 id="profile-name" class="text-xl font-semibold text-white">User Name</h2>
    517                 <p id="profile-email" class="text-sm text-gemini-textSecondary mb-6 break-all text-center">user@example.com</p>
    518                 
    519                 <div class="w-full grid grid-cols-2 gap-3 mb-6">
    520                     <div class="bg-gemini-bg p-3 rounded-xl border border-gemini-surfaceHover text-center">
    521                         <span class="block text-xs text-gemini-textSecondary uppercase tracking-wider mb-1">Status</span>
    522                         <span class="text-sm text-white font-medium">Free</span>
    523                     </div>
    524                     <div class="bg-gemini-bg p-3 rounded-xl border border-gemini-surfaceHover text-center">
    525                         <span class="block text-xs text-gemini-textSecondary uppercase tracking-wider mb-1">Joined</span>
    526                         <span class="text-sm text-white font-medium">Jan '26</span>
    527                     </div>
    528                 </div>
    529 
    530                 <button onclick="confirmSignOut()" class="w-full bg-[#3C4043] hover:bg-[#494c50] text-white py-2.5 rounded-full flex items-center justify-center gap-2 transition-colors font-medium">
    531                     <i data-lucide="log-out" class="w-4 h-4"></i>
    532                     Sign Out
    533                 </button>
    534             </div>
    535         </div>
    536     </div>
    537 
    538     <!-- Settings Modal -->
    539     <div id="settings-modal" onclick="toggleSettingsModal()" class="fixed inset-0 z-[110] flex items-center justify-center bg-black/60 backdrop-blur-sm transition-opacity duration-300 hidden opacity-0 pointer-events-none">
    540         <div onclick="event.stopPropagation()" class="w-full max-w-md bg-gemini-surface p-6 rounded-2xl shadow-2xl border border-gemini-surfaceHover transform scale-95 transition-transform duration-300 max-h-[85vh] overflow-y-auto" id="settings-modal-content">
    541             <div class="flex items-center justify-between mb-6 border-b border-gemini-surfaceHover pb-4">
    542                 <h2 class="text-xl font-semibold text-white">Settings</h2>
    543                 <button onclick="toggleSettingsModal()" class="text-gemini-textSecondary hover:text-white p-1 rounded-full hover:bg-gemini-surfaceHover transition-colors">
    544                     <i data-lucide="x" class="w-5 h-5"></i>
    545                 </button>
    546             </div>
    547             
    548             <div class="space-y-2">
    549                 <!-- Chat Sharing -->
    550                 <div class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center justify-between group">
    551                     <div class="flex items-center gap-3">
    552                         <div class="p-2 bg-purple-500/10 rounded-lg text-purple-400 group-hover:bg-purple-500/20"><i data-lucide="share-2" class="w-4 h-4"></i></div>
    553                         <div>
    554                             <h3 class="text-white text-sm font-medium">Chat Sharing</h3>
    555                             <p class="text-xs text-gemini-textSecondary">Allow public links</p>
    556                         </div>
    557                     </div>
    558                     <!-- Custom Toggle UI -->
    559                     <label class="switch">
    560                         <input type="checkbox" id="share-toggle-checkbox" onchange="toggleShareSetting(this)">
    561                         <div class="slider">
    562                             <div class="circle">
    563                                 <svg class="cross" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 365.696 365.696" y="0" x="0" height="6" width="6" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg">
    564                                     <g>
    565                                         <path data-original="#000000" fill="currentColor" d="M243.188 182.86 356.32 69.726c12.5-12.5 12.5-32.766 0-45.247L341.238 9.398c-12.504-12.503-32.77-12.503-45.25 0L182.86 122.528 69.727 9.374c-12.5-12.5-32.766-12.5-45.247 0L9.375 24.457c-12.5 12.504-12.5 32.77 0 45.25l113.152 113.152L9.398 295.99c-12.503 12.503-12.503 32.769 0 45.25L24.48 356.32c12.5 12.5 32.766 12.5 45.247 0l113.132-113.132L295.99 356.32c12.503 12.5 32.769 12.5 45.25 0l15.081-15.082c12.5-12.504 12.5-32.77 0-45.25zm0 0"></path>
    566                                     </g>
    567                                 </svg>
    568                                 <svg class="checkmark" xml:space="preserve" style="enable-background:new 0 0 512 512" viewBox="0 0 24 24" y="0" x="0" height="10" width="10" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" xmlns="http://www.w3.org/2000/svg">
    569                                     <g>
    570                                         <path class="" data-original="#000000" fill="currentColor" d="M9.707 19.121a.997.997 0 0 1-1.414 0l-5.646-5.647a1.5 1.5 0 0 1 0-2.121l.707-.707a1.5 1.5 0 0 1 2.121 0L9 14.171l9.525-9.525a1.5 1.5 0 0 1 2.121 0l.707.707a1.5 1.5 0 0 1 0 2.121z"></path>
    571                                     </g>
    572                                 </svg>
    573                             </div>
    574                         </div>
    575                     </label>
    576                 </div>
    577 
    578                 <!-- Font Size -->
    579                 <div class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors flex items-center justify-between group">
    580                     <div class="flex items-center gap-3">
    581                         <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="type" class="w-4 h-4"></i></div>
    582                         <div>
    583                             <h3 class="text-white text-sm font-medium">Font Size</h3>
    584                             <p class="text-xs text-gemini-textSecondary">Adjust readability</p>
    585                         </div>
    586                     </div>
    587                     <div class="flex items-center gap-2 bg-gemini-bg p-1 rounded-lg border border-gemini-surfaceHover">
    588                         <button onclick="changeFontSize(-1)" class="p-1 hover:bg-gemini-surfaceHover rounded text-gemini-textSecondary hover:text-white"><i data-lucide="minus" class="w-3 h-3"></i></button>
    589                         <span id="font-size-display" class="text-xs font-mono w-4 text-center">14</span>
    590                         <button onclick="changeFontSize(1)" class="p-1 hover:bg-gemini-surfaceHover rounded text-gemini-textSecondary hover:text-white"><i data-lucide="plus" class="w-3 h-3"></i></button>
    591                     </div>
    592                 </div>
    593 
    594                 <div class="h-px bg-gemini-surfaceHover my-2"></div>
    595 
    596                 <!-- Help & Support -->
    597                 <a href="https://github.com/notamitgamer/ada-web/issues" target="_blank" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    598                     <div class="p-2 bg-green-500/10 rounded-lg text-green-400 group-hover:bg-green-500/20"><i data-lucide="help-circle" class="w-4 h-4"></i></div>
    599                     <div>
    600                         <h3 class="text-white text-sm font-medium">Help & Support</h3>
    601                         <p class="text-xs text-gemini-textSecondary">Report bugs or request features</p>
    602                     </div>
    603                     <i data-lucide="external-link" class="w-4 h-4 text-gemini-textSecondary ml-auto"></i>
    604                 </a>
    605 
    606                 <!-- Contribute -->
    607                 <a href="https://github.com/notamitgamer/ada-web" target="_blank" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    608                     <div class="p-2 bg-orange-500/10 rounded-lg text-orange-400 group-hover:bg-orange-500/20"><i data-lucide="git-branch" class="w-4 h-4"></i></div>
    609                     <div>
    610                         <h3 class="text-white text-sm font-medium">Contribute</h3>
    611                         <p class="text-xs text-gemini-textSecondary">Fork repo & submit PRs</p>
    612                     </div>
    613                     <i data-lucide="external-link" class="w-4 h-4 text-gemini-textSecondary ml-auto"></i>
    614                 </a>
    615 
    616                 <!-- Developer Contact -->
    617                 <a href="mailto:amitdutta4255@gmail.com?subject=Ada%20AI%20Critical%20Support" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    618                     <div class="p-2 bg-red-500/10 rounded-lg text-red-400 group-hover:bg-red-500/20"><i data-lucide="alert-circle" class="w-4 h-4"></i></div>
    619                     <div>
    620                         <h3 class="text-white text-sm font-medium">Critical Support</h3>
    621                         <p class="text-xs text-gemini-textSecondary">Contact developer directly</p>
    622                     </div>
    623                 </a>
    624 
    625                 <!-- General Feedback -->
    626                 <a href="mailto:mail@amit.is-a.dev?subject=Ada%20AI%20Feedback" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    627                     <div class="p-2 bg-yellow-500/10 rounded-lg text-yellow-400 group-hover:bg-yellow-500/20"><i data-lucide="message-square" class="w-4 h-4"></i></div>
    628                     <div>
    629                         <h3 class="text-white text-sm font-medium">Send Feedback</h3>
    630                         <p class="text-xs text-gemini-textSecondary">Suggestions & improvements</p>
    631                     </div>
    632                 </a>
    633 
    634                 <div class="h-px bg-gemini-surfaceHover my-2"></div>
    635 
    636                 <!-- Terms -->
    637                 <a href="/terms.html" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    638                     <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="file-text" class="w-4 h-4"></i></div>
    639                     <div>
    640                         <h3 class="text-white text-sm font-medium">Terms & Conditions</h3>
    641                         <p class="text-xs text-gemini-textSecondary">Usage policies</p>
    642                     </div>
    643                 </a>
    644 		<!-- Docs -->
    645                 <a href="/docs.html" class="p-3 hover:bg-gemini-surfaceHover rounded-xl transition-colors cursor-pointer flex items-center gap-3 group">
    646                     <div class="p-2 bg-gray-500/10 rounded-lg text-gray-400 group-hover:bg-gray-500/20"><i data-lucide="file-text" class="w-4 h-4"></i></div>
    647                     <div>
    648                         <h3 class="text-white text-sm font-medium">Docs</h3>
    649                         <p class="text-xs text-gemini-textSecondary">Service Documentation</p>
    650                     </div>
    651                 </a>
    652 
    653                 <!-- Delete History -->
    654                 <button onclick="confirmClearHistory()" class="w-full p-3 hover:bg-red-500/10 rounded-xl transition-colors cursor-pointer flex items-center gap-3 group text-left">
    655                     <div class="p-2 bg-red-500/10 rounded-lg text-red-400 group-hover:bg-red-500/20"><i data-lucide="trash-2" class="w-4 h-4"></i></div>
    656                     <div>
    657                         <h3 class="text-red-400 text-sm font-medium">Clear Activity</h3>
    658                         <p class="text-xs text-gemini-textSecondary">Remove local session data</p>
    659                     </div>
    660                 </button>
    661 
    662                 <p class="text-center text-xs text-gemini-textSecondary pt-4 font-mono">Ada AI v1.4.0 • <a href="https://github.com/notamitgamer" class="hover:text-white underline">@notamitgamer</a></p>
    663             </div>
    664         </div>
    665     </div>
    666 
    667     <!-- Sidebar (Collapsible Drawer on ALL screens) -->
    668     <aside id="sidebar" class="bg-gemini-surface w-[280px] flex-shrink-0 flex flex-col border-r border-gemini-surfaceHover fixed inset-y-0 left-0 transform -translate-x-full z-[60] drawer shadow-2xl">
    669         <!-- Sidebar Header -->
    670         <div class="h-16 flex items-center justify-between px-4">
    671             <button onclick="toggleSidebar()" class="p-2 text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover rounded-full transition-colors">
    672                 <i data-lucide="menu" class="w-5 h-5"></i>
    673             </button>
    674             <span id="history-label" class="text-gemini-textSecondary text-xs font-medium uppercase tracking-wider">History</span>
    675             
    676             <div id="history-search-container" class="relative w-full max-w-[140px] ml-4">
    677                <input type="text" id="history-search" placeholder="Search..." oninput="filterHistory(this.value)" class="w-full bg-[#131314] text-xs text-white border border-gemini-surfaceHover rounded-md px-2 py-1 focus:outline-none focus:border-gemini-blue">
    678                <i data-lucide="search" class="absolute right-2 top-1.5 w-3 h-3 text-gemini-textSecondary"></i>
    679             </div>
    680         </div>
    681 
    682         <!-- New Chat Button -->
    683         <div class="px-3 mb-2">
    684             <button onclick="startNewChat()" class="w-full bg-gemini-surfaceHover hover:bg-[#333537] text-gemini-textSecondary hover:text-white py-3 px-4 rounded-full flex items-center gap-3 transition-colors text-sm font-medium">
    685                 <i data-lucide="plus" class="w-5 h-5"></i>
    686                 <span>New chat</span>
    687             </button>
    688         </div>
    689 
    690         <!-- Chat History List -->
    691         <div id="chat-history-list" class="flex-1 overflow-y-auto px-2 py-2 space-y-1">
    692             <!-- Skeleton Loader injected via JS -->
    693         </div>
    694 
    695         <!-- User Profile (Bottom) -->
    696         <div class="p-4 border-t border-gemini-surfaceHover space-y-1">
    697             <button onclick="toggleSettingsModal()" class="w-full flex items-center gap-3 p-2 hover:bg-gemini-surfaceHover rounded-lg transition-colors text-left text-gemini-textSecondary hover:text-white">
    698                 <i data-lucide="settings" class="w-4 h-4"></i>
    699                 <span class="text-sm font-medium">Settings</span>
    700             </button>
    701             
    702             <button onclick="toggleProfileModal()" class="w-full flex items-center gap-3 p-2 hover:bg-gemini-surfaceHover rounded-lg transition-colors text-left group mt-1">
    703                 <div class="w-7 h-7 rounded-full bg-gradient-to-tr from-blue-500 to-purple-500 flex items-center justify-center text-[10px] font-bold text-white overflow-hidden">
    704                     <img id="user-avatar" class="w-full h-full object-cover hidden" src="" alt="User">
    705                     <span id="user-initial">U</span>
    706                 </div>
    707                 <div class="flex-1 min-w-0">
    708                     <p id="user-email" class="text-xs text-gemini-textSecondary truncate">Not signed in</p>
    709                 </div>
    710             </button>
    711         </div>
    712     </aside>
    713 
    714     <!-- Overlay for Sidebar -->
    715     <div id="sidebar-overlay" onclick="toggleSidebar()" class="fixed inset-0 bg-black/50 z-[55] hidden backdrop-blur-sm transition-opacity"></div>
    716 
    717     <!-- Main Content Area -->
    718     <main class="flex-1 flex flex-col relative w-full h-full min-w-0 bg-gemini-bg">
    719         
    720         <!-- Top Bar (Fixed) -->
    721         <header class="h-16 flex items-center justify-between px-4 md:px-6 sticky top-0 z-30 bg-gemini-bg/80 backdrop-blur-md border-b border-transparent transition-colors">
    722             <div class="flex items-center gap-2">
    723                 <button onclick="toggleSidebar()" class="p-2 -ml-2 text-gemini-textSecondary hover:text-white hover:bg-gemini-surfaceHover rounded-full transition-colors" title="Toggle History">
    724                     <i data-lucide="menu" class="w-6 h-6"></i>
    725                 </button>
    726                 <span class="text-lg font-medium text-white tracking-tight flex items-center gap-2">
    727                     <span class="flex items-center gap-2">
    728                         Ada <span class="text-gemini-blue text-xs font-normal border border-gemini-surfaceHover px-2 py-0.5 rounded-full bg-gemini-surface">Beta</span>
    729                     </span>
    730                 </span>
    731             </div>
    732             
    733             <!-- Code Viewer Toggle & Login Trigger for Shared View -->
    734             <div class="flex items-center gap-2">
    735                 <button id="shared-login-btn" onclick="signInWithGoogle()" class="hidden px-4 py-2 bg-white text-black rounded-full text-sm font-medium hover:bg-gray-200 transition-colors">
    736                     Sign In to Save
    737                 </button>
    738                 
    739                 <button onclick="toggleArtifactPanel()" class="p-2 text-gemini-textSecondary hover:text-gemini-blue relative rounded-full hover:bg-gemini-surfaceHover transition-colors" title="Toggle Code Viewer">
    740                     <i data-lucide="panel-right" class="w-6 h-6"></i>
    741                     <span id="artifact-indicator" class="absolute top-2 right-2 w-2.5 h-2.5 bg-gemini-blue border-2 border-gemini-bg rounded-full hidden shadow-glow"></span>
    742                 </button>
    743             </div>
    744         </header>
    745 
    746         <!-- Chat Container -->
    747         <div id="chat-container" class="flex-1 overflow-y-auto px-4 md:px-0 pb-32 pt-4 scroll-smooth">
    748             <div class="max-w-3xl mx-auto flex flex-col gap-6">
    749                 <!-- Welcome Message -->
    750                 <div id="welcome-message" class="flex flex-col items-start justify-center min-h-[50vh] space-y-8 animate-slide-up px-2">
    751                     <div class="space-y-2 w-full">
    752                         <div class="w-12 h-12 mb-4 animate-spin-slow-entry">
    753                             <svg class="w-full h-full drop-shadow-[0_0_15px_rgba(168,199,250,0.5)]"><use href="#icon-ada"></use></svg>
    754                         </div>
    755                         <h1 class="text-4xl md:text-5xl font-medium text-transparent bg-clip-text bg-gradient-to-r from-[#4285F4] via-[#9B72CB] to-[#D96570] pb-2">
    756                             Hello, <span id="welcome-name" class="text-white truncate block md:inline max-w-[200px] md:max-w-none">Student</span>
    757                         </h1>
    758                         <!-- UPDATED COLOR -->
    759                         <h2 class="text-3xl md:text-5xl font-medium text-gemini-textSecondary/30">How can I help you code today?</h2>
    760                     </div>
    761 
    762                     <!-- Suggestion Chips (Hidden on Mobile) -->
    763                     <div class="hidden md:flex flex-wrap gap-3 w-full" id="suggestion-chips">
    764                         <button onclick="setPrompt('Debug this Python script')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
    765                             <span class="block mb-1 text-gemini-blue group-hover:translate-x-1 transition-transform"><i data-lucide="bug" class="w-4 h-4 inline mr-1"></i> Debug</span>
    766                             Find errors in code
    767                         </button>
    768                         <button onclick="setPrompt('Explain this concept')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
    769                             <span class="block mb-1 text-gemini-purple group-hover:translate-x-1 transition-transform"><i data-lucide="book-open" class="w-4 h-4 inline mr-1"></i> Explain</span>
    770                             Understand algorithms
    771                         </button>
    772                         <button onclick="setPrompt('Refactor this function')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
    773                             <span class="block mb-1 text-green-400 group-hover:translate-x-1 transition-transform"><i data-lucide="wand-2" class="w-4 h-4 inline mr-1"></i> Refactor</span>
    774                             Optimize performance
    775                         </button>
    776                     </div>
    777                 </div>
    778             </div>
    779         </div>
    780 
    781         <!-- Input Area (Fixed Bottom) -->
    782         <div class="absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-gemini-bg via-gemini-bg to-transparent z-20" id="input-area">
    783             <div class="max-w-3xl mx-auto">
    784                 <form id="chat-form" onsubmit="handleFormSubmit(event)" class="bg-gemini-surface rounded-[28px] flex items-end p-2 border border-gemini-surfaceHover focus-within:bg-gemini-surfaceHover focus-within:border-gemini-textSecondary/20 transition-all shadow-xl">
    785                     <!-- ADDED: transition-all duration-200 for smooth growth -->
    786                     <textarea 
    787                         id="user-input"
    788                         class="w-full bg-transparent text-white placeholder-gemini-textSecondary py-3.5 px-4 max-h-48 min-h-[52px] resize-none focus:outline-none text-base no-scrollbar transition-all duration-200 ease-in-out"
    789                         placeholder="Enter a prompt here"
    790                         rows="1"
    791                         oninput="autoResize(this)"
    792                         onkeydown="handleEnter(event)"
    793                         enterkeyhint="send"
    794                     ></textarea>
    795                     
    796                     <button type="submit" id="send-btn" class="p-3 text-gemini-textSecondary hover:text-white disabled:opacity-50 disabled:cursor-not-allowed transition-colors rounded-full">
    797                         <i data-lucide="send-horizontal" class="w-6 h-6"></i>
    798                     </button>
    799                 </form>
    800                 <div class="text-center mt-3 text-xs text-gemini-textSecondary/60">
    801                     Ada may display inaccurate info, including about people, so double-check its responses.
    802                 </div>
    803             </div>
    804         </div>
    805     </main>
    806 
    807     <!-- Right Artifact Panel (Drawer on ALL screens) -->
    808     <aside id="artifact-panel" class="fixed inset-y-0 right-0 z-[70] w-full md:w-[600px] bg-[#1e1e1e] border-l border-[#333] transform translate-x-full drawer shadow-2xl flex flex-col">
    809         <!-- Panel Header -->
    810         <div class="h-14 flex-shrink-0 flex items-center justify-between px-4 bg-[#252526] border-b border-[#333]">
    811             <div class="flex items-center gap-3">
    812                 <span class="text-xs uppercase tracking-wide text-[#969696] font-medium">Workspace</span>
    813                 <span id="lang-display" class="text-xs text-[#cccccc] bg-[#3c3c3c] px-2 py-0.5 rounded">PLAINTEXT</span>
    814             </div>
    815             <div class="flex gap-2">
    816                 <button onclick="copyArtifact()" class="p-2 text-[#cccccc] hover:text-white hover:bg-[#3c3c3c] rounded transition-colors" title="Copy Code">
    817                     <i data-lucide="copy" class="w-4 h-4"></i>
    818                 </button>
    819                 <button onclick="toggleArtifactPanel()" class="p-2 text-[#cccccc] hover:text-white hover:bg-[#3c3c3c] rounded transition-colors" title="Close">
    820                     <i data-lucide="x" class="w-5 h-5"></i>
    821                 </button>
    822             </div>
    823         </div>
    824 
    825         <!-- Editor Content -->
    826         <div class="flex-1 overflow-hidden relative bg-[#1e1e1e]">
    827             <textarea id="artifact-editor" class="w-full h-full"></textarea>
    828         </div>
    829 
    830         <!-- ADDED: Status Bar -->
    831         <div class="h-6 bg-[#007acc] text-white flex items-center px-3 text-xs justify-end gap-4 select-none">
    832             <div class="flex items-center gap-1">
    833                 <i data-lucide="code" class="w-3 h-3"></i>
    834                 <span id="status-lang">JavaScript</span>
    835             </div>
    836             <div class="flex items-center gap-1">
    837                 <span id="status-cursor">Ln 1, Col 1</span>
    838             </div>
    839             <div>UTF-8</div>
    840         </div>
    841     </aside>
    842 
    843     <script>
    844         // --- CONFIGURATION ---
    845         const API_BASE_URL = "https://ada-web.onrender.com/api"; 
    846         
    847         const firebaseConfig = {
    848             apiKey: "AIzaSyAhyoNYUSXWIxdBiTxwSDcU7HkhhLEVlOc",
    849             authDomain: "ada-ai-aranag.firebaseapp.com",
    850             projectId: "ada-ai-aranag",
    851             storageBucket: "ada-ai-aranag.firebasestorage.app",
    852             messagingSenderId: "865895114061",
    853             appId: "1:865895114061:web:5fd4493b0e388727e6c304"
    854         };
    855         
    856         // --- STATE & INIT ---
    857         let auth, db;
    858         let isSignUpMode = false;
    859         let state = {
    860             messages: [],
    861             isTyping: false,
    862             currentChatId: null,
    863             user: null,
    864             isSharedView: false
    865         };
    866         let editor = null;
    867         let settings = {
    868             allowSharing: localStorage.getItem('ada_allow_sharing') === 'true',
    869             fontSize: parseInt(localStorage.getItem('ada_font_size')) || 14
    870         };
    871 
    872         // --- COMMAND PALETTE DATA ---
    873         const commands = [
    874             { name: "New Chat", icon: "plus", action: startNewChat, shortcut: "N" },
    875             { name: "Toggle Sidebar", icon: "sidebar", action: toggleSidebar, shortcut: "Ctrl+/" },
    876             { name: "Clear History", icon: "trash-2", action: confirmClearHistory, shortcut: "" },
    877             { name: "Settings", icon: "settings", action: toggleSettingsModal, shortcut: "" },
    878             { name: "Sign Out", icon: "log-out", action: confirmSignOut, shortcut: "" }
    879         ];
    880 
    881         function initApp() {
    882             lucide.createIcons();
    883             
    884             // Set initial settings
    885             applyFontSize(settings.fontSize);
    886             
    887             const shareToggle = document.getElementById('share-toggle-checkbox');
    888             if(shareToggle) shareToggle.checked = settings.allowSharing;
    889 
    890             // Check for Shared URL param
    891             const urlParams = new URLSearchParams(window.location.search);
    892             const sharedChatId = urlParams.get('chat');
    893             if (sharedChatId) {
    894                 state.isSharedView = true;
    895                 state.currentChatId = sharedChatId;
    896                 enterSharedMode(sharedChatId);
    897             }
    898             
    899             // Initialize CodeMirror (Standard setup)
    900             editor = CodeMirror.fromTextArea(document.getElementById("artifact-editor"), {
    901                 lineNumbers: true,
    902                 mode: "javascript",
    903                 theme: "dracula",
    904                 readOnly: true, // Read-only as it's an output viewer primarily
    905                 lineWrapping: true
    906             });
    907 
    908             // ADDED: Cursor Activity Listener for Status Bar
    909             editor.on("cursorActivity", () => {
    910                 const pos = editor.getCursor();
    911                 document.getElementById('status-cursor').innerText = `Ln ${pos.line + 1}, Col ${pos.ch + 1}`;
    912             });
    913 
    914             // Initialize Firebase
    915             try {
    916                 firebase.initializeApp(firebaseConfig);
    917                 auth = firebase.auth();
    918                 db = firebase.firestore();
    919                 if (!state.isSharedView) checkAuth();
    920                 else checkAuthShared();
    921             } catch (e) {
    922                 console.error("Init Failed:", e);
    923                 document.getElementById('loading-overlay').classList.add('opacity-0', 'pointer-events-none');
    924             }
    925 
    926             // Mobile Height Fix
    927             const setVh = () => {
    928                 let vh = window.innerHeight * 0.01;
    929                 document.documentElement.style.setProperty('--vh', `${vh}px`);
    930             };
    931             window.addEventListener('resize', setVh);
    932             setVh();
    933 
    934             // Context Menu Listener
    935             document.addEventListener('click', (e) => {
    936                 const menu = document.querySelector('.context-menu');
    937                 if (menu) menu.remove();
    938             });
    939 
    940             // ADDED: Global Keyboard Shortcuts
    941             document.addEventListener('keydown', handleGlobalKeydown);
    942 
    943             // ADDED: Swipe Gestures
    944             initSwipeGestures();
    945         }
    946 
    947         function autoResize(textarea) {
    948             textarea.style.height = 'auto';
    949             textarea.style.height = Math.min(textarea.scrollHeight, 200) + 'px';
    950         }
    951 
    952         // ADDED: Swipe Gesture Logic
    953         function initSwipeGestures() {
    954             let touchStartX = 0;
    955             let touchStartY = 0;
    956             
    957             document.addEventListener('touchstart', e => {
    958                 touchStartX = e.changedTouches[0].screenX;
    959                 touchStartY = e.changedTouches[0].screenY;
    960             }, {passive: true});
    961 
    962             document.addEventListener('touchend', e => {
    963                 const touchEndX = e.changedTouches[0].screenX;
    964                 const touchEndY = e.changedTouches[0].screenY;
    965                 
    966                 handleSwipe(touchStartX, touchStartY, touchEndX, touchEndY);
    967             }, {passive: true});
    968         }
    969 
    970         function handleSwipe(startX, startY, endX, endY) {
    971             const diffX = endX - startX;
    972             const diffY = endY - startY;
    973 
    974             // Only trigger if horizontal swipe is dominant and significant
    975             if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 50) {
    976                 const sidebar = document.getElementById('sidebar');
    977                 const isClosed = sidebar.classList.contains('-translate-x-full');
    978 
    979                 // Swipe Right (Open) - Only works from left edge area (first 30px)
    980                 if (diffX > 0 && startX < 30 && isClosed) {
    981                     toggleSidebar();
    982                 }
    983                 
    984                 // Swipe Left (Close)
    985                 if (diffX < 0 && !isClosed) {
    986                     toggleSidebar();
    987                 }
    988             }
    989         }
    990 
    991         // ADDED: Keyboard Shortcuts Handler
    992         function handleGlobalKeydown(e) {
    993             // Toggle Sidebar: Ctrl + / (or Cmd + /)
    994             if ((e.ctrlKey || e.metaKey) && e.key === '/') {
    995                 e.preventDefault();
    996                 toggleSidebar();
    997             }
    998 
    999             // Command Palette: Ctrl + K (or Cmd + K)
   1000             if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
   1001                 e.preventDefault();
   1002                 toggleCommandPalette();
   1003             }
   1004 
   1005             // Close Palette on ESC
   1006             if (e.key === 'Escape') {
   1007                 const cmd = document.getElementById('command-palette');
   1008                 if (!cmd.classList.contains('hidden')) {
   1009                     toggleCommandPalette();
   1010                 }
   1011             }
   1012         }
   1013 
   1014         // ADDED: Command Palette Logic
   1015         function toggleCommandPalette() {
   1016             const palette = document.getElementById('command-palette');
   1017             const input = document.getElementById('cmd-input');
   1018             const list = document.getElementById('cmd-list');
   1019 
   1020             if (palette.classList.contains('hidden')) {
   1021                 // Show
   1022                 palette.classList.remove('hidden', 'pointer-events-none');
   1023                 requestAnimationFrame(() => palette.classList.remove('opacity-0'));
   1024                 input.value = '';
   1025                 input.focus();
   1026                 renderCommands(commands);
   1027             } else {
   1028                 // Hide
   1029                 palette.classList.add('opacity-0');
   1030                 setTimeout(() => palette.classList.add('hidden', 'pointer-events-none'), 150);
   1031             }
   1032 
   1033             input.oninput = (e) => {
   1034                 const val = e.target.value.toLowerCase();
   1035                 const filtered = commands.filter(c => c.name.toLowerCase().includes(val));
   1036                 renderCommands(filtered);
   1037             };
   1038         }
   1039 
   1040         function renderCommands(cmds) {
   1041             const list = document.getElementById('cmd-list');
   1042             list.innerHTML = '';
   1043             
   1044             if (cmds.length === 0) {
   1045                 list.innerHTML = `<div class="text-gemini-textSecondary text-xs p-3 text-center">No commands found</div>`;
   1046                 return;
   1047             }
   1048 
   1049             cmds.forEach(cmd => {
   1050                 const div = document.createElement('div');
   1051                 div.className = 'cmd-item group';
   1052                 div.onclick = () => {
   1053                     cmd.action();
   1054                     toggleCommandPalette();
   1055                 };
   1056                 div.innerHTML = `
   1057                     <div class="flex items-center gap-3">
   1058                         <i data-lucide="${cmd.icon}" class="w-4 h-4 text-gemini-textSecondary group-hover:text-white"></i>
   1059                         <span class="text-sm">${cmd.name}</span>
   1060                     </div>
   1061                     ${cmd.shortcut ? `<span class="cmd-shortcut">${cmd.shortcut}</span>` : ''}
   1062                 `;
   1063                 list.appendChild(div);
   1064             });
   1065             lucide.createIcons();
   1066         }
   1067 
   1068         // --- SETTINGS ---
   1069         function changeFontSize(delta) {
   1070             settings.fontSize = Math.max(10, Math.min(24, settings.fontSize + delta));
   1071             localStorage.setItem('ada_font_size', settings.fontSize);
   1072             applyFontSize(settings.fontSize);
   1073         }
   1074 
   1075         function applyFontSize(size) {
   1076             document.getElementById('font-size-display').innerText = size;
   1077             if(editor) {
   1078                 editor.getWrapperElement().style.fontSize = `${size}px`;
   1079                 editor.refresh();
   1080             }
   1081         }
   1082 
   1083         // --- SHARED MODE LOGIC ---
   1084         async function enterSharedMode(chatId) {
   1085             document.getElementById('sidebar').classList.add('hidden');
   1086             const inputArea = document.getElementById('input-area');
   1087             const sidebarToggle = document.querySelector('header button[title="Toggle History"]');
   1088             
   1089             inputArea.classList.add('hidden');
   1090             if(sidebarToggle) sidebarToggle.style.display = 'none';
   1091         }
   1092 
   1093         function checkAuthShared() {
   1094              auth.onAuthStateChanged(user => {
   1095                 const loadingOverlay = document.getElementById('loading-overlay');
   1096                 loadingOverlay.classList.add('opacity-0', 'pointer-events-none');
   1097 
   1098                 if (user) {
   1099                     state.user = user;
   1100                     document.getElementById('sidebar').classList.remove('hidden');
   1101                     document.getElementById('input-area').classList.remove('hidden');
   1102                     const sidebarToggle = document.querySelector('header button[title="Toggle History"]');
   1103                     if(sidebarToggle) sidebarToggle.style.display = 'block';
   1104                     document.getElementById('shared-login-btn').classList.add('hidden');
   1105 
   1106                     fetchChats();
   1107                     loadChat(state.currentChatId);
   1108                 } else {
   1109                     state.user = null;
   1110                     document.getElementById('shared-login-btn').classList.remove('hidden');
   1111                     loadChatReadOnly(state.currentChatId);
   1112                 }
   1113             });
   1114         }
   1115         
   1116         async function loadChatReadOnly(chatId) {
   1117              const container = document.querySelector('#chat-container > div');
   1118              container.innerHTML = `
   1119                 <div class="flex flex-col items-center justify-center min-h-[50vh] text-center p-6">
   1120                     <div class="p-4 bg-gemini-surface rounded-2xl border border-gemini-surfaceHover mb-4">
   1121                         <i data-lucide="lock" class="w-8 h-8 text-gemini-textSecondary mx-auto mb-2"></i>
   1122                         <p class="text-white font-medium">Shared Chat</p>
   1123                     </div>
   1124                     <p class="text-gemini-textSecondary max-w-md">To view and continue this conversation, please sign in. The chat will be saved to your history.</p>
   1125                 </div>
   1126              `;
   1127              lucide.createIcons();
   1128         }
   1129 
   1130         // --- UI TOGGLES & HELPERS ---
   1131         let toastTimeout;
   1132 
   1133         function showToast(msg, type = 'info') {
   1134             // Check for Mobile + Auth Modal Open case
   1135             const authModal = document.getElementById('auth-modal');
   1136             const isMobile = window.innerWidth < 768; // Tailwind md breakpoint
   1137             const isAuthOpen = !authModal.classList.contains('hidden') && !authModal.classList.contains('opacity-0');
   1138 
   1139             if (isMobile && isAuthOpen) {
   1140                 const feedback = document.getElementById('auth-feedback');
   1141                 feedback.innerText = msg;
   1142                 
   1143                 // Style based on type
   1144                 if (type === 'error') {
   1145                     feedback.className = 'text-center text-sm mt-3 p-3 rounded-lg bg-red-500/10 text-red-400 border border-red-500/20';
   1146                 } else if (type === 'success') {
   1147                     feedback.className = 'text-center text-sm mt-3 p-3 rounded-lg bg-green-500/10 text-green-400 border border-green-500/20';
   1148                 } else {
   1149                     feedback.className = 'text-center text-sm mt-3 p-3 rounded-lg bg-blue-500/10 text-blue-400 border border-blue-500/20';
   1150                 }
   1151                 
   1152                 feedback.classList.remove('hidden');
   1153                 
   1154                 // Auto-hide inline feedback after 6s
   1155                 if (toastTimeout) clearTimeout(toastTimeout);
   1156                 toastTimeout = setTimeout(() => {
   1157                     feedback.classList.add('hidden');
   1158                 }, 6000);
   1159                 return;
   1160             }
   1161 
   1162             // Standard Toast Logic (PC or Auth closed)
   1163             const t = document.getElementById('toast');
   1164             
   1165             if (toastTimeout) clearTimeout(toastTimeout);
   1166 
   1167             // 1. Determine icon and style based on type
   1168             let iconName = 'info';
   1169             let iconColor = 'text-gemini-blue';
   1170             let containerClass = 'bg-gemini-surface border-gemini-accent text-white';
   1171 
   1172             if (type === 'error') {
   1173                 iconName = 'alert-circle';
   1174                 iconColor = 'text-red-400';
   1175                 containerClass = 'bg-red-500/10 border-red-500/20 text-red-400';
   1176             } else if (type === 'success') {
   1177                 iconName = 'check-circle';
   1178                 iconColor = 'text-green-400';
   1179             }
   1180 
   1181             // 2. Completely rebuild innerHTML to ensure we have a fresh <i> tag for Lucide
   1182             t.innerHTML = `<i data-lucide="${iconName}" class="w-4 h-4 ${iconColor} flex-shrink-0"></i><span id="toast-message" class="text-sm font-medium whitespace-normal text-center">${msg}</span>`;
   1183             
   1184             // 3. Set container classes and visibility
   1185             t.className = `fixed bottom-24 md:bottom-10 left-1/2 -translate-x-1/2 border px-6 py-3 rounded-full shadow-2xl z-[220] transition-all duration-300 transform translate-y-0 opacity-100 flex items-center gap-2 max-w-[90vw] w-max ${containerClass}`;
   1186             
   1187             // 4. Render icons
   1188             lucide.createIcons();
   1189             
   1190             // 5. Auto-hide
   1191             toastTimeout = setTimeout(() => {
   1192                  t.classList.remove('opacity-100', 'translate-y-0');
   1193                  t.classList.add('opacity-0', 'translate-y-20', 'pointer-events-none');
   1194             }, 3000);
   1195         }
   1196 
   1197         function togglePasswordVisibility() {
   1198             const input = document.getElementById('auth-password');
   1199             const icon = document.getElementById('password-toggle-icon');
   1200             
   1201             if (input.type === 'password') {
   1202                 input.type = 'text';
   1203                 icon.setAttribute('data-lucide', 'eye-off');
   1204             } else {
   1205                 input.type = 'password';
   1206                 icon.setAttribute('data-lucide', 'eye');
   1207             }
   1208             lucide.createIcons();
   1209         }
   1210 
   1211         function toggleShareSetting(checkbox) {
   1212             settings.allowSharing = checkbox.checked;
   1213             localStorage.setItem('ada_allow_sharing', settings.allowSharing);
   1214         }
   1215 
   1216         function toggleSidebar() {
   1217             const sb = document.getElementById('sidebar');
   1218             const overlay = document.getElementById('sidebar-overlay');
   1219             const isClosed = sb.classList.contains('-translate-x-full');
   1220             
   1221             if (isClosed) {
   1222                 sb.classList.remove('-translate-x-full');
   1223                 overlay.classList.remove('hidden');
   1224             } else {
   1225                 sb.classList.add('-translate-x-full');
   1226                 overlay.classList.add('hidden');
   1227             }
   1228         }
   1229 
   1230         function toggleArtifactPanel() {
   1231             const panel = document.getElementById('artifact-panel');
   1232             const isClosed = panel.classList.contains('translate-x-full');
   1233             
   1234             if (isClosed) {
   1235                 panel.classList.remove('translate-x-full');
   1236                 document.getElementById('artifact-indicator').classList.add('hidden');
   1237                 setTimeout(() => editor.refresh(), 300); 
   1238             } else {
   1239                 panel.classList.add('translate-x-full');
   1240             }
   1241         }
   1242         
   1243         function toggleProfileModal() {
   1244             const modal = document.getElementById('profile-modal');
   1245             const content = document.getElementById('profile-modal-content');
   1246             
   1247             if (modal.classList.contains('hidden')) {
   1248                 modal.classList.remove('hidden', 'pointer-events-none');
   1249                 requestAnimationFrame(() => {
   1250                     modal.classList.remove('opacity-0');
   1251                     content.classList.remove('scale-95');
   1252                     content.classList.add('scale-100');
   1253                 });
   1254                 
   1255                 if (state.user) {
   1256                      // Handle Guest / User Display
   1257                      if (state.user.isAnonymous) {
   1258                          document.getElementById('profile-name').innerText = "Guest User";
   1259                          document.getElementById('profile-email').innerText = "Anonymous Session";
   1260                          document.getElementById('profile-initial').innerText = "G";
   1261                          document.getElementById('profile-avatar').classList.add('hidden');
   1262                          document.getElementById('profile-initial').classList.remove('hidden');
   1263                      } else {
   1264                          document.getElementById('profile-name').innerText = state.user.displayName || 'User';
   1265                          document.getElementById('profile-email').innerText = state.user.email || '';
   1266                          const initial = document.getElementById('profile-initial');
   1267                          const avatar = document.getElementById('profile-avatar');
   1268                          
   1269                          if (state.user.photoURL) {
   1270                              avatar.src = state.user.photoURL;
   1271                              avatar.classList.remove('hidden');
   1272                              initial.classList.add('hidden');
   1273                          } else {
   1274                              initial.innerText = (state.user.displayName || 'U')[0];
   1275                              avatar.classList.add('hidden');
   1276                              initial.classList.remove('hidden');
   1277                          }
   1278                      }
   1279                 }
   1280             } else {
   1281                 modal.classList.add('opacity-0');
   1282                 content.classList.remove('scale-100');
   1283                 content.classList.add('scale-95');
   1284                 setTimeout(() => modal.classList.add('hidden', 'pointer-events-none'), 300);
   1285             }
   1286         }
   1287 
   1288         function toggleSettingsModal() {
   1289             const modal = document.getElementById('settings-modal');
   1290             const content = document.getElementById('settings-modal-content');
   1291             
   1292             if (modal.classList.contains('hidden')) {
   1293                 modal.classList.remove('hidden', 'pointer-events-none');
   1294                 requestAnimationFrame(() => {
   1295                     modal.classList.remove('opacity-0');
   1296                     content.classList.remove('scale-95');
   1297                     content.classList.add('scale-100');
   1298                 });
   1299             } else {
   1300                 modal.classList.add('opacity-0');
   1301                 content.classList.remove('scale-100');
   1302                 content.classList.add('scale-95');
   1303                 setTimeout(() => modal.classList.add('hidden', 'pointer-events-none'), 300);
   1304             }
   1305         }
   1306 
   1307         // --- FEATURES IMPLEMENTATION ---
   1308 
   1309         // 1. History Search
   1310         function filterHistory(query) {
   1311             const list = document.getElementById('chat-history-list');
   1312             const items = list.querySelectorAll('div[onclick]');
   1313             query = query.toLowerCase();
   1314             
   1315             items.forEach(item => {
   1316                 const text = item.querySelector('span').innerText.toLowerCase();
   1317                 if (text.includes(query)) {
   1318                     item.style.display = 'flex';
   1319                 } else {
   1320                     item.style.display = 'none';
   1321                 }
   1322             });
   1323         }
   1324 
   1325         // --- CONFIRM MODALS ---
   1326         let confirmCallback = null;
   1327 
   1328         function showConfirmModal(title, message, callback, matchText = null) {
   1329             const modal = document.getElementById('confirm-modal');
   1330             const content = document.getElementById('confirm-modal-content');
   1331             
   1332             document.getElementById('confirm-title').innerText = title;
   1333             document.getElementById('confirm-message').innerText = message;
   1334             
   1335             const inputContainer = document.getElementById('confirm-input-container');
   1336             const input = document.getElementById('confirm-input');
   1337             const btn = document.getElementById('confirm-action-btn');
   1338 
   1339             if (matchText) {
   1340                 inputContainer.classList.remove('hidden');
   1341                 document.getElementById('confirm-match-text').innerText = matchText;
   1342                 input.value = '';
   1343                 input.oninput = () => {
   1344                     if (input.value === matchText) {
   1345                         btn.disabled = false;
   1346                         btn.classList.remove('opacity-50', 'cursor-not-allowed');
   1347                     } else {
   1348                         btn.disabled = true;
   1349                         btn.classList.add('opacity-50', 'cursor-not-allowed');
   1350                     }
   1351                 };
   1352                 btn.disabled = true;
   1353                 btn.classList.add('opacity-50', 'cursor-not-allowed');
   1354             } else {
   1355                 inputContainer.classList.add('hidden');
   1356                 btn.disabled = false;
   1357                 btn.classList.remove('opacity-50', 'cursor-not-allowed');
   1358             }
   1359 
   1360             confirmCallback = callback;
   1361             
   1362             modal.classList.remove('hidden');
   1363             requestAnimationFrame(() => {
   1364                 modal.classList.remove('opacity-0');
   1365                 content.classList.remove('scale-95');
   1366                 content.classList.add('scale-100');
   1367             });
   1368             
   1369             btn.onclick = () => {
   1370                  closeConfirmModal();
   1371                  if (confirmCallback) confirmCallback();
   1372             };
   1373         }
   1374 
   1375         function closeConfirmModal() {
   1376             const modal = document.getElementById('confirm-modal');
   1377             const content = document.getElementById('confirm-modal-content');
   1378             modal.classList.add('opacity-0');
   1379             content.classList.remove('scale-100');
   1380             content.classList.add('scale-95');
   1381             setTimeout(() => modal.classList.add('hidden'), 300);
   1382         }
   1383 
   1384         function confirmSignOut() {
   1385             toggleProfileModal(); 
   1386             showConfirmModal('Sign Out', 'Are you sure you want to sign out?', signOutUser);
   1387         }
   1388 
   1389         function confirmClearHistory() {
   1390             toggleSettingsModal();
   1391             if (!state.user || !state.user.email) return;
   1392             showConfirmModal(
   1393                 'Clear Activity', 
   1394                 'This will permanently delete all your chat history. Type your email to confirm.', 
   1395                 clearHistory, 
   1396                 state.user.email
   1397             );
   1398         }
   1399 
   1400         async function clearHistory() {
   1401             if (!state.user) return;
   1402             const loading = document.getElementById('loading-overlay');
   1403             loading.classList.remove('opacity-0', 'pointer-events-none');
   1404             
   1405             try {
   1406                 // FIXED: Use correct path users/{uid}/chats
   1407                 const chatsRef = db.collection('users').doc(state.user.uid).collection('chats');
   1408                 const snapshot = await chatsRef.get();
   1409                 
   1410                 const batch = db.batch();
   1411                 snapshot.docs.forEach((doc) => {
   1412                     batch.delete(doc.ref);
   1413                 });
   1414                 await batch.commit();
   1415                 
   1416                 location.reload();
   1417             } catch (error) {
   1418                 console.error("Error clearing history:", error);
   1419                 loading.classList.add('opacity-0', 'pointer-events-none');
   1420                 showToast("Failed to clear history.", "error");
   1421             }
   1422         }
   1423 
   1424         function confirmDeleteChat(chatId) {
   1425             showConfirmModal('Delete Chat', 'This action cannot be undone.', () => deleteChat(chatId));
   1426         }
   1427 
   1428         async function deleteChat(chatId) {
   1429             if (!state.user) return;
   1430             try {
   1431                 // FIXED: Use correct path users/{uid}/chats/{chatId}
   1432                 await db.collection('users').doc(state.user.uid).collection('chats').doc(chatId).delete();
   1433                 
   1434                 if (state.currentChatId === chatId) {
   1435                     location.reload();
   1436                 } else {
   1437                     fetchChats(); 
   1438                     showToast("Chat deleted.", "success");
   1439                 }
   1440             } catch (e) {
   1441                 console.error("Delete Error:", e);
   1442                 showToast("Failed to delete chat.", "error");
   1443             }
   1444         }
   1445 
   1446         // --- CONTEXT MENU & EXPORT ---
   1447         function showChatContextMenu(e, chatId, chatTitle) {
   1448             e.preventDefault();
   1449             e.stopPropagation();
   1450 
   1451             const existing = document.querySelector('.context-menu');
   1452             if (existing) existing.remove();
   1453 
   1454             const menu = document.createElement('div');
   1455             menu.className = 'context-menu';
   1456             
   1457             // Share Option
   1458             if (settings.allowSharing) {
   1459                 const shareBtn = document.createElement('div');
   1460                 shareBtn.className = 'context-menu-item';
   1461                 shareBtn.innerHTML = `<i data-lucide="link" class="w-4 h-4"></i> Share Chat`;
   1462                 shareBtn.onclick = async () => {
   1463                     const url = `${window.location.origin}?chat=${chatId}`;
   1464                     if (navigator.share) {
   1465                         try {
   1466                             await navigator.share({ title: 'Ada Chat', url: url });
   1467                         } catch (err) { /* Share cancelled */ }
   1468                     } else {
   1469                         navigator.clipboard.writeText(url).then(() => showToast('Link copied!', 'success'));
   1470                     }
   1471                     menu.remove();
   1472                 };
   1473                 menu.appendChild(shareBtn);
   1474             }
   1475 
   1476             // Export Options (Expanded)
   1477             const jsonBtn = document.createElement('div');
   1478             jsonBtn.className = 'context-menu-item';
   1479             jsonBtn.innerHTML = `<i data-lucide="file-json" class="w-4 h-4"></i> Export JSON`;
   1480             jsonBtn.onclick = () => {
   1481                 downloadChat(chatId, chatTitle, 'json');
   1482                 menu.remove();
   1483             };
   1484             menu.appendChild(jsonBtn);
   1485 
   1486             const mdBtn = document.createElement('div');
   1487             mdBtn.className = 'context-menu-item';
   1488             mdBtn.innerHTML = `<i data-lucide="file-text" class="w-4 h-4"></i> Export Markdown`;
   1489             mdBtn.onclick = () => {
   1490                 downloadChat(chatId, chatTitle, 'md');
   1491                 menu.remove();
   1492             };
   1493             menu.appendChild(mdBtn);
   1494 
   1495             // Delete Option
   1496             const delBtn = document.createElement('div');
   1497             delBtn.className = 'context-menu-item danger';
   1498             delBtn.innerHTML = `<i data-lucide="trash-2" class="w-4 h-4"></i> Delete Chat`;
   1499             delBtn.onclick = () => {
   1500                 confirmDeleteChat(chatId);
   1501                 menu.remove();
   1502             };
   1503             menu.appendChild(delBtn);
   1504 
   1505             document.body.appendChild(menu);
   1506             
   1507             // Position
   1508             const rect = e.target.getBoundingClientRect();
   1509             const menuWidth = 180;
   1510             const menuHeight = 200;
   1511             
   1512             let left = rect.left;
   1513             let top = rect.bottom + 5;
   1514 
   1515             if (left + menuWidth > window.innerWidth) left = window.innerWidth - menuWidth - 16;
   1516             if (left < 16) left = 16;
   1517             if (top + menuHeight > window.innerHeight) top = rect.top - menuHeight - 5;
   1518 
   1519             menu.style.top = `${top}px`;
   1520             menu.style.left = `${left}px`;
   1521             
   1522             lucide.createIcons();
   1523         }
   1524 
   1525         async function downloadChat(chatId, title, format) {
   1526              try {
   1527                 const token = await state.user.getIdToken();
   1528                 const res = await fetch(`${API_BASE_URL}/chats/${chatId}`, { headers: { 'Authorization': `Bearer ${token}` } });
   1529                 const data = await res.json();
   1530                 
   1531                 let content, type, ext;
   1532                 if (format === 'json') {
   1533                     content = JSON.stringify(data, null, 2);
   1534                     type = 'application/json';
   1535                     ext = 'json';
   1536                 } else {
   1537                     // Markdown conversion
   1538                     content = `# ${title}\n\n`;
   1539                     data.messages.forEach(msg => {
   1540                         content += `### ${msg.role === 'user' ? 'User' : 'Ada AI'}\n${msg.content}\n\n`;
   1541                     });
   1542                     type = 'text/markdown';
   1543                     ext = 'md';
   1544                 }
   1545                 
   1546                 const blob = new Blob([content], { type: type });
   1547                 const url = URL.createObjectURL(blob);
   1548                 const a = document.createElement('a');
   1549                 a.href = url;
   1550                 a.download = `ada_chat_${title.replace(/\s+/g, '_')}.${ext}`;
   1551                 document.body.appendChild(a);
   1552                 a.click();
   1553                 document.body.removeChild(a);
   1554                 URL.revokeObjectURL(url);
   1555                 showToast("Chat exported.", "success");
   1556              } catch(e) { 
   1557                  console.error(e);
   1558                  showToast("Export failed.", "error");
   1559              }
   1560         }
   1561 
   1562         // --- AUTH & FIREBASE ---
   1563         async function checkAuth() {
   1564             auth.onAuthStateChanged(async (user) => {
   1565                 const loadingOverlay = document.getElementById('loading-overlay');
   1566                 const authModal = document.getElementById('auth-modal');
   1567                 
   1568                 if (user) {
   1569                     try {
   1570                         // Force refresh user to get latest emailVerified status
   1571                         await user.reload();
   1572                     } catch (e) {
   1573                         console.log("Session reload failed, signing out.");
   1574                         auth.signOut();
   1575                         return;
   1576                     }
   1577 
   1578                     const updatedUser = auth.currentUser;
   1579                     if (!updatedUser) return;
   1580 
   1581                     // Check if email is verified for email/password users
   1582                     const isEmailProvider = updatedUser.providerData.some(p => p.providerId === 'password');
   1583                     if (isEmailProvider && !updatedUser.emailVerified) {
   1584                         showToast("Please verify your email. Check your inbox!", "error");
   1585                         auth.signOut();
   1586                         loadingOverlay.classList.add('opacity-0', 'pointer-events-none');
   1587                         authModal.classList.remove('hidden', 'opacity-0', 'pointer-events-none');
   1588                         return;
   1589                     }
   1590 
   1591                     state.user = updatedUser;
   1592                     localStorage.setItem('ada_user_cached', 'true');
   1593                     
   1594                     loadingOverlay.classList.add('opacity-0', 'pointer-events-none');
   1595                     authModal.classList.add('hidden', 'opacity-0', 'pointer-events-none');
   1596 
   1597                     // --- SIDEBAR VISIBILITY LOGIC (Guest vs User) ---
   1598                     const historyLabel = document.getElementById('history-label');
   1599                     const historySearch = document.getElementById('history-search-container');
   1600                     const historyList = document.getElementById('chat-history-list');
   1601 
   1602                     if (updatedUser.isAnonymous) {
   1603                         // GUEST: Hide History
   1604                         if(historyLabel) historyLabel.classList.add('hidden');
   1605                         if(historySearch) historySearch.classList.add('hidden');
   1606                         if(historyList) historyList.classList.add('hidden');
   1607                         
   1608                         document.getElementById('user-email').innerText = 'Guest Mode';
   1609                         document.getElementById('user-initial').innerText = 'G';
   1610                         document.getElementById('user-initial').classList.remove('hidden');
   1611                         document.getElementById('user-avatar').classList.add('hidden');
   1612                     } else {
   1613                         // USER: Show History
   1614                         if(historyLabel) historyLabel.classList.remove('hidden');
   1615                         if(historySearch) historySearch.classList.remove('hidden');
   1616                         if(historyList) historyList.classList.remove('hidden');
   1617 
   1618                         document.getElementById('user-email').innerText = updatedUser.email || '';
   1619                         document.getElementById('user-initial').innerText = (updatedUser.displayName || 'U')[0];
   1620                         
   1621                         if (updatedUser.photoURL) {
   1622                             const img = document.getElementById('user-avatar');
   1623                             img.src = updatedUser.photoURL;
   1624                             img.classList.remove('hidden');
   1625                             document.getElementById('user-initial').classList.add('hidden');
   1626                         }
   1627                     }
   1628                     
   1629                     const welcomeName = document.getElementById('welcome-name');
   1630                     if (welcomeName) {
   1631                         const name = updatedUser.isAnonymous ? 'Guest' : (updatedUser.email || updatedUser.displayName || 'Student');
   1632                         welcomeName.innerText = name;
   1633                         welcomeName.title = name;
   1634                     }
   1635 
   1636                     if(!state.currentChatId) state.currentChatId = 'session_' + Date.now();
   1637                     
   1638                     // Only fetch history if not guest
   1639                     if (!updatedUser.isAnonymous) {
   1640                         fetchChats();
   1641                     }
   1642                 } else {
   1643                     state.user = null;
   1644                     localStorage.removeItem('ada_user_cached');
   1645                     loadingOverlay.classList.add('opacity-0', 'pointer-events-none');
   1646                     authModal.classList.remove('hidden', 'opacity-0', 'pointer-events-none');
   1647                 }
   1648             });
   1649         }
   1650 
   1651         // --- AUTH HANDLERS ---
   1652         function toggleAuthMode() {
   1653             isSignUpMode = !isSignUpMode;
   1654             const title = document.getElementById('auth-title');
   1655             const subtitle = document.getElementById('auth-subtitle');
   1656             const btn = document.getElementById('auth-submit-btn');
   1657             const toggle = document.getElementById('toggle-auth-mode');
   1658             const extras = document.getElementById('signin-extras');
   1659             
   1660             // Hide feedback when switching modes
   1661             document.getElementById('auth-feedback').classList.add('hidden');
   1662 
   1663             if (isSignUpMode) {
   1664                 title.innerText = "Create Account";
   1665                 subtitle.innerText = "Join Ada to save your code history.";
   1666                 btn.innerText = "Register";
   1667                 toggle.innerText = "Already have an account? Sign In";
   1668                 extras.classList.add('hidden');
   1669             } else {
   1670                 title.innerText = "Welcome to Ada";
   1671                 subtitle.innerText = "Sign in to access your workspace.";
   1672                 btn.innerText = "Sign In";
   1673                 toggle.innerText = "Don't have an account? Create one";
   1674                 extras.classList.remove('hidden');
   1675             }
   1676         }
   1677 
   1678         async function handleAuthSubmit(e) {
   1679             e.preventDefault();
   1680             const email = document.getElementById('auth-email').value;
   1681             const pass = document.getElementById('auth-password').value;
   1682             const btn = document.getElementById('auth-submit-btn');
   1683             
   1684             // Hide previous feedback
   1685             document.getElementById('auth-feedback').classList.add('hidden');
   1686 
   1687             if (!email || !pass) return;
   1688 
   1689             try {
   1690                 btn.disabled = true;
   1691                 btn.innerText = isSignUpMode ? "Registering..." : "Signing in...";
   1692 
   1693                 if (isSignUpMode) {
   1694                     // Create account
   1695                     const cred = await auth.createUserWithEmailAndPassword(email, pass);
   1696                     // Send verification email
   1697                     await cred.user.sendEmailVerification();
   1698                     // Sign out immediately so they can't log in without verification
   1699                     await auth.signOut();
   1700                     // Switch to Sign In mode FIRST so the toast can populate the correct feedback container
   1701                     toggleAuthMode();
   1702                     showToast("Verification email sent! Please check your inbox and spam folder.", "success");
   1703                 } else {
   1704                     // Sign in
   1705                     const cred = await auth.signInWithEmailAndPassword(email, pass);
   1706                     // Reload to check verification status handled in checkAuth
   1707                 }
   1708             } catch (err) {
   1709                 showToast(err.message, "error");
   1710             } finally {
   1711                 btn.disabled = false;
   1712                 btn.innerText = isSignUpMode ? "Register" : "Sign In";
   1713             }
   1714         }
   1715 
   1716         async function handleForgotPassword() {
   1717             const email = document.getElementById('auth-email').value;
   1718             if (!email) {
   1719                 showToast("Enter your email first.", "error");
   1720                 return;
   1721             }
   1722             try {
   1723                 await auth.sendPasswordResetEmail(email);
   1724                 showToast("Password reset link sent!", "success");
   1725             } catch (err) {
   1726                 showToast(err.message, "error");
   1727             }
   1728         }
   1729 
   1730         function signInWithGoogle() {
   1731             const provider = new firebase.auth.GoogleAuthProvider();
   1732             auth.signInWithPopup(provider).catch(e => {
   1733                 console.error(e);
   1734                 showToast("Sign in failed.", "error");
   1735             });
   1736         }
   1737         
   1738         function signInAsGuest() {
   1739             auth.signInAnonymously().catch(e => {
   1740                 console.error(e);
   1741                 showToast("Guest login failed.", "error");
   1742             });
   1743         }
   1744 
   1745         function signOutUser() {
   1746             auth.signOut().then(() => {
   1747                 localStorage.removeItem('ada_user_cached');
   1748                 location.reload();
   1749             });
   1750         }
   1751 
   1752         // ADDED: Skeleton Loader Generator
   1753         function renderSkeletonLoader() {
   1754              const list = document.getElementById('chat-history-list');
   1755              list.innerHTML = '';
   1756              for(let i=0; i<5; i++) {
   1757                  list.innerHTML += `
   1758                     <div class="flex items-center gap-3 p-2.5 rounded-full skeleton-shimmer opacity-50 mb-1">
   1759                         <div class="w-4 h-4 bg-gemini-surfaceHover rounded-full"></div>
   1760                         <div class="h-4 bg-gemini-surfaceHover rounded w-24"></div>
   1761                     </div>
   1762                  `;
   1763              }
   1764         }
   1765 
   1766         async function fetchChats() {
   1767             if (!state.user || state.user.isAnonymous) return;
   1768             try {
   1769                 // USE SKELETON LOADER
   1770                 renderSkeletonLoader();
   1771                 
   1772                 const token = await state.user.getIdToken();
   1773                 const res = await fetch(`${API_BASE_URL}/chats`, { headers: { 'Authorization': `Bearer ${token}` } });
   1774                 const data = await res.json();
   1775                 
   1776                 const list = document.getElementById('chat-history-list');
   1777                 list.innerHTML = '';
   1778                 
   1779                 if (data.chats && data.chats.length > 0) {
   1780                     data.chats.forEach(chat => {
   1781                         const div = document.createElement('div');
   1782                         const isActive = chat.id === state.currentChatId;
   1783                         div.className = `group relative p-2.5 rounded-full cursor-pointer text-sm flex items-center gap-3 transition-colors truncate ${isActive ? 'bg-[#004A77] text-white font-medium' : 'text-gemini-textSecondary hover:bg-gemini-surfaceHover hover:text-white'}`;
   1784                         div.onclick = () => loadChat(chat.id);
   1785                         
   1786                         let pressTimer;
   1787                         div.ontouchstart = (e) => {
   1788                              pressTimer = setTimeout(() => showChatContextMenu(e, chat.id, chat.title), 500);
   1789                         };
   1790                         div.ontouchend = () => clearTimeout(pressTimer);
   1791                         div.oncontextmenu = (e) => showChatContextMenu(e, chat.id, chat.title);
   1792 
   1793                         div.innerHTML = `
   1794                             <i data-lucide="message-square" class="w-4 h-4 flex-shrink-0"></i>
   1795                             <span class="truncate flex-1">${chat.title}</span>
   1796                             <button class="opacity-0 group-hover:opacity-100 p-1 hover:bg-white/10 rounded-full transition-opacity" onclick="showChatContextMenu(event, '${chat.id}', '${chat.title}')">
   1797                                 <i data-lucide="more-vertical" class="w-3 h-3"></i>
   1798                             </button>
   1799                         `;
   1800                         list.appendChild(div);
   1801                     });
   1802                 } else {
   1803                     list.innerHTML = `<div class="p-4 text-center text-xs text-gemini-textSecondary">No recent chats</div>`;
   1804                 }
   1805                 lucide.createIcons();
   1806             } catch (e) { console.error(e); }
   1807         }
   1808 
   1809         async function loadChat(chatId) {
   1810             if (state.isTyping) return;
   1811             state.currentChatId = chatId;
   1812             
   1813             // Skeleton Loading for Main Chat
   1814             const container = document.querySelector('#chat-container > div');
   1815             container.innerHTML = `
   1816                 <div class="flex flex-col space-y-6 p-4">
   1817                     <div class="flex justify-end"><div class="h-10 w-2/3 rounded-2xl skeleton-shimmer"></div></div>
   1818                     <div class="flex justify-start gap-4">
   1819                         <div class="w-8 h-8 rounded-full skeleton-shimmer flex-shrink-0"></div>
   1820                         <div class="h-24 w-3/4 rounded-2xl skeleton-shimmer"></div>
   1821                     </div>
   1822                     <div class="flex justify-end"><div class="h-10 w-1/2 rounded-2xl skeleton-shimmer"></div></div>
   1823                 </div>`;
   1824             
   1825             try {
   1826                 const token = await state.user.getIdToken();
   1827                 const res = await fetch(`${API_BASE_URL}/chats/${chatId}`, { headers: { 'Authorization': `Bearer ${token}` } });
   1828                 const data = await res.json();
   1829                 
   1830                 state.messages = [];
   1831                 container.innerHTML = '';
   1832 
   1833                 if (data.messages && data.messages.length > 0) {
   1834                     data.messages.forEach(msg => {
   1835                         const role = msg.role === 'model' ? 'ai' : 'user';
   1836                         state.messages.push({ role, content: msg.content });
   1837                         renderMessage(role, msg.content);
   1838                     });
   1839                 } else {
   1840                     container.innerHTML = `<div class="text-center p-8 text-gemini-textSecondary">Start conversation...</div>`;
   1841                 }
   1842                 
   1843                 // Only refresh history if NOT shared view AND NOT guest
   1844                 if(!state.isSharedView && state.user && !state.user.isAnonymous) fetchChats();
   1845             } catch (e) { 
   1846                 console.error(e); 
   1847                 container.innerHTML = `<div class="text-center text-red-400 p-4">Failed to load chat.</div>`;
   1848             }
   1849         }
   1850 
   1851         function setPrompt(text) {
   1852             const input = document.getElementById('user-input');
   1853             if(input) {
   1854                 input.value = text;
   1855                 input.focus();
   1856                 autoResize(input);
   1857             }
   1858         }
   1859 
   1860         function scrollToBottom() {
   1861             const container = document.getElementById('chat-container');
   1862             container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' });
   1863         }
   1864 
   1865         function renderMessage(role, content) {
   1866             const container = document.querySelector('#chat-container > div');
   1867             const welcome = document.getElementById('welcome-message');
   1868             if (welcome) welcome.remove();
   1869 
   1870             let wrapper = container.lastElementChild;
   1871             let bubble = null;
   1872             
   1873             if (role === 'ai' && wrapper && wrapper.dataset.role === 'ai' && state.isTyping) {
   1874                  bubble = wrapper.querySelector('.prose');
   1875             } else {
   1876                  wrapper = document.createElement('div');
   1877                  wrapper.className = `flex gap-4 w-full animate-fade-in ${role === 'user' ? 'justify-end' : 'justify-start group'}`;
   1878                  wrapper.dataset.role = role;
   1879                  
   1880                  if (role === 'user') {
   1881                      wrapper.innerHTML = `<div class="msg-user text-sm md:text-base">${content}</div>`;
   1882                  } else {
   1883                      wrapper.innerHTML = `
   1884                         <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center mt-1">
   1885                             <svg class="w-6 h-6 animate-spin-slow-entry"><use href="#icon-ada"></use></svg>
   1886                         </div>
   1887                         <div class="flex-1 min-w-0 py-1">
   1888                             <div class="prose prose-invert max-w-none text-sm md:text-base"></div>
   1889                         </div>
   1890                      `;
   1891                      bubble = wrapper.querySelector('.prose');
   1892                  }
   1893                  container.appendChild(wrapper);
   1894             }
   1895 
   1896             if (role === 'ai') {
   1897                 if(!bubble) bubble = wrapper.querySelector('.prose');
   1898                 
   1899                 const customTagRegex = /<<<CODE_START>>>([\s\S]*?)<<<CODE_END>>>/g;
   1900                 const markdownRegex = /```(\w*)([\s\S]*?)```/g;
   1901                 
   1902                 let processedContent = content;
   1903                 let extractedCode = "";
   1904                 let lang = "PLAINTEXT";
   1905 
   1906                 const cardReplacement = (code, language) => {
   1907                     extractedCode = code.trim();
   1908                     if(language) lang = language.toUpperCase();
   1909                     return `<div class="code-card group" onclick="toggleArtifactPanel()">
   1910                                 <div class="px-4 py-3 bg-[#252526] border-b border-[#333] flex items-center justify-between">
   1911                                     <div class="flex items-center gap-2">
   1912                                         <i data-lucide="code-2" class="w-4 h-4 text-gemini-blue"></i>
   1913                                         <span class="text-xs font-mono text-[#cccccc]">Generated Code</span>
   1914                                     </div>
   1915                                     <span class="text-xs text-gemini-blue group-hover:underline">View Code &rarr;</span>
   1916                                 </div>
   1917                                 <div class="px-4 py-3 text-xs font-mono text-gray-400 bg-[#1e1e1e]">
   1918                                     // Code extracted to workspace...
   1919                                 </div>
   1920                             </div>`;
   1921                 };
   1922 
   1923                 processedContent = processedContent.replace(customTagRegex, (m, c) => cardReplacement(c));
   1924                 processedContent = processedContent.replace(markdownRegex, (m, l, c) => cardReplacement(c, l));
   1925 
   1926                 try {
   1927                     bubble.innerHTML = marked.parse(processedContent);
   1928                 } catch (e) {
   1929                     bubble.innerText = content;
   1930                 }
   1931 
   1932                 if (extractedCode) {
   1933                     updateArtifactPanel(extractedCode, lang);
   1934                     const indicator = document.getElementById('artifact-indicator');
   1935                     if(indicator) indicator.classList.remove('hidden');
   1936                     
   1937                     if (window.innerWidth >= 1280) {
   1938                         const panel = document.getElementById('artifact-panel');
   1939                         if (panel.classList.contains('translate-x-full')) {
   1940                             toggleArtifactPanel();
   1941                         }
   1942                     }
   1943                 }
   1944             }
   1945 
   1946             scrollToBottom();
   1947             lucide.createIcons();
   1948         }
   1949 
   1950         function renderTypingIndicator() {
   1951             const container = document.querySelector('#chat-container > div');
   1952             const wrapper = document.createElement('div');
   1953             wrapper.id = 'typing-indicator';
   1954             wrapper.className = 'flex gap-4 w-full justify-start animate-fade-in';
   1955             wrapper.innerHTML = `
   1956                 <div class="flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center mt-1">
   1957                     <svg class="w-6 h-6 animate-pulse"><use href="#icon-ada"></use></svg>
   1958                 </div>
   1959                 <div class="py-3">
   1960                     <div class="flex gap-1">
   1961                         <div class="typing-dot"></div>
   1962                         <div class="typing-dot"></div>
   1963                         <div class="typing-dot"></div>
   1964                     </div>
   1965                 </div>
   1966             `;
   1967             container.appendChild(wrapper);
   1968             scrollToBottom();
   1969             lucide.createIcons();
   1970         }
   1971 
   1972         function removeTypingIndicator() {
   1973             const el = document.getElementById('typing-indicator');
   1974             if (el) el.remove();
   1975         }
   1976 
   1977         function updateArtifactPanel(code, lang) {
   1978             const langDisplay = document.getElementById('lang-display');
   1979             const statusLang = document.getElementById('status-lang'); // Update status bar
   1980             if(lang) {
   1981                 langDisplay.innerText = lang;
   1982                 statusLang.innerText = lang; // Sync status bar
   1983                 const modeMap = {
   1984                     'PYTHON': 'python',
   1985                     'JAVASCRIPT': 'javascript',
   1986                     'JS': 'javascript',
   1987                     'HTML': 'xml',
   1988                     'CSS': 'css'
   1989                 };
   1990                 if(editor) editor.setOption("mode", modeMap[lang] || "javascript");
   1991             }
   1992             
   1993             if(editor) {
   1994                 editor.setValue(code);
   1995                 setTimeout(() => editor.refresh(), 100);
   1996             }
   1997         }
   1998         
   1999         function copyArtifact() {
   2000             if(editor) {
   2001                 const content = editor.getValue();
   2002                 navigator.clipboard.writeText(content);
   2003                 showToast("Code copied to clipboard!", "success");
   2004             }
   2005         }
   2006 
   2007         function handleEnter(e) {
   2008             if (e.key === 'Enter' && !e.shiftKey) {
   2009                 e.preventDefault();
   2010                 handleFormSubmit(e);
   2011             }
   2012         }
   2013 
   2014         async function handleFormSubmit(e) {
   2015             if (e) e.preventDefault();
   2016             const input = document.getElementById('user-input');
   2017             const message = input.value.trim();
   2018             if (!message || state.isTyping || !state.user) return;
   2019 
   2020             // UI Updates
   2021             renderMessage('user', message);
   2022             input.value = '';
   2023             autoResize(input);
   2024             state.isTyping = true;
   2025             renderTypingIndicator();
   2026             
   2027             try {
   2028                 const token = await state.user.getIdToken();
   2029                 const response = await fetch(`${API_BASE_URL}/chat`, {
   2030                     method: 'POST',
   2031                     headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
   2032                     body: JSON.stringify({ 
   2033                         message: message, 
   2034                         history: state.messages.map(m => ({ user: m.role === 'user' ? m.content : '', model: m.role === 'ai' ? m.content : '' })),
   2035                         sessionId: state.currentChatId
   2036                     })
   2037                 });
   2038 
   2039                 if (!response.ok) throw new Error("API Error");
   2040 
   2041                 removeTypingIndicator();
   2042                 const reader = response.body.getReader();
   2043                 const decoder = new TextDecoder();
   2044                 let fullText = "";
   2045                 renderMessage('ai', '');
   2046 
   2047                 while (true) {
   2048                     const { done, value } = await reader.read();
   2049                     if (done) break;
   2050                     fullText += decoder.decode(value);
   2051                     renderMessage('ai', fullText);
   2052                 }
   2053 
   2054                 state.messages.push({ role: 'user', content: message });
   2055                 state.messages.push({ role: 'ai', content: fullText });
   2056                 
   2057                 // Only refresh history if not guest
   2058                 if (!state.user.isAnonymous) {
   2059                     setTimeout(fetchChats, 1500);
   2060                 }
   2061 
   2062             } catch (error) {
   2063                 removeTypingIndicator();
   2064                 renderMessage('ai', "I'm having trouble connecting right now.");
   2065                 showToast("Error generating response", "error");
   2066             } finally {
   2067                 state.isTyping = false;
   2068             }
   2069         }
   2070         
   2071         function startNewChat() {
   2072             state.messages = [];
   2073             state.currentChatId = 'session_' + Date.now();
   2074             
   2075             const userName = (state.user && !state.user.isAnonymous) ? (state.user.email || state.user.displayName || 'Student') : 'Guest';
   2076             
   2077             const container = document.querySelector('#chat-container > div');
   2078             container.innerHTML = `
   2079                 <div id="welcome-message" class="flex flex-col items-start justify-center min-h-[50vh] space-y-8 animate-slide-up px-2">
   2080                     <div class="space-y-2 w-full">
   2081                         <div class="w-12 h-12 mb-4 animate-spin-slow-entry">
   2082                             <svg class="w-full h-full drop-shadow-[0_0_15px_rgba(168,199,250,0.5)]"><use href="#icon-ada"></use></svg>
   2083                         </div>
   2084                         <h1 class="text-4xl md:text-5xl font-medium text-transparent bg-clip-text bg-gradient-to-r from-[#4285F4] via-[#9B72CB] to-[#D96570] pb-2">
   2085                             Hello, <span id="welcome-name" class="text-white truncate block md:inline max-w-[200px] md:max-w-none">${userName}</span>
   2086                         </h1>
   2087                         <!-- UPDATED COLOR -->
   2088                         <h2 class="text-3xl md:text-5xl font-medium text-gemini-textSecondary/5">How can I help you code today?</h2>
   2089                     </div>
   2090                     <div class="hidden md:flex flex-wrap gap-3 w-full">
   2091                         <button onclick="setPrompt('Debug this Python script')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
   2092                             <span class="block mb-1 text-gemini-blue group-hover:translate-x-1 transition-transform"><i data-lucide="bug" class="w-4 h-4 inline mr-1"></i> Debug</span>
   2093                         </button>
   2094                         <button onclick="setPrompt('Explain this concept')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
   2095                             <span class="block mb-1 text-gemini-purple group-hover:translate-x-1 transition-transform"><i data-lucide="book-open" class="w-4 h-4 inline mr-1"></i> Explain</span>
   2096                         </button>
   2097                         <button onclick="setPrompt('Refactor this function')" class="group bg-gemini-surface hover:bg-gemini-surfaceHover text-gemini-text px-5 py-4 rounded-2xl text-sm font-medium transition-all text-left flex-1 min-w-[200px] border border-transparent hover:border-gemini-surfaceHover">
   2098                             <span class="block mb-1 text-green-400 group-hover:translate-x-1 transition-transform"><i data-lucide="wand-2" class="w-4 h-4 inline mr-1"></i> Refactor</span>
   2099                         </button>
   2100                     </div>
   2101                 </div>`;
   2102             lucide.createIcons();
   2103             if (state.user && !state.user.isAnonymous) fetchChats();
   2104         }
   2105 
   2106         window.onload = initApp;
   2107 
   2108     </script>
   2109 </body>
   2110 </html>
© notamitgamer • Site Built: 2026-07-21 13:58:23 UTC • git-mirror commit: 1037f62 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror