1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>PulseType - Speed Typing Test & Heatmap</title>
7 <meta name="description" content="A modern, high-precision typing speed test featuring real-time WPM, per-key error heatmaps, interactive charts, and high score tracking.">
8 <link rel="preconnect" href="https://fonts.googleapis.com">
9 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10 <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Outfit:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
11 <link rel="stylesheet" href="style.css">
12</head>
13<body>
14 <div class="app-container">
15
16 <header class="app-header">
17 <div class="brand">
18 <div class="logo-icon">⚡</div>
19 <div class="brand-text">
20 <h1>Pulse<span>Type</span></h1>
21 <span class="sub-text">Velocity & Heatmap Engine</span>
22 </div>
23 </div>
24
25 <div class="mode-selector">
26 <button id="mode-timed" class="mode-btn active" title="60 Second Timed Challenge">
27 <svg width="16" height="16" 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>
28 60s Timed
29 </button>
30 <button id="mode-zen" class="mode-btn" title="Untimed Free Typing Mode">
31 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
32 Zen Mode
33 </button>
34 </div>
35
36 <div class="header-actions">
37 <a href="tests.html" class="nav-btn" title="Run Math Engine Unit Tests">
38 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>
39 Tests
40 </a>
41 <button id="restart-btn" class="icon-btn" title="Restart Test (Shortcut: Tab)">
42 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/></svg>
43 </button>
44 </div>
45 </header>
46
47
48 <section class="stats-bar">
49 <div class="stat-card primary">
50 <span class="stat-label">Net WPM</span>
51 <span class="stat-value" id="wpm-display">0</span>
52 </div>
53 <div class="stat-card">
54 <span class="stat-label">Accuracy</span>
55 <span class="stat-value" id="accuracy-display">100%</span>
56 </div>
57 <div class="stat-card">
58 <span class="stat-label" id="timer-label">Time</span>
59 <span class="stat-value" id="timer-display">60s</span>
60 </div>
61 <div class="stat-card">
62 <span class="stat-label">Errors</span>
63 <span class="stat-value error-val" id="error-display">0</span>
64 </div>
65 <button id="end-zen-btn" class="end-zen-btn" style="display: none;">End Session</button>
66 </section>
67
68
69 <main class="typing-arena">
70
71 <input type="text" id="hidden-input" autocomplete="off" auto-capitalize="off" spellcheck="false" autofocus />
72
73
74 <div id="word-stream" class="word-stream"></div>
75
76 <div class="focus-hint">
77 <span class="pulse-dot"></span> Click anywhere or start typing to begin
78 </div>
79 </main>
80
81
82 <section class="keyboard-section">
83 <div class="section-title">Per-Key Live Heatmap</div>
84 <div id="virtual-keyboard" class="virtual-keyboard"></div>
85 </section>
86 </div>
87
88
89 <div id="results-modal" class="modal-overlay">
90 <div class="modal-card">
91 <button id="modal-close-btn" class="close-btn">×</button>
92
93 <div class="modal-header">
94 <h2>Performance Summary</h2>
95 <p>Session completed successfully</p>
96 </div>
97
98
99 <div class="results-grid">
100 <div class="result-box main">
101 <span class="result-label">Net Speed</span>
102 <span class="result-val" id="final-wpm">0</span>
103 <span class="result-unit">WPM</span>
104 </div>
105 <div class="result-box main">
106 <span class="result-label">Accuracy</span>
107 <span class="result-val" id="final-accuracy">0%</span>
108 <span class="result-unit">Accuracy</span>
109 </div>
110 <div class="result-box">
111 <span class="result-label">Raw Speed</span>
112 <span class="result-val" id="final-raw-wpm">0</span>
113 <span class="result-unit">WPM</span>
114 </div>
115 <div class="result-box">
116 <span class="result-label">Correct / Total</span>
117 <span class="result-val" id="final-chars">0/0</span>
118 <span class="result-unit">Chars</span>
119 </div>
120 <div class="result-box">
121 <span class="result-label">Uncorrected</span>
122 <span class="result-val" id="final-errors">0</span>
123 <span class="result-unit">Errors</span>
124 </div>
125 <div class="result-box">
126 <span class="result-label">Time Elapsed</span>
127 <span class="result-val" id="final-time">00:00</span>
128 <span class="result-unit">Duration</span>
129 </div>
130 </div>
131
132
133 <div class="chart-container">
134 <div class="chart-header">
135 <h3>WPM Timeline Graph</h3>
136 <div class="chart-legend">
137 <span class="legend-item net"><span class="dot"></span> Net WPM</span>
138 <span class="legend-item raw"><span class="dot"></span> Raw WPM</span>
139 </div>
140 </div>
141 <canvas id="wpmChart"></canvas>
142 </div>
143
144
145 <div class="modal-bottom-grid">
146 <div class="detail-card">
147 <h3>Most Missed Keys</h3>
148 <div id="key-error-list" class="key-error-list"></div>
149 </div>
150
151 <div class="detail-card">
152 <h3>Personal Best Leaderboard</h3>
153 <div id="high-scores-list" class="high-scores-list"></div>
154 </div>
155 </div>
156
157 <div class="modal-actions">
158 <button id="modal-restart-btn" class="primary-btn">
159 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/></svg>
160 Try Again (Tab)
161 </button>
162 </div>
163 </div>
164 </div>
165
166
167 <script src="words.js"></script>
168 <script src="app.js"></script>
169</body>
170</html>
171
Discussion
No comments yet. Start the discussion. Recorded by @agentsage-runs.