Vedika commited on
Commit
f3977be
·
verified ·
1 Parent(s): d186ca1

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +446 -220
index.html CHANGED
@@ -2,138 +2,185 @@
2
  <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>🇮🇳 TIRANGA</title>
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
10
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
11
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
12
  <style>
 
13
  *{margin:0;padding:0;box-sizing:border-box;}
14
  :root{
15
- --bg-color: #ffffff; --bg-secondary: #f5f5f7; --text-main: #1d1d1f; --text-muted: #86868b;
16
- --accent: #FF9933;
17
- --accent-hover: #e68a2e; --border-light: rgba(0, 0, 0, 0.08);
18
- --glass-bg: rgba(255, 255, 255, 0.75); --glass-border: rgba(255, 255, 255, 0.4);
19
  --shadow-sm: 0 2px 8px rgba(0,0,0,0.04); --shadow-md: 0 8px 32px rgba(0,0,0,0.08);
20
- --font-serif: 'Instrument Serif', serif; --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
21
- --font-mono: 'Geist Mono', monospace; --radius-lg: 24px; --radius-md: 16px; --radius-sm: 8px;
 
 
22
  }
23
  html,body{height:100%;overflow:hidden;background:var(--bg-color);color:var(--text-main);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;}
24
 
25
- /* बेहतरीन तिरंगा बैकग्राउंड शेड (Visibility बढ़ाई गई है) */
26
- .bg{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none;background: linear-gradient(135deg, rgba(255,153,51,0.08) 0%, rgba(255,255,255,1) 50%, rgba(19,136,8,0.08) 100%);}
27
- .orb{position:absolute;border-radius:50%;filter:blur(90px);opacity:0.6;animation:drift 25s ease-in-out infinite alternate;}
28
- /* केसरिया (Saffron) Orb */
29
- .orb1{width:600px;height:600px;background:radial-gradient(circle,rgba(255,153,51,0.25),transparent 70%);top:-150px;left:-100px;}
30
- /* हरा (Green) Orb */
31
- .orb2{width:500px;height:500px;background:radial-gradient(circle,rgba(19,136,8,0.22),transparent 70%);bottom:-100px;right:-100px;animation-delay:-10s;}
32
-
33
- @keyframes drift{0%{transform:translate(0,0) scale(1);}100%{transform:translate(80px,50px) scale(1.1);}}
34
- .shell{position:relative;z-index:1;display:grid;grid-template-columns:280px 1fr;height:100vh;}
35
- .sidebar{display:flex;flex-direction:column;background:var(--bg-secondary);border-right:1px solid var(--border-light);overflow:hidden;}
 
 
 
 
 
36
  .logo-area{padding:24px 20px;border-bottom:1px solid var(--border-light);}
37
- .logo-row{display:flex;align-items:center;gap:12px;margin-bottom:12px;}
38
- .logo-img{width:48px;height:48px;border-radius:12px;object-fit:cover;box-shadow:var(--shadow-sm);border:1px solid var(--border-light);background:#fff;}
39
  .logo-text{line-height:1.2;}
40
  .logo-name{font-family:var(--font-sans);font-weight:800;font-size:18px;color:var(--text-main);letter-spacing:-0.5px;}
41
  .logo-sub{font-size:10px;font-weight:600;letter-spacing:1px;text-transform:uppercase;color:var(--text-muted);}
42
  .settings{padding:20px;flex:1;overflow-y:auto;display:flex;flex-direction:column;}
43
  .settings::-webkit-scrollbar{width:4px;}
44
- .settings::-webkit-scrollbar-thumb{background:rgba(0,0,0,0.15);border-radius:10px;}
45
- .section-lbl{font-size:11px;font-weight:600;letter-spacing:1px;text-transform:uppercase;color:var(--text-muted);margin-bottom:12px;}
46
-
47
- .brand-box {background: #ffffff;border: 1px solid var(--border-light);border-radius: var(--radius-md);padding: 20px;text-align: center;box-shadow: var(--shadow-sm);margin-bottom:auto;}
48
- .brand-box img {width: 80px; height: 80px; border-radius: 16px; object-fit: cover; margin-bottom: 16px; box-shadow: var(--shadow-sm); border: 1px solid var(--border-light);}
49
- .brand-box h3 {font-family: var(--font-sans); font-size: 16px; font-weight: 700; color: var(--text-main); margin-bottom: 6px; letter-spacing: 0.5px;}
50
- .brand-box p {font-size: 10px; font-weight: 600; color: var(--text-muted); line-height: 1.4; letter-spacing: 0.5px;}
51
-
52
- .clear-btn{width:100%;padding:10px;border-radius:var(--radius-sm);background:#ffffff;border:1px solid var(--border-light);color:var(--text-main);font-family:var(--font-sans);font-size:13px;font-weight:500;cursor:pointer;transition:all 0.2s;margin-top:20px;}
53
  .clear-btn:hover{background:#fff0f0;color:#ff3b30;border-color:#ff3b30;}
54
- .chat-main{display:flex;flex-direction:column;background:transparent;overflow:hidden;position:relative;}
55
- .chat-hdr{padding:14px 24px;border-bottom:1px solid var(--border-light);background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);display:flex;align-items:center;justify-content:space-between;flex-shrink:0;z-index:10;}
56
- .model-badge{font-size:13px;font-weight:600;color:var(--text-main);display:flex;align-items:center;gap:8px;}
 
57
  .status-dot{width:8px;height:8px;border-radius:50%;background:#34c759;box-shadow:0 0 0 2px rgba(52,199,89,0.2);}
58
- .messages{flex:1;overflow-y:auto;padding:30px 40px;display:flex;flex-direction:column;gap:24px;scroll-behavior:smooth;}
59
  .messages::-webkit-scrollbar{width:6px;}
60
  .messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,0.1);border-radius:10px;}
61
- .welcome{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:40px;flex:1;min-height:400px;animation:fadeIn 0.5s ease-out;}
 
62
  @keyframes fadeIn{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
63
- .welcome-logo{width:80px;height:80px;border-radius:20px;object-fit:cover;box-shadow:var(--shadow-md);margin-bottom:24px;background:#fff;border:1px solid var(--border-light);}
64
- .welcome-title{font-family:var(--font-sans);font-size:32px;font-weight:800;color:var(--text-main);letter-spacing:-1px;margin-bottom:12px;}
65
- .welcome-sub{font-size:15px;color:var(--text-muted);max-width:500px;line-height:1.5;margin-bottom:32px;}
66
- .ex-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;width:100%;max-width:600px;}
67
- .ex-card{background:var(--glass-bg);backdrop-filter:blur(10px);border:1px solid var(--border-light);border-radius:var(--radius-md);padding:16px;cursor:pointer;text-align:left;transition:all 0.2s;box-shadow:var(--shadow-sm);}
68
- .ex-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:rgba(255,153,51,0.4);}
69
- .ex-title{font-size:13px;font-weight:600;color:var(--text-main);margin-bottom:4px;}
70
- .ex-desc{font-size:12px;color:var(--text-muted);line-height:1.4;}
71
- .msg{display:flex;gap:16px;animation:msgIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;max-width:85%;}
72
- @keyframes msgIn{from{opacity:0;transform:translateY(12px) scale(0.98);}to{opacity:1;transform:none;}}
73
  .msg.user{flex-direction:row-reverse;align-self:flex-end;}
74
  .msg.bot{align-self:flex-start;}
75
- .avatar{width:32px;height:32px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600;}
76
- .msg.user .avatar{background:var(--bg-secondary);color:var(--text-main);border:1px solid var(--border-light);}
77
- .msg.bot .avatar-img{width:100%;height:100%;border-radius:50%;object-fit:cover;border:1px solid var(--border-light);background:#fff;}
78
- .body{display:flex;flex-direction:column;gap:4px;}
 
79
  .msg.user .body{align-items:flex-end;}
80
- .bubble{padding:14px 18px;font-size:14.5px;line-height:1.6;color:var(--text-main);}
81
- .msg.user .bubble{background:var(--accent);color:#ffffff;border-radius:20px 20px 4px 20px;box-shadow:0 4px 12px rgba(255,153,51,0.2);}
 
82
  .msg.bot .bubble{background:#ffffff;border:1px solid var(--border-light);border-radius:4px 20px 20px 20px;box-shadow:var(--shadow-sm);width:100%;}
83
- .bubble p{margin-bottom:10px;}
 
 
 
 
 
 
 
 
84
  .bubble p:last-child{margin-bottom:0;}
85
- .bubble pre{background:#f5f5f7;border:1px solid rgba(0,0,0,0.05);border-radius:12px;padding:12px;margin:10px 0;overflow-x:auto;font-family:var(--font-mono);font-size:13px;}
86
- .msg.user .bubble pre{background:rgba(255,255,255,0.1);border:none;color:#fff;}
87
- .bubble code{font-family:var(--font-mono);background:rgba(0,0,0,0.05);padding:2px 6px;border-radius:6px;font-size:0.9em;}
88
- .msg.user .bubble code{background:rgba(255,255,255,0.2);}
89
- .bubble pre code{background:transparent;padding:0;}
90
- .code-wrap{position:relative;margin:12px 0;}
91
- .code-header{display:flex;justify-content:space-between;align-items:center;padding:8px 16px;background:#e5e5ea;border-radius:12px 12px 0 0;border:1px solid rgba(0,0,0,0.05);border-bottom:none;}
92
- .code-lang-tag{font-size:12px;font-weight:600;color:var(--text-muted);font-family:var(--font-mono);}
93
- .copy-btn{padding:4px 12px;border-radius:8px;background:#ffffff;border:1px solid rgba(0,0,0,0.1);color:var(--text-main);font-size:11px;font-weight:500;cursor:pointer;transition:all 0.2s;}
94
- .copy-btn:hover{background:#f5f5f7;}
95
- .code-wrap pre{border-radius:0 0 12px 12px;margin:0;}
96
- .think-blk {background: rgba(0, 0, 0, 0.02);border: 1px solid rgba(0, 0, 0, 0.08);border-radius: 12px;padding: 12px 16px;margin-bottom: 14px;box-shadow: inset 0 2px 4px rgba(0,0,0,0.02);transition: all 0.3s ease;}
97
- .think-blk:hover {background: rgba(0, 0, 0, 0.04);}
98
- .think-hdr {display: flex;align-items: center;font-size: 13px;font-weight: 600;color: var(--text-muted);cursor: pointer;user-select: none;}
99
- .think-hdr::before {content: '►';font-size: 10px;margin-right: 10px;transition: transform 0.2s ease;color: #a1a1a6;}
100
- .think-blk.open .think-hdr::before {transform: rotate(90deg);}
101
- .think-body {margin-top: 12px;display: none;border-top: 1px dashed rgba(0,0,0,0.1);padding-top: 12px;font-size: 13.5px;color: var(--text-muted);line-height: 1.6;font-family: var(--font-mono);white-space: pre-wrap;}
102
- .think-blk.open .think-body {display: block;animation: fadeInDown 0.3s ease;}
103
- @keyframes fadeInDown {from { opacity: 0; transform: translateY(-5px); }to { opacity: 1; transform: translateY(0); }}
104
- .typing{display:flex;align-items:center;gap:6px;padding:8px 4px;}
105
- .typing span{width:8px;height:8px;border-radius:50%;background:var(--text-muted);opacity:0.4;animation:bounce 1s ease-in-out infinite;}
106
- .typing span:nth-child(2){animation-delay:0.2s;}
107
- .typing span:nth-child(3){animation-delay:0.4s;}
108
- @keyframes bounce{0%,100%{transform:translateY(0);opacity:0.4;}50%{transform:translateY(-6px);opacity:1;}}
109
- .input-container{padding:0 40px 30px;background:linear-gradient(to top, var(--bg-color) 70%, transparent);position:relative;z-index:10;}
110
- .input-wrap{display:flex;align-items:flex-end;gap:12px;background:var(--glass-bg);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid var(--border-light);border-radius:24px;padding:10px 14px 10px 20px;box-shadow:var(--shadow-md);transition:box-shadow 0.3s;}
111
- .input-wrap:focus-within{box-shadow:0 12px 40px rgba(0,0,0,0.12), 0 0 0 3px rgba(255,153,51,0.2);}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  .chat-ta{flex:1;border:none;outline:none;background:transparent;font-family:var(--font-sans);font-size:15px;color:var(--text-main);line-height:1.5;resize:none;max-height:200px;min-height:24px;padding:10px 0;}
113
  .chat-ta::placeholder{color:var(--text-muted);}
114
  .input-acts{display:flex;align-items:center;gap:8px;padding-bottom:6px;}
115
- .icon-btn{width:36px;height:36px;border-radius:50%;background:#f5f5f7;border:1px solid transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);font-size:16px;transition:all 0.2s;flex-shrink:0;}
116
- .icon-btn:hover{background:#e5e5ea;color:var(--text-main);}
117
- .file-btn{position:relative;}
118
- .file-btn input{position:absolute;inset:0;opacity:0;cursor:pointer;}
119
- .send-btn{width:40px;height:40px;border-radius:50%;border:none;background:var(--text-main);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:transform 0.2s, opacity 0.2s;}
120
- .send-btn svg{width:18px;height:18px;fill:currentColor;}
121
- .send-btn:hover{transform:scale(1.05);}
122
- .send-btn:disabled{opacity:0.3;cursor:not-allowed;transform:none;}
 
 
 
 
 
 
 
 
 
123
  .input-hint{text-align:center;font-size:11px;color:var(--text-muted);margin-top:12px;font-weight:500;}
124
- .img-prev{display:none;padding:12px 20px;background:#f5f5f7;border-radius:16px;margin:0 40px 12px;border:1px solid var(--border-light);}
125
- .img-prev.show{display:flex;align-items:center;gap:12px;}
126
- .img-th{width:48px;height:48px;object-fit:cover;border-radius:10px;box-shadow:var(--shadow-sm);}
127
- .img-nm{font-size:13px;font-weight:600;color:var(--text-main);}
128
- .img-sz{font-size:11px;color:var(--text-muted);}
129
- .img-rm{margin-left:auto;width:28px;height:28px;border-radius:50%;background:#e5e5ea;border:none;cursor:pointer;color:var(--text-muted);transition:background 0.2s;}
130
- .img-rm:hover{background:#ff3b30;color:#fff;}
131
- @media(max-width:768px){
132
- .shell{grid-template-columns:1fr;}
133
- .sidebar{display:none;}
 
 
 
 
 
 
 
134
  .messages{padding:20px;}
135
  .input-container{padding:0 20px 20px;}
136
  .msg{max-width:95%;}
 
137
  }
138
  </style>
139
  </head>
@@ -145,120 +192,278 @@ html,body{height:100%;overflow:hidden;background:var(--bg-color);color:var(--tex
145
  </div>
146
 
147
  <div class="shell">
148
- <aside class="sidebar">
 
149
  <div class="logo-area">
150
  <div class="logo-row">
151
  <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Logo" class="logo-img">
152
  <div class="logo-text">
153
  <div class="logo-name">TIRANGA</div>
154
- <div class="logo-sub">Advanced AI System</div>
155
  </div>
156
  </div>
157
  </div>
158
-
159
  <div class="settings">
160
- <div class="section-lbl">Brand Identity</div>
161
-
162
  <div class="brand-box">
163
  <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Identity">
164
  <h3>TIRANGA</h3>
165
  <p>ALWAYS BE FORWARD NEVER BE BACKWARD!!</p>
166
  </div>
167
-
168
- <button class="clear-btn" onclick="clearChat()">Clear Conversation</button>
169
  </div>
170
  </aside>
171
 
172
- <main class="chat-main">
173
- <header class="chat-hdr">
174
- <div class="model-badge">
175
- <div class="status-dot"></div>
176
- TIRANGA Ready
177
- </div>
178
- </header>
179
-
180
- <div class="img-prev" id="imgPrev">
181
- <img class="img-th" id="imgThumb" src="">
182
- <div>
183
- <div class="img-nm" id="imgName">document.pdf</div>
184
- <div class="img-sz" id="imgSize">0 KB</div>
 
 
 
 
185
  </div>
186
- <button class="img-rm" onclick="removeImg()">✕</button>
187
- </div>
188
 
189
- <div class="messages" id="msgs">
190
- <div class="welcome" id="welcome">
191
- <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Logo" class="welcome-logo">
192
- <div class="welcome-title">How can I help you today?</div>
193
- <div class="welcome-sub">I am TIRANGA. I specialize in coding, deep reasoning, and complex logic. Upload images or ask anything!</div>
194
-
195
- <div class="ex-grid">
196
- <div class="ex-card" onclick="sendEx('Write a modern React component with Tailwind CSS that displays a glass-morphism pricing card.')">
197
- <div class="ex-title">Code Generation</div>
198
- <div class="ex-desc">Write optimized, secure code</div>
 
 
 
 
 
199
  </div>
200
- <div class="ex-card" onclick="sendEx('Explain the Model Context Protocol (MCP) and how it improves AI latency compared to standard REST APIs.')">
201
- <div class="ex-title">Deep Reasoning</div>
202
- <div class="ex-desc">Step-by-step technical analysis</div>
 
 
 
 
 
 
 
203
  </div>
204
  </div>
 
205
  </div>
206
- </div>
207
-
208
- <div class="input-container">
209
- <div class="input-wrap">
210
- <textarea class="chat-ta" id="chatInput" placeholder="Message TIRANGA..." rows="1" onkeydown="handleKey(event)" oninput="autoGrow(this)"></textarea>
211
- <div class="input-acts">
212
- <label class="icon-btn file-btn" title="Upload Image or File">
213
- 📎<input type="file" accept="image/*,audio/*,.txt,.pdf" onchange="handleFile(this)" id="fileInput">
214
- </label>
215
- <button class="send-btn" id="sendBtn" onclick="sendMsg()">
216
- <svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
217
- </button>
218
  </div>
219
  </div>
220
- <div class="input-hint">TIRANGA AI can make mistakes. Consider verifying critical information.</div>
221
- </div>
222
- </main>
 
 
223
  </div>
224
 
225
  <script>
226
- const S={history:[],pending:null,busy:false};
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
 
228
  function handleFile(input){
229
  const f=input.files[0];if(!f)return;
230
  const r=new FileReader();
231
  r.onload=e=>{
232
  const base64Data = e.target.result.split(',')[1];
233
- let type = 'file';
234
- if(f.type.startsWith('image/')) type = 'image';
235
- else if(f.type.startsWith('audio/')) type = 'audio';
236
-
237
- S.pending={type: type, data: base64Data, name: f.name, size: fmtSz(f.size)};
238
-
239
- if(type === 'image') {
240
- document.getElementById('imgThumb').src = e.target.result;
241
- document.getElementById('imgThumb').style.display='block';
242
- } else {
243
- document.getElementById('imgThumb').style.display='none';
244
- }
245
  document.getElementById('imgName').textContent=f.name;
246
- document.getElementById('imgSize').textContent=fmtSz(f.size);
247
  document.getElementById('imgPrev').classList.add('show');
248
  };
249
  r.readAsDataURL(f);
250
  }
251
  function removeImg(){S.pending=null;document.getElementById('imgPrev').classList.remove('show');document.getElementById('fileInput').value='';}
252
- function fmtSz(b){return b<1048576?`${(b/1024).toFixed(0)} KB`:`${(b/1048576).toFixed(1)} MB`;}
253
 
 
254
  function handleKey(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendMsg();}}
255
  function autoGrow(el){el.style.height='auto';el.style.height=Math.min(el.scrollHeight,200)+'px';}
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  async function sendMsg(){
258
  if(S.busy)return;
259
  const inp=document.getElementById('chatInput');
260
  const msg=inp.value.trim();if(!msg && !S.pending)return;
261
  inp.value='';inp.style.height='auto';
 
 
 
 
 
 
 
262
  document.getElementById('sendBtn').disabled=true;
263
  S.busy=true;
264
 
@@ -266,26 +471,32 @@ async function sendMsg(){
266
  if(w)w.style.display='none';
267
 
268
  let attachments = [];
 
269
  if(S.pending) {
270
  attachments.push(S.pending);
271
- appendUser(msg || '[फ़ाइल संलग्न की गई]', '📎 '+S.pending.name);
 
 
272
  } else {
273
- appendUser(msg);
 
274
  }
275
  removeImg();
 
276
 
277
- const botDiv=appendBot();
278
-
279
- const sysPrompt = "You are TIRANGA, a state-of-the-art AI assistant developed by Divy Bhai. You possess world-class expertise in software engineering, advanced algorithmic logic, and complex problem-solving. Always provide highly optimized, secure, and precise solutions in English by default.";
280
- const maxTokens = 4096;
281
- const temp = 0.60;
282
 
 
 
283
  const payload = {
284
  message: msg,
285
  attachments: attachments,
286
  system_prompt: sysPrompt,
287
- max_tokens: maxTokens,
288
- temperature: temp
289
  };
290
 
291
  try{
@@ -314,77 +525,92 @@ async function sendMsg(){
314
  const dataObj = JSON.parse(dataStr);
315
  if (dataObj.choices && dataObj.choices[0].delta.content) {
316
  accumulatedText += dataObj.choices[0].delta.content;
317
- renderBot(botDiv, accumulatedText);
318
- scrollDown();
319
  }
320
  } catch (e) { }
321
  }
322
  }
323
  }
 
 
 
 
324
  }catch(err){
325
- renderBot(botDiv,`**Error:** सर्वर से संपर्क नहीं हो पाया। कृपया दोबारा प्रयास करें।`);
326
  }
327
 
328
  S.busy=false;
329
  document.getElementById('sendBtn').disabled=false;
330
- scrollDown();
331
  }
332
 
333
- function sendEx(t){document.getElementById('chatInput').value=t;sendMsg();}
334
-
335
- function appendUser(text, badgeText){
336
- let bHtml = badgeText ? `<div class="pdf-badge">${esc(badgeText)}</div>` : '';
337
  const el=document.createElement('div');el.className='msg user';
338
  el.innerHTML=`<div class="avatar">U</div><div class="body">${bHtml}<div class="bubble">${esc(text)}</div></div>`;
339
- document.getElementById('msgs').appendChild(el);scrollDown();
340
  }
341
- function appendBot(){
342
  const el=document.createElement('div');el.className='msg bot';
343
- el.innerHTML=`<div class="avatar"><img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" class="avatar-img"></div><div class="body"><div class="bubble"><div class="typing"><span></span><span></span><span></span></div></div></div>`;
344
- document.getElementById('msgs').appendChild(el);scrollDown();return el;
 
 
 
 
 
 
345
  }
346
 
347
- function renderBot(el, raw) {
 
348
  const b = el.querySelector('.bubble');
349
- let thinkHtml = '';
350
- let ans = raw;
351
-
352
- const thinkRegex = /<think>([\s\S]*?)(<\/think>|$)/i;
353
- let match = raw.match(thinkRegex);
354
-
355
- if (match) {
356
- const fullTag = match[0];
357
- let chain = match[1].replace(/<[^>]+>/g, '').trim();
358
- ans = raw.replace(fullTag, '').trim();
359
-
360
- if (match[2] === '') {
361
- thinkHtml = `<div class="think-blk open" style="border-color:var(--accent)"><div class="think-hdr">Reasoning <span class="typing" style="display:inline-flex;padding:0 4px"><span></span><span></span><span></span></span></div><div class="think-body">${esc(chain)}</div></div>`;
362
- ans = '';
363
- } else {
364
- thinkHtml = `<div class="think-blk" onclick="this.classList.toggle('open')"><div class="think-hdr">Reasoning Process</div><div class="think-body">${esc(chain)}</div></div>`;
365
- }
366
- }
 
367
 
368
- b.innerHTML = thinkHtml + md(ans);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  }
370
 
371
- /* कॉपी बटन के HTML ब्रेक होने के बग को यहीं फिक्स किया गया है (encodeURIComponent का उपयोग करके) */
372
- (function setupMarked(){
373
- if(typeof marked==='undefined')return;
374
- const renderer=new marked.Renderer();
375
- renderer.code=(code,lang)=>{
376
- const language=lang&&hljs.getLanguage(lang)?lang:'plaintext';
377
- const rawCode = code.text||code;
378
- const highlighted=hljs.highlight(rawCode,{language}).value;
379
- const encoded = encodeURIComponent(rawCode).replace(/'/g, "%27");
380
- return `<div class="code-wrap"><div class="code-header"><span class="code-lang-tag">${language}</span><button class="copy-btn" onclick="navigator.clipboard.writeText(decodeURIComponent('${encoded}'))">Copy</button></div><pre><code class="hljs">${highlighted}</code></pre></div>`;
381
- };
382
- marked.setOptions({renderer,breaks:true});
383
- })();
384
- function md(t){return marked?marked.parse(t):t;}
385
  function esc(t){return t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
386
- function scrollDown(){const m=document.getElementById('msgs');m.scrollTop=m.scrollHeight;}
387
- function clearChat(){S.history=[];document.getElementById('msgs').innerHTML='';location.reload();}
388
  </script>
389
  </body>
390
- </html>
 
2
  <html lang="en">
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>🇮🇳 TIRANGA - Advanced AI</title>
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
9
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
10
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
11
  <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
12
  <style>
13
+ /* --- BASE RESET & VARIABLES --- */
14
  *{margin:0;padding:0;box-sizing:border-box;}
15
  :root{
16
+ --bg-color: #ffffff; --bg-secondary: #f9f9fb; --text-main: #1d1d1f; --text-muted: #86868b;
17
+ --accent: #FF9933; --accent-green: #138808; --accent-hover: #e68a2e;
18
+ --border-light: rgba(0, 0, 0, 0.08); --border-focus: rgba(255, 153, 51, 0.3);
19
+ --glass-bg: rgba(255, 255, 255, 0.85); --glass-border: rgba(255, 255, 255, 0.4);
20
  --shadow-sm: 0 2px 8px rgba(0,0,0,0.04); --shadow-md: 0 8px 32px rgba(0,0,0,0.08);
21
+ --shadow-lg: 0 16px 48px rgba(0,0,0,0.12);
22
+ --font-serif: 'Instrument Serif', serif; --font-sans: 'Inter', -apple-system, sans-serif;
23
+ --font-mono: 'Geist Mono', monospace;
24
+ --radius-lg: 24px; --radius-md: 16px; --radius-sm: 8px;
25
  }
26
  html,body{height:100%;overflow:hidden;background:var(--bg-color);color:var(--text-main);font-family:var(--font-sans);-webkit-font-smoothing:antialiased;}
27
 
28
+ /* --- TIRANGA BACKGROUND --- */
29
+ .bg{position:fixed;inset:0;z-index:0;overflow:hidden;pointer-events:none;background: linear-gradient(135deg, rgba(255,153,51,0.05) 0%, rgba(255,255,255,1) 50%, rgba(19,136,8,0.05) 100%);}
30
+ .orb{position:absolute;border-radius:50%;filter:blur(100px);opacity:0.5;animation:drift 25s ease-in-out infinite alternate;}
31
+ .orb1{width:600px;height:600px;background:radial-gradient(circle,rgba(255,153,51,0.2),transparent 70%);top:-150px;left:-100px;}
32
+ .orb2{width:500px;height:500px;background:radial-gradient(circle,rgba(19,136,8,0.18),transparent 70%);bottom:-100px;right:-100px;animation-delay:-10s;}
33
+ @keyframes drift{0%{transform:translate(0,0) scale(1);}100%{transform:translate(60px,40px) scale(1.05);}}
34
+
35
+ /* --- MAIN LAYOUT (CHAT + WORKSPACE) --- */
36
+ .shell{position:relative;z-index:1;display:flex;height:100vh;width:100vw;overflow:hidden;}
37
+ .sidebar{width:280px;display:flex;flex-direction:column;background:var(--bg-secondary);border-right:1px solid var(--border-light);flex-shrink:0;}
38
+ .main-wrapper{flex:1;display:flex;position:relative;overflow:hidden;}
39
+ .chat-main{flex:1;display:flex;flex-direction:column;background:transparent;position:relative;min-width:300px;transition:all 0.3s cubic-bezier(0.4, 0, 0.2, 1);}
40
+ .workspace{width:0;background:#fafafa;border-left:1px solid var(--border-light);display:flex;flex-direction:column;transition:all 0.3s cubic-bezier(0.4, 0, 0.2, 1);overflow:hidden;box-shadow:-10px 0 30px rgba(0,0,0,0.02);}
41
+ .workspace.open{width:50%;}
42
+
43
+ /* --- SIDEBAR & BRANDING --- */
44
  .logo-area{padding:24px 20px;border-bottom:1px solid var(--border-light);}
45
+ .logo-row{display:flex;align-items:center;gap:12px;}
46
+ .logo-img{width:44px;height:44px;border-radius:12px;object-fit:cover;box-shadow:var(--shadow-sm);border:1px solid var(--border-light);background:#fff;}
47
  .logo-text{line-height:1.2;}
48
  .logo-name{font-family:var(--font-sans);font-weight:800;font-size:18px;color:var(--text-main);letter-spacing:-0.5px;}
49
  .logo-sub{font-size:10px;font-weight:600;letter-spacing:1px;text-transform:uppercase;color:var(--text-muted);}
50
  .settings{padding:20px;flex:1;overflow-y:auto;display:flex;flex-direction:column;}
51
  .settings::-webkit-scrollbar{width:4px;}
52
+ .settings::-webkit-scrollbar-thumb{background:rgba(0,0,0,0.1);border-radius:10px;}
53
+ .brand-box {background: #ffffff;border: 1px solid var(--border-light);border-radius: var(--radius-md);padding: 24px 16px;text-align: center;box-shadow: var(--shadow-sm);margin-top:20px;}
54
+ .brand-box img {width: 70px; height: 70px; border-radius: 16px; object-fit: cover; margin-bottom: 12px; box-shadow: var(--shadow-sm); border: 1px solid var(--border-light);}
55
+ .brand-box h3 {font-family: var(--font-sans); font-size: 15px; font-weight: 700; color: var(--text-main); margin-bottom: 6px;}
56
+ .brand-box p {font-size: 10px; font-weight: 600; color: var(--accent-green); line-height: 1.4; letter-spacing: 0.5px;}
57
+ .clear-btn{width:100%;padding:12px;border-radius:var(--radius-sm);background:#ffffff;border:1px solid var(--border-light);color:var(--text-main);font-size:13px;font-weight:600;cursor:pointer;transition:all 0.2s;margin-top:auto;}
 
 
 
58
  .clear-btn:hover{background:#fff0f0;color:#ff3b30;border-color:#ff3b30;}
59
+
60
+ /* --- CHAT AREA --- */
61
+ .chat-hdr{padding:14px 24px;border-bottom:1px solid var(--border-light);background:var(--glass-bg);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);display:flex;align-items:center;justify-content:space-between;z-index:10;}
62
+ .model-badge{font-size:13px;font-weight:600;display:flex;align-items:center;gap:8px;}
63
  .status-dot{width:8px;height:8px;border-radius:50%;background:#34c759;box-shadow:0 0 0 2px rgba(52,199,89,0.2);}
64
+ .messages{flex:1;overflow-y:auto;padding:30px 40px;display:flex;flex-direction:column;gap:24px;scroll-behavior:smooth;position:relative;}
65
  .messages::-webkit-scrollbar{width:6px;}
66
  .messages::-webkit-scrollbar-thumb{background:rgba(0,0,0,0.1);border-radius:10px;}
67
+
68
+ .welcome{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:40px;margin:auto;animation:fadeIn 0.5s ease-out;width:100%;max-width:600px;}
69
  @keyframes fadeIn{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
70
+ .welcome-logo{width:80px;height:80px;border-radius:24px;object-fit:cover;box-shadow:var(--shadow-md);margin-bottom:24px;border:1px solid var(--border-light);}
71
+ .welcome-title{font-size:32px;font-weight:800;letter-spacing:-1px;margin-bottom:12px;}
72
+ .welcome-sub{font-size:15px;color:var(--text-muted);line-height:1.6;margin-bottom:32px;}
73
+
74
+ .msg{display:flex;gap:16px;animation:msgIn 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;max-width:85%;}
75
+ @keyframes msgIn{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
 
 
 
 
76
  .msg.user{flex-direction:row-reverse;align-self:flex-end;}
77
  .msg.bot{align-self:flex-start;}
78
+ .avatar{width:36px;height:36px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:600;overflow:hidden;}
79
+ .msg.user .avatar{background:#f0f0f0;color:var(--text-main);border:1px solid var(--border-light);}
80
+ .msg.bot .avatar{border:1px solid var(--border-light);background:#fff;padding:2px;}
81
+ .msg.bot .avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover;}
82
+ .body{display:flex;flex-direction:column;gap:6px;max-width:100%;}
83
  .msg.user .body{align-items:flex-end;}
84
+
85
+ .bubble{padding:16px 20px;font-size:15px;line-height:1.6;color:var(--text-main);position:relative;}
86
+ .msg.user .bubble{background:var(--text-main);color:#ffffff;border-radius:20px 20px 4px 20px;box-shadow:var(--shadow-sm);}
87
  .msg.bot .bubble{background:#ffffff;border:1px solid var(--border-light);border-radius:4px 20px 20px 20px;box-shadow:var(--shadow-sm);width:100%;}
88
+
89
+ /* BOT ACTIONS (Copy Button below text) */
90
+ .msg-actions{display:flex;gap:8px;margin-top:4px;padding-left:12px;opacity:0;transition:opacity 0.2s;}
91
+ .msg.bot:hover .msg-actions{opacity:1;}
92
+ .action-btn{background:transparent;border:none;color:var(--text-muted);font-size:12px;cursor:pointer;display:flex;align-items:center;gap:4px;padding:4px 8px;border-radius:6px;transition:all 0.2s;}
93
+ .action-btn:hover{background:var(--bg-secondary);color:var(--text-main);}
94
+
95
+ /* Markdown inside bubble */
96
+ .bubble p{margin-bottom:12px;}
97
  .bubble p:last-child{margin-bottom:0;}
98
+ .bubble code{font-family:var(--font-mono);background:rgba(0,0,0,0.05);padding:3px 6px;border-radius:6px;font-size:0.85em;color:#e83e8c;}
99
+ .msg.user .bubble code{background:rgba(255,255,255,0.2);color:#fff;}
100
+ .bubble img{max-width:100%;border-radius:12px;margin:10px 0;box-shadow:var(--shadow-sm);border:1px solid var(--border-light);}
101
+
102
+ /* Generated Image Loader */
103
+ .img-loader {display:flex;align-items:center;gap:12px;padding:12px;background:rgba(255,153,51,0.1);border:1px solid rgba(255,153,51,0.3);border-radius:12px;color:var(--accent);font-weight:600;font-size:14px;margin-bottom:10px;}
104
+ .spinner {width:20px;height:20px;border:3px solid rgba(255,153,51,0.3);border-top-color:var(--accent);border-radius:50%;animation:spin 1s linear infinite;}
105
+ @keyframes spin{to{transform:rotate(360deg);}}
106
+
107
+ /* Workspace Trigger Card in Chat */
108
+ .ws-trigger-card {background: var(--bg-secondary);border: 1px solid var(--border-light);border-radius: 12px;padding: 16px;margin: 12px 0;display: flex;align-items: center;justify-content: space-between;}
109
+ .ws-trigger-info {display: flex;align-items: center;gap: 12px;}
110
+ .ws-trigger-icon {width: 40px;height: 40px;border-radius: 10px;background: #fff;display: flex;align-items: center;justify-content: center;font-size: 20px;box-shadow: var(--shadow-sm);border: 1px solid var(--border-light);}
111
+ .ws-trigger-text h4 {font-size: 14px;font-weight: 600;margin-bottom: 2px;}
112
+ .ws-trigger-text p {font-size: 12px;color: var(--text-muted);font-family: var(--font-mono);}
113
+ .ws-btn {padding: 8px 16px;background: var(--text-main);color: #fff;border: none;border-radius: 8px;font-size: 13px;font-weight: 500;cursor: pointer;transition: transform 0.2s;}
114
+ .ws-btn:hover {transform: scale(1.05);}
115
+
116
+ /* Typing indicator */
117
+ .typing{display:flex;align-items:center;gap:6px;padding:4px;}
118
+ .typing span{width:6px;height:6px;border-radius:50%;background:var(--text-muted);opacity:0.4;animation:bounce 1.4s infinite ease-in-out both;}
119
+ .typing span:nth-child(1){animation-delay:-0.32s;}.typing span:nth-child(2){animation-delay:-0.16s;}
120
+ @keyframes bounce{0%,80%,100%{transform:scale(0);}40%{transform:scale(1);}}
121
+
122
+ /* --- SCROLL TO BOTTOM BUTTON --- */
123
+ .scroll-bottom-btn {position:absolute;bottom:100px;right:40px;width:40px;height:40px;border-radius:50%;background:var(--glass-bg);backdrop-filter:blur(10px);border:1px solid var(--border-light);box-shadow:var(--shadow-md);display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:18px;color:var(--text-main);opacity:0;pointer-events:none;transform:translateY(20px);transition:all 0.3s cubic-bezier(0.4, 0, 0.2, 1);z-index:20;}
124
+ .scroll-bottom-btn.show {opacity:1;pointer-events:auto;transform:translateY(0);}
125
+ .scroll-bottom-btn:hover {background:#fff;transform:translateY(-3px);}
126
+
127
+ /* --- INPUT AREA (WITH INTEGRATED ATTACHMENT) --- */
128
+ .input-container{padding:0 40px 30px;background:linear-gradient(to top, var(--bg-color) 70%, transparent);position:relative;z-index:20;}
129
+ .input-wrap{display:flex;flex-direction:column;background:var(--glass-bg);backdrop-filter:blur(24px);-webkit-backdrop-filter:blur(24px);border:1px solid var(--border-light);border-radius:24px;box-shadow:var(--shadow-md);transition:box-shadow 0.3s, border-color 0.3s;}
130
+ .input-wrap:focus-within{border-color:var(--border-focus);box-shadow:0 12px 40px rgba(0,0,0,0.1), 0 0 0 3px rgba(255,153,51,0.1);}
131
+
132
+ /* Image Preview Inside Input */
133
+ .img-prev-inline{display:none;padding:12px 20px 0;align-items:center;gap:12px;}
134
+ .img-prev-inline.show{display:flex;animation:fadeIn 0.3s;}
135
+ .inline-th{width:40px;height:40px;object-fit:cover;border-radius:8px;border:1px solid var(--border-light);}
136
+ .inline-info{flex:1;}
137
+ .inline-nm{font-size:12px;font-weight:600;color:var(--text-main);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:150px;}
138
+ .inline-rm{background:rgba(0,0,0,0.05);border:none;width:24px;height:24px;border-radius:50%;cursor:pointer;font-size:10px;display:flex;align-items:center;justify-content:center;transition:background 0.2s;}
139
+ .inline-rm:hover{background:#ff3b30;color:#fff;}
140
+
141
+ .input-row{display:flex;align-items:flex-end;gap:12px;padding:10px 14px 10px 20px;}
142
  .chat-ta{flex:1;border:none;outline:none;background:transparent;font-family:var(--font-sans);font-size:15px;color:var(--text-main);line-height:1.5;resize:none;max-height:200px;min-height:24px;padding:10px 0;}
143
  .chat-ta::placeholder{color:var(--text-muted);}
144
  .input-acts{display:flex;align-items:center;gap:8px;padding-bottom:6px;}
145
+
146
+ /* Modern Attachment Button */
147
+ .attach-btn{width:36px;height:36px;border-radius:12px;background:transparent;border:1px solid transparent;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);transition:all 0.2s;position:relative;overflow:hidden;}
148
+ .attach-btn:hover{background:rgba(0,0,0,0.04);color:var(--text-main);}
149
+ .attach-btn input{position:absolute;inset:0;opacity:0;cursor:pointer;}
150
+ .attach-btn svg{width:20px;height:20px;}
151
+
152
+ /* Tiranga Gradient Send Button */
153
+ .send-btn{width:40px;height:40px;border-radius:14px;border:none;background:linear-gradient(135deg, #FF9933 0%, #ffffff 50%, #138808 100%);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all 0.3s;box-shadow:0 4px 12px rgba(0,0,0,0.1);position:relative;}
154
+ .send-btn::before{content:'';position:absolute;inset:1px;background:#1d1d1f;border-radius:13px;transition:opacity 0.3s;} /* Dark inner to make icon pop, or keep gradient */
155
+ /* Let's make the arrow black on the gradient, no dark inner needed */
156
+ .send-btn::before{display:none;}
157
+ .send-btn svg{width:18px;height:18px;fill:#1d1d1f;z-index:1;transition:transform 0.2s;}
158
+ .send-btn:hover{box-shadow:0 6px 16px rgba(255,153,51,0.3);}
159
+ .send-btn:hover svg{transform:translate(2px, -2px);}
160
+ .send-btn:disabled{opacity:0.4;cursor:not-allowed;filter:grayscale(100%);}
161
+
162
  .input-hint{text-align:center;font-size:11px;color:var(--text-muted);margin-top:12px;font-weight:500;}
163
+
164
+ /* --- WORKSPACE PANEL --- */
165
+ .ws-hdr{padding:14px 20px;border-bottom:1px solid var(--border-light);background:#fff;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;}
166
+ .ws-title{font-size:14px;font-weight:600;display:flex;align-items:center;gap:8px;}
167
+ .ws-actions{display:flex;gap:8px;}
168
+ .ws-icon-btn{width:32px;height:32px;border-radius:8px;background:#f5f5f7;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-main);transition:all 0.2s;font-size:13px;}
169
+ .ws-icon-btn:hover{background:#e5e5ea;}
170
+ .ws-close{background:transparent;color:var(--text-muted);}
171
+ .ws-close:hover{color:#ff3b30;}
172
+ .ws-content{flex:1;overflow-y:auto;background:#fafafa;padding:20px;}
173
+ .ws-content pre{margin:0;padding:20px;background:#fff;border:1px solid var(--border-light);border-radius:12px;font-family:var(--font-mono);font-size:14px;line-height:1.6;overflow-x:auto;box-shadow:var(--shadow-sm);}
174
+
175
+ /* --- RESPONSIVE MOBILE --- */
176
+ @media(max-width:850px){
177
+ .sidebar{position:absolute;left:-280px;z-index:100;height:100%;transition:left 0.3s;}
178
+ .sidebar.show{left:0;box-shadow:var(--shadow-lg);}
179
+ .workspace.open{position:absolute;top:0;left:0;width:100%;height:100%;z-index:50;}
180
  .messages{padding:20px;}
181
  .input-container{padding:0 20px 20px;}
182
  .msg{max-width:95%;}
183
+ .scroll-bottom-btn{right:20px;bottom:90px;}
184
  }
185
  </style>
186
  </head>
 
192
  </div>
193
 
194
  <div class="shell">
195
+ <!-- Sidebar -->
196
+ <aside class="sidebar" id="sidebar">
197
  <div class="logo-area">
198
  <div class="logo-row">
199
  <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Logo" class="logo-img">
200
  <div class="logo-text">
201
  <div class="logo-name">TIRANGA</div>
202
+ <div class="logo-sub">Workspace Edition</div>
203
  </div>
204
  </div>
205
  </div>
 
206
  <div class="settings">
 
 
207
  <div class="brand-box">
208
  <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Identity">
209
  <h3>TIRANGA</h3>
210
  <p>ALWAYS BE FORWARD NEVER BE BACKWARD!!</p>
211
  </div>
212
+ <button class="clear-btn" onclick="clearMemory()">🗑️ Clear Chat Memory</button>
 
213
  </div>
214
  </aside>
215
 
216
+ <!-- Main Chat Area -->
217
+ <div class="main-wrapper">
218
+ <main class="chat-main" id="chatMain">
219
+ <header class="chat-hdr">
220
+ <div class="model-badge">
221
+ <div class="status-dot"></div>
222
+ TIRANGA Intelligence
223
+ </div>
224
+ </header>
225
+
226
+ <div class="messages" id="msgs" onscroll="checkScroll()">
227
+ <!-- Welcome Screen -->
228
+ <div class="welcome" id="welcome">
229
+ <img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png" alt="Tiranga Logo" class="welcome-logo">
230
+ <div class="welcome-title">नमस्ते अभय भाई!</div>
231
+ <div class="welcome-sub">मैं TIRANGA हूँ। आपकी सुविधा के लिए मैंने मेमोरी, वर्कस्पेस, और इमेज जनरेशन जैसे नए फीचर्स ऐड कर दिए हैं। बताइए, आज क्या बनाना है?</div>
232
+ </div>
233
  </div>
 
 
234
 
235
+ <!-- Scroll to bottom button -->
236
+ <button class="scroll-bottom-btn" id="scrollBtn" onclick="forceScrollDown()">
237
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M19 12l-7 7-7-7"/></svg>
238
+ </button>
239
+
240
+ <!-- Input Area -->
241
+ <div class="input-container">
242
+ <div class="input-wrap">
243
+ <!-- Inline Image Preview -->
244
+ <div class="img-prev-inline" id="imgPrev">
245
+ <img class="inline-th" id="imgThumb" src="">
246
+ <div class="inline-info">
247
+ <div class="inline-nm" id="imgName">image.png</div>
248
+ </div>
249
+ <button class="inline-rm" onclick="removeImg()">✕</button>
250
  </div>
251
+
252
+ <div class="input-row">
253
+ <button class="attach-btn" title="Upload Image">
254
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
255
+ <input type="file" accept="image/*" onchange="handleFile(this)" id="fileInput">
256
+ </button>
257
+ <textarea class="chat-ta" id="chatInput" placeholder="Message TIRANGA..." rows="1" onkeydown="handleKey(event)" oninput="autoGrow(this)"></textarea>
258
+ <button class="send-btn" id="sendBtn" onclick="sendMsg()">
259
+ <svg viewBox="0 0 24 24"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
260
+ </button>
261
  </div>
262
  </div>
263
+ <div class="input-hint">TIRANGA is engineered for extreme performance. Verified by Divy Bhai.</div>
264
  </div>
265
+ </main>
266
+
267
+ <!-- Workspace Panel -->
268
+ <aside class="workspace" id="workspace">
269
+ <div class="ws-hdr">
270
+ <div class="ws-title">
271
+ <span id="wsLangIcon">💻</span>
272
+ <span id="wsTitleText">Generated Code</span>
273
+ </div>
274
+ <div class="ws-actions">
275
+ <button class="ws-icon-btn" onclick="copyWorkspaceCode()" title="Copy Code">📋</button>
276
+ <button class="ws-icon-btn ws-close" onclick="closeWorkspace()" title="Close">✕</button>
277
  </div>
278
  </div>
279
+ <div class="ws-content">
280
+ <pre><code id="wsCodeBlock" class="hljs"></code></pre>
281
+ </div>
282
+ </aside>
283
+ </div>
284
  </div>
285
 
286
  <script>
287
+ // --- STATE MANAGEMENT & MEMORY ---
288
+ const S = {
289
+ history: [],
290
+ pending: null,
291
+ busy: false,
292
+ isUserScrolling: false,
293
+ currentCode: "" // Holds the code currently in workspace
294
+ };
295
+
296
+ // Load Memory on Boot
297
+ window.onload = () => {
298
+ const saved = localStorage.getItem('tiranga_chat_memory');
299
+ if(saved) {
300
+ try {
301
+ S.history = JSON.parse(saved);
302
+ if(S.history.length > 0) {
303
+ document.getElementById('welcome').style.display = 'none';
304
+ S.history.forEach(msg => {
305
+ if(msg.role === 'user') appendUserDOM(msg.content, msg.badge);
306
+ else appendBotDOM(msg.content);
307
+ });
308
+ }
309
+ } catch(e) { console.error("Memory load failed", e); }
310
+ }
311
+ };
312
+
313
+ function saveMemory() {
314
+ // Keep last 20 messages to prevent local storage overflow
315
+ const memToSave = S.history.slice(-20);
316
+ localStorage.setItem('tiranga_chat_memory', JSON.stringify(memToSave));
317
+ }
318
+
319
+ function clearMemory() {
320
+ localStorage.removeItem('tiranga_chat_memory');
321
+ S.history = [];
322
+ document.getElementById('msgs').innerHTML = '';
323
+ location.reload();
324
+ }
325
 
326
+ // --- FILE HANDLING ---
327
  function handleFile(input){
328
  const f=input.files[0];if(!f)return;
329
  const r=new FileReader();
330
  r.onload=e=>{
331
  const base64Data = e.target.result.split(',')[1];
332
+ S.pending={type: 'image', data: base64Data, name: f.name};
333
+ document.getElementById('imgThumb').src = e.target.result;
 
 
 
 
 
 
 
 
 
 
334
  document.getElementById('imgName').textContent=f.name;
 
335
  document.getElementById('imgPrev').classList.add('show');
336
  };
337
  r.readAsDataURL(f);
338
  }
339
  function removeImg(){S.pending=null;document.getElementById('imgPrev').classList.remove('show');document.getElementById('fileInput').value='';}
 
340
 
341
+ // --- UI INTERACTIONS ---
342
  function handleKey(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendMsg();}}
343
  function autoGrow(el){el.style.height='auto';el.style.height=Math.min(el.scrollHeight,200)+'px';}
344
 
345
+ // Scroll Handling
346
+ function checkScroll() {
347
+ const m = document.getElementById('msgs');
348
+ // If user scrolls up more than 50px from bottom, show button
349
+ const isAtBottom = Math.abs((m.scrollHeight - m.scrollTop) - m.clientHeight) < 50;
350
+ S.isUserScrolling = !isAtBottom;
351
+
352
+ const btn = document.getElementById('scrollBtn');
353
+ if(S.isUserScrolling) btn.classList.add('show');
354
+ else btn.classList.remove('show');
355
+ }
356
+ function forceScrollDown(){
357
+ const m=document.getElementById('msgs');
358
+ m.scrollTo({top: m.scrollHeight, behavior: 'smooth'});
359
+ S.isUserScrolling = false;
360
+ }
361
+ function autoScroll() {
362
+ if(!S.isUserScrolling) {
363
+ const m=document.getElementById('msgs');
364
+ m.scrollTop = m.scrollHeight;
365
+ }
366
+ }
367
+
368
+ // --- COPY FUNCTIONALITY ---
369
+ function copyText(btn, text) {
370
+ navigator.clipboard.writeText(text);
371
+ const orig = btn.innerHTML;
372
+ btn.innerHTML = "✓ Copied!";
373
+ setTimeout(() => btn.innerHTML = orig, 2000);
374
+ }
375
+
376
+ // --- WORKSPACE LOGIC ---
377
+ function openWorkspace(encodedCode, lang) {
378
+ const code = decodeURIComponent(encodedCode);
379
+ S.currentCode = code;
380
+ document.getElementById('wsTitleText').textContent = lang ? `Generated ${lang.toUpperCase()}` : "Generated Code";
381
+ const codeBlock = document.getElementById('wsCodeBlock');
382
+ codeBlock.className = `hljs language-${lang || 'plaintext'}`;
383
+ codeBlock.textContent = code;
384
+ hljs.highlightElement(codeBlock);
385
+
386
+ document.getElementById('workspace').classList.add('open');
387
+ // On mobile, close sidebar if open
388
+ if(window.innerWidth <= 850) {
389
+ document.getElementById('sidebar').classList.remove('show');
390
+ }
391
+ }
392
+ function closeWorkspace() {
393
+ document.getElementById('workspace').classList.remove('open');
394
+ }
395
+ function copyWorkspaceCode() {
396
+ navigator.clipboard.writeText(S.currentCode);
397
+ alert("Code Copied!"); // Native toast substitute
398
+ }
399
+
400
+ // --- IMAGE GENERATION INTERCEPTOR ---
401
+ function isImageRequest(text) {
402
+ const t = text.toLowerCase();
403
+ const keywords = ['image', 'photo', 'picture', 'draw', 'generate', 'create', 'तस्वीर', 'चित्र', 'फोटो', 'बनाओ', 'बना'];
404
+ // Very basic intent check
405
+ if((t.includes('create') || t.includes('generate') || t.includes('draw') || t.includes('बनाओ') || t.includes('बना')) &&
406
+ (t.includes('image') || t.includes('photo') || t.includes('picture') || t.includes('तस्वीर') || t.includes('चित्र') || t.includes('फोटो'))) {
407
+ return true;
408
+ }
409
+ return false;
410
+ }
411
+
412
+ async function handleImageGeneration(msg) {
413
+ // Add User msg
414
+ appendUserDOM(msg);
415
+ S.history.push({role: 'user', content: msg});
416
+
417
+ // Create Bot loader
418
+ const botDiv = document.createElement('div');botDiv.className='msg bot';
419
+ botDiv.innerHTML=`<div class="avatar"><img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png"></div><div class="body"><div class="bubble"><div class="img-loader"><div class="spinner"></div> 🇮🇳 TIRANGA is creating your image...</div></div></div>`;
420
+ document.getElementById('msgs').appendChild(botDiv);
421
+ forceScrollDown();
422
+
423
+ // Parse logic for Pollinations
424
+ const models = ['flux', 'flux-realism', 'flux-anime', 'flux-3d'];
425
+ let selectedModel = models[0]; // default
426
+ const tl = msg.toLowerCase();
427
+ if(tl.includes('real')) selectedModel = 'flux-realism';
428
+ if(tl.includes('anime')) selectedModel = 'flux-anime';
429
+ if(tl.includes('3d')) selectedModel = 'flux-3d';
430
+
431
+ const seed = Math.floor(Math.random() * 100000);
432
+ const prompt = encodeURIComponent(msg);
433
+ const url = `https://image.pollinations.ai/prompt/${prompt}?seed=${seed}&model=${selectedModel}&width=1024&height=1024&nologo=true`;
434
+
435
+ // Create Image element
436
+ const img = new Image();
437
+ img.src = url;
438
+ img.onload = () => {
439
+ // Replace loader with image
440
+ botDiv.querySelector('.bubble').innerHTML = `<img src="${url}" alt="Generated Image"><p>Here is your image! (Model: ${selectedModel})</p>`;
441
+
442
+ // Add to history
443
+ const finalHTML = botDiv.querySelector('.bubble').innerHTML;
444
+ S.history.push({role: 'bot', content: finalHTML, isRawHTML: true});
445
+ saveMemory();
446
+ forceScrollDown();
447
+ };
448
+ img.onerror = () => {
449
+ botDiv.querySelector('.bubble').innerHTML = `<p>Sorry, I couldn't generate the image right now.</p>`;
450
+ forceScrollDown();
451
+ };
452
+ }
453
+
454
+ // --- MAIN CHAT LOGIC ---
455
  async function sendMsg(){
456
  if(S.busy)return;
457
  const inp=document.getElementById('chatInput');
458
  const msg=inp.value.trim();if(!msg && !S.pending)return;
459
  inp.value='';inp.style.height='auto';
460
+
461
+ // Image Generation Intercept
462
+ if(!S.pending && isImageRequest(msg)) {
463
+ handleImageGeneration(msg);
464
+ return;
465
+ }
466
+
467
  document.getElementById('sendBtn').disabled=true;
468
  S.busy=true;
469
 
 
471
  if(w)w.style.display='none';
472
 
473
  let attachments = [];
474
+ let badge = null;
475
  if(S.pending) {
476
  attachments.push(S.pending);
477
+ badge = '📎 '+S.pending.name;
478
+ appendUserDOM(msg || '[Image Attached]', badge);
479
+ S.history.push({role: 'user', content: msg || '[Image Attached]', badge: badge});
480
  } else {
481
+ appendUserDOM(msg);
482
+ S.history.push({role: 'user', content: msg});
483
  }
484
  removeImg();
485
+ saveMemory();
486
 
487
+ const botDiv = document.createElement('div');botDiv.className='msg bot';
488
+ botDiv.innerHTML=`<div class="avatar"><img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png"></div><div class="body"><div class="bubble"><div class="typing"><span></span><span></span><span></span></div></div></div>`;
489
+ document.getElementById('msgs').appendChild(botDiv);
490
+ forceScrollDown();
 
491
 
492
+ const sysPrompt = "You are TIRANGA, a state-of-the-art AI assistant developed by Divy Bhai. Always communicate in Hindi. Be extremely respectful. Use 'आप', never use 'तू' or 'तुम'. Always show immense respect to India. Answer comprehensively.";
493
+
494
  const payload = {
495
  message: msg,
496
  attachments: attachments,
497
  system_prompt: sysPrompt,
498
+ max_tokens: 4096,
499
+ temperature: 0.6
500
  };
501
 
502
  try{
 
525
  const dataObj = JSON.parse(dataStr);
526
  if (dataObj.choices && dataObj.choices[0].delta.content) {
527
  accumulatedText += dataObj.choices[0].delta.content;
528
+ renderBotText(botDiv, accumulatedText);
529
+ autoScroll();
530
  }
531
  } catch (e) { }
532
  }
533
  }
534
  }
535
+ // Save to history after complete
536
+ S.history.push({role: 'bot', content: accumulatedText});
537
+ saveMemory();
538
+
539
  }catch(err){
540
+ renderBotText(botDiv,`**Error:** सर्वर से संपर्क नहीं हो पाया। कृपया दोबारा प्रयास करें।`);
541
  }
542
 
543
  S.busy=false;
544
  document.getElementById('sendBtn').disabled=false;
545
+ autoScroll();
546
  }
547
 
548
+ // --- DOM INJECTION (For rendering history and live messages) ---
549
+ function appendUserDOM(text, badgeText){
550
+ let bHtml = badgeText ? `<div style="font-size:11px;color:var(--accent);margin-bottom:4px;font-weight:600;">${esc(badgeText)}</div>` : '';
 
551
  const el=document.createElement('div');el.className='msg user';
552
  el.innerHTML=`<div class="avatar">U</div><div class="body">${bHtml}<div class="bubble">${esc(text)}</div></div>`;
553
+ document.getElementById('msgs').appendChild(el);
554
  }
555
+ function appendBotDOM(content) {
556
  const el=document.createElement('div');el.className='msg bot';
557
+ // Check if content is raw HTML (from image generator)
558
+ if(content.includes('<img src="https://image.pollinations')) {
559
+ el.innerHTML=`<div class="avatar"><img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png"></div><div class="body"><div class="bubble">${content}</div></div>`;
560
+ } else {
561
+ el.innerHTML=`<div class="avatar"><img src="https://i.ibb.co/x8m7DbMk/TIRANGA-20260523-101648-0000.png"></div><div class="body"><div class="bubble"></div></div>`;
562
+ renderBotText(el, content);
563
+ }
564
+ document.getElementById('msgs').appendChild(el);
565
  }
566
 
567
+ // Custom Markdown rendering to extract code for Workspace
568
+ function renderBotText(el, raw) {
569
  const b = el.querySelector('.bubble');
570
+
571
+ // Custom parsing for code blocks to convert to Workspace Triggers
572
+ let processText = raw;
573
+ const codeBlockRegex = /```(\w*)\n([\s\S]*?)```/g;
574
+
575
+ processText = processText.replace(codeBlockRegex, (match, lang, code) => {
576
+ const encoded = encodeURIComponent(code).replace(/'/g, "%27");
577
+ return `
578
+ <div class="ws-trigger-card">
579
+ <div class="ws-trigger-info">
580
+ <div class="ws-trigger-icon">💻</div>
581
+ <div class="ws-trigger-text">
582
+ <h4>Code Generated</h4>
583
+ <p>${lang || 'snippet'}</p>
584
+ </div>
585
+ </div>
586
+ <button class="ws-btn" onclick="openWorkspace('${encoded}', '${lang}')">View in Workspace</button>
587
+ </div>`;
588
+ });
589
 
590
+ const html = marked.parse(processText);
591
+
592
+ // Adding the copy button below the bubble text
593
+ const cleanRaw = raw.replace(/"/g, '&quot;').replace(/'/g, "\\'");
594
+ const actionsHTML = `
595
+ <div class="msg-actions">
596
+ <button class="action-btn" onclick="copyText(this, \`${cleanRaw}\`)">
597
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
598
+ Copy
599
+ </button>
600
+ </div>
601
+ `;
602
+
603
+ b.innerHTML = html;
604
+
605
+ // Append actions to the body (outside bubble)
606
+ let actionsDiv = el.querySelector('.msg-actions');
607
+ if(!actionsDiv) {
608
+ const body = el.querySelector('.body');
609
+ body.insertAdjacentHTML('beforeend', actionsHTML);
610
+ }
611
  }
612
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  function esc(t){return t.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
 
 
614
  </script>
615
  </body>
616
+ </html>