620 lines
19 KiB
Plaintext
620 lines
19 KiB
Plaintext
---
|
|
// src/pages/projects.astro
|
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
|
import '../styles/card-animations.css';
|
|
import Header from '../components/Header.astro';
|
|
import Footer from '../components/Footer.astro';
|
|
|
|
const title = "Projects | LaForceIT";
|
|
const description = "Explore Daniel LaForce's projects, including infrastructure solutions, automation tools, and home lab configurations.";
|
|
|
|
// Category icons
|
|
const categoryIcons = {
|
|
"Infrastructure": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><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></svg>`,
|
|
"DevOps": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline><line x1="19" y1="12" x2="5" y2="12"></line></svg>`,
|
|
"Web Development": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>`,
|
|
"Documentation": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>`,
|
|
"Automation": `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 20V10"></path><path d="M12 20V4"></path><path d="M6 20v-6"></path><path d="M18 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path><path d="M12 8a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path><path d="M6 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg>`
|
|
};
|
|
|
|
// Featured projects
|
|
const featuredProjects = [
|
|
{
|
|
title: "Home Lab Infrastructure",
|
|
description: "Enterprise-grade home lab environment with Kubernetes, virtualization, networking, and storage solutions.",
|
|
image: "/images/projects/homelab.jpg",
|
|
url: "https://argobox.com",
|
|
isExternal: true,
|
|
technologies: ["Proxmox", "Kubernetes", "pfSense", "TrueNAS"],
|
|
category: "Infrastructure"
|
|
},
|
|
{
|
|
title: "Tech Stack",
|
|
description: "A detailed overview of the technologies, tools, and platforms that power my projects and home lab environment.",
|
|
image: "/images/projects/tech-stack.jpg",
|
|
url: "/tech-stack",
|
|
isExternal: false,
|
|
technologies: ["Kubernetes", "Docker", "Terraform", "Ansible"],
|
|
category: "Documentation"
|
|
},
|
|
{
|
|
title: "Infrastructure as Code Templates",
|
|
description: "Collection of Terraform and Ansible templates for automating infrastructure deployment.",
|
|
image: "/images/projects/iac.jpg",
|
|
url: "/projects/infrastructure-templates",
|
|
isExternal: false,
|
|
technologies: ["Terraform", "Ansible", "AWS", "Azure"],
|
|
category: "DevOps"
|
|
},
|
|
{
|
|
title: "Kubernetes Management Dashboard",
|
|
description: "Custom web interface for monitoring and managing Kubernetes clusters with enhanced visualization.",
|
|
image: "/images/projects/k8s-dashboard.jpg",
|
|
url: "/projects/kubernetes-dashboard",
|
|
isExternal: false,
|
|
technologies: ["React", "Node.js", "Kubernetes API", "Prometheus"],
|
|
category: "Web Development"
|
|
}
|
|
];
|
|
|
|
// Project categories
|
|
const categories = [
|
|
"All",
|
|
"Infrastructure",
|
|
"DevOps",
|
|
"Web Development",
|
|
"Documentation",
|
|
"Automation"
|
|
];
|
|
---
|
|
|
|
<BaseLayout title={title} description={description}>
|
|
<Header slot="header" />
|
|
|
|
<div class="container">
|
|
<div class="page-header">
|
|
<h1 class="page-title">Projects</h1>
|
|
<p class="page-description">
|
|
Explore my projects focused on infrastructure automation, DevOps solutions, and home lab configurations. These projects demonstrate practical applications of modern technologies in real-world scenarios.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Search & Filters -->
|
|
<div class="resource-search">
|
|
<div class="search-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
</svg>
|
|
</div>
|
|
<input type="text" placeholder="Search projects..." class="search-input" id="project-search">
|
|
</div>
|
|
|
|
<div class="resource-filters">
|
|
{categories.map(category => (
|
|
<button class={`filter-button ${category === 'All' ? 'active' : ''}`} data-filter={category.toLowerCase().replace(' ', '-')}>
|
|
{category}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<!-- Projects Grid -->
|
|
<div class="resources-grid">
|
|
{featuredProjects.map(project => (
|
|
<div class="resource-card" data-category={project.category.toLowerCase().replace(' ', '-')}>
|
|
<div class="resource-icon-wrapper">
|
|
<div class="resource-icon" set:html={categoryIcons[project.category]}></div>
|
|
<div class="resource-icon-particles">
|
|
<div class="resource-icon-particle"></div>
|
|
<div class="resource-icon-particle"></div>
|
|
<div class="resource-icon-particle"></div>
|
|
<div class="resource-icon-particle"></div>
|
|
<div class="resource-icon-particle"></div>
|
|
</div>
|
|
{/* Add animated dots in the background of each icon area */}
|
|
<div class="icon-bg-dot" style={{top: '20%', left: '80%'}}></div>
|
|
<div class="icon-bg-dot" style={{top: '70%', left: '15%'}}></div>
|
|
<div class="icon-bg-dot" style={{top: '30%', left: '30%'}}></div>
|
|
<div class="icon-bg-dot" style={{top: '60%', left: '70%'}}></div>
|
|
<div class="icon-bg-dot" style={{top: '10%', left: '50%'}}></div>
|
|
</div>
|
|
<div class="resource-content">
|
|
<h2 class="resource-title">{project.title}</h2>
|
|
<p class="resource-description">{project.description}</p>
|
|
<a href={project.url} class="resource-link" target={project.isExternal ? "_blank" : undefined} rel={project.isExternal ? "noopener noreferrer" : undefined}>
|
|
{project.isExternal ? 'Visit Project' : 'View Project'}
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" 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 class="resource-tags">
|
|
{project.technologies.map(tech => (
|
|
<span class="resource-tag">{tech}</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div class="shine-effect"></div>
|
|
</div>
|
|
))}
|
|
|
|
<!-- Empty State (hidden by default) -->
|
|
<div class="no-results" style="display: none;">
|
|
<div class="no-results-icon">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round">
|
|
<circle cx="11" cy="11" r="8"></circle>
|
|
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
<line x1="11" y1="8" x2="11" y2="14"></line>
|
|
<line x1="8" y1="11" x2="14" y2="11"></line>
|
|
</svg>
|
|
</div>
|
|
<h3>No matching projects found</h3>
|
|
<p>Try adjusting your search terms or filters to find what you're looking for.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="github-section">
|
|
<div class="github-header">
|
|
<div class="github-icon-wrapper">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
|
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
|
</svg>
|
|
<div class="github-icon-particles">
|
|
<div class="github-icon-particle"></div>
|
|
<div class="github-icon-particle"></div>
|
|
<div class="github-icon-particle"></div>
|
|
<div class="github-icon-particle"></div>
|
|
</div>
|
|
</div>
|
|
<h2 class="section-title">GitHub Repositories</h2>
|
|
<a href="/projects/github" class="view-all">
|
|
View All
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<polyline points="9 18 15 12 9 6"></polyline>
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
<div class="github-content">
|
|
<p class="github-message">
|
|
Explore my open-source projects and contributions on GitHub. These repositories include infrastructure configurations, automation scripts, and development tools.
|
|
</p>
|
|
<a href="/projects/github" class="github-cta">
|
|
<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">
|
|
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
|
</svg>
|
|
Browse Repositories
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Footer slot="footer" />
|
|
</BaseLayout>
|
|
|
|
<style>
|
|
.container {
|
|
max-width: 1280px;
|
|
margin: 0 auto;
|
|
padding: 0 var(--container-padding, 1.5rem);
|
|
}
|
|
|
|
.page-header {
|
|
text-align: center;
|
|
margin-bottom: 3rem;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 3rem;
|
|
font-weight: 700;
|
|
margin-bottom: 1rem;
|
|
background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary));
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
color: transparent;
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
|
|
.page-title::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -10px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 100px;
|
|
height: 3px;
|
|
background: linear-gradient(to right, var(--accent-primary), var(--accent-secondary));
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.page-description {
|
|
max-width: 800px;
|
|
margin: 0 auto;
|
|
color: var(--text-secondary);
|
|
font-size: 1.1rem;
|
|
}
|
|
|
|
/* Resource Filtering */
|
|
.resource-filters {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: 0.75rem;
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
.filter-button {
|
|
padding: 0.5rem 1.25rem;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border-primary);
|
|
color: var(--text-secondary);
|
|
border-radius: 20px;
|
|
font-size: 0.9rem;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.filter-button:hover {
|
|
background: linear-gradient(90deg, rgba(6, 182, 212, 0.1), rgba(59, 130, 246, 0.1));
|
|
color: var(--text-primary);
|
|
border-color: var(--accent-primary);
|
|
box-shadow: 0 0 10px var(--glow-primary);
|
|
}
|
|
|
|
.filter-button.active {
|
|
background: linear-gradient(90deg, rgba(6, 182, 212, 0.2), rgba(59, 130, 246, 0.2));
|
|
color: var(--accent-primary);
|
|
border-color: var(--accent-primary);
|
|
box-shadow: 0 0 15px var(--glow-primary);
|
|
}
|
|
|
|
/* Search Box */
|
|
.resource-search {
|
|
display: flex;
|
|
margin: 0 auto 2rem;
|
|
max-width: 500px;
|
|
position: relative;
|
|
}
|
|
|
|
.search-input {
|
|
width: 100%;
|
|
padding: 0.75rem 1rem 0.75rem 2.75rem;
|
|
background: var(--bg-tertiary);
|
|
border: 1px solid var(--border-primary);
|
|
border-radius: 8px;
|
|
color: var(--text-primary);
|
|
font-size: 1rem;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.search-input:focus {
|
|
outline: none;
|
|
border-color: var(--accent-primary);
|
|
box-shadow: 0 0 0 3px var(--glow-primary);
|
|
}
|
|
|
|
.search-icon {
|
|
position: absolute;
|
|
left: 1rem;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: var(--text-tertiary);
|
|
}
|
|
|
|
/* Resources Grid */
|
|
.resources-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
gap: 2rem;
|
|
margin-top: 1rem;
|
|
margin-bottom: 4rem;
|
|
}
|
|
|
|
/* Styles for .resource-card, .resource-icon-wrapper, etc. are now in card-animations.css */
|
|
|
|
.resource-content {
|
|
padding: 1.5rem;
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.resource-title {
|
|
font-size: 1.3rem;
|
|
font-weight: 600;
|
|
margin-bottom: 0.75rem;
|
|
color: var(--text-primary);
|
|
}
|
|
|
|
.resource-description {
|
|
color: var(--text-secondary);
|
|
margin-bottom: 1.5rem;
|
|
flex: 1;
|
|
}
|
|
|
|
.resource-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
text-decoration: none;
|
|
color: var(--accent-primary);
|
|
font-weight: 500;
|
|
transition: all 0.3s ease;
|
|
position: relative;
|
|
align-self: flex-start;
|
|
}
|
|
|
|
.resource-link::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -2px;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 1px;
|
|
background: var(--accent-primary);
|
|
transform: scaleX(0);
|
|
transform-origin: right;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.resource-link:hover {
|
|
color: var(--accent-secondary);
|
|
}
|
|
|
|
.resource-link:hover::after {
|
|
transform: scaleX(1);
|
|
transform-origin: left;
|
|
}
|
|
|
|
.resource-link svg {
|
|
margin-left: 0.5rem;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.resource-link:hover svg {
|
|
transform: translateX(3px);
|
|
}
|
|
|
|
.resource-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.5rem;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
/* .resource-tag styling is now in card-animations.css */
|
|
|
|
|
|
/* Background dots styling is now in card-animations.css */
|
|
|
|
|
|
/* Shine effect styling is now in card-animations.css */
|
|
|
|
/* Empty State */
|
|
.no-results {
|
|
text-align: center;
|
|
padding: 3rem;
|
|
color: var(--text-secondary);
|
|
background: var(--bg-tertiary);
|
|
border-radius: 12px;
|
|
border: 1px dashed var(--border-primary);
|
|
margin-top: 2rem;
|
|
display: none; /* Hidden by default */
|
|
grid-column: 1 / -1; /* Span all columns */
|
|
}
|
|
|
|
.no-results-icon {
|
|
color: var(--text-tertiary);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.no-results-icon svg {
|
|
width: 64px;
|
|
height: 64px;
|
|
stroke-width: 1;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
/* GitHub Section (kept from original) */
|
|
.github-section {
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border-primary);
|
|
border-radius: 16px;
|
|
padding: 3rem;
|
|
margin: 2rem 0 4rem;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.github-section::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: radial-gradient(circle at 30% 50%, rgba(6, 182, 212, 0.1), transparent 70%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.github-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 1rem;
|
|
margin-bottom: 2rem;
|
|
position: relative;
|
|
}
|
|
|
|
.github-icon-wrapper {
|
|
position: relative;
|
|
width: 64px;
|
|
height: 64px;
|
|
border-radius: 12px;
|
|
background: rgba(0, 0, 0, 0.2);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--text-primary);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.github-icon-particles {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.github-icon-particle {
|
|
position: absolute;
|
|
width: 4px;
|
|
height: 4px;
|
|
border-radius: 50%;
|
|
background: var(--accent-primary);
|
|
opacity: 0.5;
|
|
animation: github-particle 3s infinite ease-in-out;
|
|
}
|
|
|
|
.github-icon-particle:nth-child(1) { animation-delay: 0s; }
|
|
.github-icon-particle:nth-child(2) { animation-delay: 0.5s; }
|
|
.github-icon-particle:nth-child(3) { animation-delay: 1s; }
|
|
.github-icon-particle:nth-child(4) { animation-delay: 1.5s; }
|
|
|
|
@keyframes github-particle {
|
|
0% { transform: translate(0, 0); opacity: 0; }
|
|
25% { opacity: 0.5; }
|
|
50% { transform: translate(20px, -20px); opacity: 0.8; }
|
|
75% { opacity: 0.5; }
|
|
100% { transform: translate(40px, -40px); opacity: 0; }
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 2rem;
|
|
color: var(--text-primary);
|
|
margin: 0;
|
|
position: relative;
|
|
flex: 1;
|
|
}
|
|
|
|
.view-all {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
color: var(--accent-primary);
|
|
font-size: var(--font-size-sm);
|
|
text-decoration: none;
|
|
transition: all 0.3s ease;
|
|
position: relative;
|
|
}
|
|
|
|
.view-all::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: -2px;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 1px;
|
|
background: var(--accent-primary);
|
|
transform: scaleX(0);
|
|
transform-origin: right;
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.view-all:hover {
|
|
color: var(--accent-secondary);
|
|
transform: translateX(3px);
|
|
}
|
|
|
|
.view-all:hover::after {
|
|
transform: scaleX(1);
|
|
transform-origin: left;
|
|
}
|
|
|
|
.view-all svg {
|
|
transition: transform 0.3s ease;
|
|
}
|
|
|
|
.view-all:hover svg {
|
|
transform: translateX(3px);
|
|
}
|
|
|
|
.github-content {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
gap: 2rem;
|
|
}
|
|
|
|
.github-message {
|
|
color: var(--text-secondary);
|
|
font-size: var(--font-size-lg);
|
|
line-height: 1.7;
|
|
max-width: 70%;
|
|
margin: 0;
|
|
}
|
|
|
|
.github-cta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.75rem;
|
|
background: #24292e;
|
|
color: white;
|
|
padding: 0.75rem 1.25rem;
|
|
border-radius: 8px;
|
|
text-decoration: none;
|
|
font-weight: 500;
|
|
transition: all 0.3s ease;
|
|
white-space: nowrap;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.github-cta::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), transparent);
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.github-cta:hover {
|
|
transform: translateY(-3px);
|
|
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.github-cta:hover::before {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Keyframes are now in card-animations.css */
|
|
|
|
@media (max-width: 768px) {
|
|
.page-title {
|
|
font-size: 2.5rem;
|
|
}
|
|
|
|
.github-section {
|
|
padding: 2rem 1.5rem;
|
|
}
|
|
|
|
.github-content {
|
|
flex-direction: column;
|
|
text-align: center;
|
|
gap: 1.5rem;
|
|
}
|
|
|
|
.github-message {
|
|
max-width: 100%;
|
|
}
|
|
|
|
.github-header {
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
text-align: center;
|
|
}
|
|
} |