diff --git a/index.html b/index.html index a81af8f..6ce1fc7 100644 --- a/index.html +++ b/index.html @@ -1,496 +1,12 @@ - + - Interstellar Development | Free and Open Source Software - - - - - - - - - - - - + Document - - -
-
- - - - -
- -
-
-
-

- Advancing Free Software Development -

-

- We develop high-quality free and open source software solutions, - with a focus on gaming and applications that respect user freedom. -

- -
-
-
- - -
-
-
-

Our Projects

-

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

-
- - -
-
- - - - -
- -
- -
- -
- -
-
-
-
- - -
-
-
-

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 -
-
-
-
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- - -
-
-
-
- - - -
- - - - - - - - - - - - +

THERE IS NOTHING HERE! - WEBSITE OUT OF COMMISSION

+ ForgeJo diff --git a/src/favicon/android-chrome-192x192.png b/src/favicon/android-chrome-192x192.png deleted file mode 100644 index e636383..0000000 Binary files a/src/favicon/android-chrome-192x192.png and /dev/null differ diff --git a/src/favicon/android-chrome-512x512.png b/src/favicon/android-chrome-512x512.png deleted file mode 100644 index 65f6ef4..0000000 Binary files a/src/favicon/android-chrome-512x512.png and /dev/null differ diff --git a/src/favicon/apple-touch-icon.png b/src/favicon/apple-touch-icon.png deleted file mode 100644 index 42de221..0000000 Binary files a/src/favicon/apple-touch-icon.png and /dev/null differ diff --git a/src/favicon/favicon-16x16.png b/src/favicon/favicon-16x16.png deleted file mode 100644 index e736fae..0000000 Binary files a/src/favicon/favicon-16x16.png and /dev/null differ diff --git a/src/favicon/favicon-32x32.png b/src/favicon/favicon-32x32.png deleted file mode 100644 index 74501cd..0000000 Binary files a/src/favicon/favicon-32x32.png and /dev/null differ diff --git a/src/favicon/favicon.ico b/src/favicon/favicon.ico deleted file mode 100644 index 4de4913..0000000 Binary files a/src/favicon/favicon.ico and /dev/null differ diff --git a/src/images/Patrick.png b/src/images/Patrick.png deleted file mode 100644 index 6aa6377..0000000 Binary files a/src/images/Patrick.png and /dev/null differ diff --git a/src/images/sage.png b/src/images/sage.png deleted file mode 100644 index 3bc7bd8..0000000 Binary files a/src/images/sage.png and /dev/null differ diff --git a/src/js/animation/Meteor.js b/src/js/animation/Meteor.js deleted file mode 100644 index 1387e54..0000000 --- a/src/js/animation/Meteor.js +++ /dev/null @@ -1,274 +0,0 @@ -class Meteor { - constructor(container) { - this.container = container; - this.containerRect = container.getBoundingClientRect(); - - // Smooth movement settings - this.speed = Math.random() * 1.5 + 2; - this.life = 1.0; - this.fadeSpeed = 0.002; - - // Enhanced color schemes for vibrant streaks - this.colorSchemes = [ - // Classic golden-white meteor - { - core: "#ffffff", - mid: "#ffeb99", - outer: "#ff9933", - }, - // Blue-white ice meteor - { - core: "#ffffff", - mid: "#aaddff", - outer: "#4488ff", - }, - // Purple cosmic meteor - { - core: "#ffffff", - mid: "#ddaaff", - outer: "#aa44ff", - }, - // Green-white aurora meteor - { - core: "#ffffff", - mid: "#aaffcc", - outer: "#44ff88", - }, - ]; - - this.colors = - this.colorSchemes[Math.floor(Math.random() * this.colorSchemes.length)]; - - // Start positions - const startSide = Math.random(); - if (startSide < 0.7) { - this.x = Math.random() * this.containerRect.width; - this.y = -100; - this.angle = Math.PI / 2 + (Math.random() - 0.5) * 0.6; - } else if (startSide < 0.85) { - this.x = -100; - this.y = Math.random() * this.containerRect.height * 0.3; - this.angle = Math.PI / 4 + Math.random() * 0.4; - } else { - this.x = this.containerRect.width + 100; - this.y = Math.random() * this.containerRect.height * 0.3; - this.angle = (Math.PI * 3) / 4 + Math.random() * 0.4; - } - - this.dx = Math.cos(this.angle) * this.speed; - this.dy = Math.sin(this.angle) * this.speed; - - // Trail settings - this.trailPoints = []; - this.maxTrailLength = 25; - - this.hasBeenOnScreen = false; - - this.init(); - } - - init() { - // Create SVG for smooth gradient trail - this.svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - this.svg.style.cssText = ` - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - pointer-events: none; - overflow: visible; - z-index: 9; - `; - this.svg.setAttribute("width", this.containerRect.width); - this.svg.setAttribute("height", this.containerRect.height); - - // Create gradient for trail - const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); - const gradient = document.createElementNS( - "http://www.w3.org/2000/svg", - "linearGradient" - ); - this.gradientId = `meteor-gradient-${Date.now()}-${Math.random() - .toString(36) - .substr(2, 9)}`; - gradient.setAttribute("id", this.gradientId); - gradient.setAttribute("gradientUnits", "userSpaceOnUse"); - - // Gradient stops for smooth colored fade - const stops = [ - { offset: "0%", color: this.colors.core, opacity: "1" }, - { offset: "30%", color: this.colors.mid, opacity: "0.8" }, - { offset: "60%", color: this.colors.outer, opacity: "0.5" }, - { offset: "100%", color: this.colors.outer, opacity: "0" }, - ]; - - stops.forEach((stop) => { - const stopEl = document.createElementNS( - "http://www.w3.org/2000/svg", - "stop" - ); - stopEl.setAttribute("offset", stop.offset); - stopEl.setAttribute("stop-color", stop.color); - stopEl.setAttribute("stop-opacity", stop.opacity); - gradient.appendChild(stopEl); - }); - - defs.appendChild(gradient); - this.svg.appendChild(defs); - - // Create path for trail - this.trailPath = document.createElementNS( - "http://www.w3.org/2000/svg", - "path" - ); - this.trailPath.setAttribute("fill", "none"); - this.trailPath.setAttribute("stroke", `url(#${this.gradientId})`); - this.trailPath.setAttribute("stroke-linecap", "round"); - this.trailPath.setAttribute("stroke-linejoin", "round"); - - const headSize = Math.random() * 2 + 2.5; - this.headSize = headSize; - this.trailPath.setAttribute("stroke-width", headSize * 2); - this.trailPath.style.filter = `blur(${headSize * 0.4}px)`; - - this.svg.appendChild(this.trailPath); - this.container.appendChild(this.svg); - - // Meteor head - use absolute positioning like the SVG - this.head = document.createElement("div"); - this.head.style.cssText = ` - position: absolute; - width: ${headSize}px; - height: ${headSize}px; - border-radius: 50%; - background: ${this.colors.core}; - box-shadow: 0 0 ${headSize * 3}px ${this.colors.mid}, - 0 0 ${headSize * 5}px ${this.colors.outer}; - pointer-events: none; - z-index: 10; - transform: translate(-50%, -50%); - `; - - this.container.appendChild(this.head); - - // Initialize trail - for (let i = 0; i < 3; i++) { - this.trailPoints.push({ x: this.x, y: this.y }); - } - } - - isOnScreen() { - const buffer = 50; - return ( - this.x > -buffer && - this.x < this.containerRect.width + buffer && - this.y > -buffer && - this.y < this.containerRect.height + buffer - ); - } - - isOffScreen() { - const buffer = 200; - return ( - this.x < -buffer || - this.x > this.containerRect.width + buffer || - this.y < -buffer || - this.y > this.containerRect.height + buffer - ); - } - - updateTrail() { - // Add current position to trail - this.trailPoints.unshift({ x: this.x, y: this.y }); - - // Limit trail length - if (this.trailPoints.length > this.maxTrailLength) { - this.trailPoints.pop(); - } - - // Update SVG path with smooth curves - if (this.trailPoints.length >= 2) { - let pathData = `M ${this.trailPoints[0].x} ${this.trailPoints[0].y}`; - - // Use smooth curves - for (let i = 1; i < this.trailPoints.length - 1; i++) { - const curr = this.trailPoints[i]; - const next = this.trailPoints[i + 1]; - const midX = (curr.x + next.x) / 2; - const midY = (curr.y + next.y) / 2; - pathData += ` Q ${curr.x} ${curr.y} ${midX} ${midY}`; - } - - // Final point - if (this.trailPoints.length > 1) { - const last = this.trailPoints[this.trailPoints.length - 1]; - pathData += ` L ${last.x} ${last.y}`; - } - - this.trailPath.setAttribute("d", pathData); - - // Update gradient position for directional effect - const gradient = document.getElementById(this.gradientId); - if (gradient) { - gradient.setAttribute("x1", this.x); - gradient.setAttribute("y1", this.y); - const lastPoint = this.trailPoints[this.trailPoints.length - 1]; - gradient.setAttribute("x2", lastPoint.x); - gradient.setAttribute("y2", lastPoint.y); - } - } - } - - update(deltaTime) { - // Use deltaTime for consistent movement - const dt = Math.min(deltaTime / 16.67, 2); - - // Update position - this.x += this.dx * dt; - this.y += this.dy * dt; - - // Track screen presence - if (!this.hasBeenOnScreen && this.isOnScreen()) { - this.hasBeenOnScreen = true; - } - - // Fade when off screen - if (this.hasBeenOnScreen && this.isOffScreen()) { - this.life -= this.fadeSpeed * 3 * dt; - } - - // Update head position using left/top (same coordinate system as SVG) - this.head.style.left = `${this.x}px`; - this.head.style.top = `${this.y}px`; - this.head.style.opacity = this.life; - - // Update SVG trail opacity - this.svg.style.opacity = this.life; - - // Update trail - this.updateTrail(); - - // Check if should be removed - if ( - this.life <= 0 || - (this.hasBeenOnScreen && this.isOffScreen() && this.life < 0.3) - ) { - this.remove(); - return false; - } - - return true; - } - - remove() { - if (this.svg && this.svg.parentNode) { - this.svg.remove(); - } - if (this.head && this.head.parentNode) { - this.head.remove(); - } - } -} - -export default Meteor; diff --git a/src/js/animation/Star.js b/src/js/animation/Star.js deleted file mode 100644 index 53b21f2..0000000 --- a/src/js/animation/Star.js +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index 83611a0..0000000 --- a/src/js/animation/starBackground.js +++ /dev/null @@ -1,161 +0,0 @@ -import Star from "./Star.js"; -import Meteor from "./Meteor.js"; - -const starInstances = []; -const meteorInstances = []; -let lastTime = performance.now(); -let isTabVisible = true; -let animationFrameId = null; - -// Track tab visibility to prevent spawning when hidden -document.addEventListener("visibilitychange", () => { - isTabVisible = !document.hidden; - - // If tab becomes visible after being hidden, clean up excess meteors - if (isTabVisible && meteorInstances.length > 3) { - // Remove excess meteors - const excess = meteorInstances.length - 3; - for (let i = 0; i < excess; i++) { - if (meteorInstances[i]) { - meteorInstances[i].remove(); - } - } - meteorInstances.splice(0, excess); - } - - // Resume animation loop if it stopped - if (isTabVisible && !animationFrameId) { - lastTime = performance.now(); - animate(); - } -}); - -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() { - // Only spawn if tab is visible and not too many meteors - if (!isTabVisible || meteorInstances.length >= 2) { - return; - } - - const spawnChance = 0.15; - if (Math.random() < spawnChance) { - const stars = document.getElementById("stars"); - const newMeteor = new Meteor(stars); - meteorInstances.push(newMeteor); - } -} - -function animate() { - const currentTime = performance.now(); - const deltaTime = currentTime - lastTime; - lastTime = currentTime; - - // Cap deltaTime to prevent huge jumps when tab is hidden - const cappedDelta = Math.min(deltaTime, 100); - - // Update stars with delta time - starInstances.forEach((star) => star.update()); - - // Update meteors and remove dead ones - for (let i = meteorInstances.length - 1; i >= 0; i--) { - if (!meteorInstances[i].update(cappedDelta)) { - meteorInstances.splice(i, 1); - } - } - - animationFrameId = requestAnimationFrame(animate); -} - -function createMeteorBurst() { - // Only burst if tab is visible - if (!isTabVisible) return; - - // Limit burst size - const burstSize = Math.min(2, 3 - meteorInstances.length); - - for (let i = 0; i < burstSize; i++) { - setTimeout(() => { - if (isTabVisible && meteorInstances.length < 3) { - const stars = document.getElementById("stars"); - const newMeteor = new Meteor(stars); - meteorInstances.push(newMeteor); - } - }, i * 300); - } -} - -let spawnInterval = null; -let burstInterval = null; - -function init() { - injectStarCSS(); - createStars(); - lastTime = performance.now(); - animate(); - - // Longer interval for spawning - spawnInterval = setInterval(() => { - if (isTabVisible) { - trySpawnMeteor(); - } - }, 3000); // Every 3 seconds instead of 2 - - // Longer interval for bursts - burstInterval = setInterval(() => { - if (isTabVisible) { - createMeteorBurst(); - } - }, 20000); // Every 20 seconds instead of 15 -} - -// Cleanup function -function cleanup() { - if (animationFrameId) { - cancelAnimationFrame(animationFrameId); - } - if (spawnInterval) { - clearInterval(spawnInterval); - } - if (burstInterval) { - clearInterval(burstInterval); - } -} - -// Handle page unload -window.addEventListener("beforeunload", cleanup); - -if (document.readyState === "loading") { - document.addEventListener("DOMContentLoaded", init); -} else { - init(); -} - -export { cleanup }; diff --git a/src/js/form.js b/src/js/form.js deleted file mode 100644 index 4dbfa2e..0000000 --- a/src/js/form.js +++ /dev/null @@ -1,22 +0,0 @@ -// 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 deleted file mode 100644 index bd2f14a..0000000 --- a/src/js/main.js +++ /dev/null @@ -1,27 +0,0 @@ -// 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 deleted file mode 100644 index 974476d..0000000 --- a/src/js/navigation.js +++ /dev/null @@ -1,106 +0,0 @@ -// 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 deleted file mode 100644 index 9dd7bf2..0000000 --- a/src/js/overview.js +++ /dev/null @@ -1,57 +0,0 @@ -// 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 deleted file mode 100644 index 2fd2d79..0000000 --- a/src/js/portfolioCard.js +++ /dev/null @@ -1,228 +0,0 @@ -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("")} -
-
-
- - Explore Project - -
-
- `; - } -} - -customElements.define("portfolio-card", PortfolioCard); diff --git a/src/js/portfolioFilter.js b/src/js/portfolioFilter.js deleted file mode 100644 index 7779c87..0000000 --- a/src/js/portfolioFilter.js +++ /dev/null @@ -1,95 +0,0 @@ -// 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 deleted file mode 100644 index e392724..0000000 --- a/src/js/sectionTracker.js +++ /dev/null @@ -1,111 +0,0 @@ -// 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 deleted file mode 100644 index 3229eb9..0000000 --- a/src/styles/styles.css +++ /dev/null @@ -1,1943 +0,0 @@ -/* 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; - } -}