argobox/src/components/HomePage.astro

1101 lines
31 KiB
Plaintext

---
// HomePage.astro
// Premium homepage for LaForceIT tech blog
import BaseLayout from '../layouts/BaseLayout.astro';
import Header from '../components/Header.astro';
import Footer from '../components/Footer.astro';
import Terminal from '../components/Terminal.astro';
import KnowledgeGraph from '../components/KnowledgeGraph.astro';
import { getCollection } from 'astro:content';
import { Image } from 'astro:assets';
import { COMMON_COMMANDS, TERMINAL_CONTENT } from '../config/terminal.js';
// Get all blog entries
const allPosts = await getCollection('posts');
// Sort by publication date
const sortedPosts = allPosts.sort((a, b) => {
const dateA = a.data.pubDate ? new Date(a.data.pubDate) : new Date(0);
const dateB = b.data.pubDate ? new Date(b.data.pubDate) : new Date(0);
return dateB.getTime() - dateA.getTime();
});
// Get recent posts (latest 4)
const recentPosts = sortedPosts.slice(0, 4);
// Prepare terminal commands - now imported from central config
const terminalCommands = COMMON_COMMANDS;
// Prepare graph data for knowledge map
// Extract categories and tags from posts
const categories = [...new Set(allPosts.map(post => post.data.category || 'Uncategorized'))];
const allTags = [...new Set(allPosts.flatMap(post => post.data.tags || []))];
// Prepare graph nodes (posts)
const graphNodes = allPosts.map(post => ({
id: post.slug,
label: post.data.title,
category: post.data.category || 'Uncategorized',
tags: post.data.tags || []
}));
// Create edges between posts with similar tags or categories
const graphEdges = [];
for (let i = 0; i < graphNodes.length; i++) {
const postA = graphNodes[i];
for (let j = i + 1; j < graphNodes.length; j++) {
const postB = graphNodes[j];
// Create edge if posts share at least one tag or same category
const sharedTags = postA.tags.filter(tag => postB.tags.includes(tag));
if (sharedTags.length > 0 || postA.category === postB.category) {
graphEdges.push({
source: postA.id,
target: postB.id,
strength: sharedTags.length + (postA.category === postB.category ? 1 : 0)
});
}
}
}
const graphData = {
nodes: graphNodes,
edges: graphEdges
};
// Featured services
const services = [
{
title: "Kubernetes Configurations",
description: "Production-ready Kubernetes manifests for deploying applications at scale.",
icon: "server",
link: "/resources/kubernetes"
},
{
title: "Docker Compose Templates",
description: "Ready-to-use compose files for quickly deploying services in your home lab.",
icon: "box",
link: "/resources/docker-compose"
},
{
title: "Infrastructure Guides",
description: "Step-by-step tutorials for setting up enterprise-grade home infrastructure.",
icon: "layers",
link: "/resources/infrastructure"
},
{
title: "Monitoring Solutions",
description: "End-to-end monitoring stacks for keeping an eye on your systems.",
icon: "activity",
link: "/resources/monitoring"
}
];
// Tech stack items
const techStack = [
{ name: "Kubernetes", icon: "https://cdn.simpleicons.org/kubernetes/326CE5" },
{ name: "Docker", icon: "https://cdn.simpleicons.org/docker/2496ED" },
{ name: "Prometheus", icon: "https://cdn.simpleicons.org/prometheus/E6522C" },
{ name: "Ansible", icon: "https://cdn.simpleicons.org/ansible/EE0000" },
{ name: "Terraform", icon: "https://cdn.simpleicons.org/terraform/7B42BC" },
{ name: "ArgoCD", icon: "https://cdn.simpleicons.org/argo/EF7B4D" },
{ name: "GitHub", icon: "https://cdn.simpleicons.org/github/181717" },
{ name: "Grafana", icon: "https://cdn.simpleicons.org/grafana/F46800" },
];
---
<BaseLayout title="LaForceIT - Home Lab & DevOps Insights" description="Dive into enterprise-grade home lab setups, Kubernetes deployments, and DevOps best practices for the modern tech enthusiast">
<Header slot="header" />
<main>
<!-- Hero Section -->
<section class="hero-section">
<div class="hero-bg"></div>
<div class="container">
<div class="hero-content">
<div class="hero-text">
<div class="hero-subtitle">
<span class="hero-badge">Technical Articles & Guides</span>
</div>
<h1 class="hero-title">
Exploring
<span class="gradient-text">advanced</span><br>
<span class="gradient-text-alt">infrastructure</span> and
<span class="emphasis">automation</span>
</h1>
<p class="hero-description">
Dive into enterprise-grade home lab setups, Kubernetes deployments, and DevOps best practices for the modern tech enthusiast.
</p>
<div class="hero-actions">
<a href="/blog" class="primary-button">
<span>Explore Articles</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="/resources" class="secondary-button">
<span>View Resources</span>
</a>
</div>
</div>
<div class="terminal-container">
<Terminal commands={terminalCommands} title="argobox:~/homelab" />
</div>
</div>
</div>
<div class="tech-stack">
<div class="tech-stack-slider">
<div class="tech-stack-track">
{techStack.map((tech) => (
<div class="tech-item">
<img src={tech.icon} alt={tech.name} class="tech-icon" />
<span class="tech-name">{tech.name}</span>
</div>
))}
{/* Duplicate for infinite scrolling */}
{techStack.map((tech) => (
<div class="tech-item">
<img src={tech.icon} alt={tech.name} class="tech-icon" />
<span class="tech-name">{tech.name}</span>
</div>
))}
</div>
</div>
</div>
</section>
<!-- Featured Services Section -->
<section class="services-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Technical Resources</h2>
<p class="section-description">
Enterprise-grade solutions for your home lab and DevOps workflows
</p>
</div>
<div class="services-grid">
{services.map((service) => (
<a href={service.link} class="service-card">
<div class="service-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
{service.icon === 'server' && (
<>
<rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect>
<rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect>
<line x1="6" y1="6" x2="6.01" y2="6"></line>
<line x1="6" y1="18" x2="6.01" y2="18"></line>
</>
)}
{service.icon === 'box' && (
<>
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</>
)}
{service.icon === 'layers' && (
<>
<polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
<polyline points="2 17 12 22 22 17"></polyline>
<polyline points="2 12 12 17 22 12"></polyline>
</>
)}
{service.icon === 'activity' && (
<>
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>
</>
)}
</svg>
</div>
<h3 class="service-title">{service.title}</h3>
<p class="service-description">{service.description}</p>
<div class="service-link">
<span>Explore</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
<polyline points="15 3 21 3 21 9"></polyline>
<line x1="10" y1="14" x2="21" y2="3"></line>
</svg>
</div>
</a>
))}
</div>
</div>
</section>
<!-- Knowledge Graph Section -->
<section class="graph-container-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Knowledge Graph</h2>
<p class="section-description">
Explore connections between articles based on topics and categories
</p>
</div>
</div>
<div class="full-width-container">
<KnowledgeGraph graphData={graphData} height="600px" />
</div>
</section>
<!-- Recent Articles Section -->
<section class="recent-articles-section">
<div class="container">
<div class="section-header">
<h2 class="section-title">Recent Articles</h2>
<p class="section-description">
Latest insights and guides from the LaForceIT blog
</p>
</div>
<div class="articles-grid">
{recentPosts.map((post) => (
<a href={`/posts/${post.slug}/`} class="article-card">
<div class="article-image-container">
<img
src={post.data.heroImage || '/images/placeholders/default.jpg'}
alt={post.data.title}
class="article-image"
width="600"
height="300"
loading="lazy"
/>
{post.data.category && (
<span class="article-category">{post.data.category}</span>
)}
</div>
<div class="article-content">
<div class="article-meta">
<time datetime={post.data.pubDate?.toISOString()}>
{post.data.pubDate ? new Date(post.data.pubDate).toLocaleDateString('en-us', {
year: 'numeric',
month: 'short',
day: 'numeric'
}) : 'No date'}
</time>
<span class="article-read-time">{post.data.readTime || '5 min read'}</span>
</div>
<h3 class="article-title">{post.data.title}</h3>
<p class="article-excerpt">{post.data.description || 'No description available'}</p>
<div class="article-footer">
<div class="article-tags">
{post.data.tags && post.data.tags.slice(0, 2).map((tag) => (
<span class="article-tag">{tag}</span>
))}
{post.data.tags && post.data.tags.length > 2 && (
<span class="article-tag">+{post.data.tags.length - 2}</span>
)}
</div>
<span class="read-more">Read More</span>
</div>
</div>
</a>
))}
</div>
<div class="view-all-container">
<a href="/blog" class="view-all-button">
<span>View All Articles</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</div>
</div>
</section>
<!-- CTA Section -->
<section class="cta-section">
<div class="cta-bg"></div>
<div class="container">
<div class="cta-container">
<h2 class="cta-title">Ready to upgrade your home lab?</h2>
<p class="cta-description">
Get access to premium resources, configuration templates, and step-by-step guides to take your infrastructure to the next level.
</p>
<div class="cta-actions">
<a href="/resources" class="cta-primary-button">
<span>Explore Resources</span>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
<polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
<a href="/contact" class="cta-secondary-button">
<span>Get in Touch</span>
</a>
</div>
</div>
</div>
</section>
<!-- Terminal Section -->
<section class="terminal-section">
<div class="container">
<div class="row">
<div class="col-12 col-md-6">
<Terminal
title="argobox:~/kubernetes"
promptPrefix={TERMINAL_DEFAULTS.promptPrefix}
height="400px"
command="kubectl get pods -A | head -8"
output={`NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-66bff467f8-8p7z2 1/1 Running 0 15d
kube-system coredns-66bff467f8-v68vr 1/1 Running 0 15d
kube-system etcd-control-plane 1/1 Running 0 15d
kube-system kube-apiserver-control-plane 1/1 Running 0 15d
kube-system kube-controller-manager-control-plane 1/1 Running 0 15d
kube-system kube-proxy-c84qf 1/1 Running 0 15d
kube-system kube-scheduler-control-plane 1/1 Running 0 15d`}
/>
</div>
<div class="col-12 col-md-6">
<Terminal
title="argobox:~/system"
promptPrefix={TERMINAL_DEFAULTS.promptPrefix}
height="400px"
content={SYSTEM_MONITOR_SEQUENCE.map(item => `<div class="term-blue">${item.prompt}</div><span>$</span> <span class="term-bold">${item.command}</span>\n${item.output.join('\n')}`).join('\n\n')}
/>
</div>
</div>
</div>
</section>
</main>
<Footer slot="footer" />
</BaseLayout>
<style>
/* Hero Section */
.hero-section {
position: relative;
padding: 8rem 0 6rem;
overflow: hidden;
background: linear-gradient(to bottom, var(--bg-secondary), var(--bg-primary));
}
.hero-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at 20% 35%, rgba(6, 182, 212, 0.1) 0%, transparent 50%),
radial-gradient(circle at 75% 15%, rgba(59, 130, 246, 0.1) 0%, transparent 45%),
radial-gradient(circle at 85% 70%, rgba(139, 92, 246, 0.1) 0%, transparent 40%);
z-index: -1;
}
.hero-bg::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(226, 232, 240, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(226, 232, 240, 0.03) 1px, transparent 1px);
background-size: 30px 30px;
}
.hero-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
align-items: center;
}
.hero-text {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.hero-subtitle {
display: flex;
align-items: center;
gap: 0.5rem;
}
.hero-badge {
background: rgba(6, 182, 212, 0.1);
color: var(--accent-primary);
padding: 0.5rem 1rem;
border-radius: 30px;
font-size: 0.85rem;
font-weight: 500;
letter-spacing: 0.05em;
font-family: var(--font-mono);
border: 1px solid rgba(6, 182, 212, 0.2);
}
.hero-title {
font-size: clamp(2.5rem, 5vw, 3.5rem);
line-height: 1.1;
margin: 0;
}
.gradient-text {
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-block;
}
.gradient-text-alt {
background: linear-gradient(90deg, var(--accent-secondary), var(--accent-tertiary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-block;
}
.emphasis {
position: relative;
display: inline-block;
}
.emphasis::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 100%;
height: 4px;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
border-radius: 2px;
}
.hero-description {
color: var(--text-secondary);
font-size: clamp(1rem, 2vw, 1.25rem);
line-height: 1.6;
max-width: 540px;
margin: 0;
}
.hero-actions {
display: flex;
flex-wrap: wrap;
gap: 1rem;
margin-top: 1rem;
}
.primary-button {
padding: 0.8rem 1.5rem;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
color: var(--bg-primary);
font-weight: 600;
border-radius: 8px;
border: none;
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(6, 182, 212, 0.3);
}
.primary-button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(6, 182, 212, 0.4);
}
.secondary-button {
padding: 0.8rem 1.5rem;
background: rgba(226, 232, 240, 0.1);
color: var(--text-primary);
font-weight: 600;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
}
.secondary-button:hover {
background: rgba(226, 232, 240, 0.2);
border-color: rgba(255, 255, 255, 0.2);
}
.terminal-container {
position: relative;
z-index: 1;
}
/* Tech Stack Slider */
.tech-stack {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background: linear-gradient(0deg, rgba(13, 18, 30, 0.9), transparent);
padding: 1.5rem 0;
overflow: hidden;
}
.tech-stack-slider {
width: 100%;
overflow: hidden;
}
.tech-stack-track {
display: flex;
animation: scroll 30s linear infinite;
}
.tech-item {
display: flex;
align-items: center;
gap: 0.75rem;
margin: 0 1.5rem;
white-space: nowrap;
color: var(--text-secondary);
}
.tech-icon {
width: 24px;
height: 24px;
}
.tech-name {
font-size: 0.9rem;
font-family: var(--font-mono);
}
@keyframes scroll {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-50%);
}
}
/* Services Section */
.services-section {
padding: 6rem 0;
background: var(--bg-primary);
position: relative;
}
.section-header {
text-align: center;
max-width: 800px;
margin: 0 auto 4rem;
}
.section-title {
font-size: clamp(1.75rem, 3vw, 2.5rem);
margin-bottom: 1rem;
position: relative;
display: inline-block;
}
.section-title::after {
content: '';
position: absolute;
height: 4px;
width: 60px;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
bottom: -10px;
left: 50%;
transform: translateX(-50%);
border-radius: 2px;
}
.section-description {
color: var(--text-secondary);
max-width: 600px;
margin: 0 auto;
}
.services-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.service-card {
background: rgba(30, 41, 59, 0.5);
border: 1px solid var(--border-primary);
border-radius: 12px;
padding: 2rem;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
gap: 1.25rem;
text-decoration: none;
color: var(--text-primary);
position: relative;
overflow: hidden;
height: 100%;
}
.service-card::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(6, 182, 212, 0.05), rgba(139, 92, 246, 0.05));
z-index: -1;
opacity: 0;
transition: opacity 0.3s ease;
}
.service-card:hover {
transform: translateY(-5px);
border-color: rgba(6, 182, 212, 0.3);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.service-card:hover::before {
opacity: 1;
}
.service-icon {
background: rgba(6, 182, 212, 0.1);
width: 56px;
height: 56px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: var(--accent-primary);
transition: all 0.3s ease;
}
.service-card:hover .service-icon {
background: var(--accent-primary);
color: var(--bg-primary);
transform: scale(1.1);
}
.service-title {
font-size: 1.25rem;
margin: 0;
}
.service-description {
color: var(--text-secondary);
font-size: 0.95rem;
margin: 0;
line-height: 1.6;
flex-grow: 1;
}
.service-link {
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--accent-primary);
font-weight: 500;
font-size: 0.95rem;
margin-top: auto;
transition: all 0.3s ease;
}
.service-card:hover .service-link {
transform: translateX(5px);
}
/* Knowledge Graph Section */
.graph-container-section {
padding: 4rem 0;
background: linear-gradient(180deg, var(--bg-primary), var(--bg-secondary), var(--bg-primary));
position: relative;
}
.full-width-container {
max-width: 1440px;
margin: 0 auto;
padding: 0 1rem;
}
/* Recent Articles Section */
.recent-articles-section {
padding: 6rem 0;
background: var(--bg-primary);
position: relative;
}
.articles-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
margin-top: 2rem;
}
.article-card {
background: var(--card-bg);
border-radius: 12px;
border: 1px solid var(--card-border);
overflow: hidden;
transition: all 0.3s ease;
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
height: 100%;
text-decoration: none;
color: var(--text-primary);
}
.article-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(6, 182, 212, 0.1);
border-color: rgba(6, 182, 212, 0.3);
}
.article-card::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(6, 182, 212, 0.05), rgba(139, 92, 246, 0.05));
z-index: -1;
opacity: 0;
transition: opacity 0.3s ease;
}
.article-card:hover::before {
opacity: 1;
}
.article-image-container {
position: relative;
}
.article-image {
width: 100%;
height: 200px;
object-fit: cover;
}
.article-category {
position: absolute;
top: 15px;
right: 15px;
background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
color: var(--bg-primary);
padding: 0.35rem 0.8rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
box-shadow: 0 2px 10px rgba(6, 182, 212, 0.25);
font-family: var(--font-mono);
}
.article-content {
padding: 1.5rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.article-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
font-size: 0.85rem;
color: var(--text-secondary);
}
.article-title {
font-size: 1.25rem;
margin-bottom: 0.75rem;
line-height: 1.3;
}
.article-excerpt {
color: var(--text-secondary);
font-size: 0.9rem;
margin-bottom: 1.5rem;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
flex-grow: 1;
}
.article-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: auto;
}
.article-tags {
display: flex;
gap: 0.5rem;
}
.article-tag {
background: rgba(255, 255, 255, 0.05);
color: var(--text-secondary);
padding: 0.2rem 0.5rem;
border-radius: 4px;
font-size: 0.7rem;
font-family: var(--font-mono);
}
.read-more {
color: var(--accent-primary);
font-weight: 500;
display: flex;
align-items: center;
gap: 0.25rem;
transition: all 0.3s ease;
}
.read-more::after {
content: '→';
transition: transform 0.3s ease;
}
.article-card:hover .read-more::after {
transform: translateX(3px);
}
.view-all-container {
display: flex;
justify-content: center;
margin-top: 3rem;
}
.view-all-button {
padding: 0.8rem 1.5rem;
background: rgba(226, 232, 240, 0.05);
color: var(--text-primary);
font-weight: 600;
border-radius: 8px;
border: 1px solid var(--border-primary);
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
}
.view-all-button:hover {
background: rgba(226, 232, 240, 0.1);
transform: translateY(-3px);
}
/* CTA Section */
.cta-section {
padding: 6rem 0;
position: relative;
}
.cta-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(6, 182, 212, 0.05), rgba(139, 92, 246, 0.05));
z-index: -1;
}
.cta-bg::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(226, 232, 240, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(226, 232, 240, 0.03) 1px, transparent 1px);
background-size: 30px 30px;
}
.cta-container {
max-width: 800px;
margin: 0 auto;
text-align: center;
background: rgba(30, 41, 59, 0.7);
backdrop-filter: blur(10px);
border: 1px solid var(--border-primary);
border-radius: 16px;
padding: 3rem;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.cta-title {
font-size: clamp(1.5rem, 3vw, 2.25rem);
margin-bottom: 1.5rem;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-tertiary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
display: inline-block;
}
.cta-description {
color: var(--text-secondary);
font-size: clamp(1rem, 2vw, 1.1rem);
margin-bottom: 2rem;
line-height: 1.6;
}
.cta-actions {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: center;
}
.cta-primary-button {
padding: 0.8rem 1.5rem;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
color: var(--bg-primary);
font-weight: 600;
border-radius: 8px;
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(6, 182, 212, 0.3);
}
.cta-primary-button:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(6, 182, 212, 0.4);
}
.cta-secondary-button {
padding: 0.8rem 1.5rem;
background: rgba(226, 232, 240, 0.1);
color: var(--text-primary);
font-weight: 600;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
transition: all 0.3s ease;
}
.cta-secondary-button:hover {
background: rgba(226, 232, 240, 0.2);
}
/* Terminal Section */
.terminal-section {
padding: 6rem 0;
background: var(--bg-primary);
position: relative;
}
.section-title {
font-size: clamp(1.75rem, 3vw, 2.5rem);
margin-bottom: 1rem;
position: relative;
display: inline-block;
}
.section-title::after {
content: '';
position: absolute;
height: 4px;
width: 60px;
background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary));
bottom: -10px;
left: 50%;
transform: translateX(-50%);
border-radius: 2px;
}
/* Responsive Design */
@media (max-width: 1024px) {
.hero-content {
grid-template-columns: 1fr;
gap: 3rem;
}
.hero-text {
text-align: center;
align-items: center;
}
.hero-description {
max-width: 100%;
}
.cta-container {
padding: 2rem;
margin: 0 1rem;
}
}
@media (max-width: 768px) {
.hero-section {
padding: 6rem 0 8rem;
}
.articles-grid {
grid-template-columns: 1fr;
}
.hero-actions {
justify-content: center;
}
.services-grid {
grid-template-columns: 1fr;
}
.cta-container {
padding: 2rem 1rem;
}
}
</style>
<script>
// Animate neural nodes in hero section
document.addEventListener('DOMContentLoaded', () => {
const heroSection = document.querySelector('.hero-section');
if (heroSection) {
// Create animated nodes
for (let i = 0; i < 15; i++) {
const node = document.createElement('div');
node.classList.add('neural-node');
// Set random positions
node.style.position = 'absolute';
node.style.width = `${Math.random() * 2 + 1}px`;
node.style.height = node.style.width;
node.style.background = 'rgba(226, 232, 240, 0.15)';
node.style.borderRadius = '50%';
node.style.top = `${Math.random() * 100}%`;
node.style.left = `${Math.random() * 100}%`;
node.style.boxShadow = '0 0 10px rgba(6, 182, 212, 0.5)';
node.style.zIndex = '-1';
// Set animation properties
node.style.animation = `pulse ${4 + Math.random() * 4}s infinite alternate ease-in-out`;
node.style.animationDelay = `${Math.random() * 5}s`;
heroSection.appendChild(node);
}
}
});
</script>