Update contact details, enhance footer and resume sections, improve form notification styles, and fix container metrics in index.html

This commit is contained in:
Daniel LaForce 2025-04-10 00:47:07 -06:00
parent 606be6d044
commit e4f6a2542f
6 changed files with 231 additions and 80 deletions

View File

@ -1 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} {"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"}

View File

@ -124,7 +124,7 @@
<div class="terminal-line success">> CPU load: Normal</div> <div class="terminal-line success">> CPU load: Normal</div>
<div class="terminal-line success">> RAM usage: 42%</div> <div class="terminal-line success">> RAM usage: 42%</div>
<div class="terminal-line success">> Network: Stable</div> <div class="terminal-line success">> Network: Stable</div>
<div class="terminal-line info">> Containers: 16 running</div> <div class="terminal-line info">> Containers: 23 running</div>
<div class="terminal-line warning">> Backing up critical data...</div> <div class="terminal-line warning">> Backing up critical data...</div>
<div class="terminal-line">> Status: All systems operational</div> <div class="terminal-line">> Status: All systems operational</div>
</div> </div>
@ -589,7 +589,7 @@
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
</div> </div>
<h3 class="contact-title">Email</h3> <h3 class="contact-title">Email</h3>
<p><a href="mailto:daniel.laforce@argobox.com">daniel.laforce@argobox.com</a></p> <a href="mailto:daniel@laforceit.com">daniel@laforceit.com</a>
</div> </div>
<div class="contact-item"> <div class="contact-item">
@ -597,7 +597,7 @@
<i class="fab fa-linkedin"></i> <i class="fab fa-linkedin"></i>
</div> </div>
<h3 class="contact-title">LinkedIn</h3> <h3 class="contact-title">LinkedIn</h3>
<p><a href="https://www.linkedin.com/in/danlaforce" target="_blank">linkedin.com/in/danlaforce</a></p> <p><a href="https://www.linkedin.com/in/daniellaforce" target="_blank">linkedin.com/in/daniellaforce</a></p>
</div> </div>
<div class="contact-item"> <div class="contact-item">
@ -605,7 +605,7 @@
<i class="fab fa-github"></i> <i class="fab fa-github"></i>
</div> </div>
<h3 class="contact-title">GitHub</h3> <h3 class="contact-title">GitHub</h3>
<p><a href="https://github.com/keyargo" target="_blank">github.com/keyargo</a></p> <p><a href="https://github.com/daniellaforce" target="_blank">github.com/daniellaforce</a></p>
</div> </div>
</div> </div>
@ -650,27 +650,40 @@
<div class="container"> <div class="container">
<div class="footer-content"> <div class="footer-content">
<div class="footer-logo"> <div class="footer-logo">
<span class="logo-text">LaForceIT</span> <span class="logo-text-glow">LaForceIT</span>
<span class="logo-dot">.com</span> <span class="logo-dot-glow">.com</span>
</div> </div>
<div class="footer-links"> <div class="footer-links">
<a href="#home">Home</a> <a href="#home">Home</a>
<a href="#services">Services</a> <a href="#services">Services</a>
<a href="#lab">Live Lab</a> <a href="#lab">Live Lab</a>
<a href="#projects">Projects</a> <a href="#projects">Projects</a>
<a href="#experience">Experience</a>
<a href="#contact">Contact</a> <a href="#contact">Contact</a>
</div> </div>
<div class="footer-social"> <div class="footer-social">
<a href="https://github.com/keyargo" target="_blank" aria-label="GitHub"><i class="fab fa-github"></i></a> <a href="https://www.linkedin.com/in/daniellaforce" target="_blank" title="LinkedIn">
<a href="https://www.linkedin.com/in/danlaforce" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a> <i class="fab fa-linkedin"></i>
<a href="mailto:daniel.laforce@argobox.com" aria-label="Email"><i class="fas fa-envelope"></i></a> </a>
<a href="https://github.com/daniellaforce" target="_blank" title="GitHub">
<i class="fab fa-github"></i>
</a>
<a href="mailto:daniel@laforceit.com" title="Email">
<i class="fas fa-envelope"></i>
</a>
<a href="https://git.argobox.com" target="_blank" title="Gitea">
<i class="fas fa-code-branch"></i>
</a>
<a href="https://www.argobox.com" target="_blank" title="ArgoBox Lab">
<i class="fas fa-flask"></i>
</a>
</div> </div>
</div> </div>
<div class="footer-bottom"> <div class="footer-bottom">
<p>&copy; <span id="current-year"></span> All rights reserved. LaForce IT Consulting</p> <p>© All rights reserved. Inovin LLC</p>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daniel LaForce | Resume</title> <title>Daniel LaForce | Enterprise IT Solutions Architect & Security Expert</title>
<!-- SEO Meta Tags --> <!-- SEO Meta Tags -->
<meta name="description" content="Professional resume of Daniel LaForce - Systems & Infrastructure Engineer specializing in virtualization, containerization, and secure network architecture."> <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 --> <!-- Favicon -->
<link rel="icon" type="image/png" href="images/favicon.png"> <link rel="icon" type="image/png" href="images/favicon.png">
@ -486,7 +486,7 @@
<i class="fas fa-rocket"></i> <i class="fas fa-rocket"></i>
Schedule a Free Consultation Schedule a Free Consultation
</a> </a>
<a href="mailto:daniel.laforce@argobox.com" class="btn btn-outline cta-btn"> <a href="mailto:daniel@laforceit.com" class="btn btn-outline cta-btn">
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
Discuss Employment Opportunities Discuss Employment Opportunities
</a> </a>
@ -496,29 +496,38 @@
<div class="resume-header"> <div class="resume-header">
<h1 class="resume-name">Daniel LaForce</h1> <h1 class="resume-name">Daniel LaForce</h1>
<h2 class="resume-title">Network & Cyber Security Professional</h2> <h2 class="resume-title">Enterprise IT Solutions Architect & Security Expert</h2>
<!-- Contact Links -->
<div class="resume-contact"> <div class="resume-contact">
<div class="resume-contact-item"> <div class="resume-contact-item">
<i class="fas fa-map-marker-alt"></i> <i class="fas fa-map-marker-alt"></i>
<span>Colorado Springs, Colorado</span> Colorado Springs, CO
</div> </div>
<div class="resume-contact-item"> <div class="resume-contact-item">
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
<a href="tel:7203100064">720-310-0064</a> <a href="tel:7203100064">720-310-0064</a>
</div> </div>
<div class="resume-contact-item"> <a href="mailto:daniel.laforce@laforceit.com" class="resume-contact-item">
<i class="fas fa-envelope"></i> <i class="fas fa-envelope"></i>
<a href="mailto:daniel.laforce@argobox.com">daniel.laforce@argobox.com</a> daniel.laforce@laforceit.com
</div> </a>
<div class="resume-contact-item"> <a href="https://www.linkedin.com/in/danlaforce" class="resume-contact-item" target="_blank">
<i class="fab fa-linkedin"></i> <i class="fab fa-linkedin"></i>
<a href="https://www.linkedin.com/in/danlaforce" target="_blank">linkedin.com/in/danlaforce</a> linkedin.com/in/danlaforce
</div> </a>
<div class="resume-contact-item"> <a href="https://www.laforceit.com" class="resume-contact-item" target="_blank">
<i class="fab fa-github"></i> <i class="fas fa-globe"></i>
<a href="https://github.com/keyargo" target="_blank">github.com/keyargo</a> www.laforceit.com
</div> </a>
<a href="https://www.argobox.com" class="resume-contact-item" target="_blank">
<i class="fas fa-server"></i>
www.argobox.com
</a>
<a href="https://git.argobox.com" class="resume-contact-item" target="_blank">
<i class="fas fa-code-branch"></i>
git.argobox.com
</a>
</div> </div>
</div> </div>
@ -528,7 +537,7 @@
<div class="resume-job"> <div class="resume-job">
<div class="resume-job-header"> <div class="resume-job-header">
<h3 class="resume-job-title">Freelance Consultant GIS, Infrastructure & Security Solutions</h3> <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-company">Inovin LLC</div>
<div class="resume-job-period">April 2023 Present | Colorado Springs, CO</div> <div class="resume-job-period">April 2023 Present | Colorado Springs, CO</div>
</div> </div>
@ -549,6 +558,14 @@
<i class="fas fa-check-circle"></i> <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> <span>Automated infrastructure tasks via PowerShell, Python, and Bash, optimizing system deployment, backup routines, and monitoring pipelines.</span>
</div> </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> </div>
@ -578,28 +595,6 @@
</div> </div>
</div> </div>
<div class="resume-job">
<div class="resume-job-header">
<h3 class="resume-job-title">Interim Virtual Chief Security Officer</h3>
<div class="resume-job-company">Technology Response Team, LLC</div>
<div class="resume-job-period">August 2023 - September 2023</div>
</div>
<div class="resume-job-achievements">
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Served as temporary VCSO for ~120 clients, conducting penetration testing using BURP Professional.</span>
</div>
<div class="resume-job-achievement">
<i class="fas fa-check-circle"></i>
<span>Managed enterprise security stack deployment including Blackpoint & Webroot (Endpoint), DNSFilter (Network), and ThreatLocker (Application Control).</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%.</span>
</div>
</div>
</div>
<div class="resume-job"> <div class="resume-job">
<div class="resume-job-header"> <div class="resume-job-header">
<h3 class="resume-job-title">Network Engineer II</h3> <h3 class="resume-job-title">Network Engineer II</h3>
@ -953,14 +948,13 @@
</div> </div>
<div class="resume-project"> <div class="resume-project">
<h3 class="resume-project-title">AI-Driven Car Price Prediction</h3> <h3 class="resume-project-title">ArgoBox Lab</h3>
<p>Developed machine learning model for predicting used car prices with over 90% accuracy using Random Forest Regression and comprehensive feature engineering.</p> <p>A production-grade Kubernetes homelab environment featuring zero-trust architecture, complete automation, and enterprise-class infrastructure. Running 32+ CPU cores, 64GB RAM, and 12TB storage, hosting 16+ containerized services.</p>
<div class="resume-project-tech"> <div class="resume-project-tech">
<span class="resume-project-tech-item">Python</span> <span class="resume-project-tech-item">Kubernetes</span>
<span class="resume-project-tech-item">Scikit-learn</span> <span class="resume-project-tech-item">Proxmox</span>
<span class="resume-project-tech-item">Pandas</span> <span class="resume-project-tech-item">Ansible</span>
<span class="resume-project-tech-item">Random Forest</span> <span class="resume-project-tech-item">Zero Trust</span>
<span class="resume-project-tech-item">Jupyter</span>
</div> </div>
</div> </div>
</div> </div>
@ -993,13 +987,26 @@
</div> </div>
<div class="footer-social"> <div class="footer-social">
<a href="https://www.linkedin.com/in/danlaforce" target="_blank"><i class="fab fa-linkedin"></i></a> <a href="https://www.linkedin.com/in/daniellaforce" target="_blank" title="LinkedIn">
<a href="https://github.com/keyargo" target="_blank"><i class="fab fa-github"></i></a> <i class="fab fa-linkedin"></i>
</a>
<a href="https://github.com/daniellaforce" target="_blank" title="GitHub">
<i class="fab fa-github"></i>
</a>
<a href="mailto:daniel@laforceit.com" title="Email">
<i class="fas fa-envelope"></i>
</a>
<a href="https://git.argobox.com" target="_blank" title="Gitea">
<i class="fas fa-code-branch"></i>
</a>
<a href="https://www.argobox.com" target="_blank" title="ArgoBox Lab">
<i class="fas fa-flask"></i>
</a>
</div> </div>
</div> </div>
<div class="footer-bottom"> <div class="footer-bottom">
<p>&copy; <span id="current-year"></span> All rights reserved. Inovin LLC</p> <p>© All rights reserved. Inovin LLC</p>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -372,6 +372,10 @@ function updateMetrics() {
* Initialize contact form handling * Initialize contact form handling
*/ */
function initFormHandling(form) { function initFormHandling(form) {
// Prevent multiple initializations
if (form.hasAttribute('data-initialized')) return;
form.setAttribute('data-initialized', 'true');
form.addEventListener('submit', async function (e) { form.addEventListener('submit', async function (e) {
e.preventDefault(); e.preventDefault();
@ -384,6 +388,14 @@ function initFormHandling(form) {
const notificationIcon = notification.querySelector('i'); const notificationIcon = notification.querySelector('i');
const notificationText = notification.querySelector('.notification-text'); 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 = { const formData = {
name: form.elements['name'].value, name: form.elements['name'].value,
email: form.elements['email'].value, email: form.elements['email'].value,
@ -392,7 +404,6 @@ function initFormHandling(form) {
}; };
try { try {
console.log('Sending form data...');
const res = await fetch("/api/send-email", { const res = await fetch("/api/send-email", {
method: "POST", method: "POST",
headers: { headers: {
@ -402,21 +413,20 @@ function initFormHandling(form) {
}); });
const data = await res.json(); const data = await res.json();
console.log('Response:', data);
notification.style.display = 'flex';
if (res.ok) { if (res.ok) {
notification.style.display = 'flex';
notification.classList.remove('error'); notification.classList.remove('error');
notification.classList.add('success'); notification.classList.add('success');
notificationIcon.className = 'fas fa-check-circle'; notificationIcon.className = 'fas fa-check-circle';
notificationText.textContent = "Message sent successfully! We'll get back to you soon."; notificationText.textContent = "Message sent successfully! We'll get back to you soon.";
form.reset(); form.reset();
} else { } else {
notification.style.display = 'flex';
notification.classList.remove('success'); notification.classList.remove('success');
notification.classList.add('error'); notification.classList.add('error');
notificationIcon.className = 'fas fa-exclamation-circle'; notificationIcon.className = 'fas fa-exclamation-circle';
notificationText.textContent = `Error: ${data.error}${data.details ? ` - ${data.details}` : ''}`; notificationText.textContent = data.error + (data.details ? `: ${data.details}` : '');
} }
} catch (error) { } catch (error) {
@ -430,10 +440,14 @@ function initFormHandling(form) {
submitButton.innerHTML = originalButtonText; submitButton.innerHTML = originalButtonText;
submitButton.disabled = false; submitButton.disabled = false;
// Hide notification after 10 seconds // Hide notification after 5 seconds with animation
setTimeout(() => { setTimeout(() => {
notification.style.display = 'none'; notification.classList.add('hiding');
}, 10000); setTimeout(() => {
notification.classList.remove('hiding');
notification.style.display = 'none';
}, 300);
}, 5000);
} }
}); });
} }

101
style.css Normal file
View File

@ -0,0 +1,101 @@
.form-notification {
margin-top: 1rem;
padding: 1rem 1.5rem;
border-radius: 0.5rem;
display: none;
align-items: center;
gap: 0.75rem;
animation: slideIn 0.3s ease-out;
font-weight: 500;
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 1000;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.form-notification.success {
background-color: var(--success);
color: white;
border: none;
}
.form-notification.error {
background-color: var(--error);
color: white;
border: none;
}
.form-notification i {
font-size: 1.25rem;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.form-notification.hiding {
animation: slideOut 0.3s ease-in forwards;
}
@keyframes float-particle {
0% {
transform: translate(0, 0);
}
25% {
transform: translate(20px, -20px);
}
50% {
transform: translate(40px, 0);
}
75% {
transform: translate(20px, 20px);
}
100% {
transform: translate(0, 0);
}
}
:root {
--success: #10b981;
--error: #ef4444;
}
.logo-text-glow {
font-weight: 800;
font-size: 1.6rem;
background: linear-gradient(90deg, var(--accent), var(--accent-darker));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 6px rgba(59, 130, 246, 0.5);
transition: all 0.3s ease-in-out;
letter-spacing: -0.02em;
}
.logo-dot-glow {
color: white;
font-weight: 600;
font-size: 1.6rem;
margin-left: -1px;
text-shadow: 0 0 3px rgba(255, 255, 255, 0.3);
transition: all 0.3s ease-in-out;
}

View File

@ -1333,18 +1333,19 @@ background-clip: text;
/* Footer */ /* Footer */
.footer { .footer {
background-color: var(--secondary-bg); width: 100%;
padding: 4rem 0 1rem; padding: 2rem 0;
margin-top: 6rem; background: transparent;
border-top: 1px solid var(--border);
margin-top: 2rem;
} }
.footer-content { .footer-content {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: 3rem;
flex-wrap: wrap; flex-wrap: wrap;
gap: 2rem; gap: 1rem;
} }
.footer-logo { .footer-logo {
@ -1354,40 +1355,55 @@ background-clip: text;
.footer-links { .footer-links {
display: flex; display: flex;
gap: 2rem; gap: 1.5rem;
flex-wrap: wrap;
} }
.footer-links a { .footer-links a {
color: var(--text-secondary); color: var(--text-secondary);
text-decoration: none;
transition: color var(--transition-normal); transition: color var(--transition-normal);
} }
.footer-links a:hover { .footer-links a:hover {
color: var(--text-primary); color: var(--accent);
} }
.footer-social { .footer-social {
display: flex; display: flex;
gap: 1.5rem; gap: 1rem;
} }
.footer-social a { .footer-social a {
color: var(--text-secondary); color: var(--text-secondary);
font-size: 1.25rem; font-size: 1.25rem;
transition: all var(--transition-normal); transition: color var(--transition-normal);
} }
.footer-social a:hover { .footer-social a:hover {
color: var(--accent); color: var(--accent);
transform: translateY(-3px);
} }
.footer-bottom { .footer-bottom {
margin-top: 1.5rem;
text-align: center; text-align: center;
color: var(--text-secondary); color: var(--text-secondary);
font-size: 0.9rem; font-size: 0.9rem;
padding-top: 2rem; }
border-top: 1px solid var(--border);
@media (max-width: 768px) {
.footer-content {
flex-direction: column;
text-align: center;
}
.footer-links {
justify-content: center;
}
.footer-social {
justify-content: center;
}
} }
/* Reveal animations on scroll */ /* Reveal animations on scroll */