Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>VoiceVault β AI Knowledge Agent</title> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="/static/style.css"> | |
| </head> | |
| <body> | |
| <!-- Animated background orbs --> | |
| <div class="bg-orbs" aria-hidden="true"> | |
| <div class="orb orb-1"></div> | |
| <div class="orb orb-2"></div> | |
| <div class="orb orb-3"></div> | |
| </div> | |
| <!-- App shell --> | |
| <div class="app"> | |
| <!-- βββ Sidebar βββββββββββββββββββββββββββββββββββββββββ --> | |
| <aside class="sidebar"> | |
| <!-- Logo --> | |
| <div class="sidebar-logo"> | |
| <div class="logo-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z"/> | |
| </svg> | |
| </div> | |
| <div class="logo-text"> | |
| <span class="logo-name">VoiceVault</span> | |
| <span class="logo-tagline">AI Knowledge Agent</span> | |
| </div> | |
| </div> | |
| <!-- Navigation --> | |
| <nav class="sidebar-nav"> | |
| <button class="nav-item active" data-view="ask" onclick="switchView('ask')"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M8.625 12a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 0 1-2.555-.337A5.972 5.972 0 0 1 5.41 20.97a5.969 5.969 0 0 1-.474-.065 4.48 4.48 0 0 0 .978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25Z"/> | |
| </svg> | |
| Ask | |
| </button> | |
| <button class="nav-item" data-view="kbs" onclick="switchView('kbs')"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/> | |
| </svg> | |
| Knowledge Bases | |
| </button> | |
| <button class="nav-item" data-view="analytics" onclick="switchView('analytics')"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z"/> | |
| </svg> | |
| Analytics | |
| </button> | |
| </nav> | |
| <!-- KB quick-list --> | |
| <div class="sidebar-section-title">Knowledge Bases</div> | |
| <div id="sidebar-kb-list"> | |
| <div class="sidebar-kb-empty">No KBs yet</div> | |
| </div> | |
| <div style="flex:1"></div> | |
| <!-- Footer --> | |
| <div class="sidebar-footer"> | |
| <span class="version-badge">v0.1.0</span> | |
| <div class="status-dot" title="Server online"></div> | |
| </div> | |
| </aside> | |
| <!-- βββ Main Content ββββββββββββββββββββββββββββββββββββ --> | |
| <main class="main"> | |
| <!-- βββ Ask View βββββββββββββββββββββββββββββββββββββββ --> | |
| <div class="view" id="view-ask"> | |
| <div class="view-header"> | |
| <div> | |
| <div class="view-title">Ask VoiceVault</div> | |
| <div class="view-subtitle">Speak or type β get cited answers from your documents</div> | |
| </div> | |
| <button class="btn btn-ghost" onclick="clearChat()" title="Clear conversation"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"/> | |
| </svg> | |
| Clear | |
| </button> | |
| </div> | |
| <!-- Chat messages --> | |
| <div class="chat-area" id="chat-area"> | |
| <div class="chat-empty" id="chat-empty"> | |
| <div class="chat-empty-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z"/> | |
| </svg> | |
| </div> | |
| <h3>Ready to answer</h3> | |
| <p>Record your voice or type a question below, then select a Knowledge Base.</p> | |
| </div> | |
| </div> | |
| <!-- Input area --> | |
| <div class="input-area"> | |
| <!-- KB chip selector --> | |
| <div class="kb-selector-wrap"> | |
| <span class="kb-selector-label">KBs:</span> | |
| <div class="kb-chips" id="kb-chips"> | |
| <span class="kb-chips-empty">No knowledge bases β create one first</span> | |
| </div> | |
| </div> | |
| <!-- Text + controls --> | |
| <div class="input-row"> | |
| <button class="mic-btn" id="mic-btn" onclick="toggleRecording()" title="Hold to record"> | |
| <!-- Mic icon (default) --> | |
| <svg id="mic-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 18.75a6 6 0 0 0 6-6v-1.5m-6 7.5a6 6 0 0 1-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 0 1-3-3V4.5a3 3 0 1 1 6 0v8.25a3 3 0 0 1-3 3Z"/> | |
| </svg> | |
| <!-- Stop icon (while recording) --> | |
| <svg id="stop-icon" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24" style="display:none"> | |
| <rect x="6" y="6" width="12" height="12" rx="2"/> | |
| </svg> | |
| </button> | |
| <div class="input-field-wrap"> | |
| <textarea | |
| id="query-input" | |
| placeholder="Speak using the mic, or type your question hereβ¦" | |
| rows="1" | |
| onkeydown="handleInputKey(event)" | |
| oninput="autoResize(this)" | |
| ></textarea> | |
| </div> | |
| <div class="input-actions"> | |
| <button class="tts-btn" id="tts-btn" onclick="speakLastAnswer()" title="Read answer aloud"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z"/> | |
| </svg> | |
| Speak | |
| </button> | |
| <button class="send-btn" id="send-btn" onclick="sendQuery()" title="Send question"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 12 3.269 3.125A59.769 59.769 0 0 1 21.485 12 59.768 59.768 0 0 1 3.27 20.875L5.999 12Zm0 0h7.5"/> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Status indicators --> | |
| <div class="recording-status" id="recording-status"> | |
| <div class="rec-dot"></div> | |
| <div class="waveform show"> | |
| <div class="wave-bar"></div><div class="wave-bar"></div> | |
| <div class="wave-bar"></div><div class="wave-bar"></div> | |
| <div class="wave-bar"></div> | |
| </div> | |
| <span>Recording⦠click Stop when done</span> | |
| </div> | |
| <div class="transcribing-status" id="transcribing-status"> | |
| <div class="transcribing-spinner"></div> | |
| <span>Transcribing with Whisperβ¦</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- βββ Knowledge Bases View ββββββββββββββββββββββββββββ --> | |
| <div class="view hidden" id="view-kbs"> | |
| <div class="view-header"> | |
| <div> | |
| <div class="view-title">Knowledge Bases</div> | |
| <div class="view-subtitle">Create and manage document collections</div> | |
| </div> | |
| <button class="btn btn-primary" onclick="openCreateKBModal()"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15"/> | |
| </svg> | |
| New Knowledge Base | |
| </button> | |
| </div> | |
| <div class="kbs-content"> | |
| <div class="kb-grid" id="kb-grid"> | |
| <div class="kb-empty-state" id="kb-empty"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/> | |
| </svg> | |
| <h3>No knowledge bases yet</h3> | |
| <p>Create your first KB and upload documents to get started.</p> | |
| <button class="btn btn-primary" style="margin-top:8px" onclick="openCreateKBModal()"> | |
| Create Knowledge Base | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- βββ Analytics View ββββββββββββββββββββββββββββββββββ --> | |
| <div class="view hidden" id="view-analytics"> | |
| <div class="view-header"> | |
| <div> | |
| <div class="view-title">Analytics</div> | |
| <div class="view-subtitle">Query statistics β last 7 days</div> | |
| </div> | |
| <button class="btn btn-secondary" onclick="loadAnalytics()"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"/> | |
| </svg> | |
| Refresh | |
| </button> | |
| </div> | |
| <div class="analytics-content"> | |
| <div class="stats-grid" id="stats-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M8.625 12a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375M21 12c0 4.556-4.03 8.25-9 8.25a9.764 9.764 0 0 1-2.555-.337A5.972 5.972 0 0 1 5.41 20.97a5.969 5.969 0 0 1-.474-.065 4.48 4.48 0 0 0 .978-2.025c.09-.457-.133-.901-.467-1.226C3.93 16.178 3 14.189 3 12c0-4.556 4.03-8.25 9-8.25s9 3.694 9 8.25Z"/> | |
| </svg> | |
| </div> | |
| <div class="stat-card-value" id="stat-total-queries">β</div> | |
| <div class="stat-card-label">Total Queries (7d)</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/> | |
| </svg> | |
| </div> | |
| <div class="stat-card-value" id="stat-avg-latency">β</div> | |
| <div class="stat-card-label">Avg Latency (ms)</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/> | |
| </svg> | |
| </div> | |
| <div class="stat-card-value" id="stat-avg-citations">β</div> | |
| <div class="stat-card-label">Avg Citations / Answer</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-card-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/> | |
| </svg> | |
| </div> | |
| <div class="stat-card-value" id="stat-kb-count">β</div> | |
| <div class="stat-card-label">Knowledge Bases</div> | |
| </div> | |
| </div> | |
| <!-- Daily bar chart --> | |
| <div class="section-title">Queries by Day</div> | |
| <div class="day-chart" id="day-chart"> | |
| <div style="color:var(--text-3);font-size:12px;width:100%;text-align:center">Click Refresh to load data</div> | |
| </div> | |
| <!-- KB inventory --> | |
| <div class="section-title">Knowledge Base Inventory</div> | |
| <table class="analytics-table" id="kb-inventory-table"> | |
| <thead> | |
| <tr> | |
| <th>Name</th> | |
| <th>Slug</th> | |
| <th>Documents</th> | |
| <th>Chunks</th> | |
| </tr> | |
| </thead> | |
| <tbody id="kb-inventory-body"> | |
| <tr><td colspan="4" style="color:var(--text-3);text-align:center">Click Refresh to load data</td></tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <!-- βββ Modals βββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div id="modal-overlay" class="modal-overlay hidden" onclick="handleOverlayClick(event)"> | |
| <!-- Create KB Modal --> | |
| <div id="modal-create-kb" class="modal hidden"> | |
| <div class="modal-header"> | |
| <div class="modal-title">New Knowledge Base</div> | |
| <button class="modal-close" onclick="closeModal()"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label" for="new-kb-slug">Slug (ID) <span class="optional">required</span></label> | |
| <input class="form-input" id="new-kb-slug" type="text" placeholder="e.g. research-papers" | |
| oninput="slugifyInput(this)"> | |
| <div class="form-hint">Lowercase letters, digits, hyphens only. 1β64 chars. Cannot start/end with hyphen.</div> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label" for="new-kb-name">Display Name <span class="optional">required</span></label> | |
| <input class="form-input" id="new-kb-name" type="text" placeholder="e.g. Research Papers"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label" for="new-kb-pass">Password <span class="optional">optional</span></label> | |
| <input class="form-input" id="new-kb-pass" type="password" placeholder="Leave blank for public KB"> | |
| <div class="form-hint">If set, a password will be required to upload documents.</div> | |
| </div> | |
| <div class="modal-actions"> | |
| <button class="btn btn-ghost" onclick="closeModal()">Cancel</button> | |
| <button class="btn btn-primary" id="create-kb-btn" onclick="createKB()"> | |
| Create Knowledge Base | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Upload Documents Modal --> | |
| <div id="modal-upload" class="modal hidden"> | |
| <div class="modal-header"> | |
| <div class="modal-title">Upload Documents</div> | |
| <button class="modal-close" onclick="closeModal()"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Knowledge Base</label> | |
| <input class="form-input" id="upload-kb-name" type="text" readonly style="opacity:0.6"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label" for="upload-pass">Password <span class="optional">if protected</span></label> | |
| <input class="form-input" id="upload-pass" type="password" placeholder="Leave blank for public KBs"> | |
| </div> | |
| <div class="form-group"> | |
| <div class="file-drop-zone" id="file-drop-zone" | |
| ondrop="handleDrop(event)" ondragover="handleDragOver(event)" ondragleave="handleDragLeave(event)"> | |
| <input type="file" id="file-input" multiple | |
| accept=".pdf,.docx,.doc,.txt,.md,.html" | |
| onchange="handleFileSelect(event)"> | |
| <div class="file-drop-icon"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M12 16.5V9.75m0 0 3 3m-3-3-3 3M6.75 19.5a4.5 4.5 0 0 1-1.41-8.775 5.25 5.25 0 0 1 10.338-2.32 3.75 3.75 0 0 1 3.832 3.849 4.5 4.5 0 0 1-1.41 8.775H6.75Z"/> | |
| </svg> | |
| </div> | |
| <div class="file-drop-text">Drop files here or click to browse</div> | |
| <div class="file-drop-hint">PDF, DOCX, TXT, MD, HTML</div> | |
| <div class="file-list" id="file-list"></div> | |
| </div> | |
| </div> | |
| <div class="upload-progress" id="upload-progress"></div> | |
| <div class="modal-actions"> | |
| <button class="btn btn-ghost" onclick="closeModal()">Cancel</button> | |
| <button class="btn btn-primary" id="upload-btn" onclick="uploadDocuments()"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"> | |
| <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5m-13.5-9L12 3m0 0 4.5 4.5M12 3v13.5"/> | |
| </svg> | |
| Upload & Index | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Toast container --> | |
| <div id="toasts"></div> | |
| <script src="/static/app.js"></script> | |
| </body> | |
| </html> | |