diff --git a/src/docs.css b/src/docs.css index ef27ea3..1bd0764 100644 --- a/src/docs.css +++ b/src/docs.css @@ -24,21 +24,8 @@ body { } .container { - max-width: 700px; + max-width: 650px; 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 { @@ -48,33 +35,14 @@ body { .back-link { color: var(--subtext0); text-decoration: none; - font-size: 0.9rem; - 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; + font-size: 0.85rem; + margin-bottom: 2rem; + display: inline-block; + transition: color 0.2s ease; } .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 { @@ -98,33 +66,18 @@ h1 { } .command-box { - background: rgba(26, 26, 26, 0.95); + background: rgba(26, 26, 26, 0.8); border: 1px solid var(--green); - border-radius: 8px; - padding: 1.75rem; + padding: 1.25rem; 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); - } + transition: border-color 0.2s ease; } .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 { @@ -171,22 +124,6 @@ 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 { @@ -215,27 +152,18 @@ strong { } .breakdown-item { - 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); + padding: 1rem; + border-bottom: 1px solid rgba(166, 227, 161, 0.1); } -.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:last-child { + border-bottom: none; } .breakdown-item h3 { - 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; + color: var(--blue); + font-size: 1rem; + margin-bottom: 0.5rem; font-weight: 600; } @@ -284,67 +212,23 @@ kbd { } .resource-card { - 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; + display: block; + padding: 0.75rem 1rem; + background: rgba(26, 26, 26, 0.5); + border: 1px solid rgba(166, 227, 161, 0.15); text-decoration: none; color: var(--text); margin: 0.5rem 0; - 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; + transition: border-color 0.2s ease, background-color 0.2s ease; } .resource-card:hover { border-color: var(--green); - 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%; + background: rgba(26, 26, 26, 0.7); } .resource-card span { - 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); + font-size: 0.9rem; } @media (max-width: 768px) { @@ -353,15 +237,11 @@ kbd { } h1 { - font-size: 2rem; + font-size: 1.8rem; } h2 { - font-size: 1.3rem; - } - - .command-box code { - font-size: 0.9rem; + font-size: 1.1rem; } .breakdown-grid, diff --git a/src/main.ts b/src/main.ts index d0fa7a9..85f3220 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,119 +1,91 @@ import './style.css'; -// Interactive Matrix Background +// Beautiful Matrix Rain 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; +// Catppuccin Mocha colors +const colors = { + green: '#a6e3a1', + blue: '#89b4fa', + mauve: '#cba6f7', + text: '#cdd6f4' +}; + +const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%'; +const fontSize = 12; 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 +// Trail effect 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 + const color = Math.random() > 0.5 ? colors.green : colors.blue; + for (let i = 0; i < 12; i++) { + const angle = (Math.PI * 2 * i) / 12; + const speed = Math.random() * 2 + 1; + trail.push({ + x: x + (Math.random() - 0.5) * 20, + y: y + (Math.random() - 0.5) * 20, + color: color, + life: 1 }); } } function draw() { - // Fade background for trail effect - ctx.fillStyle = 'rgba(0, 0, 0, 0.08)'; + // Subtle fade for trails + ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; ctx.fillRect(0, 0, width, height); - // Draw trail around cursor + // Draw trail with glow if (trail.length > 0) { ctx.font = `${fontSize}px monospace`; + ctx.globalAlpha = 0.3; 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.fillStyle = t.color; + ctx.shadowBlur = 8; + ctx.shadowColor = t.color; 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); - } + if (t.life <= 0) trail.splice(i, 1); } + ctx.shadowBlur = 0; } - // Draw matrix rain + // Matrix rain with distance-based brightness ctx.font = `${fontSize}px monospace`; - for (let i = 0; i < drops.length; i++) { const x = i * fontSize; const y = drops[i] * fontSize; + + // Calculate distance from cursor 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 brightness = Math.max(0.2, 1 - dist / 250); - const text = chars[Math.floor(Math.random() * chars.length)]; - const color = Math.floor(alpha * 255).toString(16).padStart(2, '0'); + // Pick color based on distance + let color: string; + if (dist < 80) color = colors.green; + else if (dist < 150) color = colors.blue; + else color = colors.mauve; - // 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; + ctx.fillStyle = color; + ctx.fillText(chars[Math.floor(Math.random() * chars.length)], x, y); - 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(); - } + if (drops[i] * fontSize > height + fontSize && Math.random() > 0.95) drops[i] = 0; + drops[i]++; } ctx.globalAlpha = 1; @@ -121,23 +93,20 @@ function draw() { function update() { // Add trail around cursor - if (Math.random() > 0.3) { + if (Math.random() > 0.4) { + const dist = Math.sqrt((mouseX - width/2) ** 2 + (mouseY - height/2) ** 2); trail.push({ x: mouseX + (Math.random() - 0.5) * 20, y: mouseY + (Math.random() - 0.5) * 20, - color: '#a6e3a1', + color: dist < 80 ? colors.green : colors.blue, life: 1 }); } - - // Limit trail length - if (trail.length > 150) { - trail.shift(); - } + if (trail.length > 10) 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; + if (drops[i] * fontSize > height + fontSize && Math.random() > 0.93) drops[i] = 0; drops[i]++; } } @@ -173,13 +142,15 @@ window.addEventListener('touchstart', (e) => { } }, { passive: true }); -// Resize -window.addEventListener('resize', () => { +// Resize handler +function resize() { width = canvas.width = window.innerWidth; height = canvas.height = window.innerHeight; -}); +} + +window.addEventListener('resize', resize); +resize(); -// Start loop loop(); // Copy functionality diff --git a/src/style.css b/src/style.css index 32e0336..3265211 100644 --- a/src/style.css +++ b/src/style.css @@ -45,26 +45,26 @@ body { .container { width: 100%; - max-width: 600px; + max-width: 500px; position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; - gap: 3rem; - padding: 2rem; + gap: 2rem; + padding: 1rem; opacity: 0; - animation: containerFloatUp 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards; + animation: containerFloatUp 0.8s cubic-bezier(0.22, 1, 0.36, 1) forwards; } @keyframes containerFloatUp { from { opacity: 0; - transform: translateY(40px) scale(0.95); + transform: translateY(30px); } to { opacity: 1; - transform: translateY(0) scale(1); + transform: translateY(0); } } @@ -96,17 +96,14 @@ body { .command-container { position: relative; width: 100%; - padding: 0 2rem; } .command-box { - background: rgba(0, 0, 0, 0.95); - border: 1px solid #a6e3a1; - 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; + background: rgba(0, 0, 0, 0.8); + border: 1px solid rgba(166, 227, 161, 0.3); + border-radius: 6px; + padding: 1rem 1.25rem; + font-size: 1.1rem; font-weight: 500; color: var(--text); display: flex; @@ -114,50 +111,22 @@ body { 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); - } + transition: all 0.3s ease; } .command-box:hover { - 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); + border-color: rgba(166, 227, 161, 0.6); + box-shadow: 0 0 20px rgba(166, 227, 161, 0.1); + transform: translateY(-2px); } .command-box:active { - transform: scale(0.98); + transform: translateY(0); } .dollar { color: var(--green); font-weight: 600; - 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 { @@ -167,83 +136,51 @@ body { .copy-btn { position: absolute; - right: 1.25rem; + right: 0.75rem; top: 50%; transform: translateY(-50%); - background: rgba(166, 227, 161, 0.05); - border: 1px solid rgba(166, 227, 161, 0.2); + background: none; + border: none; color: var(--subtext0); - width: 38px; - height: 38px; - border-radius: 8px; cursor: pointer; + padding: 0.25rem; display: flex; align-items: center; justify-content: center; - transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + transition: color 0.2s ease; 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); + width: 18px; + height: 18px; } .tooltip { position: absolute; top: -2rem; right: 0; - background: linear-gradient(135deg, var(--surface1) 0%, var(--surface0) 100%); + background: rgba(26, 26, 26, 0.9); color: var(--green); - padding: 0.4rem 0.7rem; - border-radius: 6px; - font-size: 0.7rem; - font-weight: 600; + padding: 0.3rem 0.6rem; + font-size: 0.65rem; opacity: 0; pointer-events: none; - transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + transition: opacity 0.2s ease; 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) { @@ -252,23 +189,17 @@ body { } .container { - gap: 2rem; - padding: 1.5rem; + gap: 1.5rem; + padding: 1rem; } .command-box { - font-size: 1.15rem; - padding: 1.5rem 1.75rem; + font-size: 0.95rem; + padding: 0.85rem 1rem; } - .copy-btn svg { - width: 18px; - height: 18px; - } - - .copy-btn { - width: 32px; - height: 32px; + .docs-link { + font-size: 0.8rem; } } @@ -277,50 +208,15 @@ body { text-decoration: none; font-size: 0.85rem; opacity: 0; - transform: translateY(20px); - transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1); + transition: opacity 0.4s ease; 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); }