Update website with new features: - Restored live dashboard layout - Moved sign-in button to top right - Updated documentation links to construction.html - Added Ansible Sandbox icon - Renamed Dev Environment to VS Code Powered - Updated AI Assistant description - Added GitHub Actions service - Replaced NextCloud with Synology Drive
This commit is contained in:
parent
e4abc52092
commit
d606b4018e
|
@ -40,6 +40,7 @@
|
||||||
--card-hover-bg: rgba(30, 41, 59, 0.95);
|
--card-hover-bg: rgba(30, 41, 59, 0.95);
|
||||||
--card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
--card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
||||||
--transition-normal: 0.3s ease;
|
--transition-normal: 0.3s ease;
|
||||||
|
--glass-effect: blur(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -58,333 +59,236 @@
|
||||||
radial-gradient(circle at 75% 60%, rgba(14, 165, 233, 0.1) 0%, transparent 50%);
|
radial-gradient(circle at 75% 60%, rgba(14, 165, 233, 0.1) 0%, transparent 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-container {
|
.navbar {
|
||||||
display: flex;
|
background-color: rgba(15, 23, 42, 0.9);
|
||||||
min-height: 100vh;
|
backdrop-filter: var(--glass-effect);
|
||||||
}
|
-webkit-backdrop-filter: var(--glass-effect);
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 280px;
|
|
||||||
background-color: var(--sidebar-bg);
|
|
||||||
border-right: 1px solid var(--border);
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
height: 100vh;
|
right: 0;
|
||||||
overflow-y: auto;
|
z-index: 1000;
|
||||||
scrollbar-width: thin;
|
padding: 1.25rem 0;
|
||||||
scrollbar-color: var(--border) transparent;
|
border-bottom: 1px solid var(--border);
|
||||||
padding: 2rem 0;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar::-webkit-scrollbar {
|
.navbar .container {
|
||||||
width: 6px;
|
display: flex;
|
||||||
}
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
.sidebar::-webkit-scrollbar-track {
|
max-width: 1400px;
|
||||||
background: transparent;
|
margin: 0 auto;
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar::-webkit-scrollbar-thumb {
|
|
||||||
background-color: var(--border);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-header {
|
|
||||||
padding: 0 1.5rem;
|
padding: 0 1.5rem;
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-title {
|
.logo a {
|
||||||
font-size: 1.25rem;
|
color: var(--text-primary);
|
||||||
font-weight: 600;
|
text-decoration: none;
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.back-link {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.25rem;
|
||||||
color: var(--accent);
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 0.5rem 0;
|
|
||||||
transition: all var(--transition-normal);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-link:hover {
|
.logo-text {
|
||||||
color: var(--accent-darker);
|
background: var(--accent-gradient);
|
||||||
transform: translateX(-3px);
|
-webkit-background-clip: text;
|
||||||
}
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
.sidebar-section {
|
font-size: 1.5rem;
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-section-title {
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 0.85rem;
|
}
|
||||||
text-transform: uppercase;
|
|
||||||
|
.logo-dot {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
letter-spacing: 0.05em;
|
font-size: 1.5rem;
|
||||||
padding: 0 1.5rem;
|
font-weight: 600;
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-nav {
|
.nav-menu {
|
||||||
list-style: none;
|
display: flex;
|
||||||
|
gap: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-nav-item {
|
.nav-link {
|
||||||
transition: all var(--transition-normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav-link {
|
|
||||||
display: block;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
transition: all var(--transition-normal);
|
transition: all var(--transition-normal);
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-nav-link:hover {
|
.nav-link.active,
|
||||||
color: var(--text-primary);
|
.nav-link:hover {
|
||||||
background-color: rgba(255, 255, 255, 0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-nav-link.active {
|
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.625rem 1.25rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-primary);
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
background-color: rgba(59, 130, 246, 0.1);
|
||||||
|
border: 1px solid rgba(59, 130, 246, 0.2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-nav-link.active::before {
|
.dashboard-link:hover {
|
||||||
content: '';
|
background-color: var(--accent-darker);
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 3px;
|
|
||||||
background: var(--accent-gradient);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.navbar .menu-toggle {
|
||||||
flex: 1;
|
background: none;
|
||||||
margin-left: 280px;
|
border: none;
|
||||||
padding: 3rem;
|
color: var(--text-primary);
|
||||||
max-width: 1000px;
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-header {
|
.navbar .menu-toggle i {
|
||||||
margin-bottom: 3rem;
|
transition: transform var(--transition-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-title {
|
.navbar .nav-menu.show {
|
||||||
font-size: 2.5rem;
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background-color: var(--secondary-bg);
|
||||||
|
padding: 2rem;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-logo .logo-text {
|
||||||
|
font-size: 1.5rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
margin-bottom: 1rem;
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-subtitle {
|
.footer .footer-logo .logo-dot {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-links a {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
transition: color var(--transition-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-links a:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-social {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .footer-social a {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
|
transition: color var(--transition-normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-section {
|
.footer .footer-social a:hover {
|
||||||
margin-bottom: 3rem;
|
|
||||||
scroll-margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-section-title {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
color: var(--text-primary);
|
|
||||||
position: relative;
|
|
||||||
padding-bottom: 0.75rem;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-subsection {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-subsection-title {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-text {
|
.footer .footer-bottom {
|
||||||
color: var(--text-secondary);
|
text-align: center;
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-list {
|
|
||||||
list-style-type: disc;
|
|
||||||
margin-left: 1.5rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-list li {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-code {
|
|
||||||
font-family: 'JetBrains Mono', monospace;
|
|
||||||
background-color: var(--sidebar-bg);
|
|
||||||
padding: 1.5rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
overflow-x: auto;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
border: 1px solid var(--border);
|
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-code pre {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-table th {
|
|
||||||
text-align: left;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
background-color: var(--sidebar-bg);
|
|
||||||
color: var(--text-primary);
|
|
||||||
font-weight: 600;
|
|
||||||
border-bottom: 2px solid var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-table td {
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
color: var(--text-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-note {
|
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
|
||||||
border-left: 4px solid var(--accent);
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
border-radius: 0 0.5rem 0.5rem 0;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-note-title {
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--accent);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-warning {
|
|
||||||
background-color: rgba(245, 158, 11, 0.1);
|
|
||||||
border-left: 4px solid var(--warning);
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
border-radius: 0 0.5rem 0.5rem 0;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-warning-title {
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--warning);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-button {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
background-color: var(--accent);
|
|
||||||
color: white;
|
|
||||||
padding: 0.75rem 1.25rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all var(--transition-normal);
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-button:hover {
|
|
||||||
background-color: var(--accent-darker);
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: var(--card-shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.docs-footer {
|
|
||||||
border-top: 1px solid var(--border);
|
|
||||||
margin-top: 3rem;
|
|
||||||
padding-top: 2rem;
|
|
||||||
color: var(--text-secondary);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-menu-toggle {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 1.5rem;
|
|
||||||
right: 1.5rem;
|
|
||||||
background: var(--accent-gradient);
|
|
||||||
color: white;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
bottom: 1.5rem;
|
|
||||||
right: 1.5rem;
|
|
||||||
background: var(--accent-gradient);
|
|
||||||
color: white;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 20;
|
|
||||||
box-shadow: var(--card-shadow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 992px) {
|
@media (max-width: 992px) {
|
||||||
.sidebar {
|
.navbar .nav-menu {
|
||||||
transform: translateX(-100%);
|
display: none;
|
||||||
transition: transform var(--transition-normal);
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background-color: var(--secondary-bg);
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: 0;
|
||||||
|
width: 200px;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar.active {
|
.navbar .nav-menu.show {
|
||||||
transform: translateX(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
margin-left: 0;
|
|
||||||
padding: 2rem 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mobile-menu-toggle {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Navigation Bar -->
|
||||||
|
<nav class="navbar">
|
||||||
|
<div class="container">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="index.html">
|
||||||
|
<span class="logo-text">Argobox</span>
|
||||||
|
<span class="logo-dot">.com</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="nav-menu">
|
||||||
|
<a href="index.html#home" class="nav-link">Home</a>
|
||||||
|
<a href="index.html#services" class="nav-link">Services</a>
|
||||||
|
<a href="index.html#lab" class="nav-link active">Live Lab</a>
|
||||||
|
<a href="index.html#projects" class="nav-link">Projects</a>
|
||||||
|
<a href="index.html#experience" class="nav-link">Experience</a>
|
||||||
|
<a href="index.html#contact" class="nav-link">Contact</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>
|
||||||
|
|
||||||
<div class="docs-container">
|
<div class="docs-container">
|
||||||
<aside class="sidebar">
|
<aside class="sidebar">
|
||||||
<div class="sidebar-header">
|
<div class="sidebar-header">
|
||||||
|
@ -837,18 +741,39 @@ web-server/
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<footer class="docs-footer">
|
|
||||||
<p>
|
|
||||||
For questions or suggestions about the Ansible Sandbox, please contact <a href="mailto:contact@argobox.com">contact@argobox.com</a>.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
© <span id="current-year">2025</span> Argobox.com. All rights reserved.
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container">
|
||||||
|
<div class="footer-content">
|
||||||
|
<div class="footer-logo">
|
||||||
|
<span class="logo-text">Argobox</span>
|
||||||
|
<span class="logo-dot">.com</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-links">
|
||||||
|
<a href="index.html#home">Home</a>
|
||||||
|
<a href="index.html#services">Services</a>
|
||||||
|
<a href="index.html#lab">Live Lab</a>
|
||||||
|
<a href="index.html#projects">Projects</a>
|
||||||
|
<a href="index.html#contact">Contact</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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/danlaforce" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
||||||
|
<a href="mailto:daniel.laforce@argobox.com" aria-label="Email"><i class="fas fa-envelope"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p>© <span id="current-year"></span> All rights reserved. Inovin LLC</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
<button class="mobile-menu-toggle">
|
<button class="mobile-menu-toggle">
|
||||||
<i class="fas fa-bars"></i>
|
<i class="fas fa-bars"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -934,6 +859,23 @@ web-server/
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add mobile menu toggle functionality
|
||||||
|
const menuToggleNav = document.querySelector('.menu-toggle');
|
||||||
|
const navMenu = document.querySelector('.nav-menu');
|
||||||
|
|
||||||
|
menuToggleNav.addEventListener('click', function() {
|
||||||
|
navMenu.classList.toggle('show');
|
||||||
|
const icon = menuToggleNav.querySelector('i');
|
||||||
|
|
||||||
|
if (navMenu.classList.contains('show')) {
|
||||||
|
icon.classList.remove('fa-bars');
|
||||||
|
icon.classList.add('fa-times');
|
||||||
|
} else {
|
||||||
|
icon.classList.remove('fa-times');
|
||||||
|
icon.classList.add('fa-bars');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
--card-hover-bg: rgba(30, 41, 59, 0.95);
|
--card-hover-bg: rgba(30, 41, 59, 0.95);
|
||||||
--card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
--card-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3);
|
||||||
--transition-normal: 0.3s ease;
|
--transition-normal: 0.3s ease;
|
||||||
|
--glass-effect: blur(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -245,9 +246,184 @@
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
background-color: rgba(15, 23, 42, 0.9);
|
||||||
|
backdrop-filter: var(--glass-effect);
|
||||||
|
-webkit-backdrop-filter: var(--glass-effect);
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
padding: 1.25rem 0;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar .container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 1400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo a {
|
||||||
|
color: var(--text-primary);
|
||||||
|
text-decoration: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-text {
|
||||||
|
background: var(--accent-gradient);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
color: transparent;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-dot {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu {
|
||||||
|
display: flex;
|
||||||
|
gap: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.625rem 1.25rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-primary);
|
||||||
|
background-color: rgba(59, 130, 246, 0.1);
|
||||||
|
border: 1px solid rgba(59, 130, 246, 0.2);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all var(--transition-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-toggle {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-toggle i {
|
||||||
|
transition: transform var(--transition-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background-color: var(--secondary-bg);
|
||||||
|
padding: 2rem 0;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-logo {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links a {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color var(--transition-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-links a:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-social a {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
transition: color var(--transition-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-social a:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-bottom {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- Navigation Bar -->
|
||||||
|
<nav class="navbar">
|
||||||
|
<div class="container">
|
||||||
|
<div class="logo">
|
||||||
|
<a href="index.html">
|
||||||
|
<span class="logo-text">Argobox</span>
|
||||||
|
<span class="logo-dot">.com</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="nav-menu">
|
||||||
|
<a href="index.html#home" class="nav-link">Home</a>
|
||||||
|
<a href="index.html#services" class="nav-link">Services</a>
|
||||||
|
<a href="index.html#lab" class="nav-link active">Live Lab</a>
|
||||||
|
<a href="index.html#projects" class="nav-link">Projects</a>
|
||||||
|
<a href="index.html#experience" class="nav-link">Experience</a>
|
||||||
|
<a href="index.html#contact" class="nav-link">Contact</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>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="help-header">
|
<div class="help-header">
|
||||||
<a href="ansible-sandbox.html" class="back-link">
|
<a href="ansible-sandbox.html" class="back-link">
|
||||||
|
@ -421,11 +597,60 @@
|
||||||
<span class="key-term">Template</span> - A text file that uses variables to create dynamic configuration files.
|
<span class="key-term">Template</span> - A text file that uses variables to create dynamic configuration files.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="help-footer">
|
|
||||||
<p>Need more detailed information? Check out the <a href="ansible-docs.html">Ansible Sandbox Documentation</a>.</p>
|
|
||||||
<p>For questions about this sandbox, contact me at <a href="mailto:contact@argobox.com">contact@argobox.com</a>.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container">
|
||||||
|
<div class="footer-content">
|
||||||
|
<div class="footer-logo">
|
||||||
|
<span class="logo-text">Argobox</span>
|
||||||
|
<span class="logo-dot">.com</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-links">
|
||||||
|
<a href="index.html#home">Home</a>
|
||||||
|
<a href="index.html#services">Services</a>
|
||||||
|
<a href="index.html#lab">Live Lab</a>
|
||||||
|
<a href="index.html#projects">Projects</a>
|
||||||
|
<a href="index.html#contact">Contact</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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/danlaforce" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
||||||
|
<a href="mailto:daniel.laforce@argobox.com" aria-label="Email"><i class="fas fa-envelope"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-bottom">
|
||||||
|
<p>© <span id="current-year"></span> All rights reserved. Inovin LLC</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Set current year in footer
|
||||||
|
document.getElementById('current-year').textContent = new Date().getFullYear();
|
||||||
|
|
||||||
|
// Mobile menu toggle
|
||||||
|
const menuToggle = document.querySelector('.menu-toggle');
|
||||||
|
const navMenu = document.querySelector('.nav-menu');
|
||||||
|
|
||||||
|
menuToggle.addEventListener('click', function() {
|
||||||
|
navMenu.classList.toggle('show');
|
||||||
|
const icon = menuToggle.querySelector('i');
|
||||||
|
|
||||||
|
if (navMenu.classList.contains('show')) {
|
||||||
|
icon.classList.remove('fa-bars');
|
||||||
|
icon.classList.add('fa-times');
|
||||||
|
} else {
|
||||||
|
icon.classList.remove('fa-times');
|
||||||
|
icon.classList.add('fa-bars');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -95,7 +95,7 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
padding: 1rem 0;
|
padding: 1.25rem 0;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,16 +105,12 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo a {
|
.logo a {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-text {
|
.logo-text {
|
||||||
|
@ -122,15 +118,19 @@
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo-dot {
|
.logo-dot {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-menu {
|
.nav-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2rem;
|
gap: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
.nav-link {
|
||||||
|
@ -172,15 +172,15 @@
|
||||||
.nav-buttons {
|
.nav-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1rem;
|
gap: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-link {
|
.dashboard-link {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.75rem;
|
||||||
padding: 0.5rem 1rem;
|
padding: 0.625rem 1.25rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.95rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
background-color: rgba(59, 130, 246, 0.1);
|
background-color: rgba(59, 130, 246, 0.1);
|
||||||
|
@ -1469,11 +1469,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer-links">
|
<div class="footer-links">
|
||||||
<a href="#home">Home</a>
|
<a href="index.html#home">Home</a>
|
||||||
<a href="#services">Services</a>
|
<a href="index.html#services">Services</a>
|
||||||
<a href="#lab">Live Lab</a>
|
<a href="index.html#lab">Live Lab</a>
|
||||||
<a href="#projects">Projects</a>
|
<a href="index.html#projects">Projects</a>
|
||||||
<a href="#contact">Contact</a>
|
<a href="index.html#contact">Contact</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer-social">
|
<div class="footer-social">
|
||||||
|
|
|
@ -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 | ArgoBox</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://argobox.com" class="construction-back">
|
||||||
|
<i class="fas fa-arrow-left"></i>
|
||||||
|
Return to ArgoBox
|
||||||
|
</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>
|
|
@ -996,18 +996,18 @@
|
||||||
<nav class="navbar">
|
<nav class="navbar">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<a href="#home">
|
<a href="index.html">
|
||||||
<span class="logo-text">Argobox</span>
|
<span class="logo-text">Argobox</span>
|
||||||
<span class="logo-dot">.com</span>
|
<span class="logo-dot">.com</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-menu">
|
<div class="nav-menu">
|
||||||
<a href="#home" class="nav-link active">Home</a>
|
<a href="index.html#home" class="nav-link">Home</a>
|
||||||
<a href="#services" class="nav-link">Services</a>
|
<a href="index.html#services" class="nav-link">Services</a>
|
||||||
<a href="#lab" class="nav-link">Live Lab</a>
|
<a href="index.html#lab" class="nav-link">Live Lab</a>
|
||||||
<a href="#projects" class="nav-link">Projects</a>
|
<a href="index.html#projects" class="nav-link">Projects</a>
|
||||||
<a href="#experience" class="nav-link">Experience</a>
|
<a href="index.html#experience" class="nav-link">Experience</a>
|
||||||
<a href="#contact" class="nav-link">Contact</a>
|
<a href="index.html#contact" class="nav-link">Contact</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-buttons">
|
<div class="nav-buttons">
|
||||||
<a href="dashboard.html" class="dashboard-link" target="_blank">
|
<a href="dashboard.html" class="dashboard-link" target="_blank">
|
||||||
|
@ -1400,13 +1400,13 @@
|
||||||
<a href="index.html#services">Services</a>
|
<a href="index.html#services">Services</a>
|
||||||
<a href="index.html#lab">Live Lab</a>
|
<a href="index.html#lab">Live Lab</a>
|
||||||
<a href="index.html#projects">Projects</a>
|
<a href="index.html#projects">Projects</a>
|
||||||
<a href="index.html#experience">Experience</a>
|
|
||||||
<a href="index.html#contact">Contact</a>
|
<a href="index.html#contact">Contact</a>
|
||||||
</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://github.com/keyargo" target="_blank" aria-label="GitHub"><i class="fab fa-github"></i></a>
|
||||||
<a href="https://github.com/keyargo" target="_blank"><i class="fab fa-github"></i></a>
|
<a href="https://www.linkedin.com/in/danlaforce" target="_blank" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
||||||
|
<a href="mailto:daniel.laforce@argobox.com" aria-label="Email"><i class="fas fa-envelope"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Binary file not shown.
1336
index.html
1336
index.html
File diff suppressed because it is too large
Load Diff
836
resume.html
836
resume.html
|
@ -1,836 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Daniel LaForce | Resume</title>
|
|
||||||
|
|
||||||
<!-- SEO Meta Tags -->
|
|
||||||
<meta name="description" content="Professional resume of Daniel LaForce - Systems & Infrastructure Engineer specializing in virtualization, containerization, and secure network architecture.">
|
|
||||||
|
|
||||||
<!-- Favicon -->
|
|
||||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22256%22 height=%22256%22 viewBox=%220 0 100 100%22><rect width=%22100%22 height=%22100%22 rx=%2220%22 fill=%22%230f172a%22></rect><path fill=%22%233b82f6%22 d=%22M30 40L50 20L70 40L50 60L30 40Z%22></path><path fill=%22%233b82f6%22 d=%22M50 60L70 40L70 70L50 90L30 70L30 40L50 60Z%22 fill-opacity=%220.6%22></path></svg>">
|
|
||||||
|
|
||||||
<!-- 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: 6rem auto 4rem;
|
|
||||||
padding: 0 1.5rem;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<!-- Navigation -->
|
|
||||||
<nav class="navbar">
|
|
||||||
<div class="container">
|
|
||||||
<div class="logo">
|
|
||||||
<a href="index.html">
|
|
||||||
<span class="logo-text">Argobox</span>
|
|
||||||
<span class="logo-dot">.com</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="nav-menu">
|
|
||||||
<a href="index.html#home" class="nav-link">Home</a>
|
|
||||||
<a href="index.html#services" class="nav-link">Services</a>
|
|
||||||
<a href="index.html#lab" class="nav-link">Live Lab</a>
|
|
||||||
<a href="index.html#projects" class="nav-link">Projects</a>
|
|
||||||
<a href="index.html#experience" class="nav-link">Experience</a>
|
|
||||||
<a href="index.html#contact" class="nav-link">Contact</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>
|
|
||||||
|
|
||||||
<!-- Resume Content -->
|
|
||||||
<div class="resume-container">
|
|
||||||
<div class="resume-header">
|
|
||||||
<h1 class="resume-name">Daniel LaForce</h1>
|
|
||||||
<h2 class="resume-title">Infrastructure & Systems Engineer</h2>
|
|
||||||
|
|
||||||
<div class="resume-contact">
|
|
||||||
<div class="resume-contact-item">
|
|
||||||
<i class="fas fa-map-marker-alt"></i>
|
|
||||||
<span>Colorado Springs, Colorado</span>
|
|
||||||
</div>
|
|
||||||
<div class="resume-contact-item">
|
|
||||||
<i class="fas fa-phone"></i>
|
|
||||||
<a href="tel:7203100064">720-310-0064</a>
|
|
||||||
</div>
|
|
||||||
<div class="resume-contact-item">
|
|
||||||
<i class="fas fa-envelope"></i>
|
|
||||||
<a href="mailto:daniel.laforce@argobox.com">daniel.laforce@argobox.com</a>
|
|
||||||
</div>
|
|
||||||
<div class="resume-contact-item">
|
|
||||||
<i class="fab fa-linkedin"></i>
|
|
||||||
<a href="https://www.linkedin.com/in/danlaforce" target="_blank">linkedin.com/in/danlaforce</a>
|
|
||||||
</div>
|
|
||||||
<div class="resume-contact-item">
|
|
||||||
<i class="fab fa-github"></i>
|
|
||||||
<a href="https://github.com/keyargo" target="_blank">github.com/keyargo</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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 Consultant – GIS, Infrastructure & Security 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>
|
|
||||||
</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">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-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">Full-Access Wi-Fi Testing Cage</h3>
|
|
||||||
<p>Designed and implemented a comprehensive testing environment for router firmware validation with remote access capabilities. Engineered cable modem/SONU configurations for MAP-T and dual-stack testing with automated relay and RF switcher control.</p>
|
|
||||||
<div class="resume-project-tech">
|
|
||||||
<span class="resume-project-tech-item">RF Engineering</span>
|
|
||||||
<span class="resume-project-tech-item">Network Testing</span>
|
|
||||||
<span class="resume-project-tech-item">CAD Prototyping</span>
|
|
||||||
<span class="resume-project-tech-item">Serial Interface</span>
|
|
||||||
<span class="resume-project-tech-item">Automation</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="resume-project">
|
|
||||||
<h3 class="resume-project-title">TerraTracer GIS Platform</h3>
|
|
||||||
<p>A GIS mapping platform used by mining claim prospectors to automate boundary plotting and compliance verification, reducing manual research by 85% and improving claim success rates by 40%.</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">GeoPandas</span>
|
|
||||||
<span class="resume-project-tech-item">KML</span>
|
|
||||||
<span class="resume-project-tech-item">GDAL/OGR</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="resume-project">
|
|
||||||
<h3 class="resume-project-title">VSA Deployer</h3>
|
|
||||||
<p>Custom application for streamlining Kaseya VSA RMM agent installation, reducing deployment time by 80% across dental practice environments. Implemented for 300+ practices with 3700+ workstations.</p>
|
|
||||||
<div class="resume-project-tech">
|
|
||||||
<span class="resume-project-tech-item">PowerShell</span>
|
|
||||||
<span class="resume-project-tech-item">AutoHotkey</span>
|
|
||||||
<span class="resume-project-tech-item">RMM</span>
|
|
||||||
<span class="resume-project-tech-item">Kaseya VSA</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="resume-project">
|
|
||||||
<h3 class="resume-project-title">AI-Driven Car Price Prediction</h3>
|
|
||||||
<p>Developed machine learning model for predicting used car prices with over 90% accuracy using Random Forest Regression and comprehensive feature engineering.</p>
|
|
||||||
<div class="resume-project-tech">
|
|
||||||
<span class="resume-project-tech-item">Python</span>
|
|
||||||
<span class="resume-project-tech-item">Scikit-learn</span>
|
|
||||||
<span class="resume-project-tech-item">Pandas</span>
|
|
||||||
<span class="resume-project-tech-item">Random Forest</span>
|
|
||||||
<span class="resume-project-tech-item">Jupyter</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="resume-download">
|
|
||||||
<a href="files/daniel-laforce-resume.pdf" class="btn btn-primary" download>
|
|
||||||
<i class="fas fa-download btn-icon"></i>
|
|
||||||
Download Full Resume (PDF)
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="container">
|
|
||||||
<div class="footer-content">
|
|
||||||
<div class="footer-logo">
|
|
||||||
<span class="logo-text">Argobox</span>
|
|
||||||
<span class="logo-dot">.com</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer-links">
|
|
||||||
<a href="index.html#home">Home</a>
|
|
||||||
<a href="index.html#services">Services</a>
|
|
||||||
<a href="index.html#lab">Live Lab</a>
|
|
||||||
<a href="index.html#projects">Projects</a>
|
|
||||||
<a href="index.html#experience">Experience</a>
|
|
||||||
<a href="index.html#contact">Contact</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer-social">
|
|
||||||
<a href="https://www.linkedin.com/in/danlaforce" target="_blank"><i class="fab fa-linkedin"></i></a>
|
|
||||||
<a href="https://github.com/keyargo" target="_blank"><i class="fab fa-github"></i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="footer-bottom">
|
|
||||||
<p>© <span id="current-year"></span> All rights reserved. Inovin LLC</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- JavaScript -->
|
|
||||||
<script src="script.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
432
script.js
432
script.js
|
@ -7,78 +7,51 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
// Initialize all website functionality
|
// Initialize all website functionality
|
||||||
initNavigation();
|
initNavigation();
|
||||||
initParticlesAndIcons();
|
initParticlesAndIcons();
|
||||||
initRoleRotation();
|
|
||||||
initTerminalTyping();
|
initTerminalTyping();
|
||||||
initSolutionsCarousel();
|
|
||||||
initScrollReveal();
|
|
||||||
updateMetrics();
|
|
||||||
updateYear();
|
updateYear();
|
||||||
|
|
||||||
// Initialize form handling
|
|
||||||
const contactForm = document.getElementById('contact-form');
|
|
||||||
if (contactForm) {
|
|
||||||
initFormHandling(contactForm);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up navigation functionality - mobile menu and scroll spy
|
* Set up navigation functionality - mobile menu and scroll spy
|
||||||
*/
|
*/
|
||||||
function initNavigation() {
|
function initNavigation() {
|
||||||
// Mobile menu toggle
|
|
||||||
const menuToggle = document.querySelector('.menu-toggle');
|
const menuToggle = document.querySelector('.menu-toggle');
|
||||||
const navMenu = document.querySelector('.nav-menu');
|
const navMenu = document.querySelector('.nav-menu');
|
||||||
|
|
||||||
if (menuToggle && navMenu) {
|
if (menuToggle && navMenu) {
|
||||||
menuToggle.addEventListener('click', function() {
|
menuToggle.addEventListener('click', () => {
|
||||||
navMenu.classList.toggle('active');
|
navMenu.classList.toggle('show');
|
||||||
menuToggle.setAttribute('aria-expanded',
|
const icon = menuToggle.querySelector('i');
|
||||||
menuToggle.getAttribute('aria-expanded') === 'true' ? 'false' : 'true');
|
if (navMenu.classList.contains('show')) {
|
||||||
});
|
icon.classList.remove('fa-bars');
|
||||||
}
|
icon.classList.add('fa-times');
|
||||||
|
} else {
|
||||||
// Navigation scroll spy
|
icon.classList.remove('fa-times');
|
||||||
const sections = document.querySelectorAll('section[id]');
|
icon.classList.add('fa-bars');
|
||||||
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
|
// Scroll spy for navigation
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
|
|
||||||
function updateNavbarStyle() {
|
|
||||||
if (window.scrollY > 50) {
|
|
||||||
navbar?.classList.add('scrolled');
|
|
||||||
} else {
|
|
||||||
navbar?.classList.remove('scrolled');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('scroll', () => {
|
window.addEventListener('scroll', () => {
|
||||||
updateActiveNavLink();
|
const sections = document.querySelectorAll('section');
|
||||||
updateNavbarStyle();
|
const navLinks = document.querySelectorAll('.nav-link');
|
||||||
|
|
||||||
|
let current = '';
|
||||||
|
sections.forEach(section => {
|
||||||
|
const sectionTop = section.offsetTop;
|
||||||
|
if (window.scrollY >= sectionTop - 100) {
|
||||||
|
current = section.getAttribute('id');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
navLinks.forEach(link => {
|
||||||
|
link.classList.remove('active');
|
||||||
|
if (link.getAttribute('href').substring(1) === current) {
|
||||||
|
link.classList.add('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initial call to set correct states
|
|
||||||
updateActiveNavLink();
|
|
||||||
updateNavbarStyle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,334 +70,44 @@ function createBackgroundParticles() {
|
||||||
|
|
||||||
if (!particlesContainer) return;
|
if (!particlesContainer) return;
|
||||||
|
|
||||||
|
// Clear existing particles
|
||||||
particlesContainer.innerHTML = '';
|
particlesContainer.innerHTML = '';
|
||||||
|
|
||||||
for (let i = 0; i < 40; i++) {
|
// Create particles
|
||||||
|
for (let i = 0; i < 50; i++) {
|
||||||
const particle = document.createElement('div');
|
const particle = document.createElement('div');
|
||||||
particle.classList.add('particle');
|
particle.classList.add('particle');
|
||||||
|
|
||||||
// Random size, opacity, and position
|
// Random size between 2 and 6px
|
||||||
const size = Math.random() * 4 + 1;
|
const size = Math.random() * 4 + 2;
|
||||||
const opacity = Math.random() * 0.3 + 0.1;
|
|
||||||
|
|
||||||
particle.style.width = `${size}px`;
|
particle.style.width = `${size}px`;
|
||||||
particle.style.height = `${size}px`;
|
particle.style.height = `${size}px`;
|
||||||
particle.style.opacity = opacity;
|
|
||||||
|
|
||||||
// Position randomly with some clustering toward top areas
|
// Random position
|
||||||
const xPos = Math.random() * 100;
|
particle.style.left = `${Math.random() * 100}%`;
|
||||||
const yPos = Math.random() * 100;
|
particle.style.top = `${Math.random() * 100}%`;
|
||||||
|
|
||||||
particle.style.left = `${xPos}%`;
|
// Random opacity between 0.1 and 0.3
|
||||||
particle.style.top = `${yPos}%`;
|
particle.style.opacity = (Math.random() * 0.2 + 0.1).toString();
|
||||||
|
|
||||||
// Animation properties
|
// Animation properties
|
||||||
particle.style.animationDuration = `${Math.random() * 20 + 10}s`;
|
particle.style.animation = `float-particle ${Math.random() * 20 + 10}s linear infinite`;
|
||||||
particle.style.animationDelay = `${Math.random() * 5}s`;
|
particle.style.animationDelay = `${Math.random() * 10}s`;
|
||||||
|
|
||||||
// Add particle animation
|
|
||||||
particle.style.animation = `particle-float ${Math.random() * 20 + 10}s linear infinite`;
|
|
||||||
|
|
||||||
particlesContainer.appendChild(particle);
|
particlesContainer.appendChild(particle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create floating tech icons in the background
|
* Initialize terminal typing animation
|
||||||
*/
|
|
||||||
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 initRoleRotation() {
|
|
||||||
const roles = document.querySelectorAll('.role');
|
|
||||||
const descriptionElement = document.getElementById('role-description');
|
|
||||||
|
|
||||||
if (roles.length === 0 || !descriptionElement) return;
|
|
||||||
|
|
||||||
let currentRole = 0;
|
|
||||||
|
|
||||||
function rotateRoles() {
|
|
||||||
// Hide current role
|
|
||||||
roles[currentRole].classList.remove('active');
|
|
||||||
|
|
||||||
// Move to next role
|
|
||||||
currentRole = (currentRole + 1) % roles.length;
|
|
||||||
|
|
||||||
// Show new role
|
|
||||||
roles[currentRole].classList.add('active');
|
|
||||||
|
|
||||||
// Update description text
|
|
||||||
const newDescription = roles[currentRole].getAttribute('data-description');
|
|
||||||
if (newDescription) {
|
|
||||||
descriptionElement.textContent = newDescription;
|
|
||||||
|
|
||||||
// Animate the description change
|
|
||||||
descriptionElement.style.opacity = '0';
|
|
||||||
descriptionElement.style.transform = 'translateY(10px)';
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
descriptionElement.style.opacity = '1';
|
|
||||||
descriptionElement.style.transform = 'translateY(0)';
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set initial role to active
|
|
||||||
roles[0].classList.add('active');
|
|
||||||
|
|
||||||
// Initialize with the first description
|
|
||||||
const initialDescription = roles[0].getAttribute('data-description');
|
|
||||||
if (initialDescription && descriptionElement) {
|
|
||||||
descriptionElement.textContent = initialDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start rotation with delay
|
|
||||||
setInterval(rotateRoles, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize terminal typing animation in the hero section
|
|
||||||
*/
|
*/
|
||||||
function initTerminalTyping() {
|
function initTerminalTyping() {
|
||||||
const terminalText = document.getElementById('terminal-text');
|
const cursor = document.querySelector('.cursor');
|
||||||
if (!terminalText) return;
|
if (cursor) {
|
||||||
|
setInterval(() => {
|
||||||
const terminalMessages = [
|
cursor.style.opacity = cursor.style.opacity === '0' ? '1' : '0';
|
||||||
"> Ready for deployment...",
|
}, 600);
|
||||||
"> 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) {
|
|
||||||
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;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Simulated form submission - in production replace with actual API call
|
|
||||||
// const formData = new FormData(form);
|
|
||||||
// const formValues = Object.fromEntries(formData.entries());
|
|
||||||
|
|
||||||
// Simulated API response delay
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
||||||
|
|
||||||
// Success message
|
|
||||||
alert('Thank you for your message! I will get back to you soon.');
|
|
||||||
form.reset();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
alert('Failed to send message. Please try again or contact me directly via email.');
|
|
||||||
} finally {
|
|
||||||
submitButton.innerHTML = originalButtonText;
|
|
||||||
submitButton.disabled = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -435,25 +118,4 @@ function updateYear() {
|
||||||
if (yearElement) {
|
if (yearElement) {
|
||||||
yearElement.textContent = new Date().getFullYear();
|
yearElement.textContent = new Date().getFullYear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility function to add particle float animation
|
|
||||||
*/
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
// Initialize all website functionality
|
|
||||||
initNavigation();
|
|
||||||
initParticlesAndIcons();
|
|
||||||
initRoleRotation(); // Updated function
|
|
||||||
initTerminalTyping(); // Updated function
|
|
||||||
initSolutionsCarousel(); // Updated function
|
|
||||||
initScrollReveal();
|
|
||||||
updateMetrics();
|
|
||||||
updateYear();
|
|
||||||
|
|
||||||
// Initialize form handling
|
|
||||||
const contactForm = document.getElementById('contact-form');
|
|
||||||
if (contactForm) {
|
|
||||||
initFormHandling(contactForm);
|
|
||||||
}
|
|
||||||
});
|
|
1188
styles.css
1188
styles.css
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue