Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,7 @@ <h1 class="heading">Keep In Touch</h1>


<script src="script.js"></script>
<!-- Toast Container -->
<div id="toast-container"></div>
</body>
</html>
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

129 changes: 81 additions & 48 deletions script.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,18 +63,16 @@ document.addEventListener("DOMContentLoaded", () => {
e.stopPropagation();
});




// --- Contact Form Handling ---
const contactForm = document.getElementById("contact-form");
if (contactForm) {
contactForm.addEventListener("submit", function (e) {
e.preventDefault();
if (!this.checkValidity()) {
this.reportValidity(); // Show native browser messages
return;
}
if (!this.checkValidity()) {
this.reportValidity(); // Show native browser messages
return;
}

const formData = new FormData(this);
const button = this.querySelector('button[type="submit"]');
const buttonText = button.querySelector(".button-text");
Expand All @@ -92,76 +90,111 @@ document.addEventListener("DOMContentLoaded", () => {
loading.style.display = "none";
button.disabled = false;

alert("Thank you for your message! We'll get back to you soon.");
showToast("Thank you for your message! We'll get back to you soon.");
}, 2000);
});
}
const NUM_TRAILS = 30;
const snakeDots = [];

for (let i = 0; i < NUM_TRAILS; i++) {
const dot = document.createElement("div");
dot.classList.add("snake-dot");
document.body.appendChild(dot);
snakeDots.push({
el: dot,
x: window.innerWidth / 2,
y: window.innerHeight / 2,
scale: 1 - i * 0.02,
opacity: 1 - i * 0.02
});
}

let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
// --- Toast Notification ---
function showToast(message) {
let toastContainer = document.getElementById("toast-container");

if (!toastContainer) {
toastContainer = document.createElement("div");
toastContainer.id = "toast-container";
toastContainer.style.position = "fixed";
toastContainer.style.top = "20px";
toastContainer.style.right = "20px";
toastContainer.style.zIndex = "10000";
document.body.appendChild(toastContainer);
}

document.addEventListener("mousemove", (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});
const toast = document.createElement("div");
toast.className = "toast";
toast.textContent = message;

Object.assign(toast.style, {
backgroundColor: "#28a745",
color: "#fff",
padding: "12px 20px",
borderRadius: "5px",
marginTop: "10px",
opacity: "0.95",
animation: "fadein 0.5s, fadeout 0.5s 2.5s",
});

function animateSnakeCursor() {
let x = mouseX;
let y = mouseY;
toastContainer.appendChild(toast);

snakeDots.forEach((dot, i) => {
const next = snakeDots[i + 1] || { x, y };
setTimeout(() => {
toast.remove();
}, 3000);
}

// Faster follow speed
dot.x += (x - dot.x) * 0.35;
dot.y += (y - dot.y) * 0.35;
// --- Snake Cursor Trail ---
const NUM_TRAILS = 30;
const snakeDots = [];

for (let i = 0; i < NUM_TRAILS; i++) {
const dot = document.createElement("div");
dot.classList.add("snake-dot");
document.body.appendChild(dot);
snakeDots.push({
el: dot,
x: window.innerWidth / 2,
y: window.innerHeight / 2,
scale: 1 - i * 0.02,
opacity: 1 - i * 0.02
});
}

dot.el.style.left = `${dot.x}px`;
dot.el.style.top = `${dot.y}px`;
dot.el.style.transform = `translate(-50%, -50%) scale(${dot.scale})`;
dot.el.style.opacity = dot.opacity;
let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;

x = dot.x;
y = dot.y;
document.addEventListener("mousemove", (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});

requestAnimationFrame(animateSnakeCursor);
}
function animateSnakeCursor() {
let x = mouseX;
let y = mouseY;

snakeDots.forEach((dot, i) => {
const next = snakeDots[i + 1] || { x, y };

animateSnakeCursor();
dot.x += (x - dot.x) * 0.35;
dot.y += (y - dot.y) * 0.35;

dot.el.style.left = `${dot.x}px`;
dot.el.style.top = `${dot.y}px`;
dot.el.style.transform = `translate(-50%, -50%) scale(${dot.scale})`;
dot.el.style.opacity = dot.opacity;

x = dot.x;
y = dot.y;
});

requestAnimationFrame(animateSnakeCursor);
}

animateSnakeCursor();

// --- Set Current Year ---
const currentYearElement = document.getElementById("currentYear");
if (currentYearElement) {
currentYearElement.textContent = new Date().getFullYear();
}
});

const currentPath = window.location.pathname.split("/").pop();

// Navbar
document
.querySelectorAll(".nav-link, .mobile-menu-link, .footer-ul li a")
.forEach((link) => {
if (link.getAttribute("href").includes(currentPath)) {
link.classList.add("active");
}
// Highlight dropdown 'Components' if any of its child pages is active

const componentPages = ["website.html", "games.html", "ml.html"];
const dropdownToggle = document.querySelector(".dropdown-toggle");

Expand Down
32 changes: 0 additions & 32 deletions style.css
Original file line number Diff line number Diff line change
Expand Up @@ -296,34 +296,6 @@ nav a:hover,
background: rgba(255, 255, 255, 0.1);
}

/* Header */
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #ffffff;
padding: 4rem 2rem;
text-align: center;
position: relative;
overflow: hidden;
}

header::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="1" fill="rgba(255,255,255,0.1)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
animation: float 20s ease-in-out infinite;
opacity: 0.3;
}

@keyframes float {
0%, 100% { transform: translateX(0) translateY(0) rotate(0deg); }
25% { transform: translateX(-20px) translateY(-20px) rotate(90deg); }
50% { transform: translateX(20px) translateY(-10px) rotate(180deg); }
75% { transform: translateX(-10px) translateY(20px) rotate(270deg); }
}

header h1 {
font-size: clamp(2rem, 5vw, 4rem);
Expand Down Expand Up @@ -893,8 +865,4 @@ footer::before {
border-radius: 50%;
border-top-color: #fff;
animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
to { transform: rotate(360deg); }
}