SecureAttendAI / frontend /index.html
Nishant Katiyar
Deploy biometric node to HF Spaces
b561839
Raw
History Blame Contribute Delete
29.1 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SecureAttend AI - Facial Recognition Attendance Control Center</title>
<!-- Material Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Custom Styling -->
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<!-- Floating Escape button for Kiosk mode -->
<button class="kiosk-escape-btn" id="btn-kiosk-escape" style="display: none;">
<i class="material-icons">exit_to_app</i>
<span>Exit Kiosk</span>
</button>
<!-- Futuristic Glassmorphism Login Overlay -->
<div id="login-overlay" class="login-overlay">
<div class="login-card glass-card">
<div class="logo-container" style="justify-content: center; margin-bottom: 24px;">
<i class="material-icons logo-icon" style="font-size: 36px;">fingerprint</i>
<h2 style="font-size: 24px; font-weight: 800; background: linear-gradient(90deg, #ffffff, var(--neon-cyan)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin: 0;">SECUREATTEND AI</h2>
</div>
<h3 style="text-align: center; margin-bottom: 8px; font-size: 18px; font-weight: 700;">BIOMETRIC TERMINAL ACCESS</h3>
<p style="text-align: center; color: var(--text-secondary); font-size: 13px; margin-bottom: 28px;">Authorization required. Input credential keys.</p>
<div class="form-group">
<label class="form-label" for="login-username">SECURITY ACCOUNT KEY</label>
<input type="text" id="login-username" class="form-input" placeholder="e.g. admin, hr, kiosk">
</div>
<div class="form-group" style="margin-bottom: 28px;">
<label class="form-label" for="login-password">SECURE KEYPASS</label>
<input type="password" id="login-password" class="form-input" placeholder="••••••••">
</div>
<button class="btn" id="btn-login-submit" style="width: 100%; justify-content: center; padding: 12px;">
<i class="material-icons">key</i>
<span>Establish Security Session</span>
</button>
<div id="login-error-msg" style="color: var(--neon-red); text-align: center; font-size: 13px; font-weight: 600; margin-top: 16px; display: none;">
Access Denied: Invalid Keystore Combination.
</div>
</div>
</div>
<div class="app-container">
<!-- 1. Left Navigation Sidebar -->
<aside class="sidebar" id="app-sidebar">
<div class="logo-container" style="margin-bottom: 10px;">
<i class="material-icons logo-icon">fingerprint</i>
<div class="logo-text">SECUREATTEND AI</div>
</div>
<div id="role-badge-container" style="margin-bottom: 30px; padding-left: 8px;">
<span id="role-badge" style="font-size: 10px; background: rgba(0, 255, 242, 0.1); border: 1px solid var(--neon-cyan); color: var(--neon-cyan); padding: 2.5px 10px; border-radius: 20px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;">ADMIN NODE</span>
</div>
<ul class="nav-links">
<li class="nav-item active" data-tab="dashboard">
<i class="material-icons">dashboard</i>
<span>Dashboard</span>
</li>
<li class="nav-item" data-tab="scanner">
<i class="material-icons">videocam</i>
<span>Live Scanner</span>
</li>
<li class="nav-item" data-tab="directory">
<i class="material-icons">people</i>
<span>Employee Directory</span>
</li>
<li class="nav-item" data-tab="settings">
<i class="material-icons">settings</i>
<span>Admin Settings</span>
</li>
<li class="nav-item" id="nav-logout" style="margin-top: 24px; border: 1px solid rgba(231, 76, 60, 0.15); background: rgba(231, 76, 60, 0.03); color: var(--neon-red);">
<i class="material-icons" style="color: var(--neon-red);">power_settings_new</i>
<span style="color: var(--neon-red); font-weight: 600;">Close Session</span>
</li>
</ul>
<div class="sidebar-footer">
<div class="sys-status-indicator"></div>
<div class="sys-status-text">SYSTEM SECURE & ACTIVE</div>
</div>
</aside>
<!-- 2. Main Viewport Content -->
<main class="main-content">
<!-- View Header -->
<header class="view-header">
<div class="view-title">
<h1 id="view-title-text">Dashboard Overview</h1>
<p id="view-subtitle-text">Real-time attendance metrics & engine status.</p>
</div>
<div class="current-time-container" style="text-align: right;">
<h3 id="live-clock" style="font-weight: 700; color: var(--neon-cyan); letter-spacing: 0.5px;">12:00:00 PM</h3>
<span style="font-size: 12px; color: var(--text-secondary); font-weight: 500;">LOCAL SECURITY NODE</span>
</div>
</header>
<!-- TAB PANEL 1: DASHBOARD OVERVIEW -->
<section id="tab-dashboard" class="tab-panel active">
<!-- Metrics Counter Grid -->
<div class="widgets-grid">
<div class="glass-card widget-card">
<div class="widget-icon"><i class="material-icons">people_outline</i></div>
<div class="widget-info">
<h3 id="stat-total">0</h3>
<p>Total Enrolled</p>
</div>
</div>
<div class="glass-card widget-card" style="border-color: rgba(46, 204, 113, 0.15);">
<div class="widget-icon" style="background: rgba(46, 204, 113, 0.08); color: var(--neon-green); box-shadow: 0 0 15px rgba(46, 204, 113, 0.2);"><i class="material-icons">check_circle_outline</i></div>
<div class="widget-info">
<h3 id="stat-present">0</h3>
<p>Checked In Today</p>
</div>
</div>
<div class="glass-card widget-card" style="border-color: rgba(241, 196, 15, 0.15);">
<div class="widget-icon" style="background: rgba(241, 196, 15, 0.08); color: var(--neon-amber); box-shadow: 0 0 15px rgba(241, 196, 15, 0.2);"><i class="material-icons">exit_to_app</i></div>
<div class="widget-info">
<h3 id="stat-out">0</h3>
<p>Checked Out Today</p>
</div>
</div>
<div class="glass-card widget-card" style="border-color: rgba(231, 76, 60, 0.15);">
<div class="widget-icon" style="background: rgba(231, 76, 60, 0.08); color: var(--neon-red); box-shadow: 0 0 15px rgba(231, 76, 60, 0.2);"><i class="material-icons">error_outline</i></div>
<div class="widget-info">
<h3 id="stat-absent">0</h3>
<p>Absent Today</p>
</div>
</div>
</div>
<!-- Dynamic Dynamic SVG Analytics Charts -->
<div class="analytics-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 24px;">
<!-- Chart 1: Weekly spline curve -->
<div class="glass-card chart-card" style="display: flex; flex-direction: column; gap: 16px; padding: 20px; min-height: 270px; position: relative;">
<div class="activity-header" style="margin-bottom: 0;">
<span style="display: flex; align-items: center; gap: 8px;">
<i class="material-icons" style="color: var(--neon-cyan); font-size: 20px;">trending_up</i>
WEEKLY ATTENDANCE TRENDS
</span>
<span style="font-size: 11px; background: rgba(0, 255, 242, 0.1); border: 1px solid var(--neon-cyan); color: var(--neon-cyan); padding: 2.5px 10px; border-radius: 20px; font-weight: 700; text-transform: uppercase;">PAST 7 DAYS</span>
</div>
<div class="chart-container" style="position: relative; flex-grow: 1; width: 100%;">
<svg id="weekly-trends-svg" width="100%" height="100%" viewBox="0 0 500 200" preserveAspectRatio="none" style="overflow: visible;">
<defs>
<linearGradient id="cyan-gradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="var(--neon-cyan)" stop-opacity="0.3"/>
<stop offset="100%" stop-color="var(--neon-cyan)" stop-opacity="0.0"/>
</linearGradient>
<filter id="neon-glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- SVG path, gridlines, labels, and nodes are injected in JS -->
</svg>
</div>
</div>
<!-- Chart 2: Hourly bar columns -->
<div class="glass-card chart-card" style="display: flex; flex-direction: column; gap: 16px; padding: 20px; min-height: 270px; position: relative;">
<div class="activity-header" style="margin-bottom: 0;">
<span style="display: flex; align-items: center; gap: 8px;">
<i class="material-icons" style="color: var(--neon-green); font-size: 20px;">bar_chart</i>
HOURLY PEAK SCAN CLUSTERS
</span>
<span style="font-size: 11px; background: rgba(46, 204, 113, 0.1); border: 1px solid var(--neon-green); color: var(--neon-green); padding: 2.5px 10px; border-radius: 20px; font-weight: 700; text-transform: uppercase;">TODAY</span>
</div>
<div class="chart-container" style="position: relative; flex-grow: 1; width: 100%;">
<svg id="hourly-clusters-svg" width="100%" height="100%" viewBox="0 0 500 200" preserveAspectRatio="none" style="overflow: visible;">
<defs>
<filter id="green-glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<!-- SVG bars, grids, and values are injected in JS -->
</svg>
</div>
</div>
</div>
<!-- Dashboard Main Split -->
<div class="dashboard-layout">
<!-- Info panel -->
<div class="glass-card" style="display: flex; flex-direction: column; justify-content: center; padding: 40px; background: linear-gradient(135deg, rgba(20, 16, 38, 0.45) 0%, rgba(0, 255, 242, 0.02) 100%);">
<h2 style="font-size: 28px; font-weight: 800; margin-bottom: 16px; background: linear-gradient(90deg, #ffffff, var(--neon-cyan)); -webkit-background-clip: text; -webkit-text-fill-color: transparent;">Biometric AI Attendance Node</h2>
<p style="color: var(--text-secondary); line-height: 1.6; margin-bottom: 24px; font-size: 15px;">
Welcome to your local high-accuracy face recognition terminal. The system uses a local deep learning **YuNet** detector and a neural **SFace** vectorizer to recognize registered employees instantaneously at multiple POV head angles.
</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
<div class="glass-card" style="padding: 16px; background: rgba(0, 0, 0, 0.15);">
<h4 style="color: var(--neon-cyan); margin-bottom: 4px; font-size: 13px; text-transform: uppercase;">Engine Mode</h4>
<p style="font-size: 16px; font-weight: 700;">ON-PREMISES CPU</p>
</div>
<div class="glass-card" style="padding: 16px; background: rgba(0, 0, 0, 0.15);">
<h4 style="color: var(--neon-cyan); margin-bottom: 4px; font-size: 13px; text-transform: uppercase;">Confidence Bar</h4>
<p style="font-size: 16px; font-weight: 700;">36.3% COSINE</p>
</div>
</div>
</div>
<!-- Active Activity Logs panel -->
<div class="glass-card activity-card">
<div class="activity-header">
<span>RECENT LOG ACTIVITY</span>
<i class="material-icons" style="color: var(--neon-cyan);">history</i>
</div>
<div class="activity-list" id="dashboard-activity-list">
<!-- Log list dynamically filled -->
<div class="activity-item" style="justify-content: center; color: var(--text-muted); border: none; background: transparent;">
<p>No scans recorded yet today.</p>
</div>
</div>
</div>
</div>
</section>
<!-- TAB PANEL 2: LIVE SCANNER -->
<section id="tab-scanner" class="tab-panel">
<div class="dashboard-layout">
<!-- Live Camera Stream Frame -->
<div class="glass-card" style="display: flex; flex-direction: column; gap: 16px; padding: 20px;">
<div class="activity-header" style="margin-bottom: 0;">
<span>LIVE WEB-CAMERA MONITORING</span>
<span id="cam-badge" style="font-size: 11px; background: rgba(46, 204, 113, 0.15); border: 1px solid var(--neon-green); color: var(--neon-green); padding: 2px 8px; border-radius: 20px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;">ACTIVE</span>
</div>
<div class="feed-container">
<!-- Live Video stream is rendered on canvas via JS -->
<canvas id="live-scanner-canvas" class="live-feed-img" width="640" height="480"></canvas>
</div>
<!-- Camera controls panel -->
<div style="display: flex; justify-content: space-between; align-items: center; padding-top: 4px;">
<span style="font-size: 13px; color: var(--text-secondary); font-weight: 500;">Hardware Control:</span>
<button class="btn" id="btn-toggle-camera" style="padding: 8px 18px; font-size: 13px; border-radius: 10px;">
<i class="material-icons" style="font-size: 18px;">videocam_off</i>
<span>Disable Camera</span>
</button>
</div>
</div>
<!-- Quick Scanner Logs console -->
<div class="glass-card activity-card">
<div class="activity-header">
<span>SESSION ATTENDANCE RECORDS</span>
<span id="session-log-count" style="font-size: 12px; color: var(--neon-cyan); font-weight: 700;">0 LOGS</span>
</div>
<div class="activity-list" id="scanner-session-logs">
<!-- Dynamically filled stream -->
<div class="activity-item" style="justify-content: center; color: var(--text-muted); border: none; background: transparent;">
<p>Standing in front of the camera to check-in/out.</p>
</div>
</div>
</div>
</div>
</section>
<!-- TAB PANEL 3: EMPLOYEE DIRECTORY -->
<section id="tab-directory" class="tab-panel">
<div class="glass-card directory-layout">
<!-- Table Controls -->
<div class="table-controls">
<div class="search-input-wrapper">
<i class="material-icons">search</i>
<input type="text" id="directory-search" class="search-input" placeholder="Search employees by ID, name, or role...">
</div>
<button class="btn" id="btn-open-enrollment">
<i class="material-icons">person_add</i>
<span>Register Employee</span>
</button>
</div>
<!-- Directory Table Container -->
<div class="table-container">
<table>
<thead>
<tr>
<th>Employee ID</th>
<th>Employee Name</th>
<th>Email Address</th>
<th>Designation / Role</th>
<th>Enrollment Date</th>
<th style="text-align: right;">Action</th>
</tr>
</thead>
<tbody id="directory-table-body">
<!-- Filled dynamically -->
<tr>
<td colspan="6" style="text-align: center; color: var(--text-muted); padding: 40px;">
Retrieving employees database directory...
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- TAB PANEL 4: ADMIN SETTINGS -->
<section id="tab-settings" class="tab-panel">
<div class="settings-grid">
<!-- Camera Config Card -->
<div class="glass-card" style="display: flex; flex-direction: column; gap: 20px;">
<h3 style="font-size: 18px; font-weight: 700; color: var(--neon-cyan); display: flex; align-items: center; gap: 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.05); padding-bottom: 12px;">
<i class="material-icons">videocam</i>
Webcam Input Settings
</h3>
<div class="form-group">
<label class="form-label" for="camera-select">ACTIVE CAMERA INPUT ID</label>
<select id="camera-select" class="form-input" style="background: rgba(0,0,0,0.3); border-color: var(--glass-border);">
<option value="0">Camera Index 0 (Default Integrated Cam)</option>
<option value="1">Camera Index 1 (External USB WebCam)</option>
<option value="2">Camera Index 2 (Secondary Device)</option>
<option value="3">Camera Index 3 (Virtual Camera / OBS)</option>
</select>
</div>
<button class="btn" id="btn-save-camera" style="width: 100%; justify-content: center;">
<i class="material-icons">save</i>
<span>Switch Active Camera Source</span>
</button>
</div>
<!-- System Status Rules Card -->
<div class="glass-card" style="display: flex; flex-direction: column; gap: 20px;">
<h3 style="font-size: 18px; font-weight: 700; color: var(--neon-cyan); display: flex; align-items: center; gap: 8px; border-bottom: 1px solid rgba(255, 255, 255, 0.05); padding-bottom: 12px;">
<i class="material-icons">security</i>
Attendance Matching Rules
</h3>
<div style="display: flex; flex-direction: column; gap: 14px; font-size: 14px;">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid rgba(255,255,255,0.03); padding-bottom: 8px;">
<span style="color: var(--text-secondary);">Double-Scan Debounce:</span>
<span style="font-weight: 700; color: var(--neon-cyan);">2 Minutes Cooldown</span>
</div>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid rgba(255,255,255,0.03); padding-bottom: 8px;">
<span style="color: var(--text-secondary);">Verification Strategy:</span>
<span style="font-weight: 700; color: var(--neon-green);">Cosine Similarity</span>
</div>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid rgba(255,255,255,0.03); padding-bottom: 8px;">
<span style="color: var(--text-secondary);">Matching Threshold:</span>
<span style="font-weight: 700; color: var(--neon-cyan);">0.363 (SFace Default)</span>
</div>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid rgba(255,255,255,0.03); padding-bottom: 8px;">
<span style="color: var(--text-secondary);">Enrollment Angles Required:</span>
<span style="font-weight: 700; color: var(--neon-cyan);">5 Angles (3D POV mapping)</span>
</div>
</div>
</div>
</div>
</section>
</main>
</div>
<!-- 3. Dynamic Multi-Angle Enrollment Wizard (Modal) -->
<div class="wizard-modal" id="wizard-modal">
<div class="wizard-card glass-card">
<!-- Wizard Left Sidebar -->
<aside class="wizard-sidebar">
<h3 style="font-size: 16px; font-weight: 700; margin-bottom: 24px; color: var(--neon-cyan);">Registration</h3>
<ul class="wizard-steps">
<li class="step-indicator active" id="step-ind-1">
<div class="step-num">1</div>
<span>Profile Details</span>
</li>
<li class="step-indicator" id="step-ind-2">
<div class="step-num">2</div>
<span>Biometric Scans</span>
</li>
<li class="step-indicator" id="step-ind-3">
<div class="step-num">3</div>
<span>Registration Complete</span>
</li>
</ul>
</aside>
<!-- Wizard Right Content Panel -->
<div class="wizard-content">
<!-- STEP 1 PANEL: Employee Details Form -->
<div class="wizard-panel active" id="wizard-panel-1">
<h2 style="font-size: 22px; font-weight: 700; margin-bottom: 6px;">Create Employee Profile</h2>
<p style="color: var(--text-secondary); font-size: 14px; margin-bottom: 28px;">Input employee credentials before proceeding to biometric registration.</p>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; flex-grow: 1; align-content: flex-start;">
<div class="form-group">
<label class="form-label" for="emp-id-input">Employee ID</label>
<input type="text" id="emp-id-input" class="form-input" placeholder="e.g. EMP-2401">
</div>
<div class="form-group">
<label class="form-label" for="emp-name-input">Full Name</label>
<input type="text" id="emp-name-input" class="form-input" placeholder="e.g. Kunal Katiyar">
</div>
<div class="form-group">
<label class="form-label" for="emp-email-input">Work Email</label>
<input type="email" id="emp-email-input" class="form-input" placeholder="e.g. kunal@office.com">
</div>
<div class="form-group">
<label class="form-label" for="emp-role-input">Designation / Role</label>
<input type="text" id="emp-role-input" class="form-input" placeholder="e.g. Lead Fullstack Architect">
</div>
</div>
<div style="display: flex; justify-content: flex-end; gap: 16px; margin-top: auto;">
<button class="btn btn-danger" id="btn-cancel-wizard">Cancel</button>
<button class="btn" id="btn-step1-next">
<span>Next Step: Face Scan</span>
<i class="material-icons">arrow_forward</i>
</button>
</div>
</div>
<!-- STEP 2 PANEL: Biometric Scans (Camera View + Angles Guide) -->
<div class="wizard-panel" id="wizard-panel-2">
<h2 style="font-size: 20px; font-weight: 700; margin-bottom: 4px;">Biometric Facial Scanner</h2>
<p style="color: var(--text-secondary); font-size: 13px; margin-bottom: 20px;">Follow the 5 POV steps below. Turn your face accordingly and scan each angle.</p>
<div class="scan-area-layout">
<!-- Camera View -->
<div style="display: flex; flex-direction: column; gap: 10px;">
<div class="feed-container" style="border-radius: 12px;">
<!-- Renders stream dynamically during enrollment -->
<canvas id="enrollment-canvas" class="live-feed-img" width="640" height="480"></canvas>
<div class="feed-overlay-text" id="enroll-cam-loading-text">Starting Camera Feed...</div>
</div>
<div style="font-size: 11px; color: var(--text-muted); text-align: center; font-weight: 500;">
Webcam capturing aligned 5-point facial coordinates in real-time.
</div>
</div>
<!-- Vertical Angles Cards list -->
<div class="angle-selector">
<div class="angle-card active" data-angle="center">
<div class="angle-label">
<i class="material-icons angle-status-icon">face</i>
<span>1. Center Face (Straight)</span>
</div>
<button class="btn" style="padding: 4px 10px; font-size: 11px; border-radius: 6px;" onclick="app.captureAngle('center')">SCAN</button>
</div>
<div class="angle-card" data-angle="left">
<div class="angle-label">
<i class="material-icons angle-status-icon">chevron_left</i>
<span>2. Look Left (Angle)</span>
</div>
<button class="btn" style="padding: 4px 10px; font-size: 11px; border-radius: 6px;" onclick="app.captureAngle('left')">SCAN</button>
</div>
<div class="angle-card" data-angle="right">
<div class="angle-label">
<i class="material-icons angle-status-icon">chevron_right</i>
<span>3. Look Right (Angle)</span>
</div>
<button class="btn" style="padding: 4px 10px; font-size: 11px; border-radius: 6px;" onclick="app.captureAngle('right')">SCAN</button>
</div>
<div class="angle-card" data-angle="up">
<div class="angle-label">
<i class="material-icons angle-status-icon">expand_less</i>
<span>4. Tilt Up</span>
</div>
<button class="btn" style="padding: 4px 10px; font-size: 11px; border-radius: 6px;" onclick="app.captureAngle('up')">SCAN</button>
</div>
<div class="angle-card" data-angle="down">
<div class="angle-label">
<i class="material-icons angle-status-icon">expand_more</i>
<span>5. Tilt Down</span>
</div>
<button class="btn" style="padding: 4px 10px; font-size: 11px; border-radius: 6px;" onclick="app.captureAngle('down')">SCAN</button>
</div>
</div>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: auto; padding-top: 16px;">
<div style="font-size: 12px; color: var(--text-secondary); font-weight: 500;" id="scan-progress-label">
Scan progress: <span style="color: var(--neon-cyan); font-weight: 700;">0 / 5 angles</span> captured
</div>
<div style="display: flex; gap: 12px;">
<button class="btn btn-danger" style="padding: 8px 16px;" id="btn-step2-back">Back</button>
<button class="btn" style="padding: 8px 20px; opacity: 0.5;" id="btn-step2-next" disabled>
<span>Save & Complete</span>
<i class="material-icons">arrow_forward</i>
</button>
</div>
</div>
</div>
<!-- STEP 3 PANEL: Completion Card -->
<div class="wizard-panel" id="wizard-panel-3" style="align-items: center; justify-content: center; text-align: center; gap: 20px;">
<div style="width: 80px; height: 80px; border-radius: 50%; background: rgba(46, 204, 113, 0.1); border: 2px solid var(--neon-green); display: flex; align-items: center; justify-content: center; color: var(--neon-green); box-shadow: var(--shadow-neon-success); margin-bottom: 8px;">
<i class="material-icons" style="font-size: 48px;">check</i>
</div>
<h2 style="font-size: 24px; font-weight: 800;">Biometric Registration Successful!</h2>
<p style="color: var(--text-secondary); font-size: 15px; max-width: 480px; line-height: 1.6;">
All 5 reference angle embeddings have been processed and encrypted locally. <span id="enrolled-emp-name" style="color: var(--neon-cyan); font-weight: 700;">Kunal Katiyar</span> is now active and will be recognized instantly by the camera stream.
</p>
<button class="btn" id="btn-wizard-finish" style="margin-top: 24px; padding: 12px 32px;">
<span>Return to Control Directory</span>
</button>
</div>
</div>
</div>
</div>
<!-- 4. Floating Real-Time Success Alerts Toast Box -->
<div class="alerts-container" id="alerts-container">
<!-- Notifications automatically fade-in/out here -->
</div>
<!-- Hidden video element for client-side webcam capture -->
<video id="client-webcam" style="display: none;" autoplay playsinline></video>
<!-- Javascript client logic -->
<script src="/static/js/app.js"></script>
</body>
</html>