Skip to content

Commit 6429d2b

Browse files
Add celebratory completion page with confetti πŸŽ‰
- Add complete.html with animated confetti effects - 'More Confetti!' button for endless celebration - Shows skills learned and stats - Konami code easter egg for mega confetti - Space bar shortcut for quick confetti - Link to completion page from final step
1 parent ddef6d0 commit 6429d2b

2 files changed

Lines changed: 388 additions & 2 deletions

File tree

β€Ždocs/complete.htmlβ€Ž

Lines changed: 383 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>πŸŽ‰ Workshop Complete! | VS GitHub Copilot Lab</title>
7+
<link rel="preconnect" href="https://fonts.googleapis.com">
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9+
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Space+Grotesk:wght@400;500;700&display=swap" rel="stylesheet">
10+
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.2/dist/confetti.browser.min.js"></script>
11+
<style>
12+
:root {
13+
--bg-dark: #0a0a0f;
14+
--bg-card: #12121a;
15+
--vs-purple: #68217a;
16+
--vs-blue: #0078d4;
17+
--neon-purple: #b366ff;
18+
--neon-blue: #00d4ff;
19+
--text-primary: #ffffff;
20+
--text-secondary: #a0a0b0;
21+
--border-color: #2a2a3a;
22+
}
23+
24+
* {
25+
margin: 0;
26+
padding: 0;
27+
box-sizing: border-box;
28+
}
29+
30+
body {
31+
font-family: 'Space Grotesk', sans-serif;
32+
background: var(--bg-dark);
33+
color: var(--text-primary);
34+
min-height: 100vh;
35+
display: flex;
36+
flex-direction: column;
37+
align-items: center;
38+
justify-content: center;
39+
overflow: hidden;
40+
}
41+
42+
/* Animated grid background */
43+
body::before {
44+
content: '';
45+
position: fixed;
46+
top: 0;
47+
left: 0;
48+
width: 100%;
49+
height: 100%;
50+
background:
51+
linear-gradient(90deg, rgba(104,33,122,0.05) 1px, transparent 1px),
52+
linear-gradient(rgba(104,33,122,0.05) 1px, transparent 1px);
53+
background-size: 50px 50px;
54+
pointer-events: none;
55+
z-index: -1;
56+
animation: gridPulse 4s ease-in-out infinite;
57+
}
58+
59+
@keyframes gridPulse {
60+
0%, 100% { opacity: 0.5; }
61+
50% { opacity: 1; }
62+
}
63+
64+
.container {
65+
text-align: center;
66+
padding: 2rem;
67+
max-width: 800px;
68+
z-index: 10;
69+
}
70+
71+
.trophy {
72+
font-size: 8rem;
73+
margin-bottom: 1rem;
74+
animation: bounce 2s ease-in-out infinite;
75+
}
76+
77+
@keyframes bounce {
78+
0%, 100% { transform: translateY(0); }
79+
50% { transform: translateY(-20px); }
80+
}
81+
82+
h1 {
83+
font-size: clamp(2.5rem, 8vw, 4.5rem);
84+
font-weight: 700;
85+
margin-bottom: 1rem;
86+
background: linear-gradient(135deg, var(--vs-purple), var(--neon-blue), var(--neon-purple));
87+
background-size: 200% 200%;
88+
-webkit-background-clip: text;
89+
-webkit-text-fill-color: transparent;
90+
background-clip: text;
91+
animation: gradientShift 3s ease infinite;
92+
}
93+
94+
@keyframes gradientShift {
95+
0%, 100% { background-position: 0% 50%; }
96+
50% { background-position: 100% 50%; }
97+
}
98+
99+
.subtitle {
100+
font-size: 1.5rem;
101+
color: var(--text-secondary);
102+
margin-bottom: 2rem;
103+
}
104+
105+
.stats {
106+
display: flex;
107+
justify-content: center;
108+
gap: 3rem;
109+
margin: 3rem 0;
110+
flex-wrap: wrap;
111+
}
112+
113+
.stat {
114+
text-align: center;
115+
}
116+
117+
.stat-value {
118+
font-size: 3rem;
119+
font-weight: 700;
120+
color: var(--neon-purple);
121+
font-family: 'JetBrains Mono', monospace;
122+
}
123+
124+
.stat-label {
125+
font-size: 1rem;
126+
color: var(--text-secondary);
127+
margin-top: 0.25rem;
128+
}
129+
130+
.skills {
131+
display: flex;
132+
flex-wrap: wrap;
133+
justify-content: center;
134+
gap: 0.75rem;
135+
margin: 2rem 0;
136+
}
137+
138+
.skill-badge {
139+
padding: 0.5rem 1rem;
140+
background: var(--bg-card);
141+
border: 1px solid var(--border-color);
142+
border-radius: 50px;
143+
font-size: 0.9rem;
144+
color: var(--neon-blue);
145+
transition: all 0.3s ease;
146+
}
147+
148+
.skill-badge:hover {
149+
border-color: var(--neon-purple);
150+
transform: scale(1.05);
151+
}
152+
153+
.buttons {
154+
display: flex;
155+
gap: 1rem;
156+
justify-content: center;
157+
flex-wrap: wrap;
158+
margin-top: 2rem;
159+
}
160+
161+
.btn {
162+
display: inline-flex;
163+
align-items: center;
164+
gap: 0.5rem;
165+
padding: 1rem 2rem;
166+
border-radius: 12px;
167+
font-weight: 600;
168+
text-decoration: none;
169+
transition: all 0.3s ease;
170+
font-size: 1.1rem;
171+
cursor: pointer;
172+
border: none;
173+
font-family: inherit;
174+
}
175+
176+
.btn-confetti {
177+
background: linear-gradient(135deg, #ff6b6b, #feca57, #48dbfb, #ff9ff3, #54a0ff);
178+
background-size: 300% 300%;
179+
color: var(--bg-dark);
180+
animation: rainbow 3s ease infinite;
181+
font-size: 1.25rem;
182+
padding: 1.25rem 2.5rem;
183+
}
184+
185+
@keyframes rainbow {
186+
0%, 100% { background-position: 0% 50%; }
187+
50% { background-position: 100% 50%; }
188+
}
189+
190+
.btn-confetti:hover {
191+
transform: scale(1.1) rotate(-2deg);
192+
box-shadow: 0 10px 40px rgba(255,107,107,0.4);
193+
}
194+
195+
.btn-confetti:active {
196+
transform: scale(0.95);
197+
}
198+
199+
.btn-secondary {
200+
background: var(--bg-card);
201+
border: 2px solid var(--border-color);
202+
color: var(--text-primary);
203+
}
204+
205+
.btn-secondary:hover {
206+
border-color: var(--neon-purple);
207+
color: var(--neon-purple);
208+
transform: translateY(-2px);
209+
}
210+
211+
.footer-links {
212+
margin-top: 3rem;
213+
display: flex;
214+
gap: 2rem;
215+
justify-content: center;
216+
flex-wrap: wrap;
217+
}
218+
219+
.footer-links a {
220+
color: var(--text-secondary);
221+
text-decoration: none;
222+
transition: color 0.3s ease;
223+
}
224+
225+
.footer-links a:hover {
226+
color: var(--neon-purple);
227+
}
228+
229+
.confetti-counter {
230+
font-family: 'JetBrains Mono', monospace;
231+
font-size: 0.875rem;
232+
color: var(--text-secondary);
233+
margin-top: 1rem;
234+
}
235+
236+
.confetti-counter span {
237+
color: var(--neon-purple);
238+
}
239+
</style>
240+
</head>
241+
<body>
242+
<div class="container">
243+
<div class="trophy">πŸ†</div>
244+
<h1>Workshop Complete!</h1>
245+
<p class="subtitle">You've mastered GitHub Copilot in Visual Studio 2026!</p>
246+
247+
<div class="stats">
248+
<div class="stat">
249+
<div class="stat-value">13</div>
250+
<div class="stat-label">Parts Completed</div>
251+
</div>
252+
<div class="stat">
253+
<div class="stat-value">∞</div>
254+
<div class="stat-label">Productivity Unlocked</div>
255+
</div>
256+
<div class="stat">
257+
<div class="stat-value">πŸš€</div>
258+
<div class="stat-label">Ready to Ship</div>
259+
</div>
260+
</div>
261+
262+
<div class="skills">
263+
<span class="skill-badge">✨ Code Completion</span>
264+
<span class="skill-badge">πŸ€– Agent Mode</span>
265+
<span class="skill-badge">πŸ’¬ Copilot Chat</span>
266+
<span class="skill-badge">πŸ‘οΈ Vision</span>
267+
<span class="skill-badge">πŸ”Œ MCP Servers</span>
268+
<span class="skill-badge">πŸ“‹ Planning Mode</span>
269+
<span class="skill-badge">πŸ“ Prompt Files</span>
270+
<span class="skill-badge">☁️ Cloud Delegation</span>
271+
<span class="skill-badge">πŸ› Debugging</span>
272+
</div>
273+
274+
<div class="buttons">
275+
<button class="btn btn-confetti" id="confettiBtn">
276+
🎊 More Confetti!
277+
</button>
278+
</div>
279+
280+
<p class="confetti-counter">Confetti bursts: <span id="counter">0</span></p>
281+
282+
<div class="buttons">
283+
<a href="index.html" class="btn btn-secondary">🏠 Back to Home</a>
284+
<a href="step.html?step=setup" class="btn btn-secondary">πŸ”„ Start Over</a>
285+
<a href="https://github.com/dotnet-presentations/visual-studio-github-copilot-lab" class="btn btn-secondary">⭐ Star on GitHub</a>
286+
</div>
287+
288+
<div class="footer-links">
289+
<a href="https://learn.microsoft.com/visualstudio/ide/visual-studio-github-copilot-extension">πŸ“š VS Copilot Docs</a>
290+
<a href="https://github.com/features/copilot">πŸ€– GitHub Copilot</a>
291+
<a href="https://dotnet.microsoft.com/">.NET</a>
292+
</div>
293+
</div>
294+
295+
<script>
296+
let confettiCount = 0;
297+
const counter = document.getElementById('counter');
298+
const btn = document.getElementById('confettiBtn');
299+
300+
// Epic confetti function
301+
function fireConfetti() {
302+
const duration = 3000;
303+
const animationEnd = Date.now() + duration;
304+
const colors = ['#68217a', '#0078d4', '#b366ff', '#00d4ff', '#ff6b6b', '#feca57', '#48dbfb'];
305+
306+
const randomInRange = (min, max) => Math.random() * (max - min) + min;
307+
308+
(function frame() {
309+
confetti({
310+
particleCount: 7,
311+
angle: 60,
312+
spread: 55,
313+
origin: { x: 0, y: 0.7 },
314+
colors: colors
315+
});
316+
confetti({
317+
particleCount: 7,
318+
angle: 120,
319+
spread: 55,
320+
origin: { x: 1, y: 0.7 },
321+
colors: colors
322+
});
323+
324+
if (Date.now() < animationEnd) {
325+
requestAnimationFrame(frame);
326+
}
327+
}());
328+
329+
// Center burst
330+
confetti({
331+
particleCount: 100,
332+
spread: 100,
333+
origin: { y: 0.6 },
334+
colors: colors
335+
});
336+
337+
confettiCount++;
338+
counter.textContent = confettiCount;
339+
}
340+
341+
// Initial confetti on page load
342+
window.addEventListener('load', () => {
343+
setTimeout(fireConfetti, 300);
344+
});
345+
346+
// Button click
347+
btn.addEventListener('click', fireConfetti);
348+
349+
// Keyboard shortcut
350+
document.addEventListener('keydown', (e) => {
351+
if (e.code === 'Space') {
352+
e.preventDefault();
353+
fireConfetti();
354+
}
355+
});
356+
357+
// Easter egg: Konami code for mega confetti
358+
let konamiCode = [];
359+
const konamiSequence = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'KeyB', 'KeyA'];
360+
361+
document.addEventListener('keydown', (e) => {
362+
konamiCode.push(e.code);
363+
konamiCode = konamiCode.slice(-10);
364+
365+
if (konamiCode.join(',') === konamiSequence.join(',')) {
366+
// MEGA CONFETTI
367+
for (let i = 0; i < 10; i++) {
368+
setTimeout(() => {
369+
confetti({
370+
particleCount: 200,
371+
spread: 180,
372+
origin: { x: Math.random(), y: Math.random() * 0.5 },
373+
colors: ['#68217a', '#0078d4', '#b366ff', '#00d4ff', '#ff6b6b', '#feca57']
374+
});
375+
}, i * 150);
376+
}
377+
confettiCount += 10;
378+
counter.textContent = confettiCount;
379+
}
380+
});
381+
</script>
382+
</body>
383+
</html>

β€Ždocs/step.htmlβ€Ž

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,8 +600,11 @@
600600
nextLink.textContent = `${steps[idx + 1].title} β†’`;
601601
nextLink.classList.remove('disabled');
602602
} else {
603-
nextLink.classList.add('disabled');
604-
nextLink.textContent = 'Next β†’';
603+
// Last step - link to completion page
604+
nextLink.href = 'complete.html';
605+
nextLink.textContent = 'πŸŽ‰ Complete Workshop!';
606+
nextLink.classList.remove('disabled');
607+
nextLink.style.background = 'linear-gradient(135deg, var(--vs-purple), var(--vs-blue))';
605608
}
606609
}
607610

0 commit comments

Comments
Β (0)