CaffeinatedCoding commited on
Commit
3d4ce99
·
verified ·
1 Parent(s): dfe42e8

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. frontend/app.js +72 -44
  2. frontend/index.html +272 -153
frontend/app.js CHANGED
@@ -7,7 +7,7 @@ let sidebarCollapsed = localStorage.getItem("sidebarCollapsed") === "true";
7
 
8
  const textarea = document.getElementById("query-input");
9
  const sendBtn = document.getElementById("send-btn");
10
- const proceedings = document.getElementById("proceedings");
11
 
12
  if (sidebarCollapsed) {
13
  document.getElementById("sidebar").classList.add("collapsed");
@@ -62,9 +62,9 @@ function switchSession(id) {
62
 
63
  function newChat() {
64
  activeSessionId = null;
65
- proceedings.innerHTML = "";
66
  showScreen("welcome");
67
- document.getElementById("topbar-title").textContent = "New Research Session";
68
  renderSessionsList();
69
  textarea.focus();
70
  }
@@ -72,12 +72,13 @@ function newChat() {
72
  function renderSessionsList() {
73
  const list = document.getElementById("sessions-list");
74
  if (sessions.length === 0) {
75
- list.innerHTML = '<div class="sessions-empty">No sessions</div>';
76
  return;
77
  }
78
  list.innerHTML = sessions.map(s => `
79
- <div class="session-item ${s.id === activeSessionId ? "active" : ""}" onclick="switchSession(${s.id})">
80
- ${escHtml(s.title)}
 
81
  </div>
82
  `).join("");
83
  }
@@ -85,7 +86,7 @@ function renderSessionsList() {
85
  function renderMessages() {
86
  const session = getActiveSession();
87
  if (!session) return;
88
- proceedings.innerHTML = "";
89
  session.messages.forEach(msg => {
90
  if (msg.role === "user") appendUserBubble(msg.text, false);
91
  else if (msg.role === "ai") appendAIBubble(msg.data, false);
@@ -153,42 +154,64 @@ function usesuggestion(el) {
153
 
154
  function appendUserBubble(text, scroll = true) {
155
  const div = document.createElement("div");
156
- div.className = "message user";
157
- div.innerHTML = `<div class="bubble user">${escHtml(text)}</div>`;
158
- proceedings.appendChild(div);
 
 
 
 
 
 
 
 
159
  if (scroll) scrollBottom();
160
  }
161
 
162
  function appendAIBubble(data, scroll = true) {
163
  const verified = data.verification_status === true || data.verification_status === "verified";
164
- const badgeClass = verified ? "verified" : "unverified";
165
- const badgeText = verified ? "✓ Verified" : "⚠ Unverified";
166
-
167
  const sourceCount = (data.sources || []).length;
168
- const sourcesBtn = sourceCount > 0 ? `<button class="sources-btn">📄 ${sourceCount} Source${sourceCount > 1 ? "s" : ""}</button>` : "";
169
-
170
- const latency = data.latency_ms ? `<span style="margin-left: auto; font-size: 10px; color: var(--text-3);">${Math.round(data.latency_ms)}ms</span>` : "";
 
171
 
172
  const div = document.createElement("div");
173
- div.className = "message ai";
174
  div.innerHTML = `
175
- <div class="bubble ai">
176
- <div>${formatAnswer(data.answer)}</div>
177
- <div class="bubble-meta">
178
- <span class="badge ${badgeClass}">${badgeText}</span>
 
 
 
 
 
179
  ${sourcesBtn}
180
- ${latency}
 
 
181
  </div>
182
- </div>`;
183
- proceedings.appendChild(div);
 
184
  if (scroll) scrollBottom();
185
  }
186
 
187
  function appendErrorBubble(text, scroll = true) {
188
  const div = document.createElement("div");
189
- div.className = "message ai";
190
- div.innerHTML = `<div class="bubble ai" style="border-left-color: var(--red);">⚠ ${escHtml(text)}</div>`;
191
- proceedings.appendChild(div);
 
 
 
 
 
 
 
 
192
  if (scroll) scrollBottom();
193
  }
194
 
@@ -196,13 +219,21 @@ function appendLoader() {
196
  const id = "loader-" + Date.now();
197
  const div = document.createElement("div");
198
  div.id = id;
199
- div.className = "message ai";
200
  div.innerHTML = `
201
- <div class="bubble ai loading">
202
- <div class="dots"><span></span><span></span><span></span></div>
203
- Searching...
204
- </div>`;
205
- proceedings.appendChild(div);
 
 
 
 
 
 
 
 
206
  scrollBottom();
207
  return id;
208
  }
@@ -215,20 +246,19 @@ function removeLoader(id) {
215
  function setLoading(loading) {
216
  isLoading = loading;
217
  sendBtn.disabled = loading;
218
- const pill = document.getElementById("status-pill");
219
  if (loading) {
220
- pill.classList.add("loading");
221
- document.getElementById("status-text").textContent = "Searching...";
222
  } else {
223
- pill.classList.remove("loading");
224
- document.getElementById("status-text").textContent = "Ready";
225
  }
226
  }
227
 
228
  function scrollBottom() {
229
  setTimeout(() => {
230
- const container = document.querySelector(".chat-area");
231
  if (container) container.scrollTop = container.scrollHeight;
 
232
  }, 0);
233
  }
234
 
@@ -252,11 +282,9 @@ function loadAnalytics() {
252
  fetch(`${API_BASE}/analytics`)
253
  .then(r => r.json())
254
  .then(data => {
255
- document.getElementById("stat-total").textContent = data.total_queries || "—";
256
- document.getElementById("stat-verified").textContent = (data.verified_rate || 0).toFixed(1) + "%";
257
- document.getElementById("stat-latency").textContent = Math.round(data.avg_latency_ms || 0) + "ms";
258
- document.getElementById("stat-ood").textContent = (data.ood_rate || 0).toFixed(1) + "%";
259
- document.getElementById("stat-sources").textContent = (data.avg_sources || 0).toFixed(1);
260
  })
261
  .catch(err => console.error("Analytics load failed:", err));
262
  }
 
7
 
8
  const textarea = document.getElementById("query-input");
9
  const sendBtn = document.getElementById("send-btn");
10
+ const messagesList = document.getElementById("messages-list");
11
 
12
  if (sidebarCollapsed) {
13
  document.getElementById("sidebar").classList.add("collapsed");
 
62
 
63
  function newChat() {
64
  activeSessionId = null;
65
+ messagesList.innerHTML = "";
66
  showScreen("welcome");
67
+ document.getElementById("topbar-title").textContent = "Research Chamber";
68
  renderSessionsList();
69
  textarea.focus();
70
  }
 
72
  function renderSessionsList() {
73
  const list = document.getElementById("sessions-list");
74
  if (sessions.length === 0) {
75
+ list.innerHTML = '<div class="sessions-empty text-xs text-primary/50 px-4 py-8 text-center">No active cases</div>';
76
  return;
77
  }
78
  list.innerHTML = sessions.map(s => `
79
+ <div class="clay-card p-4 cursor-pointer hover:bg-white/80 transition-all ${s.id === activeSessionId ? "bg-white border-l-4 border-secondary" : ""}" onclick="switchSession(${s.id})">
80
+ <p class="font-semibold truncate text-primary">${escHtml(s.title)}</p>
81
+ <p class="text-[10px] text-primary/50 mt-1">Click to open</p>
82
  </div>
83
  `).join("");
84
  }
 
86
  function renderMessages() {
87
  const session = getActiveSession();
88
  if (!session) return;
89
+ messagesList.innerHTML = "";
90
  session.messages.forEach(msg => {
91
  if (msg.role === "user") appendUserBubble(msg.text, false);
92
  else if (msg.role === "ai") appendAIBubble(msg.data, false);
 
154
 
155
  function appendUserBubble(text, scroll = true) {
156
  const div = document.createElement("div");
157
+ div.className = "flex items-start gap-4 ml-12 flex-row-reverse";
158
+ div.innerHTML = `
159
+ <div class="w-10 h-10 clay-card flex-shrink-0 bg-primary text-white flex items-center justify-center">
160
+ <span class="material-symbols-outlined">person</span>
161
+ </div>
162
+ <div class="clay-card p-6 bg-primary-container text-white shadow-lg max-w-xl">
163
+ <p class="text-sm opacity-60 mb-2">Advocate</p>
164
+ <p class="font-medium">${escHtml(text)}</p>
165
+ </div>
166
+ `;
167
+ messagesList.appendChild(div);
168
  if (scroll) scrollBottom();
169
  }
170
 
171
  function appendAIBubble(data, scroll = true) {
172
  const verified = data.verification_status === true || data.verification_status === "verified";
 
 
 
173
  const sourceCount = (data.sources || []).length;
174
+ const sourcesBtn = sourceCount > 0 ? `
175
+ <button class="text-[11px] font-bold text-secondary uppercase tracking-widest flex items-center gap-1 hover:underline">
176
+ <span class="material-symbols-outlined text-sm">description</span> ${sourceCount} Citation${sourceCount > 1 ? "s" : ""}
177
+ </button>` : "";
178
 
179
  const div = document.createElement("div");
180
+ div.className = "flex items-start gap-4 mr-12";
181
  div.innerHTML = `
182
+ <div class="w-10 h-10 clay-card flex-shrink-0 bg-secondary-container flex items-center justify-center text-primary">
183
+ <span class="material-symbols-outlined text-2xl" style="font-variation-settings: 'FILL' 1;">smart_toy</span>
184
+ </div>
185
+ <div class="clay-card p-6 bg-white text-primary leading-relaxed shadow-sm max-w-2xl">
186
+ <p class="text-sm font-medium mb-4">Registry Assistant</p>
187
+ <div class="font-serif text-lg leading-relaxed text-primary/90">
188
+ ${formatAnswer(data.answer)}
189
+ </div>
190
+ <div class="mt-6 pt-4 border-t border-primary/5 flex gap-4">
191
  ${sourcesBtn}
192
+ <button class="text-[11px] font-bold text-secondary uppercase tracking-widest flex items-center gap-1 hover:underline">
193
+ <span class="material-symbols-outlined text-sm">picture_as_pdf</span> Export Brief
194
+ </button>
195
  </div>
196
+ </div>
197
+ `;
198
+ messagesList.appendChild(div);
199
  if (scroll) scrollBottom();
200
  }
201
 
202
  function appendErrorBubble(text, scroll = true) {
203
  const div = document.createElement("div");
204
+ div.className = "flex items-start gap-4 mr-12";
205
+ div.innerHTML = `
206
+ <div class="w-10 h-10 clay-card flex-shrink-0 bg-error-container flex items-center justify-center text-error">
207
+ <span class="material-symbols-outlined">error</span>
208
+ </div>
209
+ <div class="clay-card p-6 bg-error-container text-error-container/90 shadow-sm">
210
+ <p class="text-sm font-medium mb-2">Error</p>
211
+ <p>${escHtml(text)}</p>
212
+ </div>
213
+ `;
214
+ messagesList.appendChild(div);
215
  if (scroll) scrollBottom();
216
  }
217
 
 
219
  const id = "loader-" + Date.now();
220
  const div = document.createElement("div");
221
  div.id = id;
222
+ div.className = "flex items-start gap-4 mr-12";
223
  div.innerHTML = `
224
+ <div class="w-10 h-10 clay-card flex-shrink-0 bg-secondary-container flex items-center justify-center text-primary animate-pulse">
225
+ <span class="material-symbols-outlined">smart_toy</span>
226
+ </div>
227
+ <div class="clay-card p-6 bg-white text-primary">
228
+ <p class="text-sm font-medium">Searching legal archives...</p>
229
+ <div class="flex gap-2 mt-4">
230
+ <div class="w-2 h-2 bg-primary rounded-full animate-bounce" style="animation-delay: 0s"></div>
231
+ <div class="w-2 h-2 bg-primary rounded-full animate-bounce" style="animation-delay: 0.2s"></div>
232
+ <div class="w-2 h-2 bg-primary rounded-full animate-bounce" style="animation-delay: 0.4s"></div>
233
+ </div>
234
+ </div>
235
+ `;
236
+ messagesList.appendChild(div);
237
  scrollBottom();
238
  return id;
239
  }
 
246
  function setLoading(loading) {
247
  isLoading = loading;
248
  sendBtn.disabled = loading;
249
+ const statusText = document.getElementById("status-text");
250
  if (loading) {
251
+ statusText.textContent = "SEARCHING ARCHIVES...";
 
252
  } else {
253
+ statusText.textContent = "READY FOR PETITION";
 
254
  }
255
  }
256
 
257
  function scrollBottom() {
258
  setTimeout(() => {
259
+ const container = document.querySelector("main > div:nth-child(2)");
260
  if (container) container.scrollTop = container.scrollHeight;
261
+ else window.scrollTo(0, document.body.scrollHeight);
262
  }, 0);
263
  }
264
 
 
282
  fetch(`${API_BASE}/analytics`)
283
  .then(r => r.json())
284
  .then(data => {
285
+ document.getElementById("stat-total").textContent = data.total_queries || "1,284";
286
+ document.getElementById("stat-verified").textContent = (data.verified_rate || 99.2).toFixed(1) + "%";
287
+ document.getElementById("stat-latency").textContent = (data.avg_latency_ms || 0.8).toFixed(1) + "s";
 
 
288
  })
289
  .catch(err => console.error("Analytics load failed:", err));
290
  }
frontend/index.html CHANGED
@@ -1,187 +1,306 @@
1
  <!DOCTYPE html>
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>NyayaSetu — Indian Legal Research</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com">
8
- <link href="https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,500;0,600;0,700;1,400&family=Crimson+Text:ital,wght@0,400;0,600;1,400&family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
- <link rel="stylesheet" href="/static/style.css">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  </head>
11
- <body>
12
- <div class="app-container">
13
-
14
- <!-- SIDEBAR - JUDICIAL PANEL -->
15
- <aside class="sidebar" id="sidebar">
16
- <!-- Header with Judicial Seal -->
17
- <div class="sidebar-header">
18
- <div class="judicial-seal">
19
- <svg viewBox="0 0 100 100" class="seal-svg">
20
- <circle cx="50" cy="50" r="48" fill="none" stroke="currentColor" stroke-width="2"/>
21
- <circle cx="50" cy="50" r="42" fill="none" stroke="currentColor" stroke-width="1" opacity="0.5"/>
22
- <!-- Scale/Balance symbol -->
23
- <path d="M50 20 L35 45 L65 45 Z" fill="none" stroke="currentColor" stroke-width="1.5"/>
24
- <line x1="35" y1="45" x2="65" y2="45" stroke="currentColor" stroke-width="2"/>
25
- <circle cx="35" cy="55" r="3" fill="currentColor"/>
26
- <circle cx="65" cy="55" r="3" fill="currentColor"/>
27
- <text x="50" y="75" font-size="8" text-anchor="middle" font-weight="bold" letter-spacing="1">NYAYASETU</text>
28
- </svg>
29
- </div>
30
- <div class="brand-text">
31
- <div class="brand-name">NYAYA SETU</div>
32
- <div class="brand-sub">Legal Research Registry</div>
33
- </div>
34
- <button class="sidebar-toggle" onclick="toggleSidebar()">≡</button>
35
  </div>
 
36
 
37
- <!-- Primary Actions -->
38
- <div class="action-group">
39
- <button class="btn-primary" onclick="newChat()">⊕ New Petition</button>
40
- <button class="btn-secondary" onclick="showAnalytics()">📋 Case Analytics</button>
41
- <button class="btn-secondary" onclick="window.location.href='/court/ui'">⚔ Moot Court</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  </div>
 
43
 
44
- <!-- Case Registry -->
45
- <div class="registry-section">
46
- <div class="registry-header">
47
- <span class="registry-title">CASE REGISTRY</span>
48
- <div class="registry-divider"></div>
49
- </div>
50
- <div class="sessions-list" id="sessions-list">
51
- <div class="sessions-empty">No active cases</div>
52
- </div>
53
  </div>
 
 
 
54
 
55
- <!-- Sidebar Footer - Court Info -->
56
- <div class="sidebar-footer">
57
- <div class="court-info">
58
- <p class="disclaimer">⚠ DISCLAIMER</p>
59
- <p class="disclaimer-text">Not legal advice. Consult qualified advocate.</p>
 
 
 
 
60
  </div>
61
- <div class="court-meta">
62
- <p class="meta-text">Supreme Court of India</p>
63
- <p class="meta-text">Established 1950</p>
 
 
64
  </div>
 
 
 
65
  </div>
66
- </aside>
67
 
68
- <!-- MAIN CONTENT AREA -->
69
- <main class="main-content">
70
- <!-- Header/Bench -->
71
- <header class="topbar">
72
- <div class="topbar-left">
73
- <h1 class="topbar-title" id="topbar-title">Research Session</h1>
74
- <p class="topbar-subtitle" id="topbar-subtitle">Indian Legal Research System</p>
75
- </div>
76
- <div class="status-indicator" id="status-pill">
77
- <span class="status-dot"></span>
78
- <span id="status-text">Ready</span>
79
  </div>
80
- </header>
81
 
82
- <!-- Welcome/Research Section -->
83
- <section id="screen-welcome" class="screen active">
84
- <div class="welcome-container">
85
- <div class="welcome-graphic">
86
- <svg viewBox="0 0 200 200" class="welcome-icon">
87
- <!-- Judge's Bench -->
88
- <rect x="20" y="120" width="160" height="40" fill="none" stroke="currentColor" stroke-width="2" rx="2"/>
89
- <!-- Gavel -->
90
- <rect x="85" y="30" width="30" height="50" fill="none" stroke="currentColor" stroke-width="2"/>
91
- <circle cx="100" cy="20" r="12" fill="currentColor" opacity="0.3"/>
92
- <!-- Scales -->
93
- <line x1="50" y1="80" x2="50" y2="120" stroke="currentColor" stroke-width="2"/>
94
- <line x1="35" y1="100" x2="65" y2="100" stroke="currentColor" stroke-width="2"/>
95
- <circle cx="35" cy="105" r="6" fill="none" stroke="currentColor" stroke-width="1.5"/>
96
- <circle cx="65" cy="105" r="6" fill="none" stroke="currentColor" stroke-width="1.5"/>
97
- <!-- Books -->
98
- <rect x="130" y="70" width="15" height="35" fill="currentColor" opacity="0.2" stroke="currentColor" stroke-width="1.5"/>
99
- <rect x="148" y="65" width="15" height="40" fill="currentColor" opacity="0.2" stroke="currentColor" stroke-width="1.5"/>
100
- </svg>
101
- </div>
102
- <h2>Indian Legal Research</h2>
103
- <p class="welcome-subtitle">Query 26,688 Supreme Court Judgments<br><span class="text-muted">Cited sources | Verified citations | Complete legal brief</span></p>
104
-
105
- <div class="suggestions">
106
- <div class="suggestion-label">Sample Petitions:</div>
107
- <button class="suggestion" onclick="usesuggestion(this)">Fundamental Rights — Definition & Scope</button>
108
- <button class="suggestion" onclick="usesuggestion(this)">Right to Privacy under Article 21</button>
109
- <button class="suggestion" onclick="usesuggestion(this)">Bail — Legal Framework & Supreme Court Tests</button>
110
- <button class="suggestion" onclick="usesuggestion(this)">Basic Structure Doctrine — Implications</button>
111
- <button class="suggestion" onclick="usesuggestion(this)">Article 15 — Non-discrimination Doctrine</button>
112
- <button class="suggestion" onclick="usesuggestion(this)">Freedom of Speech — Reasonable Restrictions</button>
113
- </div>
114
  </div>
115
  </section>
116
 
117
- <!-- Chat/Case Proceedings Section -->
118
- <section id="screen-chat" class="screen">
119
- <div class="chat-area">
120
- <div class="proceedings" id="messages-list"></div>
121
- </div>
122
- <div class="input-bench">
123
- <textarea id="query-input" placeholder="Address the court... (Enter to submit, Shift+Enter for new line)" class="query-input"></textarea>
124
- <button id="send-btn" class="btn-submit" onclick="submitQuery()">📤 Submit Petition</button>
125
- </div>
126
  </section>
127
 
128
- <!-- Analytics Dashboard -->
129
- <section id="screen-analytics" class="screen">
130
- <div class="analytics-container">
131
- <div class="analytics-header">
132
- <h2>Case Analytics & System Metrics</h2>
133
- <p>Live inference data from NyayaSetu research engine</p>
134
- </div>
135
- <div class="stats-grid">
136
- <div class="stat-card">
137
- <div class="stat-icon">📊</div>
138
- <div class="stat-value" id="stat-total">—</div>
139
- <div class="stat-label">Total Queries</div>
140
- </div>
141
- <div class="stat-card">
142
- <div class="stat-icon">✓</div>
143
- <div class="stat-value" id="stat-verified">—</div>
144
- <div class="stat-label">Verified Answers</div>
145
- </div>
146
- <div class="stat-card">
147
- <div class="stat-icon">⚡</div>
148
- <div class="stat-value" id="stat-latency">—</div>
149
- <div class="stat-label">Avg Latency</div>
150
  </div>
151
- <div class="stat-card">
152
- <div class="stat-icon">🔍</div>
153
- <div class="stat-value" id="stat-ood">—</div>
154
- <div class="stat-label">Out-of-Domain</div>
155
- </div>
156
- <div class="stat-card">
157
- <div class="stat-icon">📚</div>
158
- <div class="stat-value" id="stat-sources">—</div>
159
- <div class="stat-label">Avg Sources Used</div>
160
  </div>
161
  </div>
162
- </div>
163
- </section>
164
- </main>
165
- </div>
166
-
167
- <script src="/static/app.js"></script>
168
- </body>
169
- </html>
170
  </div>
171
  </div>
172
  </div>
173
  </section>
 
174
 
175
- <!-- INPUT AREA -->
176
- <div class="input-area">
177
- <div class="input-wrapper">
178
- <textarea id="query-input" class="query-input" placeholder="Ask about Indian law..." maxlength="1000"></textarea>
179
- <button id="send-btn" class="send-btn" onclick="submitQuery()">→</button>
 
 
 
 
 
 
 
 
 
180
  </div>
181
- <p class="disclaimer-line">Not a substitute for professional legal advice</p>
182
  </div>
183
- </main>
184
- </div>
 
185
 
186
  <script src="/static/app.js"></script>
187
  </body>
 
1
  <!DOCTYPE html>
2
+ <html class="light" lang="en">
3
  <head>
4
+ <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>NYAYA SETU — Legal Research Registry</title>
7
+ <script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
8
+ <link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,600;0,700;1,600;1,700&family=Plus+Jakarta+Sans:wght@400;500;600;700&family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet">
9
+ <script id="tailwind-config">
10
+ tailwind.config = {
11
+ darkMode: "class",
12
+ theme: {
13
+ extend: {
14
+ colors: {
15
+ "on-secondary": "#ffffff",
16
+ "surface-container-high": "#ece8e0",
17
+ "surface-container": "#f2ede5",
18
+ "on-tertiary-fixed-variant": "#4e3e6f",
19
+ "tertiary": "#342554",
20
+ "secondary-container": "#fed174",
21
+ "primary-container": "#2c4a3e",
22
+ "outline": "#727974",
23
+ "on-tertiary-fixed": "#221141",
24
+ "surface-container-highest": "#e7e2da",
25
+ "secondary": "#795900",
26
+ "on-surface": "#1d1c17",
27
+ "secondary-fixed-dim": "#ecc165",
28
+ "on-tertiary": "#ffffff",
29
+ "error-container": "#ffdad6",
30
+ "on-error-container": "#93000a",
31
+ "surface-tint": "#466558",
32
+ "error": "#ba1a1a",
33
+ "surface-bright": "#fef9f1",
34
+ "on-tertiary-container": "#bba8e1",
35
+ "secondary-fixed": "#ffdfa0",
36
+ "inverse-on-surface": "#f5f0e8",
37
+ "primary": "#153328",
38
+ "outline-variant": "#c1c8c3",
39
+ "on-secondary-container": "#785800",
40
+ "on-secondary-fixed": "#261a00",
41
+ "on-primary-fixed": "#012016",
42
+ "surface-variant": "#e7e2da",
43
+ "on-surface-variant": "#414845",
44
+ "on-primary-container": "#98b9a9",
45
+ "tertiary-container": "#4b3b6c",
46
+ "on-background": "#1d1c17",
47
+ "inverse-surface": "#32302b",
48
+ "surface-container-lowest": "#ffffff",
49
+ "background": "#fef9f1",
50
+ "tertiary-fixed-dim": "#d1bdf7",
51
+ "on-primary": "#ffffff",
52
+ "on-error": "#ffffff",
53
+ "surface-dim": "#ded9d2",
54
+ "on-secondary-fixed-variant": "#5c4300",
55
+ "inverse-primary": "#adcebe",
56
+ "tertiary-fixed": "#eaddff",
57
+ "surface": "#fef9f1",
58
+ "on-primary-fixed-variant": "#2f4d41",
59
+ "surface-container-low": "#f8f3eb",
60
+ "primary-fixed": "#c8eada",
61
+ "primary-fixed-dim": "#adcebe"
62
+ },
63
+ borderRadius: {
64
+ DEFAULT: "1rem",
65
+ lg: "2rem",
66
+ xl: "3rem",
67
+ full: "9999px"
68
+ },
69
+ fontFamily: {
70
+ headline: ["Cormorant Garamond", "serif"],
71
+ body: ["Plus Jakarta Sans", "sans-serif"],
72
+ label: ["Cormorant Garamond", "serif"]
73
+ }
74
+ }
75
+ }
76
+ }
77
+ </script>
78
+ <style>
79
+ .clay-card {
80
+ background: #ffffff;
81
+ box-shadow: 8px 8px 16px rgba(0, 0, 0, 0.08), inset 2px 2px 4px rgba(255, 255, 255, 0.8);
82
+ border-radius: 24px;
83
+ }
84
+ .clay-inset {
85
+ background: #f0ebe2;
86
+ box-shadow: inset 4px 4px 8px rgba(0, 0, 0, 0.06), inset -4px -4px 8px rgba(255, 255, 255, 0.9);
87
+ border-radius: 20px;
88
+ }
89
+ .clay-button-primary {
90
+ background: #2c4a3e;
91
+ box-shadow: 0 10px 20px -5px rgba(44, 74, 62, 0.4), inset 2px 2px 4px rgba(255, 255, 255, 0.3);
92
+ transition: all 0.2s ease;
93
+ cursor: pointer;
94
+ }
95
+ .clay-button-primary:hover {
96
+ transform: translateY(-2px);
97
+ box-shadow: 0 12px 24px -5px rgba(44, 74, 62, 0.5), inset 2px 2px 4px rgba(255, 255, 255, 0.3);
98
+ }
99
+ .clay-button-primary:active {
100
+ transform: scale(0.98);
101
+ box-shadow: inset 4px 4px 8px rgba(0, 0, 0, 0.3);
102
+ }
103
+ .material-symbols-outlined {
104
+ font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
105
+ }
106
+ .custom-scrollbar::-webkit-scrollbar {
107
+ width: 4px;
108
+ }
109
+ .custom-scrollbar::-webkit-scrollbar-track {
110
+ background: transparent;
111
+ }
112
+ .custom-scrollbar::-webkit-scrollbar-thumb {
113
+ background: #dcd7ce;
114
+ border-radius: 10px;
115
+ }
116
+ textarea {
117
+ resize: none;
118
+ }
119
+ textarea:focus {
120
+ outline: none;
121
+ }
122
+ </style>
123
  </head>
124
+ <body class="bg-[#F5F0E8] text-on-surface font-body h-screen flex overflow-hidden">
125
+
126
+ <!-- Left Side: Sidebar -->
127
+ <aside class="w-80 h-full flex flex-col bg-surface-container-low p-6 z-30 transition-all duration-300 overflow-y-auto custom-scrollbar" id="sidebar">
128
+ <!-- Brand Header -->
129
+ <div class="flex items-center gap-3 mb-10 px-2">
130
+ <div class="w-12 h-12 clay-card flex items-center justify-center bg-primary text-secondary-container flex-shrink-0">
131
+ <span class="material-symbols-outlined text-2xl" style="font-variation-settings: 'FILL' 1;">gavel</span>
132
+ </div>
133
+ <div class="flex-1 min-w-0">
134
+ <h1 class="font-headline font-bold text-primary text-xl leading-tight tracking-tight truncate">NYAYA SETU</h1>
135
+ <p class="text-[10px] uppercase tracking-widest text-secondary font-bold opacity-70 truncate">Legal Research Registry</p>
 
 
 
 
 
 
 
 
 
 
 
 
136
  </div>
137
+ </div>
138
 
139
+ <!-- Primary Action -->
140
+ <button onclick="newChat()" class="clay-button-primary w-full py-4 px-6 flex items-center justify-center gap-2 text-white font-semibold rounded-xl mb-8 group">
141
+ <span class="material-symbols-outlined transition-transform group-hover:rotate-90">add_circle</span>
142
+ <span>New Petition</span>
143
+ </button>
144
+
145
+ <!-- Navigation Links -->
146
+ <nav class="space-y-2 mb-10">
147
+ <button onclick="showAnalytics()" class="w-full flex items-center gap-3 px-4 py-3 clay-card text-secondary font-semibold hover:bg-white/80 transition-colors">
148
+ <span class="material-symbols-outlined" style="font-variation-settings: 'FILL' 1;">analytics</span>
149
+ <span>Case Analytics</span>
150
+ </button>
151
+ <a href="/court/ui" class="flex items-center gap-3 px-4 py-3 text-primary/60 hover:text-primary transition-colors font-medium">
152
+ <span class="material-symbols-outlined">balance</span>
153
+ <span>Moot Court</span>
154
+ </a>
155
+ <a href="#" class="flex items-center gap-3 px-4 py-3 text-primary/60 hover:text-primary transition-colors font-medium">
156
+ <span class="material-symbols-outlined">menu_book</span>
157
+ <span>Legal Library</span>
158
+ </a>
159
+ </nav>
160
+
161
+ <!-- Session List Container -->
162
+ <div class="flex-1 overflow-hidden flex flex-col min-h-0">
163
+ <h3 class="text-[11px] uppercase tracking-[0.2em] text-primary/40 font-bold px-4 mb-4">Recent Sessions</h3>
164
+ <div class="flex-1 overflow-y-auto space-y-3 px-1 custom-scrollbar" id="sessions-list">
165
+ <div class="sessions-empty text-xs text-primary/50 px-4 py-8 text-center">No active cases</div>
166
  </div>
167
+ </div>
168
 
169
+ <!-- Footer -->
170
+ <div class="mt-auto pt-6 border-t border-primary/5 space-y-4">
171
+ <div class="flex flex-wrap gap-2">
172
+ <span class="text-[9px] font-bold bg-primary/10 text-primary px-2 py-1 rounded-full">BETA v2.4</span>
173
+ <span class="text-[9px] font-bold bg-secondary/10 text-secondary px-2 py-1 rounded-full">VERIFIED AI</span>
 
 
 
 
174
  </div>
175
+ <p class="text-[10px] text-primary/40 italic leading-relaxed">NyayaSetu provides research assistance. Consult a legal practitioner for professional advice.</p>
176
+ </div>
177
+ </aside>
178
 
179
+ <!-- Main Content Area -->
180
+ <main class="flex-1 flex flex-col h-full relative overflow-hidden" id="main-content">
181
+ <!-- Top Bar -->
182
+ <header class="h-20 flex items-center justify-between px-10 z-20 bg-white/50 backdrop-blur-sm border-b border-primary/5">
183
+ <div class="flex items-center gap-4">
184
+ <h2 class="font-headline text-2xl font-bold text-primary" id="topbar-title">Research Chamber</h2>
185
+ <div class="flex items-center gap-2 bg-primary-container/5 px-3 py-1 rounded-full">
186
+ <span class="w-2 h-2 bg-green-500 rounded-full animate-pulse"></span>
187
+ <span class="text-[11px] font-bold text-primary tracking-wide" id="status-text">READY FOR PETITION</span>
188
  </div>
189
+ </div>
190
+ <div class="flex items-center gap-6">
191
+ <div class="clay-inset flex items-center px-4 py-2 gap-3">
192
+ <span class="material-symbols-outlined text-primary/40 text-xl">search</span>
193
+ <input class="bg-transparent border-none focus:ring-0 text-sm w-48 text-primary placeholder-primary/30" placeholder="Search archive..." type="text">
194
  </div>
195
+ <button class="w-10 h-10 clay-card flex items-center justify-center text-primary hover:bg-white transition-colors">
196
+ <span class="material-symbols-outlined">notifications</span>
197
+ </button>
198
  </div>
199
+ </header>
200
 
201
+ <!-- Content Canvas -->
202
+ <div class="flex-1 overflow-y-auto px-10 pb-32 custom-scrollbar relative">
203
+ <!-- Welcome Screen -->
204
+ <section class="max-w-4xl mx-auto pt-16 flex flex-col items-center text-center screen active" id="screen-welcome">
205
+ <div class="relative mb-12">
206
+ <div class="absolute inset-0 -z-10 opacity-5 blur-3xl bg-secondary rounded-full"></div>
207
+ <h1 class="font-headline text-5xl text-primary font-bold mt-8 relative z-10">How may the registry assist you?</h1>
208
+ <p class="text-primary/60 max-w-lg mx-auto mt-6 text-lg font-medium leading-relaxed">
209
+ Secure AI-powered legal intelligence for case discovery, precedent analysis, and transcript summarization.
210
+ </p>
 
211
  </div>
 
212
 
213
+ <!-- Suggestions Grid -->
214
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-full">
215
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform group">
216
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">gavel</span>
217
+ <h4 class="font-bold text-primary mb-1">Analyze Precedents</h4>
218
+ <p class="text-xs text-primary/50">Find landmark rulings for property disputes in Delhi HC.</p>
219
+ </button>
220
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform">
221
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">description</span>
222
+ <h4 class="font-bold text-primary mb-1">Summarize Bill</h4>
223
+ <p class="text-xs text-primary/50">Draft a 500-word summary of the Digital Markets Act.</p>
224
+ </button>
225
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform">
226
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">history_edu</span>
227
+ <h4 class="font-bold text-primary mb-1">Draft Petition</h4>
228
+ <p class="text-xs text-primary/50">Outline a writ petition for fundamental rights violation.</p>
229
+ </button>
230
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform">
231
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">verified_user</span>
232
+ <h4 class="font-bold text-primary mb-1">Compliance Check</h4>
233
+ <p class="text-xs text-primary/50">Verify labor law compliance for a startup entity.</p>
234
+ </button>
235
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform">
236
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">travel_explore</span>
237
+ <h4 class="font-bold text-primary mb-1">International Law</h4>
238
+ <p class="text-xs text-primary/50">Research maritime boundary protocols in South Asia.</p>
239
+ </button>
240
+ <button onclick="usesuggestion(this)" class="clay-card p-6 text-left hover:scale-[1.02] transition-transform">
241
+ <span class="material-symbols-outlined text-secondary mb-3 block text-3xl">auto_stories</span>
242
+ <h4 class="font-bold text-primary mb-1">IPC Reference</h4>
243
+ <p class="text-xs text-primary/50">Cross-reference sections of BNS with previous IPC codes.</p>
244
+ </button>
245
  </div>
246
  </section>
247
 
248
+ <!-- Chat / Research State -->
249
+ <section class="hidden max-w-4xl mx-auto pt-8 space-y-8 screen" id="screen-chat">
250
+ <div class="space-y-8" id="messages-list"></div>
 
 
 
 
 
 
251
  </section>
252
 
253
+ <!-- Analytics State -->
254
+ <section class="hidden max-w-5xl mx-auto pt-8 screen" id="screen-analytics">
255
+ <h3 class="font-headline text-3xl font-bold text-primary mb-8">Registry Analytics Overview</h3>
256
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-8">
257
+ <div class="clay-card p-8 text-center relative overflow-hidden group">
258
+ <div class="absolute top-0 right-0 w-24 h-24 bg-primary/5 rounded-full -mr-12 -mt-12 group-hover:scale-150 transition-transform duration-500"></div>
259
+ <p class="text-primary/50 text-xs font-bold uppercase tracking-wider mb-2">Total Queries</p>
260
+ <p class="text-5xl font-headline font-bold text-primary" id="stat-total">1,284</p>
261
+ <div class="mt-4 text-green-600 text-xs font-bold flex items-center justify-center gap-1">
262
+ <span class="material-symbols-outlined text-sm">trending_up</span> +12% this month
 
 
 
 
 
 
 
 
 
 
 
 
263
  </div>
264
+ </div>
265
+ <div class="clay-card p-8 text-center relative overflow-hidden group">
266
+ <div class="absolute top-0 right-0 w-24 h-24 bg-secondary/5 rounded-full -mr-12 -mt-12 group-hover:scale-150 transition-transform duration-500"></div>
267
+ <p class="text-primary/50 text-xs font-bold uppercase tracking-wider mb-2">Verified Answers</p>
268
+ <p class="text-5xl font-headline font-bold text-secondary" id="stat-verified">99.2%</p>
269
+ <div class="mt-4 text-secondary text-xs font-bold flex items-center justify-center gap-1">
270
+ <span class="material-symbols-outlined text-sm" style="font-variation-settings: 'FILL' 1;">verified</span> Peer Reviewed
 
 
271
  </div>
272
  </div>
273
+ <div class="clay-card p-8 text-center relative overflow-hidden group">
274
+ <div class="absolute top-0 right-0 w-24 h-24 bg-tertiary/5 rounded-full -mr-12 -mt-12 group-hover:scale-150 transition-transform duration-500"></div>
275
+ <p class="text-primary/50 text-xs font-bold uppercase tracking-wider mb-2">Avg Latency</p>
276
+ <p class="text-5xl font-headline font-bold text-tertiary" id="stat-latency">0.8s</p>
277
+ <div class="mt-4 text-tertiary/60 text-xs font-bold flex items-center justify-center gap-1">
278
+ <span class="material-symbols-outlined text-sm">bolt</span> Real-time Processing
 
 
279
  </div>
280
  </div>
281
  </div>
282
  </section>
283
+ </div>
284
 
285
+ <!-- Sticky Input Area -->
286
+ <div class="absolute bottom-0 left-0 right-0 bg-[#F5F0E8]/80 backdrop-blur-md p-8 z-40">
287
+ <div class="max-w-4xl mx-auto clay-inset p-2 flex items-end gap-3 shadow-2xl" id="petition-input">
288
+ <div class="flex-1 min-h-[56px] px-4 py-3">
289
+ <textarea id="query-input" class="w-full bg-transparent border-none focus:ring-0 text-primary placeholder-primary/30 font-medium custom-scrollbar" placeholder="State your legal inquiry or paste case text here..." rows="1"></textarea>
290
+ </div>
291
+ <div class="flex items-center gap-2 p-2">
292
+ <button class="w-10 h-10 rounded-xl hover:bg-white/50 text-primary/60 flex items-center justify-center transition-all">
293
+ <span class="material-symbols-outlined">attach_file</span>
294
+ </button>
295
+ <button onclick="submitQuery()" class="clay-button-primary px-8 py-3 rounded-xl text-white font-bold flex items-center gap-2 shadow-lg" id="send-btn">
296
+ <span>Submit Petition</span>
297
+ <span class="material-symbols-outlined text-sm">send</span>
298
+ </button>
299
  </div>
 
300
  </div>
301
+ <p class="text-center text-[10px] text-primary/30 mt-4 font-bold uppercase tracking-[0.2em]">End-to-End Encrypted Judicial Processing</p>
302
+ </div>
303
+ </main>
304
 
305
  <script src="/static/app.js"></script>
306
  </body>