{"id":184,"date":"2026-05-28T14:36:01","date_gmt":"2026-05-28T14:36:01","guid":{"rendered":"https:\/\/news.orghub.in\/?page_id=184"},"modified":"2026-05-28T18:03:20","modified_gmt":"2026-05-28T18:03:20","slug":"live-chat","status":"publish","type":"page","link":"https:\/\/news.orghub.in\/index.php\/live-chat\/","title":{"rendered":"LIVE CHAT"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no\">\n<title>Connect 1-to-1<\/title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}\n:root{--bg:#0f0f13;--s1:#18181f;--s2:#22222c;--s3:#2e2e3a;--bd:rgba(255,255,255,.09);--bd2:rgba(255,255,255,.17);--tx:#eeeef5;--mt:#8888a0;--bl:#4f6ef7;--gr:#22c55e;--rd:#ef4444;--ff:system-ui,-apple-system,sans-serif}\nhtml,body{height:100%;background:var(--bg);color:var(--tx);font-family:var(--ff);overflow:hidden}\n#P{height:100vh;display:flex;align-items:center;justify-content:center;padding:16px;overflow-y:auto}\n.card{background:var(--s1);border:1.5px solid var(--bd2);border-radius:18px;padding:26px 20px;width:100%;max-width:400px}\nh1{font-size:22px;font-weight:700;background:linear-gradient(135deg,#4f6ef7,#a78bfa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;text-align:center;margin-bottom:4px}\n.sub{font-size:12px;color:var(--mt);text-align:center;margin-bottom:20px}\n.lbl{display:block;font-size:11px;font-weight:600;color:var(--mt);text-transform:uppercase;letter-spacing:.07em;margin-bottom:5px}\ninput[type=text]{width:100%;padding:12px 14px;background:var(--s2);border:1.5px solid var(--bd);border-radius:10px;color:var(--tx);font-size:15px;font-family:var(--ff);outline:none;margin-bottom:12px;-webkit-appearance:none}\ninput:focus{border-color:var(--bl)}\ninput::placeholder{color:var(--mt)}\n.btn{width:100%;padding:13px;border:none;border-radius:10px;font-size:15px;font-weight:600;cursor:pointer;font-family:var(--ff);display:flex;align-items:center;justify-content:center;gap:8px;touch-action:manipulation;transition:opacity .15s}\n.btn:active{opacity:.78}\n.bp{background:var(--bl);color:#fff;margin-bottom:8px}\n.bs{background:var(--s2);color:var(--tx);border:1.5px solid var(--bd2)}\n.or{display:flex;align-items:center;gap:10px;color:var(--mt);font-size:12px;margin:14px 0}\n.or::before,.or::after{content:'';flex:1;height:1px;background:var(--bd)}\n.note{margin-top:12px;padding:11px 13px;border-radius:9px;font-size:13px;line-height:1.5;display:none;word-break:break-word}\n.note.on{display:block}\n.info{background:rgba(79,110,247,.13);border:1.5px solid rgba(79,110,247,.3);color:#a5b4fc}\n.ok{background:rgba(34,197,94,.1);border:1.5px solid rgba(34,197,94,.3);color:#86efac}\n.err{background:rgba(239,68,68,.1);border:1.5px solid rgba(239,68,68,.3);color:#fca5a5}\n.codebox{background:var(--s2);border:2px solid var(--bl);border-radius:10px;padding:14px;text-align:center;font-size:28px;font-weight:700;letter-spacing:.2em;color:var(--bl);cursor:pointer;margin:10px 0 4px;display:none}\n.codebox:active{background:var(--s3)}\n.codehint{text-align:center;font-size:11px;color:var(--mt);margin-bottom:10px;display:none}\n.spin{display:inline-block;width:14px;height:14px;border:2.5px solid rgba(255,255,255,.25);border-top-color:#fff;border-radius:50%;animation:sp .7s linear infinite}\n@keyframes sp{to{transform:rotate(360deg)}}\n#A{height:100vh;display:none;flex-direction:column}\n#A.on{display:flex}\n.topbar{display:flex;align-items:center;gap:10px;padding:9px 13px;background:var(--s1);border-bottom:1px solid var(--bd);flex-shrink:0}\n.av{width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,var(--bl),#6c5ce7);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:13px;color:#fff;flex-shrink:0}\n.ti{flex:1;min-width:0}\n.tn{font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ts{font-size:11px;color:var(--gr);display:flex;align-items:center;gap:4px}\n.tsd{width:6px;height:6px;border-radius:50%;background:var(--gr);flex-shrink:0}\n.tbb{display:flex;gap:7px}\n.ibb{width:36px;height:36px;border-radius:50%;border:1px solid var(--bd);background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:19px;color:var(--tx);touch-action:manipulation}\n.ibb:active{background:var(--s2)}\n#VP{display:none;flex-direction:column;background:#000;flex-shrink:0}\n#VP.on{display:flex}\n.va{position:relative;overflow:hidden;background:#0a0a0a;height:52vh}\n#VP.fs .va{position:fixed!important;inset:0!important;height:100vh!important;z-index:500!important}\n#RV{width:100%;height:100%;object-fit:cover;display:block}\n#LV{position:absolute;bottom:10px;right:10px;width:88px;height:62px;object-fit:cover;border-radius:8px;border:2px solid rgba(255,255,255,.22);background:#222;z-index:5}\n.vt{position:absolute;top:10px;left:50%;transform:translateX(-50%);background:rgba(0,0,0,.6);color:#fff;padding:3px 12px;border-radius:20px;font-size:12px;font-weight:600;z-index:5;pointer-events:none}\n.nr{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:8px;background:#0a0a0a}\n.nr .bav{width:62px;height:62px;border-radius:50%;background:var(--s2);border:2px solid var(--bd2);display:flex;align-items:center;justify-content:center;font-size:23px;font-weight:700}\n.nr span{font-size:12px;color:var(--mt)}\n.fsx{display:none;position:fixed;top:12px;right:12px;z-index:510;background:rgba(0,0,0,.65);border:none;border-radius:50%;width:36px;height:36px;font-size:18px;cursor:pointer;color:#fff;align-items:center;justify-content:center}\n#VP.fs .fsx{display:flex}\n.vui{display:none;padding:26px 16px;align-items:center;justify-content:center;flex-direction:column;gap:10px;background:var(--bg)}\n#VP.voice .vui{display:flex}\n#VP.voice .va{display:none}\n.biga{width:80px;height:80px;border-radius:50%;background:linear-gradient(135deg,var(--bl),#6c5ce7);display:flex;align-items:center;justify-content:center;font-size:30px;font-weight:700;color:#fff;animation:pulse 2s infinite}\n@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(79,110,247,.4)}50%{box-shadow:0 0 0 18px rgba(79,110,247,0)}}\n.vnm{font-size:17px;font-weight:600}\n.vtm{font-size:13px;color:var(--mt)}\n.vc{padding:10px;display:flex;align-items:center;justify-content:center;gap:12px;background:rgba(0,0,0,.85);flex-shrink:0}\n#VP.fs .vc{position:fixed;bottom:0;left:0;right:0;z-index:510}\n.vb{width:46px;height:46px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:19px;touch-action:manipulation}\n.vb:active{opacity:.7}\n.vn{background:#333}.vo{background:var(--rd)}\n.ve{background:var(--rd);width:52px;height:52px;font-size:21px}\n#CP{display:flex;flex-direction:column;flex:1;min-height:0}\n.msgs{flex:1;overflow-y:auto;padding:10px 12px 4px;display:flex;flex-direction:column;gap:6px;-webkit-overflow-scrolling:touch}\n.msgs::-webkit-scrollbar{width:0}\n.sm{text-align:center;font-size:11px;color:var(--mt);padding:2px 0}\n.dl{align-self:center;font-size:11px;color:var(--mt);background:var(--s2);padding:2px 10px;border-radius:20px}\n.mg{display:flex;flex-direction:column;gap:2px;max-width:82%}\n.mg.me{align-self:flex-end;align-items:flex-end}\n.mn{font-size:11px;color:var(--mt);padding:0 3px}\n.mb{padding:8px 13px;border-radius:14px;font-size:14px;line-height:1.5;word-break:break-word}\n.mb.th{background:var(--s2);color:var(--tx);border-bottom-left-radius:3px}\n.mb.me{background:var(--bl);color:#fff;border-bottom-right-radius:3px}\n.mt2{font-size:10px;color:var(--mt);padding:0 3px}\n.tr{min-height:20px;display:flex;align-items:center;gap:6px;padding:2px 12px 3px;flex-shrink:0}\n.tr.on .td{display:flex}\n.td{display:none;gap:3px}\n.td span{width:5px;height:5px;border-radius:50%;background:var(--mt);animation:td 1.1s infinite}\n.td span:nth-child(2){animation-delay:.17s}.td span:nth-child(3){animation-delay:.34s}\n@keyframes td{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(-4px)}}\n.tl{font-size:11px;color:var(--mt)}\n.ir{padding:8px 10px;border-top:1px solid var(--bd);background:var(--s1);display:flex;gap:6px;align-items:flex-end;flex-shrink:0;position:relative}\n.etw{position:absolute;bottom:100%;left:0;right:0;background:var(--s1);border-top:1.5px solid var(--bd2);display:none;padding:10px 8px;z-index:30}\n.etw.on{display:block}\n.eg{display:grid;grid-template-columns:repeat(8,1fr);gap:3px}\n.eg button{background:none;border:none;font-size:22px;cursor:pointer;padding:5px;border-radius:6px;touch-action:manipulation;line-height:1}\n.eg button:active{background:var(--s3)}\n.ta{flex:1;padding:9px 13px;background:var(--s2);border:1.5px solid var(--bd);border-radius:18px;color:var(--tx);font-size:15px;font-family:var(--ff);resize:none;min-height:38px;max-height:90px;overflow-y:auto;outline:none;line-height:1.5;-webkit-appearance:none}\n.ta:focus{border-color:var(--bl)}\n.ta::placeholder{color:var(--mt)}\n.sb{width:38px;height:38px;border-radius:50%;background:var(--bl);border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:16px;flex-shrink:0;color:#fff;touch-action:manipulation}\n.sb:active{opacity:.8}\n.ia{background:none;border:none;font-size:20px;cursor:pointer;padding:4px;line-height:1;margin-bottom:2px;flex-shrink:0;color:var(--mt)}\n#INC{display:none;position:fixed;top:0;left:0;right:0;z-index:1000;background:#1a1a2e;border-bottom:1.5px solid var(--bd2);padding:16px;text-align:center;box-shadow:0 4px 24px rgba(0,0,0,.7)}\n#INC.on{display:block}\n#INC h3{font-size:14px;color:#fff;margin-bottom:3px}\n#INC p{font-size:12px;color:rgba(255,255,255,.5);margin-bottom:13px}\n.ab{display:flex;gap:10px;justify-content:center}\n.ab button{padding:10px 22px;border:none;border-radius:9px;font-size:14px;font-weight:600;cursor:pointer;touch-action:manipulation}\n.ac{background:var(--gr);color:#fff}.dc{background:var(--rd);color:#fff}\n#CAL{display:none;position:fixed;inset:0;background:rgba(0,0,0,.9);z-index:999;align-items:center;justify-content:center;flex-direction:column;gap:14px}\n#CAL.on{display:flex}\n.ra{width:88px;height:88px;border-radius:50%;background:linear-gradient(135deg,var(--bl),#6c5ce7);display:flex;align-items:center;justify-content:center;font-size:34px;font-weight:700;color:#fff;animation:rp 1.3s infinite}\n@keyframes rp{0%,100%{box-shadow:0 0 0 0 rgba(79,110,247,.5)}60%{box-shadow:0 0 0 24px rgba(79,110,247,0)}}\n#CAL p{font-size:17px;font-weight:600}\n#CAL small{color:rgba(255,255,255,.5);font-size:13px}\n.cc{margin-top:8px;padding:11px 30px;background:var(--rd);border:none;border-radius:10px;color:#fff;font-size:14px;font-weight:600;cursor:pointer;touch-action:manipulation}\n.fb{display:flex;align-items:center;gap:7px;padding:7px 10px;background:rgba(255,255,255,.07);border-radius:10px;cursor:pointer;max-width:200px}\n.fi{font-size:20px}.fn{font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:130px}.fsz{font-size:10px;color:var(--mt)}\n<\/style>\n<\/head>\n<body>\n\n<!-- SETUP -->\n<div id=\"P\">\n<div class=\"card\">\n  <h1>Connect 1\u2011to\u20111<\/h1>\n  <div class=\"sub\">Real-time chat &amp; video \u00b7 any device<\/div>\n  <span class=\"lbl\">Your name<\/span>\n  <input type=\"text\" id=\"NM\" placeholder=\"Enter your name\" maxlength=\"20\" autocomplete=\"off\"\/>\n  <button class=\"btn bp\" onclick=\"createRoom()\">\ud83c\udfe0 Create Room<\/button>\n  <div class=\"codebox\" id=\"CB\" onclick=\"copyCode()\"><\/div>\n  <div class=\"codehint\" id=\"CH\">\ud83d\udc46 Tap to copy \u00b7 Send to your friend<\/div>\n  <div class=\"or\">\u2014 or join \u2014<\/div>\n  <span class=\"lbl\">Room code from friend<\/span>\n  <input type=\"text\" id=\"JC\" placeholder=\"Enter 6-letter code\" maxlength=\"6\"\n    autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"characters\"\n    style=\"text-transform:uppercase;letter-spacing:.15em;font-size:20px;text-align:center\"\n    oninput=\"this.value=this.value.toUpperCase()\"\/>\n  <button class=\"btn bs\" style=\"margin-top:0\" onclick=\"joinRoom()\">\ud83d\udd17 Join Room<\/button>\n  <div class=\"note\" id=\"NT\"><\/div>\n<\/div>\n<\/div>\n\n<!-- INCOMING CALL -->\n<div id=\"INC\">\n  <h3>\ud83d\udcde Incoming Call<\/h3>\n  <p id=\"INCP\">Someone is calling&#8230;<\/p>\n  <div class=\"ab\">\n    <button class=\"ac\" onclick=\"answerCall()\">\u2705 Accept<\/button>\n    <button class=\"dc\" onclick=\"declineCall()\">\u274c Decline<\/button>\n  <\/div>\n<\/div>\n\n<!-- CALLING OVERLAY -->\n<div id=\"CAL\">\n  <div class=\"ra\" id=\"CALAV\"><\/div>\n  <p id=\"CALN\">Calling&#8230;<\/p>\n  <small id=\"CALT\">Video call<\/small>\n  <button class=\"cc\" onclick=\"cancelCall()\">Cancel<\/button>\n<\/div>\n\n<!-- MAIN APP -->\n<div id=\"A\">\n  <div class=\"topbar\">\n    <div class=\"av\" id=\"PAV\">?<\/div>\n    <div class=\"ti\">\n      <div class=\"tn\" id=\"PNM\">\u2014<\/div>\n      <div class=\"ts\"><span class=\"tsd\"><\/span>Online<\/div>\n    <\/div>\n    <div class=\"tbb\">\n      <button class=\"ibb\" onclick=\"startCall('voice')\" title=\"Voice call\">\ud83d\udcde<\/button>\n      <button class=\"ibb\" onclick=\"startCall('video')\" title=\"Video call\">\ud83d\udcf9<\/button>\n      <button class=\"ibb\" onclick=\"copyCode()\" title=\"Copy room code\">\ud83d\udd17<\/button>\n    <\/div>\n  <\/div>\n\n  <div style=\"display:flex;flex-direction:column;flex:1;overflow:hidden;min-height:0\">\n    <!-- VIDEO PANEL -->\n    <div id=\"VP\">\n      <div class=\"va\" id=\"VA\">\n        <div class=\"nr\" id=\"NR\">\n          <div class=\"bav\" id=\"RAV\">?<\/div>\n          <span>Video not started<\/span>\n        <\/div>\n        <video id=\"RV\" autoplay playsinline><\/video>\n        <video id=\"LV\" autoplay playsinline muted><\/video>\n        <div class=\"vt\" id=\"VT\">00:00<\/div>\n        <button class=\"fsx\" onclick=\"exitFS()\">\u2715<\/button>\n      <\/div>\n      <div class=\"vui\">\n        <div class=\"biga\" id=\"VAUX\"><\/div>\n        <div class=\"vnm\" id=\"VNM\"><\/div>\n        <div class=\"vtm\" id=\"VTMX\">00:00<\/div>\n      <\/div>\n      <div class=\"vc\">\n        <button class=\"vb vn\" id=\"MB\" onclick=\"toggleMic()\">\ud83c\udfa4<\/button>\n        <button class=\"vb vn\" id=\"CB2\" onclick=\"toggleCam()\">\ud83d\udcf7<\/button>\n        <button class=\"vb ve\" onclick=\"hangup()\">\ud83d\udcf5<\/button>\n      <\/div>\n    <\/div>\n\n    <!-- CHAT PANEL -->\n    <div id=\"CP\">\n      <div class=\"msgs\" id=\"MS\">\n        <div class=\"dl\">Today<\/div>\n        <div class=\"sm\">Waiting for friend to join&#8230;<\/div>\n      <\/div>\n      <div class=\"tr\" id=\"TR\">\n        <div class=\"td\"><span><\/span><span><\/span><span><\/span><\/div>\n        <span class=\"tl\" id=\"TL\">typing&#8230;<\/span>\n      <\/div>\n      <div class=\"ir\">\n        <div class=\"etw\" id=\"ETW\"><div class=\"eg\" id=\"EG\"><\/div><\/div>\n        <button class=\"ia\" onclick=\"toggleEmoji(event)\">\ud83d\ude0a<\/button>\n        <textarea class=\"ta\" id=\"TA\" placeholder=\"Type a message...\" rows=\"1\"><\/textarea>\n        <label class=\"ia\" style=\"cursor:pointer;margin-bottom:2px\">\n          <input type=\"file\" id=\"FI\" style=\"display:none\" onchange=\"sendFile(this)\"\/>\ud83d\udcce\n        <\/label>\n        <button class=\"sb\" onclick=\"sendMsg()\">\u27a4<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script type=\"module\">\nimport { initializeApp } from \"https:\/\/www.gstatic.com\/firebasejs\/10.12.2\/firebase-app.js\";\nimport { getDatabase, ref, set, get, onValue, push, remove, off, serverTimestamp }\n  from \"https:\/\/www.gstatic.com\/firebasejs\/10.12.2\/firebase-database.js\";\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  YOUR FIREBASE CONFIG\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nconst firebaseConfig = {\n  apiKey: \"AIzaSyAtz_OdA5_E5N1Qxhf9xqc2EEcUQb0TvCM\",\n  authDomain: \"relaxminds-c2f34.firebaseapp.com\",\n  databaseURL: \"https:\/\/relaxminds-c2f34-default-rtdb.asia-southeast1.firebasedatabase.app\",\n  projectId: \"relaxminds-c2f34\",\n  storageBucket: \"relaxminds-c2f34.firebasestorage.app\",\n  messagingSenderId: \"102747556634\",\n  appId: \"1:102747556634:web:e397f81b2bfb322a3a3aa3\"\n};\n\nconst app = initializeApp(firebaseConfig);\nconst db  = getDatabase(app);\n\n\/\/ \u2500\u2500 Shorthand DB helpers \u2500\u2500\nconst R   = path => ref(db, path);\nconst dbS = (path, val) => set(R(path), val);\nconst dbG = path => get(R(path)).then(s => s.val());\nconst dbP = (path, val) => push(R(path), val);\nconst dbD = path => remove(R(path));\nconst dbL = (path, cb) => { onValue(R(path), s => cb(s.val())); return () => off(R(path)); };\n\n\/\/ \u2500\u2500 Emojis \u2500\u2500\nconst EMOJIS = ['\ud83d\ude00','\ud83d\ude02','\ud83d\ude0d','\ud83e\udd70','\ud83d\ude0e','\ud83e\udd14','\ud83d\ude05','\ud83d\ude4f','\ud83d\udc4d','\u2764\ufe0f','\ud83d\udd25','\ud83c\udf89','\u2705','\ud83d\ude0a','\ud83e\udd23',\n  '\ud83d\udcaf','\ud83d\ude4c','\ud83d\udc4f','\ud83d\udcaa','\ud83e\udd79','\ud83d\ude2d','\ud83e\udd29','\ud83d\ude34','\ud83e\udd17','\ud83c\udfb5','\ud83c\udf1f','\ud83d\udc40','\ud83e\udee1','\ud83d\ude24','\ud83e\udd73'];\n\n\/\/ \u2500\u2500 State \u2500\u2500\nlet myName='', peerName='', myRoom='', myRole='';\nlet localStream=null, pendingCallType=null, callType='video';\nlet micMuted=false, camOff=false, timerInt=null, timerSec=0;\nlet typingTmr=null, isFS=false;\nlet unsubFns=[];\nlet seenMsgKeys=new Set();\n\n\/\/ \u2500\u2500 Helpers \u2500\u2500\nfunction ts(){const n=new Date();let h=n.getHours(),m=n.getMinutes(),a=h>=12?'PM':'AM';h=h%12||12;return h+':'+(m<10?'0':'')+m+' '+a}\nfunction esc(s){return(s||'').replace(\/&#038;\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\\n\/g,'<br>')}\nfunction note(msg,cls){const e=document.getElementById('NT');e.innerHTML=msg;e.className='note on '+cls}\nfunction sysMsg(t){const d=document.createElement('div');d.className='sm';d.textContent=t;MS().appendChild(d);scrollM()}\nfunction MS(){return document.getElementById('MS')}\nfunction scrollM(){const m=MS();m.scrollTop=m.scrollHeight}\nfunction sig(type,extra={}){dbS('rooms\/'+myRoom+'\/signal',{type,to:peerName,from:myName,...extra,ts:Date.now()})}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  CREATE ROOM\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nwindow.createRoom = async function(){\n  const n=document.getElementById('NM').value.trim();\n  if(!n){alert('Enter your name first');return}\n  myName=n; myRole='host';\n  myRoom=Math.random().toString(36).slice(2,8).toUpperCase();\n\n  note('<span class=\"spin\"><\/span> Creating room...','info');\n\n  try{\n    await dbS('rooms\/'+myRoom, {host:myName, status:'waiting', ts:Date.now()});\n  }catch(e){\n    note('\u274c Firebase error: '+e.message+'. Check database rules (set to test mode).','err');\n    return;\n  }\n\n  \/\/ Show code\n  const cb=document.getElementById('CB');\n  cb.textContent=myRoom; cb.style.display='block';\n  document.getElementById('CH').style.display='block';\n  document.getElementById('JC').value=myRoom;\n  note('\u2705 Room <b>'+myRoom+'<\/b> is ready!<br>Tap the code to copy it, then send to your friend.','ok');\n\n  \/\/ Listen for guest joining\n  const unsub=dbL('rooms\/'+myRoom+'\/guest', async data=>{\n    if(data && data.name && data.name!==myName){\n      peerName=data.name;\n      await dbS('rooms\/'+myRoom+'\/hostAck',{name:myName,ts:Date.now()});\n      enterApp();\n    }\n  });\n  unsubFns.push(unsub);\n};\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  JOIN ROOM\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nwindow.joinRoom = async function(){\n  const n=document.getElementById('NM').value.trim();\n  const c=document.getElementById('JC').value.trim().toUpperCase();\n  if(!n){alert('Enter your name first');return}\n  if(c.length<4){alert('Enter the 6-letter room code');return}\n  myName=n; myRole='guest'; myRoom=c;\n\n  note('<span class=\"spin\"><\/span> Looking for room '+c+'...','info');\n\n  let room;\n  try{\n    room=await dbG('rooms\/'+c);\n  }catch(e){\n    note('\u274c Firebase error: '+e.message,'err');return;\n  }\n\n  if(!room){\n    note('\u274c Room <b>'+c+'<\/b> not found.<br>Make sure your friend created the room first.','err');\n    return;\n  }\n\n  peerName=room.host;\n  note('<span class=\"spin\"><\/span> Connecting to '+peerName+'...','info');\n\n  \/\/ Tell host we joined\n  await dbS('rooms\/'+c+'\/guest',{name:myName,ts:Date.now()});\n\n  \/\/ Wait for host acknowledgement\n  let tries=0;\n  const iv=setInterval(async()=>{\n    tries++;\n    if(tries>25){\n      clearInterval(iv);\n      note('\u274c No response from host. Make sure they have the room open and their name entered.','err');\n      return;\n    }\n    const ack=await dbG('rooms\/'+c+'\/hostAck');\n    if(ack && ack.name){\n      clearInterval(iv);\n      peerName=ack.name;\n      enterApp();\n    }\n  },1500);\n};\n\n\/\/ \u2500\u2500 Copy code \u2500\u2500\nwindow.copyCode = function(){\n  if(!myRoom)return;\n  navigator.clipboard.writeText(myRoom)\n    .then(()=>{\n      const cb=document.getElementById('CB');\n      const p=cb.textContent; cb.textContent='Copied! \u2713';\n      setTimeout(()=>cb.textContent=p,1500);\n    })\n    .catch(()=>{ prompt('Your room code (copy this):', myRoom); });\n};\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  ENTER APP\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction enterApp(){\n  document.getElementById('P').style.display='none';\n  document.getElementById('A').classList.add('on');\n  const i=(peerName||'?').slice(0,2).toUpperCase();\n  ['PAV','RAV','CALAV','VAUX'].forEach(id=>document.getElementById(id).textContent=i);\n  document.getElementById('PNM').textContent=peerName;\n  document.getElementById('VNM').textContent=peerName;\n  document.getElementById('CALN').textContent='Calling '+peerName+'...';\n  document.getElementById('INCP').textContent=peerName+' is calling...';\n  MS().innerHTML='<div class=\"dl\">Today<\/div>';\n  sysMsg('Connected with '+peerName+' \ud83c\udf89');\n  buildEmojis();\n  listenMessages();\n  listenTyping();\n  listenSignals();\n  \/\/ Clean up old room data after connect\n  setTimeout(()=>dbD('rooms\/'+myRoom+'\/guest'),3000);\n}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  MESSAGES\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nfunction listenMessages(){\n  const unsub=dbL('rooms\/'+myRoom+'\/messages', data=>{\n    if(!data)return;\n    Object.entries(data).forEach(([k,m])=>{\n      if(seenMsgKeys.has(k))return;\n      seenMsgKeys.add(k);\n      if(m.from===myName)return; \/\/ already rendered\n      if(m.file) renderFileMsg(m,false);\n      else renderMsg(m,false);\n    });\n  });\n  unsubFns.push(unsub);\n}\n\nfunction listenTyping(){\n  const key='rooms\/'+myRoom+'\/typing_'+(myRole==='host'?'guest':'host');\n  const unsub=dbL(key, data=>{\n    if(data&&data.active&&(Date.now()-data.ts)<3500) showTyping();\n    else hideTyping();\n  });\n  unsubFns.push(unsub);\n}\n\nfunction listenSignals(){\n  const unsub=dbL('rooms\/'+myRoom+'\/signal', data=>{\n    if(!data||data.to!==myName)return;\n    if(data.type==='call_req'){\n      pendingCallType=data.callType||'video';\n      document.getElementById('INCP').textContent=peerName+' is calling ('+(pendingCallType==='voice'?'Voice \ud83d\udcde':'Video \ud83d\udcf9')+')...';\n      document.getElementById('INC').classList.add('on');\n    }\n    if(data.type==='call_dec'){\n      document.getElementById('CAL').classList.remove('on');\n      sysMsg('Call declined');\n      if(localStream){localStream.getTracks().forEach(t=>t.stop());localStream=null;}\n    }\n    if(data.type==='call_end'){ endCallUI(); sysMsg('Call ended by '+peerName); }\n  });\n  unsubFns.push(unsub);\n}\n\n\/\/ \u2500\u2500 Send message \u2500\u2500\nwindow.sendMsg = async function(){\n  const ta=document.getElementById('TA');\n  const txt=ta.value.trim(); if(!txt)return;\n  ta.value=''; ta.style.height='';\n  const msg={from:myName,text:txt,time:ts()};\n  renderMsg(msg,true);\n  await dbP('rooms\/'+myRoom+'\/messages', msg);\n  \/\/ stop typing\n  await dbS('rooms\/'+myRoom+'\/typing_'+myRole,{active:false,ts:Date.now()});\n};\n\nfunction renderMsg(m,own){\n  const g=document.createElement('div'); g.className='mg'+(own?' me':'');\n  g.innerHTML=`<div class=\"mn\">${own?'You':esc(m.from)}<\/div><div class=\"mb ${own?'me':'th'}\">${esc(m.text)}<\/div><div class=\"mt2\">${m.time}<\/div>`;\n  MS().appendChild(g); scrollM();\n}\n\nfunction showTyping(){document.getElementById('TL').textContent=peerName+' is typing...';document.getElementById('TR').classList.add('on')}\nfunction hideTyping(){document.getElementById('TR').classList.remove('on')}\n\nconst ta=document.getElementById('TA');\nta.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendMsg();}});\nta.addEventListener('input',async()=>{\n  ta.style.height='auto'; ta.style.height=Math.min(ta.scrollHeight,90)+'px';\n  if(!myRoom)return;\n  await dbS('rooms\/'+myRoom+'\/typing_'+myRole,{active:true,ts:Date.now()});\n  clearTimeout(typingTmr);\n  typingTmr=setTimeout(()=>dbS('rooms\/'+myRoom+'\/typing_'+myRole,{active:false,ts:Date.now()}),2500);\n});\n\n\/\/ \u2500\u2500 File share \u2500\u2500\nwindow.sendFile = function(inp){\n  const f=inp.files[0]; if(!f)return;\n  const r=new FileReader();\n  r.onload=async e=>{\n    const d={from:myName,file:true,name:f.name,size:f.size,mime:f.type,data:e.target.result,time:ts()};\n    renderFileMsg(d,true);\n    await dbP('rooms\/'+myRoom+'\/messages',d);\n  };\n  r.readAsDataURL(f); inp.value='';\n};\n\nfunction renderFileMsg(d,own){\n  const g=document.createElement('div'); g.className='mg'+(own?' me':'');\n  const sz=d.size>1048576?(d.size\/1048576).toFixed(1)+' MB':(d.size\/1024).toFixed(0)+' KB';\n  const ico=d.mime.startsWith('image')?'\ud83d\uddbc\ufe0f':d.mime.startsWith('video')?'\ud83c\udfac':d.mime.startsWith('audio')?'\ud83c\udfb5':'\ud83d\udcc4';\n  const fb=document.createElement('div'); fb.className='fb';\n  fb.innerHTML=`<span class=\"fi\">${ico}<\/span><div><div class=\"fn\">${esc(d.name)}<\/div><div class=\"fsz\">${sz}<\/div><\/div>`;\n  fb.onclick=()=>{const a=document.createElement('a');a.href=d.data;a.download=d.name;a.click()};\n  g.innerHTML=`<div class=\"mn\">${own?'You':esc(d.from)}<\/div>`;\n  g.appendChild(fb);\n  const tm=document.createElement('div'); tm.className='mt2'; tm.textContent=d.time||ts();\n  g.appendChild(tm); MS().appendChild(g); scrollM();\n}\n\n\/\/ \u2500\u2500 Emoji \u2500\u2500\nfunction buildEmojis(){\n  const g=document.getElementById('EG'); g.innerHTML='';\n  EMOJIS.forEach(e=>{\n    const b=document.createElement('button'); b.textContent=e;\n    b.onclick=()=>{document.getElementById('TA').value+=e;document.getElementById('ETW').classList.remove('on');};\n    g.appendChild(b);\n  });\n}\nwindow.toggleEmoji=function(ev){ev.stopPropagation();document.getElementById('ETW').classList.toggle('on');}\ndocument.addEventListener('click',()=>document.getElementById('ETW').classList.remove('on'));\n\n\/\/ \u2500\u2500 Fullscreen (double tap) \u2500\u2500\nlet lastTap=0;\ndocument.getElementById('VA').addEventListener('touchend',e=>{const n=Date.now();if(n-lastTap<350)toggleFS();lastTap=n;});\ndocument.getElementById('VA').addEventListener('dblclick',toggleFS);\nfunction toggleFS(){\n  isFS=!isFS;\n  document.getElementById('VP').classList.toggle('fs',isFS);\n  if(isFS&#038;&#038;screen.orientation&#038;&#038;screen.orientation.lock) screen.orientation.lock('landscape').catch(()=>{});\n  else if(!isFS&&screen.orientation&&screen.orientation.unlock) screen.orientation.unlock();\n}\nwindow.exitFS=function(){isFS=false;document.getElementById('VP').classList.remove('fs');if(screen.orientation&&screen.orientation.unlock)screen.orientation.unlock();}\n\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\/\/  VOICE \/ VIDEO CALL\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nwindow.startCall=async function(type){\n  callType=type;\n  document.getElementById('CALT').textContent=type==='voice'?'Voice call \ud83d\udcde':'Video call \ud83d\udcf9';\n  document.getElementById('CAL').classList.add('on');\n  sig('call_req',{callType:type});\n  try{\n    const con=type==='voice'?{video:false,audio:true}:{video:{facingMode:'user'},audio:true};\n    localStream=await navigator.mediaDevices.getUserMedia(con)\n      .catch(()=>navigator.mediaDevices.getUserMedia({video:false,audio:true}));\n    if(type==='video') document.getElementById('LV').srcObject=localStream;\n    showCallUI(type); startTimer();\n  }catch(e){\n    document.getElementById('CAL').classList.remove('on');\n    alert('Cannot access mic\/camera:\\n'+e.message);\n  }\n};\n\nwindow.answerCall=async function(){\n  document.getElementById('INC').classList.remove('on');\n  const type=pendingCallType||'video'; callType=type;\n  sig('call_acc');\n  try{\n    const con=type==='voice'?{video:false,audio:true}:{video:{facingMode:'user'},audio:true};\n    localStream=await navigator.mediaDevices.getUserMedia(con)\n      .catch(()=>navigator.mediaDevices.getUserMedia({video:false,audio:true}));\n    if(type==='video') document.getElementById('LV').srcObject=localStream;\n    showCallUI(type); startTimer();\n    sysMsg((type==='voice'?'\ud83d\udcde Voice':'\ud83d\udcf9 Video')+' call connected');\n  }catch(e){ alert('Cannot access mic\/camera:\\n'+e.message); }\n};\n\nwindow.declineCall=function(){document.getElementById('INC').classList.remove('on');sig('call_dec');}\nwindow.cancelCall=function(){\n  document.getElementById('CAL').classList.remove('on');\n  if(localStream){localStream.getTracks().forEach(t=>t.stop());localStream=null;}\n  sig('call_end'); endCallUI();\n}\nwindow.hangup=function(){sig('call_end');endCallUI();sysMsg('You ended the call');}\n\nfunction showCallUI(type){\n  const vp=document.getElementById('VP'); vp.classList.add('on');\n  if(type==='voice'){vp.classList.add('voice');document.getElementById('CB2').style.display='none';}\n  else{vp.classList.remove('voice');document.getElementById('CB2').style.display='flex';}\n}\n\nfunction endCallUI(){\n  if(localStream){localStream.getTracks().forEach(t=>t.stop());localStream=null;}\n  document.getElementById('LV').srcObject=null;\n  document.getElementById('RV').srcObject=null;\n  document.getElementById('NR').style.display='flex';\n  const vp=document.getElementById('VP');\n  vp.classList.remove('on','voice','fs'); isFS=false;\n  if(screen.orientation&&screen.orientation.unlock) screen.orientation.unlock();\n  document.getElementById('CAL').classList.remove('on');\n  stopTimer(); micMuted=false; camOff=false;\n  const mb=document.getElementById('MB'),cb2=document.getElementById('CB2');\n  mb.className='vb vn'; mb.textContent='\ud83c\udfa4';\n  cb2.className='vb vn'; cb2.textContent='\ud83d\udcf7'; cb2.style.display='flex';\n}\n\nwindow.toggleMic=function(){\n  if(!localStream)return; micMuted=!micMuted;\n  localStream.getAudioTracks().forEach(t=>t.enabled=!micMuted);\n  const b=document.getElementById('MB');\n  b.className=micMuted?'vb vo':'vb vn'; b.textContent=micMuted?'\ud83d\udd07':'\ud83c\udfa4';\n}\nwindow.toggleCam=function(){\n  if(!localStream)return; camOff=!camOff;\n  localStream.getVideoTracks().forEach(t=>t.enabled=!camOff);\n  const b=document.getElementById('CB2');\n  b.className=camOff?'vb vo':'vb vn'; b.textContent=camOff?'\ud83d\udeab':'\ud83d\udcf7';\n}\n\nfunction startTimer(){\n  timerSec=0;\n  timerInt=setInterval(()=>{\n    timerSec++;\n    const m=Math.floor(timerSec\/60),s=timerSec%60;\n    const str=(m<10?'0':'')+m+':'+(s<10?'0':'')+s;\n    document.getElementById('VT').textContent=str;\n    document.getElementById('VTMX').textContent=str;\n  },1000);\n}\nfunction stopTimer(){clearInterval(timerInt);document.getElementById('VT').textContent='00:00';document.getElementById('VTMX').textContent='00:00';}\n\n\/\/ Cleanup\nwindow.addEventListener('beforeunload',()=>{\n  unsubFns.forEach(f=>{ try{f()}catch(e){} });\n  try{dbD('rooms\/'+myRoom);}catch(e){}\n});\n<\/script>\n<\/body>\n<\/html>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Connect 1-to-1 Connect 1\u2011to\u20111 Real-time chat &amp; video \u00b7 any device Your name \ud83c\udfe0 Create Room \ud83d\udc46 Tap to copy \u00b7 Send to your friend \u2014 or join \u2014 Room code from friend \ud83d\udd17 Join Room \ud83d\udcde Incoming Call Someone is calling&#8230; \u2705 Accept \u274c Decline Calling&#8230; Video call Cancel ? \u2014 Online \ud83d\udcde \ud83d\udcf9<a class=\"more-link\" href=\"https:\/\/news.orghub.in\/index.php\/live-chat\/\">Continue reading <span class=\"screen-reader-text\">&#8220;LIVE CHAT&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-184","page","type-page","status-publish","hentry","entry"],"_links":{"self":[{"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/pages\/184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/comments?post=184"}],"version-history":[{"count":12,"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/pages\/184\/revisions"}],"predecessor-version":[{"id":198,"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/pages\/184\/revisions\/198"}],"wp:attachment":[{"href":"https:\/\/news.orghub.in\/index.php\/wp-json\/wp\/v2\/media?parent=184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}