Initial commit

This commit is contained in:
Daniel LaForce 2025-04-22 16:01:08 -06:00
commit 35ffe75572
51 changed files with 5459 additions and 0 deletions

49
assets/css/style.css Normal file
View File

@ -0,0 +1,49 @@
@keyframes pulse-ring {
0% {
transform: scale(0.33);
opacity: 0;
}
80%, 100% {
opacity: 0;
}
40% {
opacity: 0.3;
}
}
/* Particles */
.particles-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
z-index: 0;
}
.particle {
position: absolute;
background-color: rgba(59, 130, 246, 0.2);
border-radius: 50%;
pointer-events: none;
}
@keyframes float-particle {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(50px, -50px);
}
50% {
transform: translate(100px, 0);
}
75% {
transform: translate(50px, 50px);
}
100% {
transform: translate(0, 0);
}
}

50
assets/js/script.js Normal file
View File

@ -0,0 +1,50 @@
function initFormHandling() {
const form = document.getElementById('contact-form');
if (!form) return;
form.addEventListener('submit', async (e) => {
e.preventDefault();
const submitBtn = form.querySelector('button[type="submit"]');
const originalBtnText = submitBtn.innerHTML;
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
submitBtn.disabled = true;
const formData = new FormData(form);
const data = {
name: formData.get('name'),
email: formData.get('email'),
subject: formData.get('subject'),
message: formData.get('message')
};
try {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.details || result.error || 'Failed to send message');
}
// Show success message
showAlert('success', 'Message sent successfully! I will get back to you soon.');
form.reset();
} catch (error) {
console.error('Form submission error:', error);
showAlert('error', `Something went wrong: ${error.message}`);
} finally {
submitBtn.innerHTML = originalBtnText;
submitBtn.disabled = false;
}
});
}
// ... existing code ...

135
casestudy.html Normal file
View File

@ -0,0 +1,135 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Case Study: SharePoint & M365 Migrations | Daniel LaForce</title>
<meta name="description" content="Enterprise migration case study: Seamless transition from legacy systems to Microsoft 365 with automation, SharePoint, OneDrive, and Teams integration.">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.portfolio-header {
padding: 2rem 0 1rem;
}
.portfolio-section {
padding-top: 1rem;
padding-bottom: 2rem;
}
.project-card {
margin-top: 0;
padding: 1.5rem;
}
</style>
</head>
<body>
<br>
<br>
<br>
<!-- Header/Nav -->
<nav class="navbar">
<div class="container">
<div class="logo">
<a href="index.html">
<span class="logo-text-glow">Daniel LaForce</span>
</a>
</div>
<div class="nav-menu">
<a href="index.html#home" class="nav-link">Home</a>
<a href="index.html#portfolio" class="nav-link active">Portfolio</a>
<a href="index.html#services" class="nav-link">Services</a>
<a href="index.html#lab" class="nav-link">Live Lab</a>
<a href="resume.html" class="nav-link">Resume</a>
</div>
</div>
</nav>
<!-- Case Study Content -->
<section class="portfolio-header">
<div class="container">
<h1 class="portfolio-title">Case Study: SharePoint & M365 Migrations</h1>
<p class="portfolio-subtitle">Modernizing enterprise collaboration and storage through Microsoft 365</p>
</div>
</section>
<section class="portfolio-section">
<div class="container">
<div class="project-card">
<div class="project-content">
<h3 class="project-title">Client Overview</h3>
<p class="project-description">
A mid-sized professional services firm relied on Dropbox, Egnyte, Google Workspace, and on-prem file servers to manage daily operations. The IT environment was fragmented, increasing operational complexity and impeding secure collaboration. They needed a scalable solution to unify infrastructure, reduce support load, and enhance productivity.
</p>
<h3 class="project-title">Objectives</h3>
<ul>
<li>Consolidate file and email services under Microsoft 365</li>
<li>Minimize business disruption during migration</li>
<li>Strengthen compliance, backup, and access control</li>
<li>Enable centralized collaboration with Microsoft Teams</li>
</ul>
<br>
<h3 class="project-title">Solution Strategy</h3>
<ul>
<li>Provisioned a temporary VM to act as a synchronized landing zone for Egnyte and local file server data</li>
<li>Used Egnytes API and command-line tools to batch-export permissions and files to the sync VM</li>
<li>Ran Microsofts SharePoint Migration Tool (SPMT) with JSON-based mapping to import content into SharePoint document libraries</li>
<li>Automated pre/post migration checks and permissions auditing via PowerShell and Graph API</li>
<li>Staged migration of mail and calendar data using MigrationWiz with coexistence enabled between Google Workspace and Exchange Online</li>
<li>Provided Teams onboarding with channel templates and cross-platform training</li>
</ul>
<br>
<h3 class="project-title">Results</h3>
<ul>
<li>12.4 TB of content migrated across four platforms in under 90 days</li>
<li>Zero data loss or permission mismatches confirmed via script-based audits</li>
<li>Helpdesk load cut by 40% within the first month post-migration</li>
<li>Fully adopted Microsoft Teams structure with defined department-based channels and integrated file repositories</li>
<li>End-user training boosted post-migration satisfaction to 97%</li>
</ul>
<div class="project-skills">
<span class="skill-tag">SharePoint Online</span>
<span class="skill-tag">OneDrive</span>
<span class="skill-tag">Teams</span>
<span class="skill-tag">Exchange Online</span>
<span class="skill-tag">PowerShell</span>
<span class="skill-tag">Migration Tools</span>
<span class="skill-tag">Egnyte API</span>
<span class="skill-tag">SPMT</span>
</div>
<div class="project-links">
<a href="/index.html#portfolio" class="project-link"><i class="fas fa-arrow-left"></i> Back to Portfolio</a>
</div>
</div>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-logo">
<span class="logo-text-glow">Daniel LaForce</span>
</div>
<div class="footer-links">
<a href="/index.html#home">Home</a>
<a href="/index.html#portfolio">Portfolio</a>
<a href="/index.html#services">Services</a>
<a href="/index.html#lab">Live Lab</a>
<a href="/resume.html">Resume</a>
</div>
</div>
<div class="footer-bottom">
<p>© All rights reserved. LaForceIT.com</p>
<p class="disclaimer">Custom-built with HTML, CSS, and JavaScript.</p>
</div>
</div>
</footer>
</body>
</html>

170
construction.html Normal file
View File

@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Under Construction | LaForceIT</title>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
.construction-container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%);
position: relative;
overflow: hidden;
}
.construction-content {
text-align: center;
z-index: 1;
padding: 2rem;
max-width: 800px;
}
.construction-title {
font-size: 3rem;
color: #00ff9d;
margin-bottom: 1rem;
text-shadow: 0 0 10px rgba(0, 255, 157, 0.5);
font-family: 'JetBrains Mono', monospace;
}
.construction-subtitle {
font-size: 1.5rem;
color: #ffffff;
margin-bottom: 2rem;
opacity: 0.8;
}
.construction-status {
background: rgba(0, 255, 157, 0.1);
border: 1px solid rgba(0, 255, 157, 0.3);
padding: 1rem;
border-radius: 8px;
margin-bottom: 2rem;
font-family: 'JetBrains Mono', monospace;
}
.status-line {
color: #00ff9d;
margin: 0.5rem 0;
text-align: left;
}
.status-line::before {
content: '> ';
color: #00ff9d;
}
.construction-progress {
width: 100%;
height: 4px;
background: rgba(255, 255, 255, 0.1);
border-radius: 2px;
margin: 2rem 0;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg, #00ff9d, #00b8ff);
width: 0;
animation: progress 2s ease-in-out infinite;
}
@keyframes progress {
0% { width: 0; }
50% { width: 100%; }
100% { width: 0; }
}
.construction-back {
color: #ffffff;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: color 0.3s ease;
}
.construction-back:hover {
color: #00ff9d;
}
.binary-rain {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
opacity: 0.1;
}
</style>
</head>
<body>
<div class="construction-container">
<div class="binary-rain" id="binary-rain"></div>
<div class="construction-content">
<h1 class="construction-title">UNDER CONSTRUCTION</h1>
<p class="construction-subtitle">This service is currently being deployed and configured</p>
<div class="construction-status">
<div class="status-line">Initializing deployment sequence...</div>
<div class="status-line">Configuring infrastructure components...</div>
<div class="status-line">Deploying service containers...</div>
<div class="status-line">Establishing secure connections...</div>
<div class="status-line">Optimizing performance parameters...</div>
</div>
<div class="construction-progress">
<div class="progress-bar"></div>
</div>
<a href="https://laforceit.com" class="construction-back">
<i class="fas fa-arrow-left"></i>
Return to LaForceIT
</a>
</div>
</div>
<script>
// Create binary rain effect
const binaryRain = document.getElementById('binary-rain');
const chars = '01';
function createBinaryRain() {
const span = document.createElement('span');
span.textContent = chars.charAt(Math.floor(Math.random() * chars.length));
span.style.position = 'absolute';
span.style.left = Math.random() * 100 + '%';
span.style.top = '-20px';
span.style.color = '#00ff9d';
span.style.opacity = Math.random() * 0.5 + 0.5;
span.style.fontSize = Math.random() * 10 + 10 + 'px';
span.style.fontFamily = 'JetBrains Mono, monospace';
binaryRain.appendChild(span);
let pos = -20;
const fall = setInterval(() => {
pos += 2;
span.style.top = pos + 'px';
if (pos > window.innerHeight) {
clearInterval(fall);
span.remove();
}
}, 50);
}
setInterval(createBinaryRain, 100);
</script>
</body>
</html>

Binary file not shown.

View File

@ -0,0 +1,76 @@
/**
* Cloudflare Pages Function - /api/send-email
*/
export async function onRequestPost(context) {
const { name, email, subject, message } = await context.request.json();
try {
// Check if API key is configured
if (!context.env.MAILERSEND_API_KEY) {
throw new Error('MailerSend API key is not configured');
}
console.log('Attempting to send email with MailerSend...');
const response = await fetch("https://api.mailersend.com/v1/email", {
method: "POST",
headers: {
Authorization: "Bearer " + context.env.MAILERSEND_API_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({ from: {
email: email,
name: name
},
to: [
{
email: "upwork@example.com",
name: "Contact Form"
}
],
subject: `LaForceIT Contact Form: ${subject}`,
html: `
<h2>New Contact Message on LaForceIT.com</h2>
<p><strong>Name:</strong> ${name}</p>
<p><strong>Email:</strong> ${email}</p>
<p><strong>Message:</strong><br>${message.replace(/\n/g, "<br>")}</p>
`,
reply_to: [
{
email,
name
}
]
})
});
const responseData = await response.text();
console.log("MailerSend Response:", responseData);
if (!response.ok) {
const errorDetail = responseData ? JSON.parse(responseData) : {};
throw new Error(`MailerSend API error (${response.status}): ${JSON.stringify(errorDetail)}`);
}
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: {
'Content-Type': 'application/json'
}
});
} catch (err) {
console.error("Email Send Error:", err);
return new Response(JSON.stringify({
error: "Failed to send email",
details: err.message,
timestamp: new Date().toISOString()
}), {
status: 500,
headers: {
'Content-Type': 'application/json'
}
});
}
}

18
images/.gitkeep Normal file
View File

@ -0,0 +1,18 @@
# This file ensures the images directory exists in the repository.
# You should add the following images:
# Infrastructure Dashboard Images
# - argobox-dashboard.jpg - Screenshot of your ArgoBox dashboard
# - ansible-automation.jpg - Visualization of Ansible automation workflows
# - zero-trust.jpg - Diagram or screenshot of zero trust architecture
# - kubernetes-lab.jpg - Screenshot of K3s cluster dashboard
# Project Portfolio Images
# - prospector-pulse.jpg - Screenshot or mockup of Prospector Pulse mapping interface
# - terramappix.jpg - Screenshot or mockup of TerraMappix interface
# - cloudflare-ddns.jpg - Visual representation of the DDNS workflow
# - car-price-ml.jpg - Screenshot of the car price prediction model interface
# - wifi-cage.jpg - Photo or diagram of the Wi-Fi testing cage
# - vsadeployer.jpg - Screenshot of the VSADeployer interface
# These images should be approximately 800x450px in size for optimal display in the portfolio.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
images/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

BIN
images/argobox/sandbox.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

BIN
images/argobox/sandbox.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

BIN
images/cpe-vault/build.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

BIN
images/cpe-vault/cover.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

BIN
images/cpe-vault/page1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

BIN
images/cpe-vault/page10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
images/cpe-vault/page2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
images/cpe-vault/page3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

BIN
images/cpe-vault/page4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

BIN
images/cpe-vault/page5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

BIN
images/cpe-vault/page6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

BIN
images/cpe-vault/page7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

BIN
images/cpe-vault/page8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
images/cpe-vault/page9.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

BIN
images/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

BIN
images/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
images/full-stack/main.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
images/full-stack/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
images/og-preview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

1
images/site.webmanifest Normal file
View File

@ -0,0 +1 @@
{"name":"LaForceIT","short_name":"LaForceIT","icons":[{"src":"/images/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/images/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#1e293b","background_color":"#0f172a","display":"standalone"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 997 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

1367
index.html Normal file

File diff suppressed because it is too large Load Diff

927
resume.html Normal file
View File

@ -0,0 +1,927 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daniel LaForce | Enterprise IT Solutions Architect & Security Expert</title>
<!-- SEO Meta Tags -->
<meta name="description" content="Senior IT Professional specializing in enterprise infrastructure, cybersecurity, and digital transformation. Expert consultant for both project-based and full-time opportunities.">
<!-- Favicon -->
<link rel="icon" type="image/png" href="images/favicon.png">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- FontAwesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
<!-- CSS -->
<link rel="stylesheet" href="styles.css">
<style>
/* Resume-specific styles */
body {
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.resume-container {
max-width: 1000px;
margin: 2rem auto;
padding: 2rem;
background: var(--card-bg);
border-radius: 1rem;
box-shadow: var(--card-shadow);
}
.resume-header {
text-align: center;
margin-bottom: 3rem;
}
.resume-name {
font-size: 2.5rem;
margin-bottom: 0.5rem;
}
.resume-title {
font-size: 1.5rem;
color: var(--accent);
margin-bottom: 1.5rem;
}
.resume-contact {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 1.5rem;
margin-bottom: 2rem;
}
.resume-contact-item {
display: flex;
align-items: center;
color: var(--text-secondary);
}
.resume-contact-item i {
margin-right: 0.5rem;
color: var(--accent);
}
.resume-section {
margin-bottom: 2.5rem;
background-color: var(--card-bg);
border-radius: 1rem;
padding: 2rem;
border: 1px solid var(--border);
}
.resume-section-title {
font-size: 1.5rem;
margin-bottom: 1.5rem;
color: var(--accent);
position: relative;
padding-bottom: 0.75rem;
}
.resume-section-title::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 3px;
background: var(--accent-gradient);
border-radius: 3px;
}
.resume-job {
margin-bottom: 2rem;
}
.resume-job:last-child {
margin-bottom: 0;
}
.resume-job-header {
margin-bottom: 1rem;
}
.resume-job-title {
font-size: 1.25rem;
margin-bottom: 0.25rem;
}
.resume-job-company {
font-weight: 600;
color: var(--accent);
margin-bottom: 0.25rem;
}
.resume-job-period {
color: var(--text-secondary);
font-size: 0.9rem;
}
.resume-job-description {
color: var(--text-secondary);
margin-bottom: 1rem;
}
.resume-job-achievements {
list-style: none;
}
.resume-job-achievement {
display: flex;
margin-bottom: 0.75rem;
align-items: flex-start;
}
.resume-job-achievement i {
color: var(--accent);
margin-right: 0.75rem;
margin-top: 0.25rem;
flex-shrink: 0;
}
.resume-skills {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.resume-skill-category {
margin-bottom: 1.5rem;
}
.resume-skill-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: var(--accent);
}
.resume-skill-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.resume-skill {
background-color: rgba(59, 130, 246, 0.1);
border: 1px solid rgba(59, 130, 246, 0.3);
color: var(--accent);
font-size: 0.85rem;
font-weight: 500;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
}
.resume-education {
margin-bottom: 1.5rem;
}
.resume-education-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.25rem;
}
.resume-education-institution {
color: var(--accent);
margin-bottom: 0.25rem;
}
.resume-education-period {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.resume-education-grade {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.resume-education-skills {
margin-top: 0.5rem;
color: var(--text-secondary);
}
.resume-projects {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
}
.resume-project {
background-color: rgba(59, 130, 246, 0.1);
border-radius: 0.75rem;
padding: 1.5rem;
border: 1px solid rgba(59, 130, 246, 0.3);
}
.resume-project-title {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.75rem;
color: var(--accent);
}
.resume-project-tech {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: 0.75rem;
}
.resume-project-tech-item {
font-size: 0.8rem;
color: var(--text-secondary);
background-color: rgba(255, 255, 255, 0.1);
padding: 0.15rem 0.5rem;
border-radius: 0.25rem;
}
.resume-awards {
list-style: none;
}
.resume-award {
display: flex;
margin-bottom: 0.75rem;
}
.resume-award i {
color: var(--accent);
margin-right: 0.75rem;
}
.resume-download {
text-align: center;
margin-top: 3rem;
}
.footer {
width: 100%;
left: 0;
right: 0;
bottom: 0;
background: var(--dark-bg);
border-top: 1px solid var(--border);
padding: 2rem 0;
margin-top: auto;
}
@media (max-width: 768px) {
.resume-skills, .resume-projects {
grid-template-columns: 1fr;
}
}
.contact-links {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
margin: 1rem 0;
}
.contact-links a {
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--text-primary);
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
background: var(--secondary-bg);
transition: all var(--transition-normal);
}
.contact-links a:hover {
background: var(--accent);
color: white;
transform: translateY(-2px);
}
@media print {
.contact-links a {
color: black;
background: none;
padding: 0;
margin-right: 1rem;
}
}
/* Call to Action Styles */
.cta-banner {
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(37, 99, 235, 0.2));
border-radius: 1rem;
padding: 2.5rem;
margin-bottom: 3rem;
border: 1px solid rgba(59, 130, 246, 0.3);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
}
.cta-content {
max-width: 800px;
margin: 0 auto;
}
.cta-title {
font-size: 2rem;
color: var(--text-primary);
margin-bottom: 1rem;
text-align: center;
background: linear-gradient(135deg, #3b82f6, #2563eb);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-weight: 700;
}
.cta-description {
font-size: 1.1rem;
color: var(--text-secondary);
text-align: center;
margin-bottom: 2rem;
}
.cta-highlights {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.cta-highlight {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: rgba(59, 130, 246, 0.1);
border-radius: 0.75rem;
border: 1px solid rgba(59, 130, 246, 0.2);
transition: all var(--transition-normal);
}
.cta-highlight:hover {
transform: translateY(-2px);
background: rgba(59, 130, 246, 0.15);
border-color: rgba(59, 130, 246, 0.3);
}
.cta-highlight i {
font-size: 1.5rem;
color: var(--accent);
}
.cta-highlight span {
color: var(--text-primary);
font-weight: 500;
}
.cta-buttons {
display: flex;
justify-content: center;
gap: 1rem;
flex-wrap: wrap;
}
.cta-btn {
min-width: 200px;
text-align: center;
}
@media (max-width: 768px) {
.cta-title {
font-size: 1.75rem;
}
.cta-description {
font-size: 1rem;
}
.cta-highlight {
padding: 0.75rem;
}
.cta-btn {
width: 100%;
}
}
</style>
</head>
<body>
<!-- Bubble Animation -->
<div class="bubbles">
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
<div class="bubble"></div>
</div>
<!-- Navigation -->
<nav class="navbar">
<div class="container">
<div class="logo">
<a href="index.html">
<span class="logo-text-glow">Daniel LaForce</span>
</a>
</div>
<div class="nav-menu">
<a href="index.html" class="nav-link active">Home</a>
<a href="index.html#portfolio" class="nav-link">Portfolio</a>
<a href="index.html#services" class="nav-link">Services</a>
<a href="index.html#lab" class="nav-link">Live Lab</a>
<a href="resume.html" class="nav-link">Resume</a>
</div>
<div class="nav-buttons">
<a href="dashboard.html" class="dashboard-link" target="_blank">
<span class="live-indicator"></span>
<span>Live Dashboard</span>
</a>
<button class="menu-toggle" aria-label="Toggle menu">
<i class="fas fa-bars"></i>
</button>
</div>
</div>
</nav>
<br>
<!-- Resume Content -->
<div class="resume-container">
<div class="resume-header">
<h1 class="resume-name">Daniel LaForce</h1>
<h2 class="resume-title">Enterprise IT Solutions Architect & Security Expert</h2>
</div>
<!-- Experience Section -->
<div class="resume-section">
<h2 class="resume-section-title">Professional Experience</h2>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Freelance IT Consultant Infrastructure, Security & GIS Solutions</h3>
<div class="resume-job-company">Inovin LLC</div>
<div class="resume-job-period">April 2023 Present | Colorado Springs, CO</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed TerraTracer, a GIS mapping platform used by independent mining claim prospectors to automate boundary plotting, terrain-informed site selection, and BLM/state compliance, reducing manual research by 85%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Consulted on virtualization and DevOps projects for SMB clients, implementing Proxmox/VMware solutions, containerizing legacy apps with Docker, and orchestrating microservices with Kubernetes.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Built secure cloud environments integrating Azure AD, SSO, and VPN/firewall solutions, increasing operational resilience while aligning with HIPAA and zero-trust principles.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Automated infrastructure tasks via PowerShell, Python, and Bash, optimizing system deployment, backup routines, and monitoring pipelines.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Administered Azure AD security policies and MFA enforcement, reducing monthly vulnerabilities by at least 20% across client environments.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Served as Interim Virtual Chief Security Officer for 11 clients, conducting penetration testing using BURP Professional and managing enterprise security stack deployment including Blackpoint & Webroot (Endpoint), DNSFilter (Network), and ThreatLocker (Application Control).</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Project Engineer</h3>
<div class="resume-job-company">Anchor Point IT Solutions</div>
<div class="resume-job-period">December 2023 - June 2024</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Executed 5 Microsoft 365 and SharePoint migrations with downtime reduced by 60%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Implemented comprehensive security stack including BlueMira & DUO (Identity), SentinelOne (Endpoint), ConnectSecure (Network), and Email Mesh Security.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Reduced security incidents by 83% through security implementations and improved system updates by 60%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed approximately 235 clients with environment sizes ranging from 30 to 1000 people.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Network Engineer II</h3>
<div class="resume-job-company">NOVUS Professional Services, Inc.</div>
<div class="resume-job-period">August 2022 - March 2023</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Designed and implemented a WiFi testing cage for remote firmware testing of router models (Wave2, WiFi6).</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed Python automation for Plume device registration and Ansible scripts for network tasks.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed RF testing and signal verification across 9 headends and maintained network connectivity for ~100 routers across two sites.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Field Engineer</h3>
<div class="resume-job-company">COMPUTEK Dental Systems</div>
<div class="resume-job-period">December 2021 - August 2022</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed IT infrastructure for 300+ dental practices (3700+ workstations, ~300 Windows Servers).</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Developed VSA Deployer application (Kaseya VSA RMM) for agent installation, reducing deployment time by 80%.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Maintained server, Hyper-V VM, and MySQL/MSSQL backups using N-Able Backups, Windows Server Backups and AIS.</span>
</div>
</div>
</div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">End-to-End Systems Engineer</h3>
<div class="resume-job-company">Lockheed Martin</div>
<div class="resume-job-period">June 2018 - December 2019</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Maintained 2 IRON databases (AIMS and RAPID) with ~1800 configurations each, ensuring 100% database accuracy.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Collaborated with engineering team to implement Remote Tracking Station (RTS) configurations.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Identified and documented an average of 27 critical defects every month.</span>
</div>
</div>
</div>
</div>
<!-- Skills Section -->
<div class="resume-section">
<h2 class="resume-section-title">Technical Skills</h2>
<div class="resume-skills">
<div class="resume-skill-category">
<h3 class="resume-skill-title">Cloud & Infrastructure</h3>
<div class="resume-skill-list">
<span class="resume-skill">Microsoft Azure</span>
<span class="resume-skill">Azure AD</span>
<span class="resume-skill">SharePoint</span>
<span class="resume-skill">Teams</span>
<span class="resume-skill">AWS</span>
<span class="resume-skill">EC2</span>
<span class="resume-skill">S3</span>
<span class="resume-skill">GCP</span>
<span class="resume-skill">VMware ESXi/vSphere</span>
<span class="resume-skill">Hyper-V</span>
<span class="resume-skill">Docker</span>
<span class="resume-skill">Kubernetes (K3s)</span>
<span class="resume-skill">ProxMox</span>
<span class="resume-skill">Traefik</span>
<span class="resume-skill">CI/CD</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Networking</h3>
<div class="resume-skill-list">
<span class="resume-skill">LAN/WAN</span>
<span class="resume-skill">VPN</span>
<span class="resume-skill">OSPF</span>
<span class="resume-skill">EIGRP</span>
<span class="resume-skill">STP</span>
<span class="resume-skill">HSRP</span>
<span class="resume-skill">VTP</span>
<span class="resume-skill">IPv4/IPv6</span>
<span class="resume-skill">ACLs</span>
<span class="resume-skill">NAT/PAT</span>
<span class="resume-skill">DNS/DHCP</span>
<span class="resume-skill">VLANs</span>
<span class="resume-skill">QoS</span>
<span class="resume-skill">Cisco Routers</span>
<span class="resume-skill">Catalyst Switches</span>
<span class="resume-skill">ASA Firewalls</span>
<span class="resume-skill">UniFi Systems</span>
<span class="resume-skill">pfSense</span>
<span class="resume-skill">OPNsense</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Programming/Scripting</h3>
<div class="resume-skill-list">
<span class="resume-skill">Python</span>
<span class="resume-skill">JavaScript (Node.js)</span>
<span class="resume-skill">PowerShell</span>
<span class="resume-skill">Bash</span>
<span class="resume-skill">C/C++</span>
<span class="resume-skill">SQL</span>
<span class="resume-skill">MySQL/MSSQL</span>
<span class="resume-skill">AutoHotkey</span>
<span class="resume-skill">Ansible</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Security</h3>
<div class="resume-skill-list">
<span class="resume-skill">Penetration Testing</span>
<span class="resume-skill">BURP Professional</span>
<span class="resume-skill">SentinelOne</span>
<span class="resume-skill">Blackpoint</span>
<span class="resume-skill">Webroot</span>
<span class="resume-skill">ThreatLocker</span>
<span class="resume-skill">Zero-Trust Architecture</span>
<span class="resume-skill">HIPAA Compliance</span>
<span class="resume-skill">BlueMira</span>
<span class="resume-skill">DUO</span>
<span class="resume-skill">DNSFilter</span>
<span class="resume-skill">Email Mesh Security</span>
<span class="resume-skill">MFA</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Operating Systems</h3>
<div class="resume-skill-list">
<span class="resume-skill">Windows Server</span>
<span class="resume-skill">Active Directory</span>
<span class="resume-skill">Group Policy</span>
<span class="resume-skill">Exchange Server</span>
<span class="resume-skill">Linux</span>
<span class="resume-skill">Ubuntu</span>
<span class="resume-skill">CentOS</span>
<span class="resume-skill">Debian</span>
<span class="resume-skill">Fedora</span>
<span class="resume-skill">Kali Linux</span>
<span class="resume-skill">Cisco IOS</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">GIS & Data Science</h3>
<div class="resume-skill-list">
<span class="resume-skill">Geospatial Mapping</span>
<span class="resume-skill">GeoPandas</span>
<span class="resume-skill">GDAL/OGR</span>
<span class="resume-skill">KML Generation</span>
<span class="resume-skill">Data Visualization</span>
<span class="resume-skill">Machine Learning</span>
<span class="resume-skill">TensorFlow</span>
<span class="resume-skill">PyTorch</span>
<span class="resume-skill">Scikit-learn</span>
<span class="resume-skill">Pandas</span>
<span class="resume-skill">NumPy</span>
<span class="resume-skill">Matplotlib</span>
<span class="resume-skill">Seaborn</span>
</div>
</div>
<div class="resume-skill-category">
<h3 class="resume-skill-title">Management & PSA Tools</h3>
<div class="resume-skill-list">
<span class="resume-skill">N-able N-central</span>
<span class="resume-skill">Kaseya VSA</span>
<span class="resume-skill">ConnectWise Automate</span>
<span class="resume-skill">ConnectWise PSA</span>
<span class="resume-skill">PRTG</span>
<span class="resume-skill">SolarWinds</span>
<span class="resume-skill">Addigy</span>
<span class="resume-skill">ImmyBot</span>
<span class="resume-skill">Commit Ticket CRM</span>
</div>
</div>
</div>
</div>
<!-- Education Section -->
<div class="resume-section">
<h2 class="resume-section-title">Education</h2>
<div class="resume-education">
<h3 class="resume-education-title">Bachelor of Science, Computer Science</h3>
<div class="resume-education-institution">Western Governors University</div>
<div class="resume-education-period">June 2019 - April 2023</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Activities and societies: Sigma Alpha Pi Honors Society (The National Society of Leadership and Success)</span>
</div>
</div>
<div class="resume-education-skills">
<strong>Skills:</strong> Python (Programming Language) · Project Management · Machine Learning · Team Leadership
</div>
</div>
<div class="resume-education">
<h3 class="resume-education-title">Cyber Ops</h3>
<div class="resume-education-institution">Cisco Networking Academy</div>
<div class="resume-education-period">2018</div>
<div class="resume-education-skills">
<strong>Skills:</strong> Networking · Cyber-security · Cisco Technologies
</div>
</div>
<div class="resume-education">
<h3 class="resume-education-title">Computer Science and Innovation</h3>
<div class="resume-education-institution">University of Colorado Colorado Springs (UCCS)</div>
<div class="resume-education-period">January 2017 - December 2017</div>
<div class="resume-education-grade">Grade: 4.0</div>
<div class="resume-education-skills">
<strong>Skills:</strong> C++ · Team Leadership
</div>
</div>
<div class="resume-education">
<h3 class="resume-education-title">Associate's degree, General Studies</h3>
<div class="resume-education-institution">Pikes Peak State College</div>
<div class="resume-education-period">2015 - 2018</div>
<div class="resume-education-grade">Grade: 4.0</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Activities and societies: Phi Theta Kappa Honor Society</span>
</div>
</div>
<div class="resume-education-skills">
<strong>Skills:</strong> Linux · Virtual Server · C++ · System Administration · Wireless
</div>
</div>
<div class="resume-education">
<h3 class="resume-education-title">Associate's Degree, Computer Wide Area Networks</h3>
<div class="resume-education-institution">Front Range Community College</div>
<div class="resume-education-period">2014 - 2016</div>
<div class="resume-education-grade">Grade: 3.87</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Activities and societies: Phi Theta Kappa Honor Society</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-award"></i>
<span>Magna Cum Laude honors</span>
</div>
</div>
<div class="resume-education-skills">
<strong>Skills:</strong> Virtual Server · C++ · Networking · Wireless
</div>
</div>
</div>
<!-- Certifications Section -->
<div class="resume-section">
<h2 class="resume-section-title">Certifications</h2>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Project+ (CompTIA)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Network+ (FRCC)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>A+ (FRCC)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>CCNA Cyber Ops (2021)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>CCNA Routing & Switching (2021)</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-certificate"></i>
<span>Virtual Cyber Security Officer Training (vCSO Advanced)</span>
</div>
</div>
</div>
<!-- Projects Section -->
<div class="resume-section">
<h2 class="resume-section-title">Notable Projects</h2>
<div class="resume-projects">
<div class="resume-project">
<h3 class="resume-project-title">Enterprise Data Center Deployment</h3>
<p>Complete data center build-out from ground up, including rack design, power distribution, cooling optimization, and redundant network topology implementation. Integrated custom-fabricated components using mechanical engineering principles and 3D-printed mounting solutions.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Infrastructure Design</span>
<span class="resume-project-tech-item">Network Engineering</span>
<span class="resume-project-tech-item">CAD/3D Modeling</span>
<span class="resume-project-tech-item">Thermal Management</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">TerraMappix Land Claim Mapping Service</h3>
<p>Developed a Python/Node.js geospatial engine powering TerraMappix that converts BLM coordinates and legal metes-and-bounds into precise, GIS-ready property maps with accuracy down to 1.08 inches, built for mining firms and land managers.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Python</span>
<span class="resume-project-tech-item">Node.js</span>
<span class="resume-project-tech-item">Geospatial Analysis</span>
<span class="resume-project-tech-item">GIS</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">Infrastructure Monitoring Dashboard</h3>
<p>A custom, real-time monitoring solution for home lab infrastructure featuring metrics visualization via Grafana, service status tracking, and resource allocation management, built with web technologies and pulling data from Prometheus.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Kubernetes (K3s)</span>
<span class="resume-project-tech-item">Prometheus</span>
<span class="resume-project-tech-item">Grafana</span>
<span class="resume-project-tech-item">Docker</span>
</div>
</div>
<div class="resume-project">
<h3 class="resume-project-title">CPE WiFi Firmware Test Bed Prototype</h3>
<p>Designed and built a sophisticated testing environment for customer premises equipment (CPE) with remote access capabilities for firmware development and QA testing, including thermal safeguards and optimized wiring structure with Visio diagrams.</p>
<div class="resume-project-tech">
<span class="resume-project-tech-item">Network Engineering</span>
<span class="resume-project-tech-item">Visio/Diagramming</span>
<span class="resume-project-tech-item">Hardware Integration</span>
<span class="resume-project-tech-item">Firmware Testing</span>
</div>
</div>
</div>
</div>
<div class="resume-download">
<!-- Download button removed for Upwork compliance -->
</div>
</div>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-logo">
<span class="logo-text-glow">Daniel LaForce</span>
</div>
<div class="footer-links">
<a href="#home">Home</a>
<a href="#portfolio">Portfolio</a>
<a href="#services">Services</a>
<a href="#lab">Live Lab</a>
<a href="resume.html">Resume</a>
</div>
</div>
<div class="footer-bottom">
<p>© All rights reserved. LaForceIT.com</p>
<p class="disclaimer">Custom-built with HTML, CSS, and JavaScript.</p>
</div>
</div>
</footer>
<!-- JavaScript -->
<script src="script.js"></script>
</body>
</html>

600
script.js Normal file
View File

@ -0,0 +1,600 @@
/**
* Main JavaScript file for argobox.com
* Handles animations, interactions, and dynamic content
*/
document.addEventListener('DOMContentLoaded', function() {
// Initialize all website functionality
initNavigation();
initParticlesAndIcons();
initRoleAnimation();
initTerminalTyping();
initSolutionsCarousel();
initScrollReveal();
updateMetrics();
updateYear();
// Initialize form handling
const contactForm = document.getElementById('contact-form');
if (contactForm) {
initFormHandling(contactForm);
}
// Highlight navigation on scroll
setupScrollSpy();
// Setup role switching with improved timing
setupRoleSwitching();
// Other initializations...
setupFloatingIcons();
setupParticles();
setupRevealAnimations();
initializeSlider();
// Contact form handling
setupContactForm();
// Mobile menu toggle
document.querySelector('.menu-toggle').addEventListener('click', function() {
document.querySelector('.nav-menu').classList.toggle('active');
});
// Navbar effects on scroll
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 50) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
});
});
/**
* Set up navigation functionality - mobile menu and scroll spy
*/
function initNavigation() {
// Mobile menu toggle
const menuToggle = document.querySelector('.menu-toggle');
const navMenu = document.querySelector('.nav-menu');
if (menuToggle && navMenu) {
menuToggle.addEventListener('click', function() {
navMenu.classList.toggle('active');
menuToggle.setAttribute('aria-expanded',
menuToggle.getAttribute('aria-expanded') === 'true' ? 'false' : 'true');
});
}
// Navigation scroll spy
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
function updateActiveNavLink() {
let scrollPosition = window.scrollY + 100;
sections.forEach(section => {
const sectionTop = section.offsetTop;
const sectionHeight = section.offsetHeight;
const sectionId = section.getAttribute('id');
if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) {
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${sectionId}`) {
link.classList.add('active');
}
});
}
});
}
// Navbar style change on scroll
const navbar = document.querySelector('.navbar');
function updateNavbarStyle() {
if (window.scrollY > 50) {
navbar?.classList.add('scrolled');
} else {
navbar?.classList.remove('scrolled');
}
}
window.addEventListener('scroll', () => {
updateActiveNavLink();
updateNavbarStyle();
});
// Initial call to set correct states
updateActiveNavLink();
updateNavbarStyle();
}
/**
* Create background particles and floating tech icons
*/
function initParticlesAndIcons() {
createBackgroundParticles();
createFloatingIcons();
}
/**
* Create animated background particles
*/
function createBackgroundParticles() {
const particlesContainer = document.getElementById('particles-container');
if (!particlesContainer) return;
particlesContainer.innerHTML = '';
for (let i = 0; i < 40; i++) {
const particle = document.createElement('div');
particle.classList.add('particle');
// Random size, opacity, and position
const size = Math.random() * 4 + 1;
const opacity = Math.random() * 0.3 + 0.1;
particle.style.width = `${size}px`;
particle.style.height = `${size}px`;
particle.style.opacity = opacity;
// Position randomly with some clustering toward top areas
const xPos = Math.random() * 100;
const yPos = Math.random() * 100;
particle.style.left = `${xPos}%`;
particle.style.top = `${yPos}%`;
// Animation properties
const duration = Math.random() * 20 + 10;
particle.style.animationDuration = `${duration}s`;
particle.style.animationDelay = `${Math.random() * -duration}s`;
// Add particle animation
particle.style.animation = `float-particle ${duration}s linear infinite`;
particlesContainer.appendChild(particle);
}
}
/**
* Create floating tech icons in the background
*/
function createFloatingIcons() {
const iconContainer = document.getElementById('floating-icons');
if (!iconContainer) return;
iconContainer.innerHTML = '';
// Tech-related unicode symbols and fontawesome classes
const icons = [
'⚙️', '💻', '🔒', '🔌', '🌐', '☁️', '📊',
'fa-server', 'fa-network-wired', 'fa-database',
'fa-code-branch', 'fa-cloud', 'fa-shield-alt'
];
for (let i = 0; i < 12; i++) {
const icon = document.createElement('div');
icon.classList.add('floating-icon');
const iconType = icons[Math.floor(Math.random() * icons.length)];
// Handle both unicode and font awesome
if (iconType.startsWith('fa-')) {
const faIcon = document.createElement('i');
faIcon.className = `fas ${iconType}`;
icon.appendChild(faIcon);
} else {
icon.textContent = iconType;
}
// Random size and position
const size = Math.random() * 24 + 16;
icon.style.fontSize = `${size}px`;
// Position
icon.style.left = `${Math.random() * 100}%`;
icon.style.bottom = `-50px`;
// Animation
icon.style.animationDuration = `${Math.random() * 30 + 20}s`;
icon.style.animationDelay = `${Math.random() * 10}s`;
iconContainer.appendChild(icon);
}
}
/**
* Initialize role rotation in the hero section
*/
function initRoleAnimation() {
const roles = document.querySelectorAll('.role');
const description = document.getElementById('role-description');
let currentIndex = 0;
function updateRole() {
roles.forEach(role => role.classList.remove('active'));
roles[currentIndex].classList.add('active');
description.textContent = roles[currentIndex].getAttribute('data-description');
description.style.opacity = '0';
setTimeout(() => {
description.style.opacity = '1';
}, 100);
currentIndex = (currentIndex + 1) % roles.length;
}
updateRole(); // Set initial state
setInterval(updateRole, 5000); // Switch roles every 5 seconds
}
/**
* Initialize terminal typing animation in the hero section
*/
function initTerminalTyping() {
const terminalText = document.getElementById('terminal-text');
if (!terminalText) return;
const terminalMessages = [
"> Ready for deployment...",
"> Reducing operational costs by 30%",
"> Improving system reliability to 99.9%",
"> Accelerating digital transformation",
"> Enhancing security compliance",
"> Streamlining IT workflows",
"> Optimizing infrastructure performance",
"> Implementing best practices",
"> Supporting business objectives"
];
let currentMessage = 0;
function typeMessage(message, index = 0) {
if (index < message.length) {
terminalText.textContent = message.substring(0, index + 1);
setTimeout(() => typeMessage(message, index + 1), 50 + Math.random() * 50);
} else {
// Wait before clearing and typing next message
setTimeout(clearAndTypeNext, 3000);
}
}
function clearAndTypeNext() {
// Clear the current text with a backspace effect
const currentText = terminalText.textContent;
function backspace(length = currentText.length) {
if (length > 0) {
terminalText.textContent = currentText.substring(0, length - 1);
setTimeout(() => backspace(length - 1), 20);
} else {
// Move to next message
currentMessage = (currentMessage + 1) % terminalMessages.length;
setTimeout(() => typeMessage(terminalMessages[currentMessage]), 500);
}
}
backspace();
}
// Start the typing animation with the first message
typeMessage(terminalMessages[0]);
}
/**
* Initialize the solutions carousel
*/
function initSolutionsCarousel() {
const slides = document.querySelectorAll('.solution-slide');
const dots = document.querySelectorAll('.slider-dot');
if (slides.length === 0 || dots.length === 0) return;
let currentSlide = 0;
let slideInterval;
function showSlide(index) {
// Hide all slides
slides.forEach(slide => slide.classList.remove('active'));
dots.forEach(dot => dot.classList.remove('active'));
// Show selected slide
slides[index].classList.add('active');
dots[index].classList.add('active');
currentSlide = index;
}
function nextSlide() {
const next = (currentSlide + 1) % slides.length;
showSlide(next);
}
// Add click events to dots
dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
clearInterval(slideInterval);
showSlide(index);
// Restart automatic rotation
slideInterval = setInterval(nextSlide, 5000);
});
});
// Start automatic rotation
slideInterval = setInterval(nextSlide, 5000);
// Show first slide initially
showSlide(0);
}
/**
* Add scroll reveal animations to elements
*/
function initScrollReveal() {
const revealElements = document.querySelectorAll('.section-header, .service-card, .project-card, .lab-card, .timeline-item, .contact-item');
revealElements.forEach(element => {
element.classList.add('reveal');
});
function checkReveal() {
revealElements.forEach(element => {
const elementTop = element.getBoundingClientRect().top;
const elementVisible = 150;
if (elementTop < window.innerHeight - elementVisible) {
element.classList.add('active');
}
});
}
// Initial check
checkReveal();
// Check on scroll
window.addEventListener('scroll', checkReveal);
}
/**
* Update metrics values periodically to simulate live data
*/
function updateMetrics() {
const metrics = {
'CPU Usage': { min: 30, max: 60, element: null },
'Memory': { min: 45, max: 70, element: null },
'Storage': { min: 60, max: 75, element: null },
'Network': { min: 15, max: 40, element: null }
};
// Get all metric elements
document.querySelectorAll('.metric').forEach(metric => {
const nameElement = metric.querySelector('.metric-name');
if (nameElement && metrics[nameElement.textContent]) {
metrics[nameElement.textContent].element = metric;
}
});
function updateMetricValues() {
Object.keys(metrics).forEach(key => {
const metric = metrics[key];
if (!metric.element) return;
const valueEl = metric.element.querySelector('.metric-value');
const progressEl = metric.element.querySelector('.metric-progress');
if (valueEl && progressEl) {
const newValue = Math.floor(Math.random() * (metric.max - metric.min)) + metric.min;
valueEl.textContent = `${newValue}%`;
progressEl.style.width = `${newValue}%`;
}
});
}
// Update metrics every 5 seconds
setInterval(updateMetricValues, 5000);
}
/**
* Initialize contact form handling
*/
function initFormHandling(form) {
// Prevent multiple initializations
if (form.hasAttribute('data-initialized')) return;
form.setAttribute('data-initialized', 'true');
form.addEventListener('submit', async function (e) {
e.preventDefault();
const submitButton = form.querySelector('button[type="submit"]');
const originalButtonText = submitButton.innerHTML;
submitButton.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
submitButton.disabled = true;
const notification = document.getElementById('form-notification');
const notificationIcon = notification.querySelector('i');
const notificationText = notification.querySelector('.notification-text');
// Hide any existing notification with animation
if (notification.style.display === 'flex') {
notification.classList.add('hiding');
await new Promise(resolve => setTimeout(resolve, 300));
notification.classList.remove('hiding');
notification.style.display = 'none';
}
const formData = {
name: form.elements['name'].value,
email: form.elements['email'].value,
subject: form.elements['subject'].value,
message: form.elements['message'].value
};
try {
const res = await fetch("/api/send-email", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(formData)
});
const data = await res.json();
notification.style.display = 'flex';
if (res.ok) {
notification.classList.remove('error');
notification.classList.add('success');
notificationIcon.className = 'fas fa-check-circle';
notificationText.textContent = "Message sent successfully! We'll get back to you soon.";
form.reset();
} else {
notification.classList.remove('success');
notification.classList.add('error');
notificationIcon.className = 'fas fa-exclamation-circle';
notificationText.textContent = data.error + (data.details ? `: ${data.details}` : '');
}
} catch (error) {
console.error("Form submission error:", error);
notification.style.display = 'flex';
notification.classList.remove('success');
notification.classList.add('error');
notificationIcon.className = 'fas fa-exclamation-circle';
notificationText.textContent = `Error: ${error.message}`;
} finally {
submitButton.innerHTML = originalButtonText;
submitButton.disabled = false;
// Hide notification after 5 seconds with animation
setTimeout(() => {
notification.classList.add('hiding');
setTimeout(() => {
notification.classList.remove('hiding');
notification.style.display = 'none';
}, 300);
}, 5000);
}
});
}
/**
* Update copyright year in the footer
*/
function updateYear() {
const yearElement = document.getElementById('current-year');
if (yearElement) {
yearElement.textContent = new Date().getFullYear();
}
}
/**
* Sets up scroll spy functionality to highlight nav links
* as the user scrolls through different sections
*/
function setupScrollSpy() {
const sections = document.querySelectorAll('section[id]');
const navLinks = document.querySelectorAll('.nav-link');
window.addEventListener('scroll', function() {
let current = '';
sections.forEach(section => {
const sectionTop = section.offsetTop - 100;
const sectionHeight = section.offsetHeight;
if (window.scrollY >= sectionTop && window.scrollY < sectionTop + sectionHeight) {
current = section.getAttribute('id');
}
});
navLinks.forEach(link => {
link.classList.remove('active');
if (link.getAttribute('href') === `#${current}`) {
link.classList.add('active');
}
});
});
}
/**
* Sets up automated role switching with better timing and transitions
*/
function setupRoleSwitching() {
const roles = document.querySelectorAll('.role');
const roleDescription = document.getElementById('role-description');
let currentRoleIndex = 0;
// Initial role description
if (roles.length > 0 && roleDescription) {
roleDescription.textContent = roles[0].getAttribute('data-description');
roles[0].classList.add('active');
}
// Switch roles every 5 seconds with fade transition
setInterval(() => {
// Remove active class from current role
roles[currentRoleIndex].classList.remove('active');
// Move to the next role or back to the first
currentRoleIndex = (currentRoleIndex + 1) % roles.length;
// Add active class to new role
roles[currentRoleIndex].classList.add('active');
// Update the role description with fade effect
if (roleDescription) {
roleDescription.style.opacity = '0';
setTimeout(() => {
roleDescription.textContent = roles[currentRoleIndex].getAttribute('data-description');
roleDescription.style.opacity = '1';
}, 300);
}
}, 5000);
}
// Replace the existing setupFloatingIcons with this improved version
function setupFloatingIcons() {
const container = document.getElementById('floating-icons');
if (!container) return;
// Clear existing icons
container.innerHTML = '';
// Tech icons to display
const icons = [
'fa-server', 'fa-network-wired', 'fa-shield-alt',
'fa-cloud', 'fa-code-branch', 'fa-database',
'fa-laptop-code', 'fa-lock', 'fa-terminal'
];
// Create floating icons
icons.forEach(icon => {
const iconElement = document.createElement('div');
iconElement.className = 'floating-icon';
iconElement.innerHTML = `<i class="fas ${icon}"></i>`;
// Random starting position
const randomX = Math.floor(Math.random() * 100);
const randomY = Math.floor(Math.random() * 100);
const randomDelay = Math.random() * 5;
const randomDuration = 20 + Math.random() * 10;
// Apply styles
iconElement.style.left = `${randomX}%`;
iconElement.style.top = `${randomY}%`;
iconElement.style.animationDelay = `${randomDelay}s`;
iconElement.style.animationDuration = `${randomDuration}s`;
// Add to container
container.appendChild(iconElement);
});
}
// More existing code...

2066
styles.css Normal file

File diff suppressed because it is too large Load Diff