ada-web

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

indexbackup_20-01-2026_02.html (92526B)


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