VoxDoc / app /static /index.html
joelthomas77's picture
Upload app code
60d4850 verified
<!DOCTYPE html>
<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">&times;</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>