jayasrees commited on
Commit
4f88849
·
1 Parent(s): 3625193

Delete frontend directory

Browse files
frontend/README.md DELETED
@@ -1,36 +0,0 @@
1
- # Frontend (Multi-Page Flow)
2
-
3
- This frontend now uses a strict page flow:
4
-
5
- 1. `index.html` -> Login/Signup
6
- 2. `upload.html` -> Upload document and run analysis
7
- 3. `issues.html` -> Line-level issue page (duplication, inconsistency, contradiction)
8
- 4. `summary.html` -> Final full-document summary
9
-
10
- ## Run
11
-
12
- Serve this folder using any static server from `frontend/`:
13
-
14
- ```bash
15
- python -m http.server 8080
16
- ```
17
-
18
- Open:
19
-
20
- - `http://127.0.0.1:8080/index.html`
21
-
22
- ## Backend dependency
23
-
24
- Frontend expects Flask backend endpoints:
25
-
26
- - `POST /api/register`
27
- - `POST /api/login`
28
- - `POST /api/analyze`
29
-
30
- Fallback aliases are also supported in client code (`/register`, `/login`, `/analyze`) across ports `5000` and `5001`.
31
-
32
- ## Notes
33
-
34
- - Login state and analysis payload are stored in `sessionStorage`.
35
- - If user session is missing, `upload.html`, `issues.html`, and `summary.html` redirect to `index.html`.
36
- - If analysis payload is missing, `issues.html` and `summary.html` redirect to `upload.html`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/app.js DELETED
@@ -1,509 +0,0 @@
1
- const currentHost = window.location.hostname || "127.0.0.1";
2
-
3
- const API_BASES = [
4
- `http://${currentHost}:5000/api`,
5
- `http://${currentHost}:5001/api`,
6
- "http://127.0.0.1:5000/api",
7
- "http://localhost:5000/api",
8
- "http://127.0.0.1:5001/api",
9
- "http://localhost:5001/api",
10
- ];
11
-
12
- const ANALYZE_URLS = [
13
- `http://${currentHost}:5000/api/analyze`,
14
- `http://${currentHost}:5000/analyze`,
15
- `http://${currentHost}:5001/api/analyze`,
16
- `http://${currentHost}:5001/analyze`,
17
- "http://127.0.0.1:5000/api/analyze",
18
- "http://127.0.0.1:5000/analyze",
19
- "http://localhost:5000/api/analyze",
20
- "http://localhost:5000/analyze",
21
- "http://127.0.0.1:5001/api/analyze",
22
- "http://127.0.0.1:5001/analyze",
23
- "http://localhost:5001/api/analyze",
24
- "http://localhost:5001/analyze",
25
- ];
26
-
27
- const page = (window.location.pathname.split("/").pop() || "index.html").toLowerCase();
28
-
29
- function escapeHtml(value) {
30
- return String(value)
31
- .replaceAll("&", "&")
32
- .replaceAll("<", "&lt;")
33
- .replaceAll(">", "&gt;")
34
- .replaceAll('"', "&quot;")
35
- .replaceAll("'", "&#039;");
36
- }
37
-
38
- function setText(el, text, type = null) {
39
- if (!el) return;
40
- el.textContent = text;
41
- el.classList.remove("success", "error");
42
- if (type) el.classList.add(type);
43
- }
44
-
45
- function getUser() {
46
- const userRaw = sessionStorage.getItem("lsi_user");
47
- if (!userRaw) return null;
48
- try {
49
- return JSON.parse(userRaw);
50
- } catch {
51
- return null;
52
- }
53
- }
54
-
55
- function setUser(user) {
56
- sessionStorage.setItem("lsi_user", JSON.stringify(user));
57
- }
58
-
59
- function clearSession() {
60
- sessionStorage.removeItem("lsi_user");
61
- sessionStorage.removeItem("lsi_analysis_payload");
62
- }
63
-
64
- function getAnalysisPayload() {
65
- const raw = sessionStorage.getItem("lsi_analysis_payload");
66
- if (!raw) return null;
67
- try {
68
- return JSON.parse(raw);
69
- } catch {
70
- return null;
71
- }
72
- }
73
-
74
- function setAnalysisPayload(payload) {
75
- sessionStorage.setItem("lsi_analysis_payload", JSON.stringify(payload));
76
- }
77
-
78
- function ensureAuth() {
79
- const user = getUser();
80
- if (!user) {
81
- window.location.href = "index.html#home";
82
- return null;
83
- }
84
-
85
- const badge = document.getElementById("userBadge");
86
- if (badge) {
87
- badge.textContent = `${user.fullName || user.email || "User"}`;
88
- }
89
-
90
- const logoutBtn = document.getElementById("logoutBtn");
91
- if (logoutBtn) {
92
- logoutBtn.addEventListener("click", () => {
93
- clearSession();
94
- window.location.href = "index.html#home";
95
- });
96
- }
97
-
98
- return user;
99
- }
100
-
101
- async function postAuth(endpoint, payload) {
102
- let response = null;
103
- let data = null;
104
- let lastNetworkError = null;
105
-
106
- for (const base of API_BASES) {
107
- try {
108
- response = await fetch(`${base}${endpoint}`, {
109
- method: "POST",
110
- headers: { "Content-Type": "application/json" },
111
- body: JSON.stringify(payload),
112
- });
113
- data = await response.json().catch(() => null);
114
- lastNetworkError = null;
115
- break;
116
- } catch (error) {
117
- lastNetworkError = error;
118
- }
119
- }
120
-
121
- if (lastNetworkError) {
122
- throw new Error(`Cannot reach backend at ${API_BASES.join(", ")}.`);
123
- }
124
-
125
- return { response, data };
126
- }
127
-
128
- async function runDocumentAnalysis(formData) {
129
- let response = null;
130
- let data = null;
131
- let lastNetworkError = null;
132
- let status = null;
133
-
134
- for (const url of ANALYZE_URLS) {
135
- try {
136
- response = await fetch(url, { method: "POST", body: formData });
137
- data = await response.json().catch(() => null);
138
- status = response.status;
139
- lastNetworkError = null;
140
- if (response.status !== 404) break;
141
- } catch (error) {
142
- lastNetworkError = error;
143
- }
144
- }
145
-
146
- if (lastNetworkError) {
147
- throw new Error("Cannot connect to backend for analysis.");
148
- }
149
-
150
- if (!response.ok) {
151
- throw new Error(data?.error || `Analysis request failed with HTTP ${status || response.status}.`);
152
- }
153
-
154
- return data;
155
- }
156
-
157
- function buildIssueRows(lineIssues, category) {
158
- const rows = lineIssues
159
- .filter((item) => item.category === category)
160
- .slice(0, 80)
161
- .map(
162
- (item) => `
163
- <tr>
164
- <td>${escapeHtml(item.location || `Pg ${item.page}, Ln ${item.line}`)}</td>
165
- <td>${escapeHtml(item.issueType || "-")}</td>
166
- <td>${escapeHtml(item.confidence ?? "-")}</td>
167
- </tr>
168
- `
169
- )
170
- .join("");
171
-
172
- if (!rows) {
173
- return `<p class="result-muted">No ${category} lines detected.</p>`;
174
- }
175
-
176
- return `
177
- <div class="table-wrap">
178
- <table class="result-table">
179
- <thead>
180
- <tr>
181
- <th>Page/Line</th>
182
- <th>Issue Type</th>
183
- <th>Confidence</th>
184
- </tr>
185
- </thead>
186
- <tbody>${rows}</tbody>
187
- </table>
188
- </div>
189
- `;
190
- }
191
-
192
- function initIndexPage() {
193
- const loginTab = document.getElementById("loginTab");
194
- const signupTab = document.getElementById("signupTab");
195
- const authForm = document.getElementById("authForm");
196
- const nameField = document.getElementById("nameField");
197
- const fullNameInput = document.getElementById("fullName");
198
- const emailInput = document.getElementById("email");
199
- const passwordInput = document.getElementById("password");
200
- const submitBtn = document.getElementById("submitBtn");
201
- const formSubtitle = document.getElementById("formSubtitle");
202
- const message = document.getElementById("message");
203
-
204
- let mode = "login";
205
-
206
- function setMode(nextMode) {
207
- mode = nextMode;
208
- const isSignup = mode === "signup";
209
- signupTab.classList.toggle("active", isSignup);
210
- loginTab.classList.toggle("active", !isSignup);
211
- nameField.classList.toggle("hidden", !isSignup);
212
- submitBtn.textContent = isSignup ? "Create Account" : "Login";
213
- formSubtitle.textContent = isSignup
214
- ? "Create your account to start securely."
215
- : "Enter your credentials to access your account.";
216
- fullNameInput.required = isSignup;
217
- setText(message, "", null);
218
- }
219
-
220
- async function handleAuthSubmit(event) {
221
- event.preventDefault();
222
- setText(message, "", null);
223
-
224
- const email = emailInput.value.trim();
225
- const password = passwordInput.value;
226
- const fullName = fullNameInput.value.trim();
227
-
228
- if (!email || !password || (mode === "signup" && !fullName)) {
229
- setText(message, "Please fill all required fields.", "error");
230
- return;
231
- }
232
-
233
- submitBtn.disabled = true;
234
-
235
- try {
236
- const endpoint = mode === "signup" ? "/register" : "/login";
237
- const payload = mode === "signup" ? { fullName, email, password } : { email, password };
238
- const { response, data } = await postAuth(endpoint, payload);
239
-
240
- if (!response.ok) {
241
- throw new Error(data?.error || `Request failed with HTTP ${response.status}.`);
242
- }
243
-
244
- if (mode === "signup") {
245
- setText(message, "Account created. Please login now.", "success");
246
- authForm.reset();
247
- setMode("login");
248
- return;
249
- }
250
-
251
- const user = data?.user || { fullName: fullName || email, email };
252
- setUser(user);
253
- window.location.href = "upload.html";
254
- } catch (error) {
255
- setText(message, error.message || "Something went wrong.", "error");
256
- } finally {
257
- submitBtn.disabled = false;
258
- }
259
- }
260
-
261
- loginTab.addEventListener("click", () => setMode("login"));
262
- signupTab.addEventListener("click", () => setMode("signup"));
263
- authForm.addEventListener("submit", handleAuthSubmit);
264
- setMode("login");
265
-
266
- if (getUser()) {
267
- window.location.href = "upload.html";
268
- }
269
- }
270
-
271
- function initUploadPage() {
272
- if (!ensureAuth()) return;
273
-
274
- const uploadForm = document.getElementById("uploadForm");
275
- const legalFile = document.getElementById("legalFile");
276
- const scanMode = document.getElementById("scanMode");
277
- const uploadMessage = document.getElementById("uploadMessage");
278
- const loadingState = document.getElementById("loadingState");
279
- const analysisInputSummary = document.getElementById("analysisInputSummary");
280
-
281
- legalFile.addEventListener("change", () => {
282
- if (!legalFile.files || !legalFile.files[0]) return;
283
- const selectedFile = legalFile.files[0];
284
- analysisInputSummary.classList.remove("hidden");
285
- analysisInputSummary.innerHTML = `
286
- <p><strong>File:</strong> ${escapeHtml(selectedFile.name)}</p>
287
- <p><strong>Type:</strong> ${escapeHtml(selectedFile.type || "unknown")}</p>
288
- <p><strong>Size:</strong> ${escapeHtml((selectedFile.size / 1024).toFixed(2))} KB</p>
289
- <p><strong>Scan Mode:</strong> ${escapeHtml(scanMode.value)}</p>
290
- `;
291
- setText(uploadMessage, `Selected: ${selectedFile.name}`, "success");
292
- });
293
-
294
- uploadForm.addEventListener("submit", async (event) => {
295
- event.preventDefault();
296
- setText(uploadMessage, "", null);
297
-
298
- if (!legalFile.files || legalFile.files.length === 0) {
299
- setText(uploadMessage, "Please choose a file to continue.", "error");
300
- return;
301
- }
302
-
303
- const selectedFile = legalFile.files[0];
304
- const selectedScanMode = scanMode.value;
305
-
306
- const formData = new FormData();
307
- formData.append("file", selectedFile);
308
- formData.append("scanMode", selectedScanMode);
309
-
310
- uploadForm.classList.add("hidden");
311
- loadingState.classList.remove("hidden");
312
-
313
- try {
314
- const payload = await runDocumentAnalysis(formData);
315
- payload._meta = {
316
- fileName: selectedFile.name,
317
- fileType: selectedFile.type || "unknown",
318
- fileSizeKb: Number((selectedFile.size / 1024).toFixed(2)),
319
- };
320
- setAnalysisPayload(payload);
321
- window.location.href = "issues.html";
322
- } catch (error) {
323
- loadingState.classList.add("hidden");
324
- uploadForm.classList.remove("hidden");
325
- setText(uploadMessage, error.message || "Analysis failed.", "error");
326
- }
327
- });
328
- }
329
-
330
- function initIssuesPage() {
331
- if (!ensureAuth()) return;
332
-
333
- const payload = getAnalysisPayload();
334
- if (!payload) {
335
- window.location.href = "upload.html";
336
- return;
337
- }
338
-
339
- const summary = payload.summary || {};
340
- const lineIssues = Array.isArray(payload.lineIssues) ? payload.lineIssues : [];
341
-
342
- const issueStats = document.getElementById("issueStats");
343
- issueStats.innerHTML = `
344
- <article class="stat-card stat-dup">
345
- <h3>Duplication</h3>
346
- <p>${escapeHtml(summary.duplicationCount ?? 0)}</p>
347
- </article>
348
- <article class="stat-card stat-inc">
349
- <h3>Inconsistency</h3>
350
- <p>${escapeHtml(summary.inconsistencyCount ?? 0)}</p>
351
- </article>
352
- <article class="stat-card stat-con">
353
- <h3>Contradiction</h3>
354
- <p>${escapeHtml(summary.contradictionCount ?? 0)}</p>
355
- </article>
356
- `;
357
-
358
- const lineIssueTables = document.getElementById("lineIssueTables");
359
- lineIssueTables.innerHTML = `
360
- <section class="result-card">
361
- <h4>Duplication Lines</h4>
362
- ${buildIssueRows(lineIssues, "duplication")}
363
- </section>
364
- <section class="result-card">
365
- <h4>Inconsistency Lines</h4>
366
- ${buildIssueRows(lineIssues, "inconsistency")}
367
- </section>
368
- <section class="result-card">
369
- <h4>Contradiction Lines</h4>
370
- ${buildIssueRows(lineIssues, "contradiction")}
371
- </section>
372
- `;
373
- }
374
-
375
- function initSummaryPage() {
376
- if (!ensureAuth()) return;
377
-
378
- const payload = getAnalysisPayload();
379
- if (!payload) {
380
- window.location.href = "upload.html";
381
- return;
382
- }
383
-
384
- const summary = payload.summary || {};
385
- const findings = Array.isArray(payload.findings) ? payload.findings : [];
386
- const pageSummaries = Array.isArray(payload.pageSummaries) ? payload.pageSummaries : [];
387
- const lineIssues = Array.isArray(payload.lineIssues) ? payload.lineIssues : [];
388
- const detailedSummary = String(payload.detailedSummary || "").trim();
389
- const meta = payload._meta || {};
390
-
391
- const summaryDetails = document.getElementById("summaryDetails");
392
- summaryDetails.innerHTML = `
393
- <article class="summary-item"><span>File</span><strong>${escapeHtml(meta.fileName || "-")}</strong></article>
394
- <article class="summary-item"><span>Scan Mode</span><strong>${escapeHtml(summary.scanMode || "-")}</strong></article>
395
- <article class="summary-item"><span>Threshold</span><strong>${escapeHtml(summary.threshold ?? "-")}</strong></article>
396
- <article class="summary-item"><span>Vendor</span><strong>${escapeHtml(summary.vendor || "Not found")}</strong></article>
397
- <article class="summary-item"><span>Vendee</span><strong>${escapeHtml(summary.vendee || "Not found")}</strong></article>
398
- <article class="summary-item"><span>Clauses</span><strong>${escapeHtml(summary.clauses ?? 0)}</strong></article>
399
- <article class="summary-item"><span>Pairs Compared</span><strong>${escapeHtml(summary.pairsCompared ?? 0)}</strong></article>
400
- <article class="summary-item"><span>Total Issues</span><strong>${escapeHtml(summary.issuesFound ?? 0)}</strong></article>
401
- `;
402
-
403
- const findingsBoard = document.getElementById("findingsBoard");
404
- const pageSummaryBoard = document.getElementById("pageSummaryBoard");
405
- const detailedSummaryText = document.getElementById("detailedSummaryText");
406
- const lineErrorDashboard = document.getElementById("lineErrorDashboard");
407
-
408
- if (detailedSummaryText) {
409
- detailedSummaryText.textContent = detailedSummary || "Detailed summary is not available for this document.";
410
- }
411
-
412
- if (pageSummaryBoard) {
413
- if (pageSummaries.length === 0) {
414
- pageSummaryBoard.innerHTML =
415
- `<article class="result-card"><p class="result-muted">No page-wise summary available for this document.</p></article>`;
416
- } else {
417
- pageSummaryBoard.innerHTML = pageSummaries
418
- .map((item) => {
419
- const keyLines = Array.isArray(item.keyLines) ? item.keyLines : [];
420
- const keyLineHtml = keyLines.length
421
- ? keyLines.map((k) => `<li>${escapeHtml(k)}</li>`).join("")
422
- : "<li>No flagged lines on this page.</li>";
423
- return `
424
- <article class="result-card">
425
- <h4>Page ${escapeHtml(item.page)}</h4>
426
- <p><strong>Clauses:</strong> ${escapeHtml(item.clauseCount ?? 0)}</p>
427
- <p><strong>Issues:</strong> ${escapeHtml(item.issueCount ?? 0)} (Duplication: ${escapeHtml(item.duplicationCount ?? 0)}, Inconsistency: ${escapeHtml(item.inconsistencyCount ?? 0)}, Contradiction: ${escapeHtml(item.contradictionCount ?? 0)})</p>
428
- <p><strong>Page Snippet:</strong> ${escapeHtml(item.pageSnippet || "-")}</p>
429
- <p><strong>Summary:</strong> ${escapeHtml(item.summaryText || "-")}</p>
430
- <p><strong>Key Lines:</strong></p>
431
- <ul>${keyLineHtml}</ul>
432
- </article>
433
- `;
434
- })
435
- .join("");
436
- }
437
- }
438
-
439
- if (findings.length === 0) {
440
- findingsBoard.innerHTML = `<article class="result-card"><p class="result-muted">No major findings detected for this document.</p></article>`;
441
- return;
442
- }
443
-
444
- const topFindings = findings.slice(0, 20);
445
- findingsBoard.innerHTML = topFindings
446
- .map(
447
- (item) => `
448
- <article class="result-card">
449
- <h4>${escapeHtml(item.category || "issue")} - ${escapeHtml(item.issueType || "-")}</h4>
450
- <p><strong>Confidence:</strong> ${escapeHtml(item.confidence ?? "-")}</p>
451
- <p><strong>Location A:</strong> ${escapeHtml(item.location1 || "-")}</p>
452
- <p><strong>Location B:</strong> ${escapeHtml(item.location2 || "-")}</p>
453
- <p><strong>Reason:</strong> ${escapeHtml(item.reason || "-")}</p>
454
- </article>
455
- `
456
- )
457
- .join("");
458
-
459
- if (lineErrorDashboard) {
460
- if (lineIssues.length === 0) {
461
- lineErrorDashboard.innerHTML = `<p class="result-muted">No line-level errors detected.</p>`;
462
- return;
463
- }
464
-
465
- const rows = lineIssues
466
- .slice(0, 200)
467
- .map(
468
- (item) => `
469
- <tr>
470
- <td>${escapeHtml(item.location || `Pg ${item.page}, Ln ${item.line}`)}</td>
471
- <td>${escapeHtml(item.category || "-")}</td>
472
- <td>${escapeHtml(item.issueType || "-")}</td>
473
- <td>${escapeHtml(item.confidence ?? "-")}</td>
474
- <td>${escapeHtml(item.reason || "-")}</td>
475
- </tr>
476
- `
477
- )
478
- .join("");
479
-
480
- lineErrorDashboard.innerHTML = `
481
- <div class="table-wrap">
482
- <table class="result-table">
483
- <thead>
484
- <tr>
485
- <th>Page/Line</th>
486
- <th>Category</th>
487
- <th>Issue Type</th>
488
- <th>Confidence</th>
489
- <th>Reason</th>
490
- </tr>
491
- </thead>
492
- <tbody>${rows}</tbody>
493
- </table>
494
- </div>
495
- `;
496
- }
497
- }
498
-
499
- if (page === "index.html" || page === "") {
500
- initIndexPage();
501
- } else if (page === "upload.html") {
502
- initUploadPage();
503
- } else if (page === "issues.html") {
504
- initIssuesPage();
505
- } else if (page === "summary.html") {
506
- initSummaryPage();
507
- } else if (page === "workflow.html") {
508
- window.location.href = "upload.html";
509
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/assets/legal-tech-bg.svg DELETED
frontend/index.html DELETED
@@ -1,226 +0,0 @@
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>Semantix • Legal Semantic Intelligence</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="preconnect" href="https://fonts.googleapis.com" />
9
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Space+Grotesk:wght@500;600;700&display=swap" rel="stylesheet" />
11
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
12
- <style>
13
- :root {
14
- --navy: #0f172a;
15
- }
16
-
17
- .tail-container {
18
- font-family: "Inter", system-ui, sans-serif;
19
- }
20
-
21
- .heading-font {
22
- font-family: "Space Grotesk", sans-serif;
23
- }
24
-
25
- .hero-bg {
26
- background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
27
- }
28
-
29
- .card {
30
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
31
- }
32
-
33
- .card:hover {
34
- transform: translateY(-4px);
35
- box-shadow: 0 20px 25px -5px rgb(15 23 42 / 0.1), 0 8px 10px -6px rgb(15 23 42 / 0.1);
36
- }
37
-
38
- .document-3d {
39
- perspective: 1200px;
40
- transition: transform 0.6s cubic-bezier(0.23, 1, 0.32, 1);
41
- }
42
-
43
- .document-3d:hover {
44
- transform: rotateX(12deg) rotateY(12deg) scale(1.03);
45
- }
46
-
47
- .document-inner {
48
- box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.4), 0 0 80px -20px rgb(129 140 248 / 0.6), inset 0 4px 12px rgba(255, 255, 255, 0.3);
49
- }
50
-
51
- .scan-line {
52
- position: absolute;
53
- top: 0;
54
- left: 0;
55
- width: 100%;
56
- height: 4px;
57
- background: linear-gradient(90deg, transparent, #a5b4fc, transparent);
58
- animation: scan 4s linear infinite;
59
- opacity: 0.6;
60
- }
61
-
62
- .switcher button.active {
63
- background: #ffffff;
64
- color: #111827;
65
- box-shadow: 0 4px 10px rgba(15, 23, 42, 0.12);
66
- }
67
-
68
- @keyframes scan {
69
- 0% {
70
- transform: translateY(-100%);
71
- }
72
-
73
- 100% {
74
- transform: translateY(380px);
75
- }
76
- }
77
-
78
- @media (max-width: 768px) {
79
- .nav-mobile-hide {
80
- display: none;
81
- }
82
- }
83
- </style>
84
- </head>
85
- <body class="tail-container bg-zinc-50 text-slate-900">
86
- <header class="bg-white border-b border-slate-200 sticky top-0 z-50">
87
- <div class="max-w-7xl mx-auto px-6 md:px-8 py-5 flex items-center justify-between gap-4">
88
- <div class="flex items-center gap-x-3">
89
- <div class="w-9 h-9 bg-gradient-to-br from-indigo-600 to-violet-600 rounded-2xl flex items-center justify-center text-white font-bold text-2xl leading-none pt-0.5">S</div>
90
- <a href="#home" class="heading-font text-3xl font-semibold tracking-tighter text-slate-900">Semantix</a>
91
- </div>
92
-
93
- <nav class="nav-mobile-hide md:flex items-center gap-x-10 text-sm font-medium">
94
- <a href="#home" class="hover:text-indigo-600 transition-colors">Home</a>
95
- <a href="#about" class="hover:text-indigo-600 transition-colors">About</a>
96
- <a href="#service" class="hover:text-indigo-600 transition-colors">Service</a>
97
- <a href="#contact" class="hover:text-indigo-600 transition-colors">Contact</a>
98
- </nav>
99
-
100
- <a href="#authView" class="px-5 py-2.5 text-sm font-semibold bg-indigo-600 hover:bg-indigo-700 text-white rounded-2xl transition-colors">Get Started</a>
101
- </div>
102
- </header>
103
-
104
- <main>
105
- <section id="home" class="hero-bg min-h-screen flex items-center relative overflow-hidden">
106
- <div class="absolute inset-0 bg-[radial-gradient(at_50%_30%,rgba(129,140,248,0.15),transparent)]"></div>
107
-
108
- <div class="max-w-7xl mx-auto px-6 md:px-8 grid md:grid-cols-12 gap-14 items-center relative z-10 py-16">
109
- <div class="md:col-span-7">
110
- <div class="inline-flex items-center gap-x-2 bg-white/10 backdrop-blur-md border border-white/20 text-white text-xs font-medium px-4 py-2 rounded-3xl mb-6">
111
- <span class="relative flex h-3 w-3">
112
- <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
113
- <span class="relative inline-flex rounded-full h-3 w-3 bg-emerald-500"></span>
114
- </span>
115
- AI LEGAL INTELLIGENCE
116
- </div>
117
-
118
- <h1 class="heading-font text-5xl md:text-7xl leading-none font-semibold tracking-tighter text-white max-w-2xl">
119
- Legal Documents,<br />Deeply Understood
120
- </h1>
121
-
122
- <p class="mt-8 text-lg md:text-xl text-slate-300 max-w-xl">
123
- Advanced semantic analysis that uncovers hidden risks and delivers crystal-clear clarity in every contract.
124
- </p>
125
-
126
- <div class="mt-12 flex justify-center md:justify-start">
127
- <div class="document-3d relative inline-block">
128
- <div class="document-inner w-[300px] md:w-[320px] h-[360px] md:h-[380px] bg-white rounded-3xl overflow-hidden border border-white/40 relative">
129
- <div class="h-12 bg-gradient-to-r from-indigo-600 to-violet-600 flex items-center px-6 text-white text-sm font-medium">
130
- CONTRACT • PAGE 1
131
- </div>
132
-
133
- <div class="p-6 space-y-3 text-[10px] leading-tight text-slate-700 font-mono">
134
- <div class="h-2.5 bg-slate-200 rounded w-3/4"></div>
135
- <div class="h-2.5 bg-slate-200 rounded w-11/12"></div>
136
- <div class="h-2.5 bg-slate-200 rounded w-5/6"></div>
137
- <div class="h-2.5 bg-slate-200 rounded w-full"></div>
138
- <div class="h-2.5 bg-slate-200 rounded w-3/4"></div>
139
- <div class="h-2.5 bg-slate-200 rounded w-10/12"></div>
140
- </div>
141
-
142
- <div class="absolute inset-0 bg-gradient-to-br from-indigo-400/10 to-violet-400/10 flex items-center justify-center">
143
- <i class="fa-solid fa-wand-magic-sparkles text-white text-[120px] opacity-30"></i>
144
- </div>
145
- <div class="scan-line"></div>
146
- </div>
147
- </div>
148
- </div>
149
- </div>
150
-
151
- <div class="md:col-span-5">
152
- <section id="authView" class="bg-white rounded-3xl shadow-2xl p-8 md:p-10 card">
153
- <div class="form-header mb-8">
154
- <div class="switcher grid grid-cols-2 bg-slate-100 p-1 rounded-2xl mb-3" role="tablist" aria-label="Auth mode">
155
- <button id="loginTab" class="active px-7 py-3 text-sm font-semibold rounded-[14px]" type="button">Login</button>
156
- <button id="signupTab" class="px-7 py-3 text-sm font-semibold rounded-[14px]" type="button">Sign Up</button>
157
- </div>
158
- <p id="formSubtitle" class="text-slate-500 text-sm">Enter your credentials to access your account.</p>
159
- </div>
160
-
161
- <form id="authForm" class="space-y-5" novalidate>
162
- <div id="nameField" class="hidden">
163
- <label class="text-xs uppercase tracking-widest text-slate-500 block mb-1" for="fullName">Full Name</label>
164
- <input id="fullName" name="fullName" type="text" placeholder="Jayasree" class="w-full bg-zinc-50 border border-slate-200 focus:border-indigo-500 rounded-2xl px-5 py-4 outline-none" />
165
- </div>
166
- <div>
167
- <label class="text-xs uppercase tracking-widest text-slate-500 block mb-1" for="email">Email</label>
168
- <input id="email" name="email" type="email" placeholder="you@lawfirm.in" autocomplete="email" required class="w-full bg-zinc-50 border border-slate-200 focus:border-indigo-500 rounded-2xl px-5 py-4 outline-none" />
169
- </div>
170
- <div>
171
- <label class="text-xs uppercase tracking-widest text-slate-500 block mb-1" for="password">Password</label>
172
- <input id="password" name="password" type="password" placeholder="Minimum 6 characters" autocomplete="current-password" required class="w-full bg-zinc-50 border border-slate-200 focus:border-indigo-500 rounded-2xl px-5 py-4 outline-none" />
173
- </div>
174
- <button id="submitBtn" type="submit" class="w-full bg-indigo-600 hover:bg-indigo-700 transition-colors text-white font-semibold py-4 rounded-3xl">Login</button>
175
- </form>
176
- <p id="message" class="text-center text-sm mt-6 text-slate-500"></p>
177
- </section>
178
- </div>
179
- </div>
180
- </section>
181
-
182
- <section id="about" class="py-20 bg-white">
183
- <div class="max-w-4xl mx-auto px-8 text-center">
184
- <h2 class="heading-font text-4xl md:text-5xl font-semibold tracking-tighter mb-6">Reliable. Precise. Intelligent.</h2>
185
- <p class="text-lg text-slate-600 max-w-2xl mx-auto">
186
- Semantix delivers clear, accurate semantic analysis of legal documents, helping you catch issues instantly and work with confidence.
187
- </p>
188
- </div>
189
- </section>
190
-
191
- <section id="service" class="py-24 bg-slate-50">
192
- <div class="max-w-7xl mx-auto px-8">
193
- <h2 class="heading-font text-center text-4xl md:text-5xl font-semibold tracking-tighter mb-16">Built for serious legal work</h2>
194
- <div class="grid md:grid-cols-3 gap-8">
195
- <div class="bg-white p-10 rounded-3xl card text-center">
196
- <div class="text-5xl mb-6">🔐</div>
197
- <h3 class="font-semibold text-xl">Enterprise Security</h3>
198
- <p class="text-slate-500 mt-3">Your documents stay private and protected.</p>
199
- </div>
200
- <div class="bg-white p-10 rounded-3xl card text-center">
201
- <div class="text-5xl mb-6">🧠</div>
202
- <h3 class="font-semibold text-xl">Smart Analysis</h3>
203
- <p class="text-slate-500 mt-3">Understands legal language like a senior counsel.</p>
204
- </div>
205
- <div class="bg-white p-10 rounded-3xl card text-center">
206
- <div class="text-5xl mb-6">📈</div>
207
- <h3 class="font-semibold text-xl">Instant Insights</h3>
208
- <p class="text-slate-500 mt-3">Visual dashboard with line-level clarity.</p>
209
- </div>
210
- </div>
211
- </div>
212
- </section>
213
-
214
- <section id="contact" class="py-20 bg-slate-900 text-white text-center">
215
- <div class="max-w-7xl mx-auto px-8">
216
- <p class="text-sm uppercase tracking-widest text-slate-400">Made for legal professionals</p>
217
- <h2 class="heading-font text-4xl mt-4">Ready for flawless contracts?</h2>
218
- <a href="mailto:hello@semantix.ai" class="inline-block mt-10 px-10 py-4 bg-white text-slate-900 font-semibold rounded-3xl hover:bg-indigo-50 transition-colors">Contact Us</a>
219
- <p class="mt-20 text-xs text-slate-500">© 2026 Semantix • Legal Semantic Intelligence</p>
220
- </div>
221
- </section>
222
- </main>
223
-
224
- <script src="app.js"></script>
225
- </body>
226
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/issues.html DELETED
@@ -1,48 +0,0 @@
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>Issue Analysis | LegalSI</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
- <link
10
- href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;700;800&family=Space+Grotesk:wght@500;700&display=swap"
11
- rel="stylesheet"
12
- />
13
- <link rel="stylesheet" href="styles.css" />
14
- </head>
15
- <body>
16
- <header class="topbar">
17
- <div class="container topbar-inner">
18
- <a class="brand" href="index.html#home">LegalSI</a>
19
- <div class="page-links">
20
- <a class="page-link" href="upload.html">Upload</a>
21
- <a class="page-link active" href="issues.html">Issue Analysis</a>
22
- <a class="page-link" href="summary.html">Final Summary</a>
23
- <button id="logoutBtn" class="logout-btn" type="button">Logout</button>
24
- </div>
25
- </div>
26
- </header>
27
-
28
- <main class="flow-main">
29
- <section class="container flow-card">
30
- <div class="upload-header">
31
- <h1>Line-Level Issue Analysis</h1>
32
- <span id="userBadge" class="user-badge"></span>
33
- </div>
34
- <p class="upload-subtitle">Inconsistencies, contradictions, and duplications with page and line references.</p>
35
-
36
- <div id="issueStats" class="stats-grid"></div>
37
- <div id="lineIssueTables"></div>
38
-
39
- <div class="workflow-actions">
40
- <a class="secondary-btn as-link" href="upload.html">Back to Upload</a>
41
- <a class="submit-btn as-link submit-link" href="summary.html">Next: Final Summary</a>
42
- </div>
43
- </section>
44
- </main>
45
-
46
- <script src="app.js"></script>
47
- </body>
48
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/styles.css DELETED
@@ -1,957 +0,0 @@
1
- :root {
2
- --bg: #f3f5f8;
3
- --surface: #ffffff;
4
- --surface-soft: #f8fafc;
5
- --ink: #0e2238;
6
- --muted: #5b6f85;
7
- --border: #d3dee9;
8
- --navy: #12385f;
9
- --navy-2: #1f4d79;
10
- --gold: #b78a28;
11
- --primary: #1f5fa6;
12
- --primary-2: #2e79c8;
13
- --teal: #1f8a75;
14
- --danger: #b93f4f;
15
- --ok: #166a47;
16
- }
17
-
18
- * {
19
- box-sizing: border-box;
20
- }
21
-
22
- html {
23
- scroll-behavior: smooth;
24
- }
25
-
26
- body {
27
- margin: 0;
28
- font-family: "Manrope", sans-serif;
29
- color: var(--ink);
30
- background:
31
- radial-gradient(1000px 450px at -10% -8%, #dfe9f5 0%, rgba(223, 233, 245, 0) 60%),
32
- radial-gradient(900px 420px at 110% -10%, #ece5d5 0%, rgba(236, 229, 213, 0) 58%),
33
- linear-gradient(180deg, #eff3f7 0%, #f8fafd 42%, #ffffff 100%);
34
- line-height: 1.45;
35
- }
36
-
37
- .container {
38
- width: min(1180px, 92%);
39
- margin: 0 auto;
40
- }
41
-
42
- .topbar {
43
- position: sticky;
44
- top: 0;
45
- z-index: 20;
46
- background: rgba(249, 251, 253, 0.94);
47
- backdrop-filter: blur(6px);
48
- border-bottom: 1px solid #cfd9e4;
49
- box-shadow: 0 4px 18px rgba(14, 34, 56, 0.06);
50
- }
51
-
52
- .topbar-inner {
53
- display: flex;
54
- align-items: center;
55
- justify-content: space-between;
56
- min-height: 68px;
57
- }
58
-
59
- .brand {
60
- font-family: "Space Grotesk", sans-serif;
61
- font-size: 24px;
62
- font-weight: 700;
63
- color: var(--navy);
64
- text-decoration: none;
65
- }
66
-
67
- .nav-links {
68
- display: flex;
69
- gap: 20px;
70
- }
71
-
72
- .nav-links a {
73
- color: #264868;
74
- text-decoration: none;
75
- font-weight: 700;
76
- font-size: 14px;
77
- padding: 6px 8px;
78
- border-radius: 8px;
79
- }
80
-
81
- .nav-links a:hover {
82
- background: #e9f0f8;
83
- color: var(--navy);
84
- }
85
-
86
- .hero {
87
- position: relative;
88
- padding: 48px 0 42px;
89
- overflow: hidden;
90
- }
91
-
92
- .hero-bg {
93
- position: absolute;
94
- inset: 0;
95
- background:
96
- linear-gradient(120deg, rgba(18, 56, 95, 0.1), rgba(183, 138, 40, 0.09)),
97
- url("assets/legal-tech-bg.svg") right center / cover no-repeat;
98
- opacity: 0.95;
99
- pointer-events: none;
100
- }
101
-
102
- .hero-grid {
103
- position: relative;
104
- display: grid;
105
- grid-template-columns: 1.1fr 0.95fr;
106
- gap: 24px;
107
- align-items: start;
108
- }
109
-
110
- .hero-copy {
111
- background: rgba(255, 255, 255, 0.82);
112
- border: 1px solid var(--border);
113
- border-radius: 20px;
114
- padding: 24px;
115
- box-shadow: 0 14px 34px rgba(15, 38, 66, 0.11);
116
- animation: fadeInUp 0.45s ease-out;
117
- }
118
-
119
- .eyebrow {
120
- margin: 0 0 10px;
121
- font-size: 13px;
122
- letter-spacing: 0.05em;
123
- text-transform: uppercase;
124
- color: var(--navy-2);
125
- font-weight: 800;
126
- }
127
-
128
- .hero-copy h1 {
129
- margin: 0;
130
- font-size: clamp(30px, 4.6vw, 50px);
131
- line-height: 1.08;
132
- font-family: "Space Grotesk", sans-serif;
133
- }
134
-
135
- .hero-text {
136
- margin: 14px 0 18px;
137
- color: var(--muted);
138
- line-height: 1.6;
139
- max-width: 66ch;
140
- }
141
-
142
- .hero-cta-row {
143
- display: flex;
144
- gap: 10px;
145
- flex-wrap: wrap;
146
- margin: 8px 0 14px;
147
- }
148
-
149
- .hero-cta-primary,
150
- .hero-cta-secondary {
151
- text-decoration: none;
152
- border-radius: 11px;
153
- font-size: 14px;
154
- font-weight: 800;
155
- padding: 10px 14px;
156
- }
157
-
158
- .hero-cta-primary {
159
- color: #ffffff;
160
- background: linear-gradient(92deg, var(--navy), var(--primary-2) 58%, var(--teal));
161
- box-shadow: 0 10px 18px rgba(17, 62, 110, 0.22);
162
- }
163
-
164
- .hero-cta-secondary {
165
- color: #1c446b;
166
- background: #ecf4ff;
167
- border: 1px solid #bfd6f2;
168
- }
169
-
170
- .trust-strip {
171
- display: flex;
172
- flex-wrap: wrap;
173
- gap: 8px;
174
- margin: 0 0 14px;
175
- }
176
-
177
- .trust-strip span {
178
- border: 1px solid #d0dded;
179
- border-radius: 999px;
180
- padding: 5px 10px;
181
- font-size: 12px;
182
- font-weight: 700;
183
- color: #315579;
184
- background: #f5f9ff;
185
- }
186
-
187
- .hero-metrics {
188
- display: grid;
189
- grid-template-columns: repeat(3, 1fr);
190
- gap: 10px;
191
- }
192
-
193
- .hero-metrics > div {
194
- border: 1px solid #d5e2f0;
195
- background: #ffffff;
196
- border-radius: 12px;
197
- padding: 12px;
198
- transition: transform 0.18s ease, box-shadow 0.18s ease;
199
- }
200
-
201
- .hero-metrics > div:hover {
202
- transform: translateY(-2px);
203
- box-shadow: 0 10px 18px rgba(16, 43, 74, 0.09);
204
- }
205
-
206
- .hero-metrics h3 {
207
- margin: 0;
208
- font-size: 14px;
209
- }
210
-
211
- .hero-metrics p {
212
- margin: 6px 0 0;
213
- color: var(--muted);
214
- font-size: 12px;
215
- }
216
-
217
- .preview-card {
218
- margin-top: 12px;
219
- border: 1px solid #ccdaea;
220
- border-radius: 14px;
221
- padding: 12px;
222
- background: linear-gradient(160deg, #f7fbff 0%, #edf5ff 100%);
223
- }
224
-
225
- .preview-card h3 {
226
- margin: 0 0 10px;
227
- font-size: 14px;
228
- color: #163a60;
229
- }
230
-
231
- .preview-grid {
232
- display: grid;
233
- grid-template-columns: repeat(4, 1fr);
234
- gap: 8px;
235
- }
236
-
237
- .preview-grid div {
238
- border: 1px solid #c8d9ec;
239
- border-radius: 10px;
240
- background: #ffffff;
241
- padding: 8px;
242
- display: grid;
243
- gap: 3px;
244
- }
245
-
246
- .preview-grid span {
247
- font-size: 11px;
248
- color: #5a7090;
249
- }
250
-
251
- .preview-grid strong {
252
- font-size: 19px;
253
- color: #15395e;
254
- }
255
-
256
- .panel {
257
- background: var(--surface);
258
- border: 1px solid var(--border);
259
- border-radius: 18px;
260
- box-shadow: 0 14px 30px rgba(12, 31, 53, 0.12);
261
- animation: fadeInUp 0.5s ease-out;
262
- }
263
-
264
- .auth-panel {
265
- padding: 22px;
266
- }
267
-
268
- .form-header {
269
- margin-bottom: 18px;
270
- }
271
-
272
- .switcher {
273
- display: grid;
274
- grid-template-columns: 1fr 1fr;
275
- background: #e9eff7;
276
- border-radius: 12px;
277
- padding: 4px;
278
- margin-bottom: 12px;
279
- }
280
-
281
- .switcher button {
282
- border: 0;
283
- background: transparent;
284
- border-radius: 9px;
285
- padding: 10px;
286
- font-weight: 800;
287
- cursor: pointer;
288
- color: #315579;
289
- transition: background 0.2s ease, color 0.2s ease, transform 0.12s ease;
290
- }
291
-
292
- .switcher button.active {
293
- color: #112a48;
294
- background: #ffffff;
295
- box-shadow: 0 6px 14px rgba(8, 26, 49, 0.08);
296
- }
297
-
298
- .switcher button:active {
299
- transform: scale(0.98);
300
- }
301
-
302
- #formSubtitle {
303
- margin: 0;
304
- color: var(--muted);
305
- font-size: 14px;
306
- }
307
-
308
- .auth-form {
309
- display: grid;
310
- gap: 14px;
311
- }
312
-
313
- .field {
314
- display: grid;
315
- gap: 7px;
316
- }
317
-
318
- .field label {
319
- font-size: 14px;
320
- font-weight: 700;
321
- }
322
-
323
- .field input,
324
- .control {
325
- border: 1px solid var(--border);
326
- border-radius: 12px;
327
- padding: 12px 13px;
328
- font: inherit;
329
- background: #ffffff;
330
- outline: none;
331
- width: 100%;
332
- }
333
-
334
- .field input:focus,
335
- .control:focus {
336
- border-color: var(--primary);
337
- box-shadow: 0 0 0 4px rgba(31, 95, 166, 0.16);
338
- }
339
-
340
- .hidden {
341
- display: none;
342
- }
343
-
344
- .submit-btn {
345
- margin-top: 8px;
346
- border: 0;
347
- border-radius: 12px;
348
- padding: 12px;
349
- background: linear-gradient(92deg, var(--navy), var(--primary-2) 58%, var(--teal));
350
- color: #ffffff;
351
- font-weight: 800;
352
- font-size: 15px;
353
- cursor: pointer;
354
- transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
355
- }
356
-
357
- .submit-btn:hover {
358
- filter: brightness(1.03);
359
- transform: translateY(-1px);
360
- box-shadow: 0 10px 18px rgba(17, 62, 110, 0.22);
361
- }
362
-
363
- .message {
364
- min-height: 22px;
365
- margin: 14px 0 0;
366
- font-size: 14px;
367
- font-weight: 700;
368
- }
369
-
370
- .message.success {
371
- color: var(--ok);
372
- }
373
-
374
- .message.error {
375
- color: var(--danger);
376
- }
377
-
378
- .upload-header {
379
- display: flex;
380
- align-items: center;
381
- justify-content: space-between;
382
- }
383
-
384
- .upload-header h2 {
385
- margin: 0;
386
- font-family: "Space Grotesk", sans-serif;
387
- }
388
-
389
- .upload-subtitle {
390
- margin: 10px 0 18px;
391
- color: var(--muted);
392
- }
393
-
394
- .stepper {
395
- display: grid;
396
- grid-template-columns: repeat(3, 1fr);
397
- gap: 8px;
398
- margin: 10px 0 16px;
399
- }
400
-
401
- .step-chip {
402
- text-align: center;
403
- border: 1px solid var(--border);
404
- border-radius: 10px;
405
- padding: 8px 10px;
406
- font-size: 13px;
407
- font-weight: 800;
408
- color: #5d7190;
409
- background: #f3f6fb;
410
- transition: all 0.2s ease;
411
- }
412
-
413
- .step-chip.active {
414
- color: #0f2d4e;
415
- border-color: #b7cde7;
416
- background: #e8f1fc;
417
- box-shadow: inset 0 0 0 1px rgba(38, 97, 166, 0.15);
418
- }
419
-
420
- .workflow-step {
421
- margin-top: 6px;
422
- }
423
-
424
- .summary-box {
425
- border: 1px solid var(--border);
426
- border-radius: 12px;
427
- background: var(--surface-soft);
428
- padding: 12px;
429
- color: #25496f;
430
- box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);
431
- }
432
-
433
- .summary-box p {
434
- margin: 5px 0;
435
- font-size: 14px;
436
- }
437
-
438
- .workflow-actions {
439
- display: flex;
440
- gap: 10px;
441
- margin-top: 12px;
442
- flex-wrap: wrap;
443
- }
444
-
445
- .upload-zone-wrap {
446
- margin-top: 2px;
447
- }
448
-
449
- .upload-zone {
450
- border: 1.5px dashed #b8cbe0;
451
- border-radius: 14px;
452
- background: linear-gradient(180deg, #f8fbff 0%, #f3f8ff 100%);
453
- min-height: 132px;
454
- display: grid;
455
- place-content: center;
456
- text-align: center;
457
- gap: 6px;
458
- cursor: pointer;
459
- padding: 14px;
460
- transition: border-color 0.2s ease, background 0.2s ease, transform 0.18s ease;
461
- }
462
-
463
- .upload-zone:hover {
464
- border-color: #7ca4cf;
465
- background: linear-gradient(180deg, #fafdff 0%, #eef5ff 100%);
466
- transform: translateY(-1px);
467
- }
468
-
469
- .upload-icon {
470
- width: 34px;
471
- height: 34px;
472
- border-radius: 999px;
473
- margin: 0 auto;
474
- display: grid;
475
- place-content: center;
476
- font-size: 22px;
477
- font-weight: 700;
478
- color: #21507f;
479
- background: #e5eef9;
480
- }
481
-
482
- .upload-title {
483
- font-size: 14px;
484
- font-weight: 800;
485
- color: #1f4469;
486
- }
487
-
488
- .upload-hint {
489
- font-size: 12px;
490
- color: #5f7691;
491
- }
492
-
493
- .file-input-hidden {
494
- position: absolute;
495
- left: -10000px;
496
- width: 1px;
497
- height: 1px;
498
- opacity: 0;
499
- }
500
-
501
- .chat-panel {
502
- border: 1px solid var(--border);
503
- border-radius: 12px;
504
- background: #f7fbff;
505
- padding: 12px;
506
- margin-top: 10px;
507
- display: grid;
508
- gap: 10px;
509
- max-height: 220px;
510
- overflow-y: auto;
511
- }
512
-
513
- .chat-bubble {
514
- padding: 10px 12px;
515
- border-radius: 12px;
516
- font-size: 13px;
517
- line-height: 1.5;
518
- }
519
-
520
- .chat-bubble.user {
521
- justify-self: end;
522
- max-width: 92%;
523
- background: #e8f1ff;
524
- border: 1px solid #bfd6f4;
525
- color: #1f4268;
526
- }
527
-
528
- .chat-bubble.bot {
529
- justify-self: start;
530
- max-width: 96%;
531
- background: #ffffff;
532
- border: 1px solid #d4e0ee;
533
- color: #274968;
534
- }
535
-
536
- .logout-btn {
537
- border: 1px solid var(--border);
538
- background: #ffffff;
539
- border-radius: 10px;
540
- padding: 8px 12px;
541
- font-weight: 700;
542
- cursor: pointer;
543
- }
544
-
545
- .secondary-btn {
546
- border: 1px solid #b8cbe0;
547
- background: #f1f6fc;
548
- color: #1f4469;
549
- border-radius: 12px;
550
- padding: 12px 14px;
551
- font-weight: 800;
552
- font-size: 14px;
553
- cursor: pointer;
554
- transition: background 0.18s ease, transform 0.14s ease;
555
- }
556
-
557
- .secondary-btn:hover {
558
- background: #e7f0fa;
559
- }
560
-
561
- .secondary-btn:active {
562
- transform: scale(0.98);
563
- }
564
-
565
- .section {
566
- padding: 20px 0 26px;
567
- }
568
-
569
- .section-card {
570
- background: var(--surface);
571
- border: 1px solid var(--border);
572
- border-radius: 18px;
573
- padding: 24px;
574
- box-shadow: 0 10px 24px rgba(12, 34, 58, 0.09);
575
- transition: box-shadow 0.2s ease, transform 0.2s ease;
576
- }
577
-
578
- .section-card:hover {
579
- box-shadow: 0 14px 26px rgba(12, 34, 58, 0.13);
580
- transform: translateY(-1px);
581
- }
582
-
583
- .section-card h2 {
584
- margin: 0 0 10px;
585
- font-family: "Space Grotesk", sans-serif;
586
- }
587
-
588
- .section-card p {
589
- margin: 0;
590
- color: var(--muted);
591
- line-height: 1.7;
592
- }
593
-
594
- .service-grid {
595
- margin-top: 14px;
596
- display: grid;
597
- grid-template-columns: repeat(3, 1fr);
598
- gap: 12px;
599
- }
600
-
601
- .service-grid article {
602
- border: 1px solid var(--border);
603
- border-radius: 12px;
604
- padding: 14px;
605
- background: var(--surface-soft);
606
- }
607
-
608
- .service-grid h3 {
609
- margin: 0 0 8px;
610
- font-size: 16px;
611
- }
612
-
613
- .contact-grid {
614
- margin-top: 14px;
615
- display: grid;
616
- gap: 8px;
617
- color: #193b61;
618
- }
619
-
620
- .analysis-result {
621
- margin-top: 16px;
622
- border-top: 1px solid var(--border);
623
- padding-top: 14px;
624
- }
625
-
626
- .result-summary h3 {
627
- margin: 0 0 8px;
628
- font-family: "Space Grotesk", sans-serif;
629
- }
630
-
631
- .result-summary p {
632
- margin: 4px 0;
633
- color: #1d3352;
634
- }
635
-
636
- .result-visual {
637
- margin-top: 12px;
638
- border: 1px solid var(--border);
639
- border-radius: 12px;
640
- padding: 12px;
641
- background: linear-gradient(180deg, #f8fbff 0%, #f4f8fd 100%);
642
- }
643
-
644
- .result-visual h3 {
645
- margin: 0 0 10px;
646
- }
647
-
648
- .bar-row {
649
- display: grid;
650
- grid-template-columns: 170px 1fr 52px;
651
- align-items: center;
652
- gap: 8px;
653
- margin-bottom: 8px;
654
- }
655
-
656
- .bar-label,
657
- .bar-value {
658
- font-size: 13px;
659
- font-weight: 700;
660
- }
661
-
662
- .bar-track {
663
- width: 100%;
664
- height: 12px;
665
- border-radius: 999px;
666
- background: #dde5f1;
667
- overflow: hidden;
668
- }
669
-
670
- .bar-fill {
671
- height: 100%;
672
- border-radius: 999px;
673
- }
674
-
675
- .bar-fill.dup {
676
- background: #2d6ec8;
677
- }
678
-
679
- .bar-fill.inc {
680
- background: #d08f28;
681
- }
682
-
683
- .bar-fill.con {
684
- background: #bd4b58;
685
- }
686
-
687
- .result-list {
688
- margin-top: 12px;
689
- display: grid;
690
- gap: 10px;
691
- }
692
-
693
- .result-card {
694
- border: 1px solid var(--border);
695
- border-radius: 12px;
696
- padding: 10px 12px;
697
- background: #f9fbfe;
698
- transition: box-shadow 0.16s ease;
699
- }
700
-
701
- .result-card:hover {
702
- box-shadow: 0 10px 20px rgba(12, 34, 58, 0.09);
703
- }
704
-
705
- .result-card h4 {
706
- margin: 0 0 6px;
707
- }
708
-
709
- .result-muted {
710
- color: var(--muted);
711
- }
712
-
713
- .table-wrap {
714
- width: 100%;
715
- overflow-x: auto;
716
- }
717
-
718
- .result-table {
719
- width: 100%;
720
- border-collapse: collapse;
721
- margin-top: 8px;
722
- }
723
-
724
- .result-table th,
725
- .result-table td {
726
- border: 1px solid var(--border);
727
- padding: 8px;
728
- text-align: left;
729
- font-size: 13px;
730
- vertical-align: top;
731
- }
732
-
733
- .result-table th {
734
- background: #eef4ff;
735
- }
736
-
737
- @keyframes fadeInUp {
738
- from {
739
- opacity: 0;
740
- transform: translateY(8px);
741
- }
742
- to {
743
- opacity: 1;
744
- transform: translateY(0);
745
- }
746
- }
747
-
748
- @media (max-width: 980px) {
749
- .hero-grid {
750
- grid-template-columns: 1fr;
751
- }
752
-
753
- .hero-metrics {
754
- grid-template-columns: 1fr;
755
- }
756
-
757
- .preview-grid {
758
- grid-template-columns: repeat(2, 1fr);
759
- }
760
-
761
- .service-grid {
762
- grid-template-columns: 1fr;
763
- }
764
-
765
- .bar-row {
766
- grid-template-columns: 1fr;
767
- gap: 6px;
768
- }
769
-
770
- .nav-links {
771
- gap: 12px;
772
- flex-wrap: wrap;
773
- justify-content: flex-end;
774
- }
775
-
776
- .topbar-inner {
777
- padding-block: 8px;
778
- }
779
- }
780
-
781
- .page-links {
782
- display: flex;
783
- align-items: center;
784
- gap: 10px;
785
- }
786
-
787
- .page-link {
788
- border: 1px solid #bfd0e3;
789
- border-radius: 10px;
790
- padding: 6px 10px;
791
- font-size: 13px;
792
- font-weight: 700;
793
- color: #23496f;
794
- text-decoration: none;
795
- background: #f4f8fd;
796
- }
797
-
798
- .page-link.active {
799
- background: #e7f1ff;
800
- border-color: #98b9dc;
801
- color: #14395f;
802
- }
803
-
804
- .flow-main {
805
- padding: 28px 0 36px;
806
- }
807
-
808
- .flow-card {
809
- background: var(--surface);
810
- border: 1px solid var(--border);
811
- border-radius: 18px;
812
- box-shadow: 0 14px 30px rgba(12, 31, 53, 0.12);
813
- padding: 22px;
814
- }
815
-
816
- .flow-card h1 {
817
- margin: 0;
818
- font-family: "Space Grotesk", sans-serif;
819
- font-size: clamp(28px, 4vw, 40px);
820
- }
821
-
822
- .user-badge {
823
- border: 1px solid #c6d9ee;
824
- border-radius: 999px;
825
- padding: 8px 12px;
826
- background: #f2f8ff;
827
- color: #24486d;
828
- font-weight: 700;
829
- font-size: 13px;
830
- }
831
-
832
- .loading-panel {
833
- margin-top: 16px;
834
- border: 1px solid var(--border);
835
- border-radius: 12px;
836
- padding: 18px;
837
- background: #f5f9ff;
838
- display: grid;
839
- justify-items: center;
840
- gap: 10px;
841
- }
842
-
843
- .spinner {
844
- width: 30px;
845
- height: 30px;
846
- border: 3px solid #c8d8eb;
847
- border-top-color: #1f5fa6;
848
- border-radius: 50%;
849
- animation: spin 0.8s linear infinite;
850
- }
851
-
852
- .stats-grid {
853
- display: grid;
854
- grid-template-columns: repeat(3, minmax(0, 1fr));
855
- gap: 10px;
856
- margin: 12px 0 14px;
857
- }
858
-
859
- .stat-card {
860
- border: 1px solid var(--border);
861
- border-radius: 12px;
862
- padding: 12px;
863
- background: #f9fbfe;
864
- }
865
-
866
- .stat-card h3 {
867
- margin: 0;
868
- font-size: 14px;
869
- }
870
-
871
- .stat-card p {
872
- margin: 6px 0 0;
873
- font-size: 28px;
874
- font-weight: 800;
875
- }
876
-
877
- .stat-dup p {
878
- color: #2d6ec8;
879
- }
880
-
881
- .stat-inc p {
882
- color: #d08f28;
883
- }
884
-
885
- .stat-con p {
886
- color: #bd4b58;
887
- }
888
-
889
- .summary-grid {
890
- display: grid;
891
- grid-template-columns: repeat(2, minmax(0, 1fr));
892
- gap: 10px;
893
- margin-bottom: 14px;
894
- }
895
-
896
- .summary-item {
897
- border: 1px solid var(--border);
898
- border-radius: 12px;
899
- padding: 10px;
900
- background: #f9fbfe;
901
- display: grid;
902
- gap: 4px;
903
- }
904
-
905
- .summary-item span {
906
- color: var(--muted);
907
- font-size: 13px;
908
- }
909
-
910
- .summary-item strong {
911
- color: #1b3d63;
912
- font-size: 14px;
913
- }
914
-
915
- .section-subtitle {
916
- margin: 6px 0 10px;
917
- font-family: "Space Grotesk", sans-serif;
918
- font-size: 20px;
919
- color: #183d62;
920
- }
921
-
922
- .detailed-summary-text {
923
- white-space: pre-wrap;
924
- line-height: 1.65;
925
- color: #1d3552;
926
- font-size: 14px;
927
- }
928
-
929
- .as-link {
930
- text-decoration: none;
931
- display: inline-flex;
932
- align-items: center;
933
- justify-content: center;
934
- }
935
-
936
- .submit-link {
937
- min-width: 220px;
938
- }
939
-
940
- @keyframes spin {
941
- to {
942
- transform: rotate(360deg);
943
- }
944
- }
945
-
946
- @media (max-width: 980px) {
947
- .page-links {
948
- gap: 6px;
949
- flex-wrap: wrap;
950
- justify-content: flex-end;
951
- }
952
-
953
- .stats-grid,
954
- .summary-grid {
955
- grid-template-columns: 1fr;
956
- }
957
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/summary.html DELETED
@@ -1,59 +0,0 @@
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>Final Summary | LegalSI</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
- <link
10
- href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;700;800&family=Space+Grotesk:wght@500;700&display=swap"
11
- rel="stylesheet"
12
- />
13
- <link rel="stylesheet" href="styles.css" />
14
- </head>
15
- <body>
16
- <header class="topbar">
17
- <div class="container topbar-inner">
18
- <a class="brand" href="index.html#home">LegalSI</a>
19
- <div class="page-links">
20
- <a class="page-link" href="upload.html">Upload</a>
21
- <a class="page-link" href="issues.html">Issue Analysis</a>
22
- <a class="page-link active" href="summary.html">Final Summary</a>
23
- <button id="logoutBtn" class="logout-btn" type="button">Logout</button>
24
- </div>
25
- </div>
26
- </header>
27
-
28
- <main class="flow-main">
29
- <section class="container flow-card">
30
- <div class="upload-header">
31
- <h1>Final Document Summary</h1>
32
- <span id="userBadge" class="user-badge"></span>
33
- </div>
34
- <p class="upload-subtitle">Overall analysis result for the entire uploaded legal document.</p>
35
-
36
- <div id="summaryDetails" class="summary-grid"></div>
37
- <h3 class="section-subtitle">Detailed Document Summary</h3>
38
- <article class="result-card">
39
- <div id="detailedSummaryText" class="detailed-summary-text"></div>
40
- </article>
41
- <h3 class="section-subtitle">Page-wise Summary</h3>
42
- <div id="pageSummaryBoard" class="result-list"></div>
43
- <h3 class="section-subtitle">Top Findings</h3>
44
- <div id="findingsBoard" class="result-list"></div>
45
- <h3 class="section-subtitle">Line Error Dashboard</h3>
46
- <article class="result-card">
47
- <div id="lineErrorDashboard"></div>
48
- </article>
49
-
50
- <div class="workflow-actions">
51
- <a class="secondary-btn as-link" href="issues.html">Back to Issue Analysis</a>
52
- <a class="submit-btn as-link submit-link" href="upload.html">Analyze New Document</a>
53
- </div>
54
- </section>
55
- </main>
56
-
57
- <script src="app.js"></script>
58
- </body>
59
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/upload.html DELETED
@@ -1,75 +0,0 @@
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>Upload Document | LegalSI</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
- <link
10
- href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;700;800&family=Space+Grotesk:wght@500;700&display=swap"
11
- rel="stylesheet"
12
- />
13
- <link rel="stylesheet" href="styles.css" />
14
- </head>
15
- <body>
16
- <header class="topbar">
17
- <div class="container topbar-inner">
18
- <a class="brand" href="index.html#home">LegalSI</a>
19
- <div class="page-links">
20
- <a class="page-link active" href="upload.html">Upload</a>
21
- <a class="page-link" href="issues.html">Issue Analysis</a>
22
- <a class="page-link" href="summary.html">Final Summary</a>
23
- <button id="logoutBtn" class="logout-btn" type="button">Logout</button>
24
- </div>
25
- </div>
26
- </header>
27
-
28
- <main class="flow-main">
29
- <section class="container flow-card">
30
- <div class="upload-header">
31
- <h1>Upload Document</h1>
32
- <span id="userBadge" class="user-badge"></span>
33
- </div>
34
- <p class="upload-subtitle">Upload legal document, then continue to issue analysis and final summary pages.</p>
35
-
36
- <form id="uploadForm" class="auth-form" novalidate>
37
- <div class="field">
38
- <label for="scanMode">Scan Mode</label>
39
- <select id="scanMode" class="control">
40
- <option>Standard Scan (Recommended)</option>
41
- <option>Deep Search (Fuzzy)</option>
42
- <option>Strict (Duplicates Only)</option>
43
- </select>
44
- </div>
45
-
46
- <div class="field upload-zone-wrap">
47
- <label for="legalFile">Upload File (PDF/DOCX/TXT)</label>
48
- <label class="upload-zone" for="legalFile">
49
- <span class="upload-icon">+</span>
50
- <span class="upload-title">Drop your document or click to browse</span>
51
- <span class="upload-hint">Supported: PDF, DOCX, TXT</span>
52
- </label>
53
- <input id="legalFile" class="control file-input-hidden" type="file" accept=".pdf,.docx,.txt" required />
54
- </div>
55
-
56
- <div id="analysisInputSummary" class="summary-box hidden"></div>
57
-
58
- <div class="workflow-actions">
59
- <a class="secondary-btn as-link" href="index.html#home">Back to Home</a>
60
- <button id="runUploadBtn" class="submit-btn" type="submit">Upload and Analyze</button>
61
- </div>
62
- </form>
63
-
64
- <div id="loadingState" class="loading-panel hidden" aria-live="polite">
65
- <div class="spinner"></div>
66
- <p>Analyzing document. Please wait...</p>
67
- </div>
68
-
69
- <p id="uploadMessage" class="message" aria-live="polite"></p>
70
- </section>
71
- </main>
72
-
73
- <script src="app.js"></script>
74
- </body>
75
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/workflow.html DELETED
@@ -1,11 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta http-equiv="refresh" content="0;url=upload.html" />
6
- <title>Redirecting</title>
7
- </head>
8
- <body>
9
- <p>Redirecting to upload page...</p>
10
- </body>
11
- </html>