Aashish34 commited on
Commit
f25d831
Β·
1 Parent(s): 1f0a0ef

updated code

Browse files
._complete-statistics ADDED
Binary file (4.1 kB). View file
 
complete-statistics/app.js ADDED
@@ -0,0 +1,454 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ===== CONFIGURATION & CONSTANTS =====
2
+ const COLORS = {
3
+ primary: '#4a90e2',
4
+ cyan: '#64ffda',
5
+ orange: '#ff6b6b',
6
+ green: '#51cf66',
7
+ background: '#0f3460',
8
+ text: '#e1e1e1',
9
+ textSecondary: '#a0a0a0'
10
+ };
11
+
12
+ const chartColors = ['#1FB8CD', '#FFC185', '#B4413C', '#ECEBD5', '#5D878F', '#DB4545', '#D2BA4C', '#964325', '#944454', '#13343B'];
13
+
14
+ // ===== STATE MANAGEMENT =====
15
+ let currentTopic = 1;
16
+ let animationFrames = {};
17
+
18
+ // ===== INITIALIZATION =====
19
+ document.addEventListener('DOMContentLoaded', () => {
20
+ initNavigation();
21
+ initInteractiveElements();
22
+ setupScrollObserver();
23
+ initializeAllVisualizations();
24
+ });
25
+
26
+ // ===== NAVIGATION =====
27
+ function initNavigation() {
28
+ // Mobile menu toggle
29
+ const mobileMenuBtn = document.getElementById('mobileMenuBtn');
30
+ const sidebar = document.getElementById('sidebar');
31
+
32
+ if (mobileMenuBtn) {
33
+ mobileMenuBtn.addEventListener('click', () => {
34
+ sidebar.classList.toggle('active');
35
+ });
36
+ }
37
+
38
+ // Topic link navigation
39
+ const topicLinks = document.querySelectorAll('.topic-link');
40
+ topicLinks.forEach(link => {
41
+ link.addEventListener('click', (e) => {
42
+ e.preventDefault();
43
+ const topicId = link.getAttribute('data-topic');
44
+ const target = document.getElementById(`topic-${topicId}`);
45
+
46
+ if (target) {
47
+ target.scrollIntoView({ behavior: 'smooth', block: 'start' });
48
+ updateActiveLink(topicId);
49
+
50
+ // Close mobile menu if open
51
+ if (window.innerWidth <= 1024) {
52
+ sidebar.classList.remove('active');
53
+ }
54
+ }
55
+ });
56
+ });
57
+ }
58
+
59
+ function updateActiveLink(topicId) {
60
+ document.querySelectorAll('.topic-link').forEach(link => {
61
+ link.classList.remove('active');
62
+ });
63
+ const activeLink = document.querySelector(`[data-topic="${topicId}"]`);
64
+ if (activeLink) {
65
+ activeLink.classList.add('active');
66
+ }
67
+ currentTopic = parseInt(topicId);
68
+ }
69
+
70
+ // ===== SCROLL OBSERVER =====
71
+ function setupScrollObserver() {
72
+ const options = {
73
+ root: null,
74
+ rootMargin: '-100px',
75
+ threshold: 0.3
76
+ };
77
+
78
+ const observer = new IntersectionObserver((entries) => {
79
+ entries.forEach(entry => {
80
+ if (entry.isIntersecting) {
81
+ const topicId = entry.target.id.split('-')[1];
82
+ updateActiveLink(topicId);
83
+ }
84
+ });
85
+ }, options);
86
+
87
+ document.querySelectorAll('.topic-section').forEach(section => {
88
+ observer.observe(section);
89
+ });
90
+ }
91
+
92
+ // ===== CANVAS UTILITIES =====
93
+ function clearCanvas(ctx, canvas) {
94
+ ctx.fillStyle = COLORS.background;
95
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
96
+ }
97
+
98
+ function drawText(ctx, text, x, y, fontSize = 14, color = COLORS.text, align = 'center') {
99
+ ctx.fillStyle = color;
100
+ ctx.font = `${fontSize}px 'Segoe UI', sans-serif`;
101
+ ctx.textAlign = align;
102
+ ctx.fillText(text, x, y);
103
+ }
104
+
105
+ function drawCircle(ctx, x, y, radius, color, filled = true) {
106
+ ctx.beginPath();
107
+ ctx.arc(x, y, radius, 0, Math.PI * 2);
108
+ if (filled) {
109
+ ctx.fillStyle = color;
110
+ ctx.fill();
111
+ } else {
112
+ ctx.strokeStyle = color;
113
+ ctx.lineWidth = 2;
114
+ ctx.stroke();
115
+ }
116
+ }
117
+
118
+ function drawLine(ctx, x1, y1, x2, y2, color = COLORS.text, width = 1) {
119
+ ctx.beginPath();
120
+ ctx.moveTo(x1, y1);
121
+ ctx.lineTo(x2, y2);
122
+ ctx.strokeStyle = color;
123
+ ctx.lineWidth = width;
124
+ ctx.stroke();
125
+ }
126
+
127
+ function drawRect(ctx, x, y, width, height, color, filled = true) {
128
+ if (filled) {
129
+ ctx.fillStyle = color;
130
+ ctx.fillRect(x, y, width, height);
131
+ } else {
132
+ ctx.strokeStyle = color;
133
+ ctx.lineWidth = 2;
134
+ ctx.strokeRect(x, y, width, height);
135
+ }
136
+ }
137
+
138
+ // ===== STATISTICAL CALCULATIONS =====
139
+ function calculateMean(data) {
140
+ return data.reduce((sum, val) => sum + val, 0) / data.length;
141
+ }
142
+
143
+ function calculateMedian(data) {
144
+ const sorted = [...data].sort((a, b) => a - b);
145
+ const mid = Math.floor(sorted.length / 2);
146
+ return sorted.length % 2 === 0
147
+ ? (sorted[mid - 1] + sorted[mid]) / 2
148
+ : sorted[mid];
149
+ }
150
+
151
+ function calculateMode(data) {
152
+ const frequency = {};
153
+ let maxFreq = 0;
154
+
155
+ data.forEach(val => {
156
+ frequency[val] = (frequency[val] || 0) + 1;
157
+ maxFreq = Math.max(maxFreq, frequency[val]);
158
+ });
159
+
160
+ if (maxFreq === 1) return 'None';
161
+
162
+ const modes = Object.keys(frequency).filter(key => frequency[key] === maxFreq);
163
+ return modes.join(', ');
164
+ }
165
+
166
+ function calculateVariance(data, isSample = true) {
167
+ const mean = calculateMean(data);
168
+ const squaredDiffs = data.map(val => Math.pow(val - mean, 2));
169
+ const divisor = isSample ? data.length - 1 : data.length;
170
+ return squaredDiffs.reduce((sum, val) => sum + val, 0) / divisor;
171
+ }
172
+
173
+ function calculateStdDev(data, isSample = true) {
174
+ return Math.sqrt(calculateVariance(data, isSample));
175
+ }
176
+
177
+ function calculateQuartiles(data) {
178
+ const sorted = [...data].sort((a, b) => a - b);
179
+ const q2 = calculateMedian(sorted);
180
+ const midIndex = Math.floor(sorted.length / 2);
181
+
182
+ const lowerHalf = sorted.length % 2 === 0
183
+ ? sorted.slice(0, midIndex)
184
+ : sorted.slice(0, midIndex);
185
+ const upperHalf = sorted.length % 2 === 0
186
+ ? sorted.slice(midIndex)
187
+ : sorted.slice(midIndex + 1);
188
+
189
+ const q1 = calculateMedian(lowerHalf);
190
+ const q3 = calculateMedian(upperHalf);
191
+
192
+ return { q1, q2, q3 };
193
+ }
194
+
195
+ function calculateIQR(data) {
196
+ const { q1, q3 } = calculateQuartiles(data);
197
+ const iqr = q3 - q1;
198
+ const lowerFence = q1 - 1.5 * iqr;
199
+ const upperFence = q3 + 1.5 * iqr;
200
+
201
+ return { q1, q3, iqr, lowerFence, upperFence };
202
+ }
203
+
204
+ function detectOutliers(data) {
205
+ const { lowerFence, upperFence } = calculateIQR(data);
206
+ return data.filter(val => val < lowerFence || val > upperFence);
207
+ }
208
+
209
+ function calculateCovariance(x, y) {
210
+ const meanX = calculateMean(x);
211
+ const meanY = calculateMean(y);
212
+ let sum = 0;
213
+
214
+ for (let i = 0; i < x.length; i++) {
215
+ sum += (x[i] - meanX) * (y[i] - meanY);
216
+ }
217
+
218
+ return sum / (x.length - 1);
219
+ }
220
+
221
+ function calculateCorrelation(x, y) {
222
+ const cov = calculateCovariance(x, y);
223
+ const stdX = calculateStdDev(x);
224
+ const stdY = calculateStdDev(y);
225
+ return cov / (stdX * stdY);
226
+ }
227
+
228
+ // ===== VISUALIZATION FUNCTIONS =====
229
+
230
+ // Population vs Sample Visualization
231
+ function initPopulationSampleViz() {
232
+ const canvas = document.getElementById('populationSampleCanvas');
233
+ if (!canvas) return;
234
+
235
+ const ctx = canvas.getContext('2d');
236
+ let population = [];
237
+ let sample = [];
238
+ let sampleSize = 30;
239
+
240
+ // Initialize population
241
+ for (let i = 0; i < 200; i++) {
242
+ population.push({
243
+ x: Math.random() * (canvas.width - 40) + 20,
244
+ y: Math.random() * (canvas.height - 40) + 20,
245
+ inSample: false
246
+ });
247
+ }
248
+
249
+ function draw() {
250
+ clearCanvas(ctx, canvas);
251
+
252
+ // Draw title
253
+ drawText(ctx, 'Population (All dots) vs Sample (Highlighted)', canvas.width / 2, 30, 16, COLORS.cyan);
254
+
255
+ // Draw population
256
+ population.forEach(point => {
257
+ const color = point.inSample ? COLORS.orange : COLORS.primary;
258
+ const radius = point.inSample ? 6 : 4;
259
+ drawCircle(ctx, point.x, point.y, radius, color);
260
+ });
261
+
262
+ // Draw statistics
263
+ const popCount = population.length;
264
+ const sampleCount = population.filter(p => p.inSample).length;
265
+ drawText(ctx, `Population Size: N = ${popCount}`, 150, canvas.height - 20, 14, COLORS.text, 'center');
266
+ drawText(ctx, `Sample Size: n = ${sampleCount}`, canvas.width - 150, canvas.height - 20, 14, COLORS.orange, 'center');
267
+ }
268
+
269
+ function takeSample() {
270
+ // Reset all
271
+ population.forEach(p => p.inSample = false);
272
+
273
+ // Randomly select sample
274
+ const shuffled = [...population].sort(() => Math.random() - 0.5);
275
+ for (let i = 0; i < Math.min(sampleSize, population.length); i++) {
276
+ shuffled[i].inSample = true;
277
+ }
278
+
279
+ draw();
280
+ }
281
+
282
+ // Event listeners
283
+ const sampleBtn = document.getElementById('sampleBtn');
284
+ const resetBtn = document.getElementById('resetPopBtn');
285
+ const sizeSlider = document.getElementById('sampleSizeSlider');
286
+ const sizeLabel = document.getElementById('sampleSizeLabel');
287
+
288
+ if (sampleBtn) {
289
+ sampleBtn.addEventListener('click', takeSample);
290
+ }
291
+
292
+ if (resetBtn) {
293
+ resetBtn.addEventListener('click', () => {
294
+ population.forEach(p => p.inSample = false);
295
+ draw();
296
+ });
297
+ }
298
+
299
+ if (sizeSlider) {
300
+ sizeSlider.addEventListener('input', (e) => {
301
+ sampleSize = parseInt(e.target.value);
302
+ if (sizeLabel) {
303
+ sizeLabel.textContent = sampleSize;
304
+ }
305
+ });
306
+ }
307
+
308
+ draw();
309
+ }
310
+
311
+ // Central Tendency Visualization
312
+ function initCentralTendencyViz() {
313
+ const canvas = document.getElementById('centralTendencyCanvas');
314
+ if (!canvas) return;
315
+
316
+ const ctx = canvas.getContext('2d');
317
+ let data = [10, 20, 30, 40, 50];
318
+
319
+ function parseInput(input) {
320
+ return input.split(',').map(s => parseFloat(s.trim())).filter(n => !isNaN(n));
321
+ }
322
+
323
+ function draw() {
324
+ clearCanvas(ctx, canvas);
325
+
326
+ if (data.length === 0) {
327
+ drawText(ctx, 'Please enter valid numbers', canvas.width / 2, canvas.height / 2, 16, COLORS.orange);
328
+ return;
329
+ }
330
+
331
+ const sorted = [...data].sort((a, b) => a - b);
332
+ const min = Math.min(...sorted);
333
+ const max = Math.max(...sorted);
334
+ const range = max - min || 1;
335
+ const padding = 80;
336
+ const width = canvas.width - 2 * padding;
337
+
338
+ // Calculate statistics
339
+ const mean = calculateMean(data);
340
+ const median = calculateMedian(data);
341
+ const mode = calculateMode(data);
342
+
343
+ // Update results display
344
+ document.getElementById('meanResult').textContent = mean.toFixed(2);
345
+ document.getElementById('medianResult').textContent = median.toFixed(2);
346
+ document.getElementById('modeResult').textContent = mode;
347
+
348
+ // Draw axis
349
+ const axisY = canvas.height / 2;
350
+ drawLine(ctx, padding, axisY, canvas.width - padding, axisY, COLORS.text, 2);
351
+
352
+ // Draw data points
353
+ sorted.forEach((val, idx) => {
354
+ const x = padding + ((val - min) / range) * width;
355
+ drawCircle(ctx, x, axisY, 8, COLORS.primary);
356
+ drawText(ctx, val.toString(), x, axisY + 30, 12, COLORS.text);
357
+ });
358
+
359
+ // Draw mean
360
+ const meanX = padding + ((mean - min) / range) * width;
361
+ drawLine(ctx, meanX, axisY - 60, meanX, axisY + 60, COLORS.cyan, 3);
362
+ drawText(ctx, `Mean: ${mean.toFixed(2)}`, meanX, axisY - 70, 14, COLORS.cyan);
363
+
364
+ // Draw median
365
+ const medianX = padding + ((median - min) / range) * width;
366
+ drawLine(ctx, medianX, axisY - 50, medianX, axisY + 50, COLORS.orange, 2);
367
+ drawText(ctx, `Median: ${median.toFixed(2)}`, medianX, axisY - 55, 12, COLORS.orange);
368
+ }
369
+
370
+ // Event listeners
371
+ const input = document.getElementById('centralTendencyInput');
372
+ const calcBtn = document.getElementById('calculateCentralBtn');
373
+ const randomBtn = document.getElementById('randomDataBtn');
374
+
375
+ if (calcBtn && input) {
376
+ calcBtn.addEventListener('click', () => {
377
+ data = parseInput(input.value);
378
+ draw();
379
+ });
380
+ }
381
+
382
+ if (randomBtn && input) {
383
+ randomBtn.addEventListener('click', () => {
384
+ data = Array.from({ length: 10 }, () => Math.floor(Math.random() * 100));
385
+ input.value = data.join(', ');
386
+ draw();
387
+ });
388
+ }
389
+
390
+ if (input) {
391
+ input.addEventListener('keypress', (e) => {
392
+ if (e.key === 'Enter') {
393
+ data = parseInput(input.value);
394
+ draw();
395
+ }
396
+ });
397
+ }
398
+
399
+ draw();
400
+ }
401
+
402
+ // ===== INITIALIZE ALL VISUALIZATIONS =====
403
+ function initializeAllVisualizations() {
404
+ // Topic 2: Population vs Sample
405
+ initPopulationSampleViz();
406
+
407
+ // Topic 5: Central Tendency
408
+ initCentralTendencyViz();
409
+
410
+ // Add more visualizations as needed
411
+ // Each topic with a canvas gets its own initialization function
412
+ }
413
+
414
+ // ===== INTERACTIVE ELEMENTS =====
415
+ function initInteractiveElements() {
416
+ // Add any additional interactive elements here
417
+ // Such as tooltips, modals, etc.
418
+ }
419
+
420
+ // ===== HELPER FUNCTIONS =====
421
+ function generateRandomData(count, min, max) {
422
+ return Array.from({ length: count }, () =>
423
+ Math.floor(Math.random() * (max - min + 1)) + min
424
+ );
425
+ }
426
+
427
+ function formatNumber(num, decimals = 2) {
428
+ return Number(num).toFixed(decimals);
429
+ }
430
+
431
+ // ===== ANIMATION LOOP =====
432
+ function startAnimation(canvasId, animationFunction) {
433
+ if (animationFrames[canvasId]) {
434
+ cancelAnimationFrame(animationFrames[canvasId]);
435
+ }
436
+
437
+ function animate() {
438
+ animationFunction();
439
+ animationFrames[canvasId] = requestAnimationFrame(animate);
440
+ }
441
+
442
+ animate();
443
+ }
444
+
445
+ function stopAnimation(canvasId) {
446
+ if (animationFrames[canvasId]) {
447
+ cancelAnimationFrame(animationFrames[canvasId]);
448
+ delete animationFrames[canvasId];
449
+ }
450
+ }
451
+
452
+ // ===== CONSOLE LOG =====
453
+ console.log('%cπŸ“Š Statistics Mastery Platform Loaded', 'color: #64ffda; font-size: 16px; font-weight: bold;');
454
+ console.log('%cReady to explore 41 comprehensive statistics topics!', 'color: #4a90e2; font-size: 14px;');
complete-statistics/index.html ADDED
The diff for this file is too large to render. See raw diff
 
complete-statistics/style.css ADDED
@@ -0,0 +1,1631 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ /* Primitive Color Tokens */
3
+ --color-white: rgba(255, 255, 255, 1);
4
+ --color-black: rgba(0, 0, 0, 1);
5
+ --color-cream-50: rgba(252, 252, 249, 1);
6
+ --color-cream-100: rgba(255, 255, 253, 1);
7
+ --color-gray-200: rgba(245, 245, 245, 1);
8
+ --color-gray-300: rgba(167, 169, 169, 1);
9
+ --color-gray-400: rgba(119, 124, 124, 1);
10
+ --color-slate-500: rgba(98, 108, 113, 1);
11
+ --color-brown-600: rgba(94, 82, 64, 1);
12
+ --color-charcoal-700: rgba(31, 33, 33, 1);
13
+ --color-charcoal-800: rgba(38, 40, 40, 1);
14
+ --color-slate-900: rgba(19, 52, 59, 1);
15
+ --color-teal-300: rgba(50, 184, 198, 1);
16
+ --color-teal-400: rgba(45, 166, 178, 1);
17
+ --color-teal-500: rgba(33, 128, 141, 1);
18
+ --color-teal-600: rgba(29, 116, 128, 1);
19
+ --color-teal-700: rgba(26, 104, 115, 1);
20
+ --color-teal-800: rgba(41, 150, 161, 1);
21
+ --color-red-400: rgba(255, 84, 89, 1);
22
+ --color-red-500: rgba(192, 21, 47, 1);
23
+ --color-orange-400: rgba(230, 129, 97, 1);
24
+ --color-orange-500: rgba(168, 75, 47, 1);
25
+
26
+ /* RGB versions for opacity control */
27
+ --color-brown-600-rgb: 94, 82, 64;
28
+ --color-teal-500-rgb: 33, 128, 141;
29
+ --color-slate-900-rgb: 19, 52, 59;
30
+ --color-slate-500-rgb: 98, 108, 113;
31
+ --color-red-500-rgb: 192, 21, 47;
32
+ --color-red-400-rgb: 255, 84, 89;
33
+ --color-orange-500-rgb: 168, 75, 47;
34
+ --color-orange-400-rgb: 230, 129, 97;
35
+
36
+ /* Background color tokens (Light Mode) */
37
+ --color-bg-1: rgba(59, 130, 246, 0.08); /* Light blue */
38
+ --color-bg-2: rgba(245, 158, 11, 0.08); /* Light yellow */
39
+ --color-bg-3: rgba(34, 197, 94, 0.08); /* Light green */
40
+ --color-bg-4: rgba(239, 68, 68, 0.08); /* Light red */
41
+ --color-bg-5: rgba(147, 51, 234, 0.08); /* Light purple */
42
+ --color-bg-6: rgba(249, 115, 22, 0.08); /* Light orange */
43
+ --color-bg-7: rgba(236, 72, 153, 0.08); /* Light pink */
44
+ --color-bg-8: rgba(6, 182, 212, 0.08); /* Light cyan */
45
+
46
+ /* Semantic Color Tokens (Light Mode) */
47
+ --color-background: var(--color-cream-50);
48
+ --color-surface: var(--color-cream-100);
49
+ --color-text: var(--color-slate-900);
50
+ --color-text-secondary: var(--color-slate-500);
51
+ --color-primary: var(--color-teal-500);
52
+ --color-primary-hover: var(--color-teal-600);
53
+ --color-primary-active: var(--color-teal-700);
54
+ --color-secondary: rgba(var(--color-brown-600-rgb), 0.12);
55
+ --color-secondary-hover: rgba(var(--color-brown-600-rgb), 0.2);
56
+ --color-secondary-active: rgba(var(--color-brown-600-rgb), 0.25);
57
+ --color-border: rgba(var(--color-brown-600-rgb), 0.2);
58
+ --color-btn-primary-text: var(--color-cream-50);
59
+ --color-card-border: rgba(var(--color-brown-600-rgb), 0.12);
60
+ --color-card-border-inner: rgba(var(--color-brown-600-rgb), 0.12);
61
+ --color-error: var(--color-red-500);
62
+ --color-success: var(--color-teal-500);
63
+ --color-warning: var(--color-orange-500);
64
+ --color-info: var(--color-slate-500);
65
+ --color-focus-ring: rgba(var(--color-teal-500-rgb), 0.4);
66
+ --color-select-caret: rgba(var(--color-slate-900-rgb), 0.8);
67
+
68
+ /* Common style patterns */
69
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
70
+ --focus-outline: 2px solid var(--color-primary);
71
+ --status-bg-opacity: 0.15;
72
+ --status-border-opacity: 0.25;
73
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
74
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
75
+
76
+ /* RGB versions for opacity control */
77
+ --color-success-rgb: 33, 128, 141;
78
+ --color-error-rgb: 192, 21, 47;
79
+ --color-warning-rgb: 168, 75, 47;
80
+ --color-info-rgb: 98, 108, 113;
81
+
82
+ /* Typography */
83
+ --font-family-base: "FKGroteskNeue", "Geist", "Inter", -apple-system,
84
+ BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
85
+ --font-family-mono: "Berkeley Mono", ui-monospace, SFMono-Regular, Menlo,
86
+ Monaco, Consolas, monospace;
87
+ --font-size-xs: 11px;
88
+ --font-size-sm: 12px;
89
+ --font-size-base: 14px;
90
+ --font-size-md: 14px;
91
+ --font-size-lg: 16px;
92
+ --font-size-xl: 18px;
93
+ --font-size-2xl: 20px;
94
+ --font-size-3xl: 24px;
95
+ --font-size-4xl: 30px;
96
+ --font-weight-normal: 400;
97
+ --font-weight-medium: 500;
98
+ --font-weight-semibold: 550;
99
+ --font-weight-bold: 600;
100
+ --line-height-tight: 1.2;
101
+ --line-height-normal: 1.5;
102
+ --letter-spacing-tight: -0.01em;
103
+
104
+ /* Spacing */
105
+ --space-0: 0;
106
+ --space-1: 1px;
107
+ --space-2: 2px;
108
+ --space-4: 4px;
109
+ --space-6: 6px;
110
+ --space-8: 8px;
111
+ --space-10: 10px;
112
+ --space-12: 12px;
113
+ --space-16: 16px;
114
+ --space-20: 20px;
115
+ --space-24: 24px;
116
+ --space-32: 32px;
117
+
118
+ /* Border Radius */
119
+ --radius-sm: 6px;
120
+ --radius-base: 8px;
121
+ --radius-md: 10px;
122
+ --radius-lg: 12px;
123
+ --radius-full: 9999px;
124
+
125
+ /* Shadows */
126
+ --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.02);
127
+ --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.02);
128
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.04),
129
+ 0 2px 4px -1px rgba(0, 0, 0, 0.02);
130
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.04),
131
+ 0 4px 6px -2px rgba(0, 0, 0, 0.02);
132
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.15),
133
+ inset 0 -1px 0 rgba(0, 0, 0, 0.03);
134
+
135
+ /* Animation */
136
+ --duration-fast: 150ms;
137
+ --duration-normal: 250ms;
138
+ --ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
139
+
140
+ /* Layout */
141
+ --container-sm: 640px;
142
+ --container-md: 768px;
143
+ --container-lg: 1024px;
144
+ --container-xl: 1280px;
145
+ }
146
+
147
+ /* Dark mode colors */
148
+ @media (prefers-color-scheme: dark) {
149
+ :root {
150
+ /* RGB versions for opacity control (Dark Mode) */
151
+ --color-gray-400-rgb: 119, 124, 124;
152
+ --color-teal-300-rgb: 50, 184, 198;
153
+ --color-gray-300-rgb: 167, 169, 169;
154
+ --color-gray-200-rgb: 245, 245, 245;
155
+
156
+ /* Background color tokens (Dark Mode) */
157
+ --color-bg-1: rgba(29, 78, 216, 0.15); /* Dark blue */
158
+ --color-bg-2: rgba(180, 83, 9, 0.15); /* Dark yellow */
159
+ --color-bg-3: rgba(21, 128, 61, 0.15); /* Dark green */
160
+ --color-bg-4: rgba(185, 28, 28, 0.15); /* Dark red */
161
+ --color-bg-5: rgba(107, 33, 168, 0.15); /* Dark purple */
162
+ --color-bg-6: rgba(194, 65, 12, 0.15); /* Dark orange */
163
+ --color-bg-7: rgba(190, 24, 93, 0.15); /* Dark pink */
164
+ --color-bg-8: rgba(8, 145, 178, 0.15); /* Dark cyan */
165
+
166
+ /* Semantic Color Tokens (Dark Mode) */
167
+ --color-background: var(--color-charcoal-700);
168
+ --color-surface: var(--color-charcoal-800);
169
+ --color-text: var(--color-gray-200);
170
+ --color-text-secondary: rgba(var(--color-gray-300-rgb), 0.7);
171
+ --color-primary: var(--color-teal-300);
172
+ --color-primary-hover: var(--color-teal-400);
173
+ --color-primary-active: var(--color-teal-800);
174
+ --color-secondary: rgba(var(--color-gray-400-rgb), 0.15);
175
+ --color-secondary-hover: rgba(var(--color-gray-400-rgb), 0.25);
176
+ --color-secondary-active: rgba(var(--color-gray-400-rgb), 0.3);
177
+ --color-border: rgba(var(--color-gray-400-rgb), 0.3);
178
+ --color-error: var(--color-red-400);
179
+ --color-success: var(--color-teal-300);
180
+ --color-warning: var(--color-orange-400);
181
+ --color-info: var(--color-gray-300);
182
+ --color-focus-ring: rgba(var(--color-teal-300-rgb), 0.4);
183
+ --color-btn-primary-text: var(--color-slate-900);
184
+ --color-card-border: rgba(var(--color-gray-400-rgb), 0.2);
185
+ --color-card-border-inner: rgba(var(--color-gray-400-rgb), 0.15);
186
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1),
187
+ inset 0 -1px 0 rgba(0, 0, 0, 0.15);
188
+ --button-border-secondary: rgba(var(--color-gray-400-rgb), 0.2);
189
+ --color-border-secondary: rgba(var(--color-gray-400-rgb), 0.2);
190
+ --color-select-caret: rgba(var(--color-gray-200-rgb), 0.8);
191
+
192
+ /* Common style patterns - updated for dark mode */
193
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
194
+ --focus-outline: 2px solid var(--color-primary);
195
+ --status-bg-opacity: 0.15;
196
+ --status-border-opacity: 0.25;
197
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
198
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
199
+
200
+ /* RGB versions for dark mode */
201
+ --color-success-rgb: var(--color-teal-300-rgb);
202
+ --color-error-rgb: var(--color-red-400-rgb);
203
+ --color-warning-rgb: var(--color-orange-400-rgb);
204
+ --color-info-rgb: var(--color-gray-300-rgb);
205
+ }
206
+ }
207
+
208
+ /* Data attribute for manual theme switching */
209
+ [data-color-scheme="dark"] {
210
+ /* RGB versions for opacity control (dark mode) */
211
+ --color-gray-400-rgb: 119, 124, 124;
212
+ --color-teal-300-rgb: 50, 184, 198;
213
+ --color-gray-300-rgb: 167, 169, 169;
214
+ --color-gray-200-rgb: 245, 245, 245;
215
+
216
+ /* Colorful background palette - Dark Mode */
217
+ --color-bg-1: rgba(29, 78, 216, 0.15); /* Dark blue */
218
+ --color-bg-2: rgba(180, 83, 9, 0.15); /* Dark yellow */
219
+ --color-bg-3: rgba(21, 128, 61, 0.15); /* Dark green */
220
+ --color-bg-4: rgba(185, 28, 28, 0.15); /* Dark red */
221
+ --color-bg-5: rgba(107, 33, 168, 0.15); /* Dark purple */
222
+ --color-bg-6: rgba(194, 65, 12, 0.15); /* Dark orange */
223
+ --color-bg-7: rgba(190, 24, 93, 0.15); /* Dark pink */
224
+ --color-bg-8: rgba(8, 145, 178, 0.15); /* Dark cyan */
225
+
226
+ /* Semantic Color Tokens (Dark Mode) */
227
+ --color-background: var(--color-charcoal-700);
228
+ --color-surface: var(--color-charcoal-800);
229
+ --color-text: var(--color-gray-200);
230
+ --color-text-secondary: rgba(var(--color-gray-300-rgb), 0.7);
231
+ --color-primary: var(--color-teal-300);
232
+ --color-primary-hover: var(--color-teal-400);
233
+ --color-primary-active: var(--color-teal-800);
234
+ --color-secondary: rgba(var(--color-gray-400-rgb), 0.15);
235
+ --color-secondary-hover: rgba(var(--color-gray-400-rgb), 0.25);
236
+ --color-secondary-active: rgba(var(--color-gray-400-rgb), 0.3);
237
+ --color-border: rgba(var(--color-gray-400-rgb), 0.3);
238
+ --color-error: var(--color-red-400);
239
+ --color-success: var(--color-teal-300);
240
+ --color-warning: var(--color-orange-400);
241
+ --color-info: var(--color-gray-300);
242
+ --color-focus-ring: rgba(var(--color-teal-300-rgb), 0.4);
243
+ --color-btn-primary-text: var(--color-slate-900);
244
+ --color-card-border: rgba(var(--color-gray-400-rgb), 0.15);
245
+ --color-card-border-inner: rgba(var(--color-gray-400-rgb), 0.15);
246
+ --shadow-inset-sm: inset 0 1px 0 rgba(255, 255, 255, 0.1),
247
+ inset 0 -1px 0 rgba(0, 0, 0, 0.15);
248
+ --color-border-secondary: rgba(var(--color-gray-400-rgb), 0.2);
249
+ --color-select-caret: rgba(var(--color-gray-200-rgb), 0.8);
250
+
251
+ /* Common style patterns - updated for dark mode */
252
+ --focus-ring: 0 0 0 3px var(--color-focus-ring);
253
+ --focus-outline: 2px solid var(--color-primary);
254
+ --status-bg-opacity: 0.15;
255
+ --status-border-opacity: 0.25;
256
+ --select-caret-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23134252' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
257
+ --select-caret-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23f5f5f5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
258
+
259
+ /* RGB versions for dark mode */
260
+ --color-success-rgb: var(--color-teal-300-rgb);
261
+ --color-error-rgb: var(--color-red-400-rgb);
262
+ --color-warning-rgb: var(--color-orange-400-rgb);
263
+ --color-info-rgb: var(--color-gray-300-rgb);
264
+ }
265
+
266
+ [data-color-scheme="light"] {
267
+ /* RGB versions for opacity control (light mode) */
268
+ --color-brown-600-rgb: 94, 82, 64;
269
+ --color-teal-500-rgb: 33, 128, 141;
270
+ --color-slate-900-rgb: 19, 52, 59;
271
+
272
+ /* Semantic Color Tokens (Light Mode) */
273
+ --color-background: var(--color-cream-50);
274
+ --color-surface: var(--color-cream-100);
275
+ --color-text: var(--color-slate-900);
276
+ --color-text-secondary: var(--color-slate-500);
277
+ --color-primary: var(--color-teal-500);
278
+ --color-primary-hover: var(--color-teal-600);
279
+ --color-primary-active: var(--color-teal-700);
280
+ --color-secondary: rgba(var(--color-brown-600-rgb), 0.12);
281
+ --color-secondary-hover: rgba(var(--color-brown-600-rgb), 0.2);
282
+ --color-secondary-active: rgba(var(--color-brown-600-rgb), 0.25);
283
+ --color-border: rgba(var(--color-brown-600-rgb), 0.2);
284
+ --color-btn-primary-text: var(--color-cream-50);
285
+ --color-card-border: rgba(var(--color-brown-600-rgb), 0.12);
286
+ --color-card-border-inner: rgba(var(--color-brown-600-rgb), 0.12);
287
+ --color-error: var(--color-red-500);
288
+ --color-success: var(--color-teal-500);
289
+ --color-warning: var(--color-orange-500);
290
+ --color-info: var(--color-slate-500);
291
+ --color-focus-ring: rgba(var(--color-teal-500-rgb), 0.4);
292
+
293
+ /* RGB versions for light mode */
294
+ --color-success-rgb: var(--color-teal-500-rgb);
295
+ --color-error-rgb: var(--color-red-500-rgb);
296
+ --color-warning-rgb: var(--color-orange-500-rgb);
297
+ --color-info-rgb: var(--color-slate-500-rgb);
298
+ }
299
+
300
+ /* Base styles */
301
+ html {
302
+ font-size: var(--font-size-base);
303
+ font-family: var(--font-family-base);
304
+ line-height: var(--line-height-normal);
305
+ color: var(--color-text);
306
+ background-color: var(--color-background);
307
+ -webkit-font-smoothing: antialiased;
308
+ box-sizing: border-box;
309
+ }
310
+
311
+ body {
312
+ margin: 0;
313
+ padding: 0;
314
+ }
315
+
316
+ *,
317
+ *::before,
318
+ *::after {
319
+ box-sizing: inherit;
320
+ }
321
+
322
+ /* Typography */
323
+ h1,
324
+ h2,
325
+ h3,
326
+ h4,
327
+ h5,
328
+ h6 {
329
+ margin: 0;
330
+ font-weight: var(--font-weight-semibold);
331
+ line-height: var(--line-height-tight);
332
+ color: var(--color-text);
333
+ letter-spacing: var(--letter-spacing-tight);
334
+ }
335
+
336
+ h1 {
337
+ font-size: var(--font-size-4xl);
338
+ }
339
+ h2 {
340
+ font-size: var(--font-size-3xl);
341
+ }
342
+ h3 {
343
+ font-size: var(--font-size-2xl);
344
+ }
345
+ h4 {
346
+ font-size: var(--font-size-xl);
347
+ }
348
+ h5 {
349
+ font-size: var(--font-size-lg);
350
+ }
351
+ h6 {
352
+ font-size: var(--font-size-md);
353
+ }
354
+
355
+ p {
356
+ margin: 0 0 var(--space-16) 0;
357
+ }
358
+
359
+ a {
360
+ color: var(--color-primary);
361
+ text-decoration: none;
362
+ transition: color var(--duration-fast) var(--ease-standard);
363
+ }
364
+
365
+ a:hover {
366
+ color: var(--color-primary-hover);
367
+ }
368
+
369
+ code,
370
+ pre {
371
+ font-family: var(--font-family-mono);
372
+ font-size: calc(var(--font-size-base) * 0.95);
373
+ background-color: var(--color-secondary);
374
+ border-radius: var(--radius-sm);
375
+ }
376
+
377
+ code {
378
+ padding: var(--space-1) var(--space-4);
379
+ }
380
+
381
+ pre {
382
+ padding: var(--space-16);
383
+ margin: var(--space-16) 0;
384
+ overflow: auto;
385
+ border: 1px solid var(--color-border);
386
+ }
387
+
388
+ pre code {
389
+ background: none;
390
+ padding: 0;
391
+ }
392
+
393
+ /* Buttons */
394
+ .btn {
395
+ display: inline-flex;
396
+ align-items: center;
397
+ justify-content: center;
398
+ padding: var(--space-8) var(--space-16);
399
+ border-radius: var(--radius-base);
400
+ font-size: var(--font-size-base);
401
+ font-weight: 500;
402
+ line-height: 1.5;
403
+ cursor: pointer;
404
+ transition: all var(--duration-normal) var(--ease-standard);
405
+ border: none;
406
+ text-decoration: none;
407
+ position: relative;
408
+ }
409
+
410
+ .btn:focus-visible {
411
+ outline: none;
412
+ box-shadow: var(--focus-ring);
413
+ }
414
+
415
+ .btn--primary {
416
+ background: var(--color-primary);
417
+ color: var(--color-btn-primary-text);
418
+ }
419
+
420
+ .btn--primary:hover {
421
+ background: var(--color-primary-hover);
422
+ }
423
+
424
+ .btn--primary:active {
425
+ background: var(--color-primary-active);
426
+ }
427
+
428
+ .btn--secondary {
429
+ background: var(--color-secondary);
430
+ color: var(--color-text);
431
+ }
432
+
433
+ .btn--secondary:hover {
434
+ background: var(--color-secondary-hover);
435
+ }
436
+
437
+ .btn--secondary:active {
438
+ background: var(--color-secondary-active);
439
+ }
440
+
441
+ .btn--outline {
442
+ background: transparent;
443
+ border: 1px solid var(--color-border);
444
+ color: var(--color-text);
445
+ }
446
+
447
+ .btn--outline:hover {
448
+ background: var(--color-secondary);
449
+ }
450
+
451
+ .btn--sm {
452
+ padding: var(--space-4) var(--space-12);
453
+ font-size: var(--font-size-sm);
454
+ border-radius: var(--radius-sm);
455
+ }
456
+
457
+ .btn--lg {
458
+ padding: var(--space-10) var(--space-20);
459
+ font-size: var(--font-size-lg);
460
+ border-radius: var(--radius-md);
461
+ }
462
+
463
+ .btn--full-width {
464
+ width: 100%;
465
+ }
466
+
467
+ .btn:disabled {
468
+ opacity: 0.5;
469
+ cursor: not-allowed;
470
+ }
471
+
472
+ /* Form elements */
473
+ .form-control {
474
+ display: block;
475
+ width: 100%;
476
+ padding: var(--space-8) var(--space-12);
477
+ font-size: var(--font-size-md);
478
+ line-height: 1.5;
479
+ color: var(--color-text);
480
+ background-color: var(--color-surface);
481
+ border: 1px solid var(--color-border);
482
+ border-radius: var(--radius-base);
483
+ transition: border-color var(--duration-fast) var(--ease-standard),
484
+ box-shadow var(--duration-fast) var(--ease-standard);
485
+ }
486
+
487
+ textarea.form-control {
488
+ font-family: var(--font-family-base);
489
+ font-size: var(--font-size-base);
490
+ }
491
+
492
+ select.form-control {
493
+ padding: var(--space-8) var(--space-12);
494
+ -webkit-appearance: none;
495
+ -moz-appearance: none;
496
+ appearance: none;
497
+ background-image: var(--select-caret-light);
498
+ background-repeat: no-repeat;
499
+ background-position: right var(--space-12) center;
500
+ background-size: 16px;
501
+ padding-right: var(--space-32);
502
+ }
503
+
504
+ /* Add a dark mode specific caret */
505
+ @media (prefers-color-scheme: dark) {
506
+ select.form-control {
507
+ background-image: var(--select-caret-dark);
508
+ }
509
+ }
510
+
511
+ /* Also handle data-color-scheme */
512
+ [data-color-scheme="dark"] select.form-control {
513
+ background-image: var(--select-caret-dark);
514
+ }
515
+
516
+ [data-color-scheme="light"] select.form-control {
517
+ background-image: var(--select-caret-light);
518
+ }
519
+
520
+ .form-control:focus {
521
+ border-color: var(--color-primary);
522
+ outline: var(--focus-outline);
523
+ }
524
+
525
+ .form-label {
526
+ display: block;
527
+ margin-bottom: var(--space-8);
528
+ font-weight: var(--font-weight-medium);
529
+ font-size: var(--font-size-sm);
530
+ }
531
+
532
+ .form-group {
533
+ margin-bottom: var(--space-16);
534
+ }
535
+
536
+ /* Card component */
537
+ .card {
538
+ background-color: var(--color-surface);
539
+ border-radius: var(--radius-lg);
540
+ border: 1px solid var(--color-card-border);
541
+ box-shadow: var(--shadow-sm);
542
+ overflow: hidden;
543
+ transition: box-shadow var(--duration-normal) var(--ease-standard);
544
+ }
545
+
546
+ .card:hover {
547
+ box-shadow: var(--shadow-md);
548
+ }
549
+
550
+ .card__body {
551
+ padding: var(--space-16);
552
+ }
553
+
554
+ .card__header,
555
+ .card__footer {
556
+ padding: var(--space-16);
557
+ border-bottom: 1px solid var(--color-card-border-inner);
558
+ }
559
+
560
+ /* Status indicators - simplified with CSS variables */
561
+ .status {
562
+ display: inline-flex;
563
+ align-items: center;
564
+ padding: var(--space-6) var(--space-12);
565
+ border-radius: var(--radius-full);
566
+ font-weight: var(--font-weight-medium);
567
+ font-size: var(--font-size-sm);
568
+ }
569
+
570
+ .status--success {
571
+ background-color: rgba(
572
+ var(--color-success-rgb, 33, 128, 141),
573
+ var(--status-bg-opacity)
574
+ );
575
+ color: var(--color-success);
576
+ border: 1px solid
577
+ rgba(var(--color-success-rgb, 33, 128, 141), var(--status-border-opacity));
578
+ }
579
+
580
+ .status--error {
581
+ background-color: rgba(
582
+ var(--color-error-rgb, 192, 21, 47),
583
+ var(--status-bg-opacity)
584
+ );
585
+ color: var(--color-error);
586
+ border: 1px solid
587
+ rgba(var(--color-error-rgb, 192, 21, 47), var(--status-border-opacity));
588
+ }
589
+
590
+ .status--warning {
591
+ background-color: rgba(
592
+ var(--color-warning-rgb, 168, 75, 47),
593
+ var(--status-bg-opacity)
594
+ );
595
+ color: var(--color-warning);
596
+ border: 1px solid
597
+ rgba(var(--color-warning-rgb, 168, 75, 47), var(--status-border-opacity));
598
+ }
599
+
600
+ .status--info {
601
+ background-color: rgba(
602
+ var(--color-info-rgb, 98, 108, 113),
603
+ var(--status-bg-opacity)
604
+ );
605
+ color: var(--color-info);
606
+ border: 1px solid
607
+ rgba(var(--color-info-rgb, 98, 108, 113), var(--status-border-opacity));
608
+ }
609
+
610
+ /* Container layout */
611
+ .container {
612
+ width: 100%;
613
+ margin-right: auto;
614
+ margin-left: auto;
615
+ padding-right: var(--space-16);
616
+ padding-left: var(--space-16);
617
+ }
618
+
619
+ @media (min-width: 640px) {
620
+ .container {
621
+ max-width: var(--container-sm);
622
+ }
623
+ }
624
+ @media (min-width: 768px) {
625
+ .container {
626
+ max-width: var(--container-md);
627
+ }
628
+ }
629
+ @media (min-width: 1024px) {
630
+ .container {
631
+ max-width: var(--container-lg);
632
+ }
633
+ }
634
+ @media (min-width: 1280px) {
635
+ .container {
636
+ max-width: var(--container-xl);
637
+ }
638
+ }
639
+
640
+ /* Utility classes */
641
+ .flex {
642
+ display: flex;
643
+ }
644
+ .flex-col {
645
+ flex-direction: column;
646
+ }
647
+ .items-center {
648
+ align-items: center;
649
+ }
650
+ .justify-center {
651
+ justify-content: center;
652
+ }
653
+ .justify-between {
654
+ justify-content: space-between;
655
+ }
656
+ .gap-4 {
657
+ gap: var(--space-4);
658
+ }
659
+ .gap-8 {
660
+ gap: var(--space-8);
661
+ }
662
+ .gap-16 {
663
+ gap: var(--space-16);
664
+ }
665
+
666
+ .m-0 {
667
+ margin: 0;
668
+ }
669
+ .mt-8 {
670
+ margin-top: var(--space-8);
671
+ }
672
+ .mb-8 {
673
+ margin-bottom: var(--space-8);
674
+ }
675
+ .mx-8 {
676
+ margin-left: var(--space-8);
677
+ margin-right: var(--space-8);
678
+ }
679
+ .my-8 {
680
+ margin-top: var(--space-8);
681
+ margin-bottom: var(--space-8);
682
+ }
683
+
684
+ .p-0 {
685
+ padding: 0;
686
+ }
687
+ .py-8 {
688
+ padding-top: var(--space-8);
689
+ padding-bottom: var(--space-8);
690
+ }
691
+ .px-8 {
692
+ padding-left: var(--space-8);
693
+ padding-right: var(--space-8);
694
+ }
695
+ .py-16 {
696
+ padding-top: var(--space-16);
697
+ padding-bottom: var(--space-16);
698
+ }
699
+ .px-16 {
700
+ padding-left: var(--space-16);
701
+ padding-right: var(--space-16);
702
+ }
703
+
704
+ .block {
705
+ display: block;
706
+ }
707
+ .hidden {
708
+ display: none;
709
+ }
710
+
711
+ /* Accessibility */
712
+ .sr-only {
713
+ position: absolute;
714
+ width: 1px;
715
+ height: 1px;
716
+ padding: 0;
717
+ margin: -1px;
718
+ overflow: hidden;
719
+ clip: rect(0, 0, 0, 0);
720
+ white-space: nowrap;
721
+ border-width: 0;
722
+ }
723
+
724
+ :focus-visible {
725
+ outline: var(--focus-outline);
726
+ outline-offset: 2px;
727
+ }
728
+
729
+ /* Dark mode specifics */
730
+ [data-color-scheme="dark"] .btn--outline {
731
+ border: 1px solid var(--color-border-secondary);
732
+ }
733
+
734
+ @font-face {
735
+ font-family: 'FKGroteskNeue';
736
+ src: url('https://r2cdn.perplexity.ai/fonts/FKGroteskNeue.woff2')
737
+ format('woff2');
738
+ }
739
+
740
+ /* END PERPLEXITY DESIGN SYSTEM */
741
+ /* Reset and Base Styles */
742
+ * {
743
+ margin: 0;
744
+ padding: 0;
745
+ box-sizing: border-box;
746
+ }
747
+
748
+ html {
749
+ scroll-behavior: smooth;
750
+ }
751
+
752
+ body {
753
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
754
+ background-color: #1a1a2e;
755
+ color: #e1e1e1;
756
+ line-height: 1.6;
757
+ overflow-x: hidden;
758
+ }
759
+
760
+ /* Top Navigation */
761
+ .top-nav {
762
+ position: sticky;
763
+ top: 0;
764
+ background: linear-gradient(135deg, #16213e 0%, #0f3460 100%);
765
+ padding: 1rem 0;
766
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
767
+ z-index: 1000;
768
+ border-bottom: 2px solid #4a90e2;
769
+ }
770
+
771
+ .nav-container {
772
+ max-width: 1400px;
773
+ margin: 0 auto;
774
+ padding: 0 2rem;
775
+ display: flex;
776
+ justify-content: space-between;
777
+ align-items: center;
778
+ }
779
+
780
+ .course-title {
781
+ font-size: 1.8rem;
782
+ color: #64ffda;
783
+ font-weight: 700;
784
+ text-shadow: 0 0 20px rgba(100, 255, 218, 0.3);
785
+ }
786
+
787
+ .mobile-menu-btn {
788
+ display: none;
789
+ flex-direction: column;
790
+ background: none;
791
+ border: none;
792
+ cursor: pointer;
793
+ padding: 0.5rem;
794
+ }
795
+
796
+ .mobile-menu-btn span {
797
+ width: 25px;
798
+ height: 3px;
799
+ background: #64ffda;
800
+ margin: 3px 0;
801
+ border-radius: 3px;
802
+ transition: all 0.3s ease;
803
+ }
804
+
805
+ /* Main Container */
806
+ .main-container {
807
+ display: flex;
808
+ max-width: 1400px;
809
+ margin: 0 auto;
810
+ min-height: calc(100vh - 80px);
811
+ }
812
+
813
+ /* Sidebar */
814
+ .sidebar {
815
+ width: 280px;
816
+ background: #16213e;
817
+ padding: 2rem 1rem;
818
+ position: sticky;
819
+ top: 80px;
820
+ height: calc(100vh - 80px);
821
+ overflow-y: auto;
822
+ border-right: 2px solid #0f3460;
823
+ transition: transform 0.3s ease;
824
+ }
825
+
826
+ .sidebar-content h3 {
827
+ color: #64ffda;
828
+ margin-bottom: 1.5rem;
829
+ font-size: 1.3rem;
830
+ text-align: center;
831
+ }
832
+
833
+ .module {
834
+ margin-bottom: 2rem;
835
+ }
836
+
837
+ .module-title {
838
+ color: #4a90e2;
839
+ font-size: 0.9rem;
840
+ text-transform: uppercase;
841
+ letter-spacing: 1px;
842
+ margin-bottom: 0.8rem;
843
+ padding: 0.5rem;
844
+ background: rgba(74, 144, 226, 0.1);
845
+ border-radius: 5px;
846
+ border-left: 3px solid #4a90e2;
847
+ }
848
+
849
+ .topic-list {
850
+ list-style: none;
851
+ }
852
+
853
+ .topic-list li {
854
+ margin-bottom: 0.5rem;
855
+ }
856
+
857
+ .topic-link {
858
+ display: block;
859
+ padding: 0.6rem 0.8rem;
860
+ color: #a0a0a0;
861
+ text-decoration: none;
862
+ border-radius: 5px;
863
+ transition: all 0.3s ease;
864
+ font-size: 0.9rem;
865
+ border-left: 3px solid transparent;
866
+ }
867
+
868
+ .topic-link:hover {
869
+ background: rgba(100, 255, 218, 0.1);
870
+ color: #64ffda;
871
+ border-left-color: #64ffda;
872
+ transform: translateX(5px);
873
+ }
874
+
875
+ .topic-link.active {
876
+ background: rgba(100, 255, 218, 0.15);
877
+ color: #64ffda;
878
+ border-left-color: #64ffda;
879
+ font-weight: 600;
880
+ }
881
+
882
+ /* Scrollbar Styling */
883
+ .sidebar::-webkit-scrollbar {
884
+ width: 8px;
885
+ }
886
+
887
+ .sidebar::-webkit-scrollbar-track {
888
+ background: #0f3460;
889
+ }
890
+
891
+ .sidebar::-webkit-scrollbar-thumb {
892
+ background: #4a90e2;
893
+ border-radius: 4px;
894
+ }
895
+
896
+ .sidebar::-webkit-scrollbar-thumb:hover {
897
+ background: #64ffda;
898
+ }
899
+
900
+ /* Main Content */
901
+ .content {
902
+ flex: 1;
903
+ padding: 3rem;
904
+ background: #1a1a2e;
905
+ }
906
+
907
+ /* Topic Section */
908
+ .topic-section {
909
+ margin-bottom: 4rem;
910
+ opacity: 0;
911
+ transform: translateY(20px);
912
+ animation: fadeInUp 0.6s ease forwards;
913
+ }
914
+
915
+ @keyframes fadeInUp {
916
+ to {
917
+ opacity: 1;
918
+ transform: translateY(0);
919
+ }
920
+ }
921
+
922
+ .topic-header {
923
+ margin-bottom: 2rem;
924
+ padding-bottom: 1.5rem;
925
+ border-bottom: 3px solid #0f3460;
926
+ }
927
+
928
+ .topic-number {
929
+ display: inline-block;
930
+ background: linear-gradient(135deg, #4a90e2, #64ffda);
931
+ color: #1a1a2e;
932
+ padding: 0.3rem 1rem;
933
+ border-radius: 20px;
934
+ font-size: 0.85rem;
935
+ font-weight: 700;
936
+ margin-bottom: 0.8rem;
937
+ }
938
+
939
+ .topic-header h2 {
940
+ font-size: 2.5rem;
941
+ color: #64ffda;
942
+ margin-bottom: 0.5rem;
943
+ text-shadow: 0 0 20px rgba(100, 255, 218, 0.2);
944
+ }
945
+
946
+ .topic-subtitle {
947
+ color: #a0a0a0;
948
+ font-size: 1.1rem;
949
+ font-style: italic;
950
+ }
951
+
952
+ /* Content Cards */
953
+ .content-card {
954
+ background: #16213e;
955
+ padding: 2rem;
956
+ border-radius: 12px;
957
+ margin-bottom: 2rem;
958
+ border: 1px solid #0f3460;
959
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
960
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
961
+ }
962
+
963
+ .content-card:hover {
964
+ transform: translateY(-2px);
965
+ box-shadow: 0 6px 25px rgba(74, 144, 226, 0.2);
966
+ }
967
+
968
+ .content-card h3 {
969
+ color: #4a90e2;
970
+ margin-bottom: 1rem;
971
+ font-size: 1.5rem;
972
+ }
973
+
974
+ .content-card h4 {
975
+ margin-top: 1rem;
976
+ margin-bottom: 0.8rem;
977
+ font-size: 1.2rem;
978
+ }
979
+
980
+ .content-card p {
981
+ margin-bottom: 1rem;
982
+ color: #d0d0d0;
983
+ line-height: 1.8;
984
+ }
985
+
986
+ .content-card ul,
987
+ .content-card ol {
988
+ margin-left: 2rem;
989
+ margin-bottom: 1rem;
990
+ }
991
+
992
+ .content-card li {
993
+ margin-bottom: 0.5rem;
994
+ color: #d0d0d0;
995
+ }
996
+
997
+ /* Callout Boxes */
998
+ .callout-box {
999
+ padding: 1.5rem;
1000
+ border-radius: 10px;
1001
+ margin-bottom: 2rem;
1002
+ border-left: 4px solid;
1003
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
1004
+ }
1005
+
1006
+ .callout-header {
1007
+ font-weight: 700;
1008
+ font-size: 1rem;
1009
+ margin-bottom: 0.8rem;
1010
+ display: flex;
1011
+ align-items: center;
1012
+ gap: 0.5rem;
1013
+ }
1014
+
1015
+ .callout-box.insight {
1016
+ background: rgba(100, 255, 218, 0.1);
1017
+ border-left-color: #64ffda;
1018
+ }
1019
+
1020
+ .callout-box.insight .callout-header {
1021
+ color: #64ffda;
1022
+ }
1023
+
1024
+ .callout-box.warning {
1025
+ background: rgba(255, 107, 107, 0.1);
1026
+ border-left-color: #ff6b6b;
1027
+ }
1028
+
1029
+ .callout-box.warning .callout-header {
1030
+ color: #ff6b6b;
1031
+ }
1032
+
1033
+ .callout-box.tip {
1034
+ background: rgba(81, 207, 102, 0.1);
1035
+ border-left-color: #51cf66;
1036
+ }
1037
+
1038
+ .callout-box.tip .callout-header {
1039
+ color: #51cf66;
1040
+ }
1041
+
1042
+ .callout-box.example {
1043
+ background: rgba(74, 144, 226, 0.1);
1044
+ border-left-color: #4a90e2;
1045
+ }
1046
+
1047
+ .callout-box.example .callout-header {
1048
+ color: #4a90e2;
1049
+ }
1050
+
1051
+ .callout-box p,
1052
+ .callout-box ul,
1053
+ .callout-box ol {
1054
+ color: #d0d0d0;
1055
+ }
1056
+
1057
+ /* Formula Cards */
1058
+ .formula-card {
1059
+ background: linear-gradient(135deg, #0f3460 0%, #16213e 100%);
1060
+ padding: 2rem;
1061
+ border-radius: 12px;
1062
+ margin-bottom: 1.5rem;
1063
+ border: 2px solid #4a90e2;
1064
+ box-shadow: 0 4px 20px rgba(74, 144, 226, 0.2);
1065
+ }
1066
+
1067
+ .formula-header {
1068
+ color: #64ffda;
1069
+ font-size: 1.2rem;
1070
+ font-weight: 700;
1071
+ margin-bottom: 1rem;
1072
+ text-align: center;
1073
+ text-transform: uppercase;
1074
+ letter-spacing: 1px;
1075
+ }
1076
+
1077
+ .formula-main {
1078
+ font-size: 1.8rem;
1079
+ text-align: center;
1080
+ margin: 1.5rem 0;
1081
+ color: #fff;
1082
+ font-family: 'Courier New', monospace;
1083
+ }
1084
+
1085
+ .formula-symbol {
1086
+ color: #64ffda;
1087
+ font-weight: 700;
1088
+ font-size: 2rem;
1089
+ }
1090
+
1091
+ .formula-var {
1092
+ color: #64ffda;
1093
+ font-weight: 600;
1094
+ }
1095
+
1096
+ .formula-fraction {
1097
+ display: inline-flex;
1098
+ flex-direction: column;
1099
+ align-items: center;
1100
+ margin: 0 0.5rem;
1101
+ vertical-align: middle;
1102
+ }
1103
+
1104
+ .formula-numerator,
1105
+ .formula-denominator {
1106
+ padding: 0.2rem 0.5rem;
1107
+ }
1108
+
1109
+ .formula-line {
1110
+ width: 100%;
1111
+ height: 2px;
1112
+ background: #fff;
1113
+ margin: 0.2rem 0;
1114
+ }
1115
+
1116
+ .formula-steps {
1117
+ margin-top: 1rem;
1118
+ padding-top: 1rem;
1119
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
1120
+ }
1121
+
1122
+ .formula-steps p {
1123
+ color: #a0a0a0;
1124
+ margin-bottom: 0.5rem;
1125
+ }
1126
+
1127
+ .formula-steps ol,
1128
+ .formula-steps ul {
1129
+ margin-left: 2rem;
1130
+ color: #d0d0d0;
1131
+ }
1132
+
1133
+ .formula-steps li {
1134
+ margin-bottom: 0.5rem;
1135
+ }
1136
+
1137
+ /* Interactive Container */
1138
+ .interactive-container {
1139
+ background: #16213e;
1140
+ padding: 2rem;
1141
+ border-radius: 12px;
1142
+ margin-bottom: 2rem;
1143
+ border: 2px solid #4a90e2;
1144
+ box-shadow: 0 4px 20px rgba(74, 144, 226, 0.3);
1145
+ }
1146
+
1147
+ .interactive-container h3 {
1148
+ color: #64ffda;
1149
+ margin-bottom: 1.5rem;
1150
+ text-align: center;
1151
+ font-size: 1.5rem;
1152
+ }
1153
+
1154
+ .interactive-container canvas {
1155
+ display: block;
1156
+ max-width: 100%;
1157
+ height: auto;
1158
+ margin: 0 auto 1.5rem;
1159
+ background: #0f3460;
1160
+ border-radius: 8px;
1161
+ border: 1px solid #4a90e2;
1162
+ }
1163
+
1164
+ /* Controls */
1165
+ .controls {
1166
+ display: flex;
1167
+ flex-direction: column;
1168
+ gap: 1rem;
1169
+ align-items: center;
1170
+ }
1171
+
1172
+ .input-group {
1173
+ display: flex;
1174
+ flex-direction: column;
1175
+ gap: 0.8rem;
1176
+ width: 100%;
1177
+ max-width: 600px;
1178
+ }
1179
+
1180
+ .input-group label {
1181
+ color: #64ffda;
1182
+ font-weight: 600;
1183
+ }
1184
+
1185
+ .form-control {
1186
+ padding: 0.8rem;
1187
+ background: #0f3460;
1188
+ border: 2px solid #4a90e2;
1189
+ border-radius: 8px;
1190
+ color: #e1e1e1;
1191
+ font-size: 1rem;
1192
+ transition: all 0.3s ease;
1193
+ }
1194
+
1195
+ .form-control:focus {
1196
+ outline: none;
1197
+ border-color: #64ffda;
1198
+ box-shadow: 0 0 10px rgba(100, 255, 218, 0.3);
1199
+ }
1200
+
1201
+ .slider-group {
1202
+ display: flex;
1203
+ flex-direction: column;
1204
+ gap: 0.5rem;
1205
+ width: 100%;
1206
+ }
1207
+
1208
+ .slider-group label {
1209
+ color: #64ffda;
1210
+ font-weight: 600;
1211
+ }
1212
+
1213
+ .slider {
1214
+ width: 100%;
1215
+ height: 8px;
1216
+ border-radius: 5px;
1217
+ background: #0f3460;
1218
+ outline: none;
1219
+ -webkit-appearance: none;
1220
+ }
1221
+
1222
+ .slider::-webkit-slider-thumb {
1223
+ -webkit-appearance: none;
1224
+ appearance: none;
1225
+ width: 20px;
1226
+ height: 20px;
1227
+ border-radius: 50%;
1228
+ background: #64ffda;
1229
+ cursor: pointer;
1230
+ box-shadow: 0 0 10px rgba(100, 255, 218, 0.5);
1231
+ transition: all 0.3s ease;
1232
+ }
1233
+
1234
+ .slider::-webkit-slider-thumb:hover {
1235
+ background: #4a90e2;
1236
+ transform: scale(1.2);
1237
+ }
1238
+
1239
+ .slider::-moz-range-thumb {
1240
+ width: 20px;
1241
+ height: 20px;
1242
+ border-radius: 50%;
1243
+ background: #64ffda;
1244
+ cursor: pointer;
1245
+ border: none;
1246
+ box-shadow: 0 0 10px rgba(100, 255, 218, 0.5);
1247
+ }
1248
+
1249
+ /* Buttons */
1250
+ .btn {
1251
+ padding: 0.8rem 2rem;
1252
+ border: none;
1253
+ border-radius: 8px;
1254
+ font-size: 1rem;
1255
+ font-weight: 600;
1256
+ cursor: pointer;
1257
+ transition: all 0.3s ease;
1258
+ text-transform: uppercase;
1259
+ letter-spacing: 1px;
1260
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
1261
+ }
1262
+
1263
+ .btn-primary {
1264
+ background: linear-gradient(135deg, #4a90e2, #64ffda);
1265
+ color: #1a1a2e;
1266
+ }
1267
+
1268
+ .btn-primary:hover {
1269
+ transform: translateY(-2px);
1270
+ box-shadow: 0 6px 20px rgba(100, 255, 218, 0.4);
1271
+ }
1272
+
1273
+ .btn-secondary {
1274
+ background: #0f3460;
1275
+ color: #64ffda;
1276
+ border: 2px solid #4a90e2;
1277
+ }
1278
+
1279
+ .btn-secondary:hover {
1280
+ background: #16213e;
1281
+ transform: translateY(-2px);
1282
+ }
1283
+
1284
+ /* Results Display */
1285
+ .results {
1286
+ display: grid;
1287
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
1288
+ gap: 1rem;
1289
+ width: 100%;
1290
+ margin-top: 1rem;
1291
+ }
1292
+
1293
+ .result-item {
1294
+ background: #0f3460;
1295
+ padding: 1rem;
1296
+ border-radius: 8px;
1297
+ text-align: center;
1298
+ border: 2px solid #4a90e2;
1299
+ }
1300
+
1301
+ .result-label {
1302
+ display: block;
1303
+ color: #64ffda;
1304
+ font-weight: 600;
1305
+ margin-bottom: 0.5rem;
1306
+ font-size: 0.9rem;
1307
+ }
1308
+
1309
+ .result-item span:last-child {
1310
+ display: block;
1311
+ color: #fff;
1312
+ font-size: 1.5rem;
1313
+ font-weight: 700;
1314
+ }
1315
+
1316
+ /* Tables */
1317
+ .comparison-table {
1318
+ width: 100%;
1319
+ border-collapse: collapse;
1320
+ margin: 1rem 0;
1321
+ background: #0f3460;
1322
+ border-radius: 8px;
1323
+ overflow: hidden;
1324
+ }
1325
+
1326
+ .comparison-table thead {
1327
+ background: linear-gradient(135deg, #4a90e2, #64ffda);
1328
+ color: #1a1a2e;
1329
+ }
1330
+
1331
+ .comparison-table th,
1332
+ .comparison-table td {
1333
+ padding: 1rem;
1334
+ text-align: left;
1335
+ border-bottom: 1px solid #16213e;
1336
+ }
1337
+
1338
+ .comparison-table th {
1339
+ font-weight: 700;
1340
+ text-transform: uppercase;
1341
+ font-size: 0.9rem;
1342
+ letter-spacing: 1px;
1343
+ }
1344
+
1345
+ .comparison-table tbody tr {
1346
+ transition: background 0.3s ease;
1347
+ }
1348
+
1349
+ .comparison-table tbody tr:hover {
1350
+ background: rgba(74, 144, 226, 0.1);
1351
+ }
1352
+
1353
+ .comparison-table td {
1354
+ color: #d0d0d0;
1355
+ }
1356
+
1357
+ /* Two Column Layout */
1358
+ .two-column {
1359
+ display: grid;
1360
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
1361
+ gap: 2rem;
1362
+ margin: 1.5rem 0;
1363
+ }
1364
+
1365
+ .column {
1366
+ background: #0f3460;
1367
+ padding: 1.5rem;
1368
+ border-radius: 8px;
1369
+ border: 2px solid rgba(74, 144, 226, 0.3);
1370
+ }
1371
+
1372
+ /* Comparison Grid */
1373
+ .comparison-grid {
1374
+ display: grid;
1375
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1376
+ gap: 1.5rem;
1377
+ margin: 1.5rem 0;
1378
+ }
1379
+
1380
+ .comparison-item {
1381
+ background: #0f3460;
1382
+ padding: 1.5rem;
1383
+ border-radius: 8px;
1384
+ border-left: 4px solid #4a90e2;
1385
+ }
1386
+
1387
+ /* Data Tree */
1388
+ .data-tree {
1389
+ display: flex;
1390
+ flex-direction: column;
1391
+ align-items: center;
1392
+ gap: 2rem;
1393
+ padding: 2rem;
1394
+ margin: 1.5rem 0;
1395
+ }
1396
+
1397
+ .tree-level-1,
1398
+ .tree-level-2,
1399
+ .tree-level-3 {
1400
+ display: flex;
1401
+ gap: 2rem;
1402
+ justify-content: center;
1403
+ flex-wrap: wrap;
1404
+ }
1405
+
1406
+ .tree-node {
1407
+ padding: 1rem 2rem;
1408
+ background: #0f3460;
1409
+ border: 2px solid #4a90e2;
1410
+ border-radius: 8px;
1411
+ color: #64ffda;
1412
+ font-weight: 600;
1413
+ position: relative;
1414
+ transition: all 0.3s ease;
1415
+ }
1416
+
1417
+ .tree-node:hover {
1418
+ transform: scale(1.05);
1419
+ box-shadow: 0 4px 15px rgba(74, 144, 226, 0.4);
1420
+ }
1421
+
1422
+ .tree-node.main {
1423
+ font-size: 1.3rem;
1424
+ background: linear-gradient(135deg, #4a90e2, #64ffda);
1425
+ color: #1a1a2e;
1426
+ }
1427
+
1428
+ .tree-node.categorical {
1429
+ border-color: #64ffda;
1430
+ }
1431
+
1432
+ .tree-node.numerical {
1433
+ border-color: #ff6b6b;
1434
+ }
1435
+
1436
+ /* Use Case List */
1437
+ .use-case-list {
1438
+ list-style: none;
1439
+ margin-left: 0;
1440
+ }
1441
+
1442
+ .use-case-list li {
1443
+ padding: 1rem;
1444
+ margin-bottom: 1rem;
1445
+ background: #0f3460;
1446
+ border-radius: 8px;
1447
+ border-left: 4px solid #4a90e2;
1448
+ transition: all 0.3s ease;
1449
+ }
1450
+
1451
+ .use-case-list li:hover {
1452
+ transform: translateX(5px);
1453
+ border-left-color: #64ffda;
1454
+ }
1455
+
1456
+ /* Example Solution */
1457
+ .example-solution {
1458
+ background: #0f3460;
1459
+ padding: 1.5rem;
1460
+ border-radius: 8px;
1461
+ margin-top: 1rem;
1462
+ font-family: 'Courier New', monospace;
1463
+ }
1464
+
1465
+ .example-solution p {
1466
+ margin-bottom: 0.8rem;
1467
+ color: #d0d0d0;
1468
+ }
1469
+
1470
+ .example-solution strong {
1471
+ color: #64ffda;
1472
+ }
1473
+
1474
+ /* Summary Card */
1475
+ .summary-card {
1476
+ background: linear-gradient(135deg, #0f3460 0%, #16213e 100%);
1477
+ padding: 2rem;
1478
+ border-radius: 12px;
1479
+ border: 2px solid #64ffda;
1480
+ box-shadow: 0 4px 20px rgba(100, 255, 218, 0.3);
1481
+ margin-bottom: 2rem;
1482
+ }
1483
+
1484
+ .summary-card h3 {
1485
+ color: #64ffda;
1486
+ margin-bottom: 1rem;
1487
+ font-size: 1.5rem;
1488
+ text-align: center;
1489
+ }
1490
+
1491
+ .summary-card ul {
1492
+ list-style: none;
1493
+ margin-left: 0;
1494
+ }
1495
+
1496
+ .summary-card li {
1497
+ padding: 0.8rem;
1498
+ margin-bottom: 0.8rem;
1499
+ background: rgba(100, 255, 218, 0.05);
1500
+ border-radius: 6px;
1501
+ border-left: 3px solid #64ffda;
1502
+ color: #d0d0d0;
1503
+ }
1504
+
1505
+ .summary-card li::before {
1506
+ content: "βœ“";
1507
+ color: #64ffda;
1508
+ font-weight: 700;
1509
+ margin-right: 0.8rem;
1510
+ }
1511
+
1512
+ /* Data Examples Table */
1513
+ .data-examples-table {
1514
+ width: 100%;
1515
+ border-collapse: collapse;
1516
+ margin-top: 1rem;
1517
+ }
1518
+
1519
+ .data-examples-table th,
1520
+ .data-examples-table td {
1521
+ padding: 1rem;
1522
+ text-align: left;
1523
+ border-bottom: 1px solid rgba(74, 144, 226, 0.2);
1524
+ }
1525
+
1526
+ .data-examples-table th {
1527
+ background: rgba(74, 144, 226, 0.2);
1528
+ color: #64ffda;
1529
+ font-weight: 600;
1530
+ }
1531
+
1532
+ /* Responsive Design */
1533
+ @media (max-width: 1024px) {
1534
+ .main-container {
1535
+ flex-direction: column;
1536
+ }
1537
+
1538
+ .sidebar {
1539
+ width: 100%;
1540
+ height: auto;
1541
+ position: static;
1542
+ transform: translateX(-100%);
1543
+ }
1544
+
1545
+ .sidebar.active {
1546
+ transform: translateX(0);
1547
+ }
1548
+
1549
+ .mobile-menu-btn {
1550
+ display: flex;
1551
+ }
1552
+
1553
+ .content {
1554
+ padding: 2rem 1.5rem;
1555
+ }
1556
+
1557
+ .topic-header h2 {
1558
+ font-size: 2rem;
1559
+ }
1560
+
1561
+ .two-column {
1562
+ grid-template-columns: 1fr;
1563
+ }
1564
+ }
1565
+
1566
+ @media (max-width: 768px) {
1567
+ .course-title {
1568
+ font-size: 1.3rem;
1569
+ }
1570
+
1571
+ .content {
1572
+ padding: 1.5rem 1rem;
1573
+ }
1574
+
1575
+ .topic-header h2 {
1576
+ font-size: 1.6rem;
1577
+ }
1578
+
1579
+ .formula-main {
1580
+ font-size: 1.3rem;
1581
+ }
1582
+
1583
+ .comparison-grid {
1584
+ grid-template-columns: 1fr;
1585
+ }
1586
+
1587
+ .results {
1588
+ grid-template-columns: 1fr;
1589
+ }
1590
+
1591
+ .interactive-container canvas {
1592
+ max-width: 100%;
1593
+ height: auto;
1594
+ }
1595
+ }
1596
+
1597
+ /* Animations */
1598
+ @keyframes pulse {
1599
+ 0%, 100% {
1600
+ opacity: 1;
1601
+ }
1602
+ 50% {
1603
+ opacity: 0.5;
1604
+ }
1605
+ }
1606
+
1607
+ .pulse {
1608
+ animation: pulse 2s ease-in-out infinite;
1609
+ }
1610
+
1611
+ /* Loading State */
1612
+ .loading {
1613
+ display: inline-block;
1614
+ width: 20px;
1615
+ height: 20px;
1616
+ border: 3px solid rgba(100, 255, 218, 0.3);
1617
+ border-radius: 50%;
1618
+ border-top-color: #64ffda;
1619
+ animation: spin 1s ease-in-out infinite;
1620
+ }
1621
+
1622
+ @keyframes spin {
1623
+ to {
1624
+ transform: rotate(360deg);
1625
+ }
1626
+ }
1627
+
1628
+ /* Smooth Transitions */
1629
+ * {
1630
+ transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
1631
+ }
ml_complete-all-topics/app.js CHANGED
@@ -104,6 +104,9 @@ function initSections() {
104
  if (section.id === 'cross-validation') initCrossValidation();
105
  if (section.id === 'preprocessing') initPreprocessing();
106
  if (section.id === 'loss-functions') initLossFunctions();
 
 
 
107
  }
108
  });
109
  });
@@ -2351,6 +2354,334 @@ function drawLossCurves() {
2351
  ctx.restore();
2352
  }
2353
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2354
  // Handle window resize
2355
  let resizeTimer;
2356
  window.addEventListener('resize', () => {
@@ -2377,5 +2708,8 @@ window.addEventListener('resize', () => {
2377
  drawSVMCParameter();
2378
  drawSVMTraining();
2379
  drawSVMKernel();
 
 
 
2380
  }, 250);
2381
  });
 
104
  if (section.id === 'cross-validation') initCrossValidation();
105
  if (section.id === 'preprocessing') initPreprocessing();
106
  if (section.id === 'loss-functions') initLossFunctions();
107
+ if (section.id === 'optimal-k') initOptimalK();
108
+ if (section.id === 'hyperparameter-tuning') initHyperparameterTuning();
109
+ if (section.id === 'naive-bayes') initNaiveBayes();
110
  }
111
  });
112
  });
 
2354
  ctx.restore();
2355
  }
2356
 
2357
+ // Optimal K for KNN
2358
+ function initOptimalK() {
2359
+ const canvas = document.getElementById('optimal-k-canvas');
2360
+ if (!canvas || canvas.dataset.initialized) return;
2361
+ canvas.dataset.initialized = 'true';
2362
+
2363
+ const rangeSlider = document.getElementById('k-range-slider');
2364
+ const foldsSlider = document.getElementById('cv-folds-slider');
2365
+
2366
+ if (rangeSlider) {
2367
+ rangeSlider.addEventListener('input', (e) => {
2368
+ document.getElementById('k-range-val').textContent = e.target.value;
2369
+ drawOptimalK();
2370
+ });
2371
+ }
2372
+
2373
+ if (foldsSlider) {
2374
+ foldsSlider.addEventListener('input', (e) => {
2375
+ document.getElementById('cv-folds-val').textContent = e.target.value;
2376
+ drawOptimalK();
2377
+ });
2378
+ }
2379
+
2380
+ drawOptimalK();
2381
+ }
2382
+
2383
+ function drawOptimalK() {
2384
+ const canvas = document.getElementById('optimal-k-canvas');
2385
+ if (!canvas) return;
2386
+
2387
+ const ctx = canvas.getContext('2d');
2388
+ const width = canvas.width = canvas.offsetWidth;
2389
+ const height = canvas.height = 400;
2390
+
2391
+ ctx.clearRect(0, 0, width, height);
2392
+ ctx.fillStyle = '#1a2332';
2393
+ ctx.fillRect(0, 0, width, height);
2394
+
2395
+ const padding = 60;
2396
+ const chartWidth = width - 2 * padding;
2397
+ const chartHeight = height - 2 * padding;
2398
+
2399
+ // Use provided data
2400
+ const kRange = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
2401
+ const accuracies = [0.85, 0.88, 0.92, 0.94, 0.96, 0.97, 0.98, 0.97, 0.96, 0.95, 0.94, 0.93, 0.92, 0.91, 0.90, 0.89, 0.88, 0.87, 0.86, 0.85];
2402
+ const optimalK = 7;
2403
+
2404
+ const scaleX = (k) => padding + ((k - 1) / 19) * chartWidth;
2405
+ const scaleY = (acc) => height - padding - ((acc - 0.8) / 0.2) * chartHeight;
2406
+
2407
+ // Draw grid
2408
+ ctx.strokeStyle = 'rgba(42, 53, 68, 0.5)';
2409
+ ctx.lineWidth = 1;
2410
+ for (let i = 0; i <= 10; i++) {
2411
+ const x = padding + (chartWidth / 10) * i;
2412
+ ctx.beginPath();
2413
+ ctx.moveTo(x, padding);
2414
+ ctx.lineTo(x, height - padding);
2415
+ ctx.stroke();
2416
+
2417
+ const y = padding + (chartHeight / 10) * i;
2418
+ ctx.beginPath();
2419
+ ctx.moveTo(padding, y);
2420
+ ctx.lineTo(width - padding, y);
2421
+ ctx.stroke();
2422
+ }
2423
+
2424
+ // Draw axes
2425
+ ctx.strokeStyle = '#2a3544';
2426
+ ctx.lineWidth = 2;
2427
+ ctx.beginPath();
2428
+ ctx.moveTo(padding, padding);
2429
+ ctx.lineTo(padding, height - padding);
2430
+ ctx.lineTo(width - padding, height - padding);
2431
+ ctx.stroke();
2432
+
2433
+ // Draw line
2434
+ ctx.strokeStyle = '#6aa9ff';
2435
+ ctx.lineWidth = 3;
2436
+ ctx.beginPath();
2437
+ kRange.forEach((k, i) => {
2438
+ const x = scaleX(k);
2439
+ const y = scaleY(accuracies[i]);
2440
+ if (i === 0) ctx.moveTo(x, y);
2441
+ else ctx.lineTo(x, y);
2442
+ });
2443
+ ctx.stroke();
2444
+
2445
+ // Draw points
2446
+ kRange.forEach((k, i) => {
2447
+ const x = scaleX(k);
2448
+ const y = scaleY(accuracies[i]);
2449
+ const isOptimal = k === optimalK;
2450
+
2451
+ ctx.fillStyle = isOptimal ? '#7ef0d4' : '#6aa9ff';
2452
+ ctx.beginPath();
2453
+ ctx.arc(x, y, isOptimal ? 8 : 5, 0, 2 * Math.PI);
2454
+ ctx.fill();
2455
+
2456
+ if (isOptimal) {
2457
+ ctx.strokeStyle = '#7ef0d4';
2458
+ ctx.lineWidth = 2;
2459
+ ctx.beginPath();
2460
+ ctx.arc(x, y, 14, 0, 2 * Math.PI);
2461
+ ctx.stroke();
2462
+
2463
+ // Label
2464
+ ctx.fillStyle = '#7ef0d4';
2465
+ ctx.font = 'bold 14px sans-serif';
2466
+ ctx.textAlign = 'center';
2467
+ ctx.fillText(`Optimal K=${optimalK}`, x, y - 25);
2468
+ ctx.fillText(`Accuracy: ${(accuracies[i] * 100).toFixed(1)}%`, x, y - 10);
2469
+ }
2470
+ });
2471
+
2472
+ // Draw vertical line at optimal K
2473
+ ctx.strokeStyle = 'rgba(126, 240, 212, 0.3)';
2474
+ ctx.lineWidth = 2;
2475
+ ctx.setLineDash([5, 5]);
2476
+ ctx.beginPath();
2477
+ ctx.moveTo(scaleX(optimalK), padding);
2478
+ ctx.lineTo(scaleX(optimalK), height - padding);
2479
+ ctx.stroke();
2480
+ ctx.setLineDash([]);
2481
+
2482
+ // Labels
2483
+ ctx.fillStyle = '#a9b4c2';
2484
+ ctx.font = '12px sans-serif';
2485
+ ctx.textAlign = 'center';
2486
+ ctx.fillText('K Value', width / 2, height - 20);
2487
+ ctx.save();
2488
+ ctx.translate(20, height / 2);
2489
+ ctx.rotate(-Math.PI / 2);
2490
+ ctx.fillText('Mean Accuracy', 0, 0);
2491
+ ctx.restore();
2492
+
2493
+ // X-axis labels
2494
+ for (let i = 1; i <= 20; i += 2) {
2495
+ ctx.fillText(i, scaleX(i), height - padding + 20);
2496
+ }
2497
+ }
2498
+
2499
+ // Hyperparameter Tuning & GridSearch
2500
+ function initHyperparameterTuning() {
2501
+ const canvas = document.getElementById('gridsearch-canvas');
2502
+ if (!canvas || canvas.dataset.initialized) return;
2503
+ canvas.dataset.initialized = 'true';
2504
+ drawGridSearch();
2505
+ }
2506
+
2507
+ function drawGridSearch() {
2508
+ const canvas = document.getElementById('gridsearch-canvas');
2509
+ if (!canvas) return;
2510
+
2511
+ const ctx = canvas.getContext('2d');
2512
+ const width = canvas.width = canvas.offsetWidth;
2513
+ const height = canvas.height = 400;
2514
+
2515
+ ctx.clearRect(0, 0, width, height);
2516
+ ctx.fillStyle = '#1a2332';
2517
+ ctx.fillRect(0, 0, width, height);
2518
+
2519
+ const padding = 80;
2520
+ const chartWidth = width - 2 * padding;
2521
+ const chartHeight = height - 2 * padding;
2522
+
2523
+ // Grid data - C vs gamma heatmap
2524
+ const cValues = [0.1, 1, 10, 100];
2525
+ const gammaValues = [0.001, 0.01, 0.1, 1];
2526
+
2527
+ // Scores (simulated)
2528
+ const scores = [
2529
+ [0.70, 0.75, 0.78, 0.76],
2530
+ [0.82, 0.88, 0.92, 0.85],
2531
+ [0.88, 0.95, 0.93, 0.87],
2532
+ [0.85, 0.90, 0.88, 0.82]
2533
+ ];
2534
+
2535
+ const cellWidth = chartWidth / cValues.length;
2536
+ const cellHeight = chartHeight / gammaValues.length;
2537
+
2538
+ // Draw cells
2539
+ cValues.forEach((c, i) => {
2540
+ gammaValues.forEach((g, j) => {
2541
+ const x = padding + i * cellWidth;
2542
+ const y = padding + j * cellHeight;
2543
+ const score = scores[i][j];
2544
+
2545
+ // Color based on score
2546
+ const intensity = (score - 0.7) / 0.25;
2547
+ const r = Math.floor(255 - intensity * 155);
2548
+ const gb = Math.floor(100 + intensity * 140);
2549
+ ctx.fillStyle = `rgb(${r}, ${gb}, ${Math.floor(gb * 0.9)})`;
2550
+ ctx.fillRect(x, y, cellWidth, cellHeight);
2551
+
2552
+ // Border
2553
+ ctx.strokeStyle = '#1a2332';
2554
+ ctx.lineWidth = 2;
2555
+ ctx.strokeRect(x, y, cellWidth, cellHeight);
2556
+
2557
+ // Score text
2558
+ ctx.fillStyle = score > 0.88 ? '#1a2332' : '#e8eef6';
2559
+ ctx.font = 'bold 14px sans-serif';
2560
+ ctx.textAlign = 'center';
2561
+ ctx.fillText((score * 100).toFixed(0) + '%', x + cellWidth / 2, y + cellHeight / 2 + 5);
2562
+
2563
+ // Highlight best
2564
+ if (score === 0.95) {
2565
+ ctx.strokeStyle = '#7ef0d4';
2566
+ ctx.lineWidth = 4;
2567
+ ctx.strokeRect(x, y, cellWidth, cellHeight);
2568
+
2569
+ ctx.fillStyle = '#7ef0d4';
2570
+ ctx.font = '12px sans-serif';
2571
+ ctx.fillText('β˜… Best', x + cellWidth / 2, y + cellHeight / 2 + 22);
2572
+ }
2573
+ });
2574
+ });
2575
+
2576
+ // Axis labels - C
2577
+ ctx.fillStyle = '#a9b4c2';
2578
+ ctx.font = '12px sans-serif';
2579
+ ctx.textAlign = 'center';
2580
+ cValues.forEach((c, i) => {
2581
+ const x = padding + i * cellWidth + cellWidth / 2;
2582
+ ctx.fillText(`C=${c}`, x, height - padding + 25);
2583
+ });
2584
+
2585
+ // Axis labels - gamma
2586
+ ctx.textAlign = 'right';
2587
+ gammaValues.forEach((g, i) => {
2588
+ const y = padding + i * cellHeight + cellHeight / 2;
2589
+ ctx.fillText(`Ξ³=${g}`, padding - 10, y + 5);
2590
+ });
2591
+
2592
+ // Title
2593
+ ctx.fillStyle = '#7ef0d4';
2594
+ ctx.font = 'bold 16px sans-serif';
2595
+ ctx.textAlign = 'center';
2596
+ ctx.fillText('GridSearch Heatmap: C vs gamma (RBF kernel)', width / 2, 30);
2597
+
2598
+ // Legend
2599
+ ctx.font = '12px sans-serif';
2600
+ ctx.fillStyle = '#a9b4c2';
2601
+ ctx.textAlign = 'left';
2602
+ ctx.fillText('Lower accuracy', padding, height - 10);
2603
+ ctx.textAlign = 'right';
2604
+ ctx.fillText('Higher accuracy', width - padding, height - 10);
2605
+ }
2606
+
2607
+ // Naive Bayes
2608
+ function initNaiveBayes() {
2609
+ const canvas = document.getElementById('naive-bayes-canvas');
2610
+ if (!canvas || canvas.dataset.initialized) return;
2611
+ canvas.dataset.initialized = 'true';
2612
+ drawNaiveBayes();
2613
+ }
2614
+
2615
+ function drawNaiveBayes() {
2616
+ const canvas = document.getElementById('naive-bayes-canvas');
2617
+ if (!canvas) return;
2618
+
2619
+ const ctx = canvas.getContext('2d');
2620
+ const width = canvas.width = canvas.offsetWidth;
2621
+ const height = canvas.height = 350;
2622
+
2623
+ ctx.clearRect(0, 0, width, height);
2624
+ ctx.fillStyle = '#1a2332';
2625
+ ctx.fillRect(0, 0, width, height);
2626
+
2627
+ // Display calculation flow
2628
+ const steps = [
2629
+ { label: 'Words', value: '["free", "money"]', color: '#6aa9ff' },
2630
+ { label: 'P(free|spam)', value: '0.8', color: '#7ef0d4' },
2631
+ { label: 'P(money|spam)', value: '0.7', color: '#7ef0d4' },
2632
+ { label: 'P(spam)', value: '0.3', color: '#ff8c6a' },
2633
+ { label: 'Likelihood', value: '0.8 Γ— 0.7 = 0.56', color: '#7ef0d4' },
2634
+ { label: 'Posterior', value: '0.56 Γ— 0.3 = 0.168', color: '#7ef0d4' },
2635
+ { label: 'Result', value: 'P(spam) = 0.98 (98%)', color: '#7ef0d4' }
2636
+ ];
2637
+
2638
+ const boxWidth = 180;
2639
+ const boxHeight = 45;
2640
+ const startY = 40;
2641
+ const gap = 8;
2642
+
2643
+ steps.forEach((step, i) => {
2644
+ const x = (width - boxWidth) / 2;
2645
+ const y = startY + i * (boxHeight + gap);
2646
+
2647
+ // Box
2648
+ ctx.fillStyle = '#2a3544';
2649
+ ctx.fillRect(x, y, boxWidth, boxHeight);
2650
+ ctx.strokeStyle = step.color;
2651
+ ctx.lineWidth = 2;
2652
+ ctx.strokeRect(x, y, boxWidth, boxHeight);
2653
+
2654
+ // Text
2655
+ ctx.fillStyle = '#a9b4c2';
2656
+ ctx.font = '11px sans-serif';
2657
+ ctx.textAlign = 'center';
2658
+ ctx.fillText(step.label, x + boxWidth / 2, y + boxHeight / 2 - 6);
2659
+
2660
+ ctx.fillStyle = step.color;
2661
+ ctx.font = 'bold 13px monospace';
2662
+ ctx.fillText(step.value, x + boxWidth / 2, y + boxHeight / 2 + 10);
2663
+
2664
+ // Arrow
2665
+ if (i < steps.length - 1) {
2666
+ ctx.strokeStyle = '#6aa9ff';
2667
+ ctx.fillStyle = '#6aa9ff';
2668
+ ctx.lineWidth = 2;
2669
+ const arrowY = y + boxHeight + gap / 2;
2670
+ ctx.beginPath();
2671
+ ctx.moveTo(x + boxWidth / 2, arrowY - 3);
2672
+ ctx.lineTo(x + boxWidth / 2, arrowY + 3);
2673
+ ctx.stroke();
2674
+
2675
+ // Arrowhead
2676
+ ctx.beginPath();
2677
+ ctx.moveTo(x + boxWidth / 2, arrowY + 3);
2678
+ ctx.lineTo(x + boxWidth / 2 - 4, arrowY - 2);
2679
+ ctx.lineTo(x + boxWidth / 2 + 4, arrowY - 2);
2680
+ ctx.fill();
2681
+ }
2682
+ });
2683
+ }
2684
+
2685
  // Handle window resize
2686
  let resizeTimer;
2687
  window.addEventListener('resize', () => {
 
2708
  drawSVMCParameter();
2709
  drawSVMTraining();
2710
  drawSVMKernel();
2711
+ drawOptimalK();
2712
+ drawGridSearch();
2713
+ drawNaiveBayes();
2714
  }, 250);
2715
  });
ml_complete-all-topics/index.html CHANGED
@@ -496,6 +496,9 @@ canvas {
496
  <a href="#cross-validation" class="toc-link">10. Cross-Validation</a>
497
  <a href="#preprocessing" class="toc-link">11. Data Preprocessing</a>
498
  <a href="#loss-functions" class="toc-link">12. Loss Functions</a>
 
 
 
499
  </nav>
500
  </aside>
501
 
@@ -2378,6 +2381,514 @@ Actual Pos TP FN
2378
  </div>
2379
  </div>
2380
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2381
  </main>
2382
  </div>
2383
 
 
496
  <a href="#cross-validation" class="toc-link">10. Cross-Validation</a>
497
  <a href="#preprocessing" class="toc-link">11. Data Preprocessing</a>
498
  <a href="#loss-functions" class="toc-link">12. Loss Functions</a>
499
+ <a href="#optimal-k" class="toc-link">13. Finding Optimal K for KNN</a>
500
+ <a href="#hyperparameter-tuning" class="toc-link">14. Hyperparameter Tuning &amp; GridSearch</a>
501
+ <a href="#naive-bayes" class="toc-link">15. Naive Bayes Classifier</a>
502
  </nav>
503
  </aside>
504
 
 
2381
  </div>
2382
  </div>
2383
 
2384
+ <!-- Section 13: Finding Optimal K for KNN -->
2385
+ <div class="section" id="optimal-k">
2386
+ <div class="section-header">
2387
+ <h2>13. Finding Optimal K for KNN 🎯</h2>
2388
+ <button class="section-toggle">β–Ό</button>
2389
+ </div>
2390
+ <div class="section-body">
2391
+ <p>In KNN, choosing the right K value is crucial! Too small = overfitting, too large = underfitting. How do we find the optimal K? Use cross-validation!</p>
2392
+
2393
+ <div class="info-card">
2394
+ <div class="info-card-title">The Problem</div>
2395
+ <ul class="info-card-list">
2396
+ <li>K=1: Overfits (memorizes training data, including noise)</li>
2397
+ <li>K=too large: Underfits (boundary too smooth, misses patterns)</li>
2398
+ <li>Need: K that balances bias and variance</li>
2399
+ <li>K controls model complexity</li>
2400
+ </ul>
2401
+ </div>
2402
+
2403
+ <h3>Why K Matters</h3>
2404
+ <ul>
2405
+ <li><strong>K controls model complexity:</strong> Small K = complex boundaries, large K = simple boundaries</li>
2406
+ <li><strong>Affects decision boundary smoothness:</strong> Directly impacts predictions</li>
2407
+ <li><strong>Impacts generalization ability:</strong> Wrong K hurts test performance</li>
2408
+ <li><strong>Must be chosen carefully:</strong> Can't just guess!</li>
2409
+ </ul>
2410
+
2411
+ <h3>The Solution: Cross-Validation</h3>
2412
+ <div class="formula">
2413
+ <strong>K-Selection Algorithm:</strong>
2414
+ For K = 1 to 20:<br>
2415
+ &nbsp;&nbsp;For each fold in K-Fold CV:<br>
2416
+ &nbsp;&nbsp;&nbsp;&nbsp;Train KNN with this K value<br>
2417
+ &nbsp;&nbsp;&nbsp;&nbsp;Test on validation fold<br>
2418
+ &nbsp;&nbsp;&nbsp;&nbsp;Record accuracy<br>
2419
+ &nbsp;&nbsp;Calculate mean accuracy across all folds<br>
2420
+ &nbsp;&nbsp;Store: (K, mean_accuracy)<br>
2421
+ <br>
2422
+ Plot K vs Mean Accuracy<br>
2423
+ Choose K with highest mean accuracy
2424
+ </div>
2425
+
2426
+ <h3>Step-by-Step Process</h3>
2427
+ <ol>
2428
+ <li><strong>Define K Range:</strong> Try K = 1, 2, 3, ..., 20 (or use √n as starting point)</li>
2429
+ <li><strong>Set Up Cross-Validation:</strong> Use k-fold CV (e.g., k=10) to ensure robust evaluation</li>
2430
+ <li><strong>Train and Evaluate:</strong> For each K value, run k-fold CV, get accuracy for each fold, calculate mean Β± std dev</li>
2431
+ <li><strong>Select Optimal K:</strong> Choose K with highest mean accuracy (or use elbow method)</li>
2432
+ </ol>
2433
+
2434
+ <h3>Example Walkthrough</h3>
2435
+ <p><strong>Dataset:</strong> A, B, C, D, E, F (6 samples), k-fold = 3</p>
2436
+
2437
+ <table class="data-table">
2438
+ <thead>
2439
+ <tr><th>K Value</th><th>Fold 1</th><th>Fold 2</th><th>Fold 3</th><th>Mean Accuracy</th></tr>
2440
+ </thead>
2441
+ <tbody>
2442
+ <tr><td>K=1</td><td>100%</td><td>100%</td><td>50%</td><td>83.3%</td></tr>
2443
+ <tr style="background: rgba(126, 240, 212, 0.1);"><td><strong>K=3</strong></td><td>100%</td><td>100%</td><td>100%</td><td><strong>100% ← Best!</strong></td></tr>
2444
+ <tr><td>K=5</td><td>100%</td><td>50%</td><td>100%</td><td>83.3%</td></tr>
2445
+ </tbody>
2446
+ </table>
2447
+
2448
+ <div class="figure">
2449
+ <div class="figure-placeholder" style="height: 400px">
2450
+ <canvas id="optimal-k-canvas"></canvas>
2451
+ </div>
2452
+ <p class="figure-caption"><strong>Figure:</strong> K vs Accuracy plot showing optimal K value</p>
2453
+ </div>
2454
+
2455
+ <div class="controls">
2456
+ <div class="control-group">
2457
+ <label>K Range (max): <span id="k-range-val">20</span></label>
2458
+ <input type="range" id="k-range-slider" min="10" max="30" step="5" value="20">
2459
+ </div>
2460
+ <div class="control-group">
2461
+ <label>CV Folds: <span id="cv-folds-val">10</span></label>
2462
+ <input type="range" id="cv-folds-slider" min="3" max="10" step="1" value="10">
2463
+ </div>
2464
+ </div>
2465
+
2466
+ <h3>Elbow Method</h3>
2467
+ <p>Look for the "elbow point" where accuracy stops improving significantly:</p>
2468
+ <ul>
2469
+ <li><strong>Sharp increase:</strong> Significant improvement with larger K</li>
2470
+ <li><strong>Elbow point:</strong> Diminishing returns begin</li>
2471
+ <li><strong>Plateau:</strong> Little benefit from larger K</li>
2472
+ <li><strong>Choose K at/near elbow:</strong> Best trade-off</li>
2473
+ </ul>
2474
+
2475
+ <div class="callout info">
2476
+ <div class="callout-title">πŸ’‘ Odd K Values</div>
2477
+ <div class="callout-content">
2478
+ Always prefer odd K values (3, 5, 7, 9) for binary classification! This avoids ties when neighbors vote. For K=4, you might get 2 votes for each class.
2479
+ </div>
2480
+ </div>
2481
+
2482
+ <div class="callout warning">
2483
+ <div class="callout-title">⚠️ Don't Use Test Set!</div>
2484
+ <div class="callout-content">
2485
+ Never use the test set for K selection! Always use cross-validation on training data only. The test set should remain untouched until final evaluation.
2486
+ </div>
2487
+ </div>
2488
+
2489
+ <h3>Practical Tips</h3>
2490
+ <ul>
2491
+ <li><strong>Start with K = √n:</strong> n = training samples (good starting point)</li>
2492
+ <li><strong>Use odd K:</strong> Avoids ties in binary classification</li>
2493
+ <li><strong>Consider computational cost:</strong> Large K = more neighbors to check</li>
2494
+ <li><strong>Visualize decision boundaries:</strong> For different K values</li>
2495
+ <li><strong>Use stratified k-fold:</strong> For imbalanced data</li>
2496
+ </ul>
2497
+
2498
+ <h3>Real-World Example</h3>
2499
+ <div class="info-card">
2500
+ <div class="info-card-title">🌸 Iris Flower Classification (150 samples)</div>
2501
+ <p style="margin: 12px 0; line-height: 1.6;">
2502
+ <strong>Process:</strong> Try K = 1 to 20, Use 10-fold CV<br>
2503
+ <strong>Results:</strong><br>
2504
+ β€’ K=1: 95% accuracy (overfits to noise)<br>
2505
+ β€’ K=7: 97% accuracy (optimal! βœ“)<br>
2506
+ β€’ K=15: 94% accuracy (underfits, too smooth)<br>
2507
+ <br>
2508
+ The optimal K=7 provides the best balance between model complexity and generalization!
2509
+ </p>
2510
+ </div>
2511
+
2512
+ <div class="callout success">
2513
+ <div class="callout-title">βœ… Key Takeaway</div>
2514
+ <div class="callout-content">
2515
+ Finding optimal K is not guesswork! Use systematic cross-validation to evaluate multiple K values and choose the one with highest mean accuracy. This ensures your KNN model generalizes well to unseen data.
2516
+ </div>
2517
+ </div>
2518
+ </div>
2519
+ </div>
2520
+
2521
+ <!-- Section 14: Hyperparameter Tuning & GridSearch -->
2522
+ <div class="section" id="hyperparameter-tuning">
2523
+ <div class="section-header">
2524
+ <h2>14. Hyperparameter Tuning &amp; GridSearch βš™οΈ</h2>
2525
+ <button class="section-toggle">β–Ό</button>
2526
+ </div>
2527
+ <div class="section-body">
2528
+ <p>Models have two types of parameters: <strong>learned parameters</strong> (like weights) and <strong>hyperparameters</strong> (like learning rate). We must tune hyperparameters to get the best model!</p>
2529
+
2530
+ <h3>What Are Hyperparameters?</h3>
2531
+ <p><strong>Definition:</strong> Parameters that control the learning process but aren't learned from data.</p>
2532
+
2533
+ <div class="info-card">
2534
+ <div class="info-card-title">Parameters vs Hyperparameters</div>
2535
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: 12px;">
2536
+ <div style="background: rgba(126, 240, 212, 0.1); padding: 12px; border-radius: 6px;">
2537
+ <strong style="color: #7ef0d4;">Parameters (Learned)</strong>
2538
+ <ul style="margin-top: 8px; font-size: 14px;">
2539
+ <li>Linear Regression: w, b</li>
2540
+ <li>Logistic Regression: coefficients</li>
2541
+ <li>SVM: support vector positions</li>
2542
+ <li>Optimized during training</li>
2543
+ </ul>
2544
+ </div>
2545
+ <div style="background: rgba(106, 169, 255, 0.1); padding: 12px; border-radius: 6px;">
2546
+ <strong style="color: #6aa9ff;">Hyperparameters (Set Before)</strong>
2547
+ <ul style="margin-top: 8px; font-size: 14px;">
2548
+ <li>Learning rate (Ξ±)</li>
2549
+ <li>Number of iterations</li>
2550
+ <li>SVM: C, gamma, kernel</li>
2551
+ <li>KNN: K value</li>
2552
+ <li>Must be tuned manually</li>
2553
+ </ul>
2554
+ </div>
2555
+ </div>
2556
+ </div>
2557
+
2558
+ <h3>Examples Across Algorithms</h3>
2559
+
2560
+ <h4>Linear/Logistic Regression:</h4>
2561
+ <ul>
2562
+ <li><strong>Learning rate (Ξ±):</strong> 0.001, 0.01, 0.1</li>
2563
+ <li><strong>Number of iterations:</strong> 100, 1000, 10000</li>
2564
+ <li><strong>Regularization strength (Ξ»):</strong> 0.01, 0.1, 1, 10</li>
2565
+ </ul>
2566
+
2567
+ <h4>SVM:</h4>
2568
+ <ul>
2569
+ <li><strong>C (regularization):</strong> 0.1, 1, 10, 100, 1000</li>
2570
+ <li><strong>gamma (kernel coefficient):</strong> 'scale', 'auto', 0.001, 0.01, 0.1</li>
2571
+ <li><strong>kernel:</strong> 'linear', 'poly', 'rbf', 'sigmoid'</li>
2572
+ <li><strong>degree (for poly):</strong> 2, 3, 4, 5</li>
2573
+ </ul>
2574
+
2575
+ <h4>KNN:</h4>
2576
+ <ul>
2577
+ <li><strong>K (neighbors):</strong> 1, 3, 5, 7, 9, 11</li>
2578
+ <li><strong>Distance metric:</strong> 'euclidean', 'manhattan', 'minkowski'</li>
2579
+ <li><strong>Weights:</strong> 'uniform', 'distance'</li>
2580
+ </ul>
2581
+
2582
+ <div class="callout warning">
2583
+ <div class="callout-title">⚠️ The Problem with Random Values</div>
2584
+ <div class="callout-content">
2585
+ If we just try random hyperparameter values:<br>
2586
+ β€’ Inefficient (might miss optimal combination)<br>
2587
+ β€’ No systematic approach<br>
2588
+ β€’ Hard to reproduce<br>
2589
+ β€’ Wastes time and resources
2590
+ </div>
2591
+ </div>
2592
+
2593
+ <h3>Solution: GridSearch!</h3>
2594
+ <p><strong>What is GridSearch?</strong> Systematically try all combinations of hyperparameters and pick the best.</p>
2595
+
2596
+ <div class="formula">
2597
+ <strong>GridSearch Algorithm:</strong><br>
2598
+ 1. Define parameter grid:<br>
2599
+ &nbsp;&nbsp;{ 'C': [0.1, 1, 10, 100],<br>
2600
+ &nbsp;&nbsp;&nbsp;&nbsp;'gamma': ['scale', 'auto', 0.001, 0.01],<br>
2601
+ &nbsp;&nbsp;&nbsp;&nbsp;'kernel': ['linear', 'rbf', 'poly'] }<br>
2602
+ <br>
2603
+ 2. Generate all combinations:<br>
2604
+ &nbsp;&nbsp;Total: 4 Γ— 4 Γ— 3 = 48 combinations<br>
2605
+ <br>
2606
+ 3. For each combination:<br>
2607
+ &nbsp;&nbsp;- Train model with these hyperparameters<br>
2608
+ &nbsp;&nbsp;- Evaluate using cross-validation<br>
2609
+ &nbsp;&nbsp;- Record mean CV score<br>
2610
+ <br>
2611
+ 4. Select best combination:<br>
2612
+ &nbsp;&nbsp;- Highest CV score = best hyperparameters
2613
+ </div>
2614
+
2615
+ <div class="figure">
2616
+ <div class="figure-placeholder" style="height: 400px">
2617
+ <canvas id="gridsearch-canvas"></canvas>
2618
+ </div>
2619
+ <p class="figure-caption"><strong>Figure:</strong> GridSearch heatmap showing parameter combinations and their scores</p>
2620
+ </div>
2621
+
2622
+ <h3>SVM GridSearch Example</h3>
2623
+
2624
+ <table class="data-table">
2625
+ <thead>
2626
+ <tr><th>#</th><th>C</th><th>gamma</th><th>kernel</th><th>CV Score</th></tr>
2627
+ </thead>
2628
+ <tbody>
2629
+ <tr><td>1</td><td>0.1</td><td>0.001</td><td>linear</td><td>0.85</td></tr>
2630
+ <tr><td>2</td><td>0.1</td><td>0.001</td><td>rbf</td><td>0.88</td></tr>
2631
+ <tr><td>...</td><td>...</td><td>...</td><td>...</td><td>...</td></tr>
2632
+ <tr style="background: rgba(126, 240, 212, 0.1);"><td><strong>32</strong></td><td><strong>10</strong></td><td><strong>0.01</strong></td><td><strong>rbf</strong></td><td><strong>0.95 ← Best!</strong></td></tr>
2633
+ </tbody>
2634
+ </table>
2635
+
2636
+ <p><strong>Result:</strong> Best parameters found automatically: C=10, gamma=0.01, kernel='rbf'</p>
2637
+
2638
+ <h3>Computational Cost</h3>
2639
+ <div class="formula">
2640
+ <strong>Total Time Formula:</strong><br>
2641
+ Total Time = n_combinations Γ— cv_folds Γ— training_time<br>
2642
+ <br>
2643
+ <strong>Example:</strong><br>
2644
+ β€’ 48 combinations<br>
2645
+ β€’ 5-fold CV<br>
2646
+ β€’ 1 second per training<br>
2647
+ <strong>Total:</strong> 48 Γ— 5 Γ— 1 = 240 seconds (4 minutes)
2648
+ </div>
2649
+
2650
+ <div class="callout warning">
2651
+ <div class="callout-title">⚠️ GridSearch Can Be Slow!</div>
2652
+ <div class="callout-content">
2653
+ For large parameter grids, GridSearch can take hours or days! Solutions:<br>
2654
+ β€’ Use fewer parameter values (coarse then fine grid)<br>
2655
+ β€’ Use RandomizedSearchCV (samples random combinations)<br>
2656
+ β€’ Use parallel processing (n_jobs=-1)
2657
+ </div>
2658
+ </div>
2659
+
2660
+ <div class="callout info">
2661
+ <div class="callout-title">πŸ’‘ Always Use Cross-Validation!</div>
2662
+ <div class="callout-content">
2663
+ GridSearch must use cross-validation internally to avoid overfitting to validation set. Never tune hyperparameters on test set!
2664
+ </div>
2665
+ </div>
2666
+
2667
+ <h3>Practical Workflow</h3>
2668
+ <ol>
2669
+ <li><strong>Step 1 - Coarse Grid:</strong> Wide range, few values (e.g., C = [0.1, 1, 10, 100, 1000]) to find approximate best region</li>
2670
+ <li><strong>Step 2 - Fine Grid:</strong> Narrow range, more values (e.g., C = [5, 7, 9, 11, 13]) to refine optimal value</li>
2671
+ <li><strong>Step 3 - Final Model:</strong> Train on full training set using best hyperparameters, then evaluate on test set</li>
2672
+ </ol>
2673
+
2674
+ <div class="callout success">
2675
+ <div class="callout-title">βœ… Key Takeaway</div>
2676
+ <div class="callout-content">
2677
+ GridSearch finds optimal hyperparameters automatically - no manual guessing needed! It's the standard approach for hyperparameter tuning in machine learning. Just be patient with large grids!
2678
+ </div>
2679
+ </div>
2680
+
2681
+ <h3>Advanced: RandomizedSearchCV</h3>
2682
+ <p>For very large hyperparameter spaces, use <strong>RandomizedSearchCV</strong>:</p>
2683
+ <ul>
2684
+ <li>Samples random combinations instead of trying all</li>
2685
+ <li>Much faster than exhaustive GridSearch</li>
2686
+ <li>Good for many hyperparameters or continuous ranges</li>
2687
+ <li>Specify number of iterations (e.g., 100 random combinations)</li>
2688
+ </ul>
2689
+ </div>
2690
+ </div>
2691
+
2692
+ <!-- Section 15: Naive Bayes Classifier -->
2693
+ <div class="section" id="naive-bayes">
2694
+ <div class="section-header">
2695
+ <h2>15. Naive Bayes Classifier πŸ“Š</h2>
2696
+ <button class="section-toggle">β–Ό</button>
2697
+ </div>
2698
+ <div class="section-body">
2699
+ <p>Naive Bayes is a probabilistic classifier based on Bayes' Theorem. It's called "naive" because it assumes features are independent (which often isn't true, but it works surprisingly well anyway!)</p>
2700
+
2701
+ <div class="info-card">
2702
+ <div class="info-card-title">Key Concepts</div>
2703
+ <ul class="info-card-list">
2704
+ <li>Based on Bayes' Theorem and probability</li>
2705
+ <li>Assumes features are independent ("naive" assumption)</li>
2706
+ <li>Fast training and prediction</li>
2707
+ <li>Works well for text classification</li>
2708
+ </ul>
2709
+ </div>
2710
+
2711
+ <h3>Bayes' Theorem</h3>
2712
+ <div class="formula">
2713
+ <strong>Bayes' Theorem:</strong><br>
2714
+ P(A|B) = P(B|A) Γ— P(A) / P(B)<br>
2715
+ <br>
2716
+ <strong>In classification context:</strong><br>
2717
+ P(class|features) = P(features|class) Γ— P(class) / P(features)<br>
2718
+ <br>
2719
+ <small>where:<br>
2720
+ β€’ P(class|features) = Posterior probability (what we want)<br>
2721
+ β€’ P(features|class) = Likelihood<br>
2722
+ β€’ P(class) = Prior probability<br>
2723
+ β€’ P(features) = Evidence (normalizing constant)</small>
2724
+ </div>
2725
+
2726
+ <h3>Simple Example: Email Spam Classification</h3>
2727
+ <p>Email contains words: ["free", "money"]</p>
2728
+ <p><strong>Calculate:</strong> P(spam|free, money)</p>
2729
+
2730
+ <h4>Given:</h4>
2731
+ <ul>
2732
+ <li>P(spam) = 0.3 (30% emails are spam)</li>
2733
+ <li>P(not spam) = 0.7</li>
2734
+ <li>P(free|spam) = 0.8</li>
2735
+ <li>P(money|spam) = 0.7</li>
2736
+ <li>P(free|not spam) = 0.1</li>
2737
+ <li>P(money|not spam) = 0.05</li>
2738
+ </ul>
2739
+
2740
+ <h4>Naive Assumption (features are independent):</h4>
2741
+ <div class="formula">
2742
+ P(free, money|spam) = P(free|spam) Γ— P(money|spam)<br>
2743
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0.8 Γ— 0.7 = 0.56<br>
2744
+ <br>
2745
+ P(free, money|not spam) = 0.1 Γ— 0.05 = 0.005
2746
+ </div>
2747
+
2748
+ <h4>Calculate Posterior:</h4>
2749
+ <div class="formula">
2750
+ P(spam|features) = P(free, money|spam) Γ— P(spam)<br>
2751
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= 0.56 Γ— 0.3 = 0.168<br>
2752
+ <br>
2753
+ P(not spam|features) = 0.005 Γ— 0.7 = 0.0035<br>
2754
+ <br>
2755
+ <strong>Normalize:</strong><br>
2756
+ P(spam|features) = 0.168 / (0.168 + 0.0035) = 0.98<br>
2757
+ <br>
2758
+ <strong style="color: #7ef0d4;">Result: 98% probability it's spam! πŸ“§</strong>
2759
+ </div>
2760
+
2761
+ <div class="figure">
2762
+ <div class="figure-placeholder" style="height: 350px">
2763
+ <canvas id="naive-bayes-canvas"></canvas>
2764
+ </div>
2765
+ <p class="figure-caption"><strong>Figure:</strong> Naive Bayes probability calculations for spam detection</p>
2766
+ </div>
2767
+
2768
+ <h3>Types of Naive Bayes</h3>
2769
+
2770
+ <h4>1. Gaussian Naive Bayes</h4>
2771
+ <ul>
2772
+ <li><strong>For:</strong> Continuous features</li>
2773
+ <li><strong>Assumes:</strong> Normal distribution</li>
2774
+ <li><strong>Formula:</strong> P(x|class) = (1/√(2πσ²)) Γ— e^(-(x-ΞΌ)Β²/(2σ²))</li>
2775
+ <li><strong>Use case:</strong> Real-valued features (height, weight, temperature)</li>
2776
+ </ul>
2777
+
2778
+ <h4>2. Multinomial Naive Bayes</h4>
2779
+ <ul>
2780
+ <li><strong>For:</strong> Count data</li>
2781
+ <li><strong>Features:</strong> Frequencies (e.g., word counts)</li>
2782
+ <li><strong>Use case:</strong> Text classification (word counts in documents)</li>
2783
+ </ul>
2784
+
2785
+ <h4>3. Bernoulli Naive Bayes</h4>
2786
+ <ul>
2787
+ <li><strong>For:</strong> Binary features (0/1, yes/no)</li>
2788
+ <li><strong>Features:</strong> Presence/absence</li>
2789
+ <li><strong>Use case:</strong> Document classification (word present or not)</li>
2790
+ </ul>
2791
+
2792
+ <h3>Training Algorithm</h3>
2793
+ <div class="formula">
2794
+ <strong>Training Process:</strong><br>
2795
+ For each class:<br>
2796
+ &nbsp;&nbsp;Calculate P(class) = count(class) / total_samples<br>
2797
+ &nbsp;&nbsp;<br>
2798
+ &nbsp;&nbsp;For each feature:<br>
2799
+ &nbsp;&nbsp;&nbsp;&nbsp;Calculate P(feature|class)<br>
2800
+ &nbsp;&nbsp;&nbsp;&nbsp;<br>
2801
+ &nbsp;&nbsp;&nbsp;&nbsp;Gaussian: Estimate ΞΌ and Οƒ<br>
2802
+ &nbsp;&nbsp;&nbsp;&nbsp;Multinomial: Count frequencies<br>
2803
+ &nbsp;&nbsp;&nbsp;&nbsp;Bernoulli: Count presence<br>
2804
+ <br>
2805
+ <strong>Prediction Process:</strong><br>
2806
+ For each class:<br>
2807
+ &nbsp;&nbsp;posterior = P(class) Γ— ∏ P(feature_i|class)<br>
2808
+ <br>
2809
+ Choose class with maximum posterior
2810
+ </div>
2811
+
2812
+ <h3>Worked Example: Play Tennis Dataset</h3>
2813
+ <p>Predict: Should we play tennis?</p>
2814
+ <p><strong>Given:</strong> Sunny, Cool, High humidity, Windy</p>
2815
+
2816
+ <table class="data-table">
2817
+ <thead>
2818
+ <tr><th>Outlook</th><th>Temp</th><th>Humidity</th><th>Windy</th><th>Play</th></tr>
2819
+ </thead>
2820
+ <tbody>
2821
+ <tr><td>Sunny</td><td>Hot</td><td>High</td><td>No</td><td>No</td></tr>
2822
+ <tr><td>Sunny</td><td>Hot</td><td>High</td><td>Yes</td><td>No</td></tr>
2823
+ <tr><td>Overcast</td><td>Hot</td><td>High</td><td>No</td><td>Yes</td></tr>
2824
+ <tr><td>Rain</td><td>Mild</td><td>High</td><td>No</td><td>Yes</td></tr>
2825
+ <tr><td>Rain</td><td>Cool</td><td>Normal</td><td>No</td><td>Yes</td></tr>
2826
+ <tr><td>...</td><td>...</td><td>...</td><td>...</td><td>...</td></tr>
2827
+ </tbody>
2828
+ </table>
2829
+
2830
+ <p>Calculate P(Yes|features) and P(No|features), then compare!</p>
2831
+
2832
+ <h3>Advantages</h3>
2833
+ <ul>
2834
+ <li>βœ“ <strong>Fast training and prediction:</strong> Very efficient</li>
2835
+ <li>βœ“ <strong>Works well with high dimensions:</strong> Many features</li>
2836
+ <li>βœ“ <strong>Requires small training data:</strong> Good for limited data</li>
2837
+ <li>βœ“ <strong>Handles missing values well:</strong> Robust</li>
2838
+ <li>βœ“ <strong>Probabilistic predictions:</strong> Returns confidence scores</li>
2839
+ <li>βœ“ <strong>Good baseline classifier:</strong> Easy to implement</li>
2840
+ </ul>
2841
+
2842
+ <h3>Disadvantages</h3>
2843
+ <ul>
2844
+ <li>βœ— <strong>Independence assumption often wrong:</strong> Features are usually correlated</li>
2845
+ <li>βœ— <strong>Zero probability problem:</strong> Needs Laplace smoothing</li>
2846
+ <li>βœ— <strong>Not great for correlated features:</strong> Performance suffers</li>
2847
+ <li>βœ— <strong>Requires distribution assumption:</strong> For continuous features</li>
2848
+ </ul>
2849
+
2850
+ <div class="callout info">
2851
+ <div class="callout-title">πŸ’‘ Despite "Naive" Assumption</div>
2852
+ <div class="callout-content">
2853
+ Despite the naive independence assumption being violated in most real-world datasets, Naive Bayes often works remarkably well in practice! It's especially powerful for text classification tasks.
2854
+ </div>
2855
+ </div>
2856
+
2857
+ <div class="callout warning">
2858
+ <div class="callout-title">⚠️ Zero Probability Problem</div>
2859
+ <div class="callout-content">
2860
+ If a feature value never occurs with a class in training, P = 0! This makes the entire posterior zero.<br>
2861
+ <br>
2862
+ <strong>Solution: Laplace Smoothing</strong><br>
2863
+ P(feature|class) = (count + Ξ±) / (total + Ξ± Γ— n_features)<br>
2864
+ where Ξ± = smoothing parameter (usually 1)
2865
+ </div>
2866
+ </div>
2867
+
2868
+ <h3>Applications</h3>
2869
+ <ul>
2870
+ <li><strong>Spam filtering:</strong> Email classification (spam/not spam)</li>
2871
+ <li><strong>Sentiment analysis:</strong> Positive/negative reviews</li>
2872
+ <li><strong>Document classification:</strong> Topic categorization</li>
2873
+ <li><strong>Medical diagnosis:</strong> Disease prediction from symptoms</li>
2874
+ <li><strong>Real-time prediction:</strong> Fast classification needed</li>
2875
+ <li><strong>Recommendation systems:</strong> User preferences</li>
2876
+ </ul>
2877
+
2878
+ <div class="callout success">
2879
+ <div class="callout-title">βœ… Key Takeaway</div>
2880
+ <div class="callout-content">
2881
+ Naive Bayes is simple, fast, and surprisingly effective! Despite its "naive" independence assumption, it's a powerful baseline classifier that works especially well for text classification. Great for when you need quick results with limited data!
2882
+ </div>
2883
+ </div>
2884
+
2885
+ <h3>πŸŽ‰ Congratulations!</h3>
2886
+ <p style="font-size: 18px; color: #7ef0d4; margin-top: 24px;">
2887
+ You've now completed all 15 machine learning topics! From basic concepts to advanced techniques, you've learned linear regression, gradient descent, classification algorithms, model evaluation, regularization, hyperparameter tuning, and probabilistic methods. You're ready to build real ML projects! πŸš€
2888
+ </p>
2889
+ </div>
2890
+ </div>
2891
+
2892
  </main>
2893
  </div>
2894