diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 1dda9bb..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# pages - diff --git a/dropdown.js b/dropdown.js deleted file mode 100644 index fc97817..0000000 --- a/dropdown.js +++ /dev/null @@ -1,61 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0 - -/* - * InterstellarDevelopment website - * Copyright (C) 2024 interstellar_development - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -document.addEventListener("DOMContentLoaded", () => { - const menu = document.querySelector(".menu"); - const burgerMenu = document.querySelector(".burger-menu"); - - if (!menu || !burgerMenu) { - console.warn( - "Menu or burger menu element not found. Ensure they exist in the DOM." - ); - return; - } - - // Toggle the menu visibility - function toggleMenu() { - menu.classList.toggle("active"); - - if (menu.classList.contains("active")) { - // Add click listener to close menu when clicking outside - document.addEventListener("click", closeMenu); - } else { - // Remove the click listener when menu is closed - document.removeEventListener("click", closeMenu); - } - } - - // Close the menu if clicking outside of it - function closeMenu(event) { - if ( - !menu.contains(event.target) && - !event.target.classList.contains("burger-menu") - ) { - menu.classList.remove("active"); - document.removeEventListener("click", closeMenu); - } - } - - // Attach click event to the burger menu button - burgerMenu.addEventListener("click", (event) => { - event.stopPropagation(); // Prevent click from immediately triggering closeMenu - toggleMenu(); - }); -}); -// @license-end diff --git a/favicon_io/about.txt b/favicon_io/about.txt deleted file mode 100644 index 2062908..0000000 --- a/favicon_io/about.txt +++ /dev/null @@ -1,6 +0,0 @@ -This favicon was generated using the following graphics from Twitter Twemoji: - -- Graphics Title: 1f680.svg -- Graphics Author: Copyright 2020 Twitter, Inc and other contributors (https://github.com/twitter/twemoji) -- Graphics Source: https://github.com/twitter/twemoji/blob/master/assets/svg/1f680.svg -- Graphics License: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/) diff --git a/favicon_io/android-chrome-192x192.png b/favicon_io/android-chrome-192x192.png deleted file mode 100644 index 385d40d..0000000 Binary files a/favicon_io/android-chrome-192x192.png and /dev/null differ diff --git a/favicon_io/android-chrome-512x512.png b/favicon_io/android-chrome-512x512.png deleted file mode 100644 index 843853f..0000000 Binary files a/favicon_io/android-chrome-512x512.png and /dev/null differ diff --git a/favicon_io/apple-touch-icon.png b/favicon_io/apple-touch-icon.png deleted file mode 100644 index 1b41da6..0000000 Binary files a/favicon_io/apple-touch-icon.png and /dev/null differ diff --git a/favicon_io/favicon-16x16.png b/favicon_io/favicon-16x16.png deleted file mode 100644 index 870d85f..0000000 Binary files a/favicon_io/favicon-16x16.png and /dev/null differ diff --git a/favicon_io/favicon-32x32.png b/favicon_io/favicon-32x32.png deleted file mode 100644 index 89bbbad..0000000 Binary files a/favicon_io/favicon-32x32.png and /dev/null differ diff --git a/favicon_io/favicon.ico b/favicon_io/favicon.ico deleted file mode 100644 index 385d320..0000000 Binary files a/favicon_io/favicon.ico and /dev/null differ diff --git a/favicon_io/site.webmanifest b/favicon_io/site.webmanifest deleted file mode 100644 index 45dc8a2..0000000 --- a/favicon_io/site.webmanifest +++ /dev/null @@ -1 +0,0 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/footer.js b/footer.js deleted file mode 100644 index 3aed36c..0000000 --- a/footer.js +++ /dev/null @@ -1,68 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0 - -/* - * interstellar_development website - * Copyright (C) 2024 interstellar_development - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -class Footer extends HTMLElement { - constructor() { - super(); - } - - connectedCallback() { - this.innerHTML = ` -
-
- -
-
- `; - - // Add event listener for button click - this.querySelector(".secret-button").addEventListener("click", () => { - window.open("secret/index.html", "_blank"); - }); - } -} - -customElements.define("footer-component", Footer); - -// CSS for the hidden button -const style = document.createElement("style"); -style.textContent = ` -.secret-button { - display: none; - position: absolute; - bottom: 10px; - right: 10px; - background-color: transparent; - border: none; - font-size: 24px; - cursor: pointer; - } - - .footer-content:hover .secret-button { - display: block; - } - `; -document.head.appendChild(style); - -// @license-end diff --git a/header.js b/header.js deleted file mode 100644 index 6cb9811..0000000 --- a/header.js +++ /dev/null @@ -1,46 +0,0 @@ -// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0 - -/* - * interstellar_development website - * Copyright (C) 2024 interstellar_development - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -class Header extends HTMLElement { - constructor() { - super(); - } - - connectedCallback() { - this.innerHTML = ` -
- -
- - `; - } -} - -customElements.define("header-component", Header); -// @license-end diff --git a/images/nicolas.png b/images/nicolas.png deleted file mode 100644 index 63b6bf3..0000000 Binary files a/images/nicolas.png and /dev/null differ diff --git a/images/star.jpg b/images/star.jpg deleted file mode 100644 index 2b1475a..0000000 Binary files a/images/star.jpg and /dev/null differ diff --git a/index.html b/index.html index f9b4677..a81af8f 100644 --- a/index.html +++ b/index.html @@ -1,233 +1,496 @@ - - - - - - + Interstellar Development | Free and Open Source Software + + + + + + + + + - - Interstellar Development - - + +
+
-
-
-

Our Projects

- -

Our Games

- - -
    -
  • -

    Previously we had more unfinished Games listed here.

    -

    - We decided against displaying them and giving people the - impression we are working on them currently. -

    -

    In the Future we will display the released games here

    -
  • -
- -

Our Other Projects

- -
- - -

Our Team

-
-
- - Patrick -

Patrick_Pluto

-

- The system administrator and our lead coder. He is the one you - will need to blame for bugs in the games -

-
+ + + +
+ +
+
+
+

+ Advancing Free Software Development +

- Our game level and asset designer. He is responsible for all - assets in our FreeFTF game. So if an asset looks ugly be mad at - him. Also, we are not sure if he is human or just a drunk wizard - cat but one thing is very clear he is still a novice at his job. + We develop high-quality free and open source software solutions, + with a focus on gaming and applications that respect user freedom.

- + +
- -
-

About Us

-

- Welcome to Interstellar Development! We are a small, passionate - international team dedicated to transforming the programming world - into a free-and-open-source future. Our diverse backgrounds and - experiences fuel our commitment to creating free and open-source - software, particularly in the realm of gaming. -

-

- Our journey began with a shared vision: to better organize our efforts - in making free and open-source games more efficient and accessible. We - recognized that many current free software games are either lacking in - quality or simply do not exist. This realization inspired us to focus - on developing games that are unplayable on GNU/Linux and FreeBSD - systems, as well as creating free software alternatives for those in - need. -

-

- At Interstellar Development, we believe that true freedom for computer - users can only be achieved through the use of free software. That’s - why we are committed to licensing all of our projects under copyleft - free and open-source software licenses, ensuring that our games remain - free for everyone to enjoy, forever. -

-

- While we are not currently accepting donations, we welcome your - support in the form of feedback and suggestions for improvements. If - you wish to contribute financially, we encourage you to donate to the - Free Software Foundation, as without them, we would have never started - this. -

-

- Join us as we strive to create a vibrant community around free - software and gaming. Together, we can make a difference and pave the - way for a free future! -

+ +
+
+
+

Our Projects

+

+ High-quality free software solutions built with passion and + dedication +

+
+ + +
+
+ + + + +
+ +
+ +
+ +
+ +
+
+
-
-

Our Vision

-

Interstellar Development: Free Software is Our Passion

-

- At Interstellar Development, we embarked on this journey to create a - more organized and efficient approach to developing free and - open-source software, with a particular focus on gaming. We recognized - a significant gap in the availability and quality of free software - games, which often fail to meet the expectations of users or simply do - not exist. Our mission is to fill this void and elevate the standards - of free gaming experiences. -

-

- Our primary goal is to target games that are currently unplayable on - GNU/Linux and FreeBSD systems. We aim to develop high-quality - alternatives that not only provide enjoyable gameplay but also adhere - to the principles of free software. Additionally, we are committed to - identifying and addressing other areas within the software ecosystem - that lack free alternatives, ensuring that users have access to a - diverse range of tools and applications that respect their freedom. -

-

- At Interstellar Development, we firmly believe that the path to true - freedom for computer users lies in the adoption and promotion of free - software. To this end, we are dedicated to licensing all of our - projects under copyleft free and open-source software licenses. This - commitment ensures that our games and software remain free for - everyone to play, modify, and share, fostering a culture of - collaboration and innovation within the community. -

-

- We understand that community involvement is crucial to our success. - While we are not currently accepting donations, we invite you to - support us by providing feedback, reporting issues, and suggesting - improvements. Your insights are invaluable in helping us refine our - projects and enhance the user experience. -

-

- If you feel compelled to contribute financially, we encourage you to - consider donating to the Free Software Foundation. Their unwavering - support and advocacy for free software principles have been - instrumental in our journey, and your contributions to them help - sustain the broader movement that enables us to create these games. -

-

- Together, we can build a vibrant community around free software and - gaming, paving the way for a future where everyone has access to - high-quality, open-source alternatives. Join us in our mission to make - a difference and champion the cause of free software for all! -

-
-
+ +
+
+
+

Our Team

+

+ A small but dedicated international team committed to free + software +

+
- - +
+
+
+ +
+

Patrick

+
+ Lead Programmer & System Administrator +
+

+ Patrick focuses on backend development and system + administration, managing our infrastructure and core application + logic with expertise in server-side technologies and DevOps. +

+
+ +
+
+ +
+

Sage

+
Frontend Developer & Communications
+

+ Sage focuses on frontend development and is in charge of + communication and UI/UX design, ensuring our projects have + intuitive interfaces and excellent user experiences. +

+
+
+
+
+ + +
+
+
+

About Us

+
+ +
+

+ Interstellar Development is a small international team dedicated + to advancing free and open source software. Our diverse + backgrounds and shared commitment to user freedom drive our + development philosophy. +

+ +

+ We began with a vision to create high-quality free software, + particularly in gaming where such options are often limited. We + recognized that many free software games either lack polish or + simply don't exist, inspiring us to focus on this under-served + area. +

+ +

+ At Interstellar Development, we believe true digital freedom can + only be achieved through free software. All our projects are + released under copyleft licenses, ensuring they remain free for + everyone to use, modify, and distribute. +

+ +

+ While we don't currently accept donations, we welcome feedback and + suggestions. If you wish to support the free software movement, we + encourage donations to the Free Software Foundation, whose work + continues to inspire our journey. +

+
+
+
+ + +
+
+
+

Our Vision

+
+ +
+
+

+ Our mission is to create high-quality free software + alternatives, particularly for games that are unavailable on + free operating systems like GNU/Linux and FreeBSD. We aim to + address gaps in the software ecosystem where free alternatives + are lacking. +

+
+ +
+
+
+ +
+

Software Freedom

+

+ All our projects are released under copyleft licenses to + ensure user freedoms are protected and preserved. +

+
+ +
+
+ +
+

Community Collaboration

+

+ We believe in building software with and for the community, + welcoming contributions and feedback. +

+
+ +
+
+ +
+

Quality Standards

+

+ We strive to create software that matches or exceeds the + quality of proprietary alternatives. +

+
+
+
+
+
+ + +
+
+
+
+
0
+
Projects
+
+
+
0
+
Team Members
+
+
+
0
+
Years Active
+
+
+
0
+
% Free Software
+
+
+
+
+ + +
+
+
+

Get In Touch

+

+ Have questions about our projects or want to contribute? We'd love + to hear from you. +

+
+ +
+
+
+
+
+ +
+ +
+ +
+
+ +
+
+

Source Code

+ View Our Projects +
+
+
+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/secret/asteroidDestroyer/explenation.html b/secret/asteroidDestroyer/explenation.html deleted file mode 100644 index 843c32c..0000000 --- a/secret/asteroidDestroyer/explenation.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - Game Landing Page - - - - - - - -
-
- - -
- -
-

Welcome to the Asteroid Game!

-

- In this game, you control a spaceship that shoots at asteroids to - avoid destruction and collect items for power-ups. -

-

Your goal is to survive as long as possible while scoring points!

- -
-
- - - - diff --git a/secret/asteroidDestroyer/game.js b/secret/asteroidDestroyer/game.js deleted file mode 100644 index 2ea6461..0000000 --- a/secret/asteroidDestroyer/game.js +++ /dev/null @@ -1,414 +0,0 @@ -"use strict"; -// Canvas setup -const canvas = document.getElementById("gameCanvas"); -const ctx = canvas.getContext("2d"); -const targetFPS = 60; -const targetFrameTime = 1000 / targetFPS; -canvas.width = window.innerWidth; -canvas.height = window.innerHeight; - -let lastFrameTime = performance.now(); - -// Game elements -const player = { - x: canvas.width / 2, - y: canvas.height - 60, - width: 40, - height: 40, - color: "white", - speed: 5, - dx: 0, -}; - -let bullets = []; -let asteroids = []; -let items = []; -let score = 0; -let totalBulletsFired = 0; -let isGameOver = false; -let lastBulletTime = 0; -let ammo = 100; // Ammo counter - -// Difficulty control -let asteroidSpawnInterval = 800; // Faster spawn rate -let asteroidSpeedMultiplier = 1.5; // Faster asteroids from the start -let difficultyIncreaseRate = 0.2; // Faster scaling every 10 seconds - -// Controls -let canShoot = true; // Flag to control shooting -let rapidFireActive = false; -let shotgunActive = false; -let rainbowActive = false; -let lastShotgunTime = 0; - -// Controls for sphere effects -let blueSphereCooldown = 0; -let yellowSphereCooldown = 0; -let greenSphereCooldown = 0; -let rainbowSphereCooldown = 0; - -// Sphere types -const sphereTypes = ["blue", "yellow", "green", "rainbow"]; - -/// Control for left button press and release -function btnMoveLeft(isPressed) { - if (isPressed) { - player.dx = -player.speed; // Start moving left - } else { - player.dx = 0; // Stop moving when button is released - } -} - -// Control for shoot button click (simulates spacebar press) -function btnShoot() { - if (canShoot && !isGameOver) { - shootBullet(); - canShoot = false; // Prevent shooting until the button is "released" - } -} - -// Control for right button press and release -function btnMoveRight(isPressed) { - if (isPressed) { - player.dx = player.speed; // Start moving right - } else { - player.dx = 0; // Stop moving when button is released - } -} - -document.getElementById("shootBtn").addEventListener("mouseup", () => { - canShoot = true; // Allow shooting again when button is released -}); - -window.addEventListener("keydown", (e) => { - if (e.key === "ArrowLeft" || e.key === "a") player.dx = -player.speed; - if (e.key === "ArrowRight" || e.key === "d") player.dx = player.speed; - - // Shoot only if it's not a hold, and we can shoot - if (e.key === " " && canShoot && !isGameOver) { - shootBullet(); - canShoot = false; // Prevent shooting until the key is released - } - - if (e.key === "r" && isGameOver) restartGame(); -}); - -window.addEventListener("keyup", (e) => { - // Stop moving when either the arrow keys or the 'a'/'d' keys are released - if ( - e.key === "ArrowLeft" || - e.key === "ArrowRight" || - e.key === "a" || - e.key === "d" - ) { - player.dx = 0; - } - - // Allow shooting again when the space key is released - if (e.key === " ") { - canShoot = true; - } -}); - -// Bullet mechanics with cooldown -function shootBullet() { - const now = Date.now(); - if (now - lastBulletTime < 100) return; // Enforce cooldown of 0.1 seconds - if (ammo <= 0) return; // Prevent shooting if ammo is empty - lastBulletTime = now; - ammo--; // Decrease ammo - - totalBulletsFired++; // Increment total bullets fired - - if (rapidFireActive) { - // If rapid fire is active, fire bullets continuously with a short delay - for (let i = 0; i < 3; i++) { - setTimeout(() => { - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - }); - }, i * 50); // Fire bullets with 50ms delay between shots - } - } else if (shotgunActive) { - // Shotgun effect, firing 3 bullets with a spread - for (let i = -1; i <= 1; i++) { - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - angle: i * 10, // Spray the bullets at different angles - }); - } - } else { - // Normal bullet - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - }); - } -} - -// Generate random color -function getRandomColor() { - const colors = ["red", "blue", "green", "orange", "purple", "pink"]; - return colors[Math.floor(Math.random() * colors.length)]; -} - -// Asteroid mechanics -function createAsteroid() { - const size = Math.random() * 40 + 30; // Bigger asteroids (min: 30, max: 70) - asteroids.push({ - x: Math.random() * canvas.width, - y: -size, - width: size, - height: size, - color: getRandomColor(), - speed: (Math.random() * 3 + 2) * asteroidSpeedMultiplier, // Faster initial speed - }); -} - -// Item mechanics -function createItem() { - const randomType = - sphereTypes[Math.floor(Math.random() * sphereTypes.length)]; - const size = 30; - const x = Math.random() * canvas.width; - items.push({ - x: x, - y: -size, - width: size, - height: size, - type: randomType, - color: - randomType === "blue" - ? "blue" - : randomType === "yellow" - ? "yellow" - : randomType === "green" - ? "green" - : "rainbow", - speed: 3, - }); -} - -// Update game elements -function updatePlayer() { - player.x += player.dx; - if (player.x < 0) player.x = 0; - if (player.x + player.width > canvas.width) - player.x = canvas.width - player.width; -} - -function updateBullets() { - bullets.forEach((bullet, index) => { - bullet.y -= bullet.speed; - if (bullet.y + bullet.height < 0) bullets.splice(index, 1); - }); -} - -function updateAsteroids() { - asteroids.forEach((asteroid, index) => { - asteroid.y += asteroid.speed; - if (asteroid.y > canvas.height) asteroids.splice(index, 1); - }); -} - -function updateItems() { - items.forEach((item, index) => { - item.y += item.speed; - if (item.y > canvas.height) items.splice(index, 1); - // Check if player collects the item - if ( - player.x < item.x + item.width && - player.x + player.width > item.x && - player.y < item.y + item.height && - player.y + player.height > item.y - ) { - applyItemEffect(item.type); - items.splice(index, 1); // Remove the item after it is collected - } - }); -} - -function applyItemEffect(type) { - let points = Math.floor(Math.random() * 5) + 1; // Random points between 1 and 5 - if (type === "blue") { - rapidFireActive = true; - setTimeout(() => (rapidFireActive = false), 15000); // 15 seconds of rapid fire - } else if (type === "yellow") { - shotgunActive = true; - setTimeout(() => (shotgunActive = false), 30000); // 30 seconds of shotgun - } else if (type === "green") { - ammo = 100; // Refill ammo - } else if (type === "rainbow") { - rapidFireActive = true; - shotgunActive = true; - setTimeout(() => { - rapidFireActive = false; - shotgunActive = false; - }, 15000); // 15 seconds with all effects - } - score += points; // Add points when an item is collected -} - -// Collision detection -function checkCollisions() { - bullets.forEach((bullet, bIndex) => { - asteroids.forEach((asteroid, aIndex) => { - if ( - bullet.x < asteroid.x + asteroid.width && - bullet.x + bullet.width > asteroid.x && - bullet.y < asteroid.y + asteroid.height && - bullet.y + bullet.height > asteroid.y - ) { - bullets.splice(bIndex, 1); - asteroids.splice(aIndex, 1); - score += Math.floor(Math.random() * 5) + 1; // Add points when an asteroid is destroyed - // Visual feedback for destroyed asteroid - createExplosion(asteroid.x, asteroid.y); - } - }); - }); - - asteroids.forEach((asteroid) => { - if ( - player.x < asteroid.x + asteroid.width && - player.x + player.width > asteroid.x && - player.y < asteroid.y + asteroid.height && - player.y + player.height > asteroid.y - ) { - isGameOver = true; - } - }); -} - -// Explosion effect -function createExplosion(x, y) { - ctx.fillStyle = "yellow"; - ctx.beginPath(); - ctx.arc(x, y, 20, 0, Math.PI * 2); - ctx.fill(); - setTimeout(() => ctx.clearRect(x - 20, y - 20, 40, 40), 200); // Clear explosion after 200ms -} - -// Draw elements -function drawPlayer() { - ctx.fillStyle = player.color; - ctx.fillRect(player.x, player.y, player.width, player.height); -} - -function drawBullets() { - bullets.forEach((bullet) => { - ctx.fillStyle = bullet.color; - ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height); - }); -} - -function drawAsteroids() { - asteroids.forEach((asteroid) => { - ctx.fillStyle = asteroid.color; - ctx.fillRect(asteroid.x, asteroid.y, asteroid.width, asteroid.height); - }); -} - -function drawItems() { - items.forEach((item) => { - ctx.fillStyle = item.color; - ctx.beginPath(); - ctx.arc( - item.x + item.width / 2, - item.y + item.height / 2, - item.width / 2, - 0, - Math.PI * 2 - ); - ctx.fill(); - }); -} - -function drawScore() { - ctx.fillStyle = "white"; - ctx.font = "24px Arial"; - ctx.fillText(`Score: ${score}`, 20, 40); // Score at top-left corner -} - -function drawAmmo() { - ctx.fillStyle = "white"; - ctx.font = "24px Arial"; - ctx.fillText(`Ammo: ${ammo}`, 20, 70); // Ammo at top-left corner -} - -function drawGameOver() { - if (isGameOver) { - ctx.fillStyle = "white"; - ctx.font = "40px Arial"; - ctx.textAlign = "center"; - ctx.fillText("Game Over!", canvas.width / 2, canvas.height / 2 - 40); - ctx.font = "24px Arial"; - ctx.fillText(`Total Score: ${score}`, canvas.width / 2, canvas.height / 2); - ctx.fillText( - `Bullets Fired: ${totalBulletsFired}`, - canvas.width / 2, - canvas.height / 2 + 40 - ); - ctx.fillText( - 'Press "R" to Restart', - canvas.width / 2, - canvas.height / 2 + 80 - ); - } -} - -// Restart game -function restartGame() { - window.location.reload(); -} - -// Main game loop -function gameLoop() { - const currentTime = performance.now(); - const elapsedTime = currentTime - lastFrameTime; - - if (elapsedTime >= targetFrameTime) { - lastFrameTime = currentTime - (elapsedTime % targetFrameTime); - ctx.clearRect(0, 0, canvas.width, canvas.height); - - if (!isGameOver) { - updatePlayer(); - updateBullets(); - updateAsteroids(); - updateItems(); - checkCollisions(); - } - - drawPlayer(); - drawBullets(); - drawAsteroids(); - drawItems(); - drawScore(); - drawAmmo(); - drawGameOver(); - - if (!isGameOver) { - if (Math.random() < 0.01) createAsteroid(); // 1% chance every frame to spawn an asteroid - if (Math.random() < 0.005) createItem(); // 0.5% chance to spawn an item - } - } - - requestAnimationFrame(gameLoop); -} - -// Start game loop -requestAnimationFrame(gameLoop); diff --git a/secret/asteroidDestroyer/secret.html b/secret/asteroidDestroyer/secret.html deleted file mode 100644 index 1b22d19..0000000 --- a/secret/asteroidDestroyer/secret.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - Asteroid Shooter - - - - - - - - - - -
- - - -
- - - - diff --git a/secret/asteroidDestroyer/style.css b/secret/asteroidDestroyer/style.css deleted file mode 100644 index e90a6ad..0000000 --- a/secret/asteroidDestroyer/style.css +++ /dev/null @@ -1,43 +0,0 @@ -body { - margin: 0; - overflow: hidden; -} - -canvas { - display: block; - background: black; - width: 100%; - height: 100%; -} - -.controls { - display: none; - position: absolute; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - display: flex; - justify-content: space-between; - width: 80%; -} - -.control-btn { - display: none; - padding: 10px; - font-size: 18px; - background-color: rgba(0, 0, 0, 0.6); - color: white; - border: 1px solid #fff; - border-radius: 5px; - cursor: pointer; - flex-grow: 1; - margin: 0 5px; -} - -@media (max-width: 600px) { - .control-btn { - display: block; - font-size: 16px; - padding: 12px; - } -} diff --git a/secret/asteroidDestroyer/styles.css b/secret/asteroidDestroyer/styles.css deleted file mode 100644 index 7d92d64..0000000 --- a/secret/asteroidDestroyer/styles.css +++ /dev/null @@ -1,76 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body, -html { - height: 100%; - font-family: Arial, sans-serif; - display: flex; - justify-content: center; - align-items: center; - background-color: #000; - color: white; - overflow: hidden; -} - -.landing-page { - position: relative; - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; -} - -.game-background { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background-color: rgba(0, 0, 0, 0.7); /* Dark overlay */ - backdrop-filter: blur(8px); /* Apply blur effect to the background */ - z-index: -1; /* Ensures it's in the background */ - pointer-events: none; /* Prevent interaction with the blurred background */ -} - -.content { - text-align: center; - z-index: 1; /* Ensure content appears above the game background */ - padding: 20px; - max-width: 600px; /* Limit the width of the content */ - position: relative; - color: white; - backdrop-filter: blur( - 8px - ); /* Ensure content has some blur as well for contrast */ -} - -h1 { - font-size: 2rem; - margin-bottom: 20px; -} - -p { - font-size: 1.2rem; - margin-bottom: 30px; -} - -button { - padding: 12px 24px; - background-color: #ffcc00; - color: black; - border: none; - font-size: 18px; - cursor: pointer; - border-radius: 5px; - text-transform: uppercase; - transition: background-color 0.3s ease; -} - -button:hover { - background-color: #ff9900; -} diff --git a/secret/endlessRunner/index.html b/secret/endlessRunner/index.html deleted file mode 100644 index c2feb26..0000000 --- a/secret/endlessRunner/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - Endless runner - - - - - - -
- - -
- - - diff --git a/secret/endlessRunner/script.js b/secret/endlessRunner/script.js deleted file mode 100644 index 59df696..0000000 --- a/secret/endlessRunner/script.js +++ /dev/null @@ -1,90 +0,0 @@ -import { useEffect, useRef, useState } from "react"; - -export default function EndlessRunner() { - const canvasRef = useRef(null); - const [running, setRunning] = useState(true); - const player = { x: 50, y: 150, width: 20, height: 20, dy: 0 }; - const gravity = 0.5; - let obstacles = []; - let score = 0; - - useEffect(() => { - const canvas = canvasRef.current; - const ctx = canvas.getContext("2d"); - canvas.width = window.innerWidth; - canvas.height = 300; - - function update() { - if (!running) return; - ctx.clearRect(0, 0, canvas.width, canvas.height); - - // Player physics - player.dy += gravity; - player.y += player.dy; - if (player.y > 150) { - player.y = 150; - player.dy = 0; - } - - // Draw player - ctx.fillStyle = "blue"; - ctx.fillRect(player.x, player.y, player.width, player.height); - - // Obstacles - if (Math.random() < 0.02) { - obstacles.push({ x: canvas.width, y: 150, width: 20, height: 20 }); - } - obstacles = obstacles.map((obstacle) => ({ - ...obstacle, - x: obstacle.x - 5, - })); - obstacles = obstacles.filter( - (obstacle) => obstacle.x + obstacle.width > 0 - ); - - obstacles.forEach((obstacle) => { - ctx.fillStyle = "red"; - ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height); - - // Collision detection - if ( - player.x < obstacle.x + obstacle.width && - player.x + player.width > obstacle.x && - player.y < obstacle.y + obstacle.height && - player.y + player.height > obstacle.y - ) { - setRunning(false); - } - }); - - // Score - score++; - ctx.fillStyle = "black"; - ctx.fillText("Score: " + score, 10, 20); - - requestAnimationFrame(update); - } - - update(); - }, [running]); - - function jump() { - if (player.y >= 150) { - player.dy = -10; - } - } - - return ( -
- - {!running && ( - - )} -
- ); -} diff --git a/secret/endlessRunner/styles.css b/secret/endlessRunner/styles.css deleted file mode 100644 index b8850fc..0000000 --- a/secret/endlessRunner/styles.css +++ /dev/null @@ -1,34 +0,0 @@ -body { - margin: 0; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - background-color: #f4f4f4; -} - -.game-container { - position: relative; - text-align: center; -} - -canvas { - border: 2px solid black; - background-color: white; - display: block; -} - -#restartBtn { - margin-top: 10px; - padding: 10px 20px; - font-size: 16px; - background-color: #007bff; - color: white; - border: none; - cursor: pointer; - display: none; -} - -#restartBtn:hover { - background-color: #0056b3; -} diff --git a/secret/game.js b/secret/game.js deleted file mode 100644 index 36185f6..0000000 --- a/secret/game.js +++ /dev/null @@ -1,404 +0,0 @@ -"use strict"; -// Canvas setup -const canvas = document.getElementById("gameCanvas"); -const ctx = canvas.getContext("2d"); -canvas.width = window.innerWidth; -canvas.height = window.innerHeight; - -// Game elements -const player = { - x: canvas.width / 2, - y: canvas.height - 60, - width: 40, - height: 40, - color: "white", - speed: 5, - dx: 0, -}; - -let bullets = []; -let asteroids = []; -let items = []; -let score = 0; -let totalBulletsFired = 0; -let isGameOver = false; -let lastBulletTime = 0; -let ammo = 100; // Ammo counter - -// Difficulty control -let asteroidSpawnInterval = 800; // Faster spawn rate -let asteroidSpeedMultiplier = 1.5; // Faster asteroids from the start -let difficultyIncreaseRate = 0.2; // Faster scaling every 10 seconds - -// Controls -let canShoot = true; // Flag to control shooting -let rapidFireActive = false; -let shotgunActive = false; -let rainbowActive = false; -let lastShotgunTime = 0; - -// Controls for sphere effects -let blueSphereCooldown = 0; -let yellowSphereCooldown = 0; -let greenSphereCooldown = 0; -let rainbowSphereCooldown = 0; - -// Sphere types -const sphereTypes = ["blue", "yellow", "green", "rainbow"]; - -/// Control for left button press and release -function btnMoveLeft(isPressed) { - if (isPressed) { - player.dx = -player.speed; // Start moving left - } else { - player.dx = 0; // Stop moving when button is released - } -} - -// Control for shoot button click (simulates spacebar press) -function btnShoot() { - if (canShoot && !isGameOver) { - shootBullet(); - canShoot = false; // Prevent shooting until the button is "released" - } -} - -// Control for right button press and release -function btnMoveRight(isPressed) { - if (isPressed) { - player.dx = player.speed; // Start moving right - } else { - player.dx = 0; // Stop moving when button is released - } -} - -document.getElementById("shootBtn").addEventListener("mouseup", () => { - canShoot = true; // Allow shooting again when button is released -}); - -window.addEventListener("keydown", (e) => { - if (e.key === "ArrowLeft" || e.key === "a") player.dx = -player.speed; - if (e.key === "ArrowRight" || e.key === "d") player.dx = player.speed; - - // Shoot only if it's not a hold, and we can shoot - if (e.key === " " && canShoot && !isGameOver) { - shootBullet(); - canShoot = false; // Prevent shooting until the key is released - } - - if (e.key === "r" && isGameOver) restartGame(); -}); - -window.addEventListener("keyup", (e) => { - // Stop moving when either the arrow keys or the 'a'/'d' keys are released - if ( - e.key === "ArrowLeft" || - e.key === "ArrowRight" || - e.key === "a" || - e.key === "d" - ) { - player.dx = 0; - } - - // Allow shooting again when the space key is released - if (e.key === " ") { - canShoot = true; - } -}); - -// Bullet mechanics with cooldown -function shootBullet() { - const now = Date.now(); - if (now - lastBulletTime < 100) return; // Enforce cooldown of 0.1 seconds - if (ammo <= 0) return; // Prevent shooting if ammo is empty - lastBulletTime = now; - ammo--; // Decrease ammo - - totalBulletsFired++; // Increment total bullets fired - - if (rapidFireActive) { - // If rapid fire is active, fire bullets continuously with a short delay - for (let i = 0; i < 3; i++) { - setTimeout(() => { - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - }); - }, i * 50); // Fire bullets with 50ms delay between shots - } - } else if (shotgunActive) { - // Shotgun effect, firing 3 bullets with a spread - for (let i = -1; i <= 1; i++) { - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - angle: i * 10, // Spray the bullets at different angles - }); - } - } else { - // Normal bullet - bullets.push({ - x: player.x + player.width / 2 - 2.5, - y: player.y, - width: 5, - height: 10, - color: "yellow", - speed: 7, - }); - } -} - -// Generate random color -function getRandomColor() { - const colors = ["red", "blue", "green", "orange", "purple", "pink"]; - return colors[Math.floor(Math.random() * colors.length)]; -} - -// Asteroid mechanics -function createAsteroid() { - const size = Math.random() * 40 + 30; // Bigger asteroids (min: 30, max: 70) - asteroids.push({ - x: Math.random() * canvas.width, - y: -size, - width: size, - height: size, - color: getRandomColor(), - speed: (Math.random() * 3 + 2) * asteroidSpeedMultiplier, // Faster initial speed - }); -} - -// Item mechanics -function createItem() { - const randomType = - sphereTypes[Math.floor(Math.random() * sphereTypes.length)]; - const size = 30; - const x = Math.random() * canvas.width; - items.push({ - x: x, - y: -size, - width: size, - height: size, - type: randomType, - color: - randomType === "blue" - ? "blue" - : randomType === "yellow" - ? "yellow" - : randomType === "green" - ? "green" - : "rainbow", - speed: 3, - }); -} - -// Update game elements -function updatePlayer() { - player.x += player.dx; - if (player.x < 0) player.x = 0; - if (player.x + player.width > canvas.width) - player.x = canvas.width - player.width; -} - -function updateBullets() { - bullets.forEach((bullet, index) => { - bullet.y -= bullet.speed; - if (bullet.y + bullet.height < 0) bullets.splice(index, 1); - }); -} - -function updateAsteroids() { - asteroids.forEach((asteroid, index) => { - asteroid.y += asteroid.speed; - if (asteroid.y > canvas.height) asteroids.splice(index, 1); - }); -} - -function updateItems() { - items.forEach((item, index) => { - item.y += item.speed; - if (item.y > canvas.height) items.splice(index, 1); - // Check if player collects the item - if ( - player.x < item.x + item.width && - player.x + player.width > item.x && - player.y < item.y + item.height && - player.y + player.height > item.y - ) { - applyItemEffect(item.type); - items.splice(index, 1); // Remove the item after it is collected - } - }); -} - -function applyItemEffect(type) { - let points = Math.floor(Math.random() * 5) + 1; // Random points between 1 and 5 - if (type === "blue") { - rapidFireActive = true; - setTimeout(() => (rapidFireActive = false), 15000); // 15 seconds of rapid fire - } else if (type === "yellow") { - shotgunActive = true; - setTimeout(() => (shotgunActive = false), 30000); // 30 seconds of shotgun - } else if (type === "green") { - ammo = 100; // Refill ammo - } else if (type === "rainbow") { - rapidFireActive = true; - shotgunActive = true; - setTimeout(() => { - rapidFireActive = false; - shotgunActive = false; - }, 15000); // 15 seconds with all effects - } - score += points; // Add points when an item is collected -} - -// Collision detection -function checkCollisions() { - bullets.forEach((bullet, bIndex) => { - asteroids.forEach((asteroid, aIndex) => { - if ( - bullet.x < asteroid.x + asteroid.width && - bullet.x + bullet.width > asteroid.x && - bullet.y < asteroid.y + asteroid.height && - bullet.y + bullet.height > asteroid.y - ) { - bullets.splice(bIndex, 1); - asteroids.splice(aIndex, 1); - score += Math.floor(Math.random() * 5) + 1; // Add points when an asteroid is destroyed - // Visual feedback for destroyed asteroid - createExplosion(asteroid.x, asteroid.y); - } - }); - }); - - asteroids.forEach((asteroid) => { - if ( - player.x < asteroid.x + asteroid.width && - player.x + player.width > asteroid.x && - player.y < asteroid.y + asteroid.height && - player.y + player.height > asteroid.y - ) { - isGameOver = true; - } - }); -} - -// Explosion effect -function createExplosion(x, y) { - ctx.fillStyle = "yellow"; - ctx.beginPath(); - ctx.arc(x, y, 20, 0, Math.PI * 2); - ctx.fill(); - setTimeout(() => ctx.clearRect(x - 20, y - 20, 40, 40), 200); // Clear explosion after 200ms -} - -// Draw elements -function drawPlayer() { - ctx.fillStyle = player.color; - ctx.fillRect(player.x, player.y, player.width, player.height); -} - -function drawBullets() { - bullets.forEach((bullet) => { - ctx.fillStyle = bullet.color; - ctx.fillRect(bullet.x, bullet.y, bullet.width, bullet.height); - }); -} - -function drawAsteroids() { - asteroids.forEach((asteroid) => { - ctx.fillStyle = asteroid.color; - ctx.fillRect(asteroid.x, asteroid.y, asteroid.width, asteroid.height); - }); -} - -function drawItems() { - items.forEach((item) => { - ctx.fillStyle = item.color; - ctx.beginPath(); - ctx.arc( - item.x + item.width / 2, - item.y + item.height / 2, - item.width / 2, - 0, - Math.PI * 2 - ); - ctx.fill(); - }); -} - -function drawScore() { - ctx.fillStyle = "white"; - ctx.font = "24px Arial"; - ctx.fillText(`Score: ${score}`, 20, 40); // Score at top-left corner -} - -function drawAmmo() { - ctx.fillStyle = "white"; - ctx.font = "24px Arial"; - ctx.fillText(`Ammo: ${ammo}`, 20, 70); // Ammo at top-left corner -} - -function drawGameOver() { - if (isGameOver) { - ctx.fillStyle = "white"; - ctx.font = "40px Arial"; - ctx.textAlign = "center"; - ctx.fillText("Game Over!", canvas.width / 2, canvas.height / 2 - 40); - ctx.font = "24px Arial"; - ctx.fillText(`Total Score: ${score}`, canvas.width / 2, canvas.height / 2); - ctx.fillText( - `Bullets Fired: ${totalBulletsFired}`, - canvas.width / 2, - canvas.height / 2 + 40 - ); - ctx.fillText( - 'Press "R" to Restart', - canvas.width / 2, - canvas.height / 2 + 80 - ); - } -} - -// Restart game -function restartGame() { - window.location.reload(); -} - -// Main game loop -function gameLoop() { - ctx.clearRect(0, 0, canvas.width, canvas.height); - - if (!isGameOver) { - updatePlayer(); - updateBullets(); - updateAsteroids(); - updateItems(); - checkCollisions(); - } - - drawPlayer(); - drawBullets(); - drawAsteroids(); - drawItems(); - drawScore(); - drawAmmo(); - drawGameOver(); - - if (!isGameOver) { - if (Math.random() < 0.01) createAsteroid(); // 1% chance every frame to spawn an asteroid - if (Math.random() < 0.005) createItem(); // 0.5% chance to spawn an item - } - - requestAnimationFrame(gameLoop); -} - -// Start game loop -gameLoop(); diff --git a/secret/guessMyNumber/game.js b/secret/guessMyNumber/game.js deleted file mode 100644 index 9a3436d..0000000 --- a/secret/guessMyNumber/game.js +++ /dev/null @@ -1,65 +0,0 @@ -"use strict"; - -const targetNum = Math.trunc(Math.random() * 20) + 1; -let highScore = Number(localStorage.getItem("highscore")) || 0; -let userGuess = 10; // Default guess -let currScore = 20; - -const screenEl = document.querySelector(".screen"); -const msgEl = document.querySelector(".message"); -const guessInput = document.querySelector("#guess"); -const scoreEl = document.querySelector(".score"); -const highScoreEl = document.querySelector(".highScore"); -const checkBtn = document.querySelector("#check"); -const restartBtn = document.querySelector("#restart"); -const incBtn = document.querySelector("#up"); -const decBtn = document.querySelector("#down"); - -const setMsg = (msg) => (msgEl.textContent = msg); -const setScore = (score) => - (scoreEl.textContent = `Score: ${(currScore = score)}`); -const setHighScore = () => { - highScoreEl.textContent = `Highscore: ${highScore}`; - localStorage.setItem("highscore", highScore); -}; -const changeColor = (color) => (screenEl.style.backgroundColor = color); - -checkBtn.addEventListener("click", () => { - userGuess = Number(guessInput.textContent); - if (!userGuess || userGuess < 1 || userGuess > 20) { - setMsg("Please enter a valid number between 1 and 20."); - } else if (userGuess === targetNum) { - highScore = Math.max(highScore, currScore); - setHighScore(); - setMsg( - currScore !== 20 ? "Correct Number!" : "Are you sure you didn't cheat?" - ); - changeColor(currScore !== 20 ? "#1ba100" : "#FFC300"); - } else { - setMsg(userGuess > targetNum ? "Too High!" : "Too Low!"); - if (currScore > 1) { - setScore(currScore - 1); - } else { - setScore(1); - setMsg("You lost the game!"); - changeColor("#a10000"); - } - } -}); - -restartBtn.addEventListener("click", () => location.reload()); -incBtn.addEventListener( - "click", - () => - (guessInput.textContent = Math.min(Number(guessInput.textContent) + 1, 20)) -); -decBtn.addEventListener( - "click", - () => - (guessInput.textContent = Math.max(Number(guessInput.textContent) - 1, 1)) -); - -guessInput.textContent = userGuess; -setMsg("Guess a number"); -setScore(currScore); -setHighScore(); diff --git a/secret/guessMyNumber/index.html b/secret/guessMyNumber/index.html deleted file mode 100644 index 4e88eaa..0000000 --- a/secret/guessMyNumber/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - Guess My Number - - - - - - - -
- -
-
-

Guess My Number - Game

-

-
- -
-

-

- -
-

Description

-

Guess a number between 1 and 20

-

A = check

-

B = Reload

-

▲ = increases guess by one

-

▼ = decreases guess by one

-
-
-
- - -
- -
- - -
- - -
- - -
- - -
-
-
- - - - diff --git a/secret/guessMyNumber/styles.css b/secret/guessMyNumber/styles.css deleted file mode 100644 index 3a50aec..0000000 --- a/secret/guessMyNumber/styles.css +++ /dev/null @@ -1,189 +0,0 @@ -/* Base Reset */ -body, -html { - margin: 0; - padding: 0; - font-family: monospace; - background-color: #3a2d56; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; -} - -/* GameBoy Layout */ -.gameboy { - background-color: #5f4c82; /* Game Boy Color purple shell */ - width: 441px; - height: 735px; - border-radius: 20px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.6); - display: flex; - flex-direction: column; - align-items: center; - padding: 10px; - position: relative; -} - -@media (max-width: 768px) { - .gameboy { - width: 100vw; - height: 100vh; - border-radius: 0; - } -} - -/* Screen */ -.screen { - background-color: #306230; /* Game Boy green screen */ - border: 4px solid #0f380f; - width: 90%; - height: 55%; - margin-top: 20px; - border-radius: 10px; - display: flex; - justify-content: center; - align-items: center; - box-shadow: inset 0 4px 8px rgba(0, 0, 0, 0.5); - overflow: hidden; -} - -.game { - text-align: center; - width: 90%; -} - -/* Titles */ -h1 { - font-size: 2rem; /* Increased font size */ - margin-bottom: 10px; - text-transform: uppercase; -} - -/* Guess Display */ -.guess-display { - background-color: #9bbc0f; - color: #0f380f; - border: 2px solid #0f380f; - font-size: 2rem; /* Increased font size */ - width: 80px; /* Increased width */ - text-align: center; - margin: 10px auto; - padding: 10px; /* Increased padding */ - border-radius: 4px; -} - -/* Messages */ -.message, -.score, -.highScore { - font-size: 1.4rem; /* Increased font size */ - margin: 5px 0; -} - -.description, -.description p { - font-size: 1.2rem; - margin: 0 auto; - padding: 0 auto; -} - -/* Controls Section */ -.controls { - margin-top: 20px; - display: flex; - justify-content: space-between; - width: 80%; - align-items: center; -} - -/* D-Pad */ -.dpad { - position: relative; - width: 120px; /* Increased size */ - height: 120px; /* Increased size */ -} - -/* Base Styling for D-Pad Buttons */ -.dpad-btn { - background-color: #0f380f; - color: #9bbc0f; - border: none; - border-radius: 5px; - position: absolute; - width: 42px; - height: 42px; - font-size: 1.5rem; /* Increased size */ - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - z-index: 1; -} - -.dpad-btn.up { - top: 0; - left: 50%; - transform: translateX(-50%); -} - -.dpad-btn.down { - bottom: 0; - left: 50%; - transform: translateX(-50%); -} - -.dpad-btn.left { - top: 50%; - left: 0; - transform: translateY(-50%); -} - -.dpad-btn.right { - top: 50%; - right: 0; - transform: translateY(-50%); -} - -/* D-Pad Center to Connect Buttons */ -.dpad-center { - background-color: #0f380f; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 40px; - height: 40px; - border: 2px solid #9cbc0f00; - z-index: 0; - border-radius: 5px; -} - -/* A and B Buttons */ -.action-buttons { - display: flex; - flex-direction: column; - justify-content: space-between; - height: 140px; /* Increased height */ -} - -.btn { - background-color: #0f380f; - color: #9bbc0f; - border: 2px solid #9bbc0f; - border-radius: 50%; - width: 60px; - height: 60px; - font-size: 1.8rem; /* Increased font size */ - cursor: pointer; - transition: transform 0.1s, background-color 0.2s; -} - -.btn:hover { - background-color: #9bbc0f; - color: #0f380f; -} - -.btn:active { - transform: scale(0.9); -} diff --git a/secret/guessMyNumber/styles.js b/secret/guessMyNumber/styles.js deleted file mode 100644 index 8ccae52..0000000 --- a/secret/guessMyNumber/styles.js +++ /dev/null @@ -1,148 +0,0 @@ -"use strict"; -const left = document.querySelector("#left"); -const right = document.querySelector("#right"); -const gameboy = document.querySelector(".gameboy"); -const html = document.documentElement; -const body = document.body; -const screen = document.querySelector(".screen"); -const dpadButtons = document.querySelectorAll(".dpad-btn"); -const dpadCenter = document.querySelector(".dpad-center"); // Darker variant -const actionButtons = document.querySelectorAll(".btn"); - -const colors = [ - { - gameboyColor: "#B39DDB", - htmlColor: "#D1C4E9", - screenColor: "#E1BEE7", - buttonColor: "#673AB7", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#5E35B1", - }, - { - gameboyColor: "#FFC107", - htmlColor: "#FFF9C4", - screenColor: "#FFEB3B", - buttonColor: "#FF9800", - buttonTextColor: "#000000", - dpadCenterColor: "#EF6C00", - }, - { - gameboyColor: "#8BC34A", - htmlColor: "#C5E1A5", - screenColor: "#A5D6A7", - buttonColor: "#FF5722", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#E64A19", - }, - { - gameboyColor: "#F44336", - htmlColor: "#FFCDD2", - screenColor: "#EF9A9A", - buttonColor: "#E91E63", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#C2185B", - }, - { - gameboyColor: "#03A9F4", - htmlColor: "#BBDEFB", - screenColor: "#90CAF9", - buttonColor: "#FFEB3B", - buttonTextColor: "#000000", - dpadCenterColor: "#0277BD", - }, - { - gameboyColor: "#FF7043", - htmlColor: "#FFCCBC", - screenColor: "#FFAB91", - buttonColor: "#FF5722", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#D84315", - }, - { - gameboyColor: "#9C27B0", - htmlColor: "#E1BEE7", - screenColor: "#D1C4E9", - buttonColor: "#7B1FA2", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#6A1B9A", - }, - { - gameboyColor: "#FFD700", - htmlColor: "#FFF9C4", - screenColor: "#FFF59D", - buttonColor: "#FF9800", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#F57F17", - }, - { - gameboyColor: "#009688", - htmlColor: "#B2DFDB", - screenColor: "#80CBC4", - buttonColor: "#4CAF50", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#00796B", - }, - { - gameboyColor: "#795548", - htmlColor: "#D7CCC8", - screenColor: "#A1887F", - buttonColor: "#9E9E9E", - buttonTextColor: "#000000", - dpadCenterColor: "#5D4037", - }, - { - gameboyColor: "#FF5733", - htmlColor: "#FFCCCB", - screenColor: "#FFABAB", - buttonColor: "#C70039", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#B71C1C", - }, - { - gameboyColor: "#00BCD4", - htmlColor: "#B2EBF2", - screenColor: "#80DEEA", - buttonColor: "#00ACC1", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#00838F", - }, -]; - -let currentColorIndex = localStorage.getItem("gameboyColorIndex") - ? parseInt(localStorage.getItem("gameboyColorIndex")) - : 0; - -function updateGameBoyColor() { - gameboy.style.backgroundColor = colors[currentColorIndex].gameboyColor; - html.style.backgroundColor = colors[currentColorIndex].htmlColor; - body.style.backgroundColor = colors[currentColorIndex].htmlColor; - screen.style.backgroundColor = colors[currentColorIndex].screenColor; - - dpadButtons.forEach((button) => { - button.style.backgroundColor = colors[currentColorIndex].buttonColor; - button.style.color = colors[currentColorIndex].buttonTextColor; - }); - - // Using darker dpad center color - dpadCenter.style.backgroundColor = colors[currentColorIndex].dpadCenterColor; - dpadCenter.style.color = colors[currentColorIndex].buttonTextColor; - - actionButtons.forEach((button) => { - button.style.backgroundColor = colors[currentColorIndex].buttonColor; - button.style.color = colors[currentColorIndex].buttonTextColor; - }); -} - -left.addEventListener("click", () => { - currentColorIndex = (currentColorIndex - 1 + colors.length) % colors.length; - localStorage.setItem("gameboyColorIndex", currentColorIndex); - updateGameBoyColor(); -}); - -right.addEventListener("click", () => { - currentColorIndex = (currentColorIndex + 1) % colors.length; - localStorage.setItem("gameboyColorIndex", currentColorIndex); - updateGameBoyColor(); -}); - -updateGameBoyColor(); diff --git a/secret/images/asteroid.png b/secret/images/asteroid.png deleted file mode 100644 index 2859780..0000000 Binary files a/secret/images/asteroid.png and /dev/null differ diff --git a/secret/images/background.jpg b/secret/images/background.jpg deleted file mode 100644 index 63f85fe..0000000 Binary files a/secret/images/background.jpg and /dev/null differ diff --git a/secret/images/blackjack.jpg b/secret/images/blackjack.jpg deleted file mode 100644 index b20ee37..0000000 Binary files a/secret/images/blackjack.jpg and /dev/null differ diff --git a/secret/images/default.jpeg b/secret/images/default.jpeg deleted file mode 100644 index 610df27..0000000 Binary files a/secret/images/default.jpeg and /dev/null differ diff --git a/secret/images/endless_runner.png b/secret/images/endless_runner.png deleted file mode 100644 index 5d153d7..0000000 Binary files a/secret/images/endless_runner.png and /dev/null differ diff --git a/secret/images/minesweeper.png b/secret/images/minesweeper.png deleted file mode 100644 index e7d7376..0000000 Binary files a/secret/images/minesweeper.png and /dev/null differ diff --git a/secret/images/number.jpeg b/secret/images/number.jpeg deleted file mode 100644 index c6dbdd3..0000000 Binary files a/secret/images/number.jpeg and /dev/null differ diff --git a/secret/images/snake.png b/secret/images/snake.png deleted file mode 100644 index 572f201..0000000 Binary files a/secret/images/snake.png and /dev/null differ diff --git a/secret/images/solitaire.png b/secret/images/solitaire.png deleted file mode 100644 index 6393bde..0000000 Binary files a/secret/images/solitaire.png and /dev/null differ diff --git a/secret/index.html b/secret/index.html deleted file mode 100644 index dc45d69..0000000 --- a/secret/index.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - Secret Game Collection - - - - - - - -
-

Secret Game Collection

-
- -
- -
- -
-

© 2025 Game Collection

-
- - diff --git a/secret/mineSweeper/index.html b/secret/mineSweeper/index.html deleted file mode 100644 index 5794679..0000000 --- a/secret/mineSweeper/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - Minesweeper - - - - - - - - -
-

Minesweeper

- - - - - - - -
- -
- -
- - - - diff --git a/secret/mineSweeper/script.js b/secret/mineSweeper/script.js deleted file mode 100644 index f30f685..0000000 --- a/secret/mineSweeper/script.js +++ /dev/null @@ -1,192 +0,0 @@ -document.getElementById("startGame").addEventListener("click", function () { - const gridSize = parseInt(document.getElementById("gridSize").value); - const bombs = parseInt(document.getElementById("bombs").value); - - document.getElementById("settings").style.display = "none"; - document.getElementById("game").style.display = "block"; - - renderGame(gridSize, bombs); -}); - -const canvas = document.getElementById("game"); -const ctx = canvas.getContext("2d"); - -class Minesweeper { - constructor(width, height, bombs) { - this.size = 25; - this.field = new Array(width); - this.bombs = new Array(width); - for (let x = 0; x < this.field.length; x++) { - this.field[x] = new Array(height); - this.bombs[x] = new Array(height); - for (let y = 0; y < this.field[x].length; y++) { - this.field[x][y] = 1; - this.bombs[x][y] = false; - } - } - - this.bombAmount = - bombs > (width * height) / 2 ? (width * height) / 2 : bombs; - this.width = width; - this.height = height; - this.firstClick = false; - this.drawField(); - } - - generateBombs() { - for (let i = 0; i < this.bombAmount; i++) { - let x = Math.floor(Math.random() * this.width); - let y = Math.floor(Math.random() * this.height); - this.bombs[x][y] || this.field[x][y] == 0 - ? i-- - : (this.bombs[x][y] = true); - } - this.firstClick = true; - } - - getNearbyBombs(x, y) { - let counter = 0; - for (let newX = x - 1; newX <= x + 1; newX++) { - for (let newY = y - 1; newY <= y + 1; newY++) { - if ( - newX < this.field.length && - newX >= 0 && - newY < this.field[0].length && - newY >= 0 - ) { - this.bombs[newX][newY] ? counter++ : {}; - } - } - } - return counter; - } - - checkWin() { - for (let x = 0; x < this.field.length; x++) { - for (let y = 0; y < this.field[x].length; y++) { - if (this.field[x][y] != 0 && !this.bombs[x][y]) { - return; - } else if (this.field[x][y] == 0 && this.bombs[x][y]) { - alert(`[ERROR]: Square (${x}|${y}) should not be a bomb!`); - this.bombs[x][y] = false; - } - } - } - this.drawField(); - alert("You won!"); - window.location.reload(); - } - - markSquare(x, y) { - if (x < this.field.length && y < this.field[0].length) { - switch (this.field[x][y]) { - case 1: - this.field[x][y]++; - break; - case 2: - this.field[x][y]++; - break; - case 3: - this.field[x][y] = 1; - break; - default: - break; - } - this.drawField(); - } - } - - uncoverSquare(x, y) { - if (x < this.field.length && x >= 0 && y < this.field[0].length && y >= 0) { - if (this.bombs[x][y] && this.field[x][y] == 1) { - alert("You lost!"); - window.location.reload(); - } else if (this.field[x][y] == 1) { - this.field[x][y] = 0; - !this.firstClick ? this.generateBombs() : {}; - if (this.getNearbyBombs(x, y) == 0) { - for (let newX = x - 1; newX <= x + 1; newX++) { - for (let newY = y - 1; newY <= y + 1; newY++) { - if ( - newX < this.field.length && - newX >= 0 && - newY < this.field[0].length && - newY >= 0 - ) { - this.field[newX][newY] == 1 - ? this.uncoverSquare(newX, newY) - : {}; - } - } - } - } - } - this.checkWin(); - this.drawField(); - } - } - - drawSquare(x, y, type) { - ctx.lineWidth = 3; - let uncovered = (x + y) % 2 === 0 ? "#D3D3D3" : "#A9A9A9"; - let covered = (x + y) % 2 === 0 ? "#4CAF50" : "#81C784"; - ctx.fillStyle = type != 0 ? covered : uncovered; - ctx.fillRect(x * this.size, y * this.size, this.size, this.size); - ctx.strokeStyle = "#000"; - ctx.strokeRect(x * this.size, y * this.size, this.size, this.size); - - if (type != 1) { - const fontSize = this.size / 2; - const number = this.getNearbyBombs(x, y); - let finalPrint; - ctx.font = `${fontSize}px sans-serif`; - ctx.fillStyle = "#000"; - type == 0 ? (finalPrint = number ? number : " ") : {}; - type == 2 ? (finalPrint = "🚩") : {}; - type == 3 ? (finalPrint = "❓") : {}; - ctx.fillText( - finalPrint, - x * this.size + fontSize / (type == 0 ? 1.5 : 1.8), - y * this.size + fontSize * 1.3 - ); - } - } - - drawField() { - if (window.innerWidth > window.innerHeight) { - this.size = window.innerHeight / (this.field[0].length + 4); - } else { - this.size = window.innerWidth / (this.field.length + 4); - } - - canvas.width = this.size * this.field.length; - canvas.height = this.size * this.field[0].length; - - const offsetX = (canvas.width - this.field.length * this.size) / 2; - const offsetY = (canvas.height - this.field[0].length * this.size) / 2; - - for (let x = 0; x < this.field.length; x++) { - for (let y = 0; y < this.field[x].length; y++) { - this.drawSquare(x, y, this.field[x][y], offsetX, offsetY); - } - } - } -} - -const renderGame = (gridSize, bombs) => { - let field = new Minesweeper(gridSize, gridSize, bombs); - window.addEventListener("resize", () => field.drawField()); - canvas.addEventListener("click", (event) => { - const rect = canvas.getBoundingClientRect(); - const x = Math.floor((event.clientX - rect.left) / field.size); - const y = Math.floor((event.clientY - rect.top) / field.size); - field.uncoverSquare(x, y); - }); - canvas.addEventListener("contextmenu", (event) => { - event.preventDefault(); - const rect = canvas.getBoundingClientRect(); - const x = Math.floor((event.clientX - rect.left) / field.size); - const y = Math.floor((event.clientY - rect.top) / field.size); - field.markSquare(x, y); - }); -}; diff --git a/secret/mineSweeper/styles.css b/secret/mineSweeper/styles.css deleted file mode 100644 index 8468965..0000000 --- a/secret/mineSweeper/styles.css +++ /dev/null @@ -1,104 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body, -html { - height: 100%; - margin: 0; - font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - background-color: #121212; - color: #e0e0e0; -} - -#settings { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; - margin: auto; - background-color: #1e1e1e; - padding: 40px; - border-radius: 12px; - box-shadow: 0 6px 15px rgba(0, 0, 0, 0.5); - width: 100%; - max-width: 600px; -} - -h1 { - font-size: 2.5em; - margin-bottom: 20px; - color: #007bff; -} - -label { - margin-bottom: 12px; - font-size: 20px; - color: #d1d1d1; -} - -input[type="number"], -input[type="range"], -span { - padding: 12px; - margin-bottom: 20px; - width: 100%; - max-width: 400px; - text-align: center; - border: 1px solid #444; - border-radius: 6px; - background-color: #333; - color: #e0e0e0; - font-size: 18px; - transition: border-color 0.3s ease; -} - -input[type="number"]:focus, -input[type="range"]:focus { - border-color: #007bff; - outline: none; -} - -button { - padding: 12px 24px; - background-color: #007bff; - color: white; - border: none; - border-radius: 6px; - cursor: pointer; - transition: background-color 0.3s ease, transform 0.2s ease; - font-size: 18px; -} - -button:hover { - background-color: #0056b3; - transform: translateY(-2px); -} - -button:active { - transform: translateY(0); -} - -canvas { - display: none; -} - -@media (max-width: 600px) { - #settings { - font-size: 16px; - } - - input[type="number"], - input[type="range"], - button { - width: 90%; - max-width: none; - } -} diff --git a/secret/snake/audio/dead.mp3 b/secret/snake/audio/dead.mp3 deleted file mode 100644 index 414bf65..0000000 Binary files a/secret/snake/audio/dead.mp3 and /dev/null differ diff --git a/secret/snake/audio/down.mp3 b/secret/snake/audio/down.mp3 deleted file mode 100644 index 03533a0..0000000 Binary files a/secret/snake/audio/down.mp3 and /dev/null differ diff --git a/secret/snake/audio/eat.mp3 b/secret/snake/audio/eat.mp3 deleted file mode 100644 index 076198c..0000000 Binary files a/secret/snake/audio/eat.mp3 and /dev/null differ diff --git a/secret/snake/audio/left.mp3 b/secret/snake/audio/left.mp3 deleted file mode 100644 index 4d3d245..0000000 Binary files a/secret/snake/audio/left.mp3 and /dev/null differ diff --git a/secret/snake/audio/right.mp3 b/secret/snake/audio/right.mp3 deleted file mode 100644 index 64408ea..0000000 Binary files a/secret/snake/audio/right.mp3 and /dev/null differ diff --git a/secret/snake/audio/up.mp3 b/secret/snake/audio/up.mp3 deleted file mode 100644 index 97cfbe9..0000000 Binary files a/secret/snake/audio/up.mp3 and /dev/null differ diff --git a/secret/snake/game.js b/secret/snake/game.js deleted file mode 100644 index f94dc2e..0000000 --- a/secret/snake/game.js +++ /dev/null @@ -1,95 +0,0 @@ -"use strict"; - -const cvs = document.getElementById("snake"); -const ctx = cvs.getContext("2d"); -const box = 20; - -let snake = [{ x: 9 * box, y: 10 * box }]; -let food = { - x: Math.floor(Math.random() * 19 + 1) * box, - y: Math.floor(Math.random() * 19 + 1) * box, -}; -let score = 0; -let d; -let game; - -document.addEventListener("keydown", direction); -function direction(event) { - let key = event.keyCode; - if ((key == 37 || key == 65) && d != "RIGHT") d = "LEFT"; - else if ((key == 38 || key == 87) && d != "DOWN") d = "UP"; - else if ((key == 39 || key == 68) && d != "LEFT") d = "RIGHT"; - else if ((key == 40 || key == 83) && d != "UP") d = "DOWN"; -} - -function collision(head, array) { - return array.some((part) => head.x == part.x && head.y == part.y); -} - -function draw() { - ctx.fillStyle = "#0f380f"; - ctx.fillRect(0, 0, cvs.width, cvs.height); - - ctx.fillStyle = "red"; - ctx.fillRect(food.x, food.y, box, box); - - for (let i = 0; i < snake.length; i++) { - ctx.fillStyle = i == 0 ? "lime" : "white"; - ctx.fillRect(snake[i].x, snake[i].y, box, box); - ctx.strokeStyle = "black"; - ctx.strokeRect(snake[i].x, snake[i].y, box, box); - } - - let snakeX = snake[0].x; - let snakeY = snake[0].y; - - if (d == "LEFT") snakeX -= box; - if (d == "UP") snakeY -= box; - if (d == "RIGHT") snakeX += box; - if (d == "DOWN") snakeY += box; - - if (snakeX == food.x && snakeY == food.y) { - score++; - food = { - x: Math.floor(Math.random() * 19 + 1) * box, - y: Math.floor(Math.random() * 19 + 1) * box, - }; - } else { - snake.pop(); - } - - let newHead = { x: snakeX, y: snakeY }; - - if ( - snakeX < 0 || - snakeX >= cvs.width || - snakeY < 0 || - snakeY >= cvs.height || - collision(newHead, snake) - ) { - clearInterval(game); - document.getElementById("restartBtn").style.display = "block"; - return; - } - - snake.unshift(newHead); - - ctx.fillStyle = "white"; - ctx.font = "20px Arial"; - ctx.fillText("Score: " + score, 10, 20); -} - -function restartGame() { - snake = [{ x: 9 * box, y: 10 * box }]; - food = { - x: Math.floor(Math.random() * 19 + 1) * box, - y: Math.floor(Math.random() * 19 + 1) * box, - }; - score = 0; - d = ""; - document.getElementById("restartBtn").style.display = "none"; - game = setInterval(draw, 150); -} - -document.getElementById("restartBtn").addEventListener("click", restartGame); -game = setInterval(draw, 150); diff --git a/secret/snake/img/food.png b/secret/snake/img/food.png deleted file mode 100644 index 921fe78..0000000 Binary files a/secret/snake/img/food.png and /dev/null differ diff --git a/secret/snake/img/ground.png b/secret/snake/img/ground.png deleted file mode 100644 index 218b190..0000000 Binary files a/secret/snake/img/ground.png and /dev/null differ diff --git a/secret/snake/index.html b/secret/snake/index.html deleted file mode 100644 index 7f81ed2..0000000 --- a/secret/snake/index.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - Snake - Game - - - - - - - -
- -
-
-

Snake - Game

-
-

Description

-

Eat as many apples and grow as much as possible

-

◀ or A or arrow left = move left

-

▶ or D or arrow right = move right

-

▲ or W or arrow up = move up

-

▼ or S or arrow down = move down

-
- -
-
- - -
- -
- - -
- - -
- - -
- - - -
-
-
- - - - diff --git a/secret/snake/styles.css b/secret/snake/styles.css deleted file mode 100644 index 2454d67..0000000 --- a/secret/snake/styles.css +++ /dev/null @@ -1,238 +0,0 @@ -/* Base Reset */ -body, -html { - margin: 0; - padding: 0; - font-family: monospace; - background-color: #3a2d56; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; -} - -/* GameBoy Layout */ -.gameboy { - background-color: #5f4c82; - width: 441px; - height: 735px; - border-radius: 20px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.6); - display: flex; - flex-direction: column; - align-items: center; - padding: 10px; - position: relative; -} - -@media (max-width: 768px) { - .gameboy { - width: 100vw; - height: 100vh; - border-radius: 0; - } -} - -/* Screen */ -.screen { - background-color: black; - border: 4px solid #0f380f; - width: 90%; - height: 55%; - margin-top: 20px; - border-radius: 10px; - display: flex; - justify-content: center; - align-items: center; - box-shadow: inset 0 4px 8px rgba(0, 0, 0, 0.5); - overflow: hidden; -} - -.game { - text-align: center; - width: 90%; -} - -/* Titles */ -h1 { - font-size: 2rem; - margin-bottom: 10px; - text-transform: uppercase; - color: #9bbc0f; -} - -.description, -.description p { - font-size: 1.2rem; - margin: 0 auto; - padding: 0 auto; - color: white; -} - -/* Grid container */ -#grid { - display: grid; - grid-template-columns: repeat(10, 1fr); /* Adjust to match gridSize */ - grid-template-rows: repeat(10, 1fr); /* Adjust to match gridSize */ - width: 400px; /* Adjust as needed */ - height: 400px; /* Adjust as needed */ - border: 2px solid #0f380f; - margin: 20px auto; - /* initially hide */ - display: none; -} - -/* Individual cells */ -.cell { - width: 100%; - height: 100%; -} - -.cell.light-green { - background-color: #9bbc0f; -} - -.cell.dark-green { - background-color: #0f380f; -} - -/* Snake styling */ -.snake { - background-color: #e600ff; /* Snake color */ - z-index: 1000; -} - -/* Apple styling */ -.apple { - background-color: red; /* Apple color */ - z-index: 999; -} - -/* Controls Section */ -.controls { - margin-top: 20px; - display: flex; - justify-content: space-between; - width: 80%; - align-items: center; -} - -/* D-Pad */ -.dpad { - position: relative; - width: 120px; - height: 120px; -} - -/* Base Styling for D-Pad Buttons */ -.dpad-btn { - background-color: #0f380f; - color: #9bbc0f; - border: none; - border-radius: 5px; - position: absolute; - width: 42px; - height: 42px; - font-size: 1.5rem; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - z-index: 1; -} - -.dpad-btn.up { - top: 0; - left: 50%; - transform: translateX(-50%); -} - -.dpad-btn.down { - bottom: 0; - left: 50%; - transform: translateX(-50%); -} - -.dpad-btn.left { - top: 50%; - left: 0; - transform: translateY(-50%); -} - -.dpad-btn.right { - top: 50%; - right: 0; - transform: translateY(-50%); -} - -/* D-Pad Center to Connect Buttons */ -.dpad-center { - background-color: #0f380f; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 40px; - height: 40px; - border: 2px solid transparent; - z-index: 0; - border-radius: 5px; -} - -/* A and B Buttons */ -.action-buttons { - display: flex; - flex-direction: column; - justify-content: space-between; - height: 200px; -} - -.btn { - background-color: #0f380f; - color: #9bbc0f; - border: 2px solid #9bbc0f; - border-radius: 50%; - width: 60px; - height: 60px; - font-size: 1.8rem; - cursor: pointer; - transition: transform 0.1s, background-color 0.2s; -} - -.btn:hover { - background-color: #9bbc0f; - color: #0f380f; -} - -.btn:active { - transform: scale(0.9); -} - -/* Start Button */ -.start-btn { - background-color: #0f380f; - color: #9bbc0f; - border: 2px solid #9bbc0f; - border-radius: 5px; - width: 100px; - height: 40px; - font-size: 1.2rem; - cursor: pointer; - transition: transform 0.1s, background-color 0.2s; - margin-bottom: 20px; -} - -.start-btn:hover { - background-color: #9bbc0f; - color: #0f380f; -} - -.start-btn:active { - transform: scale(0.9); -} - -/* Hidden Canvas for Debugging or Fallback */ -canvas { - display: none; - z-index: 1000; -} diff --git a/secret/snake/styles.js b/secret/snake/styles.js deleted file mode 100644 index 231d5b3..0000000 --- a/secret/snake/styles.js +++ /dev/null @@ -1,134 +0,0 @@ -"use strict"; -const aBtn = document.querySelector("#a"); -const bBtn = document.querySelector("#b"); -const gameboy = document.querySelector(".gameboy"); -const html = document.documentElement; -const body = document.body; -const dpadButtons = document.querySelectorAll(".dpad-btn"); -const dpadCenter = document.querySelector(".dpad-center"); // Darker variant -const actionButtons = document.querySelectorAll(".btn"); - -const colors = [ - { - gameboyColor: "#B39DDB", - htmlColor: "#D1C4E9", - buttonColor: "#673AB7", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#5E35B1", - }, - { - gameboyColor: "#FFC107", - htmlColor: "#FFF9C4", - buttonColor: "#FF9800", - buttonTextColor: "#000000", - dpadCenterColor: "#EF6C00", - }, - { - gameboyColor: "#8BC34A", - htmlColor: "#C5E1A5", - buttonColor: "#FF5722", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#E64A19", - }, - { - gameboyColor: "#F44336", - htmlColor: "#FFCDD2", - buttonColor: "#E91E63", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#C2185B", - }, - { - gameboyColor: "#03A9F4", - htmlColor: "#BBDEFB", - buttonColor: "#FFEB3B", - buttonTextColor: "#000000", - dpadCenterColor: "#0277BD", - }, - { - gameboyColor: "#FF7043", - htmlColor: "#FFCCBC", - buttonColor: "#FF5722", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#D84315", - }, - { - gameboyColor: "#9C27B0", - htmlColor: "#E1BEE7", - buttonColor: "#7B1FA2", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#6A1B9A", - }, - { - gameboyColor: "#FFD700", - htmlColor: "#FFF9C4", - buttonColor: "#FF9800", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#F57F17", - }, - { - gameboyColor: "#009688", - htmlColor: "#B2DFDB", - buttonColor: "#4CAF50", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#00796B", - }, - { - gameboyColor: "#795548", - htmlColor: "#D7CCC8", - buttonColor: "#9E9E9E", - buttonTextColor: "#000000", - dpadCenterColor: "#5D4037", - }, - { - gameboyColor: "#FF5733", - htmlColor: "#FFCCCB", - buttonColor: "#C70039", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#B71C1C", - }, - { - gameboyColor: "#00BCD4", - htmlColor: "#B2EBF2", - buttonColor: "#00ACC1", - buttonTextColor: "#FFFFFF", - dpadCenterColor: "#00838F", - }, -]; - -let currentColorIndex = localStorage.getItem("gameboyColorIndex") - ? parseInt(localStorage.getItem("gameboyColorIndex")) - : 0; - -function updateGameBoyColor() { - gameboy.style.backgroundColor = colors[currentColorIndex].gameboyColor; - html.style.backgroundColor = colors[currentColorIndex].htmlColor; - body.style.backgroundColor = colors[currentColorIndex].htmlColor; - - dpadButtons.forEach((button) => { - button.style.backgroundColor = colors[currentColorIndex].buttonColor; - button.style.color = colors[currentColorIndex].buttonTextColor; - }); - - // Using darker dpad center color - dpadCenter.style.backgroundColor = colors[currentColorIndex].dpadCenterColor; - dpadCenter.style.color = colors[currentColorIndex].buttonTextColor; - - actionButtons.forEach((button) => { - button.style.backgroundColor = colors[currentColorIndex].buttonColor; - button.style.color = colors[currentColorIndex].buttonTextColor; - }); -} - -aBtn.addEventListener("click", () => { - currentColorIndex = (currentColorIndex - 1 + colors.length) % colors.length; - localStorage.setItem("gameboyColorIndex", currentColorIndex); - updateGameBoyColor(); -}); - -bBtn.addEventListener("click", () => { - currentColorIndex = (currentColorIndex + 1) % colors.length; - localStorage.setItem("gameboyColorIndex", currentColorIndex); - updateGameBoyColor(); -}); - -updateGameBoyColor(); diff --git a/secret/snake/test.html b/secret/snake/test.html deleted file mode 100644 index 12a5cfb..0000000 --- a/secret/snake/test.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Snake Game - GameBoy Style - - - -
-

Snake Game

-
- -
- -
- - - - diff --git a/secret/styles.css b/secret/styles.css deleted file mode 100644 index b25a85c..0000000 --- a/secret/styles.css +++ /dev/null @@ -1,145 +0,0 @@ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: "Courier New", Courier, monospace; - background-color: #0d0d0d; - color: #b0b0b0; - margin: 0; - line-height: 1.6; - background-image: url("images/background.jpg"); - background-size: cover; /* Adjust size for tape appearance */ -} - -header { - background-color: #222; /* Fully opaque background */ - color: #b0b0b0; - text-align: center; - padding: 1em 0; - font-size: 2rem; - text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7); - animation: neonFlicker 1.5s infinite; -} - -/* Create the flickering neon light effect */ -@keyframes neonFlicker { - 0% { - text-shadow: 0 0 5px #ffcc00, 0 0 10px #ffcc00, 0 0 15px #ffcc00, - 0 0 20px #ffcc00, 0 0 30px #ffcc00, 0 0 40px #ffcc00, 0 0 50px #ffcc00; - } - 20% { - text-shadow: 0 0 3px #ffcc00, 0 0 7px #ffcc00, 0 0 10px #ffcc00, - 0 0 15px #ffcc00, 0 0 20px #ffcc00; - } - 40% { - text-shadow: 0 0 5px #ffcc00, 0 0 15px #ffcc00, 0 0 25px #ffcc00; - } - 60% { - text-shadow: 0 0 5px #ffcc00, 0 0 10px #ffcc00, 0 0 15px #ffcc00, - 0 0 20px #ffcc00, 0 0 30px #ffcc00; - } - 80% { - text-shadow: 0 0 3px #ffcc00, 0 0 7px #ffcc00, 0 0 10px #ffcc00; - } - 100% { - text-shadow: 0 0 5px #ffcc00, 0 0 10px #ffcc00, 0 0 15px #ffcc00, - 0 0 20px #ffcc00, 0 0 30px #ffcc00, 0 0 40px #ffcc00; - } -} - -footer { - background-color: #111; - color: #b0b0b0; - text-align: center; - padding: 1em 0; - margin-top: 20px; -} - -.grid-container { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 20px; - padding: 20px; -} - -.item { - position: relative; - background-color: #1a1a1a; - border-radius: 10px; - overflow: hidden; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.8); - transition: transform 0.3s ease, box-shadow 0.3s ease, filter 0.3s ease; - width: 100%; - height: 400px; - display: flex; - flex-direction: column; -} - -.item img { - width: 100%; - height: 100%; - object-fit: cover; - filter: brightness(0.6); -} - -.item .description { - padding: 30px; - font-size: 1rem; - color: #ccc; - background-color: rgba(0, 0, 0, 0.8); - border-radius: 0 0 10px 10px; - flex-grow: 1; -} - -p { - text-decoration: none; -} - -.item:hover { - transform: scale(1.05); - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.9); - filter: brightness(1.1); -} - -.item:hover img { - transform: scale(1.1); - filter: brightness(1.1); -} - -.item h2 { - position: absolute; - top: 10%; - left: 50%; - transform: translateX(-50%); - color: #ffffff; - font-size: 1.8rem; - background-color: rgba(0, 0, 0, 0.9); - padding: 5px 15px; - border-radius: 5px; - text-align: center; - opacity: 0; - transition: opacity 0.3s ease, transform 0.3s ease; -} - -.item:hover h2 { - opacity: 1; - transform: translateX(-50%) translateY(-10px); -} - -@media (max-width: 800px) { - header { - font-size: 1.5rem; - } - - .item { - height: auto; - width: auto; - } - - .grid-container { - grid-template-columns: repeat(1, 1fr); - } -} diff --git a/src/favicon/android-chrome-192x192.png b/src/favicon/android-chrome-192x192.png new file mode 100644 index 0000000..e636383 Binary files /dev/null and b/src/favicon/android-chrome-192x192.png differ diff --git a/src/favicon/android-chrome-512x512.png b/src/favicon/android-chrome-512x512.png new file mode 100644 index 0000000..65f6ef4 Binary files /dev/null and b/src/favicon/android-chrome-512x512.png differ diff --git a/src/favicon/apple-touch-icon.png b/src/favicon/apple-touch-icon.png new file mode 100644 index 0000000..42de221 Binary files /dev/null and b/src/favicon/apple-touch-icon.png differ diff --git a/src/favicon/favicon-16x16.png b/src/favicon/favicon-16x16.png new file mode 100644 index 0000000..e736fae Binary files /dev/null and b/src/favicon/favicon-16x16.png differ diff --git a/src/favicon/favicon-32x32.png b/src/favicon/favicon-32x32.png new file mode 100644 index 0000000..74501cd Binary files /dev/null and b/src/favicon/favicon-32x32.png differ diff --git a/src/favicon/favicon.ico b/src/favicon/favicon.ico new file mode 100644 index 0000000..4de4913 Binary files /dev/null and b/src/favicon/favicon.ico differ diff --git a/images/Patrick.png b/src/images/Patrick.png similarity index 100% rename from images/Patrick.png rename to src/images/Patrick.png diff --git a/images/sage.png b/src/images/sage.png similarity index 100% rename from images/sage.png rename to src/images/sage.png diff --git a/src/js/animation/Meteor.js b/src/js/animation/Meteor.js new file mode 100644 index 0000000..a141e80 --- /dev/null +++ b/src/js/animation/Meteor.js @@ -0,0 +1,311 @@ +class Meteor { + constructor(container) { + this.element = document.createElement("div"); + this.element.style.position = "absolute"; + this.container = container; + this.speed = Math.random() * 3 + 4; + this.life = 1.0; + this.particles = []; + + this.colorType = Math.floor(Math.random() * 4); + this.colors = this.getMeteorColors(); + + this.containerRect = container.getBoundingClientRect(); + + // Start from random edge with PIXEL-based positioning + const edge = Math.floor(Math.random() * 4); + switch (edge) { + case 0: + // Top + this.x = Math.random() * this.containerRect.width; + this.y = -20; + case 1: + // Right + this.x = this.containerRect.width + 20; + this.y = Math.random() * this.containerRect.height; + case 2: + // Bottom + this.x = Math.random() * this.containerRect.width; + this.y = this.containerRect.height + 20; + case 3: + // Left + this.x = -20; + this.y = Math.random() * this.containerRect.height; + default: + console.log("Error creating Meteor direction"); + } + + const centerX = this.containerRect.width / 2 + (Math.random() - 0.5) * 200; + const centerY = this.containerRect.height / 2 + (Math.random() - 0.5) * 200; + this.angle = + Math.atan2(centerY - this.y, centerX - this.x) + + (Math.random() - 0.5) * 0.8; + this.dx = Math.cos(this.angle) * this.speed; + this.dy = Math.sin(this.angle) * this.speed; + + this.init(); + } + + getMeteorColors() { + const colorSchemes = [ + { + head: "rgba(255, 255, 255, 1)", + core: "rgba(255, 230, 150, 0.9)", + mid: "rgba(255, 180, 80, 0.7)", + outer: "rgba(255, 100, 50, 0.5)", + glow: "rgba(255, 200, 100, 0.9)", + }, + { + head: "rgba(255, 255, 255, 1)", + core: "rgba(180, 220, 255, 0.9)", + mid: "rgba(100, 180, 255, 0.7)", + outer: "rgba(50, 100, 255, 0.5)", + glow: "rgba(100, 180, 255, 0.9)", + }, + { + head: "rgba(255, 255, 255, 1)", + core: "rgba(220, 180, 255, 0.9)", + mid: "rgba(200, 100, 255, 0.7)", + outer: "rgba(180, 50, 255, 0.5)", + glow: "rgba(200, 150, 255, 0.9)", + }, + { + head: "rgba(255, 255, 255, 1)", + core: "rgba(180, 255, 200, 0.9)", + mid: "rgba(80, 255, 150, 0.7)", + outer: "rgba(50, 200, 100, 0.5)", + glow: "rgba(150, 255, 180, 0.9)", + }, + ]; + return colorSchemes[this.colorType]; + } + + init() { + const size = Math.random() * 4 + 10; + const colors = this.colors; + + const head = document.createElement("div"); + head.style.width = `${size}px`; + head.style.height = `${size}px`; + head.style.borderRadius = "50%"; + head.style.background = ` + radial-gradient( + circle at 30% 30%, + ${colors.head} 0%, + ${colors.core} 30%, + ${colors.mid} 60%, + ${colors.outer} 100% + ) + `; + head.style.boxShadow = ` + 0 0 ${size * 4}px ${colors.glow}, + 0 0 ${size * 2}px rgba(255, 255, 255, 0.8), + inset 0 0 ${size * 0.5}px rgba(255, 255, 255, 0.9) + `; + head.style.position = "absolute"; + head.style.left = "50%"; + head.style.top = "50%"; + head.style.transform = "translate(-50%, -50%)"; + head.style.zIndex = "3"; + head.style.filter = "blur(0.5px)"; + + // Create multi-layer tail + this.createTailLayer(size * 3, size * 1.2, colors.core, 1, "1px"); + this.createTailLayer(size * 5, size * 2, colors.mid, 0.6, "2px"); + this.createTailLayer(size * 8, size * 3, colors.outer, 0.3, "3px"); + + // Assemble meteor + this.element.appendChild(head); + this.element.style.left = `${this.x}px`; + this.element.style.top = `${this.y}px`; + this.element.style.zIndex = "10"; + this.element.style.filter = "blur(0.5px)"; + + this.head = head; + this.size = size; + + this.container.appendChild(this.element); + + this.createTrailParticles(); + } + + createTailLayer(length, width, color, opacity, blur) { + const tail = document.createElement("div"); + const tailAngle = Math.atan2(this.dy, this.dx) + Math.PI; + + tail.style.width = `${length}px`; + tail.style.height = `${width}px`; + tail.style.position = "absolute"; + tail.style.left = "50%"; + tail.style.top = "50%"; + tail.style.transformOrigin = "left center"; + tail.style.transform = `translate(0, -50%) rotate(${tailAngle}rad)`; + tail.style.background = `linear-gradient(to right, + ${color} 0%, + ${color.replace(")", ", 0.8)").replace("rgba", "rgba")} 20%, + ${color.replace(")", ", 0.4)").replace("rgba", "rgba")} 50%, + ${color.replace(")", ", 0.1)").replace("rgba", "rgba")} 80%, + transparent 100%)`; + tail.style.opacity = opacity; + tail.style.filter = `blur(${blur})`; + tail.style.pointerEvents = "none"; + tail.style.zIndex = "2"; + tail.style.borderRadius = "0 50% 50% 0"; + + this.element.appendChild(tail); + this.tail = tail; + } + + createTrailParticles() { + for (let i = 0; i < 5; i++) { + this.addTrailParticle(); + } + } + + addTrailParticle() { + const particle = document.createElement("div"); + const size = Math.random() * 2 + 1; + const colors = this.colors; + + particle.style.width = `${size}px`; + particle.style.height = `${size}px`; + particle.style.borderRadius = "50%"; + particle.style.background = colors.mid; + particle.style.position = "absolute"; + particle.style.left = `${this.x}px`; + particle.style.top = `${this.y}px`; + particle.style.boxShadow = `0 0 ${size * 3}px ${colors.glow}`; + particle.style.opacity = "0.7"; + particle.style.zIndex = "1"; + particle.style.pointerEvents = "none"; + + this.container.appendChild(particle); + + this.particles.push({ + element: particle, + life: 1.0, + x: this.x, + y: this.y, + vx: (Math.random() - 0.5) * 0.5, + vy: (Math.random() - 0.5) * 0.5, + size: size, + }); + } + + update() { + this.x += this.dx; + this.y += this.dy; + this.life -= 0.005; + + this.element.style.left = `${this.x}px`; + this.element.style.top = `${this.y}px`; + this.element.style.opacity = this.life; + + // Update tail direction + const tailAngle = Math.atan2(this.dy, this.dx) + Math.PI; + const tails = this.element.querySelectorAll("div:not(.particle)"); + tails.forEach((tail) => { + if (tail !== this.head) { + tail.style.transform = `translate(0, -50%) rotate(${tailAngle}rad)`; + tail.style.opacity = this.life; + } + }); + + if (Math.random() < 0.3) { + this.addTrailParticle(); + } + + // Update existing particles with pixel positioning + for (let i = this.particles.length - 1; i >= 0; i--) { + const p = this.particles[i]; + p.life -= 0.02; + p.x += p.vx; + p.y += p.vy; + + p.element.style.left = `${p.x}px`; + p.element.style.top = `${p.y}px`; + p.element.style.opacity = p.life; + p.element.style.transform = `scale(${p.life})`; + + if (p.life <= 0) { + p.element.remove(); + this.particles.splice(i, 1); + } + } + + if ( + this.x < -50 || + this.x > this.containerRect.width + 50 || + this.y < -50 || + this.y > this.containerRect.height + 50 || + this.life <= 0 + ) { + // Fade out particles + this.particles.forEach((p) => { + p.element.style.transition = "opacity 0.5s"; + p.element.style.opacity = "0"; + setTimeout(() => p.element.remove(), 500); + }); + this.remove(); + return false; + } + return true; + } + + remove() { + if (this.life > 0.3) { + this.createExplosion(); + } + + setTimeout(() => { + this.element.remove(); + }, 300); + } + + createExplosion() { + for (let i = 0; i < 8; i++) { + const particle = document.createElement("div"); + const size = Math.random() * 3 + 2; + const colors = this.colors; + + particle.style.width = `${size}px`; + particle.style.height = `${size}px`; + particle.style.borderRadius = "50%"; + particle.style.background = colors.core; + particle.style.position = "absolute"; + particle.style.left = `${this.x}px`; + particle.style.top = `${this.y}px`; + particle.style.boxShadow = `0 0 ${size * 4}px ${colors.glow}`; + particle.style.opacity = "0.8"; + particle.style.zIndex = "2"; + + this.container.appendChild(particle); + + // Animate explosion + const angle = (i / 8) * Math.PI * 2; + const distance = Math.random() * 20 + 10; + const duration = Math.random() * 500 + 500; + + particle.animate( + [ + { + transform: "translate(0, 0) scale(1)", + opacity: 0.8, + }, + { + transform: `translate(${Math.cos(angle) * distance}px, ${ + Math.sin(angle) * distance + }px) scale(0.1)`, + opacity: 0, + }, + ], + { + duration: duration, + easing: "cubic-bezier(0.4, 0, 0.2, 1)", + } + ).onfinish = () => particle.remove(); + } + } +} + +export default Meteor; diff --git a/src/js/animation/Star.js b/src/js/animation/Star.js new file mode 100644 index 0000000..53b21f2 --- /dev/null +++ b/src/js/animation/Star.js @@ -0,0 +1,63 @@ +class Star { + constructor(container) { + this.element = document.createElement("div"); + this.element.classList.add("star"); + this.container = container; + this.speed = Math.random() * 0.5 + 0.1; + + // Random direction angle (0 to 360 degrees) + this.angle = Math.random() * Math.PI * 2; + this.dx = Math.cos(this.angle) * this.speed; + this.dy = Math.sin(this.angle) * this.speed; + + this.x = Math.random() * 100; + this.y = Math.random() * 100; + + this.color = this.getRandomStarColor(); + this.init(); + } + + getRandomStarColor() { + const colors = [ + "rgba(255, 255, 255, 0.9)", // Pure white + "rgba(255, 250, 200, 0.9)", // Warm white + "rgba(200, 220, 255, 0.9)", // Cool blue-white + "rgba(255, 220, 180, 0.9)", // Yellow-white + "rgba(180, 200, 255, 0.9)", // Blue-white + ]; + return colors[Math.floor(Math.random() * colors.length)]; + } + + init() { + const size = Math.random() * 3 + 0.5; + this.element.style.width = `${size}px`; + this.element.style.height = `${size}px`; + this.element.style.left = `${this.x}%`; + this.element.style.top = `${this.y}%`; + this.element.style.background = this.color; + this.element.style.boxShadow = `0 0 ${size * 2}px ${this.color}`; + this.element.style.animationDelay = `${Math.random() * 5}s`; + this.element.style.animationDuration = `${3 + Math.random() * 4}s`; + this.container.appendChild(this.element); + } + + update() { + this.x += this.dx * 0.05; + this.y += this.dy * 0.05; + + // Wrap around when star goes off screen + if (this.y > 100) this.y = 0; + if (this.y < 0) this.y = 100; + if (this.x > 100) this.x = 0; + if (this.x < 0) this.x = 100; + + this.element.style.left = `${this.x}%`; + this.element.style.top = `${this.y}%`; + } + + remove() { + this.element.remove(); + } +} + +export default Star; diff --git a/src/js/animation/starBackground.js b/src/js/animation/starBackground.js new file mode 100644 index 0000000..42b0d0d --- /dev/null +++ b/src/js/animation/starBackground.js @@ -0,0 +1,81 @@ +import Star from "./Star.js"; +import Meteor from "./Meteor.js"; + +const starInstances = []; +const meteorInstances = []; + +function createStars() { + const stars = document.getElementById("stars"); + const count = 400; + stars.innerHTML = ""; + starInstances.length = 0; + + for (let i = 0; i < count; i++) { + const star = new Star(stars); + starInstances.push(star); + } +} + +function injectStarCSS() { + const style = document.createElement("style"); + style.textContent = ` + .star { + position: absolute; + border-radius: 50%; + animation: twinkle ease-in-out infinite; + } + + @keyframes twinkle { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.3; } + } + `; + document.head.appendChild(style); +} + +function trySpawnMeteor() { + const spawnChance = 0.12; + if (Math.random() < spawnChance) { + const stars = document.getElementById("stars"); + const newMeteor = new Meteor(stars); + meteorInstances.push(newMeteor); + } +} + +function animateStars() { + starInstances.forEach((star) => star.update()); + + // Update meteors and remove dead ones + for (let i = meteorInstances.length - 1; i >= 0; i--) { + if (!meteorInstances[i].update()) { + meteorInstances.splice(i, 1); + } + } + + requestAnimationFrame(animateStars); +} + +function createMeteorBurst() { + for (let i = 0; i < 3; i++) { + setTimeout(() => { + const stars = document.getElementById("stars"); + const newMeteor = new Meteor(stars); + meteorInstances.push(newMeteor); + }, i * 200); + } +} + +function init() { + injectStarCSS(); + createStars(); + animateStars(); + + setInterval(trySpawnMeteor, 2000); + setInterval(createMeteorBurst, 15000); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", init); +} else { + init(); +} diff --git a/src/js/form.js b/src/js/form.js new file mode 100644 index 0000000..4dbfa2e --- /dev/null +++ b/src/js/form.js @@ -0,0 +1,22 @@ +// Form submission +function setupForm() { + const form = document.getElementById("contact-form"); + if (form) { + form.addEventListener("submit", function (e) { + e.preventDefault(); + + // Simple form validation + const name = document.getElementById("name").value; + const email = document.getElementById("email").value; + const message = document.getElementById("message").value; + + if (name && email && message) { + // In a real implementation, you would send the form data to a server + alert("Thank you for your message! We will get back to you soon."); + form.reset(); + } else { + alert("Please fill in all required fields."); + } + }); + } +} diff --git a/src/js/main.js b/src/js/main.js new file mode 100644 index 0000000..bd2f14a --- /dev/null +++ b/src/js/main.js @@ -0,0 +1,27 @@ +// Initialize everything when DOM is loaded +document.addEventListener("DOMContentLoaded", function () { + // Initialize components + if (typeof createStars === "function") createStars(); + if (typeof updateNavigation === "function") updateNavigation(); + if (typeof setupForm === "function") setupForm(); + if (typeof setupMobileNavigation === "function") setupMobileNavigation(); + + // Set up event listeners + window.addEventListener("scroll", updateNavigation); + + // Smooth scrolling for navigation links + document.querySelectorAll('a[href^="#"]').forEach((anchor) => { + anchor.addEventListener("click", function (e) { + e.preventDefault(); + const targetId = this.getAttribute("href"); + if (targetId === "#") return; + + const targetElement = document.querySelector(targetId); + if (targetElement) { + targetElement.scrollIntoView({ + behavior: "smooth", + }); + } + }); + }); +}); diff --git a/src/js/navigation.js b/src/js/navigation.js new file mode 100644 index 0000000..974476d --- /dev/null +++ b/src/js/navigation.js @@ -0,0 +1,106 @@ +// Navigation JavaScript +let lastScrollY = window.scrollY; +let ticking = false; + +function updateNavigation() { + const navigation = document.getElementById("navigation"); + const scrolled = window.scrollY > 50; + + if (scrolled) { + navigation.classList.add("scrolled"); + + // Hide/show nav on scroll + if (window.scrollY > lastScrollY && window.scrollY > 100) { + navigation.classList.add("hidden"); + } else { + navigation.classList.remove("hidden"); + } + } else { + navigation.classList.remove("scrolled", "hidden"); + } + + lastScrollY = window.scrollY; + ticking = false; +} + +function requestTick() { + if (!ticking) { + requestAnimationFrame(updateNavigation); + ticking = true; + } +} + +// Mobile navigation functionality +function setupMobileNavigation() { + const burgerMenu = document.getElementById("burger-menu"); + const mainNav = document.getElementById("main-nav"); + const body = document.body; + + // Create overlay for mobile menu + const overlay = document.createElement("div"); + overlay.className = "nav-overlay"; + document.body.appendChild(overlay); + + if (burgerMenu && mainNav) { + burgerMenu.addEventListener("click", function () { + const isActive = mainNav.classList.contains("active"); + + if (isActive) { + // Close menu + mainNav.classList.remove("active"); + burgerMenu.classList.remove("active"); + overlay.classList.remove("active"); + body.classList.remove("nav-open"); + } else { + // Open menu + mainNav.classList.add("active"); + burgerMenu.classList.add("active"); + overlay.classList.add("active"); + body.classList.add("nav-open"); + } + }); + + // Close menu when clicking on overlay + overlay.addEventListener("click", function () { + mainNav.classList.remove("active"); + burgerMenu.classList.remove("active"); + overlay.classList.remove("active"); + body.classList.remove("nav-open"); + }); + + // Close menu when clicking on a link + const navLinks = mainNav.querySelectorAll("a"); + navLinks.forEach((link) => { + link.addEventListener("click", function () { + mainNav.classList.remove("active"); + burgerMenu.classList.remove("active"); + overlay.classList.remove("active"); + body.classList.remove("nav-open"); + + // Update active state + navLinks.forEach((l) => l.classList.remove("active")); + this.classList.add("active"); + }); + }); + + // Set initial active state based on current hash + function setActiveNavLink() { + const currentHash = window.location.hash || "#home"; + navLinks.forEach((link) => { + if (link.getAttribute("href") === currentHash) { + link.classList.add("active"); + } else { + link.classList.remove("active"); + } + }); + } + + // Update active state on hash change + window.addEventListener("hashchange", setActiveNavLink); + setActiveNavLink(); + } +} + +// Initialize navigation +window.addEventListener("scroll", requestTick); +window.addEventListener("load", updateNavigation); diff --git a/src/js/overview.js b/src/js/overview.js new file mode 100644 index 0000000..9dd7bf2 --- /dev/null +++ b/src/js/overview.js @@ -0,0 +1,57 @@ +// Counter animation for stats +document.addEventListener("DOMContentLoaded", function () { + const counters = document.querySelectorAll(".stat-number"); + let hasCounted = false; + + function animateCounters() { + if (hasCounted) return; + + counters.forEach((counter) => { + const target = parseInt(counter.getAttribute("data-count")); + const duration = 2000; // 2 seconds + const frameDuration = 1000 / 60; // 60 frames per second + const totalFrames = Math.round(duration / frameDuration); + let frame = 0; + + const counterInterval = setInterval(() => { + frame++; + const progress = frame / totalFrames; + const currentCount = Math.round(target * progress); + + counter.textContent = currentCount; + + if (frame === totalFrames) { + clearInterval(counterInterval); + } + }, frameDuration); + + counter.classList.add("animated"); + }); + + hasCounted = true; + } + + // Check if element is in viewport + function isInViewport(element) { + const rect = element.getBoundingClientRect(); + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= + (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= (window.innerWidth || document.documentElement.clientWidth) + ); + } + + // Check on scroll and on load + function checkCounters() { + const statsContainer = document.querySelector(".stats-container"); + if (statsContainer && isInViewport(statsContainer)) { + animateCounters(); + window.removeEventListener("scroll", checkCounters); + } + } + + window.addEventListener("scroll", checkCounters); + checkCounters(); // Check on page load +}); diff --git a/src/js/portfolioCard.js b/src/js/portfolioCard.js new file mode 100644 index 0000000..2fd2d79 --- /dev/null +++ b/src/js/portfolioCard.js @@ -0,0 +1,228 @@ +class PortfolioCard extends HTMLElement { + constructor() { + super(); + const shadow = this.attachShadow({ mode: "open" }); + + const icon = this.getAttribute("icon") || "fas fa-code"; + const title = this.getAttribute("title") || "Project Title"; + const desc = this.getAttribute("desc") || "Project description goes here."; + const tags = (this.getAttribute("tags") || "").split(","); + const link = this.getAttribute("link") || "#"; + const collaboration = this.getAttribute("collaboration") || ""; + + shadow.innerHTML = ` + + + + + + + +
+
+ +
+
+

+ ${title} +

+

${desc}

+ ${ + collaboration + ? ` +
+ ${collaboration} +
+ ` + : "" + } +
+ ${tags + .map((tag) => `${tag.trim()}`) + .join("")} +
+
+ +
+ `; + } +} + +customElements.define("portfolio-card", PortfolioCard); diff --git a/src/js/portfolioFilter.js b/src/js/portfolioFilter.js new file mode 100644 index 0000000..7779c87 --- /dev/null +++ b/src/js/portfolioFilter.js @@ -0,0 +1,95 @@ +// Portfolio filtering functionality +document.addEventListener("DOMContentLoaded", function () { + // Get all portfolio items + const portfolioItems = document.querySelectorAll("portfolio-card"); + const filterButtons = document.querySelectorAll(".filter-btn"); + const searchInput = document.getElementById("project-search"); + + // Create a container for no results message + const noResults = document.createElement("div"); + noResults.className = "no-results"; + noResults.innerHTML = ` + +

No projects found

+

Try adjusting your search or filter criteria

+ `; + + // Function to filter portfolio items + function filterPortfolio() { + const activeFilter = + document.querySelector(".filter-btn.active").dataset.filter; + const searchTerm = searchInput.value.toLowerCase(); + let visibleItems = 0; + + portfolioItems.forEach((item) => { + const tags = item.getAttribute("tags").toLowerCase(); + const title = item.getAttribute("title").toLowerCase(); + const desc = item.getAttribute("desc").toLowerCase(); + + // Check if item matches the active filter + const matchesFilter = + activeFilter === "all" || + tags.includes(activeFilter) || + title.includes(activeFilter) || + desc.includes(activeFilter); + + // Check if item matches the search term + const matchesSearch = + searchTerm === "" || + title.includes(searchTerm) || + desc.includes(searchTerm) || + tags.includes(searchTerm); + + // Show or hide the item based on filters + if (matchesFilter && matchesSearch) { + item.style.display = "block"; + visibleItems++; + + // Add animation for appearing items + item.style.animation = "fadeInUp 0.5s ease forwards"; + } else { + item.style.display = "none"; + } + }); + + // Show no results message if needed + const portfolioGrid = document.querySelector(".portfolio-grid"); + const existingNoResults = portfolioGrid.querySelector(".no-results"); + + if (visibleItems === 0) { + if (!existingNoResults) { + portfolioGrid.appendChild(noResults); + } + } else if (existingNoResults) { + portfolioGrid.removeChild(existingNoResults); + } + } + + // Add click event listeners to filter buttons + filterButtons.forEach((button) => { + button.addEventListener("click", function () { + // Remove active class from all buttons + filterButtons.forEach((btn) => btn.classList.remove("active")); + + // Add active class to clicked button + this.classList.add("active"); + + // Filter portfolio items + filterPortfolio(); + }); + }); + + // Add input event listener to search field + searchInput.addEventListener("input", filterPortfolio); + + // Add keyboard shortcut for search (Ctrl/Cmd + F) + document.addEventListener("keydown", function (e) { + if ((e.ctrlKey || e.metaKey) && e.key === "f") { + e.preventDefault(); + searchInput.focus(); + } + }); + + // Initialize filter on page load + filterPortfolio(); +}); diff --git a/src/js/sectionTracker.js b/src/js/sectionTracker.js new file mode 100644 index 0000000..e392724 --- /dev/null +++ b/src/js/sectionTracker.js @@ -0,0 +1,111 @@ +// Section tracking and navigation highlighting +document.addEventListener("DOMContentLoaded", function () { + const sections = document.querySelectorAll("section[id]"); + const navLinks = document.querySelectorAll(".nav-links a"); + + // Configuration + const offset = 100; // Offset for when section becomes "active" (accounts for fixed nav) + let isScrolling = false; + + function getCurrentSection() { + let currentSection = ""; + const scrollPosition = window.scrollY + offset; + + // Find which section we're currently in + sections.forEach((section) => { + const sectionTop = section.offsetTop; + const sectionHeight = section.offsetHeight; + const sectionId = section.getAttribute("id"); + + if ( + scrollPosition >= sectionTop && + scrollPosition < sectionTop + sectionHeight + ) { + currentSection = sectionId; + } + }); + + // Special case: if we're at the very top, activate the first section + if (window.scrollY < 100) { + currentSection = sections[0]?.getAttribute("id") || ""; + } + + return currentSection; + } + + function updateActiveNavLink() { + const currentSection = getCurrentSection(); + + navLinks.forEach((link) => { + const href = link.getAttribute("href"); + + // Remove active class from all links + link.classList.remove("active"); + + // Add active class to matching link + if (href === `#${currentSection}`) { + link.classList.add("active"); + } + }); + } + + // Throttle scroll events for better performance + function handleScroll() { + if (!isScrolling) { + window.requestAnimationFrame(() => { + updateActiveNavLink(); + isScrolling = false; + }); + isScrolling = true; + } + } + + // Listen for scroll events + window.addEventListener("scroll", handleScroll); + + // Update on page load + updateActiveNavLink(); + + // Also update when clicking nav links (for smooth scroll) + navLinks.forEach((link) => { + link.addEventListener("click", function (e) { + // Remove active from all + navLinks.forEach((l) => l.classList.remove("active")); + // Add active to clicked link + this.classList.add("active"); + + // Let the scroll handler update it properly after scroll completes + setTimeout(updateActiveNavLink, 100); + }); + }); + + // Handle hash changes (browser back/forward) + window.addEventListener("hashchange", function () { + setTimeout(updateActiveNavLink, 100); + }); + + // Intersection Observer for more precise tracking (progressive enhancement) + if ("IntersectionObserver" in window) { + const observerOptions = { + rootMargin: "-20% 0px -70% 0px", // Trigger when section is roughly in the middle of viewport + threshold: 0, + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const sectionId = entry.target.getAttribute("id"); + navLinks.forEach((link) => { + link.classList.remove("active"); + if (link.getAttribute("href") === `#${sectionId}`) { + link.classList.add("active"); + } + }); + } + }); + }, observerOptions); + + // Observe all sections + sections.forEach((section) => observer.observe(section)); + } +}); diff --git a/src/styles/styles.css b/src/styles/styles.css new file mode 100644 index 0000000..3229eb9 --- /dev/null +++ b/src/styles/styles.css @@ -0,0 +1,1943 @@ +/* Modern CSS Reset and Variables */ +:root { + /* Color System */ + --bg-primary: #0a0a0a; + --bg-secondary: #111111; + --bg-tertiary: #1a1a1a; + --bg-card: #161616; + --bg-card-hover: #1e1e1e; + + --text-primary: #ffffff; + --text-secondary: #b3b3b3; + --text-muted: #737373; + + --accent-primary: #00f5ff; + --accent-secondary: #7c3aed; + --accent-gradient: linear-gradient(135deg, #00f5ff, #7c3aed); + --accent-gradient-reverse: linear-gradient(135deg, #7c3aed, #00f5ff); + + --purple: #8b5cf6; + --purple-light: #a78bfa; + --purple-dark: #7c3aed; + --purple-muted: #6d28d9; + --shadow-purple: rgba(139, 92, 246, 0.3); + + --border-subtle: #262626; + --border-accent: #333333; + + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); + --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1); + --shadow-glow: 0 0 20px rgba(0, 245, 255, 0.1); + + /* Border Radius */ + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 16px; + --radius-xl: 24px; + + /* Spacing */ + --spacing-xs: 0.5rem; + --spacing-sm: 1rem; + --spacing-md: 1.5rem; + --spacing-lg: 2rem; + --spacing-xl: 3rem; + --spacing-2xl: 4rem; + + /* Typography */ + --font-primary: "Inter", -apple-system, BlinkMacSystemFont, sans-serif; + --font-mono: "JetBrains Mono", "Fira Code", Consolas, monospace; + + /* Z-Index Scale */ + --z-navigation: 1000; + --z-modal: 1100; + --z-tooltip: 1200; +} + +/* Reset */ +*, +*::before, +*::after { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; + font-size: 16px; +} + +body { + font-family: var(--font-primary); + background: var(--bg-primary); + color: var(--text-primary); + line-height: 1.6; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body.nav-open { + overflow: hidden; +} + +/* Links */ +a { + color: inherit; + text-decoration: none; +} + +/* Lists */ +ul, +ol { + list-style: none; +} + +/* Images */ +img { + max-width: 100%; + height: auto; +} + +/* Focus States */ +*:focus { + outline: 2px solid var(--accent-primary); + outline-offset: 2px; +} + +/* Enhanced Background Effects */ +.animated-bg { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -2; + background: radial-gradient( + circle at 20% 50%, + rgba(124, 58, 237, 0.15) 0%, + transparent 50% + ), + radial-gradient( + circle at 80% 20%, + rgba(0, 245, 255, 0.12) 0%, + transparent 50% + ), + radial-gradient( + circle at 40% 80%, + rgba(124, 58, 237, 0.1) 0%, + transparent 50% + ); + animation: gradientShift 15s ease infinite; +} + +@keyframes gradientShift { + 0%, + 100% { + background-position: 0% 50%, 100% 50%, 50% 100%; + } + 50% { + background-position: 100% 50%, 0% 50%, 50% 0%; + } +} + +.stars { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: -1; +} + +.star { + position: absolute; + background: rgba(255, 255, 255, 0.8); + border-radius: 50%; + animation: twinkle 3s infinite ease-in-out; +} + +@keyframes twinkle { + 0%, + 100% { + opacity: 0.3; + transform: scale(1); + } + 50% { + opacity: 1; + transform: scale(1.2); + } +} + +/* Enhanced Navigation with Fixed Background Animations */ +nav { + position: fixed; + top: 0; + width: 100%; + background: rgba(10, 10, 10, 0.95); + backdrop-filter: blur(20px) saturate(180%); + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + z-index: var(--z-navigation); + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + transform: translateY(0); +} + +/* Hide nav on scroll down, show on scroll up */ +nav.hidden { + transform: translateY(-100%); +} + +nav.scrolled { + background: rgba(10, 10, 10, 0.98); + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); + border-bottom-color: rgba(124, 58, 237, 0.2); +} + +.nav-container { + max-width: 1400px; + margin: 0 auto; + padding: 0 var(--spacing-lg); + display: flex; + align-items: center; + justify-content: space-between; + height: 70px; +} + +.logo { + font-weight: 800; + font-size: 1.5rem; + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + position: relative; + padding: var(--spacing-xs) 0; +} + +.logo::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: var(--accent-gradient); + transition: width 0.3s ease; +} + +.logo:hover::after { + width: 100%; +} + +.nav-links { + display: flex; + gap: var(--spacing-md); + align-items: center; +} + +.nav-links a { + color: var(--text-secondary); + font-weight: 500; + font-size: 0.9rem; + padding: var(--spacing-sm) var(--spacing-md); + border-radius: var(--radius-md); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + position: relative; + overflow: hidden; +} + +/* Fixed background animation - only shows on hover */ +.nav-links a::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--accent-gradient); + opacity: 0; + transition: opacity 0.3s ease; + z-index: -1; + border-radius: var(--radius-md); +} + +.nav-links a:hover::before { + opacity: 0.1; +} + +/* Underline animation */ +.nav-links a::after { + content: ""; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 0; + height: 2px; + background: var(--accent-primary); + transition: width 0.3s ease; + border-radius: 2px; +} + +.nav-links a:hover { + color: var(--accent-primary); + transform: translateY(-1px); +} + +.nav-links a:hover::after { + width: 80%; +} + +/* Active state */ +.nav-links a.active { + color: var(--accent-primary); + background: rgba(0, 245, 255, 0.1); +} + +.nav-links a.active::after { + width: 80%; +} + +.nav-links a.active::before { + opacity: 0.1; +} + +/* Mobile menu button */ +.mobile-menu-btn { + display: none; + background: none; + border: none; + color: var(--text-primary); + font-size: 1.5rem; + cursor: pointer; + padding: var(--spacing-sm); + border-radius: var(--radius-md); + transition: all 0.3s ease; + position: relative; + z-index: 1001; +} + +.mobile-menu-btn:hover { + background: rgba(124, 58, 237, 0.1); + color: var(--accent-primary); +} + +.mobile-menu-btn.active { + color: var(--accent-primary); +} + +/* Mobile menu styles */ +@media (max-width: 768px) { + .mobile-menu-btn { + display: block; + } + + .nav-links { + position: fixed; + top: 0; + right: -100%; + width: 280px; + height: 100vh; + background: rgba(10, 10, 10, 0.98); + backdrop-filter: blur(30px); + flex-direction: column; + padding: 80px var(--spacing-lg) var(--spacing-lg); + transition: right 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + border-left: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3); + } + + .nav-links.active { + right: 0; + } + + .nav-links a { + width: 100%; + text-align: center; + padding: var(--spacing-md); + font-size: 1.1rem; + border-radius: var(--radius-lg); + margin-bottom: var(--spacing-xs); + } + + .nav-links a::after { + display: none; + } + + .nav-links a::before { + border-radius: var(--radius-lg); + } + + /* Overlay for mobile menu */ + .nav-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(5px); + z-index: 999; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + } + + .nav-overlay.active { + opacity: 1; + visibility: visible; + } +} + +/* Enhanced scroll behavior */ +.nav-scroll-hide { + animation: navHide 0.4s ease forwards; +} + +.nav-scroll-show { + animation: navShow 0.4s ease forwards; +} + +@keyframes navHide { + from { + transform: translateY(0); + } + to { + transform: translateY(-100%); + } +} + +@keyframes navShow { + from { + transform: translateY(-100%); + } + to { + transform: translateY(0); + } +} + +/* Container */ +.container { + max-width: 1400px; + margin: 0 auto; + padding: 0 var(--spacing-lg); +} + +/* Enhanced Hero Section */ +.hero { + min-height: 100vh; + display: flex; + align-items: center; + padding-top: 80px; + position: relative; + overflow: hidden; +} + +.hero::before { + content: ""; + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + background: radial-gradient( + circle at center, + rgba(124, 58, 237, 0.1) 0%, + transparent 70% + ); + transform: translate(-50%, -50%); + animation: pulse 4s ease-in-out infinite; +} + +@keyframes pulse { + 0%, + 100% { + opacity: 0.5; + transform: translate(-50%, -50%) scale(1); + } + 50% { + opacity: 0.8; + transform: translate(-50%, -50%) scale(1.1); + } +} + +.hero-content { + max-width: 800px; + margin: 0 auto; + text-align: center; + padding: var(--spacing-lg) 0; + position: relative; + z-index: 1; +} + +.hero h1 { + font-size: clamp(2.5rem, 6vw, 4rem); + font-weight: 800; + margin-bottom: var(--spacing-md); + line-height: 1.1; + letter-spacing: -0.02em; + animation: slideUp 1s ease-out; +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.hero h1 .highlight { + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + position: relative; + display: inline-block; +} + +.hero h1 .highlight::after { + content: ""; + position: absolute; + bottom: -5px; + left: 0; + width: 100%; + height: 3px; + background: var(--accent-gradient); + transform: scaleX(0); + transform-origin: left; + animation: expandLine 1s ease-out 0.5s forwards; +} + +@keyframes expandLine { + to { + transform: scaleX(1); + } +} + +.hero p { + font-size: 1.25rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-xl); + max-width: 600px; + margin-left: auto; + margin-right: auto; + line-height: 1.6; + animation: slideUp 1s ease-out 0.2s both; +} + +.hero-buttons { + display: flex; + gap: var(--spacing-sm); + justify-content: center; + flex-wrap: wrap; + animation: slideUp 1s ease-out 0.4s both; +} + +/* Enhanced Buttons */ +.btn { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + padding: 0.875rem var(--spacing-lg); + border-radius: var(--radius-md); + font-weight: 600; + font-size: 0.9rem; + text-decoration: none; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + border: none; + cursor: pointer; + position: relative; + overflow: hidden; +} + +.btn::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.2), + transparent + ); + transition: left 0.5s ease; +} + +.btn:hover::before { + left: 100%; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn-primary { + background: var(--accent-gradient); + color: var(--bg-primary); + box-shadow: var(--shadow-glow); +} + +.btn-primary:hover:not(:disabled) { + transform: translateY(-3px); + box-shadow: 0 15px 30px rgba(0, 245, 255, 0.4); +} + +.btn-secondary { + background: transparent; + color: var(--text-primary); + border: 2px solid var(--border-accent); + position: relative; + overflow: hidden; +} + +.btn-secondary::after { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: var(--accent-gradient); + opacity: 0.1; + transition: left 0.3s ease; + z-index: -1; +} + +.btn-secondary:hover:not(:disabled) { + background: var(--bg-card); + border-color: var(--accent-primary); + transform: translateY(-3px); +} + +.btn-secondary:hover::after { + left: 0; +} + +/* Enhanced Sections */ +.section { + padding: 8rem 0; + position: relative; +} + +.section::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient( + 180deg, + transparent 0%, + rgba(124, 58, 237, 0.03) 50%, + transparent 100% + ); + pointer-events: none; +} + +.section-header { + text-align: center; + margin-bottom: var(--spacing-2xl); + position: relative; +} + +.section-title { + font-size: clamp(2rem, 4vw, 3rem); + font-weight: 700; + margin-bottom: var(--spacing-sm); + letter-spacing: -0.02em; + position: relative; + display: inline-block; +} + +.section-title::after { + content: ""; + position: absolute; + bottom: -10px; + left: 50%; + transform: translateX(-50%); + width: 60px; + height: 3px; + background: var(--accent-gradient); + border-radius: 2px; +} + +.section-subtitle { + font-size: 1.125rem; + color: var(--text-secondary); + max-width: 600px; + margin: 0 auto; + line-height: 1.6; +} + +/* Enhanced Portfolio Controls */ +.portfolio-controls { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: var(--spacing-xl); + flex-wrap: wrap; + gap: var(--spacing-md); +} + +.filter-buttons { + display: flex; + gap: var(--spacing-sm); + flex-wrap: wrap; +} + +.filter-btn { + padding: 0.75rem 1.5rem; + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-secondary); + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.filter-btn::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: var(--accent-gradient); + transition: left 0.3s ease; + z-index: -1; +} + +.filter-btn:hover { + background: var(--bg-card-hover); + color: var(--text-primary); + transform: translateY(-2px); + border-color: var(--accent-primary); +} + +.filter-btn.active { + background: var(--accent-gradient); + color: var(--bg-primary); + border-color: transparent; + box-shadow: var(--shadow-glow); +} + +.search-box { + position: relative; + max-width: 300px; + width: 100%; +} + +.search-box input { + width: 100%; + padding: 0.75rem 1rem 0.75rem 2.5rem; + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-primary); + font-size: 0.95rem; + transition: all 0.3s ease; +} + +.search-box input:focus { + outline: none; + border-color: var(--accent-primary); + box-shadow: 0 0 0 3px rgba(0, 245, 255, 0.1); + background: var(--bg-card-hover); +} + +.search-box i { + position: absolute; + left: 1rem; + top: 50%; + transform: translateY(-50%); + color: var(--text-muted); + transition: color 0.3s ease; +} + +.search-box input:focus + i { + color: var(--accent-primary); +} + +/* Enhanced Portfolio Grid */ +.portfolio-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: var(--spacing-lg); +} + +portfolio-card { + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + overflow: hidden; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + position: relative; + display: block; + opacity: 0; + transform: translateY(30px); + animation: fadeInUp 0.6s ease forwards; +} + +@keyframes fadeInUp { + to { + opacity: 1; + transform: translateY(0); + } +} + +portfolio-card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 3px; + background: var(--accent-gradient); + transform: scaleX(0); + transform-origin: left; + transition: transform 0.3s ease; +} + +portfolio-card:hover::before { + transform: scaleX(1); +} + +portfolio-card:hover { + transform: translateY(-10px) scale(1.02); + background: var(--bg-card-hover); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3), 0 0 30px rgba(0, 245, 255, 0.1); + border-color: var(--border-accent); +} + +.portfolio-img { + display: flex; + align-items: center; + justify-content: center; + height: 120px; + background: var(--accent-gradient); + font-size: 2.5rem; + color: #ffffff; + position: relative; + overflow: hidden; +} + +.portfolio-img::after { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.2), + transparent + ); + transition: left 0.5s ease; +} + +portfolio-card:hover .portfolio-img::after { + left: 100%; +} + +.portfolio-content { + padding: var(--spacing-lg); +} + +.portfolio-title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + font-size: 1.5rem; + font-weight: 600; + margin-bottom: var(--spacing-sm); + color: var(--text-primary); +} + +.portfolio-desc { + color: var(--text-secondary); + margin-bottom: var(--spacing-md); + line-height: 1.6; +} + +.portfolio-tags { + display: flex; + flex-wrap: wrap; + gap: var(--spacing-xs); + margin-bottom: var(--spacing-md); +} + +.tag { + padding: 0.25rem 0.75rem; + background: rgba(0, 245, 255, 0.1); + color: var(--accent-primary); + border-radius: var(--radius-sm); + font-size: 0.8rem; + font-weight: 500; + font-family: var(--font-mono); + transition: all 0.3s ease; +} + +.tag:hover { + background: rgba(0, 245, 255, 0.2); + transform: translateY(-1px); +} + +/* Enhanced Portfolio Button */ +.portfolio-btn-container { + margin-top: auto; + padding: 0 1.5rem 1.5rem; +} + +.portfolio-btn { + width: 100%; + position: relative; + overflow: hidden; + z-index: 1; + padding: 1rem 1.8rem; + border-radius: 8px; + font-weight: 600; + letter-spacing: 0.5px; + text-transform: uppercase; + font-size: 0.9rem; + transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1); + border: 2px solid transparent; + background: linear-gradient(135deg, var(--purple), var(--purple-dark)); + color: white; + box-shadow: 0 4px 15px var(--shadow-purple); + display: flex; + justify-content: center; + align-items: center; + gap: 0.8rem; + text-decoration: none; + text-align: center; +} + +.portfolio-btn::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient(135deg, var(--purple-dark), var(--purple-muted)); + z-index: -1; + transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1); + transform: scaleX(0); + transform-origin: right; +} + +.portfolio-btn:hover::before { + transform: scaleX(1); + transform-origin: left; +} + +.portfolio-btn:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(168, 85, 247, 0.4); + border-color: var(--purple-light); +} + +.portfolio-btn:active { + transform: translateY(0); + box-shadow: 0 4px 15px var(--shadow-purple); +} + +.portfolio-btn i { + font-size: 1rem; + transition: transform 0.3s ease; +} + +.portfolio-btn:hover i { + transform: translateX(4px); +} + +.portfolio-btn::after { + content: ""; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + background: linear-gradient( + to bottom right, + rgba(255, 255, 255, 0.2), + rgba(255, 255, 255, 0.1) 20%, + rgba(255, 255, 255, 0) 50%, + rgba(255, 255, 255, 0) 100% + ); + transform: rotate(30deg) translateY(-150%); + transition: transform 0.6s cubic-bezier(0.165, 0.84, 0.44, 1); +} + +.portfolio-btn:hover::after { + transform: rotate(30deg) translateY(150%); +} + +.portfolio-btn:focus { + outline: 2px solid var(--purple-light); + outline-offset: 2px; +} + +/* Enhanced Collaboration Badge */ +.collaboration-badge { + display: inline-flex; + align-items: center; + gap: 0.4rem; + background: linear-gradient(135deg, #3b82f6, #2563eb); + color: white; + padding: 0.3rem 0.8rem; + border-radius: 20px; + font-size: 0.75rem; + margin-top: 0.5rem; + margin-bottom: 1rem; + animation: pulse 2s infinite; + position: relative; + overflow: hidden; +} + +.collaboration-badge::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.3), + transparent + ); + transition: left 0.5s ease; +} + +.collaboration-badge:hover::before { + left: 100%; +} + +@keyframes pulse { + 0% { + box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4); + } + 70% { + box-shadow: 0 0 0 10px rgba(59, 130, 246, 0); + } + 100% { + box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); + } +} + +/* Enhanced Stats Section */ +.stats-section { + background: var(--bg-secondary); + padding: var(--spacing-2xl) 0; + position: relative; + overflow: hidden; +} + +.stats-section::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: linear-gradient( + 45deg, + transparent 30%, + rgba(124, 58, 237, 0.05) 50%, + transparent 70% + ); + animation: shimmer 3s ease-in-out infinite; +} + +@keyframes shimmer { + 0%, + 100% { + transform: translateX(-100%); + } + 50% { + transform: translateX(100%); + } +} + +.stats-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: var(--spacing-lg); + text-align: center; + position: relative; + z-index: 1; +} + +.stat-item { + padding: var(--spacing-lg); + position: relative; +} + +.stat-item::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--accent-gradient); + opacity: 0; + border-radius: var(--radius-lg); + transition: opacity 0.3s ease; + z-index: -1; +} + +.stat-item:hover::before { + opacity: 0.05; +} + +.stat-number { + font-size: 3rem; + font-weight: 800; + background: var(--accent-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + margin-bottom: var(--spacing-sm); +} + +.stat-label { + color: var(--text-secondary); + font-weight: 500; + font-size: 1.1rem; +} + +/* Enhanced Team Section */ +.team-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: var(--spacing-lg); + margin-top: var(--spacing-lg); +} + +.team-member { + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + padding: var(--spacing-lg); + text-align: center; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + position: relative; + overflow: hidden; +} + +.team-member::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: var(--accent-gradient); + opacity: 0.05; + transition: left 0.3s ease; + z-index: -1; +} + +.team-member:hover::before { + left: 0; +} + +.team-member:hover { + transform: translateY(-8px) scale(1.02); + background: var(--bg-card-hover); + box-shadow: var(--shadow-xl); + border-color: var(--border-accent); +} + +.member-avatar { + width: 120px; + height: 120px; + background: var(--accent-gradient); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 2.5rem; + color: #ffffff; + margin: 0 auto var(--spacing-md); + position: relative; + transition: all 0.3s ease; +} + +.team-member:hover .member-avatar { + transform: scale(1.1) rotate(5deg); +} + +.member-avatar::after { + content: ""; + position: absolute; + inset: 3px; + background: var(--bg-card); + border-radius: 50%; + z-index: 1; +} + +.member-avatar i { + z-index: 2; + position: relative; +} + +.team-member h3 { + font-size: 1.5rem; + font-weight: 600; + margin-bottom: var(--spacing-xs); +} + +.team-role { + color: var(--accent-primary); + font-weight: 500; + margin-bottom: var(--spacing-sm); + font-family: var(--font-mono); + font-size: 0.9rem; +} + +.team-member p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* Enhanced About Section */ +.about-content { + max-width: 800px; + margin: 0 auto; + text-align: center; +} + +.about-content p { + font-size: 1.125rem; + color: var(--text-secondary); + margin-bottom: var(--spacing-lg); + line-height: 1.7; + text-align: left; + position: relative; + padding-left: var(--spacing-lg); +} + +.about-content p::before { + content: ""; + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 3px; + background: var(--accent-gradient); + border-radius: 2px; + transform: scaleY(0); + transition: transform 0.3s ease; +} + +.about-content p:hover::before { + transform: scaleY(1); +} + +.about-content p:last-child { + margin-bottom: 0; +} + +/* Enhanced Vision Section */ +.vision-content { + max-width: 1000px; + margin: 0 auto; +} + +.vision-text { + text-align: center; + margin-bottom: var(--spacing-2xl); +} + +.vision-text p { + font-size: 1.125rem; + color: var(--text-secondary); + line-height: 1.7; + max-width: 700px; + margin: 0 auto; +} + +.principles-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: var(--spacing-lg); +} + +.principle-card { + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + padding: var(--spacing-lg); + text-align: center; + transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + position: relative; + overflow: hidden; +} + +.principle-card::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: var(--accent-gradient); + opacity: 0.05; + transition: left 0.3s ease; + z-index: -1; +} + +.principle-card:hover::before { + left: 0; +} + +.principle-card:hover { + transform: translateY(-8px) scale(1.02); + background: var(--bg-card-hover); + box-shadow: var(--shadow-lg); + border-color: var(--border-accent); +} + +.principle-icon { + display: flex; + align-items: center; + justify-content: center; + width: 80px; + height: 80px; + background: var(--accent-gradient); + border-radius: 50%; + margin: 0 auto var(--spacing-md); + font-size: 1.8rem; + color: #ffffff; + transition: all 0.3s ease; +} + +.principle-card:hover .principle-icon { + transform: scale(1.1) rotate(10deg); +} + +.principle-card h4 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: var(--spacing-sm); + color: var(--text-primary); +} + +.principle-card p { + color: var(--text-secondary); + line-height: 1.6; +} + +/* Enhanced Contact Section */ +.contact-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-2xl); + max-width: 1000px; + margin: 0 auto; +} + +.contact-methods { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); +} + +.contact-item { + display: flex; + align-items: flex-start; + gap: var(--spacing-sm); + transition: all 0.3s ease; + padding: var(--spacing-md); + border-radius: var(--radius-lg); +} + +.contact-item:hover { + background: var(--bg-card); + transform: translateX(10px); +} + +.contact-icon { + display: flex; + align-items: center; + justify-content: center; + width: 50px; + height: 50px; + background: var(--accent-gradient); + border-radius: var(--radius-md); + font-size: 1.2rem; + color: #ffffff; + flex-shrink: 0; + transition: all 0.3s ease; +} + +.contact-item:hover .contact-icon { + transform: scale(1.1) rotate(5deg); +} + +.contact-details h4 { + font-size: 1.1rem; + font-weight: 600; + margin-bottom: var(--spacing-xs); + color: var(--text-primary); +} + +.contact-details a { + color: var(--text-secondary); + transition: color 0.3s ease; + position: relative; +} + +.contact-details a::after { + content: ""; + position: absolute; + bottom: -2px; + left: 0; + width: 0; + height: 1px; + background: var(--accent-primary); + transition: width 0.3s ease; +} + +.contact-details a:hover { + color: var(--accent-primary); +} + +.contact-details a:hover::after { + width: 100%; +} + +/* Enhanced Contact Form */ +.contact-form { + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-lg); + padding: var(--spacing-xl); + transition: all 0.3s ease; +} + +.contact-form:hover { + border-color: var(--accent-primary); + box-shadow: var(--shadow-glow); +} + +.form-group { + margin-bottom: var(--spacing-md); + position: relative; +} + +.form-group label { + display: block; + margin-bottom: var(--spacing-xs); + font-weight: 500; + color: var(--text-primary); + font-size: 0.9rem; + transition: color 0.3s ease; +} + +.form-group input, +.form-group select, +.form-group textarea { + width: 100%; + padding: var(--spacing-sm); + background: var(--bg-tertiary); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-primary); + font-size: 0.95rem; + font-family: var(--font-primary); + transition: all 0.3s ease; +} + +.form-group input:focus, +.form-group select:focus, +.form-group textarea:focus { + outline: none; + border-color: var(--accent-primary); + box-shadow: 0 0 0 3px rgba(0, 245, 255, 0.1); + background: var(--bg-card-hover); +} + +.form-group textarea { + resize: vertical; + min-height: 120px; + font-family: var(--font-primary); +} + +.form-group select { + cursor: pointer; +} + +.contact-form .btn { + width: 100%; + justify-content: center; + margin-top: var(--spacing-sm); +} + +/* Enhanced Footer */ +.footer { + background: var(--bg-secondary); + border-top: 1px solid var(--border-subtle); + padding: var(--spacing-2xl) 0 var(--spacing-lg); + position: relative; +} + +.footer::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 1px; + background: var(--accent-gradient); +} + +.footer-content { + display: grid; + grid-template-columns: 2fr 1fr 1fr 1fr; + gap: var(--spacing-xl); + margin-bottom: var(--spacing-xl); +} + +.footer-brand .logo { + font-size: 1.5rem; + margin-bottom: var(--spacing-sm); + display: block; +} + +.footer-brand p { + color: var(--text-secondary); + margin-bottom: var(--spacing-lg); + line-height: 1.6; + max-width: 300px; +} + +.footer-social { + display: flex; + gap: var(--spacing-sm); +} + +.social-link { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + height: 40px; + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-md); + color: var(--text-secondary); + font-size: 1.1rem; + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +.social-link::before { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: var(--accent-gradient); + transition: left 0.3s ease; + z-index: -1; +} + +.social-link:hover::before { + left: 0; +} + +.social-link:hover { + background: var(--accent-gradient); + color: #ffffff; + transform: translateY(-3px) scale(1.1); + border-color: transparent; +} + +.footer-links h4 { + font-size: 1.1rem; + font-weight: 600; + color: var(--text-primary); + margin-bottom: var(--spacing-sm); + position: relative; +} + +.footer-links h4::after { + content: ""; + position: absolute; + bottom: -5px; + left: 0; + width: 30px; + height: 2px; + background: var(--accent-primary); +} + +.footer-links ul { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); +} + +.footer-links a { + color: var(--text-secondary); + font-size: 0.9rem; + transition: all 0.3s ease; + padding: 0.25rem 0; + position: relative; +} + +.footer-links a::before { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 1px; + background: var(--accent-primary); + transition: width 0.3s ease; +} + +.footer-links a:hover { + color: var(--accent-primary); + transform: translateX(5px); +} + +.footer-links a:hover::before { + width: 100%; +} + +.footer-bottom { + border-top: 1px solid var(--border-subtle); + padding-top: var(--spacing-lg); +} + +.footer-bottom-content { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: var(--spacing-sm); +} + +.footer-bottom p { + color: var(--text-muted); + font-size: 0.9rem; +} + +.footer-badges { + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.badge { + display: flex; + align-items: center; + gap: var(--spacing-xs); + padding: var(--spacing-xs) var(--spacing-sm); + background: var(--bg-card); + border: 1px solid var(--border-subtle); + border-radius: var(--radius-sm); + font-size: 0.8rem; + color: var(--text-muted); + transition: all 0.3s ease; +} + +.badge:hover { + background: var(--accent-gradient); + color: var(--bg-primary); + border-color: transparent; + transform: translateY(-2px); +} + +.badge i { + color: var(--accent-primary); +} + +.badge:hover i { + color: var(--bg-primary); +} + +/* Enhanced No Results */ +.no-results { + grid-column: 1 / -1; + text-align: center; + padding: var(--spacing-2xl); + color: var(--text-muted); + position: relative; +} + +.no-results i { + font-size: 3rem; + margin-bottom: var(--spacing-md); + opacity: 0.5; + animation: bounce 2s infinite; +} + +@keyframes bounce { + 0%, + 20%, + 50%, + 80%, + 100% { + transform: translateY(0); + } + 40% { + transform: translateY(-10px); + } + 60% { + transform: translateY(-5px); + } +} + +.no-results h3 { + font-size: 1.5rem; + margin-bottom: var(--spacing-sm); + color: var(--text-secondary); +} + +.no-results p { + color: var(--text-muted); +} + +/* Responsive Design */ +@media (max-width: 1024px) { + .nav-container { + padding: 0 var(--spacing-md); + } + + .container { + padding: 0 var(--spacing-md); + } + + .footer-content { + grid-template-columns: 1fr 1fr; + gap: var(--spacing-lg); + } + + .contact-container { + grid-template-columns: 1fr; + gap: var(--spacing-xl); + } +} + +@media (max-width: 768px) { + .mobile-menu-btn { + display: block; + } + + .nav-links { + position: fixed; + top: 0; + right: -100%; + width: 280px; + height: 100vh; + background: rgba(10, 10, 10, 0.98); + backdrop-filter: blur(30px); + flex-direction: column; + padding: 80px var(--spacing-lg) var(--spacing-lg); + transition: right 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94); + border-left: 1px solid rgba(255, 255, 255, 0.1); + box-shadow: -10px 0 30px rgba(0, 0, 0, 0.3); + } + + .nav-links.active { + right: 0; + } + + .nav-links a { + width: 100%; + text-align: center; + padding: var(--spacing-md); + font-size: 1.1rem; + border-radius: var(--radius-lg); + margin-bottom: var(--spacing-xs); + } + + .nav-links a::after { + display: none; + } + + .nav-links a::before { + border-radius: var(--radius-lg); + } + + .nav-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(5px); + z-index: 999; + opacity: 0; + visibility: hidden; + transition: all 0.3s ease; + } + + .nav-overlay.active { + opacity: 1; + visibility: visible; + } + + .hero h1 { + font-size: clamp(2rem, 8vw, 3rem); + } + + .hero p { + font-size: 1.1rem; + } + + .hero-buttons { + flex-direction: column; + align-items: center; + } + + .section { + padding: 4rem 0; + } + + .portfolio-controls { + flex-direction: column; + align-items: stretch; + } + + .filter-buttons { + justify-content: center; + } + + .portfolio-grid { + grid-template-columns: 1fr; + } + + .team-grid { + grid-template-columns: 1fr; + } + + .principles-grid { + grid-template-columns: 1fr; + } + + .stats-container { + grid-template-columns: repeat(2, 1fr); + } + + .footer-content { + grid-template-columns: 1fr; + text-align: center; + gap: var(--spacing-lg); + } + + .footer-brand p { + max-width: none; + } + + .footer-social { + justify-content: center; + } + + .footer-bottom-content { + flex-direction: column; + text-align: center; + gap: var(--spacing-sm); + } + + .portfolio-btn { + padding: 0.9rem 1.5rem; + font-size: 0.85rem; + } +} + +@media (max-width: 480px) { + .container { + padding: 0 var(--spacing-sm); + } + + .nav-container { + padding: 0 var(--spacing-sm); + } + + .hero-content { + padding: var(--spacing-sm) 0; + } + + .project-card, + .team-member, + .principle-card, + .contact-form { + padding: var(--spacing-md); + } + + .section-header { + margin-bottom: var(--spacing-xl); + } + + .contact-form { + padding: var(--spacing-lg); + } + + .stats-container { + grid-template-columns: 1fr; + } +} + +/* Animations and Interactions */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } + + .star { + animation: none; + } +} + +/* Print Styles */ +@media print { + .animated-bg, + .stars, + nav, + .hero-buttons, + .contact-form, + .footer-social { + display: none; + } + + body { + background: white; + color: black; + } + + .section { + padding: 2rem 0; + } +} diff --git a/styles.css b/styles.css deleted file mode 100644 index d14c826..0000000 --- a/styles.css +++ /dev/null @@ -1,432 +0,0 @@ -/* - interstellar_development website - Copyright (C) 2024 interstellar_development - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -:root { - --background-color: #0b0c1d; - --text-color: #c7d5e0; - --accent-color: #ffdd55; - --accent-hover-color: #ffd700; - --dark-blue: rgba(31, 42, 64, 1); - --dark-blue-translucent: rgba(31, 42, 64, 0.9); - --light-blue: rgba(46, 58, 95, 0.8); - --border-radius: 8px; - --transition-speed: 0.3s; - --box-shadow: 0 2px 15px rgba(0, 0, 0, 0.7); - --font-size-large: 2.5em; - --font-size-medium: 1.8em; -} - -/* Reset and normalize */ -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -/* Body styling */ -body { - background-color: var(--background-color); - color: var(--text-color); - font-family: "Arial", sans-serif; - line-height: 1.6; - padding: 0 20px; - background: url("images/star.jpg") no-repeat center center fixed; - background-size: cover; -} - -/* Header Styling */ -/* Header Styling */ -header { - background-color: var(--dark-blue); - height: 5em; - position: fixed; - width: 100%; - top: 0; - left: 0; - padding: 15px 20px; - box-shadow: var(--box-shadow); - backdrop-filter: blur(5px); - z-index: 100; - margin-bottom: 0px; -} - -/* Burger Menu Styling */ -.burger-menu { - background: none; - border: none; - color: #ffffff; - font-size: 1.8em; - cursor: pointer; - display: block; - padding: 0; - z-index: 110; -} - -/* Dropdown Menu (Hidden by Default) */ -.div-menu { - z-index: 1; - background-color: var(--light-blue); - width: 100%; - position: fixed; - top: 0; - left: 0; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); - padding: 0; - margin-top: 0px; - height: auto; -} - -.div-menu li { - margin: 0; - padding: 1em; - z-index: 1; -} - -.div-menu a { - width: 100%; - padding: 8px 0; - text-align: center; - color: #ffffff; - text-decoration: none; - border-radius: 5px; - transition: background-color 0.3s ease; - display: block; -} - -.div-menu a:hover { - background-color: #34495e; -} - -/* Menu Animation and Styling */ -.menu { - display: flex; - flex-direction: column; - background-color: var(--light-blue); - position: absolute; - top: -50vh; - left: 0; - width: 100%; - z-index: 5; - padding: 0; - margin: 0; - list-style: none; - justify-content: center; - text-align: center; - font-weight: bolder; - font-size: large; - transition: top 0.5s ease-in-out; -} - -.menu.active { - display: flex; - top: 4em; - z-index: 5; -} - -/* Header Content Container */ -.header-content { - display: flex; - justify-content: space-between; - align-items: center; - max-width: 1200px; - margin: 0 auto; - padding: 0 20px; - z-index: 10; -} - -/* Project Name Styling */ -.project-name { - font-size: 2em; - color: var(--accent-color); - text-decoration: none; - transition: color var(--transition-speed), text-shadow var(--transition-speed); -} - -.project-name:hover { - color: var(--accent-hover-color); - text-shadow: 0 0 10px var(--accent-hover-color); -} - -/* Article styling */ -article { - max-width: 800px; - margin: 6.25em auto; - padding: 20px; - background-color: var(--dark-blue-translucent); - border-radius: var(--border-radius); - box-shadow: var(--box-shadow); - backdrop-filter: blur(5px); -} - -article h1 { - font-size: var(--font-size-large); - margin-bottom: 20px; - color: var(--accent-color); - text-shadow: 0 0 15px var(--accent-color); -} - -article p { - color: var(--text-color); - margin-bottom: 20px; - hyphens: auto; -} - -/* Download list */ -article h2 { - font-size: var(--font-size-medium); - margin: 20px 0 10px; - color: var(--accent-color); - text-shadow: 0 0 10px var(--accent-color); -} - -article ul { - list-style-type: none; - padding: 0; -} - -article ul a li { - background-color: var(--light-blue); - margin-bottom: 10px; - border-radius: var(--border-radius); - padding: 10px; - transition: background-color var(--transition-speed), - box-shadow var(--transition-speed); -} - -article ul a li:hover { - background-color: rgba(68, 80, 124, 0.9); - box-shadow: 0 0 10px var(--accent-color); -} - -article ul a li { - text-decoration: none; - color: var(--accent-color); - font-weight: bold; -} - -/* Footer styling */ -footer { - background-color: var(--dark-blue); - padding: 10px 20px; - color: var(--text-color); - width: 100%; - position: fixed; - bottom: 0; - left: 0; - box-shadow: 0 -2px 15px rgba(0, 0, 0, 0.7); - backdrop-filter: blur(5px); -} - -.footer-content { - text-align: center; - font-size: 0.9em; -} - -/* Card container styles */ -.cards { - display: grid; - grid-template-columns: repeat(3, 1fr); /* Display 3 cards per line */ - gap: 20px; - margin-top: 50px; -} - -/* Ensure the tag covers the entire card */ -section .card a { - display: flex; /* Use flex to make fill the card and align content */ - flex-direction: column; - justify-content: center; /* Vertically center the content */ - align-items: center; /* Horizontally center the content */ - text-decoration: none; - color: inherit; - height: 100%; - width: 100%; - padding: 20px; -} - -/* Card styles */ -section .card { - text-align: center; - list-style: none; - background: linear-gradient( - 180deg, - rgba(0, 0, 50, 0.9), - rgba(10, 10, 100, 0.9), - rgba(30, 30, 150, 0.9) - ); - border-radius: 12px; - box-shadow: 0 5px 20px rgba(0, 0, 50, 0.8), 0 0 10px rgba(255, 255, 255, 0.1); - border: 1px solid #2e3a60; - position: relative; - overflow: hidden; - display: flex; - flex-direction: column; - justify-content: space-between; - transition: background 0.5s ease, transform 0.4s ease, box-shadow 0.5s ease; -} - -/* Hover effect */ -section .card:hover { - transform: translateY(-8px); - background: linear-gradient( - 180deg, - rgba(30, 30, 150, 0.9), - rgba(40, 0, 100, 0.9), - rgba(100, 0, 150, 0.9) - ); - box-shadow: 0 10px 30px rgba(0, 0, 100, 0.7), 0 0 20px rgba(255, 221, 85, 0.8); -} - -section .card img { - height: 80px; - width: 80px; - object-fit: cover; - border-radius: 50%; - margin: 0 auto 15px; - box-shadow: 0 0 15px rgba(255, 221, 85, 0.5); -} - -section .card h3 { - margin: 10px 0; - font-size: 1.4em; - font-weight: bold; - color: rgba(255, 221, 85, 1); - text-shadow: 0 0 15px rgba(255, 221, 85, 0.9); -} - -section .card p { - flex-grow: 1; - color: rgba(200, 220, 255, 0.8); - margin-bottom: 10px; - text-shadow: 0 0 8px rgba(255, 255, 255, 0.2); -} - -section .card::before { - content: ""; - position: absolute; - top: -20px; - right: -20px; - width: 60px; - height: 60px; - border-radius: 50%; - background: radial-gradient( - circle, - rgba(255, 255, 255, 0.1), - rgba(255, 255, 255, 0.02) - ); - box-shadow: 0 0 50px rgba(255, 255, 255, 0.5); - animation: spin 8s linear infinite; -} - -section .card .suit-icon { - position: absolute; - bottom: 10px; - right: 10px; - width: 24px; - height: 24px; - opacity: 0.7; - transition: opacity var(--transition-speed); -} - -section .card:hover .suit-icon { - opacity: 1; -} - -/* Keyframes for spinning element */ -@keyframes spin { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} - -/* Form styling */ -form { - max-width: 600px; - margin: 0 auto; - background: var(--dark-blue-translucent); - padding: 20px; - border-radius: var(--border-radius); - box-shadow: var(--box-shadow); - backdrop-filter: blur(5px); -} - -form label, -form input, -form textarea { - color: var(--text-color); - background-color: var(--light-blue); - border: 1px solid #3a4b7f; - border-radius: var(--border-radius); - padding: 10px; - margin: 10px 0; - width: 100%; -} - -form input[type="submit"] { - background-color: var(--accent-color); - color: #fff; - border: none; - cursor: pointer; - transition: background-color var(--transition-speed); -} - -form input[type="submit"]:hover { - background-color: var(--accent-hover-color); -} - -/* Footer Styling */ -footer { - background-color: var(--dark-blue); - padding: 10px 20px; - color: var(--text-color); - text-align: center; - font-size: 0.9em; -} - -@media (max-width: 768px) { - .cards { - grid-template-columns: 1fr; /* 1 card per line on smaller screens */ - } - - header ul { - flex-direction: column; - gap: 10px; - } - - article { - margin: 12em 10px; - padding: 15px; - } - - section .card { - padding: 12px; - } - - section .card img { - height: 60px; - width: 60px; - } - - .project-name { - font-size: 1.3em; - } -} diff --git a/webGames/index.html b/webGames/index.html deleted file mode 100644 index 7f1a0bf..0000000 --- a/webGames/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - Game Collection - - - - - - - -
-

Game Collection

-
- -
- -
- - - - diff --git a/webGames/styles.css b/webGames/styles.css deleted file mode 100644 index e9a6fcf..0000000 --- a/webGames/styles.css +++ /dev/null @@ -1,120 +0,0 @@ -/* Reset and box-sizing */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -/* General Styles */ -body { - font-family: Arial, sans-serif; - background-color: #282c34; - color: #ffffff; - margin: 0; -} - -header { - background-color: #4caf50; - color: white; - text-align: center; - padding: 1em 0; - font-size: 1.5rem; -} - -footer { - background-color: #333; - color: white; - text-align: center; - padding: 1em 0; - margin-top: 20px; -} - -/* Grid Styles */ -.grid-container { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 20px; /* Space between items */ - padding: 20px; /* Space around the grid */ -} - -/* Game Item */ -.item { - position: relative; - background-color: #444; - border-radius: 10px; - overflow: hidden; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); - transition: transform 0.3s ease, box-shadow 0.3s ease, filter 0.3s ease; - width: 100%; /* Ensure it takes full width of the column */ - height: 400px; /* Set a fixed height for all items */ - display: flex; - flex-direction: column; /* Stack children vertically */ -} - -/* Ensure the image takes the top part of the card */ -.item img { - width: 100%; - height: 100%; /* Set a height for the image */ - object-fit: cover; -} - -.item .description { - padding: 30px; - font-size: 1rem; - color: #ddd; - background-color: rgba(0, 0, 0, 0.5); - border-radius: 0 0 10px 10px; - flex-grow: 1; /* Allow description to take remaining space */ -} - -p { - text-decoration: none; -} - -/* Hover effect for scaling and glowing */ -.item:hover { - transform: scale(1.05); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4); - filter: brightness(1.2); -} - -.item:hover img { - transform: scale(1.1); /* Slight zoom-in effect for the image */ - filter: brightness(1.1); /* Increase image brightness */ -} - -.item h2 { - position: absolute; - top: 10%; - left: 50%; - transform: translateX(-50%); - color: white; - font-size: 1.5rem; - background-color: rgba(0, 0, 0, 0.6); - padding: 5px 15px; - border-radius: 5px; - text-align: center; - opacity: 0; - transition: opacity 0.3s ease, transform 0.3s ease; -} - -.item:hover h2 { - opacity: 1; - transform: translateX(-50%) translateY(-10px); /* Move the title upwards with hover */ -} - -/* Mobile Optimization */ -@media (max-width: 600px) { - header { - font-size: 1.2rem; - } - - .item { - height: auto; /* Allow auto height on mobile for better responsiveness */ - width: auto; - } - - .grid-container { - grid-template-columns: repeat(1, 1fr); - } -}