Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <meta name="description" content="VoxDoc - AI-Powered Voice Symptom Intake & Documentation Assistant"> | |
| <meta name="theme-color" content="#0f111a"> | |
| <title>VoxDoc | Voice Symptom Intake</title> | |
| <link rel="stylesheet" href="/static/css/style.css?v=5"> | |
| <link rel="stylesheet" href="/static/css/conversation.css?v=1"> | |
| <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@400;500;600;700;800&display=swap" rel="stylesheet"> | |
| <!-- HTML2PDF for Print-Ready Reports --> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js" | |
| integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg==" | |
| crossorigin="anonymous" | |
| referrerpolicy="no-referrer"></script> | |
| <!-- PWA Manifest --> | |
| <link rel="manifest" href="/manifest.json"> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- Mobile Overlay --> | |
| <div id="sidebarOverlay" class="sidebar-overlay"></div> | |
| <!-- Sidebar --> | |
| <aside id="sidebar" class="sidebar"> | |
| <div class="sidebar-header"> | |
| <div class="logo"> | |
| <div class="logo-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M22 12h-4l-3 9L9 3l-3 9H2" /> | |
| </svg> | |
| </div> | |
| <span class="logo-text">VoxDoc</span> | |
| </div> | |
| <button id="closeSidebar" class="close-sidebar-btn" aria-label="Close sidebar menu"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <nav class="sidebar-nav"> | |
| <p class="nav-label">Menu</p> | |
| <button class="nav-item active" data-tab="dashboard"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <rect x="3" y="3" width="7" height="9" /> | |
| <rect x="14" y="3" width="7" height="5" /> | |
| <rect x="14" y="12" width="7" height="9" /> | |
| <rect x="3" y="16" width="7" height="5" /> | |
| </svg> | |
| <span>Dashboard</span> | |
| <div class="nav-indicator"></div> | |
| </button> | |
| <button class="nav-item" data-tab="history"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| <button class="nav-item" data-tab="monitoring"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/> | |
| </svg> | |
| <span>Monitoring</span> | |
| </button> | |
| <button class="nav-item" data-tab="hipaa"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/> | |
| </svg> | |
| <span>HIPAA</span> | |
| </button> | |
| <button class="nav-item" data-tab="settings"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <circle cx="12" cy="12" r="3" /> | |
| <path | |
| d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z" /> | |
| </svg> | |
| <span>Settings</span> | |
| </button> | |
| <p class="nav-label" style="margin-top: 2rem;">Recent Sessions</p> | |
| <div class="recent-docs"> | |
| <div class="recent-doc-item" role="button" tabindex="0"> | |
| <div class="doc-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> | |
| <polyline points="14 2 14 8 20 8" /> | |
| </svg> | |
| </div> | |
| <div class="doc-info"> | |
| <p class="doc-title">Patient Intake #1042</p> | |
| <p class="doc-date">Jan 22 • 10:30 AM</p> | |
| </div> | |
| </div> | |
| <div class="recent-doc-item" role="button" tabindex="0"> | |
| <div class="doc-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> | |
| <polyline points="14 2 14 8 20 8" /> | |
| </svg> | |
| </div> | |
| <div class="doc-info"> | |
| <p class="doc-title">Follow-up Session</p> | |
| <p class="doc-date">Jan 21 • 2:15 PM</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Recent Documents List --> | |
| <div class="recent-docs" id="recentDocsList" aria-live="polite"> | |
| <!-- Populated dynamically from localStorage --> | |
| </div> | |
| </nav> | |
| <div class="sidebar-footer"> | |
| <div class="action-card" id="batchExportBtn" role="button" tabindex="0" | |
| aria-label="Batch Export All (PDF)" | |
| style="padding: 12px; margin-bottom: 12px; display: flex; align-items: center; gap: 8px;"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> | |
| <polyline points="14 2 14 8 20 8" /> | |
| <line x1="12" y1="18" x2="12" y2="12" /> | |
| <line x1="9" y1="15" x2="15" y2="15" /> | |
| </svg> | |
| <span style="font-size: 0.8rem; font-weight: 500;">Batch Export All (PDF)</span> | |
| </div> | |
| <div class="user-card"> | |
| <div class="user-avatar" id="userAvatar">--</div> | |
| <div class="user-info"> | |
| <div class="user-name" id="userName">Local Operator</div> | |
| <div class="user-plan" id="userRole">Admin</div> | |
| </div> | |
| </div> | |
| <button id="logoutBtn" class="hidden" style="width:100%;margin-top:8px;padding:8px 12px;background:var(--bg-tertiary);color:var(--text-secondary);border:1px solid var(--border);border-radius:8px;cursor:pointer;font-size:0.85rem;">Sign Out</button> | |
| </div> | |
| </aside> | |
| <!-- Main Content --> | |
| <main class="main-content"> | |
| <!-- Header --> | |
| <header class="main-header"> | |
| <div class="header-left"> | |
| <button id="openSidebar" class="menu-btn" aria-label="Open sidebar menu" aria-expanded="false" | |
| aria-controls="sidebar"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"> | |
| <line x1="3" y1="12" x2="21" y2="12" /> | |
| <line x1="3" y1="6" x2="21" y2="6" /> | |
| <line x1="3" y1="18" x2="21" y2="18" /> | |
| </svg> | |
| </button> | |
| <div class="header-title"> | |
| <h1 id="mainTitle">Intake Session</h1> | |
| <p id="mainSubtitle">Voice Symptom Documentation Assistant</p> | |
| </div> | |
| </div> | |
| <div class="header-right"> | |
| <!-- Theme Toggle Button --> | |
| <button id="themeToggle" class="theme-toggle-btn" aria-label="Switch theme mode"> | |
| <svg class="theme-icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" aria-hidden="true"> | |
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" /> | |
| </svg> | |
| <svg class="theme-icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <circle cx="12" cy="12" r="5" /> | |
| <line x1="12" y1="1" x2="12" y2="3" /> | |
| <line x1="12" y1="21" x2="12" y2="23" /> | |
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" /> | |
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" /> | |
| <line x1="1" y1="12" x2="3" y2="12" /> | |
| <line x1="21" y1="12" x2="23" y2="12" /> | |
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" /> | |
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" /> | |
| </svg> | |
| </button> | |
| <div class="compliance-badge"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path | |
| d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" /> | |
| <line x1="12" y1="9" x2="12" y2="13" /> | |
| <line x1="12" y1="17" x2="12.01" y2="17" /> | |
| </svg> | |
| <span>Admin Use Only</span> | |
| </div> | |
| <!-- PWA Offline Badge --> | |
| <div id="offlineBadge" class="offline-badge hidden"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M1 1l22 22"></path> | |
| <path d="M16.72 11.06A10.94 10.94 0 0 1 19 12.55"></path> | |
| <path d="M5 12.55a10.94 10.94 0 0 1 5.17-2.39"></path> | |
| <path d="M10.71 5.05A16 16 0 0 1 22.58 9"></path> | |
| <path d="M1.42 9a15.91 15.91 0 0 1 4.7-2.88"></path> | |
| <path d="M8.53 16.11a6 6 0 0 1 6.95 0"></path> | |
| <line x1="12" y1="20" x2="12.01" y2="20"></line> | |
| </svg> | |
| <span>Offline</span> | |
| </div> | |
| <!-- Install App Button --> | |
| <button id="installAppBtn" class="install-app-btn hidden" aria-label="Install VoxDoc App"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect> | |
| <line x1="12" y1="18" x2="12.01" y2="18"></line> | |
| </svg> | |
| <span>Install App</span> | |
| </button> | |
| </div> | |
| </header> | |
| <!-- Dashboard View --> | |
| <div id="dashboardView" class="view-container active"> | |
| <div class="content-grid"> | |
| <!-- Left Column: Voice Interaction --> | |
| <div class="voice-column"> | |
| <!-- Voice Card --> | |
| <div class="voice-card"> | |
| <div class="voice-card-glow glow-1"></div> | |
| <div class="voice-card-glow glow-2"></div> | |
| <div class="voice-card-content"> | |
| <div class="voice-card-header"> | |
| <h2>Voice Intake</h2> | |
| <p id="voiceStatus" aria-live="polite">Tap microphone to start recording</p> | |
| </div> | |
| <!-- Waveform Visualizer --> | |
| <div id="waveformContainer" class="waveform-container"> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| <div class="waveform-bar"></div> | |
| </div> | |
| <!-- Record Button --> | |
| <div class="record-btn-wrapper"> | |
| <div id="recordRipple" class="record-ripple"></div> | |
| <button id="recordBtn" class="record-btn" aria-label="Start recording voice intake"> | |
| <svg id="micIcon" class="mic-icon" viewBox="0 0 24 24" fill="none" | |
| stroke="currentColor" stroke-width="2" aria-hidden="true"> | |
| <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" /> | |
| <path d="M19 10v2a7 7 0 0 1-14 0v-2" /> | |
| <line x1="12" y1="19" x2="12" y2="23" /> | |
| <line x1="8" y1="23" x2="16" y2="23" /> | |
| </svg> | |
| <svg id="stopIcon" class="stop-icon hidden" viewBox="0 0 24 24" | |
| fill="currentColor" aria-hidden="true"> | |
| <rect x="6" y="6" width="12" height="12" rx="2" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <!-- Duration Display --> | |
| <div id="durationDisplay" class="duration-display hidden"> | |
| <span id="recordingTime">00:00</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Text Input Alternative --> | |
| <div class="text-input-card"> | |
| <div class="divider-line"> | |
| <label for="textInput"><span>OR TYPE SYMPTOMS</span></label> | |
| </div> | |
| <textarea id="textInput" class="text-input" | |
| placeholder="Enter patient symptoms here (e.g., 'Sore throat for 48 hours with mild fever')" | |
| rows="3" aria-label="Manual symptom text entry"></textarea> | |
| </div> | |
| <!-- Image Upload Section --> | |
| <div class="image-upload-card" id="imageUploadCard"> | |
| <div class="divider-line"> | |
| <span>OR UPLOAD IMAGE</span> | |
| </div> | |
| <div class="image-drop-zone" id="imageDropZone" role="button" tabindex="0" | |
| aria-label="Upload visual patient findings image"> | |
| <div class="drop-zone-content" id="dropZoneContent"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> | |
| <polyline points="17 8 12 3 7 8" /> | |
| <line x1="12" y1="3" x2="12" y2="15" /> | |
| </svg> | |
| <p>Drag and drop a medical image<br><span>or click to browse (JPEG, PNG)</span></p> | |
| </div> | |
| <!-- Image Preview Area --> | |
| <div class="image-preview hidden" id="imagePreviewContainer"> | |
| <div class="preview-wrapper"> | |
| <img id="imagePreview" src="" alt="Selected visual findings image"> | |
| <button class="remove-image-btn" id="removeImageBtn" | |
| aria-label="Remove uploaded image"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="image-details"> | |
| <p class="filename" id="imageFilename">image.jpg</p> | |
| <p class="filesize" id="imageFilesize">2.4 MB</p> | |
| </div> | |
| </div> | |
| <!-- Loading State --> | |
| <div class="image-analyzing hidden" id="imageAnalyzingState"> | |
| <div class="spinner small"></div> | |
| <p>Analyzing image...</p> | |
| </div> | |
| <input type="file" id="imageFileInput" class="file-input-hidden" | |
| accept="image/jpeg, image/png, image/webp" aria-hidden="true" tabindex="-1" /> | |
| </div> | |
| </div> | |
| <!-- Action Cards --> | |
| <div class="action-cards"> | |
| <div class="action-card"> | |
| <div class="action-icon violet"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <rect x="3" y="4" width="18" height="18" rx="2" ry="2" /> | |
| <line x1="16" y1="2" x2="16" y2="6" /> | |
| <line x1="8" y1="2" x2="8" y2="6" /> | |
| <line x1="3" y1="10" x2="21" y2="10" /> | |
| </svg> | |
| </div> | |
| <div class="action-text"> | |
| <h3>SOAP Note Generation</h3> | |
| <p>Auto-generate clinical documentation</p> | |
| </div> | |
| </div> | |
| <div class="action-card"> | |
| <div class="action-icon cyan"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /> | |
| <polyline points="22 4 12 14.01 9 11.01" /> | |
| </svg> | |
| </div> | |
| <div class="action-text"> | |
| <h3>Symptom Extraction</h3> | |
| <p>AI-powered detail capture</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Voice Assistant Toggle --> | |
| <div class="voice-assistant-controls" style="display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem;"> | |
| <button id="convToggleBtn" class="conversation-toggle" aria-label="Toggle AI Voice Assistant"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> | |
| <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/> | |
| </svg> | |
| <span>Voice Assistant</span> | |
| </button> | |
| <select id="convModeSelect" class="conversation-mode-select" style="display: none;"> | |
| <option value="patient">Patient Mode</option> | |
| <option value="clinician">Clinician Mode</option> | |
| </select> | |
| </div> | |
| <!-- Conversation Panel (hidden by default) --> | |
| <div id="conversationPanel" class="conversation-panel"> | |
| <div id="conv-chat-messages" class="chat-messages"> | |
| <!-- Chat bubbles rendered here --> | |
| </div> | |
| <div id="conv-typing" class="typing-indicator"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| <div id="conv-entities" class="conversation-entities"></div> | |
| <div class="conversation-controls"> | |
| <button id="conv-mic-btn" class="conv-mic-btn" aria-label="Record voice"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20"> | |
| <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/> | |
| <path d="M19 10v2a7 7 0 0 1-14 0v-2"/> | |
| <line x1="12" y1="19" x2="12" y2="23"/> | |
| <line x1="8" y1="23" x2="16" y2="23"/> | |
| </svg> | |
| </button> | |
| <input type="text" id="conv-text-input" class="conv-text-input" | |
| placeholder="Type your response..." aria-label="Text input for conversation"> | |
| <button id="conv-send-btn" class="conv-send-btn" aria-label="Send message"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"> | |
| <line x1="22" y1="2" x2="11" y2="13"/> | |
| <polygon points="22 2 15 22 11 13 2 9 22 2"/> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="conversation-status"> | |
| <div class="status-indicator"> | |
| <div id="conv-status-dot" class="status-dot"></div> | |
| <span id="conv-status-text">Ready</span> | |
| </div> | |
| <button id="convEndBtn" style="background: none; border: 1px solid #666; color: #999; padding: 0.25rem 0.5rem; border-radius: 6px; font-size: 0.75rem; cursor: pointer;"> | |
| End Conversation | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Submit Button --> | |
| <button id="submitBtn" class="submit-btn" disabled> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" /> | |
| </svg> | |
| <span>Generate Documentation</span> | |
| </button> | |
| </div> | |
| <!-- Right Column: Live Transcript / Results --> | |
| <div class="transcript-column"> | |
| <div class="transcript-card" id="transcriptCard"> | |
| <!-- Header --> | |
| <div class="transcript-header"> | |
| <div class="transcript-status"> | |
| <div id="liveIndicator" class="live-indicator"></div> | |
| <h3 id="transcriptTitle">Live Transcript</h3> | |
| </div> | |
| <div class="export-actions"> | |
| <button class="action-btn" id="exportBtn" aria-label="Download JSON format"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> | |
| <polyline points="7 10 12 15 17 10" /> | |
| <line x1="12" y1="15" x2="12" y2="3" /> | |
| </svg> | |
| <span>JSON</span> | |
| </button> | |
| <button class="action-btn" id="exportPdfBtn" aria-label="Download Print-Ready PDF"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> | |
| <polyline points="14 2 14 8 20 8" /> | |
| <line x1="16" y1="13" x2="8" y2="13" /> | |
| <line x1="16" y1="17" x2="8" y2="17" /> | |
| <polyline points="10 9 9 9 8 9" /> | |
| </svg> | |
| <span>PDF</span> | |
| </button> | |
| <button class="action-btn primary" id="copyBtn" | |
| aria-label="Copy entire note to clipboard"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <rect x="9" y="9" width="13" height="13" rx="2" ry="2" /> | |
| <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" /> | |
| </svg> | |
| <span>Copy Note</span> | |
| </button> | |
| <button class="action-btn" id="fhirExportBtn" aria-label="Download FHIR R4 Bundle"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" /> | |
| <polyline points="22 4 12 14.01 9 11.01" /> | |
| </svg> | |
| <span>FHIR</span> | |
| </button> | |
| <button class="action-btn" id="ehrPushBtn" aria-label="Push to EHR System"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| aria-hidden="true"> | |
| <path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8" /> | |
| <polyline points="16 6 12 2 8 6" /> | |
| <line x1="12" y1="2" x2="12" y2="15" /> | |
| </svg> | |
| <span>Push EHR</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- EHR Push Modal --> | |
| <div id="ehrModal" class="ehr-modal hidden" role="dialog" aria-label="Push to EHR System" | |
| aria-modal="true"> | |
| <div class="ehr-modal-backdrop"></div> | |
| <div class="ehr-modal-content"> | |
| <div class="ehr-modal-header"> | |
| <h4>Push to EHR System</h4> | |
| <button class="ehr-modal-close" id="ehrModalClose" | |
| aria-label="Close modal">×</button> | |
| </div> | |
| <div class="ehr-modal-body"> | |
| <div class="ehr-field"> | |
| <label for="ehrServerUrl">FHIR Server URL</label> | |
| <input type="url" id="ehrServerUrl" | |
| placeholder="https://hapi.fhir.org/baseR4" /> | |
| </div> | |
| <div class="ehr-field"> | |
| <label for="ehrAuthToken">Authorization Token (optional)</label> | |
| <input type="password" id="ehrAuthToken" | |
| placeholder="Bearer token for Epic/Cerner" /> | |
| </div> | |
| <div class="ehr-presets"> | |
| <span class="ehr-presets-label">Quick Presets:</span> | |
| <button class="ehr-preset-btn" data-url="https://hapi.fhir.org/baseR4">HAPI | |
| (Test)</button> | |
| <button class="ehr-preset-btn" | |
| data-url="https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4">Epic</button> | |
| <button class="ehr-preset-btn" | |
| data-url="https://fhir.cerner.com/r4">Cerner</button> | |
| </div> | |
| </div> | |
| <div class="ehr-modal-footer"> | |
| <button class="action-btn" id="ehrModalCancel">Cancel</button> | |
| <button class="action-btn primary" id="ehrModalSubmit"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| width="14" height="14" aria-hidden="true"> | |
| <polyline points="16 6 12 2 8 6" /> | |
| <line x1="12" y1="2" x2="12" y2="15" /> | |
| </svg> | |
| Push Bundle | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transcript Content --> | |
| <div class="transcript-content" id="transcriptContent"> | |
| <!-- Empty State --> | |
| <div id="emptyState" class="empty-state"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> | |
| <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" /> | |
| <polyline points="14 2 14 8 20 8" /> | |
| <line x1="16" y1="13" x2="8" y2="13" /> | |
| <line x1="16" y1="17" x2="8" y2="17" /> | |
| </svg> | |
| <p>Transcript will appear here...</p> | |
| </div> | |
| <!-- Live Transcript State (shown during recording) --> | |
| <div id="liveTranscriptState" class="live-transcript-state hidden"> | |
| <div class="live-badge" aria-hidden="true"> | |
| <span class="live-dot"></span> | |
| <span>LIVE</span> | |
| </div> | |
| <div id="liveTranscriptText" class="live-transcript-text" aria-live="polite"> | |
| <span class="live-placeholder">Listening... speak clearly into your | |
| microphone</span> | |
| </div> | |
| <div class="live-cursor" aria-hidden="true"></div> | |
| </div> | |
| <!-- Follow-up Questions State --> | |
| <div id="followupState" class="followup-state hidden"> | |
| <div class="followup-header"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="22" height="22"> | |
| <circle cx="12" cy="12" r="10"/> | |
| <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/> | |
| <line x1="12" y1="17" x2="12.01" y2="17"/> | |
| </svg> | |
| <h4>Follow-up Questions</h4> | |
| <p class="followup-subtitle">Please answer these to improve documentation accuracy</p> | |
| </div> | |
| <div id="followupQuestions" class="followup-questions"></div> | |
| <div class="followup-actions"> | |
| <button id="followupSubmitBtn" class="submit-btn"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <polyline points="20 6 9 17 4 12"/> | |
| </svg> | |
| <span>Submit Answers & Generate Documentation</span> | |
| </button> | |
| <button id="followupSkipBtn" class="followup-skip-btn"> | |
| Skip — Generate Without Answers | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Loading State --> | |
| <div id="loadingState" class="loading-state hidden"> | |
| <div class="spinner"></div> | |
| <p id="loadingMessage">Processing and generating documentation...</p> | |
| <!-- Phase 6: Pipeline progress --> | |
| <div id="pipelineProgress" class="hidden" style="display:flex;gap:4px;justify-content:center;margin:10px 0;flex-wrap:wrap;"></div> | |
| <div id="queueBanner" class="queue-banner hidden"> | |
| <div class="queue-icon"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"> | |
| <circle cx="12" cy="12" r="10"/> | |
| <polyline points="12 6 12 12 16 14"/> | |
| </svg> | |
| </div> | |
| <div class="queue-info"> | |
| <span id="queuePosition">Position in queue: --</span> | |
| <span id="queueWait">Estimated wait: --</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Results Container --> | |
| <div id="resultsContainer" class="results-container hidden" aria-live="polite"> | |
| <!-- Clinician Review Notice --> | |
| <div class="review-notice"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <line x1="12" y1="16" x2="12" y2="12" /> | |
| <line x1="12" y1="8" x2="12.01" y2="8" /> | |
| </svg> | |
| <div> | |
| <strong>Requires Clinician Review</strong> | |
| <p>This documentation must be reviewed by a qualified healthcare | |
| professional. | |
| </p> | |
| <p id="complianceMetaNotice" class="compliance-meta-notice"> | |
| HIPAA minimum-necessary mode active. MedGemma terms acknowledgement | |
| required before inference. | |
| </p> | |
| <div id="reliabilityLegend" class="reliability-legend" aria-label="Extraction reliability legend"> | |
| <span class="confidence-pill confidence-green">Green: High confidence</span> | |
| <span class="confidence-pill confidence-yellow">Yellow: Verify</span> | |
| <span class="confidence-pill confidence-red">Red: Needs verification</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Transcription --> | |
| <div class="result-section"> | |
| <div | |
| style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;"> | |
| <h4 style="margin: 0;">Transcription</h4> | |
| <span id="detectedLanguageBadge" class="badge info hidden">Detected: | |
| English</span> | |
| </div> | |
| <p id="transcriptionText" class="transcription-text"></p> | |
| <!-- Audio Playback Section --> | |
| <div id="audioPlaybackSection" class="audio-playback-section hidden"> | |
| <div class="audio-playback-header"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2"> | |
| <polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" /> | |
| <path d="M15.54 8.46a5 5 0 0 1 0 7.07" /> | |
| </svg> | |
| <span>Original Recording</span> | |
| <span class="badge success">For Verification</span> | |
| </div> | |
| <audio id="resultAudioPlayer" controls class="audio-player"></audio> | |
| </div> | |
| <!-- Text Input Indicator --> | |
| <div id="textInputIndicator" class="text-input-indicator hidden"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
| <polyline points="4 7 4 4 20 4 20 7" /> | |
| <line x1="9" y1="20" x2="15" y2="20" /> | |
| <line x1="12" y1="4" x2="12" y2="20" /> | |
| </svg> | |
| <span>Text Input</span> | |
| <span class="badge info">Manual Entry</span> | |
| </div> | |
| </div> | |
| <!-- Chief Complaint --> | |
| <div class="soap-section-card" data-section="chief_complaint" role="region" | |
| aria-label="Chief Complaint Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-cc">CC</span> | |
| <h5>Chief Complaint</h5> | |
| <span class="soap-status badge warning" id="soapStatusCC">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="chiefComplaint" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="chief_complaint" | |
| aria-label="Edit Chief Complaint"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="chief_complaint" | |
| aria-label="Reject Chief Complaint"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="chief_complaint" | |
| aria-label="Approve Chief Complaint"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="chief_complaint" | |
| aria-label="View Chief Complaint History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryCC"></div> | |
| </div> | |
| <!-- Extracted Medical Entities (NER) --> | |
| <div class="soap-section-card hidden" id="nerEntitiesCard" role="region" | |
| aria-label="Extracted Medical Entities"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-ner">NER</span> | |
| <h5>Extracted Entities</h5> | |
| <span class="badge info" id="nerEntityCount">0 entities</span> | |
| </div> | |
| <div class="soap-card-body ner-entities-body"> | |
| <div class="ner-category" id="nerConditions"> | |
| <div class="ner-category-label"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path d="M22 12h-4l-3 9L9 3l-3 9H2" /> | |
| </svg> | |
| <span>Conditions</span> | |
| </div> | |
| <div class="ner-badges" id="nerConditionBadges"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| <div class="ner-category" id="nerMedications"> | |
| <div class="ner-category-label"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" /> | |
| <line x1="12" y1="9" x2="12" y2="13" /> | |
| <line x1="12" y1="17" x2="12.01" y2="17" /> | |
| </svg> | |
| <span>Medications</span> | |
| </div> | |
| <div class="ner-badges" id="nerMedicationBadges"> | |
| <!-- Dynamically populated --> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Clinical Details --> | |
| <div class="soap-section-card" data-section="clinical_details" role="region" | |
| aria-label="Clinical Details Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-cd">CD</span> | |
| <h5>Clinical Details</h5> | |
| <span class="soap-status badge warning" id="soapStatusCD">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="symptomDetails" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="clinical_details" | |
| aria-label="Edit Clinical Details"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="clinical_details" | |
| aria-label="Reject Clinical Details"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="clinical_details" | |
| aria-label="Approve Clinical Details"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="clinical_details" | |
| aria-label="View Clinical Details History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryCD"></div> | |
| </div> | |
| <!-- Visual Inspection (Images) --> | |
| <div class="soap-section-card hidden" id="imageFindingsCard" | |
| data-section="visual_findings" role="region" | |
| aria-label="Visual Findings Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-vi">VI</span> | |
| <h5>Visual Inspection</h5> | |
| <span class="soap-status badge warning" id="soapStatusVI">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="visualFindings" contenteditable="false"></div> | |
| <div class="image-findings-thumbnail-container" | |
| id="imageFindingsThumbnailContainer"> | |
| <!-- Thumbnail populated dynamically --> | |
| </div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="visual_findings" | |
| aria-label="Edit Visual Findings"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="visual_findings" | |
| aria-label="Reject Visual Findings"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="visual_findings" | |
| aria-label="Approve Visual Findings"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="visual_findings" | |
| aria-label="View Visual Findings History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryVI"></div> | |
| </div> | |
| <!-- SOAP Notes — Full (S, O, A, P) --> | |
| <div class="soap-sections-container"> | |
| <div class="soap-sections-header"> | |
| <h4>SOAP Note</h4> | |
| <span class="badge info" id="soapOverallStatus">4 sections pending | |
| review</span> | |
| </div> | |
| <!-- Subjective --> | |
| <div class="soap-section-card" data-section="subjective" role="region" | |
| aria-label="Subjective Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-s">S</span> | |
| <h5>Subjective</h5> | |
| <span class="soap-status badge warning" id="soapStatusS">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="soapS" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="subjective" | |
| aria-label="Edit Subjective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path | |
| d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="subjective" | |
| aria-label="Reject Subjective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="subjective" | |
| aria-label="Approve Subjective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="subjective" | |
| aria-label="View Subjective Section History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryS"></div> | |
| </div> | |
| <!-- Objective --> | |
| <div class="soap-section-card" data-section="objective" role="region" | |
| aria-label="Objective Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-o">O</span> | |
| <h5>Objective</h5> | |
| <span class="soap-status badge warning" id="soapStatusO">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="soapO" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="objective" | |
| aria-label="Edit Objective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path | |
| d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="objective" | |
| aria-label="Reject Objective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="objective" | |
| aria-label="Approve Objective Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="objective" | |
| aria-label="View Objective Section History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryO"></div> | |
| </div> | |
| <!-- Assessment --> | |
| <div class="soap-section-card" data-section="assessment" role="region" | |
| aria-label="Assessment Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-a">A</span> | |
| <h5>Assessment</h5> | |
| <span class="soap-status badge warning" id="soapStatusA">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="soapA" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="assessment" | |
| aria-label="Edit Assessment Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path | |
| d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="assessment" | |
| aria-label="Reject Assessment Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="assessment" | |
| aria-label="Approve Assessment Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="assessment" | |
| aria-label="View Assessment Section History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryA"></div> | |
| </div> | |
| <!-- Plan --> | |
| <div class="soap-section-card" data-section="plan" role="region" | |
| aria-label="Plan Section"> | |
| <div class="soap-card-header"> | |
| <span class="soap-label soap-label-p">P</span> | |
| <h5>Plan</h5> | |
| <span class="soap-status badge warning" id="soapStatusP">Pending | |
| Review</span> | |
| </div> | |
| <div class="soap-card-body" id="soapP" contenteditable="false"></div> | |
| <div class="soap-card-actions"> | |
| <button class="soap-edit-btn" data-section="plan" | |
| aria-label="Edit Plan Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <path | |
| d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" /> | |
| <path | |
| d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" /> | |
| </svg> | |
| <span>Edit</span> | |
| </button> | |
| <button class="soap-reject-btn" data-section="plan" | |
| aria-label="Reject Plan Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <line x1="18" y1="6" x2="6" y2="18" /> | |
| <line x1="6" y1="6" x2="18" y2="18" /> | |
| </svg> | |
| <span>Reject</span> | |
| </button> | |
| <button class="soap-approve-btn" data-section="plan" | |
| aria-label="Approve Plan Section"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <polyline points="20 6 9 17 4 12" /> | |
| </svg> | |
| <span>Approve</span> | |
| </button> | |
| <button class="soap-history-toggle" data-section="plan" | |
| aria-label="View Plan Section History" aria-expanded="false"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" | |
| stroke-width="2" width="14" height="14" aria-hidden="true"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <polyline points="12 6 12 12 16 14" /> | |
| </svg> | |
| <span>History</span> | |
| </button> | |
| </div> | |
| <div class="soap-history-panel hidden" id="soapHistoryP"></div> | |
| </div> | |
| <!-- AI Suggestion Notice --> | |
| <div class="soap-ai-notice"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" | |
| width="16" height="16"> | |
| <circle cx="12" cy="12" r="10" /> | |
| <line x1="12" y1="16" x2="12" y2="12" /> | |
| <line x1="12" y1="8" x2="12.01" y2="8" /> | |
| </svg> | |
| <span>O, A, P sections are AI-generated suggestions. Clinician review and | |
| approval is required.</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Footer --> | |
| <div class="transcript-footer"> | |
| <p class="disclaimer">Administrative documentation tool. Not for clinical | |
| decision-making. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> <!-- End Dashboard View --> | |
| <!-- History View (Hidden by default) --> | |
| <!-- Monitoring View --> | |
| <div id="monitoringView" class="view-container hidden" role="region" aria-label="Monitoring Dashboard"> | |
| <div class="monitoring-header"> | |
| <h2 class="section-title">System Monitoring</h2> | |
| <div class="monitoring-actions"> | |
| <span id="monitoringUptime" class="uptime-badge">Uptime: --</span> | |
| <button id="refreshMonitoring" class="btn-icon" title="Refresh"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"> | |
| <polyline points="23 4 23 10 17 10"/> | |
| <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Alerts Banner --> | |
| <div id="alertsBanner" class="alerts-banner hidden"></div> | |
| <!-- Model Performance Cards --> | |
| <div class="monitoring-grid"> | |
| <div class="monitor-card" id="monitorCardMedasr"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">MedASR</span> | |
| <span class="monitor-status-dot" id="statusDotMedasr"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Requests</span><span id="medasrRequests">0</span></div> | |
| <div class="stat-row"><span>Error Rate</span><span id="medasrErrorRate">0%</span></div> | |
| <div class="stat-row"><span>Avg Latency</span><span id="medasrLatency">--</span></div> | |
| <div class="stat-row"><span>P95 Latency</span><span id="medasrP95">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card" id="monitorCardMedgemma"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">MedGemma</span> | |
| <span class="monitor-status-dot" id="statusDotMedgemma"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Requests</span><span id="medgemmaRequests">0</span></div> | |
| <div class="stat-row"><span>Error Rate</span><span id="medgemmaErrorRate">0%</span></div> | |
| <div class="stat-row"><span>Avg Latency</span><span id="medgemmaLatency">--</span></div> | |
| <div class="stat-row"><span>P95 Latency</span><span id="medgemmaP95">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card" id="monitorCardVision"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Vision</span> | |
| <span class="monitor-status-dot" id="statusDotVision"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Requests</span><span id="visionRequests">0</span></div> | |
| <div class="stat-row"><span>Error Rate</span><span id="visionErrorRate">0%</span></div> | |
| <div class="stat-row"><span>Avg Latency</span><span id="visionLatency">--</span></div> | |
| <div class="stat-row"><span>P95 Latency</span><span id="visionP95">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card" id="monitorCardNer"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">NER</span> | |
| <span class="monitor-status-dot" id="statusDotNer"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Requests</span><span id="nerRequests">0</span></div> | |
| <div class="stat-row"><span>Error Rate</span><span id="nerErrorRate">0%</span></div> | |
| <div class="stat-row"><span>Avg Latency</span><span id="nerLatency">--</span></div> | |
| <div class="stat-row"><span>P95 Latency</span><span id="nerP95">--</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Queue & Connections --> | |
| <div class="monitoring-grid" style="margin-top: 16px;"> | |
| <div class="monitor-card wide"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Inference Queue</span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Active</span><span id="queueActive">0</span></div> | |
| <div class="stat-row"><span>Queued</span><span id="queueWaiting">0</span></div> | |
| <div class="stat-row"><span>Max Concurrent</span><span id="queueMaxConc">--</span></div> | |
| <div class="stat-row"><span>Avg Inference</span><span id="queueAvgTime">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card wide"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Connections</span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>HTTP</span><span id="connHttp">0</span></div> | |
| <div class="stat-row"><span>WebSocket</span><span id="connWs">0</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- HIPAA Compliance View --> | |
| <div id="hipaaView" class="view-container hidden" role="region" aria-label="HIPAA Compliance Dashboard"> | |
| <div class="monitoring-header"> | |
| <h2 class="section-title">HIPAA Compliance</h2> | |
| <div class="monitoring-actions"> | |
| <button id="refreshHipaa" class="btn-icon" title="Refresh"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="18" height="18"> | |
| <polyline points="23 4 23 10 17 10"/> | |
| <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- HIPAA Summary Cards --> | |
| <div class="monitoring-grid"> | |
| <div class="monitor-card"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Audit Trail</span> | |
| <span class="monitor-status-dot ready" id="hipaaAuditStatus"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Total Audit Logs</span><span id="hipaaTotalAudit">0</span></div> | |
| <div class="stat-row"><span>PHI Accesses</span><span id="hipaaPhiAccess">0</span></div> | |
| <div class="stat-row"><span>PHI (Last 24h)</span><span id="hipaaPhiRecent">0</span></div> | |
| <div class="stat-row"><span>Data Exports</span><span id="hipaaExports">0</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Encryption</span> | |
| <span class="monitor-status-dot" id="hipaaEncryptionStatus"></span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>At Rest</span><span id="hipaaEncryptionAtRest">--</span></div> | |
| <div class="stat-row"><span>PHI Persistence</span><span id="hipaaPhiPersistence">--</span></div> | |
| <div class="stat-row"><span>PHI Logging</span><span id="hipaaPhiLogging">--</span></div> | |
| <div class="stat-row"><span>Min-Necessary Mode</span><span id="hipaaMinNecessary">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Data Retention</span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Sessions</span><span id="hipaaSessionsTotal">0</span></div> | |
| <div class="stat-row"><span>Sessions Expired</span><span id="hipaaSessionsExpired">0</span></div> | |
| <div class="stat-row"><span>Retention (days)</span><span id="hipaaSessionRetention">--</span></div> | |
| <div class="stat-row"><span>Auto-Purge</span><span id="hipaaAutoPurge">--</span></div> | |
| </div> | |
| </div> | |
| <div class="monitor-card"> | |
| <div class="monitor-card-header"> | |
| <span class="monitor-model-name">Audit Log Retention</span> | |
| </div> | |
| <div class="monitor-stats"> | |
| <div class="stat-row"><span>Total Logs</span><span id="hipaaAuditTotal">0</span></div> | |
| <div class="stat-row"><span>Expired Logs</span><span id="hipaaAuditExpired">0</span></div> | |
| <div class="stat-row"><span>Retention (days)</span><span id="hipaaAuditRetention">--</span></div> | |
| <div class="stat-row"><span>Purge Interval</span><span id="hipaaPurgeInterval">--</span></div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Manual Purge Action --> | |
| <div class="hipaa-actions" style="margin-top: 16px;"> | |
| <button id="hipaaPurgeBtn" class="hipaa-purge-btn" title="Run data purge based on retention policies"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"> | |
| <polyline points="3 6 5 6 21 6"/> | |
| <path d="M19 6l-2 14H7L5 6"/> | |
| <path d="M10 11v6"/> | |
| <path d="M14 11v6"/> | |
| </svg> | |
| Run Manual Purge | |
| </button> | |
| <span id="hipaaPurgeResult" class="hipaa-purge-result"></span> | |
| </div> | |
| <!-- Recent Export Logs --> | |
| <div style="margin-top: 24px;"> | |
| <h3 class="section-title" style="font-size: 1rem; margin-bottom: 12px;">Recent Data Exports</h3> | |
| <div id="hipaaExportLogs" class="hipaa-export-logs"> | |
| <p class="text-muted">No export logs found.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="historyView" class="view-container hidden" role="region" aria-label="History View"> | |
| <!-- Phase 6: Session Search & Filter --> | |
| <div style="display:flex;gap:10px;margin-bottom:16px;align-items:center;flex-wrap:wrap;"> | |
| <input type="text" id="sessionSearchInput" placeholder="Search sessions..." aria-label="Search sessions" style="flex:1;min-width:200px;padding:9px 14px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:0.9rem;" /> | |
| <input type="date" id="sessionDateFilter" aria-label="Filter by date" style="padding:9px 14px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:0.9rem;" /> | |
| </div> | |
| <div class="history-grid" id="historyGrid"> | |
| <!-- Session cards dynamically populated here --> | |
| </div> | |
| <div class="history-empty hidden" id="historyEmptyState"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"> | |
| <circle cx="12" cy="12" r="10"></circle> | |
| <polyline points="12 6 12 12 16 14"></polyline> | |
| </svg> | |
| <h3>No Sessions Found</h3> | |
| <p>There are no past sessions available yet.</p> | |
| </div> | |
| </div> | |
| <!-- Settings View (Hidden by default) --> | |
| <div id="settingsView" class="settings-view hidden" role="region" aria-label="Settings Configuration"> | |
| <div class="settings-header"> | |
| <h2>Neural Config</h2> | |
| <div class="neural-badge"> | |
| <span class="pulse-dot"></span> | |
| SYSTEM ACTIVE | |
| </div> | |
| </div> | |
| <div class="settings-grid"> | |
| <!-- Theme Matrix --> | |
| <div class="settings-card full-width"> | |
| <h3>Holo-Theme Matrix</h3> | |
| <div class="theme-options"> | |
| <div class="theme-card active" data-theme="glass" role="button" tabindex="0" | |
| aria-label="Select Clinical Glass Theme"> | |
| <div class="theme-preview glass"></div> | |
| <span>Clinical Glass</span> | |
| </div> | |
| <div class="theme-card" data-theme="neon" role="button" tabindex="0" | |
| aria-label="Select Neon Cyber Theme"> | |
| <div class="theme-preview neon"></div> | |
| <span>Neon Cyber</span> | |
| </div> | |
| <div class="theme-card" data-theme="midnight" role="button" tabindex="0" | |
| aria-label="Select Midnight Void Theme"> | |
| <div class="theme-preview midnight"></div> | |
| <span>Midnight Void</span> | |
| </div> | |
| <div class="theme-card" data-theme="light" role="button" tabindex="0" | |
| aria-label="Select Clinical Light Theme"> | |
| <div class="theme-preview light"></div> | |
| <span>Clinical Light</span> | |
| </div> | |
| <div class="theme-card" data-theme="aurora" role="button" tabindex="0" | |
| aria-label="Select Aurora Dusk Theme"> | |
| <div class="theme-preview aurora"></div> | |
| <span>Aurora Dusk</span> | |
| </div> | |
| <div class="theme-card" data-theme="high-contrast" role="button" tabindex="0" | |
| aria-label="Select High Contrast Theme"> | |
| <div class="theme-preview" style="background: #000; border: 2px solid #ff0;"></div> | |
| <span>High Contrast</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- AI Temperament --> | |
| <div class="settings-card"> | |
| <h3>AI Temperament</h3> | |
| <div class="slider-group"> | |
| <label for="depthSlider"> | |
| <span>Analysis Depth</span> | |
| <span id="depthValue" class="value-display" aria-live="polite">85%</span> | |
| </label> | |
| <input type="range" id="depthSlider" min="1" max="100" value="85" class="neural-slider" | |
| aria-label="Adjust AI analysis depth"> | |
| </div> | |
| <div class="slider-group"> | |
| <label for="empathySlider"> | |
| <span>Empathy Level</span> | |
| <span id="empathyValue" class="value-display" aria-live="polite">High</span> | |
| </label> | |
| <input type="range" id="empathySlider" min="1" max="3" value="3" class="neural-slider" | |
| aria-label="Adjust AI empathy level"> | |
| </div> | |
| </div> | |
| <!-- Neural Link Status --> | |
| <div class="settings-card"> | |
| <h3>Neural Link Status</h3> | |
| <div class="neural-graph-container"> | |
| <canvas id="neuralGraph"></canvas> | |
| <div class="graph-overlay"> | |
| <div class="stat-item"> | |
| <span class="label">LATENCY</span> | |
| <span class="val">12ms</span> | |
| </div> | |
| <div class="stat-item"> | |
| <span class="label">GPU</span> | |
| <span class="val">ACTIVE</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Haptics & Feedback --> | |
| <div class="settings-card full-width"> | |
| <h3>Sensory Feedback</h3> | |
| <div class="toggles-row"> | |
| <div class="toggle-item"> | |
| <div class="toggle-info"> | |
| <label for="particleSlider" class="toggle-label">Particle Intensity</label> | |
| <span class="toggle-desc">Ambient background activity</span> | |
| </div> | |
| <input type="range" id="particleSlider" min="0" max="100" value="70" | |
| class="neural-slider small" aria-label="Adjust background particle intensity"> | |
| </div> | |
| <div class="toggle-item"> | |
| <div class="toggle-info"> | |
| <label for="soundToggle" class="toggle-label">Interface Sounds</label> | |
| <span class="toggle-desc">Haptic audio feedback</span> | |
| </div> | |
| <label class="switch"> | |
| <input type="checkbox" id="soundToggle" checked | |
| aria-label="Toggle interface sounds"> | |
| <span class="slider round"></span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| </div> | |
| <div id="pdfPrintContainer" style="display: none;"> | |
| <div id="pdfPrintTemplate" class="pdf-template"> | |
| <!-- Header / Branding --> | |
| <div class="pdf-header"> | |
| <div class="pdf-logo"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="24" height="24"> | |
| <path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" /> | |
| </svg> | |
| <h2>VoxDoc Clinic</h2> | |
| </div> | |
| <div class="pdf-meta"> | |
| <p><strong>Date:</strong> <span id="pdfDate"></span></p> | |
| <p><strong>Time:</strong> <span id="pdfTime"></span></p> | |
| <p><strong>Provider:</strong> Dr. Sarah Chen</p> | |
| </div> | |
| </div> | |
| <hr class="pdf-divider"> | |
| <!-- Patient Info --> | |
| <div class="pdf-patient-info"> | |
| <div class="pdf-info-row"> | |
| <span><strong>Patient Name:</strong> Doe, John</span> | |
| <span><strong>DOB:</strong> 01/01/1980 (46y)</span> | |
| <span><strong>MRN:</strong> 987654321</span> | |
| </div> | |
| </div> | |
| <!-- Clinical Content --> | |
| <div class="pdf-content"> | |
| <h3 class="pdf-section-title">Chief Complaint</h3> | |
| <p id="pdfChiefComplaint"></p> | |
| <h3 class="pdf-section-title">Clinical Details</h3> | |
| <div id="pdfClinicalDetails"></div> | |
| <div id="pdfVisualFindingsContainer"> | |
| <h3 class="pdf-section-title">Visual Inspection</h3> | |
| <p id="pdfVisualFindings"></p> | |
| </div> | |
| <h3 class="pdf-section-title">SOAP Note</h3> | |
| <div class="pdf-soap-section"> | |
| <h4>Subjective</h4> | |
| <p id="pdfSubjective"></p> | |
| </div> | |
| <div class="pdf-soap-section"> | |
| <h4>Objective</h4> | |
| <p id="pdfObjective"></p> | |
| </div> | |
| <div class="pdf-soap-section"> | |
| <h4>Assessment</h4> | |
| <p id="pdfAssessment"></p> | |
| </div> | |
| <div class="pdf-soap-section"> | |
| <h4>Plan</h4> | |
| <p id="pdfPlan"></p> | |
| </div> | |
| </div> | |
| <!-- Footer / Signatures --> | |
| <div class="pdf-footer"> | |
| <div class="pdf-signature"> | |
| <div class="sig-line"></div> | |
| <p>Provider Signature</p> | |
| <p class="sig-name">Dr. Sarah Chen, MD</p> | |
| </div> | |
| <div class="pdf-signature"> | |
| <div class="sig-line"></div> | |
| <p>Date</p> | |
| </div> | |
| </div> | |
| <div class="pdf-page-number">VoxDoc Generated Report</div> | |
| </div> | |
| </div> | |
| <!-- Login Overlay (Phase 4) --> | |
| <div id="loginOverlay" class="hidden" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.85);z-index:10000;display:flex;align-items:center;justify-content:center;"> | |
| <div style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:16px;padding:32px;width:360px;max-width:90vw;"> | |
| <h2 style="margin:0 0 8px;color:var(--text-primary);font-size:1.3rem;">Sign in to VoxDoc</h2> | |
| <p style="margin:0 0 20px;color:var(--text-secondary);font-size:0.85rem;">Authentication required to continue</p> | |
| <div style="margin-bottom:14px;"> | |
| <label style="display:block;margin-bottom:4px;color:var(--text-secondary);font-size:0.8rem;">Username</label> | |
| <input type="text" id="loginUsername" autocomplete="username" style="width:100%;padding:10px 12px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:0.95rem;box-sizing:border-box;" /> | |
| </div> | |
| <div style="margin-bottom:14px;"> | |
| <label style="display:block;margin-bottom:4px;color:var(--text-secondary);font-size:0.8rem;">Password</label> | |
| <input type="password" id="loginPassword" autocomplete="current-password" style="width:100%;padding:10px 12px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:0.95rem;box-sizing:border-box;" /> | |
| </div> | |
| <div id="mfaField" class="hidden" style="margin-bottom:14px;"> | |
| <label style="display:block;margin-bottom:4px;color:var(--text-secondary);font-size:0.8rem;">Authenticator Code</label> | |
| <input type="text" id="loginTotp" maxlength="6" inputmode="numeric" autocomplete="one-time-code" style="width:100%;padding:10px 12px;background:var(--bg-tertiary);border:1px solid var(--border);border-radius:8px;color:var(--text-primary);font-size:0.95rem;box-sizing:border-box;letter-spacing:4px;text-align:center;" /> | |
| </div> | |
| <div id="loginError" style="color:#ef4444;font-size:0.8rem;margin-bottom:12px;min-height:1.2em;"></div> | |
| <button id="loginBtn" style="width:100%;padding:11px;background:var(--accent);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:0.95rem;font-weight:600;">Sign In</button> | |
| </div> | |
| </div> | |
| <!-- Session Timeout Warning (Phase 4) --> | |
| <div id="timeoutWarning" class="hidden" style="position:fixed;top:0;left:0;right:0;background:#f59e0b;color:#000;text-align:center;padding:10px;z-index:9999;font-size:0.9rem;font-weight:500;"> | |
| Your session will expire due to inactivity. Move your mouse or press a key to stay signed in. | |
| </div> | |
| <!-- Consent Dialog (Phase 4) --> | |
| <div id="consentDialog" class="hidden" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:9998;display:flex;align-items:center;justify-content:center;"> | |
| <div style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:16px;padding:28px;width:400px;max-width:90vw;"> | |
| <h3 style="margin:0 0 12px;color:var(--text-primary);font-size:1.1rem;">Patient Consent Required</h3> | |
| <p style="margin:0 0 20px;color:var(--text-secondary);font-size:0.9rem;">Has the patient provided verbal consent for this intake session? This is required for HIPAA compliance.</p> | |
| <div style="display:flex;gap:12px;justify-content:flex-end;"> | |
| <button id="consentNo" style="padding:9px 20px;background:var(--bg-tertiary);color:var(--text-secondary);border:1px solid var(--border);border-radius:8px;cursor:pointer;font-size:0.9rem;">No, Cancel</button> | |
| <button id="consentYes" style="padding:9px 20px;background:var(--accent);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:0.9rem;font-weight:600;">Yes, Consent Given</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="/static/js/conversation.js?v=1"></script> | |
| <script src="/static/js/app.js?v=8"></script> | |
| </body> | |
| </html> | |