/** * Vibhu Solutions AI Chat Widget * Embed on any website with: * */ (function () { if (document.getElementById('vs-cb-root')) return; // prevent double-load const API_URL = 'https://sanjay8013-ai-robot.hf.space/chat'; // ── Bot SVG (blinking robot character) ─────────────────────────────────────── const BOT_SVG = (w, h) => ``; // ── CSS ────────────────────────────────────────────────────────────────────── // Inject Manrope font if (!document.getElementById('vs-cb-manrope')) { const lnk = document.createElement('link'); lnk.id = 'vs-cb-manrope'; lnk.rel = 'stylesheet'; lnk.href = 'https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap'; document.head.appendChild(lnk); } const style = document.createElement('style'); style.textContent = ` #vs-cb-overlay { position:fixed; inset:0; background:rgba(0,4,12,0.82); backdrop-filter:blur(14px); display:flex; align-items:center; justify-content:center; z-index:2147483640; font-family:'Manrope','Segoe UI',Tahoma,sans-serif; } #vs-cb-card { background:rgba(4,14,31,0.93); backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px); border:1px solid rgba(107,166,255,0.22); border-radius:24px; padding:40px 34px 32px; width:100%; max-width:400px; margin:16px; box-shadow:0 32px 80px rgba(0,0,0,0.8),0 0 60px rgba(0,66,200,0.18); animation:vsCbSlide 0.32s ease; } @keyframes vsCbSlide { from{opacity:0;transform:translateY(22px);} to {opacity:1;transform:translateY(0);} } .vs-logo { width:72px;height:72px; background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); border-radius:18px;display:flex;align-items:center;justify-content:center; margin:0 auto 18px; box-shadow:0 10px 26px rgba(0,102,255,0.45); } #vs-cb-card h2 { text-align:center;color:white;font-size:20px;font-weight:700; margin-bottom:6px;font-family:'Manrope','Segoe UI',sans-serif; } .vs-subtitle { text-align:center;color:rgba(255,255,255,0.55);font-size:13px; margin-bottom:22px;line-height:1.6; } .vs-field{margin-bottom:13px;} .vs-field label{ display:block;font-size:12.5px;font-weight:600; color:rgba(255,255,255,0.78);margin-bottom:6px;font-family:'Manrope','Segoe UI',sans-serif; } .vs-field input{ width:100%;border:1.5px solid rgba(107,166,255,0.22);border-radius:9px; padding:11px 14px;font-size:13.5px;color:white;outline:none; background:rgba(255,255,255,0.07);box-sizing:border-box; transition:border-color 0.2s,box-shadow 0.2s,background 0.2s; font-family:'Manrope','Segoe UI',sans-serif; } .vs-field input::placeholder{color:rgba(255,255,255,0.3);} .vs-field input:focus{ border-color:#6BA6FF; box-shadow:0 0 0 3px rgba(0,102,255,0.18); background:rgba(107,166,255,0.1); } .vs-field input.vs-err{border-color:#ef4444;} #vs-cb-login-btn{ width:100%;padding:13px;margin-top:4px; background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); color:white;border:none;border-radius:9px; font-size:14px;font-weight:600;cursor:pointer; letter-spacing:0.3px;transition:opacity 0.2s; font-family:'Manrope','Segoe UI',sans-serif; box-shadow:0 6px 20px rgba(0,102,255,0.45); } #vs-cb-login-btn:hover{opacity:0.9;} .vs-privacy{text-align:center;font-size:11px;color:rgba(255,255,255,0.35);margin-top:12px;} #vs-cb-toggle{ position:fixed;bottom:20px;right:20px; width:48px;height:48px;border-radius:50%;overflow:visible; background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); border:none;cursor:pointer;color:white; box-shadow:0 4px 18px rgba(0,102,255,0.55),0 0 14px rgba(0,102,255,0.3); z-index:2147483638; display:none;align-items:center;justify-content:center; } #vs-cb-widget{ display:none;flex-direction:column; position:fixed;bottom:78px;right:20px; width:310px;height:460px; background:#04111e; border:1px solid rgba(107,166,255,0.2); border-radius:16px; box-shadow:0 12px 48px rgba(0,0,0,0.7),0 0 30px rgba(0,66,200,0.15); z-index:2147483637;overflow:hidden; font-family:'Manrope','Segoe UI',Tahoma,sans-serif; animation:vsCbPop 0.24s ease; } @keyframes vsCbPop{ from{opacity:0;transform:scale(0.95) translateY(10px);} to {opacity:1;transform:scale(1) translateY(0);} } #vs-cb-header{ background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); color:white;padding:10px 12px; display:flex;align-items:center;gap:8px;flex-shrink:0; } .vs-avatar{ width:30px;height:30px;background:rgba(255,255,255,0.22); border-radius:50%;display:flex;align-items:center; justify-content:center;flex-shrink:0; } .vs-hinfo h3{font-size:12px;font-weight:700;margin:0;} .vs-hinfo p {font-size:10px;opacity:0.82;margin:1px 0 0;} #vs-cb-utag{ font-size:11px;background:rgba(255,255,255,0.2); border-radius:12px;padding:3px 10px;margin-left:auto; white-space:nowrap;max-width:105px; overflow:hidden;text-overflow:ellipsis; } #vs-cb-dot{ width:9px;height:9px;background:#4ade80; border-radius:50%;flex-shrink:0; animation:vsPulse 2s infinite; } @keyframes vsPulse{ 0% {box-shadow:0 0 0 0 rgba(74,222,128,0.5);} 70% {box-shadow:0 0 0 7px rgba(74,222,128,0);} 100%{box-shadow:0 0 0 0 rgba(74,222,128,0);} } #vs-cb-msgs{ flex:1;overflow-y:auto;padding:10px; display:flex;flex-direction:column;gap:8px; background:#030c1a;scroll-behavior:smooth; } #vs-cb-msgs::-webkit-scrollbar{width:4px;} #vs-cb-msgs::-webkit-scrollbar-thumb{background:rgba(107,166,255,0.3);border-radius:2px;} .vs-wrap{display:flex;flex-direction:column;} .vs-wrap.user{align-items:flex-end;} .vs-wrap.bot{flex-direction:row;align-items:flex-end;gap:8px;} .vs-wrap.bot .vs-msg-col{display:flex;flex-direction:column;align-items:flex-start;} .vs-bot-mini{ width:22px;height:22px;flex-shrink:0;border-radius:50%; background:linear-gradient(107.8deg,#6BA6FF 3.37%,#0066FF 95.93%); display:flex;align-items:center;justify-content:center;align-self:flex-end; box-shadow:0 2px 6px rgba(0,102,255,0.4); } .vs-msg{ max-width:86%;padding:8px 11px;border-radius:12px; font-size:12px;line-height:1.55; animation:vsFade 0.2s ease; } @keyframes vsFade{ from{opacity:0;transform:translateY(5px);} to {opacity:1;transform:none;} } .vs-msg.bot{ background:rgba(255,255,255,0.07);color:#d0e8ff; border:1px solid rgba(107,166,255,0.12); border-bottom-left-radius:4px; } .vs-msg.bot a{color:#6BA6FF;text-decoration:none;font-weight:500;} .vs-msg.bot a:hover{text-decoration:underline;} .vs-msg.user{ background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); color:white;border-bottom-right-radius:4px; } .vs-time{font-size:10.5px;color:rgba(255,255,255,0.3);margin-top:4px;padding:0 4px;} .vs-msg.typing{ background:rgba(255,255,255,0.07); border:1px solid rgba(107,166,255,0.12); border-bottom-left-radius:4px; padding:13px 16px; } .vs-dots{display:flex;gap:5px;align-items:center;} .vs-dots span{ width:7px;height:7px;background:rgba(107,166,255,0.7);border-radius:50%; animation:vsDot 1.3s infinite ease-in-out; } .vs-dots span:nth-child(2){animation-delay:0.18s;} .vs-dots span:nth-child(3){animation-delay:0.36s;} @keyframes vsDot{ 0%,60%,100%{transform:translateY(0);} 30% {transform:translateY(-8px);} } #vs-cb-quick{ display:flex;flex-wrap:wrap;gap:4px; padding:0 10px 7px;background:#030c1a;flex-shrink:0; } .vs-qbtn{ background:rgba(0,102,255,0.12);border:1px solid rgba(107,166,255,0.35);color:#6BA6FF; border-radius:14px;padding:3px 10px;font-size:10.5px; cursor:pointer;transition:all 0.18s;white-space:nowrap; font-family:'Manrope','Segoe UI',sans-serif; } .vs-qbtn:hover{background:#0066FF;color:white;border-color:#0066FF;} #vs-cb-inputarea{ display:flex;padding:7px 9px;gap:6px; border-top:1px solid rgba(107,166,255,0.15);background:#04111e;flex-shrink:0; } #vs-cb-input{ flex:1;border:1px solid rgba(107,166,255,0.2);border-radius:18px; padding:7px 12px;font-size:12px;outline:none;color:white; background:rgba(255,255,255,0.06); transition:border-color 0.2s,background 0.2s;resize:none;max-height:60px; font-family:'Manrope','Segoe UI',sans-serif; } #vs-cb-input::placeholder{color:rgba(255,255,255,0.3);} #vs-cb-input:focus{border-color:#6BA6FF;background:rgba(107,166,255,0.08);} #vs-cb-send{ width:30px;height:30px;flex-shrink:0; background:linear-gradient(107.8deg, #6BA6FF 3.37%, #0066FF 95.93%); border:none;border-radius:50%;cursor:pointer; color:white;font-size:13px; display:flex;align-items:center;justify-content:center; transition:opacity 0.2s; box-shadow:0 3px 10px rgba(0,102,255,0.4); } #vs-cb-send:hover{opacity:0.88;} #vs-cb-send:disabled{opacity:0.4;cursor:not-allowed;} /* ── Bot Animations ─────────────────────────────────────────────── */ .vs-bot-eye{ transform-box:fill-box;transform-origin:50% 50%; animation:vsBotBlink 4.8s ease-in-out infinite; } .vs-bot-eye-r{animation-delay:0.12s;} @keyframes vsBotBlink{ 0%,82%,100%{transform:scaleY(1);} 84%{transform:scaleY(0.18);} 86%{transform:scaleY(1);} 88%{transform:scaleY(0.08);} 90%{transform:scaleY(1);} } .vs-bot-ant{ transform-box:fill-box;transform-origin:50% 50%; animation:vsAntGlow 2.4s ease-in-out infinite; } @keyframes vsAntGlow{ 0%,100%{opacity:0.4;transform:scale(0.8);filter:drop-shadow(0 0 2px rgba(255,255,255,0.4));} 45%{opacity:1;transform:scale(1.15);filter:drop-shadow(0 0 5px white);} 70%{opacity:0.65;transform:scale(0.9);filter:drop-shadow(0 0 3px rgba(255,255,255,0.55));} } #vs-cb-toggle{animation:vsBotFloat 2s ease-in-out infinite;} #vs-cb-toggle:hover{animation:none;transform:scale(1.12);} @keyframes vsBotFloat{ 0%,100%{transform:translateY(0);} 50%{transform:translateY(-8px);} } #vs-cb-toggle::after{ content:'';position:absolute;inset:-4px;border-radius:50%; border:2px solid rgba(107,166,255,0.6); animation:vsRingPulse 1.2s ease-out infinite; } #vs-cb-toggle::before{ content:'';position:absolute;inset:-10px;border-radius:50%; border:1.5px solid rgba(107,166,255,0.25); animation:vsRingPulse 1.2s ease-out infinite 0.4s; } @keyframes vsRingPulse{ 0%{transform:scale(1);opacity:0.8;} 100%{transform:scale(1.35);opacity:0;} } @media(max-width:480px){ #vs-cb-widget{ bottom:0;right:0;left:0; width:100%;height:100%;border-radius:0; } #vs-cb-toggle{bottom:16px;right:16px;} } `; document.head.appendChild(style); // ── HTML ───────────────────────────────────────────────────────────────────── const root = document.createElement('div'); root.id = 'vs-cb-root'; root.innerHTML = `

Vibhu Solutions AI

Enter your details to chat with our
intelligent business AI assistant

🔒 Your information is kept private and secure.

${BOT_SVG(20,23)}

Vibhu Solutions AI

Ask me about our services

`; document.body.appendChild(root); // ── State ──────────────────────────────────────────────────────────────────── let cbOpen = false, cbTypingEl = null, cbUser = null; // ── Format bot message (clickable links / emails / phones) ─────────────────── function formatMsg(text) { let h = text .replace(/&/g,'&').replace(//g,'>'); h = h.replace(/\*\*([^*\n]+)\*\*/g, '$1'); h = h.replace(/(https?:\/\/[^\s&<]+)/g, '$1'); h = h.replace(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g, '$1'); h = h.replace(/(\+91[\s]?[0-9]{10})/g, '$1'); h = h.replace(/\n/g,'
'); return h; } // ── Add message ────────────────────────────────────────────────────────────── function addMsg(content, type, isHTML) { const msgs = document.getElementById('vs-cb-msgs'); const wrap = document.createElement('div'); wrap.className = 'vs-wrap ' + type; if (type === 'bot') { const mini = document.createElement('div'); mini.className = 'vs-bot-mini'; mini.innerHTML = BOT_SVG(14, 16); wrap.appendChild(mini); const col = document.createElement('div'); col.className = 'vs-msg-col'; const div = document.createElement('div'); div.className = 'vs-msg bot'; if (isHTML) div.innerHTML = content; else div.textContent = content; col.appendChild(div); const t = document.createElement('span'); t.className = 'vs-time'; t.textContent = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); col.appendChild(t); wrap.appendChild(col); } else { const div = document.createElement('div'); div.className = 'vs-msg ' + type; if (isHTML) div.innerHTML = content; else div.textContent = content; wrap.appendChild(div); const t = document.createElement('span'); t.className = 'vs-time'; t.textContent = new Date().toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); wrap.appendChild(t); } msgs.appendChild(wrap); msgs.scrollTop = msgs.scrollHeight; return wrap; } // ── Animated typing dots ───────────────────────────────────────────────────── function showTyping() { const msgs = document.getElementById('vs-cb-msgs'); const wrap = document.createElement('div'); wrap.className = 'vs-wrap bot'; const mini = document.createElement('div'); mini.className = 'vs-bot-mini'; mini.innerHTML = BOT_SVG(18, 20); wrap.appendChild(mini); const col = document.createElement('div'); col.className = 'vs-msg-col'; const div = document.createElement('div'); div.className = 'vs-msg typing'; div.innerHTML = '
'; col.appendChild(div); wrap.appendChild(col); msgs.appendChild(wrap); msgs.scrollTop = msgs.scrollHeight; cbTypingEl = wrap; } function hideTyping() { if (cbTypingEl) { cbTypingEl.remove(); cbTypingEl = null; } } // ── Login ──────────────────────────────────────────────────────────────────── function doLogin() { const nameEl = document.getElementById('vs-ln'); const emailEl = document.getElementById('vs-le'); const name = nameEl.value.trim(); const email = emailEl.value.trim(); const phone = document.getElementById('vs-lp').value.trim(); nameEl.classList.remove('vs-err'); emailEl.classList.remove('vs-err'); let ok = true; if (!name) { nameEl.classList.add('vs-err'); nameEl.focus(); ok = false; } if (!email || !email.includes('@')) { emailEl.classList.add('vs-err'); if (ok) emailEl.focus(); ok = false; } if (!ok) return; cbUser = { name, email, phone, session_id: 'vs_' + Date.now() + '_' + Math.random().toString(36).slice(2,8) }; try { localStorage.setItem('vs_cb_user', JSON.stringify(cbUser)); } catch(_){} document.getElementById('vs-cb-overlay').style.display = 'none'; document.getElementById('vs-cb-toggle').style.display = 'flex'; cbToggle(); } // ── Restore session ────────────────────────────────────────────────────────── try { const saved = localStorage.getItem('vs_cb_user'); if (saved) { cbUser = JSON.parse(saved); document.getElementById('vs-cb-overlay').style.display = 'none'; document.getElementById('vs-cb-toggle').style.display = 'flex'; } } catch(_) {} // ── Toggle widget ──────────────────────────────────────────────────────────── function cbToggle() { cbOpen = !cbOpen; const w = document.getElementById('vs-cb-widget'); const btn = document.getElementById('vs-cb-toggle'); w.style.display = cbOpen ? 'flex' : 'none'; btn.innerHTML = cbOpen ? '✕' : BOT_SVG(26, 29); if (cbUser) document.getElementById('vs-cb-utag').textContent = '👤 ' + cbUser.name.split(' ')[0]; if (cbOpen && document.getElementById('vs-cb-msgs').children.length === 0) { const fn = cbUser ? cbUser.name.split(' ')[0] : ''; const greeting = fn ? `Hi ${fn}! 👋 Welcome to Vibhu Solutions.\n\nI'm your AI assistant. I can help you with:\n• Our services & technologies\n• How to start a project\n• Our process & timelines\n• How to contact our team\n\nWhat can I help you with today?` : `Hello! 👋 Welcome to Vibhu Solutions.\n\nAsk me about our services or how to get started!`; addMsg(greeting, 'bot', false); } if (cbOpen) document.getElementById('vs-cb-input').focus(); } // ── API call with timeout ──────────────────────────────────────────────────── async function callAPI(payload, ms) { const ctrl = new AbortController(); const timer = setTimeout(() => ctrl.abort(), ms); try { const r = await fetch(API_URL, { method:'POST', signal:ctrl.signal, headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload), }); return await r.json(); } finally { clearTimeout(timer); } } // ── Send message ───────────────────────────────────────────────────────────── async function cbSend() { const input = document.getElementById('vs-cb-input'); const send = document.getElementById('vs-cb-send'); const msg = input.value.trim(); if (!msg) return; addMsg(msg, 'user', false); input.value = ''; input.style.height = ''; input.disabled = true; send.disabled = true; showTyping(); document.getElementById('vs-cb-quick').style.display = 'none'; const payload = { message: msg, session_id: cbUser ? cbUser.session_id : 'guest_' + Date.now(), user_name: cbUser ? cbUser.name : '', user_email: cbUser ? cbUser.email : '', user_phone: cbUser ? cbUser.phone : '', }; try { const data = await callAPI(payload, 30000); hideTyping(); addMsg(formatMsg(data.reply || 'Sorry, something went wrong.'), 'bot', true); } catch(_) { hideTyping(); cbTypingEl = addMsg('Please wait, connecting…', 'bot', false); await new Promise(r => setTimeout(r, 3000)); hideTyping(); try { const data = await callAPI(payload, 60000); hideTyping(); addMsg(formatMsg(data.reply || 'Sorry, something went wrong.'), 'bot', true); } catch(_) { hideTyping(); addMsg('Unable to reach assistant.\n\n📧 contact@vibhusolutions.com\n📞 +91 9380345108', 'bot', false); } } finally { input.disabled = false; send.disabled = false; input.focus(); } } // ── Event listeners ────────────────────────────────────────────────────────── document.getElementById('vs-cb-login-btn').addEventListener('click', doLogin); document.getElementById('vs-ln').addEventListener('keypress', e => { if (e.key==='Enter') doLogin(); }); document.getElementById('vs-cb-toggle').addEventListener('click', cbToggle); document.getElementById('vs-cb-send').addEventListener('click', cbSend); document.getElementById('vs-cb-input').addEventListener('keydown', e => { if (e.key==='Enter' && !e.shiftKey) { e.preventDefault(); cbSend(); } }); document.getElementById('vs-cb-input').addEventListener('input', function() { this.style.height = ''; this.style.height = Math.min(this.scrollHeight, 72) + 'px'; }); document.querySelectorAll('.vs-qbtn').forEach(btn => { btn.addEventListener('click', () => { document.getElementById('vs-cb-input').value = btn.dataset.msg; cbSend(); }); }); })();