Download frontend/live.html from r-vasanthkumar73-dev/Sentinel-Multimodal-Emotion-AI: direct link, hf CLI and curl.
- Browser
- Download file 31.1 kB
-
https://huggingface.co/spaces/r-vasanthkumar73-dev/Sentinel-Multimodal-Emotion-AI/resolve/main/frontend/live.html
- Command line
-
hf download hf://spaces/r-vasanthkumar73-dev/Sentinel-Multimodal-Emotion-AI/frontend/live.html
-
curl -L -o live.html https://huggingface.co/spaces/r-vasanthkumar73-dev/Sentinel-Multimodal-Emotion-AI/resolve/main/frontend/live.html
31.1 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Sentinel Live Pulse — Real-time Multimodal Analysis</title> | |
| <link rel="stylesheet" href="/css/styles.css"> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600;700&display=swap" | |
| rel="stylesheet"> | |
| <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" | |
| rel="stylesheet"> | |
| <style> | |
| .live-grid { | |
| display: grid; | |
| grid-template-columns: 200px 1fr 320px; | |
| gap: 20px; | |
| height: calc(100vh - 64px); | |
| padding: 20px; | |
| } | |
| .source-panel { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| overflow-y: auto; | |
| } | |
| .center-panel { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| min-height: 0; | |
| } | |
| .analytics-panel { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 16px; | |
| overflow-y: auto; | |
| } | |
| .video-container { | |
| position: relative; | |
| flex: 1; | |
| border-radius: 16px; | |
| overflow: hidden; | |
| border: 1px solid rgba(59, 73, 75, 0.15); | |
| background: #000; | |
| min-height: 380px; | |
| } | |
| #webcam-video { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| } | |
| #mesh-canvas { | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| pointer-events: none; | |
| object-fit: cover; | |
| } | |
| .video-overlay-top { | |
| position: absolute; | |
| top: 16px; | |
| left: 16px; | |
| display: flex; | |
| gap: 12px; | |
| z-index: 5; | |
| } | |
| .video-overlay-bottom { | |
| position: absolute; | |
| bottom: 16px; | |
| right: 16px; | |
| z-index: 5; | |
| } | |
| .emotion-badge { | |
| padding: 8px 16px; | |
| border-radius: 12px; | |
| background: rgba(0, 0, 0, 0.6); | |
| backdrop-filter: blur(12px); | |
| border-left: 4px solid var(--primary-container); | |
| } | |
| .emotion-badge-label { | |
| font-size: 9px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.05em; | |
| color: rgba(0, 240, 255, 0.7); | |
| } | |
| .emotion-badge-value { | |
| font-family: var(--font-headline); | |
| font-size: 1.25rem; | |
| font-weight: 700; | |
| color: var(--primary); | |
| } | |
| .source-btn { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-start; | |
| padding: 16px; | |
| border-radius: 12px; | |
| border: 1px solid rgba(59, 73, 75, 0.15); | |
| background: var(--surface-container-low); | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .source-btn:hover { | |
| background: var(--surface-container); | |
| } | |
| .source-btn.active { | |
| border-color: rgba(0, 240, 255, 0.3); | |
| } | |
| .source-btn .bar { | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| height: 3px; | |
| transition: width 0.5s; | |
| } | |
| .source-btn.active .bar { | |
| width: 100% ; | |
| } | |
| .source-label { | |
| font-size: 10px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.08em; | |
| color: var(--outline); | |
| margin-top: 4px; | |
| } | |
| .source-name { | |
| font-family: var(--font-headline); | |
| font-size: 12px; | |
| font-weight: 700; | |
| margin-top: 2px; | |
| } | |
| /* Audio Visualizer */ | |
| .audio-viz-container { | |
| height: 80px; | |
| display: flex; | |
| align-items: flex-end; | |
| gap: 2px; | |
| padding: 8px; | |
| } | |
| .audio-bar { | |
| flex: 1; | |
| border-radius: 3px 3px 0 0; | |
| transition: height 0.1s ease-out; | |
| min-height: 2px; | |
| } | |
| /* Tech Log */ | |
| .tech-log { | |
| height: 120px; | |
| border-radius: 12px; | |
| padding: 12px; | |
| font-family: 'JetBrains Mono', 'Cascadia Code', monospace; | |
| font-size: 10px; | |
| overflow-y: auto; | |
| } | |
| .tech-log .log-line { | |
| margin-bottom: 2px; | |
| color: #64748b; | |
| } | |
| /* Prosody Bars */ | |
| .prosody-bars { | |
| display: flex; | |
| align-items: flex-end; | |
| gap: 3px; | |
| height: 72px; | |
| } | |
| .prosody-bar { | |
| flex: 1; | |
| border-radius: 3px 3px 0 0; | |
| transition: height 0.3s ease-out; | |
| } | |
| /* Controls Bar */ | |
| .controls-bar { | |
| display: flex; | |
| align-items: center; | |
| gap: 12px; | |
| padding: 12px 16px; | |
| border-radius: 12px; | |
| background: rgba(26, 31, 47, 0.7); | |
| backdrop-filter: blur(16px); | |
| border: 1px solid rgba(59, 73, 75, 0.1); | |
| } | |
| .control-btn { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| border: none; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| cursor: pointer; | |
| transition: all 0.3s; | |
| background: var(--surface-container); | |
| color: var(--on-surface-variant); | |
| } | |
| .control-btn:hover { | |
| background: var(--surface-container-high); | |
| color: var(--primary-container); | |
| } | |
| .control-btn.active { | |
| background: rgba(0, 240, 255, 0.15); | |
| color: var(--primary-container); | |
| } | |
| .control-btn.recording { | |
| background: rgba(255, 59, 48, 0.15); | |
| color: #ff3b30; | |
| animation: pulse-glow 1.5s infinite; | |
| } | |
| /* Custom Live Audio Button */ | |
| .btn-record-audio { | |
| background: rgba(255, 59, 48, 0.15); | |
| border: 1px solid rgba(255, 59, 48, 0.4); | |
| color: #ff3b30; | |
| padding: 10px 24px; | |
| border-radius: 999px; | |
| font-family: var(--font-headline); | |
| font-size: 14px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| transition: all 0.3s; | |
| margin: 0 auto; | |
| } | |
| .btn-record-audio:hover { | |
| background: rgba(255, 59, 48, 0.3); | |
| box-shadow: 0 0 15px rgba(255, 59, 48, 0.4); | |
| } | |
| .btn-record-audio.active { | |
| animation: pulse-glow 1.5s infinite; | |
| background: rgba(255, 59, 48, 0.4); | |
| } | |
| </style> | |
| <!-- MediaPipe Face Mesh local/CDN dependencies --> | |
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/face_mesh/face_mesh.js" crossorigin="anonymous"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" | |
| crossorigin="anonymous"></script> | |
| </head> | |
| <body> | |
| <!-- Sidebar --> | |
| <aside class="sidebar"> | |
| <div class="sidebar-logo">S</div> | |
| <nav class="sidebar-nav"> | |
| <a href="/" class="sidebar-link"><span class="material-symbols-outlined">dashboard</span><span | |
| class="label">Home</span></a> | |
| <a href="/live" class="sidebar-link active"><span class="material-symbols-outlined" | |
| style="font-variation-settings:'FILL' 1;">sensors</span><span class="label">Live</span></a> | |
| <a href="/scan" class="sidebar-link"><span class="material-symbols-outlined">analytics</span><span | |
| class="label">Scan</span></a> | |
| <a href="/stats" class="sidebar-link"><span class="material-symbols-outlined">school</span><span | |
| class="label">Stats</span></a> | |
| </nav> | |
| </aside> | |
| <!-- Topbar --> | |
| <header class="topbar"> | |
| <div style="display:flex;align-items:center;gap:16px;"> | |
| <h1 class="topbar-title gradient-text">Sentinel Live Pulse</h1> | |
| <div class="live-indicator" id="live-badge" style="display:none;"> | |
| <div class="dot"></div>LIVE | |
| </div> | |
| <div class="status-pill" id="connection-status"> | |
| <span class="status-dot" style="background:var(--tertiary-fixed-dim);"></span> | |
| <span class="status-text" style="color:var(--tertiary-fixed-dim);">Standby</span> | |
| </div> | |
| </div> | |
| <div style="display:flex;align-items:center;gap:12px;"> | |
| <button class="btn-primary" id="btn-start-stop"> | |
| <span class="material-symbols-outlined" style="font-size:18px;">play_arrow</span> | |
| Start Monitoring | |
| </button> | |
| </div> | |
| </header> | |
| <!-- Main Grid --> | |
| <main class="main-content"> | |
| <div class="live-grid"> | |
| <!-- ── Left Panel: Sources ── --> | |
| <section class="source-panel"> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| System Sources</div> | |
| <div class="source-btn active" id="source-face"> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--primary-container);margin-bottom:8px;">videocam</span> | |
| <span class="source-name" style="color:var(--primary);">Live Face Feed</span> | |
| <span class="source-label" id="face-status">Standby</span> | |
| <div class="bar" | |
| style="background:var(--primary-container);box-shadow:0 0 10px var(--primary-container);width:100%;"> | |
| </div> | |
| </div> | |
| <div class="source-btn" id="source-audio"> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--secondary);margin-bottom:8px;">graphic_eq</span> | |
| <span class="source-name" style="color:var(--secondary);">Audio Spectrum</span> | |
| <span class="source-label" id="audio-status">Standby</span> | |
| <div class="bar" style="background:var(--secondary);box-shadow:0 0 10px var(--secondary);width:0%;"> | |
| </div> | |
| </div> | |
| <div class="source-btn" id="source-text"> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--tertiary-fixed-dim);margin-bottom:8px;">segment</span> | |
| <span class="source-name" style="color:var(--tertiary-fixed-dim);">Text Sentiment</span> | |
| <span class="source-label" id="text-status">Standby</span> | |
| <div class="bar" | |
| style="background:var(--tertiary-fixed-dim);box-shadow:0 0 10px var(--tertiary-fixed-dim);width:0%;"> | |
| </div> | |
| </div> | |
| <!-- AI Model Status --> | |
| <div style="margin-top:auto;" class="glass-card" style="padding:16px;"> | |
| <div style="padding:16px;"> | |
| <div style="display:flex;align-items:center;gap:6px;margin-bottom:8px;"> | |
| <span | |
| style="width:6px;height:6px;border-radius:50%;background:var(--primary-container);box-shadow:0 0 5px var(--primary-container);"></span> | |
| <span | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.1em;font-weight:700;">AI | |
| Engine</span> | |
| </div> | |
| <div style="font-size:12px;color:var(--on-surface-variant);font-weight:600;" id="model-name"> | |
| Sentinel-CNN-v1</div> | |
| <div style="font-size:9px;color:var(--outline);text-transform:uppercase;margin-top:4px;" | |
| id="model-latency">Latency: —</div> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ── Center Panel: Live Feed + Log ── --> | |
| <section class="center-panel"> | |
| <div class="video-container" id="video-container"> | |
| <video id="webcam-video" autoplay playsinline muted></video> | |
| <canvas id="mesh-canvas"></canvas> | |
| <!-- Mesh dot overlay --> | |
| <div id="mesh-dot-overlay" | |
| style="position:absolute;inset:0;pointer-events:none;background-image:radial-gradient(circle,rgba(0,255,0,0.2) 1px,transparent 1px);background-size:20px 20px;opacity:0.2;"> | |
| </div> | |
| <div class="video-overlay-top"> | |
| <div class="emotion-badge"> | |
| <div class="emotion-badge-label">Detected Emotion</div> | |
| <div class="emotion-badge-value" id="face-emotion-display">— —</div> | |
| </div> | |
| </div> | |
| <div class="video-overlay-bottom"> | |
| <div | |
| style="display:flex;align-items:center;gap:16px;background:rgba(0,0,0,0.4);backdrop-filter:blur(12px);padding:8px 16px;border-radius:999px;border:1px solid rgba(255,255,255,0.1);"> | |
| <div style="text-align:center;"><span | |
| style="font-size:8px;text-transform:uppercase;color:var(--outline);display:block;">Blink | |
| Rate</span><span style="font-size:12px;font-weight:700;" id="blink-rate">—</span> | |
| </div> | |
| <div style="width:1px;height:24px;background:rgba(255,255,255,0.1);"></div> | |
| <div style="text-align:center;"><span | |
| style="font-size:8px;text-transform:uppercase;color:var(--outline);display:block;">Head | |
| Pose</span><span style="font-size:12px;font-weight:700;" id="head-pose">—</span> | |
| </div> | |
| <div style="width:1px;height:24px;background:rgba(255,255,255,0.1);"></div> | |
| <div style="text-align:center;"><span | |
| style="font-size:8px;text-transform:uppercase;color:var(--outline);display:block;">Landmarks</span><span | |
| style="font-size:12px;font-weight:700;" id="landmark-count">0</span></div> | |
| </div> | |
| </div> | |
| <!-- Scan line effect --> | |
| <div id="scan-line" | |
| style="display:none;position:absolute;left:0;width:100%;height:2px;background:linear-gradient(90deg,transparent,#00ff00,transparent);animation:scan-line 3s linear infinite;opacity:0.4;"> | |
| </div> | |
| </div> | |
| <!-- Text Panel --> | |
| <div class="glass-card" id="text-panel" | |
| style="display:none; flex: 1; min-height: 300px; padding: 24px; flex-direction:column;"> | |
| <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;"> | |
| <div> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| System NLP Engine</div> | |
| <div | |
| style="font-family:var(--font-headline);font-size:1.4rem;font-weight:700;color:var(--tertiary-fixed-dim);"> | |
| Text Sentiment Analysis</div> | |
| </div> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--tertiary-fixed-dim);font-size:32px;">segment</span> | |
| </div> | |
| <div id="text-sentiment-history" | |
| style="flex:1; overflow-y:auto; background:rgba(0,0,0,0.2); border-radius:12px; padding:16px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--on-surface-variant);"> | |
| <div style="color:var(--outline); text-align:center; margin-top:20px;">Analysis stream empty. | |
| Type something below to begin.</div> | |
| </div> | |
| <!-- Manual Text Input (Restored) --> | |
| <div | |
| style="margin-top:16px; position:relative; display:flex; align-items:center; background:rgba(255,255,255,0.03); border-radius:8px 8px 0 0; border-bottom: 2px solid rgba(0, 255, 255, 0.5); box-shadow: 0 4px 12px -4px rgba(0, 255, 255, 0.4);"> | |
| <input type="text" id="live-text-input" placeholder="Enter text for deep semantic analysis..." | |
| style="flex:1; background:transparent; border:none; padding:14px 50px 14px 16px; color:#fff; outline:none; font-size:14px; letter-spacing:0.5px;"> | |
| <button id="ctrl-text-send" title="Analyze Sentiment" | |
| style="position:absolute; right:12px; background:transparent; border:none; color:cyan; cursor:pointer; display:flex; align-items:center; justify-content:center; transition: all 0.3s ease;" | |
| onmouseover="this.style.transform='scale(1.1)'; this.style.filter='drop-shadow(0 0 5px cyan)';" | |
| onmouseout="this.style.transform='scale(1)'; this.style.filter='none';"> | |
| <span class="material-symbols-outlined" style="font-size:24px;">send</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Audio Panel --> | |
| <div class="glass-card" id="audio-panel" | |
| style="display:none; flex: 1; min-height: 300px; padding: 24px; flex-direction:column;"> | |
| <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;"> | |
| <div> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| System Acoustic Engine</div> | |
| <div | |
| style="font-family:var(--font-headline);font-size:1.4rem;font-weight:700;color:var(--secondary);"> | |
| Audio Spectrum Visualizer</div> | |
| </div> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--secondary);font-size:32px;">graphic_eq</span> | |
| </div> | |
| <div style="flex:1; display:flex; align-items:flex-end; gap:4px; padding:20px; background:rgba(0,0,0,0.2); border-radius:12px; position:relative;" | |
| id="big-audio-viz"> | |
| <!-- Big bars handled by JS --> | |
| </div> | |
| <div style="margin-top:20px; text-align:center;"> | |
| <button class="btn-record-audio" id="btn-record-audio" style="display:none;"> | |
| <span class="material-symbols-outlined">mic</span> | |
| Record Live Audio | |
| </button> | |
| </div> | |
| <div style="margin-top:16px; text-align:center; display:none; flex-direction:column; gap:12px; align-items:center;" | |
| id="audio-preview-section"> | |
| <audio id="audio-previewer" controls | |
| style="height:36px; border-radius:999px; outline:none; max-width:80%;"></audio> | |
| <button class="btn-record-audio" id="btn-analyze-audio" | |
| style="background:var(--primary-container); color:#000; border:none; padding:8px 24px;"> | |
| <span class="material-symbols-outlined">analytics</span> | |
| Analyze Preview | |
| </button> | |
| </div> | |
| <div | |
| style="margin-top:16px; text-align:center; position:relative; min-height:40px; display:flex; justify-content:center; align-items:center;"> | |
| <span id="speech-emotion-display-big" | |
| style="font-family:var(--font-headline);font-size:1.5rem;font-weight:700;color:var(--secondary);">Standby</span> | |
| <button id="btn-toggle-transcript" | |
| style="position:absolute; right:0; background:rgba(255,255,255,0.05); border:1px solid rgba(255,255,255,0.1); border-radius:30px; padding:5px 12px; display:flex; align-items:center; gap:6px; color:var(--on-surface); cursor:pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-size:11px; backdrop-filter: blur(4px);" | |
| onmouseover="this.style.background='rgba(255,255,255,0.15)';this.style.borderColor='var(--primary-container)'" | |
| onmouseout="this.style.background='rgba(255,255,255,0.05)';this.style.borderColor='rgba(255,255,255,0.1)'"> | |
| <span class="material-symbols-outlined" style="font-size:16px;" | |
| id="icon-transcript-toggle">visibility</span> | |
| <span id="text-transcript-toggle" style="font-weight:600; letter-spacing:0.5px;">SHOW | |
| TRANSCRIPT</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Tech Log --> | |
| <div class="tech-log glass-card" id="tech-log"> | |
| <div | |
| style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;border-bottom:1px solid rgba(59,73,75,0.1);padding-bottom:4px;"> | |
| <span | |
| style="text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;">Technical | |
| Data Stream</span> | |
| <span style="color:var(--primary-container);" id="log-status">STANDBY</span> | |
| </div> | |
| <div id="log-content" style="overflow-y:auto;max-height:72px;"> | |
| <p class="log-line"><span class="tag-face">[SYSTEM]</span> Sentinel Live Pulse initialized. | |
| Ready for monitoring.</p> | |
| </div> | |
| </div> | |
| </section> | |
| <!-- ── Right Panel: Analytics ── --> | |
| <section class="analytics-panel"> | |
| <!-- Speech Prosody --> | |
| <div class="glass-card" style="padding:20px;"> | |
| <div style="display:flex;justify-content:space-between;align-items:flex-start;"> | |
| <div> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| Speech Prosody</div> | |
| <div style="font-family:var(--font-headline);font-size:1.1rem;font-weight:700;">Pitch & Tone | |
| </div> | |
| </div> | |
| <span class="material-symbols-outlined" style="color:var(--secondary);">waves</span> | |
| </div> | |
| <div class="prosody-bars" id="prosody-bars"> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.2);height:40%;"></div> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.4);height:60%;"></div> | |
| <div class="prosody-bar" | |
| style="background:var(--secondary);height:90%;box-shadow:0 0 10px rgba(209,188,255,0.5);"> | |
| </div> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.6);height:70%;"></div> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.3);height:50%;"></div> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.8);height:85%;"></div> | |
| <div class="prosody-bar" style="background:rgba(209,188,255,0.4);height:30%;"></div> | |
| </div> | |
| <div style="margin-top:8px;font-size:11px;color:var(--on-surface-variant);" | |
| id="speech-emotion-display">Emotion: —</div> | |
| </div> | |
| <!-- Sentiment Score --> | |
| <div class="glass-card" style="padding:20px;"> | |
| <div style="display:flex;justify-content:space-between;align-items:flex-start;"> | |
| <div> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| Sentiment Score</div> | |
| <div style="font-family:var(--font-headline);font-size:1.1rem;font-weight:700;">Text | |
| Analysis</div> | |
| </div> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--tertiary-fixed-dim);">query_stats</span> | |
| </div> | |
| <div style="margin-top:16px;"> | |
| <div class="progress-track"> | |
| <div class="progress-fill" id="sentiment-bar" | |
| style="width:50%;background:linear-gradient(90deg,var(--error),var(--tertiary-fixed-dim),var(--primary-container));"> | |
| </div> | |
| </div> | |
| <div | |
| style="display:flex;justify-content:space-between;margin-top:8px;font-size:9px;text-transform:uppercase;font-weight:700;color:var(--outline);"> | |
| <span>Negative</span> | |
| <span style="color:var(--primary-container);" id="sentiment-score-display">—</span> | |
| </div> | |
| </div> | |
| <div style="margin-top:12px;font-size:11px;color:var(--on-surface-variant);" | |
| id="text-sentiment-label">Sentiment: —</div> | |
| </div> | |
| <!-- Engagement Trend --> | |
| <div class="glass-card" style="padding:20px;flex:1;display:flex;flex-direction:column;"> | |
| <div style="display:flex;justify-content:space-between;align-items:flex-start;"> | |
| <div> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.08em;color:var(--outline);font-weight:600;"> | |
| Engagement Trend</div> | |
| <div style="font-family:var(--font-headline);font-size:1.1rem;font-weight:700;">Session | |
| Lifecycle</div> | |
| </div> | |
| <span class="material-symbols-outlined" | |
| style="color:var(--primary-container);">trending_up</span> | |
| </div> | |
| <div style="flex:1;position:relative;margin-top:12px;min-height:120px;"> | |
| <canvas id="engagement-chart" | |
| style="position:absolute;top:0;left:0;width:100%;height:100%;"></canvas> | |
| </div> | |
| <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:12px;"> | |
| <div class="stat-card" style="padding:10px;"> | |
| <div class="stat-label" style="font-size:8px;">Peak</div> | |
| <div style="font-family:var(--font-headline);font-size:1rem;font-weight:700;color:var(--primary-container);" | |
| id="peak-engagement">—</div> | |
| </div> | |
| <div class="stat-card" style="padding:10px;"> | |
| <div class="stat-label" style="font-size:8px;">Average</div> | |
| <div style="font-family:var(--font-headline);font-size:1rem;font-weight:700;color:var(--secondary);" | |
| id="avg-engagement">—</div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Overall Engagement Score --> | |
| <div class="glass-card" style="padding:20px;text-align:center;"> | |
| <div | |
| style="font-size:10px;text-transform:uppercase;letter-spacing:0.1em;color:var(--outline);font-weight:600;margin-bottom:8px;"> | |
| Overall Engagement</div> | |
| <div class="engagement-ring" style="margin:0 auto;"> | |
| <svg viewBox="0 0 120 120"> | |
| <circle class="ring-track" cx="60" cy="60" r="52"></circle> | |
| <circle class="ring-fill" cx="60" cy="60" r="52" stroke-dasharray="326.73" | |
| stroke-dashoffset="326.73" id="engagement-ring-fill"></circle> | |
| </svg> | |
| <span class="ring-value" id="engagement-value">0%</span> | |
| </div> | |
| <div style="margin-top:8px;font-size:12px;font-weight:600;color:var(--on-surface-variant);" | |
| id="engagement-level">Unknown</div> | |
| </div> | |
| </section> | |
| </div> | |
| </main> | |
| <script src="/js/live.js?v=24"></script> | |
| </body> | |
| </html> |