Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- frontend/app.js +72 -44
- 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
|
| 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 |
-
|
| 66 |
showScreen("welcome");
|
| 67 |
-
document.getElementById("topbar-title").textContent = "
|
| 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
|
| 76 |
return;
|
| 77 |
}
|
| 78 |
list.innerHTML = sessions.map(s => `
|
| 79 |
-
<div class="
|
| 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 |
-
|
| 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 = "
|
| 157 |
-
div.innerHTML = `
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 ? `
|
| 169 |
-
|
| 170 |
-
|
|
|
|
| 171 |
|
| 172 |
const div = document.createElement("div");
|
| 173 |
-
div.className = "
|
| 174 |
div.innerHTML = `
|
| 175 |
-
<div class="
|
| 176 |
-
<
|
| 177 |
-
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
${sourcesBtn}
|
| 180 |
-
|
|
|
|
|
|
|
| 181 |
</div>
|
| 182 |
-
</div>
|
| 183 |
-
|
|
|
|
| 184 |
if (scroll) scrollBottom();
|
| 185 |
}
|
| 186 |
|
| 187 |
function appendErrorBubble(text, scroll = true) {
|
| 188 |
const div = document.createElement("div");
|
| 189 |
-
div.className = "
|
| 190 |
-
div.innerHTML = `
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 = "
|
| 200 |
div.innerHTML = `
|
| 201 |
-
<div class="
|
| 202 |
-
<
|
| 203 |
-
|
| 204 |
-
<
|
| 205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 219 |
if (loading) {
|
| 220 |
-
|
| 221 |
-
document.getElementById("status-text").textContent = "Searching...";
|
| 222 |
} else {
|
| 223 |
-
|
| 224 |
-
document.getElementById("status-text").textContent = "Ready";
|
| 225 |
}
|
| 226 |
}
|
| 227 |
|
| 228 |
function scrollBottom() {
|
| 229 |
setTimeout(() => {
|
| 230 |
-
const container = document.querySelector("
|
| 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 ||
|
| 257 |
-
document.getElementById("stat-latency").textContent =
|
| 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="
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>
|
| 7 |
-
<
|
| 8 |
-
<link href="https://fonts.googleapis.com/css2?family=
|
| 9 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
</head>
|
| 11 |
-
<body>
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
<
|
| 16 |
-
|
| 17 |
-
<div class="
|
| 18 |
-
<
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 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 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
</div>
|
|
|
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 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 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
</div>
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
|
|
|
|
|
|
| 64 |
</div>
|
|
|
|
|
|
|
|
|
|
| 65 |
</div>
|
| 66 |
-
</
|
| 67 |
|
| 68 |
-
<!--
|
| 69 |
-
<
|
| 70 |
-
<!--
|
| 71 |
-
<
|
| 72 |
-
<div class="
|
| 73 |
-
<
|
| 74 |
-
<
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
<
|
| 78 |
-
<span id="status-text">Ready</span>
|
| 79 |
</div>
|
| 80 |
-
</header>
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
<
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
</
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
<
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
<
|
| 107 |
-
<
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
<
|
| 111 |
-
<
|
| 112 |
-
<
|
| 113 |
-
</
|
| 114 |
</div>
|
| 115 |
</section>
|
| 116 |
|
| 117 |
-
<!-- Chat/
|
| 118 |
-
<section
|
| 119 |
-
<div class="
|
| 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
|
| 129 |
-
<section
|
| 130 |
-
<
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
<
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
<div class="
|
| 137 |
-
<
|
| 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 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
</
|
| 156 |
-
<div class="
|
| 157 |
-
<
|
| 158 |
-
<div class="stat-value" id="stat-sources">—</div>
|
| 159 |
-
<div class="stat-label">Avg Sources Used</div>
|
| 160 |
</div>
|
| 161 |
</div>
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
</
|
| 166 |
-
|
| 167 |
-
<
|
| 168 |
-
</body>
|
| 169 |
-
</html>
|
| 170 |
</div>
|
| 171 |
</div>
|
| 172 |
</div>
|
| 173 |
</section>
|
|
|
|
| 174 |
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
</div>
|
| 181 |
-
<p class="disclaimer-line">Not a substitute for professional legal advice</p>
|
| 182 |
</div>
|
| 183 |
-
|
| 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>
|