From 77301e7b2717b0f52d114b9119d11733685a2ef7 Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Mon, 13 Apr 2026 19:32:37 -0500 Subject: [PATCH] broken but ok --- src/docs.css | 156 ++++++++++++++++++++++++++++++++++++++---- src/main.ts | 186 +++++++++++++++++++++++++++++++++++++++++++++++++- src/style.css | 179 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 486 insertions(+), 35 deletions(-) diff --git a/src/docs.css b/src/docs.css index 57ffe74..ef27ea3 100644 --- a/src/docs.css +++ b/src/docs.css @@ -26,6 +26,19 @@ body { .container { max-width: 700px; margin: 0 auto; + opacity: 0; + animation: docsContainerFadeIn 1s cubic-bezier(0.22, 1, 0.36, 1) 0.5s forwards; +} + +@keyframes docsContainerFadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } } .header { @@ -36,9 +49,32 @@ body { color: var(--subtext0); text-decoration: none; font-size: 0.9rem; - margin-bottom: 2rem; - display: inline-block; - transition: color 0.3s ease; + margin-bottom: 2.5rem; + display: inline-flex; + align-items: center; + gap: 0.5rem; + transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); +} + +.back-link::before { + content: '$'; + color: var(--green); + font-weight: 600; +} + +.back-link:hover { + color: var(--green); + gap: 0.75rem; + transform: translateX(-5px); +} + +.back-link:hover::before { + animation: dollarPulse 0.6s ease; +} + +@keyframes dollarPulse { + 0%, 100% { text-shadow: 0 0 5px rgba(166, 227, 161, 0.4); } + 50% { text-shadow: 0 0 15px rgba(166, 227, 161, 0.7); } } .back-link:hover { @@ -62,13 +98,33 @@ h1 { } .command-box { - background-color: rgba(26, 26, 26, 0.8); + background: rgba(26, 26, 26, 0.95); border: 1px solid var(--green); - padding: 1.5rem; + border-radius: 8px; + padding: 1.75rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), + 0 0 40px rgba(166, 227, 161, 0.1); + animation: docsCommandSlideIn 0.7s ease 0.6s forwards; + transform: scale(0.98) translateY(10px); + opacity: 0; +} + +@keyframes docsCommandSlideIn { + to { + opacity: 1; + transform: scale(1) translateY(0); + } +} + +.command-box:hover { + border-color: var(--blue); + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6), + 0 0 50px rgba(166, 227, 161, 0.15), + 0 0 80px rgba(137, 180, 250, 0.1); } .command-box code { @@ -115,6 +171,22 @@ h1 { } .section { + opacity: 0; + transform: translateY(20px); + animation: sectionReveal 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards; +} + +.section:nth-child(1) { animation-delay: 0.8s; } +.section:nth-child(2) { animation-delay: 1.1s; } +.section:nth-child(3) { animation-delay: 1.4s; } +.section:nth-child(4) { animation-delay: 1.7s; } +.section:nth-child(5) { animation-delay: 2s; } + +@keyframes sectionReveal { + to { + opacity: 1; + transform: translateY(0); + } } h2 { @@ -143,11 +215,25 @@ strong { } .breakdown-item { - padding: 1rem; + background: rgba(26, 26, 26, 0.6); + border: 1px solid rgba(166, 227, 161, 0.15); + border-radius: 8px; + padding: 1.5rem; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); +} + +.breakdown-item:hover { + background: rgba(26, 26, 26, 0.8); + border-color: rgba(166, 227, 161, 0.35); + transform: translateY(-3px); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4); } .breakdown-item h3 { - color: var(--blue); + background: linear-gradient(135deg, var(--green), var(--blue)); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; font-size: 1.1rem; margin-bottom: 0.75rem; font-weight: 600; @@ -198,23 +284,67 @@ kbd { } .resource-card { - display: block; - padding: 0.85rem 1rem; - background-color: rgba(26, 26, 26, 0.5); + display: flex; + align-items: center; + justify-content: space-between; + padding: 1.25rem 1.5rem; + background: linear-gradient(135deg, + rgba(26, 26, 26, 0.7) 0%, + rgba(30, 30, 30, 0.7) 100%); border: 1px solid rgba(166, 227, 161, 0.2); + border-radius: 10px; text-decoration: none; color: var(--text); margin: 0.5rem 0; - transition: border-color 0.2s ease, background-color 0.2s ease; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + position: relative; + overflow: hidden; +} + +.resource-card::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, + transparent, + rgba(166, 227, 161, 0.15), + transparent); + transition: left 0.6s ease; } .resource-card:hover { border-color: var(--green); - background-color: rgba(26, 26, 26, 0.7); + transform: translateY(-4px); + box-shadow: 0 15px 40px rgba(0, 0, 0, 0.5), + 0 0 30px rgba(166, 227, 161, 0.2); +} + +.resource-card:hover::before { + left: 100%; } .resource-card span { - font-size: 0.9rem; + font-size: 1rem; + font-weight: 500; + position: relative; + z-index: 1; +} + +.resource-card svg { + color: var(--green); + position: relative; + z-index: 1; + opacity: 0; + transform: translateX(-10px); + transition: all 0.4s ease; +} + +.resource-card:hover svg { + opacity: 1; + transform: translateX(0); } @media (max-width: 768px) { diff --git a/src/main.ts b/src/main.ts index d248ad0..d0fa7a9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,187 @@ import './style.css'; +// Interactive Matrix Background +const canvas = document.getElementById('matrix') as HTMLCanvasElement; +const ctx = canvas.getContext('2d')!; + +let width = canvas.width = window.innerWidth; +let height = canvas.height = window.innerHeight; + +const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*'; +const fontSize = 13; +const columns = Math.floor(width / fontSize); +const drops: number[] = Array(columns).fill(1); + +// Mouse interaction +let mouseX = width / 2; +let mouseY = height / 2; +let isMouseDown = false; + +// Click explosion particles +interface Particle { + x: number; + y: number; + vx: number; + vy: number; + life: number; + color: string; + size: number; +} + +const particles: Particle[] = []; + +// Trail effect - characters follow cursor +const trail: { x: number; y: number; color: string; life: number }[] = []; + +function createExplosion(x: number, y: number) { + const colors = ['#a6e3a1', '#89b4fa', '#cba6f7', '#cdd6f4', '#a6adc8']; + for (let i = 0; i < 40; i++) { + const angle = (Math.PI * 2 * i) / 40; + const speed = Math.random() * 3 + 2; + particles.push({ + x, + y, + vx: Math.cos(angle) * speed, + vy: Math.sin(angle) * speed, + life: 1, + color: colors[Math.floor(Math.random() * colors.length)], + size: Math.random() * 2 + 1 + }); + } +} + +function draw() { + // Fade background for trail effect + ctx.fillStyle = 'rgba(0, 0, 0, 0.08)'; + ctx.fillRect(0, 0, width, height); + + // Draw trail around cursor + if (trail.length > 0) { + ctx.font = `${fontSize}px monospace`; + for (let i = trail.length - 1; i >= 0; i--) { + const t = trail[i]; + const alpha = t.life; + const color = t.color + Math.floor(alpha * 255).toString(16).padStart(2, '0'); + + ctx.fillStyle = color; + ctx.globalAlpha = alpha * 0.4; + ctx.fillText(chars[Math.floor(Math.random() * chars.length)], t.x, t.y); + + t.life -= 0.03; + if (t.life <= 0) { + trail.splice(i, 1); + } + } + } + + // Draw matrix rain + ctx.font = `${fontSize}px monospace`; + + for (let i = 0; i < drops.length; i++) { + const x = i * fontSize; + const y = drops[i] * fontSize; + const dist = Math.sqrt((x - mouseX) ** 2 + (y - mouseY) ** 2); + + // Brighter near cursor, dimmer elsewhere + const distFactor = Math.max(0, 1 - dist / 300); + const baseAlpha = 0.35 + distFactor * 0.3; + const alpha = Math.max(0.1, baseAlpha); + + const text = chars[Math.floor(Math.random() * chars.length)]; + const color = Math.floor(alpha * 255).toString(16).padStart(2, '0'); + + // Gradient colors based on distance + const hue = dist < 100 ? 145 : dist < 200 ? 220 : 215; + ctx.fillStyle = `rgb(${hue}, ${hue + 30}, ${hue + 50}${color})`; + ctx.globalAlpha = alpha; + ctx.fillText(text, x, y); + } + + // Update and draw explosion particles + for (let i = particles.length - 1; i >= 0; i--) { + const p = particles[i]; + p.x += p.vx; + p.y += p.vy; + p.life -= 0.015; + p.size *= 0.97; + + if (p.life <= 0 || p.size <= 0.5) { + particles.splice(i, 1); + } else { + ctx.globalAlpha = p.life; + ctx.fillStyle = p.color; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); + ctx.fill(); + } + } + + ctx.globalAlpha = 1; +} + +function update() { + // Add trail around cursor + if (Math.random() > 0.3) { + trail.push({ + x: mouseX + (Math.random() - 0.5) * 20, + y: mouseY + (Math.random() - 0.5) * 20, + color: '#a6e3a1', + life: 1 + }); + } + + // Limit trail length + if (trail.length > 150) { + trail.shift(); + } + + // Update drops + for (let i = 0; i < drops.length; i++) { + if (drops[i] * fontSize > height + fontSize && Math.random() > 0.97) drops[i] = 0; + drops[i]++; + } +} + +function loop() { + update(); + draw(); + requestAnimationFrame(loop); +} + +// Mouse movement +window.addEventListener('mousemove', (e) => { + mouseX = e.clientX; + mouseY = e.clientY; +}); + +// Click explosion +window.addEventListener('click', (e) => { + createExplosion(e.clientX, e.clientY); +}); + +// Touch support +window.addEventListener('touchmove', (e) => { + if ('ontouchstart' in window) { + mouseX = e.touches[0].clientX; + mouseY = e.touches[0].clientY; + } +}, { passive: true }); + +window.addEventListener('touchstart', (e) => { + if ('ontouchstart' in window) { + createExplosion(e.touches[0].clientX, e.touches[0].clientY); + } +}, { passive: true }); + +// Resize +window.addEventListener('resize', () => { + width = canvas.width = window.innerWidth; + height = canvas.height = window.innerHeight; +}); + +// Start loop +loop(); + // Copy functionality const commandBox = document.getElementById('commandBox') as HTMLDivElement; const copyBtn = document.getElementById('copyBtn') as HTMLButtonElement; @@ -29,7 +211,7 @@ commandBox.addEventListener('click', (e) => { if (!(e.target as HTMLElement).closest('.copy-btn')) copyToClipboard(); }); -// Fade in docs link after 2 seconds +// Fade in docs link after 3 seconds setTimeout(() => { document.getElementById('docsLink')?.classList.add('show'); -}, 2000); \ No newline at end of file +}, 3000); diff --git a/src/style.css b/src/style.css index c001c30..32e0336 100644 --- a/src/style.css +++ b/src/style.css @@ -33,6 +33,16 @@ body { position: relative; } +#matrix { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 0; + pointer-events: none; +} + .container { width: 100%; max-width: 600px; @@ -43,6 +53,19 @@ body { align-items: center; gap: 3rem; padding: 2rem; + opacity: 0; + animation: containerFloatUp 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards; +} + +@keyframes containerFloatUp { + from { + opacity: 0; + transform: translateY(40px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } } .terminal-header { @@ -73,30 +96,68 @@ body { .command-container { position: relative; width: 100%; + padding: 0 2rem; } .command-box { - background-color: rgba(0, 0, 0, 0.85); + background: rgba(0, 0, 0, 0.95); border: 1px solid #a6e3a1; - padding: 1.5rem 2.5rem; - font-size: 1.4rem; + box-shadow: 0 0 40px rgba(166, 227, 161, 0.08), + 0 0 60px rgba(166, 227, 161, 0.03); + border-radius: 8px; + padding: 2rem 2.5rem; + font-size: 1.5rem; + font-weight: 500; color: var(--text); display: flex; align-items: center; gap: 0.75rem; cursor: pointer; user-select: none; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + animation: boxPulse 4s ease-in-out infinite; +} + +@keyframes boxPulse { + 0%, 100% { + box-shadow: 0 0 40px rgba(166, 227, 161, 0.08), + 0 0 60px rgba(166, 227, 161, 0.03); + } + 50% { + box-shadow: 0 0 50px rgba(166, 227, 161, 0.12), + 0 0 80px rgba(166, 227, 161, 0.05); + } } .command-box:hover { - border-color: #a6e3a1; + transform: scale(1.02); + border-color: #89b4fa; + box-shadow: 0 0 50px rgba(166, 227, 161, 0.15), + 0 0 100px rgba(137, 180, 250, 0.1), + 0 0 150px rgba(137, 180, 250, 0.05); +} + +.command-box:active { + transform: scale(0.98); } .dollar { color: var(--green); font-weight: 600; - font-size: 1.3rem; - text-shadow: 0 0 10px rgba(166, 227, 161, 0.5); + font-size: 1.4rem; + animation: dollarPulse 3s ease-in-out infinite; +} + +@keyframes dollarPulse { + 0%, 100% { + text-shadow: 0 0 8px rgba(166, 227, 161, 0.4), + 0 0 15px rgba(166, 227, 161, 0.2); + } + 50% { + text-shadow: 0 0 15px rgba(166, 227, 161, 0.7), + 0 0 25px rgba(166, 227, 161, 0.4), + 0 0 35px rgba(137, 180, 250, 0.15); + } } .command { @@ -106,50 +167,83 @@ body { .copy-btn { position: absolute; - right: 1rem; + right: 1.25rem; top: 50%; transform: translateY(-50%); - background: none; - border: none; + background: rgba(166, 227, 161, 0.05); + border: 1px solid rgba(166, 227, 161, 0.2); color: var(--subtext0); + width: 38px; + height: 38px; + border-radius: 8px; cursor: pointer; - padding: 0.25rem 0.5rem; display: flex; align-items: center; justify-content: center; - transition: color 0.2s ease; + transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + z-index: 10; } .copy-btn:hover { + background: rgba(166, 227, 161, 0.15); + border-color: var(--green); color: var(--green); + transform: translateY(-50%) scale(1.1); + box-shadow: 0 0 20px rgba(166, 227, 161, 0.2), + 0 0 35px rgba(166, 227, 161, 0.1); +} + +.copy-btn:active { + transform: translateY(-50%) scale(0.95); } .copy-btn.copied { + background: rgba(166, 227, 161, 0.25); + border-color: var(--green); color: var(--green); } +.copy-btn.copied svg { + animation: checkBounce 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); +} + +@keyframes checkBounce { + 0% { transform: scale(0); } + 50% { transform: scale(1.2); } + 100% { transform: scale(1); } +} + .copy-btn svg { width: 20px; height: 20px; + transition: transform 0.3s ease; +} + +.copy-btn:hover svg { + transform: scale(1.1); } .tooltip { position: absolute; top: -2rem; right: 0; - background-color: var(--surface1); + background: linear-gradient(135deg, var(--surface1) 0%, var(--surface0) 100%); color: var(--green); - padding: 0.35rem 0.6rem; - border-radius: 4px; + padding: 0.4rem 0.7rem; + border-radius: 6px; font-size: 0.7rem; + font-weight: 600; opacity: 0; pointer-events: none; - transition: opacity 0.2s ease; + transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); white-space: nowrap; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); + z-index: 20; } .tooltip.show { opacity: 1; + transform: translateY(-10px); } @media (max-width: 640px) { @@ -157,14 +251,24 @@ body { padding: 1.5rem; } + .container { + gap: 2rem; + padding: 1.5rem; + } + .command-box { - font-size: 1.1rem; - padding: 1.25rem 1.75rem; + font-size: 1.15rem; + padding: 1.5rem 1.75rem; } .copy-btn svg { - width: 16px; - height: 16px; + width: 18px; + height: 18px; + } + + .copy-btn { + width: 32px; + height: 32px; } } @@ -173,15 +277,50 @@ body { text-decoration: none; font-size: 0.85rem; opacity: 0; - transition: opacity 0.4s ease; + transform: translateY(20px); + transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); position: relative; padding: 0.5rem 1rem; } +.docs-link::before { + content: ''; + position: absolute; + bottom: 2px; + left: 0; + width: 0; + height: 1px; + background: linear-gradient(90deg, transparent, var(--green), transparent); + transition: width 0.4s ease; +} + .docs-link:hover { color: var(--green); } +.docs-link:hover::before { + width: 100%; +} + +.docs-link:hover::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 2px; + background: linear-gradient(90deg, var(--green), var(--blue)); + transform: scaleX(0); + transform-origin: right; + transition: transform 0.4s ease; +} + +.docs-link:hover::after { + transform: scaleX(1); + transform-origin: left; +} + .docs-link.show { opacity: 1; + transform: translateY(0); }