From 56d2d2d8180f63a7a705d3a8cd56c0ab971f2f89 Mon Sep 17 00:00:00 2001 From: Gemini AI Date: Thu, 25 Dec 2025 18:47:10 +0400 Subject: [PATCH] Initial commit: TRAE Aurora Crystalline Christmas Experience --- .vercel/project.json | 1 + .vercelignore | 7 + README.md | 36 +++ app.js | 585 +++++++++++++++++++++++++++++++++++++++++++ index.html | 98 ++++++++ style.css | 332 ++++++++++++++++++++++++ vercel.json | 1 + 7 files changed, 1060 insertions(+) create mode 100644 .vercel/project.json create mode 100644 .vercelignore create mode 100644 README.md create mode 100644 app.js create mode 100644 index.html create mode 100644 style.css create mode 100644 vercel.json diff --git a/.vercel/project.json b/.vercel/project.json new file mode 100644 index 0000000..514fc4a --- /dev/null +++ b/.vercel/project.json @@ -0,0 +1 @@ +{"projectId":"prj_Dhag66N2znJLYYebOLct1HoY6A1C","orgId":"team_kySCrU1jp0BBI2srgQ9vTTMw","projectName":"trae_9nt2qbd3","neverMindDeployCard":true} \ No newline at end of file diff --git a/.vercelignore b/.vercelignore new file mode 100644 index 0000000..a48e5d3 --- /dev/null +++ b/.vercelignore @@ -0,0 +1,7 @@ +node_modules +build +dist +.git +.trae +.log +.figma \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6aa32a7 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# 🎄 TRAE AURORA: Crystalline Christmas Experience + +[![TRAE](https://img.shields.io/badge/Powered%20By-TRAE.AI-00ff66?style=for-the-badge)](https://trae.ai) +[![GLM 4.7](https://img.shields.io/badge/Model-GLM%204.7-blue?style=for-the-badge)](https://z.ai/subscribe?ic=R0K78RJKNW) +[![Gemini 3 Flash](https://img.shields.io/badge/Model-Gemini%203%20Flash-orange?style=for-the-badge)](https://deepmind.google/technologies/gemini/) + +An elite, high-performance HTML5 Christmas experience built with crystalline precision. This project showcases advanced canvas animations, procedural generation, and dynamic game mechanics. + +## 🚀 Key Features + +- **Aurora Borealis Engine**: Procedural sky simulation using multi-layered canvas gradients. +- **Gift Catcher Pro**: + - Dynamic difficulty scaling (Multipliers increase with score). + - Multi-tier gift types (Common, Rare, Legendary). + - **3D Artifacts**: Custom-rendered Roblox-style crowns, trophies, and gems using pure Canvas API. + - Combo system with score multipliers. +- **Magical Message Forge**: Interactive crystalline text generation. +- **Glassmorphism UI**: Modern, responsive design with high-density visual effects. + +## 🛠️ Technical Stack + +- **Frontend**: Pure HTML5, CSS3 (Advanced Grid/Flex), Vanilla JavaScript (ES6+). +- **Graphics**: 2D Canvas API with 3D geometry simulation. +- **Architecture**: Object-Oriented Design (Class-based game entities). +- **AI-Powered**: Co-authored by **GLM 4.7** and **Gemini 3 Flash** within the **TRAE IDE**. + +## 🎨 Visuals + +The project features a deep-space aesthetic with neon green accents (`#00ff66`), reflecting the TRAE brand identity. + +## 🔗 Credits + +Developed by **[Roman | RyzenAdvanced](https://github.com/roman-ryzenadvanced/Custom-Engineered-Agents-and-Tools-for-Vibe-Coders)**. + +--- +*© 2025 Coded with Crystalline Precision.* \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..0dd736a --- /dev/null +++ b/app.js @@ -0,0 +1,585 @@ +/** + * TRAE Aurora - Crystalline Christmas Logic + * Author: Code Prism (Assistant) + */ + +document.addEventListener('DOMContentLoaded', () => { + initBackground(); + initCountdown(); + initMessageForge(); + initGame(); +}); + +// --- Utility: Scroll to Section --- +function scrollToSection(id) { + const el = document.getElementById(id); + if (el) el.scrollIntoView({ behavior: 'smooth' }); +} + +// --- 1. Background Engine (Aurora + Snow) --- +function initBackground() { + const canvas = document.getElementById('bgCanvas'); + const ctx = canvas.getContext('2d'); + let width, height, particles = []; + + const resize = () => { + width = canvas.width = window.innerWidth; + height = canvas.height = window.innerHeight; + }; + + class Particle { + constructor() { + this.reset(); + } + reset() { + this.x = Math.random() * width; + this.y = Math.random() * height; + this.size = Math.random() * 2 + 1; + this.speedY = Math.random() * 1 + 0.5; + this.speedX = Math.random() * 0.5 - 0.25; + this.opacity = Math.random() * 0.5 + 0.2; + } + update() { + this.y += this.speedY; + this.x += this.speedX; + if (this.y > height) { + this.y = -10; + this.x = Math.random() * width; + } + } + draw() { + ctx.fillStyle = `rgba(0, 255, 102, ${this.opacity})`; + ctx.beginPath(); + ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); + ctx.fill(); + } + } + + const initParticles = () => { + particles = []; + for (let i = 0; i < 150; i++) { + particles.push(new Particle()); + } + }; + + const drawAurora = () => { + const time = Date.now() * 0.001; + const gradient = ctx.createLinearGradient(0, 0, width, height); + gradient.addColorStop(0, '#050b14'); + gradient.addColorStop(0.5, '#0a1a2f'); + gradient.addColorStop(1, '#050b14'); + + ctx.fillStyle = gradient; + ctx.fillRect(0, 0, width, height); + + // Aurora waves + ctx.save(); + ctx.globalCompositeOperation = 'screen'; + for (let i = 0; i < 3; i++) { + ctx.beginPath(); + ctx.strokeStyle = i === 0 ? 'rgba(0, 255, 102, 0.1)' : 'rgba(0, 242, 255, 0.05)'; + ctx.lineWidth = 100; + const yOffset = height * 0.3 + (i * 100); + ctx.moveTo(0, yOffset + Math.sin(time + i) * 50); + for (let x = 0; x < width; x += 50) { + ctx.lineTo(x, yOffset + Math.sin(x * 0.002 + time + i) * 80); + } + ctx.stroke(); + } + ctx.restore(); + }; + + const animate = () => { + drawAurora(); + particles.forEach(p => { + p.update(); + p.draw(); + }); + requestAnimationFrame(animate); + }; + + window.addEventListener('resize', resize); + resize(); + initParticles(); + animate(); +} + +// --- 2. Countdown Timer --- +function initCountdown() { + const target = new Date('December 25, 2025 00:00:00').getTime(); + + const update = () => { + const now = new Date().getTime(); + const diff = target - now; + + if (diff <= 0) { + document.getElementById('countdown').innerHTML = "

MERRY CHRISTMAS!

"; + return; + } + + const d = Math.floor(diff / (1000 * 60 * 60 * 24)); + const h = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const m = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const s = Math.floor((diff % (1000 * 60)) / 1000); + + document.getElementById('days').innerText = d.toString().padStart(2, '0'); + document.getElementById('hours').innerText = h.toString().padStart(2, '0'); + document.getElementById('minutes').innerText = m.toString().padStart(2, '0'); + document.getElementById('seconds').innerText = s.toString().padStart(2, '0'); + }; + + setInterval(update, 1000); + update(); +} + +// --- 3. Magical Message Forge --- +function initMessageForge() { + const input = document.getElementById('messageInput'); + const btn = document.getElementById('forgeBtn'); + const output = document.getElementById('outputMessage'); + const canvas = document.getElementById('snowflakeCanvas'); + const ctx = canvas.getContext('2d'); + + canvas.width = 300; + canvas.height = 300; + + const drawCrystal = (text) => { + ctx.clearRect(0, 0, canvas.width, canvas.height); + const centerX = canvas.width / 2; + const centerY = canvas.height / 2; + + // Draw decorative snowflake based on text length + ctx.strokeStyle = '#00ff66'; + ctx.lineWidth = 2; + const branches = 6 + (text.length % 6); + const radius = 80 + (text.length * 2); + + for (let i = 0; i < branches; i++) { + const angle = (i * 2 * Math.PI) / branches; + ctx.beginPath(); + ctx.moveTo(centerX, centerY); + ctx.lineTo(centerX + Math.cos(angle) * radius, centerY + Math.sin(angle) * radius); + ctx.stroke(); + + // Sub-branches + for (let j = 1; j < 4; j++) { + const subAngle = angle + 0.5; + const subX = centerX + Math.cos(angle) * (radius * j / 4); + const subY = centerY + Math.sin(angle) * (radius * j / 4); + ctx.beginPath(); + ctx.moveTo(subX, subY); + ctx.lineTo(subX + Math.cos(subAngle) * 20, subY + Math.sin(subAngle) * 20); + ctx.stroke(); + } + } + + output.innerText = text.toUpperCase(); + output.style.opacity = 0; + setTimeout(() => { output.style.opacity = 1; output.style.transition = 'opacity 1s'; }, 100); + }; + + btn.addEventListener('click', () => { + if (input.value.trim()) { + drawCrystal(input.value); + input.value = ''; + } + }); +} + +// --- 4. Gift Catcher Mini Game --- +function initGame() { + const canvas = document.getElementById('gameCanvas'); + const ctx = canvas.getContext('2d'); + const startBtn = document.getElementById('startGameBtn'); + const scoreEl = document.getElementById('scoreVal'); + + let score = 0; + let gameActive = false; + let playerX = 0; + let gifts = []; + let particles = []; + let difficultyMultiplier = 1; + let combo = 0; + let lastCatchTime = 0; + + const resize = () => { + canvas.width = canvas.parentElement.clientWidth; + canvas.height = canvas.parentElement.clientHeight; + playerX = canvas.width / 2; + }; + + const GIFT_TYPES = { + common: { color: '#00ff66', points: 10, speedMult: 1, size: 25, chance: 0.6 }, + rare: { color: '#00f2ff', points: 25, speedMult: 1.3, size: 20, chance: 0.3 }, + legendary: { color: '#ff00ff', points: 50, speedMult: 1.8, size: 18, chance: 0.1 } + }; + + const ARTIFACT_TYPES = { + crown: { color: '#ffd700', points: 100, speedMult: 1.5, size: 30, chance: 0.05, shape: 'crown' }, + trophy: { color: '#c0c0c0', points: 75, speedMult: 1.3, size: 28, chance: 0.08, shape: 'trophy' }, + gem: { color: '#ff69b4', points: 60, speedMult: 1.6, size: 22, chance: 0.1, shape: 'gem' }, + star: { color: '#ffff00', points: 40, speedMult: 1.4, size: 20, chance: 0.12, shape: 'star' } + }; + + class Particle { + constructor(x, y, color) { + this.x = x; + this.y = y; + this.color = color; + this.size = Math.random() * 5 + 2; + this.speedX = (Math.random() - 0.5) * 8; + this.speedY = (Math.random() - 0.5) * 8 - 3; + this.life = 1; + this.decay = Math.random() * 0.02 + 0.02; + } + update() { + this.x += this.speedX; + this.y += this.speedY; + this.life -= this.decay; + } + draw() { + ctx.save(); + ctx.globalAlpha = this.life; + ctx.fillStyle = this.color; + ctx.shadowBlur = 10; + ctx.shadowColor = this.color; + ctx.beginPath(); + ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); + ctx.fill(); + ctx.restore(); + } + } + + class Gift { + constructor() { + const rand = Math.random(); + let type; + if (rand < 0.6) type = 'common'; + else if (rand < 0.9) type = 'rare'; + else type = 'legendary'; + + const typeData = GIFT_TYPES[type]; + this.x = Math.random() * (canvas.width - 50) + 25; + this.y = -60; + this.size = typeData.size; + this.baseSpeed = (3 + Math.random() * 3) * typeData.speedMult * difficultyMultiplier; + this.speed = this.baseSpeed; + this.color = typeData.color; + this.points = typeData.points; + this.rotation = 0; + this.rotationSpeed = (Math.random() - 0.5) * 0.1; + this.type = type; + } + update() { + this.y += this.speed; + this.rotation += this.rotationSpeed; + } + draw() { + ctx.save(); + ctx.translate(this.x + this.size/2, this.y + this.size/2); + ctx.rotate(this.rotation); + ctx.shadowBlur = 20; + ctx.shadowColor = this.color; + ctx.fillStyle = this.color; + ctx.fillRect(-this.size/2, -this.size/2, this.size, this.size); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + ctx.strokeRect(-this.size/2, -this.size/2, this.size, this.size); + + // Glow effect for legendary + if (this.type === 'legendary') { + ctx.beginPath(); + ctx.arc(0, 0, this.size * 0.8, 0, Math.PI * 2); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 1; + ctx.stroke(); + } + ctx.restore(); + } + } + + class Artifact { + constructor() { + const types = Object.keys(ARTIFACT_TYPES); + const rand = Math.random(); + let selectedType = 'star'; + let cumulative = 0; + for (const type of types) { + cumulative += ARTIFACT_TYPES[type].chance; + if (rand < cumulative) { + selectedType = type; + break; + } + } + + const typeData = ARTIFACT_TYPES[selectedType]; + this.x = Math.random() * (canvas.width - 60) + 30; + this.y = -70; + this.size = typeData.size; + this.baseSpeed = (4 + Math.random() * 4) * typeData.speedMult * difficultyMultiplier; + this.speed = this.baseSpeed; + this.color = typeData.color; + this.points = typeData.points; + this.rotation = 0; + this.rotationSpeed = (Math.random() - 0.5) * 0.08; + this.type = selectedType; + this.shape = typeData.shape; + this.wobble = 0; + this.wobbleSpeed = 0.05; + } + update() { + this.y += this.speed; + this.rotation += this.rotationSpeed; + this.wobble += this.wobbleSpeed; + } + draw() { + ctx.save(); + ctx.translate(this.x + this.size/2, this.y + this.size/2); + ctx.rotate(this.rotation); + ctx.translate(0, Math.sin(this.wobble) * 3); + ctx.shadowBlur = 25; + ctx.shadowColor = this.color; + ctx.fillStyle = this.color; + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + + const s = this.size; + + switch(this.shape) { + case 'crown': + this.drawCrown(s); + break; + case 'trophy': + this.drawTrophy(s); + break; + case 'gem': + this.drawGem(s); + break; + case 'star': + this.drawStar(s); + break; + } + + ctx.restore(); + } + drawCrown(s) { + ctx.beginPath(); + const base = s * 0.3; + const height = s * 0.5; + ctx.moveTo(-s/2, base); + ctx.lineTo(-s/2 + s/6, -height/2); + ctx.lineTo(-s/6, 0); + ctx.lineTo(0, -height); + ctx.lineTo(s/6, 0); + ctx.lineTo(s/2 - s/6, -height/2); + ctx.lineTo(s/2, base); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + ctx.fillStyle = '#fff'; + ctx.beginPath(); + ctx.arc(0, -height/3, s/12, 0, Math.PI * 2); + ctx.fill(); + } + drawTrophy(s) { + const baseW = s * 0.5; + const baseH = s * 0.2; + const cupW = s * 0.4; + const cupH = s * 0.4; + + ctx.fillRect(-baseW/2, s/2 - baseH, baseW, baseH); + ctx.strokeRect(-baseW/2, s/2 - baseH, baseW, baseH); + + ctx.beginPath(); + ctx.moveTo(-cupW/2, s/2 - baseH); + ctx.lineTo(-cupW/2, s/2 - baseH - cupH); + ctx.quadraticCurveTo(0, s/2 - baseH - cupH - cupW/2, cupW/2, s/2 - baseH - cupH); + ctx.lineTo(cupW/2, s/2 - baseH); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + ctx.beginPath(); + ctx.moveTo(-cupW/3, s/2 - baseH - cupH/2); + ctx.lineTo(cupW/3, s/2 - baseH - cupH/2); + ctx.stroke(); + } + drawGem(s) { + const h = s * 0.6; + ctx.beginPath(); + ctx.moveTo(0, -h); + ctx.lineTo(s/2, -h/4); + ctx.lineTo(s/3, h/2); + ctx.lineTo(0, h/3); + ctx.lineTo(-s/3, h/2); + ctx.lineTo(-s/2, -h/4); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + ctx.strokeStyle = 'rgba(255,255,255,0.5)'; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(0, -h); + ctx.lineTo(0, h/3); + ctx.moveTo(-s/2, -h/4); + ctx.lineTo(s/3, h/2); + ctx.moveTo(s/2, -h/4); + ctx.lineTo(-s/3, h/2); + ctx.stroke(); + } + drawStar(s) { + const spikes = 5; + const outerRadius = s/2; + const innerRadius = s/4; + + ctx.beginPath(); + for(let i = 0; i < spikes * 2; i++) { + const radius = i % 2 === 0 ? outerRadius : innerRadius; + const angle = (i * Math.PI / spikes) - Math.PI / 2; + const x = Math.cos(angle) * radius; + const y = Math.sin(angle) * radius; + if(i === 0) ctx.moveTo(x, y); + else ctx.lineTo(x, y); + } + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + } + } + + const createExplosion = (x, y, color) => { + for (let i = 0; i < 15; i++) { + particles.push(new Particle(x, y, color)); + } + }; + + const drawPlayer = () => { + ctx.save(); + const pulse = Math.sin(Date.now() * 0.005) * 0.2 + 0.8; + ctx.globalAlpha = pulse; + ctx.fillStyle = 'rgba(0, 255, 102, 0.3)'; + ctx.strokeStyle = '#00ff66'; + ctx.lineWidth = 3; + ctx.shadowBlur = 20; + ctx.shadowColor = '#00ff66'; + ctx.beginPath(); + ctx.roundRect(playerX - 45, canvas.height - 35, 90, 25, 8); + ctx.fill(); + ctx.stroke(); + ctx.restore(); + }; + + const updateGame = () => { + if (!gameActive) return; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // Draw grid background + ctx.save(); + ctx.strokeStyle = 'rgba(0, 255, 102, 0.05)'; + ctx.lineWidth = 1; + for (let x = 0; x < canvas.width; x += 30) { + ctx.beginPath(); + ctx.moveTo(x, 0); + ctx.lineTo(x, canvas.height); + ctx.stroke(); + } + for (let y = 0; y < canvas.height; y += 30) { + ctx.beginPath(); + ctx.moveTo(0, y); + ctx.lineTo(canvas.width, y); + ctx.stroke(); + } + ctx.restore(); + + drawPlayer(); + + // Update & Draw Particles + particles = particles.filter(p => p.life > 0); + particles.forEach(p => { + p.update(); + p.draw(); + }); + + // Spawn gifts with increasing difficulty + const spawnRate = 0.02 + (difficultyMultiplier - 1) * 0.01; + if (Math.random() < spawnRate) gifts.push(new Gift()); + + // Spawn rare artifacts + const artifactSpawnRate = 0.005 + (difficultyMultiplier - 1) * 0.002; + if (Math.random() < artifactSpawnRate) gifts.push(new Artifact()); + + gifts.forEach((gift, index) => { + gift.update(); + gift.draw(); + + // Collision detection + if (gift.y + gift.size > canvas.height - 35 && + gift.x > playerX - 55 && gift.x < playerX + 55) { + + // Combo system + const now = Date.now(); + if (now - lastCatchTime < 1000) { + combo++; + } else { + combo = 1; + } + lastCatchTime = now; + + const comboMultiplier = 1 + (combo - 1) * 0.2; + const finalPoints = Math.floor(gift.points * comboMultiplier); + + score += finalPoints; + scoreEl.innerText = score; + + createExplosion(gift.x + gift.size/2, gift.y + gift.size/2, gift.color); + gifts.splice(index, 1); + + // Increase difficulty + difficultyMultiplier = 1 + (score / 500); + } else if (gift.y > canvas.height) { + gifts.splice(index, 1); + combo = 0; + } + }); + + // Display combo + if (combo > 1) { + ctx.save(); + ctx.fillStyle = '#ff00ff'; + ctx.font = 'bold 24px Orbitron'; + ctx.textAlign = 'center'; + ctx.shadowBlur = 15; + ctx.shadowColor = '#ff00ff'; + ctx.fillText(`${combo}x COMBO!`, playerX, canvas.height - 50); + ctx.restore(); + } + + requestAnimationFrame(updateGame); + }; + + canvas.addEventListener('mousemove', (e) => { + const rect = canvas.getBoundingClientRect(); + playerX = e.clientX - rect.left; + }); + + startBtn.addEventListener('click', () => { + gameActive = true; + score = 0; + scoreEl.innerText = score; + gifts = []; + particles = []; + difficultyMultiplier = 1; + combo = 0; + lastCatchTime = 0; + startBtn.style.display = 'none'; + document.getElementById('gameUI').style.top = '40px'; + document.getElementById('gameUI').style.transform = 'translateX(-50%)'; + updateGame(); + }); + + window.addEventListener('resize', resize); + resize(); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..4ebe31f --- /dev/null +++ b/index.html @@ -0,0 +1,98 @@ + + + + + + TRAE Aurora | Crystalline Christmas + + + + + + + + + +
+ + + + +
+
+

TRAE CHRISTMAS

+

Elevating the holiday spirit through crystalline logic.

+ +
+
+ 00 + +
+
+ 00 + +
+
+ 00 + +
+
+ 00 + +
+
+ +
+ + +
+
+
+ + +
+
+

Magical Message Forge

+

Cast your festive wishes into the crystalline grid.

+
+ + +
+
+

+ +
+
+
+ + +
+
+

Gift Catcher

+

Catch the falling TRAE gifts to power the Aurora.

+
+
+
Score: 0
+ +
+ +
+
+
+ + +
+ + + + diff --git a/style.css b/style.css new file mode 100644 index 0000000..dba9c5c --- /dev/null +++ b/style.css @@ -0,0 +1,332 @@ +:root { + --bg-dark: #050b14; + --trae-green: #00ff66; + --aurora-cyan: #00f2ff; + --aurora-purple: #7000ff; + --text-primary: #e0e0e0; + --text-dim: #a0a0a0; + --glass-bg: rgba(255, 255, 255, 0.05); + --glass-border: rgba(255, 255, 255, 0.1); + --font-main: 'Space Grotesk', sans-serif; + --font-accent: 'Orbitron', sans-serif; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + scroll-behavior: smooth; +} + +body { + background-color: var(--bg-dark); + color: var(--text-primary); + font-family: var(--font-main); + overflow-x: hidden; +} + +#bgCanvas { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -1; +} + +.app-container { + max-width: 1200px; + margin: 0 auto; + padding: 0 20px; +} + +/* Glassmorphism Utility */ +.glass { + background: var(--glass-bg); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid var(--glass-border); + border-radius: 20px; +} + +/* Navigation */ +.glass-nav { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 40px; + margin-top: 20px; + background: var(--glass-bg); + backdrop-filter: blur(10px); + border: 1px solid var(--glass-border); + border-radius: 50px; + position: sticky; + top: 20px; + z-index: 100; +} + +.logo { + font-family: var(--font-accent); + font-weight: 700; + font-size: 1.5rem; + letter-spacing: 2px; +} + +.logo span { + color: var(--trae-green); + text-shadow: 0 0 10px var(--trae-green); +} + +.nav-links { + display: flex; + list-style: none; + gap: 30px; +} + +.nav-links a { + color: var(--text-primary); + text-decoration: none; + font-weight: 500; + transition: color 0.3s; +} + +.nav-links a:hover { + color: var(--trae-green); +} + +/* Hero Section */ +.hero { + height: 100vh; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; +} + +.glitch-text { + font-family: var(--font-accent); + font-size: 5rem; + font-weight: 700; + position: relative; + color: white; + margin-bottom: 10px; +} + +.glitch-text::before, +.glitch-text::after { + content: attr(data-text); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + opacity: 0.8; +} + +.glitch-text::before { + color: var(--trae-green); + z-index: -1; + animation: glitch 3s infinite; +} + +.glitch-text::after { + color: var(--aurora-cyan); + z-index: -2; + animation: glitch 2s infinite reverse; +} + +@keyframes glitch { + 0% { transform: translate(0); } + 20% { transform: translate(-2px, 2px); } + 40% { transform: translate(-2px, -2px); } + 60% { transform: translate(2px, 2px); } + 80% { transform: translate(2px, -2px); } + 100% { transform: translate(0); } +} + +.subtitle { + font-size: 1.2rem; + color: var(--text-dim); + margin-bottom: 40px; +} + +/* Countdown */ +.countdown-container { + display: flex; + gap: 20px; + margin-bottom: 40px; +} + +.time-block { + background: var(--glass-bg); + padding: 20px; + border-radius: 15px; + min-width: 100px; + border: 1px solid var(--glass-border); +} + +.time-block span { + display: block; + font-size: 2.5rem; + font-family: var(--font-accent); + color: var(--trae-green); +} + +.time-block label { + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--text-dim); +} + +/* Buttons */ +.btn-primary, .btn-secondary { + padding: 15px 35px; + font-family: var(--font-accent); + font-size: 1rem; + border-radius: 30px; + cursor: pointer; + transition: all 0.3s; + border: none; + text-transform: uppercase; + font-weight: 600; +} + +.btn-primary { + background: var(--trae-green); + color: var(--bg-dark); + box-shadow: 0 0 20px rgba(0, 255, 102, 0.4); +} + +.btn-primary:hover { + transform: translateY(-3px); + box-shadow: 0 0 30px rgba(0, 255, 102, 0.6); +} + +.btn-secondary { + background: transparent; + color: white; + border: 1px solid var(--glass-border); + margin-left: 15px; +} + +.btn-secondary:hover { + background: var(--glass-bg); +} + +/* Section Styling */ +.section-card { + margin: 100px 0; + padding: 60px; + text-align: center; +} + +.section-card h2 { + font-family: var(--font-accent); + font-size: 2.5rem; + margin-bottom: 20px; +} + +/* Forge Section */ +.forge-input-group { + display: flex; + gap: 10px; + max-width: 600px; + margin: 40px auto; +} + +.forge-input-group input { + flex: 1; + background: rgba(255, 255, 255, 0.05); + border: 1px solid var(--glass-border); + padding: 15px 25px; + border-radius: 30px; + color: white; + font-family: var(--font-main); +} + +.crystal-display { + margin-top: 40px; + min-height: 200px; + display: flex; + flex-direction: column; + align-items: center; +} + +#outputMessage { + font-size: 1.5rem; + color: var(--trae-green); + margin-bottom: 20px; + font-family: var(--font-accent); +} + +/* Game Section */ +.game-container { + position: relative; + width: 100%; + height: 400px; + background: rgba(0, 0, 0, 0.3); + border-radius: 20px; + overflow: hidden; + margin-top: 40px; +} + +#gameCanvas { + width: 100%; + height: 100%; +} + +#gameUI { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 10; + text-align: center; +} + +.score { + font-family: var(--font-accent); + font-size: 1.5rem; + margin-bottom: 20px; +} + +footer { + text-align: center; + padding: 60px 40px; + margin-top: 100px; + border-top: 1px solid var(--glass-border); + background: rgba(0, 0, 0, 0.2); +} + +footer p { + font-family: var(--font-accent); + letter-spacing: 1px; + margin-bottom: 10px; +} + +footer span, .glm-link, .author-link, .gemini-link { + color: var(--trae-green); + text-shadow: 0 0 10px rgba(0, 255, 102, 0.5); + text-decoration: none; + transition: all 0.3s ease; +} + +.glm-link:hover, .author-link:hover, .gemini-link:hover { + color: white; + text-shadow: 0 0 20px var(--trae-green); +} + +.copyright { + font-size: 0.8rem; + color: var(--text-dim); + font-family: var(--font-main); +} + +@media (max-width: 768px) { + .glitch-text { font-size: 3rem; } + .countdown-container { flex-wrap: wrap; justify-content: center; } + .forge-input-group { flex-direction: column; } + .btn-secondary { margin-left: 0; margin-top: 15px; } +} diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..c6c779f --- /dev/null +++ b/vercel.json @@ -0,0 +1 @@ +{"rewrites":[{"source":"/(.*)","destination":"/index.html"}]} \ No newline at end of file