refactoring theme system, refactoring scss, creating footer, contact, certifications and skill sections

This commit is contained in:
Sascha Bach 2025-08-26 18:08:50 +02:00
parent e13dda79bf
commit d15418c3b1
40 changed files with 2656 additions and 379 deletions

12
package-lock.json generated
View File

@ -10,7 +10,8 @@
"dependencies": { "dependencies": {
"lucide-react": "^0.539.0", "lucide-react": "^0.539.0",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1" "react-dom": "^19.1.1",
"react-icons": "^5.5.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.32.0", "@eslint/js": "^9.32.0",
@ -3255,6 +3256,15 @@
"react": "^19.1.1" "react": "^19.1.1"
} }
}, },
"node_modules/react-icons": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
"license": "MIT",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.17.0", "version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",

View File

@ -12,7 +12,8 @@
"dependencies": { "dependencies": {
"lucide-react": "^0.539.0", "lucide-react": "^0.539.0",
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1" "react-dom": "^19.1.1",
"react-icons": "^5.5.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.32.0", "@eslint/js": "^9.32.0",

View File

@ -4,6 +4,11 @@ import Navbar from '../components/layout/Navigation';
import HeroSection from '../components/sections/HeroSection'; import HeroSection from '../components/sections/HeroSection';
import AboutSection from '../components/sections/AboutSection'; import AboutSection from '../components/sections/AboutSection';
import ServicesSection from '../components/sections/ServicesSection'; import ServicesSection from '../components/sections/ServicesSection';
import SkillsSection from '../components/sections/SkillsSection';
import CertificationsSection from '../components/sections/CertificationsSection';
import ProjectsSection from '../components/sections/ProjectsSection';
import ContactSection from '../components/sections/ContactSection';
import Footer from '../components/layout/Footer';
function PortfolioApp() { function PortfolioApp() {
const [theme, setTheme] = useState<'light' | 'dark'>('light'); const [theme, setTheme] = useState<'light' | 'dark'>('light');
@ -18,6 +23,11 @@ function PortfolioApp() {
<HeroSection /> <HeroSection />
<AboutSection /> <AboutSection />
<ServicesSection /> <ServicesSection />
<SkillsSection />
<CertificationsSection />
<ProjectsSection />
<ContactSection />
<Footer />
</> </>
); );
} }

View File

@ -0,0 +1,50 @@
import { Github, Linkedin, Mail } from 'lucide-react';
import { personalConfig, createEmailLink } from '../../config/personal';
export default function Footer() {
// Email obfuscation function using config
const handleEmailClick = (e: React.MouseEvent) => {
e.preventDefault();
window.location.href = createEmailLink();
};
return (
<footer className="footer">
<div className="footer__container">
<div className="footer__separator"></div>
<div className="footer__content">
<div className="footer__copyright">
© {new Date().getFullYear()} {personalConfig.name}. All rights reserved.
</div>
<div className="footer__social">
<button
className="footer__social-button"
onClick={() => window.open(personalConfig.social.github.url, '_blank')}
aria-label="GitHub Profile"
>
<Github className="footer__social-icon" />
</button>
<button
className="footer__social-button"
onClick={() => window.open(personalConfig.social.linkedin.url, '_blank')}
aria-label="LinkedIn Profile"
>
<Linkedin className="footer__social-icon" />
</button>
<button
className="footer__social-button"
onClick={handleEmailClick}
aria-label="Send Email"
>
<Mail className="footer__social-icon" />
</button>
</div>
</div>
</div>
</footer>
);
}

View File

@ -1,6 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import ThemeToggle from '../ThemeToggle'; import ThemeToggle from '../ThemeToggle';
import MobileMenu from './MobileMenu'; import MobileMenu from './MobileMenu';
import { personalConfig } from '../../config/personal';
type Props = { type Props = {
theme: 'light' | 'dark'; theme: 'light' | 'dark';
@ -19,9 +20,8 @@ export default function Navbar({ theme, setTheme }: Props) {
]; ];
return ( return (
// TODO Centralize strings, create buttons via loops
<div className="navbar"> <div className="navbar">
<div className="navbar__name">Sascha Bach</div> <div className="navbar__name">{personalConfig.name}</div>
<div className="navbar__container"> <div className="navbar__container">
{menuItems.map((item) => ( {menuItems.map((item) => (
<button <button

View File

@ -1,6 +1,6 @@
import { Code, Palette, ShieldCheck } from 'lucide-react'; import { Code, Palette, ShieldCheck } from 'lucide-react';
import type { SkillBadge } from '../../data/SkillBadge'; import type { SkillBadge } from '../../data/SkillBadge';
import type { FeatureCard } from '../../data/FeatureCard'; import type { Service } from '../../data/Service';
import saschaImage from '../../assets/sascha.png'; import saschaImage from '../../assets/sascha.png';
interface AboutSectionProps { interface AboutSectionProps {
@ -10,14 +10,14 @@ interface AboutSectionProps {
bio?: string; bio?: string;
profileImage?: string; profileImage?: string;
skillBadges?: SkillBadge[]; skillBadges?: SkillBadge[];
featureCards?: FeatureCard[]; featureCards?: Service[];
} }
export default function AboutSection({ export default function AboutSection({
name = "Sascha Bach", name = "Sascha Bach",
title = "About Me", title = "About Me",
subtitle = "Frontend developer specializing in modern web technologies. Since 2020, I've been building efficient, scalable solutions from complex Angular applications to creative React projects. My focus is on clean, maintainable code that solves real-world problems.", subtitle = "Web developer specializing in modern web technologies. Since 2020, I've been building efficient, scalable solutions from complex Angular applications to creative React projects. My focus is on clean, maintainable code that solves real-world problems.",
bio = "As a dedicated frontend developer, I specialize in creating modern, responsive web applications using both Angular and React frameworks with TypeScript. I'm passionate about writing clean, maintainable code and ensuring exceptional user experiences across all devices and browsers. I have extensive experience with Angular and am actively developing my React expertise, while maintaining proficiency in SCSS, testing with Cypress, and working with XSLT templates.", bio = "As a dedicated web developer, I specialize in creating modern, responsive web applications using both Angular and React frameworks with TypeScript. I'm passionate about writing clean, maintainable code and ensuring exceptional user experiences across all devices and browsers. I have extensive experience with Angular and am actively developing my React expertise, while maintaining proficiency in SCSS, testing with Cypress, and working with XSLT templates.",
profileImage = saschaImage, profileImage = saschaImage,
skillBadges = [ skillBadges = [
{ text: "Angular & React Developer", colorClass: "primary" }, { text: "Angular & React Developer", colorClass: "primary" },
@ -28,7 +28,7 @@ export default function AboutSection({
featureCards = [ featureCards = [
{ {
icon: Code, icon: Code,
title: "Frontend Development", title: "Web Development",
description: "Building modern web applications with Angular and React frameworks, leveraging TypeScript and JavaScript for robust, scalable solutions.", description: "Building modern web applications with Angular and React frameworks, leveraging TypeScript and JavaScript for robust, scalable solutions.",
colorClass: "primary" colorClass: "primary"
}, },
@ -64,7 +64,7 @@ export default function AboutSection({
<div className="about-section__image-wrapper"> <div className="about-section__image-wrapper">
<img <img
src={profileImage} src={profileImage}
alt={`${name} - Full Stack Developer`} alt={`${name} - Web Developer`}
className="about-section__image" className="about-section__image"
/> />
<div className="about-section__image-overlay"></div> <div className="about-section__image-overlay"></div>

View File

@ -0,0 +1,86 @@
import { Award } from 'lucide-react';
import type { Certification } from '../../data/Certification';
interface CertificationsSectionProps {
title?: string;
subtitle?: string;
certifications?: Certification[];
}
export default function CertificationsSection({
title = "Certifications & Achievements",
subtitle = "My professional qualifications and continuous learning",
certifications = [
{
name: "Understanding Typescript",
issuer: "Udemy",
year: "2025",
icon: ""
},
{
name: "Angular Step by Step",
issuer: "Udemy",
year: "2020",
icon: ""
},
{
name: "Angular and Typescript",
issuer: "LinkedIn TestDome",
year: "2020",
icon: ""
},
{
name: "Bachelor of Science in Computer Science",
issuer: "TU Darmstadt",
year: "2015",
icon: ""
}
]
}: CertificationsSectionProps) {
// Sort certifications by year in descending order (newest first)
const sortedCertifications = [...certifications].sort((a, b) => {
return parseInt(b.year) - parseInt(a.year);
});
return (
<section id="certifications" className="certifications-section">
<div className="certifications-section__container">
{/* Section Header */}
<div className="certifications-section__header">
<h2 className="certifications-section__title">
{title}
</h2>
<p className="certifications-section__subtitle">
{subtitle}
</p>
</div>
{/* Certifications Grid */}
<div className="certifications-section__grid">
{sortedCertifications.map((cert, index) => (
<div key={index} className="certifications-section__card">
<div className="certifications-section__card-header">
{cert.icon ? (
<img
src={cert.icon}
alt={cert.issuer}
className="certifications-section__card-icon-image"
/>
) : (
<Award className="certifications-section__card-icon" />
)}
<h3 className="certifications-section__card-title">{cert.name}</h3>
<p className="certifications-section__card-issuer">{cert.issuer}</p>
</div>
<div className="certifications-section__card-content">
<span className="certifications-section__card-badge">
{cert.year}
</span>
</div>
</div>
))}
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,279 @@
import { Mail, Github, Linkedin } from 'lucide-react';
import { useState } from 'react';
import type { FormEvent } from 'react';
import { personalConfig, getObfuscatedEmail, createEmailLink } from '../../config/personal';
interface ContactSectionProps {
title?: string;
subtitle?: string;
email?: string;
github?: string;
linkedin?: string;
connectTitle?: string;
connectDescription?: string;
}
// TODO Create Backend API for handling form submissions securely
export default function ContactSection({
title = "Get In Touch",
subtitle = "Let's discuss your next project or collaboration opportunity",
github = personalConfig.social.github.username,
connectTitle = "Let's Connect",
connectDescription = "I'm always interested in new opportunities and exciting projects. Whether you have a question or just want to say hi, feel free to reach out!"
}: ContactSectionProps) {
// Anti-spam honeypot state
const [honeypot, setHoneypot] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
// Email obfuscation function using config
const handleEmailClick = (e: React.MouseEvent) => {
e.preventDefault();
window.location.href = createEmailLink();
};
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Check honeypot - if filled, it's likely spam
if (honeypot) {
console.warn('Spam detected - honeypot field was filled');
return;
}
// Prevent rapid submissions
if (isSubmitting) {
return;
}
setIsSubmitting(true);
// Get form data
const formData = new FormData(e.currentTarget);
const data = {
firstName: formData.get('firstName') as string,
lastName: formData.get('lastName') as string,
email: formData.get('email') as string,
subject: formData.get('subject') as string,
message: formData.get('message') as string,
};
// Basic validation
if (!data.firstName || !data.lastName || !data.email || !data.message) {
alert('Please fill in all required fields.');
setIsSubmitting(false);
return;
}
// Email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(data.email)) {
alert('Please enter a valid email address.');
setIsSubmitting(false);
return;
}
try {
// Submit to Formspree (replace YOUR_FORM_ID with actual ID from Formspree)
const response = await fetch('https://formspree.io/f/YOUR_FORM_ID', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: `${data.firstName} ${data.lastName}`,
email: data.email,
subject: data.subject || 'Contact from Portfolio',
message: data.message,
_replyto: data.email, // This tells Formspree what email to reply to
}),
});
if (response.ok) {
alert('Thank you for your message! I\'ll get back to you soon.');
e.currentTarget.reset();
} else {
throw new Error('Form submission failed');
}
} catch (error) {
console.error('Form submission error:', error);
alert('Sorry, there was an error sending your message. Please try again.');
}
setIsSubmitting(false);
};
return (
<section id="contact" className="contact-section">
<div className="contact-section__container">
{/* Section Header */}
<div className="contact-section__header">
<h2 className="contact-section__title">
{title}
</h2>
<p className="contact-section__subtitle">
{subtitle}
</p>
</div>
{/* Contact Content Grid */}
<div className="contact-section__grid">
{/* Contact Info */}
<div className="contact-section__info">
<div className="contact-section__connect">
<h3 className="contact-section__connect-title">{connectTitle}</h3>
<p className="contact-section__connect-description">
{connectDescription}
</p>
</div>
<div className="contact-section__details">
<div className="contact-section__detail-item">
<Mail className="contact-section__detail-icon" />
<span className="contact-section__detail-text">{getObfuscatedEmail()}</span>
</div>
<div className="contact-section__detail-item">
<Github className="contact-section__detail-icon" />
<span className="contact-section__detail-text">{github}</span>
</div>
<div className="contact-section__detail-item">
<Linkedin className="contact-section__detail-icon" />
<span className="contact-section__detail-text">{personalConfig.social.linkedin.username}</span>
</div>
</div>
<div className="contact-section__social">
<button
className="contact-section__social-button"
onClick={() => window.open(personalConfig.social.github.url, '_blank')}
aria-label="GitHub Profile"
>
<Github className="contact-section__social-icon" />
</button>
<button
className="contact-section__social-button"
onClick={() => window.open(personalConfig.social.linkedin.url, '_blank')}
aria-label="LinkedIn Profile"
>
<Linkedin className="contact-section__social-icon" />
</button>
<button
className="contact-section__social-button"
onClick={handleEmailClick}
aria-label="Send Email"
>
<Mail className="contact-section__social-icon" />
</button>
</div>
</div>
{/* Contact Form */}
<div className="contact-section__form-card">
<div className="contact-section__form-header">
<h3 className="contact-section__form-title">Send a Message</h3>
<p className="contact-section__form-description">
I'll get back to you as soon as possible
</p>
</div>
<form className="contact-section__form" onSubmit={handleSubmit}>
{/* Honeypot field - hidden from users but visible to bots */}
<div className="contact-section__honeypot">
<label htmlFor="website" className="contact-section__honeypot-label">
Website (leave blank)
</label>
<input
id="website"
name="website"
type="text"
value={honeypot}
onChange={(e) => setHoneypot(e.target.value)}
className="contact-section__honeypot-input"
tabIndex={-1}
autoComplete="off"
/>
</div>
<div className="contact-section__form-row">
<div className="contact-section__form-group">
<label htmlFor="firstName" className="contact-section__form-label">
First Name *
</label>
<input
id="firstName"
name="firstName"
type="text"
placeholder="John"
className="contact-section__form-input"
required
/>
</div>
<div className="contact-section__form-group">
<label htmlFor="lastName" className="contact-section__form-label">
Last Name *
</label>
<input
id="lastName"
name="lastName"
type="text"
placeholder="Doe"
className="contact-section__form-input"
required
/>
</div>
</div>
<div className="contact-section__form-group">
<label htmlFor="email" className="contact-section__form-label">
Email *
</label>
<input
id="email"
name="email"
type="email"
placeholder="john@example.com"
className="contact-section__form-input"
required
/>
</div>
<div className="contact-section__form-group">
<label htmlFor="subject" className="contact-section__form-label">
Subject
</label>
<input
id="subject"
name="subject"
type="text"
placeholder="Project Inquiry"
className="contact-section__form-input"
/>
</div>
<div className="contact-section__form-group">
<label htmlFor="message" className="contact-section__form-label">
Message *
</label>
<textarea
id="message"
name="message"
placeholder="Tell me about your project..."
rows={5}
className="contact-section__form-textarea"
required
></textarea>
</div>
<button
type="submit"
className="contact-section__form-button"
disabled={isSubmitting}
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
</form>
</div>
</div>
</div>
</section>
);
}

View File

@ -11,7 +11,7 @@ interface HeroSectionProps {
export default function HeroSection({ export default function HeroSection({
title = "Web-Developer", title = "Web-Developer",
description = "Creating responsive, cross-browser compatible web applications with Angular, React, and modern frontend technologies", description = "Creating responsive, cross-browser compatible web applications with Angular, React, and modern web technologies",
primaryButtonText = "View my work", primaryButtonText = "View my work",
secondaryButtonText = "Download Resume", secondaryButtonText = "Download Resume",
statItems = [ statItems = [

View File

@ -0,0 +1,105 @@
import { Github, ExternalLink } from 'lucide-react';
import { personalConfig } from '../../config/personal';
import type { Project } from '../../data/Project';
interface ProjectsSectionProps {
title?: string;
subtitle?: string;
projects?: Project[];
}
export default function ProjectsSection({
title = "Featured Projects",
subtitle = "A showcase of my recent work and personal projects",
projects = [
{
id: 1,
title: "Portfolio Website",
description: "A personal portfolio website to showcase my skills, projects, and experience.",
image: "",
technologies: ["React", "TypeScript", "SCSS", "Vercel", "Github Copilot"],
github: personalConfig.projects.portfolio,
live: ""
},
{
id: 2,
title: "ErgoVR",
description: "A virtual reality application for analysis of motion sickness in VR environments.",
image: "",
technologies: ["Unity3D", "C#", "Oculus SDK"],
github: personalConfig.projects.ergoVR
}
]
}: ProjectsSectionProps) {
return (
<section id="projects" className="projects-section">
<div className="projects-section__container">
{/* Section Header */}
<div className="projects-section__header">
<h2 className="projects-section__title">
{title}
</h2>
<p className="projects-section__subtitle">
{subtitle}
</p>
</div>
{/* Projects Grid */}
<div className="projects-section__grid">
{projects.map((project) => (
<div key={project.id} className="projects-section__card">
<div className="projects-section__image-container">
<img
src={project.image || "/api/placeholder/400/200"}
alt={project.title}
className="projects-section__image"
/>
<div className="projects-section__overlay">
<div className="projects-section__actions">
{project.github && (
<a
href={project.github}
target="_blank"
rel="noopener noreferrer"
className="projects-section__action-button projects-section__action-button--secondary"
>
<Github className="projects-section__action-icon" />
Code
</a>
)}
{project.live && (
<a
href={project.live}
target="_blank"
rel="noopener noreferrer"
className="projects-section__action-button projects-section__action-button--primary"
>
<ExternalLink className="projects-section__action-icon" />
Live
</a>
)}
</div>
</div>
</div>
<div className="projects-section__content">
<div className="projects-section__header-content">
<h3 className="projects-section__card-title">{project.title}</h3>
<p className="projects-section__card-description">{project.description}</p>
</div>
<div className="projects-section__technologies">
{project.technologies.map((tech) => (
<span key={tech} className="projects-section__tech-badge">
{tech}
</span>
))}
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
}

View File

@ -0,0 +1,144 @@
import React from 'react';
import type { Skill } from '../../data/Skill';
interface SkillCategory {
title: string;
skills: Skill[];
}
interface SkillsSectionProps {
title?: string;
subtitle?: string;
skillCategories?: SkillCategory[];
}
// Helper function to calculate skill level based on value
const calculateSkillLevel = (value: number): string => {
if (value >= 90) return "Expert";
if (value >= 75) return "Advanced";
if (value >= 50) return "Intermediate";
return "Beginner";
};
// Helper function to get color based on array position
const getColorByPosition = (index: number): string => {
const colors = ["primary", "secondary", "tertiary", "quaternary", "quinary", "senary"];
return colors[index % colors.length];
};
export default function SkillsSection({
title = "Skills & Technologies",
subtitle = "Technologies I work with to build amazing web experiences",
skillCategories = [
{
title: "Web Frameworks",
skills: [
{ skill: "Angular", value: 90 },
{ skill: "React", value: 70 },
{ skill: "Next.js", value: 70 },
{ skill: "TypeScript", value: 95 }
]
},
{
title: "Styling & Design",
skills: [
{ skill: "SCSS/Sass", value: 95 },
{ skill: "CSS3", value: 90 },
{ skill: "Accessibility (a11y) Standards", value: 45 },
{ skill: "Bootstrap", value: 65 }
]
},
{
title: "Backend Development",
skills: [
{ skill: "Node.js", value: 65 },
{ skill: "Express.js", value: 25 },
{ skill: "REST APIs", value: 70 },
{ skill: "MongoDB", value: 50 }
]
},
{
title: "Development Tools",
skills: [
{ skill: "Git & GitHub", value: 90 },
{ skill: "Visual Studio Code", value: 75 },
{ skill: "Vite", value: 80 },
{ skill: "NPM", value: 85 }
]
},
{
title: "Testing & Quality",
skills: [
{ skill: "Cypress", value: 85 },
{ skill: "Jasmine/Karma", value: 75 },
{ skill: "ESLint", value: 90 },
{ skill: "Prettier", value: 95 }
]
},
{
title: "AI-Tools",
skills: [
{ skill: "GitHub Copilot", value: 85 },
{ skill: "Prompt Engineering", value: 45 },
{ skill: "Prototyping / MVP-Building with AI", value: 45 }
]
}
]
}: SkillsSectionProps) {
return (
<section id="skills" className="skills-section">
<div className="skills-section__container">
<div className="skills-section__header">
<h2 className="skills-section__title">
{title}
</h2>
<p className="skills-section__subtitle">
{subtitle}
</p>
</div>
<div className="skills-section__grid">
{skillCategories.map((category, categoryIndex) => (
<div key={categoryIndex} className="skills-section__category">
<h3 className="skills-section__category-title">
{category.title}
</h3>
<div className="skills-section__skills">
{category.skills.map((skillItem, skillIndex) => {
// Use provided level or calculate from value
const displayLevel = skillItem.level || calculateSkillLevel(skillItem.value);
// Use provided color or get color based on position in array
const colorClass = skillItem.color || getColorByPosition(skillIndex);
return (
<div key={skillIndex} className="skills-section__skill">
<div className="skills-section__skill-header">
<span className="skills-section__skill-name">
{skillItem.skill}
</span>
<div className="skills-section__skill-info">
<span className="skills-section__skill-level">
{displayLevel}
</span>
<span className="skills-section__skill-percentage">
{skillItem.value}%
</span>
</div>
</div>
<div className="skills-section__progress">
<div
className={`skills-section__progress-bar skills-section__progress-bar--${colorClass}`}
style={{ width: `${skillItem.value}%` }}
></div>
</div>
</div>
);
})}
</div>
</div>
))}
</div>
</div>
</section>
);
}

49
src/config/personal.ts Normal file
View File

@ -0,0 +1,49 @@
export const personalConfig = {
// Basic Information
name: "Sascha Bach",
title: "Freelance Software Developer",
// Contact Information
email: {
user: "freelancer",
domain: "sascha-bach.de",
full: "freelancer@sascha-bach.de"
},
// Social Links
social: {
github: {
url: "https://github.com/LuciusShadow",
username: "LuciusShadow"
},
linkedin: {
url: "https://www.linkedin.com/in/saschabach/",
username: "saschabach"
}
},
// Project Repository
projects: {
portfolio: "https://github.com/LuciusShadow/portfolio-page",
ergoVR: "https://github.com/LuciusShadow/ErgoVR"
},
// Professional Details
location: "Germany",
timezone: "CET/CEST",
// Branding
brand: {
tagline: "Building digital solutions with passion and precision",
description: "Freelance software developer specializing in modern web technologies and user experience."
}
} as const;
// Helper functions
export const getObfuscatedEmail = () => {
return personalConfig.email.full.replace('@', ' [at] ').replace('.', ' [dot] ');
};
export const createEmailLink = () => {
return `mailto:${personalConfig.email.user}@${personalConfig.email.domain}`;
};

View File

@ -1,8 +0,0 @@
import type { LucideIcon } from 'lucide-react';
export interface ServiceCard {
icon: LucideIcon;
title: string;
description: string;
colorClass: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary' | 'senary';
}

View File

@ -5,6 +5,6 @@ export interface Project {
description: string; description: string;
image: string; image: string;
technologies: string[]; technologies: string[];
github: string; github?: string;
live: string; live?: string;
} }

6
src/data/Skill.ts Normal file
View File

@ -0,0 +1,6 @@
export interface Skill {
skill: string;
level?: string; // Make level optional
value: number;
color?: string;
}

View File

@ -1,6 +0,0 @@
export interface Skill {
skill: string;
level: string;
value: number;
color: string;
}

View File

@ -1,11 +1,13 @@
@use 'themes' as t; @use 'themes/index' as t;
@use 'variables'; @use 'variables';
@use 'mixins'; @use 'mixins';
@use 'globals'; @use 'globals';
@use 'topbar';
@use 'hero-section'; // Layout components (topbar, footer, etc.)
@use 'about-section'; @use 'layout';
@use 'services-section';
// All sections imported through index
@use 'sections';
// Import Geist font from Google Fonts or local files // Import Geist font from Google Fonts or local files
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Geist:wght@100;200;300;400;500;600;700;800;900&display=swap');

View File

@ -0,0 +1,3 @@
// Layout component imports - for structural components
@forward 'topbar';
@forward 'footer';

View File

@ -0,0 +1,71 @@
@use '../mixins';
@use '../variables';
.footer {
background-color: var(--color-background-muted);
margin-top: auto; // Push footer to bottom if using flexbox layout
&__container {
margin: 0 auto;
padding: 0 1rem;
}
&__separator {
height: 1px;
background-color: var(--color-border);
margin-bottom: 2rem;
}
&__content {
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
&__copyright {
color: var(--color-text-muted);
font-size: 0.875rem;
text-align: center;
}
&__social {
display: flex;
gap: 1rem;
}
&__social-button {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
background: transparent;
border: none;
border-radius: 0.375rem;
color: var(--color-text-muted);
cursor: pointer;
transition: all 0.2s ease-in-out;
&:hover {
background-color: var(--color-background-hover);
color: var(--color-text);
transform: translateY(-1px);
}
&:focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
&:active {
transform: translateY(0);
}
}
&__social-icon {
width: 1rem;
height: 1rem;
}
}

View File

@ -1,4 +1,4 @@
@use 'globals'; @use '../globals';
.navbar { .navbar {
@include globals.flex-center(); @include globals.flex-center();
@ -106,21 +106,3 @@
display: none; display: none;
} }
} }
.theme-toggle {
@extend %button-reset;
display: flex;
align-items: center; // Centers vertically
justify-content: center; // Centers horizontally
font-size: 1rem;
transition: transform 0.2s ease;
width: 20px;
&:hover {
transform: scale(1.2);
}
}
.toggle-theme {
width: 10px;
}

View File

@ -0,0 +1,8 @@
// Section imports - organized and easy to manage
@forward 'hero-section';
@forward 'about-section';
@forward 'services-section';
@forward 'skills-section';
@forward 'certifications-section';
@forward 'projects-section';
@forward 'contact-section';

View File

@ -1,4 +1,4 @@
@use 'globals'; @use '../globals';
.about-section { .about-section {
background: var(--about-background); background: var(--about-background);

View File

@ -0,0 +1,158 @@
@use '../globals';
.certifications-section {
background: var(--certifications-background);
&__container {
max-width: 80rem;
margin: 0 auto;
padding: 0 1rem;
@include globals.desktop-only {
padding: 0 1.5rem;
}
}
&__header {
text-align: center;
margin-bottom: 4rem;
}
&__title {
font-size: 1.875rem;
font-weight: bold;
margin-bottom: 1rem;
background: var(--gradient-certifications-title);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
-webkit-text-fill-color: transparent;
@include globals.desktop-only {
font-size: 2.25rem;
}
}
&__subtitle {
font-size: 1.25rem;
color: var(--color-text-muted);
max-width: 48rem;
margin: 0 auto;
}
&__grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 2rem;
@include globals.mobile-only {
grid-template-columns: repeat(2, 1fr);
}
@include globals.desktop-only {
grid-template-columns: repeat(4, 1fr);
}
}
&__card {
text-align: center;
border: none;
border-radius: 1rem;
box-shadow: var(--certifications-card-shadow);
background: var(--certifications-card-background);
padding: 2rem 1.5rem;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--certifications-card-overlay);
opacity: 0;
transition: opacity 0.3s ease;
pointer-events: none;
}
&:hover {
transform: translateY(-0.25rem);
box-shadow: var(--certifications-card-shadow-hover);
&::before {
opacity: 1;
}
}
}
&__card-header {
margin-bottom: 1.5rem;
position: relative;
z-index: 1;
}
&__card-icon {
width: 4rem;
height: 4rem;
margin: 0 auto 1rem;
color: var(--color-certifications-primary);
display: block;
}
&__card-icon-image {
height: 4rem;
width: 4rem;
object-fit: contain;
margin: 0 auto 1rem;
display: block;
}
&__card-title {
font-size: 1.125rem;
font-weight: 600;
color: var(--color-text);
margin-bottom: 0.5rem;
line-height: 1.4;
}
&__card-issuer {
color: var(--color-text-muted);
font-size: 0.875rem;
}
&__card-content {
position: relative;
z-index: 1;
}
&__card-badge {
display: inline-block;
background: var(--certifications-badge-background);
color: var(--color-certifications-badge-text);
padding: 0.5rem 1rem;
border-radius: 9999px;
font-size: 0.875rem;
font-weight: 500;
border: 1px solid var(--certifications-badge-border);
}
// Responsive adjustments
@include globals.mobile-only {
&__card {
padding: 1.5rem 1rem;
}
&__card-icon,
&__card-icon-image {
width: 3rem;
height: 3rem;
}
&__card-title {
font-size: 1rem;
}
}
}

View File

@ -0,0 +1,279 @@
@use '../globals';
.contact-section {
background: var(--contact-background);
&__container {
max-width: 80rem;
margin: 0 auto;
padding: 0 1rem;
@include globals.desktop-only {
padding: 0 1.5rem;
}
}
&__header {
text-align: center;
margin-bottom: 4rem;
}
&__title {
font-size: 1.875rem;
font-weight: bold;
margin-bottom: 1rem;
background: var(--gradient-contact-title);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
-webkit-text-fill-color: transparent;
@include globals.desktop-only {
font-size: 2.25rem;
}
}
&__subtitle {
font-size: 1.25rem;
color: var(--color-text-muted);
max-width: 48rem;
margin: 0 auto;
}
&__grid {
display: grid;
grid-template-columns: 1fr;
gap: 3rem;
@include globals.desktop-only {
grid-template-columns: 1fr 1fr;
}
}
// Contact Info Section
&__info {
display: flex;
flex-direction: column;
gap: 2rem;
}
&__connect-title {
font-size: 1.5rem;
font-weight: 600;
color: var(--color-text);
margin-bottom: 1.5rem;
}
&__connect-description {
color: var(--color-text-muted);
line-height: 1.6;
margin-bottom: 2rem;
}
&__details {
display: flex;
flex-direction: column;
gap: 1rem;
}
&__detail-item {
display: flex;
align-items: center;
gap: 1rem;
}
&__detail-icon {
width: 1.25rem;
height: 1.25rem;
color: var(--color-contact-primary);
flex-shrink: 0;
}
&__detail-text {
color: var(--color-text);
font-size: 0.875rem;
}
&__social {
display: flex;
gap: 1rem;
margin-top: 1rem;
}
&__social-button {
display: flex;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
border: 1px solid var(--contact-social-border);
border-radius: 0.375rem;
background: var(--contact-social-bg);
color: var(--contact-social-text);
text-decoration: none;
transition: all 0.2s ease;
&:hover {
background: var(--contact-social-hover-bg);
border-color: var(--contact-social-hover-border);
transform: translateY(-1px);
}
}
&__social-icon {
width: 1rem;
height: 1rem;
}
// Contact Form Section
&__form-card {
background: var(--contact-form-bg);
border: 1px solid var(--contact-form-border);
border-radius: 1rem;
box-shadow: var(--contact-form-shadow);
overflow: hidden;
}
&__form-header {
padding: 1.5rem 1.5rem 0;
margin-bottom: 1.5rem;
}
&__form-title {
font-size: 1.25rem;
font-weight: 600;
color: var(--color-text);
margin-bottom: 0.5rem;
}
&__form-description {
color: var(--color-text-muted);
font-size: 0.875rem;
}
&__form {
padding: 0 1.5rem 1.5rem;
display: flex;
flex-direction: column;
gap: 1rem;
}
// Honeypot field - hidden from users but visible to bots
&__honeypot {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
opacity: 0;
}
&__honeypot-label,
&__honeypot-input {
position: absolute;
left: -9999px;
width: 1px;
height: 1px;
overflow: hidden;
opacity: 0;
}
&__form-row {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
@include globals.mobile-only {
grid-template-columns: 1fr 1fr;
}
}
&__form-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
&__form-label {
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text);
}
&__form-input,
&__form-textarea {
padding: 0.75rem;
border: 1px solid var(--contact-input-border);
border-radius: 0.375rem;
background: var(--contact-input-bg);
color: var(--color-text);
font-size: 0.875rem;
transition: all 0.2s ease;
&::placeholder {
color: var(--color-text-muted);
}
&:focus {
outline: none;
border-color: var(--color-contact-primary);
box-shadow: 0 0 0 3px var(--contact-input-focus-ring);
}
}
&__form-textarea {
resize: vertical;
min-height: 5rem;
font-family: inherit;
}
&__form-button {
background: var(--contact-button-bg);
color: var(--contact-button-text);
border: none;
border-radius: 0.375rem;
padding: 0.75rem 1.5rem;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
margin-top: 0.5rem;
&:hover:not(:disabled) {
background: var(--contact-button-hover-bg);
transform: translateY(-1px);
}
&:active:not(:disabled) {
transform: translateY(0);
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;
}
}
// Responsive adjustments
@include globals.mobile-only {
&__grid {
gap: 2rem;
}
&__form-card {
border-radius: 0.75rem;
}
&__form-header,
&__form {
padding-left: 1rem;
padding-right: 1rem;
}
&__social {
justify-content: center;
margin-top: 1.5rem;
}
}
}

View File

@ -1,6 +1,6 @@
@use 'globals'; @use '../globals';
@use 'variables' as *; @use '../variables' as *;
@use 'mixins' as *; @use '../mixins' as *;
// Hero-specific button extensions // Hero-specific button extensions
%hero-button-base { %hero-button-base {

View File

@ -0,0 +1,211 @@
@use '../globals';
.projects-section {
background: var(--projects-background);
&__container {
max-width: 80rem;
margin: 0 auto;
padding: 0 1rem;
@include globals.desktop-only {
padding: 0 1.5rem;
}
}
&__header {
text-align: center;
margin-bottom: 4rem;
}
&__title {
font-size: 1.875rem;
font-weight: bold;
margin-bottom: 1rem;
background: var(--gradient-projects-title);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
-webkit-text-fill-color: transparent;
@include globals.desktop-only {
font-size: 2.25rem;
}
}
&__subtitle {
font-size: 1.25rem;
color: var(--color-text-muted);
max-width: 48rem;
margin: 0 auto;
}
&__grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
gap: 2rem;
@include globals.mobile-only {
grid-template-columns: repeat(2, 1fr);
}
@include globals.desktop-only {
grid-template-columns: repeat(3, 1fr);
}
}
&__card {
background: var(--projects-card-background);
border-radius: 1rem;
box-shadow: var(--projects-card-shadow);
overflow: hidden;
transition: all 0.3s ease;
border: 1px solid var(--projects-card-border);
&:hover {
transform: translateY(-0.25rem);
box-shadow: var(--projects-card-shadow-hover);
.projects-section__image {
transform: scale(1.05);
}
.projects-section__overlay {
opacity: 1;
}
}
}
&__image-container {
position: relative;
overflow: hidden;
height: 12rem;
}
&__image {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s ease;
}
&__overlay {
position: absolute;
inset: 0;
background: var(--projects-overlay-background);
opacity: 0;
transition: opacity 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
}
&__actions {
display: flex;
gap: 1rem;
}
&__action-button {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
border: 1px solid transparent;
&--primary {
background: var(--projects-button-primary-bg);
color: var(--projects-button-primary-text);
border-color: var(--projects-button-primary-border);
&:hover {
background: var(--projects-button-primary-hover-bg);
transform: translateY(-1px);
}
}
&--secondary {
background: var(--projects-button-secondary-bg);
color: var(--projects-button-secondary-text);
border-color: var(--projects-button-secondary-border);
&:hover {
background: var(--projects-button-secondary-hover-bg);
transform: translateY(-1px);
}
}
}
&__action-icon {
width: 1rem;
height: 1rem;
}
&__content {
padding: 1.5rem;
}
&__header-content {
margin-bottom: 1.5rem;
}
&__card-title {
font-size: 1.125rem;
font-weight: 600;
color: var(--color-text);
margin-bottom: 0.5rem;
line-height: 1.4;
}
&__card-description {
color: var(--color-text-muted);
font-size: 0.875rem;
line-height: 1.5;
}
&__technologies {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
&__tech-badge {
display: inline-block;
background: var(--projects-tech-badge-bg);
color: var(--projects-tech-badge-text);
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
border: 1px solid var(--projects-tech-badge-border);
}
// Responsive adjustments
@include globals.mobile-only {
&__card {
border-radius: 0.75rem;
}
&__content {
padding: 1rem;
}
&__image-container {
height: 10rem;
}
&__actions {
flex-direction: column;
gap: 0.75rem;
}
&__action-button {
justify-content: center;
padding: 0.75rem 1rem;
}
}
}

View File

@ -1,5 +1,5 @@
@use 'globals'; @use '../globals';
@use 'variables' as *; @use '../variables' as *;
.services-section { .services-section {
min-height: 100vh; min-height: 100vh;

View File

@ -0,0 +1,396 @@
@use '../globals';
@use '../variables' as *;
.skills-section {
padding: 5rem 0;
background: var(--skills-background);
position: relative;
// Add decorative background elements
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--skills-background-pattern);
opacity: 0.03;
pointer-events: none;
}
&__container {
max-width: 80rem;
margin: 0 auto;
padding: 0 1rem;
position: relative;
z-index: 1;
@include globals.desktop-only {
padding: 0 1.5rem;
}
}
&__header {
text-align: center;
margin-bottom: $skills-header-margin;
@include globals.mobile-only {
margin-bottom: 2rem;
}
}
&__title {
font-size: 1.875rem;
font-weight: bold;
margin-bottom: 1rem;
background: var(--gradient-skills-title);
background-clip: text;
-webkit-background-clip: text;
color: transparent;
-webkit-text-fill-color: transparent;
@include globals.desktop-only {
font-size: 2.25rem;
}
@include globals.mobile-only {
font-size: 1.5rem;
}
}
&__subtitle {
font-size: 1.25rem;
color: var(--color-text-muted);
max-width: 40rem;
margin: 0 auto;
@include globals.mobile-only {
font-size: 1rem;
}
}
&__grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: $skills-category-gap;
@include globals.mobile-only {
grid-template-columns: 1fr;
gap: $skills-category-gap-mobile;
}
}
&__category {
background: var(--skills-category-bg);
border: 1px solid var(--skills-category-border);
border-radius: 1rem;
padding: $skills-category-padding;
backdrop-filter: blur(10px);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
// Add subtle gradient overlay for depth
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--skills-category-gradient-overlay);
opacity: 0.8;
pointer-events: none;
z-index: 1;
}
// Add decorative corner accent
&::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 60px;
height: 60px;
background: var(--skills-category-accent);
clip-path: polygon(100% 0, 0 0, 100% 100%);
opacity: 0.1;
z-index: 1;
}
&:hover {
transform: translateY(-8px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
&::before {
opacity: 0.9;
}
&::after {
opacity: 0.2;
}
}
@include globals.mobile-only {
padding: $skills-category-padding-mobile;
}
// Card-specific color schemes matching your page theme
&:nth-child(1) {
// Web Frameworks - Blue theme (matching hero primary)
background: var(--skills-category-bg-primary);
border-color: var(--skills-category-border-primary);
&::before {
background: var(--skills-gradient-primary);
}
&::after {
background: var(--skills-accent-primary);
}
}
&:nth-child(2) {
// Styling & Design - Green theme (matching about section)
background: var(--skills-category-bg-secondary);
border-color: var(--skills-category-border-secondary);
&::before {
background: var(--skills-gradient-secondary);
}
&::after {
background: var(--skills-accent-secondary);
}
}
&:nth-child(3) {
// Backend Development - Purple theme (matching hero secondary)
background: var(--skills-category-bg-tertiary);
border-color: var(--skills-category-border-tertiary);
&::before {
background: var(--skills-gradient-tertiary);
}
&::after {
background: var(--skills-accent-tertiary);
}
}
&:nth-child(4) {
// Development Tools - Teal theme (complementary)
background: var(--skills-category-bg-quaternary);
border-color: var(--skills-category-border-quaternary);
&::before {
background: var(--skills-gradient-quaternary);
}
&::after {
background: var(--skills-accent-quaternary);
}
}
&:nth-child(5) {
// Testing & Quality - Orange theme (warm accent)
background: var(--skills-category-bg-quinary);
border-color: var(--skills-category-border-quinary);
&::before {
background: var(--skills-gradient-quinary);
}
&::after {
background: var(--skills-accent-quinary);
}
}
&:nth-child(6) {
// AI-Tools - Indigo theme (tech/AI vibe)
background: var(--skills-category-bg-senary);
border-color: var(--skills-category-border-senary);
&::before {
background: var(--skills-gradient-senary);
}
&::after {
background: var(--skills-accent-senary);
}
}
}
&__category-title {
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 1.5rem;
color: var(--skills-category-title-color);
text-align: center;
position: relative;
z-index: 2;
@include globals.mobile-only {
font-size: 1.25rem;
margin-bottom: 1rem;
}
}
&__skills {
display: flex;
flex-direction: column;
gap: $skills-skill-gap;
position: relative;
z-index: 2;
@include globals.mobile-only {
gap: $skills-skill-gap-mobile;
}
}
&__skill {
// Individual skill container
}
&__skill-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
gap: 1rem;
@include globals.mobile-only {
flex-direction: column;
align-items: flex-start;
gap: 0.25rem;
}
}
&__skill-name {
font-size: 1rem;
font-weight: 600;
color: var(--skills-skill-name-color);
@include globals.mobile-only {
font-size: 0.9rem;
}
}
&__skill-info {
display: flex;
align-items: center;
gap: 0.75rem;
@include globals.mobile-only {
gap: 0.5rem;
}
}
&__skill-level {
font-size: 0.8rem;
font-weight: 500;
color: var(--skills-skill-level-color);
background: var(--skills-progress-bg);
padding: 0.25rem 0.5rem;
border-radius: 0.375rem;
backdrop-filter: blur(4px);
@include globals.mobile-only {
font-size: 0.75rem;
padding: 0.2rem 0.4rem;
}
}
&__skill-percentage {
font-size: 0.875rem;
font-weight: 600;
color: var(--skills-skill-percentage-color);
@include globals.mobile-only {
font-size: 0.8rem;
}
}
&__progress {
height: $skills-progress-height;
background: var(--skills-progress-bg);
border-radius: $skills-progress-radius;
overflow: hidden;
position: relative;
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
}
&__progress-bar {
height: 100%;
border-radius: $skills-progress-radius;
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
&::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
transform: translateX(-100%);
animation: shimmer 2s infinite;
}
// Semantic hierarchy classes with enhanced gradients
&--primary {
background: var(--skills-progress-primary);
box-shadow: 0 0 8px rgba(59, 130, 246, 0.3);
}
&--secondary {
background: var(--skills-progress-secondary);
box-shadow: 0 0 8px rgba(16, 185, 129, 0.3);
}
&--tertiary {
background: var(--skills-progress-tertiary);
box-shadow: 0 0 8px rgba(139, 92, 246, 0.3);
}
&--quaternary {
background: var(--skills-progress-quaternary);
box-shadow: 0 0 8px rgba(6, 182, 212, 0.3);
}
&--quinary {
background: var(--skills-progress-quinary);
box-shadow: 0 0 8px rgba(245, 158, 11, 0.3);
}
&--senary {
background: var(--skills-progress-senary);
box-shadow: 0 0 8px rgba(239, 68, 68, 0.3);
}
}
}
// Enhanced shimmer animation
@keyframes shimmer {
0% {
transform: translateX(-100%);
opacity: 0;
}
50% {
opacity: 1;
}
100% {
transform: translateX(100%);
opacity: 0;
}
}
// Mobile responsiveness
@include globals.mobile-only {
.skills-section {
padding: 3rem 0;
}
}

View File

@ -1,322 +0,0 @@
@use 'sass:map';
@use 'variables' as *;
// Light Theme Colors
$light-theme: (
primary: #000000,
background: #ffffff,
text: #000000,
text-muted: #6b7280,
active-box-shadow: rgba(0, 0, 0, 0.1),
hover-box-shadow: rgba(0, 0, 0, 0.15),
hero-background: $gradient-hero-light,
gradient-primary: $gradient-primary,
gradient-text: $gradient-text,
// Stat colors using visual hierarchy
stat-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe),
stat-primary-value: #2563eb,
stat-primary-label: #1d4ed8,
stat-secondary-bg: linear-gradient(135deg, #dcfce7, #bbf7d0),
stat-secondary-value: #16a34a,
stat-secondary-label: #15803d,
stat-tertiary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4),
stat-tertiary-value: #0d9488,
stat-tertiary-label: #0f766e,
stat-quaternary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe),
stat-quaternary-value: #9333ea,
stat-quaternary-label: #7c3aed,
// About section colors
about-background:
linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdfa 100%),
gradient-about-title: linear-gradient(90deg, #059669, #0d9488),
about-greeting-color: #047857,
gradient-image-overlay:
linear-gradient(45deg, rgba(59, 130, 246, 0.2), rgba(147, 51, 234, 0.2)),
// Skill badge colors using visual hierarchy
skill-badge-primary-bg: #dbeafe,
skill-badge-primary-text: #1e40af,
skill-badge-secondary-bg: #dcfce7,
skill-badge-secondary-text: #166534,
skill-badge-tertiary-bg: #e9d5ff,
skill-badge-tertiary-text: #7c2d12,
skill-badge-quaternary-bg: #fed7aa,
skill-badge-quaternary-text: #9a3412,
// Feature card colors using visual hierarchy
feature-card-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe),
feature-card-secondary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe),
feature-card-tertiary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4),
feature-icon-primary: #2563eb,
feature-icon-secondary: #9333ea,
feature-icon-tertiary: #0d9488,
feature-title-primary: #1e40af,
feature-title-secondary: #7c3aed,
feature-title-tertiary: #0f766e,
feature-description-primary: #1d4ed8,
feature-description-secondary: #6d28d9,
feature-description-tertiary: #115e59,
// Services section colors - Tailwind inspired
services-background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 25%, #cbd5e1 70%, #94a3b8 100%),
gradient-services-title: linear-gradient(90deg, #0f172a, #1e293b, #334155),
// Service card colors using Tailwind color palette
service-card-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe), // blue-100 to blue-200
service-card-secondary-bg: linear-gradient(135deg, #dcfce7, #bbf7d0), // green-100 to green-200
service-card-tertiary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe), // violet-100 to violet-200
service-card-quaternary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4), // teal-100 to teal-200
service-card-quinary-bg: linear-gradient(135deg, #fed7aa, #fdba74), // orange-200 to orange-300
service-card-senary-bg: linear-gradient(135deg, #fecaca, #fca5a5), // red-200 to red-300
service-icon-primary: #2563eb, // blue-600
service-icon-secondary: #16a34a, // green-600
service-icon-tertiary: #7c3aed, // violet-600
service-icon-quaternary: #0d9488, // teal-600
service-icon-quinary: #ea580c, // orange-600
service-icon-senary: #dc2626, // red-600
service-title-primary: #1e40af, // blue-700
service-title-secondary: #166534, // green-700
service-title-tertiary: #6d28d9, // violet-700
service-title-quaternary: #0f766e, // teal-700
service-title-quinary: #c2410c, // orange-700
service-title-senary: #b91c1c, // red-700
service-description-primary: #1d4ed8, // blue-700
service-description-secondary: #15803d, // green-700
service-description-tertiary: #5b21b6, // violet-800
service-description-quaternary: #115e59, // teal-800
service-description-quinary: #9a3412, // orange-800
service-description-senary: #991b1b, // red-800
// Shadow variables
box-shadow-sm: #{$shadow-sm},
box-shadow-md: #{$shadow-md},
box-shadow-lg: #{$shadow-lg},
);
// Dark Theme Colors
$dark-theme: (
primary: #9333ea,
background: #1f2937,
text: #f9fafb,
text-muted: #9ca3af,
active-box-shadow: rgba(255, 255, 255, 0.1),
hover-box-shadow: rgba(255, 255, 255, 0.15),
hero-background: $gradient-hero-dark,
gradient-primary: $gradient-primary,
gradient-text: $gradient-text,
// Stat colors using visual hierarchy
stat-primary-bg:
linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(30, 64, 175, 0.3)),
stat-primary-value: #2563eb,
stat-primary-label: #93c5fd,
stat-secondary-bg:
linear-gradient(135deg, rgba(20, 83, 45, 0.3), rgba(22, 101, 52, 0.3)),
stat-secondary-value: #16a34a,
stat-secondary-label: #86efac,
stat-tertiary-bg:
linear-gradient(135deg, rgba(19, 78, 74, 0.3), rgba(17, 94, 89, 0.3)),
stat-tertiary-value: #0d9488,
stat-tertiary-label: #5eead4,
stat-quaternary-bg:
linear-gradient(135deg, rgba(88, 28, 135, 0.3), rgba(107, 33, 168, 0.3)),
stat-quaternary-value: #9333ea,
stat-quaternary-label: #c4b5fd,
// About section colors
about-background:
linear-gradient(
135deg,
rgba(20, 83, 45, 0.2) 0%,
rgba(6, 78, 59, 0.2) 100%
),
gradient-about-title: linear-gradient(90deg, #10b981, #14b8a6),
about-greeting-color: #34d399,
gradient-image-overlay:
linear-gradient(45deg, rgba(59, 130, 246, 0.2), rgba(147, 51, 234, 0.2)),
// Skill badge colors using visual hierarchy
skill-badge-primary-bg: rgba(30, 58, 138, 0.3),
skill-badge-primary-text: #93c5fd,
skill-badge-secondary-bg: rgba(20, 83, 45, 0.3),
skill-badge-secondary-text: #86efac,
skill-badge-tertiary-bg: rgba(88, 28, 135, 0.3),
skill-badge-tertiary-text: #c4b5fd,
skill-badge-quaternary-bg: rgba(154, 52, 18, 0.3),
skill-badge-quaternary-text: #fdba74,
// Feature card colors using visual hierarchy
feature-card-primary-bg:
linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(30, 64, 175, 0.3)),
feature-card-secondary-bg:
linear-gradient(135deg, rgba(88, 28, 135, 0.3), rgba(107, 33, 168, 0.3)),
feature-card-tertiary-bg:
linear-gradient(135deg, rgba(19, 78, 74, 0.3), rgba(17, 94, 89, 0.3)),
feature-icon-primary: #3b82f6,
feature-icon-secondary: #a855f7,
feature-icon-tertiary: #14b8a6,
feature-title-primary: #93c5fd,
feature-title-secondary: #c4b5fd,
feature-title-tertiary: #5eead4,
feature-description-primary: #dbeafe,
feature-description-secondary: #e9d5ff,
feature-description-tertiary: #ccfbf1,
// Services section colors - Dark mode with Tailwind palette
services-background: linear-gradient(135deg, #0f172a 0%, #1e293b 25%, #334155 70%, #475569 100%),
gradient-services-title: linear-gradient(90deg, #f1f5f9, #e2e8f0, #cbd5e1),
// Service card colors for dark theme - using Tailwind dark colors
service-card-primary-bg: linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(37, 99, 235, 0.2)), // blue-800/30 to blue-600/20
service-card-secondary-bg: linear-gradient(135deg, rgba(22, 101, 52, 0.3), rgba(34, 197, 94, 0.2)), // green-800/30 to green-500/20
service-card-tertiary-bg: linear-gradient(135deg, rgba(91, 33, 182, 0.3), rgba(124, 58, 237, 0.2)), // violet-800/30 to violet-600/20
service-card-quaternary-bg: linear-gradient(135deg, rgba(17, 94, 89, 0.3), rgba(20, 184, 166, 0.2)), // teal-800/30 to teal-500/20
service-card-quinary-bg: linear-gradient(135deg, rgba(154, 52, 18, 0.3), rgba(249, 115, 22, 0.2)), // orange-800/30 to orange-500/20
service-card-senary-bg: linear-gradient(135deg, rgba(153, 27, 27, 0.3), rgba(239, 68, 68, 0.2)), // red-800/30 to red-500/20
service-icon-primary: #60a5fa, // blue-400
service-icon-secondary: #4ade80, // green-400
service-icon-tertiary: #a78bfa, // violet-400
service-icon-quaternary: #2dd4bf, // teal-400
service-icon-quinary: #fb923c, // orange-400
service-icon-senary: #f87171, // red-400
service-title-primary: #93c5fd, // blue-300
service-title-secondary: #86efac, // green-300
service-title-tertiary: #c4b5fd, // violet-300
service-title-quaternary: #5eead4, // teal-300
service-title-quinary: #fdba74, // orange-300
service-title-senary: #fca5a5, // red-300
service-description-primary: #bfdbfe, // blue-200
service-description-secondary: #bbf7d0, // green-200
service-description-tertiary: #ddd6fe, // violet-200
service-description-quaternary: #99f6e4, // teal-200
service-description-quinary: #fed7aa, // orange-200
service-description-senary: #fecaca, // red-200
// Shadow variables
box-shadow-sm: #{$shadow-sm},
box-shadow-md: #{$shadow-md},
box-shadow-lg: #{$shadow-lg},
);
// Mixin: SCSS-Map CSS-Variables
@mixin theme-vars($theme) {
--color-primary: #{map.get($theme, primary)};
--color-background: #{map.get($theme, background)};
--color-text: #{map.get($theme, text)};
--color-text-muted: #{map.get($theme, text-muted)};
--box-shadow-hover: #{map.get($theme, hover-box-shadow)};
--box-shadow-active: #{map.get($theme, active-box-shadow)};
--hero-background: #{map.get($theme, hero-background)};
--gradient-primary: #{map.get($theme, gradient-primary)};
--gradient-text: #{map.get($theme, gradient-text)};
// Stat variables using semantic naming
--stat-primary-bg: #{map.get($theme, stat-primary-bg)};
--stat-primary-value: #{map.get($theme, stat-primary-value)};
--stat-primary-label: #{map.get($theme, stat-primary-label)};
--stat-secondary-bg: #{map.get($theme, stat-secondary-bg)};
--stat-secondary-value: #{map.get($theme, stat-secondary-value)};
--stat-secondary-label: #{map.get($theme, stat-secondary-label)};
--stat-tertiary-bg: #{map.get($theme, stat-tertiary-bg)};
--stat-tertiary-value: #{map.get($theme, stat-tertiary-value)};
--stat-tertiary-label: #{map.get($theme, stat-tertiary-label)};
--stat-quaternary-bg: #{map.get($theme, stat-quaternary-bg)};
--stat-quaternary-value: #{map.get($theme, stat-quaternary-value)};
--stat-quaternary-label: #{map.get($theme, stat-quaternary-label)};
// About section variables
--about-background: #{map.get($theme, about-background)};
--gradient-about-title: #{map.get($theme, gradient-about-title)};
--about-greeting-color: #{map.get($theme, about-greeting-color)};
--gradient-image-overlay: #{map.get($theme, gradient-image-overlay)};
// Skill badge variables using semantic naming
--skill-badge-primary-bg: #{map.get($theme, skill-badge-primary-bg)};
--skill-badge-primary-text: #{map.get($theme, skill-badge-primary-text)};
--skill-badge-secondary-bg: #{map.get($theme, skill-badge-secondary-bg)};
--skill-badge-secondary-text: #{map.get($theme, skill-badge-secondary-text)};
--skill-badge-tertiary-bg: #{map.get($theme, skill-badge-tertiary-bg)};
--skill-badge-tertiary-text: #{map.get($theme, skill-badge-tertiary-text)};
--skill-badge-quaternary-bg: #{map.get($theme, skill-badge-quaternary-bg)};
--skill-badge-quaternary-text: #{map.get($theme, skill-badge-quaternary-text)};
// Feature card variables using semantic naming
--feature-card-primary-bg: #{map.get($theme, feature-card-primary-bg)};
--feature-card-secondary-bg: #{map.get($theme, feature-card-secondary-bg)};
--feature-card-tertiary-bg: #{map.get($theme, feature-card-tertiary-bg)};
--feature-icon-primary: #{map.get($theme, feature-icon-primary)};
--feature-icon-secondary: #{map.get($theme, feature-icon-secondary)};
--feature-icon-tertiary: #{map.get($theme, feature-icon-tertiary)};
--feature-title-primary: #{map.get($theme, feature-title-primary)};
--feature-title-secondary: #{map.get($theme, feature-title-secondary)};
--feature-title-tertiary: #{map.get($theme, feature-title-tertiary)};
--feature-description-primary: #{map.get($theme, feature-description-primary)};
--feature-description-secondary: #{map.get(
$theme,
feature-description-secondary
)};
--feature-description-tertiary: #{map.get(
$theme,
feature-description-tertiary
)};
// Services section variables
--services-background: #{map.get($theme, services-background)};
--gradient-services-title: #{map.get($theme, gradient-services-title)};
// Service card variables
--service-card-primary-bg: #{map.get($theme, service-card-primary-bg)};
--service-card-secondary-bg: #{map.get($theme, service-card-secondary-bg)};
--service-card-tertiary-bg: #{map.get($theme, service-card-tertiary-bg)};
--service-card-quaternary-bg: #{map.get($theme, service-card-quaternary-bg)};
--service-card-quinary-bg: #{map.get($theme, service-card-quinary-bg)};
--service-card-senary-bg: #{map.get($theme, service-card-senary-bg)};
--service-icon-primary: #{map.get($theme, service-icon-primary)};
--service-icon-secondary: #{map.get($theme, service-icon-secondary)};
--service-icon-tertiary: #{map.get($theme, service-icon-tertiary)};
--service-icon-quaternary: #{map.get($theme, service-icon-quaternary)};
--service-icon-quinary: #{map.get($theme, service-icon-quinary)};
--service-icon-senary: #{map.get($theme, service-icon-senary)};
--service-title-primary: #{map.get($theme, service-title-primary)};
--service-title-secondary: #{map.get($theme, service-title-secondary)};
--service-title-tertiary: #{map.get($theme, service-title-tertiary)};
--service-title-quaternary: #{map.get($theme, service-title-quaternary)};
--service-title-quinary: #{map.get($theme, service-title-quinary)};
--service-title-senary: #{map.get($theme, service-title-senary)};
--service-description-primary: #{map.get($theme, service-description-primary)};
--service-description-secondary: #{map.get($theme, service-description-secondary)};
--service-description-tertiary: #{map.get($theme, service-description-tertiary)};
--service-description-quaternary: #{map.get($theme, service-description-quaternary)};
--service-description-quinary: #{map.get($theme, service-description-quinary)};
--service-description-senary: #{map.get($theme, service-description-senary)};
// Shadow variables
--box-shadow-sm: #{map.get($theme, box-shadow-sm)} var(--box-shadow-hover);
--box-shadow-md: #{map.get($theme, box-shadow-md)};
--box-shadow-lg: #{map.get($theme, box-shadow-lg)};
}

View File

@ -0,0 +1,67 @@
$about-light-theme: (
// About section colors
about-background: linear-gradient(135deg, #f0fdf4 0%, #ecfdf5 50%, #f0fdfa 100%),
gradient-about-title: linear-gradient(90deg, #059669, #0d9488),
about-greeting-color: #047857,
gradient-image-overlay: linear-gradient(45deg, rgba(59, 130, 246, 0.2), rgba(147, 51, 234, 0.2)),
// Skill badge colors using visual hierarchy
skill-badge-primary-bg: #dbeafe,
skill-badge-primary-text: #1e40af,
skill-badge-secondary-bg: #dcfce7,
skill-badge-secondary-text: #166534,
skill-badge-tertiary-bg: #e9d5ff,
skill-badge-tertiary-text: #7c2d12,
skill-badge-quaternary-bg: #fed7aa,
skill-badge-quaternary-text: #9a3412,
// Feature card colors using visual hierarchy
feature-card-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe),
feature-card-secondary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe),
feature-card-tertiary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4),
feature-icon-primary: #2563eb,
feature-icon-secondary: #9333ea,
feature-icon-tertiary: #0d9488,
feature-title-primary: #1e40af,
feature-title-secondary: #7c3aed,
feature-title-tertiary: #0f766e,
feature-description-primary: #1d4ed8,
feature-description-secondary: #6d28d9,
feature-description-tertiary: #115e59,
);
$about-dark-theme: (
// About section colors
about-background: linear-gradient(135deg, rgba(20, 83, 45, 0.2) 0%, rgba(6, 78, 59, 0.2) 100%),
gradient-about-title: linear-gradient(90deg, #10b981, #14b8a6),
about-greeting-color: #34d399,
gradient-image-overlay: linear-gradient(45deg, rgba(59, 130, 246, 0.2), rgba(147, 51, 234, 0.2)),
// Skill badge colors using visual hierarchy
skill-badge-primary-bg: rgba(30, 58, 138, 0.3),
skill-badge-primary-text: #93c5fd,
skill-badge-secondary-bg: rgba(20, 83, 45, 0.3),
skill-badge-secondary-text: #86efac,
skill-badge-tertiary-bg: rgba(88, 28, 135, 0.3),
skill-badge-tertiary-text: #c4b5fd,
skill-badge-quaternary-bg: rgba(154, 52, 18, 0.3),
skill-badge-quaternary-text: #fdba74,
// Feature card colors using visual hierarchy
feature-card-primary-bg: linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(30, 64, 175, 0.3)),
feature-card-secondary-bg: linear-gradient(135deg, rgba(88, 28, 135, 0.3), rgba(107, 33, 168, 0.3)),
feature-card-tertiary-bg: linear-gradient(135deg, rgba(19, 78, 74, 0.3), rgba(17, 94, 89, 0.3)),
feature-icon-primary: #3b82f6,
feature-icon-secondary: #a855f7,
feature-icon-tertiary: #14b8a6,
feature-title-primary: #93c5fd,
feature-title-secondary: #c4b5fd,
feature-title-tertiary: #5eead4,
feature-description-primary: #dbeafe,
feature-description-secondary: #e9d5ff,
feature-description-tertiary: #ccfbf1,
);

View File

@ -0,0 +1,35 @@
@use 'sass:map';
@use '../variables' as *;
// Base colors and variables that are used across sections
$base-light-theme: (
primary: #000000,
background: #ffffff,
text: #000000,
text-muted: #6b7280,
active-box-shadow: rgba(0, 0, 0, 0.1),
hover-box-shadow: rgba(0, 0, 0, 0.15),
gradient-primary: $gradient-primary,
gradient-text: $gradient-text,
// Shadow variables
box-shadow-sm: #{$shadow-sm},
box-shadow-md: #{$shadow-md},
box-shadow-lg: #{$shadow-lg},
);
$base-dark-theme: (
primary: #9333ea,
background: #1f2937,
text: #f9fafb,
text-muted: #9ca3af,
active-box-shadow: rgba(255, 255, 255, 0.1),
hover-box-shadow: rgba(255, 255, 255, 0.15),
gradient-primary: $gradient-primary,
gradient-text: $gradient-text,
// Shadow variables
box-shadow-sm: #{$shadow-sm},
box-shadow-md: #{$shadow-md},
box-shadow-lg: #{$shadow-lg},
);

View File

@ -0,0 +1,45 @@
// Certifications section theme definitions
$certifications-light-theme: (
// Certifications section background
'certifications-background': linear-gradient(135deg, #fdf2f8 0%, #fce7f3 100%),
// Certifications title gradient (purple to pink)
'gradient-certifications-title': linear-gradient(to right, #9333ea, #ec4899),
// Primary color for icons (purple)
'color-certifications-primary': #9333ea,
// Card styling
'certifications-card-background': linear-gradient(135deg, #ffffff 0%, #fafafa 100%),
'certifications-card-shadow': 0 10px 15px -3px rgba(0, 0, 0, 0.1),
'certifications-card-shadow-hover': 0 20px 25px -5px rgba(0, 0, 0, 0.1),
'certifications-card-overlay': linear-gradient(135deg, rgba(147, 51, 234, 0.02) 0%, rgba(236, 72, 153, 0.02) 100%),
// Badge styling (purple/pink theme)
'certifications-badge-background': linear-gradient(to right, #f3e8ff, #fce7f3),
'certifications-badge-border': rgba(147, 51, 234, 0.2),
'color-certifications-badge-text': #7e22ce,
);
$certifications-dark-theme: (
// Certifications section background (dark purple/pink gradient)
'certifications-background': linear-gradient(135deg, rgba(88, 28, 135, 0.2) 0%, rgba(157, 23, 77, 0.2) 100%),
// Certifications title gradient (brighter purple to pink for dark mode)
'gradient-certifications-title': linear-gradient(to right, #a855f7, #f472b6),
// Primary color for icons (lighter purple)
'color-certifications-primary': #a855f7,
// Card styling (dark theme)
'certifications-card-background': linear-gradient(135deg, #111827 0%, #1f2937 100%),
'certifications-card-shadow': 0 10px 15px -3px rgba(0, 0, 0, 0.3),
'certifications-card-shadow-hover': 0 20px 25px -5px rgba(0, 0, 0, 0.4),
'certifications-card-overlay': linear-gradient(135deg, rgba(168, 85, 247, 0.05) 0%, rgba(244, 114, 182, 0.05) 100%),
// Badge styling (dark theme with purple/pink)
'certifications-badge-background': linear-gradient(to right, rgba(88, 28, 135, 0.3), rgba(157, 23, 77, 0.3)),
'certifications-badge-border': rgba(168, 85, 247, 0.3),
'color-certifications-badge-text': #d8b4fe,
);

View File

@ -0,0 +1,66 @@
// Contact section theme definitions
$contact-light-theme: (
// Contact section background (light indigo/purple tones)
'contact-background': linear-gradient(135deg, #f0f9ff 0%, #faf5ff 100%),
// Contact title gradient (indigo to purple)
'gradient-contact-title': linear-gradient(to right, #4f46e5, #7c3aed),
// Primary color for icons (indigo)
'color-contact-primary': #4f46e5,
// Form styling
'contact-form-bg': linear-gradient(135deg, #ffffff 0%, #fefefe 100%),
'contact-form-border': rgba(79, 70, 229, 0.1),
'contact-form-shadow': 0 10px 15px -3px rgba(0, 0, 0, 0.1),
// Input styling
'contact-input-bg': #ffffff,
'contact-input-border': rgba(79, 70, 229, 0.2),
'contact-input-focus-ring': rgba(79, 70, 229, 0.1),
// Button styling
'contact-button-bg': linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%),
'contact-button-text': #ffffff,
'contact-button-hover-bg': linear-gradient(135deg, #4338ca 0%, #6d28d9 100%),
// Social button styling
'contact-social-bg': rgba(255, 255, 255, 0.8),
'contact-social-text': #4b5563,
'contact-social-border': rgba(79, 70, 229, 0.2),
'contact-social-hover-bg': #ffffff,
'contact-social-hover-border': rgba(79, 70, 229, 0.3),
);
$contact-dark-theme: (
// Contact section background (dark indigo/purple tones)
'contact-background': linear-gradient(135deg, rgba(67, 56, 202, 0.2) 0%, rgba(109, 40, 217, 0.2) 100%),
// Contact title gradient (brighter indigo to purple for dark mode)
'gradient-contact-title': linear-gradient(to right, #6366f1, #a855f7),
// Primary color for icons (lighter indigo)
'color-contact-primary': #6366f1,
// Form styling (dark theme)
'contact-form-bg': linear-gradient(135deg, #111827 0%, #1f2937 100%),
'contact-form-border': rgba(99, 102, 241, 0.2),
'contact-form-shadow': 0 10px 15px -3px rgba(0, 0, 0, 0.3),
// Input styling (dark theme)
'contact-input-bg': #1f2937,
'contact-input-border': rgba(99, 102, 241, 0.3),
'contact-input-focus-ring': rgba(99, 102, 241, 0.2),
// Button styling (dark theme)
'contact-button-bg': linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%),
'contact-button-text': #ffffff,
'contact-button-hover-bg': linear-gradient(135deg, #6366f1 0%, #a855f7 100%),
// Social button styling (dark theme)
'contact-social-bg': rgba(31, 41, 55, 0.8),
'contact-social-text': #e5e7eb,
'contact-social-border': rgba(99, 102, 241, 0.3),
'contact-social-hover-bg': #374151,
'contact-social-hover-border': rgba(99, 102, 241, 0.4),
);

View File

@ -0,0 +1,43 @@
@use '../variables' as *;
$hero-light-theme: (
hero-background: $gradient-hero-light,
// Stat colors using visual hierarchy
stat-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe),
stat-primary-value: #2563eb,
stat-primary-label: #1d4ed8,
stat-secondary-bg: linear-gradient(135deg, #dcfce7, #bbf7d0),
stat-secondary-value: #16a34a,
stat-secondary-label: #15803d,
stat-tertiary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4),
stat-tertiary-value: #0d9488,
stat-tertiary-label: #0f766e,
stat-quaternary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe),
stat-quaternary-value: #9333ea,
stat-quaternary-label: #7c3aed,
);
$hero-dark-theme: (
hero-background: $gradient-hero-dark,
// Stat colors using visual hierarchy
stat-primary-bg: linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(30, 64, 175, 0.3)),
stat-primary-value: #2563eb,
stat-primary-label: #93c5fd,
stat-secondary-bg: linear-gradient(135deg, rgba(20, 83, 45, 0.3), rgba(22, 101, 52, 0.3)),
stat-secondary-value: #16a34a,
stat-secondary-label: #86efac,
stat-tertiary-bg: linear-gradient(135deg, rgba(19, 78, 74, 0.3), rgba(17, 94, 89, 0.3)),
stat-tertiary-value: #0d9488,
stat-tertiary-label: #5eead4,
stat-quaternary-bg: linear-gradient(135deg, rgba(88, 28, 135, 0.3), rgba(107, 33, 168, 0.3)),
stat-quaternary-value: #9333ea,
stat-quaternary-label: #c4b5fd,
);

250
src/scss/themes/_index.scss Normal file
View File

@ -0,0 +1,250 @@
@use 'sass:map';
@use 'base';
@use 'hero';
@use 'about';
@use 'services';
@use 'skills';
@use 'certifications';
@use 'projects';
@use 'contact';
// Combine all section themes into main theme maps
$light-theme: map.merge(
base.$base-light-theme,
map.merge(
hero.$hero-light-theme,
map.merge(
about.$about-light-theme,
map.merge(
services.$services-light-theme,
map.merge(
skills.$skills-light-theme,
map.merge(
certifications.$certifications-light-theme,
map.merge(
projects.$projects-light-theme,
contact.$contact-light-theme
)
)
)
)
)
)
);
$dark-theme: map.merge(
base.$base-dark-theme,
map.merge(
hero.$hero-dark-theme,
map.merge(
about.$about-dark-theme,
map.merge(
services.$services-dark-theme,
map.merge(
skills.$skills-dark-theme,
map.merge(
certifications.$certifications-dark-theme,
map.merge(
projects.$projects-dark-theme,
contact.$contact-dark-theme
)
)
)
)
)
)
);
// Mixin: SCSS-Map CSS-Variables
@mixin theme-vars($theme) {
--color-primary: #{map.get($theme, primary)};
--color-background: #{map.get($theme, background)};
--color-text: #{map.get($theme, text)};
--color-text-muted: #{map.get($theme, text-muted)};
--box-shadow-hover: #{map.get($theme, hover-box-shadow)};
--box-shadow-active: #{map.get($theme, active-box-shadow)};
--gradient-primary: #{map.get($theme, gradient-primary)};
--gradient-text: #{map.get($theme, gradient-text)};
// Hero section variables
--hero-background: #{map.get($theme, hero-background)};
// Stat variables using semantic naming
--stat-primary-bg: #{map.get($theme, stat-primary-bg)};
--stat-primary-value: #{map.get($theme, stat-primary-value)};
--stat-primary-label: #{map.get($theme, stat-primary-label)};
--stat-secondary-bg: #{map.get($theme, stat-secondary-bg)};
--stat-secondary-value: #{map.get($theme, stat-secondary-value)};
--stat-secondary-label: #{map.get($theme, stat-secondary-label)};
--stat-tertiary-bg: #{map.get($theme, stat-tertiary-bg)};
--stat-tertiary-value: #{map.get($theme, stat-tertiary-value)};
--stat-tertiary-label: #{map.get($theme, stat-tertiary-label)};
--stat-quaternary-bg: #{map.get($theme, stat-quaternary-bg)};
--stat-quaternary-value: #{map.get($theme, stat-quaternary-value)};
--stat-quaternary-label: #{map.get($theme, stat-quaternary-label)};
// About section variables
--about-background: #{map.get($theme, about-background)};
--gradient-about-title: #{map.get($theme, gradient-about-title)};
--about-greeting-color: #{map.get($theme, about-greeting-color)};
--gradient-image-overlay: #{map.get($theme, gradient-image-overlay)};
// Skill badge variables using semantic naming
--skill-badge-primary-bg: #{map.get($theme, skill-badge-primary-bg)};
--skill-badge-primary-text: #{map.get($theme, skill-badge-primary-text)};
--skill-badge-secondary-bg: #{map.get($theme, skill-badge-secondary-bg)};
--skill-badge-secondary-text: #{map.get($theme, skill-badge-secondary-text)};
--skill-badge-tertiary-bg: #{map.get($theme, skill-badge-tertiary-bg)};
--skill-badge-tertiary-text: #{map.get($theme, skill-badge-tertiary-text)};
--skill-badge-quaternary-bg: #{map.get($theme, skill-badge-quaternary-bg)};
--skill-badge-quaternary-text: #{map.get($theme, skill-badge-quaternary-text)};
// Feature card variables using semantic naming
--feature-card-primary-bg: #{map.get($theme, feature-card-primary-bg)};
--feature-card-secondary-bg: #{map.get($theme, feature-card-secondary-bg)};
--feature-card-tertiary-bg: #{map.get($theme, feature-card-tertiary-bg)};
--feature-icon-primary: #{map.get($theme, feature-icon-primary)};
--feature-icon-secondary: #{map.get($theme, feature-icon-secondary)};
--feature-icon-tertiary: #{map.get($theme, feature-icon-tertiary)};
--feature-title-primary: #{map.get($theme, feature-title-primary)};
--feature-title-secondary: #{map.get($theme, feature-title-secondary)};
--feature-title-tertiary: #{map.get($theme, feature-title-tertiary)};
--feature-description-primary: #{map.get($theme, feature-description-primary)};
--feature-description-secondary: #{map.get($theme, feature-description-secondary)};
--feature-description-tertiary: #{map.get($theme, feature-description-tertiary)};
// Services section variables
--services-background: #{map.get($theme, services-background)};
--gradient-services-title: #{map.get($theme, gradient-services-title)};
// Service card variables
--service-card-primary-bg: #{map.get($theme, service-card-primary-bg)};
--service-card-secondary-bg: #{map.get($theme, service-card-secondary-bg)};
--service-card-tertiary-bg: #{map.get($theme, service-card-tertiary-bg)};
--service-card-quaternary-bg: #{map.get($theme, service-card-quaternary-bg)};
--service-card-quinary-bg: #{map.get($theme, service-card-quinary-bg)};
--service-card-senary-bg: #{map.get($theme, service-card-senary-bg)};
--service-icon-primary: #{map.get($theme, service-icon-primary)};
--service-icon-secondary: #{map.get($theme, service-icon-secondary)};
--service-icon-tertiary: #{map.get($theme, service-icon-tertiary)};
--service-icon-quaternary: #{map.get($theme, service-icon-quaternary)};
--service-icon-quinary: #{map.get($theme, service-icon-quinary)};
--service-icon-senary: #{map.get($theme, service-icon-senary)};
--service-title-primary: #{map.get($theme, service-title-primary)};
--service-title-secondary: #{map.get($theme, service-title-secondary)};
--service-title-tertiary: #{map.get($theme, service-title-tertiary)};
--service-title-quaternary: #{map.get($theme, service-title-quaternary)};
--service-title-quinary: #{map.get($theme, service-title-quinary)};
--service-title-senary: #{map.get($theme, service-title-senary)};
--service-description-primary: #{map.get($theme, service-description-primary)};
--service-description-secondary: #{map.get($theme, service-description-secondary)};
--service-description-tertiary: #{map.get($theme, service-description-tertiary)};
--service-description-quaternary: #{map.get($theme, service-description-quaternary)};
--service-description-quinary: #{map.get($theme, service-description-quinary)};
--service-description-senary: #{map.get($theme, service-description-senary)};
// Skills section variables
--skills-background: #{map.get($theme, skills-background)};
--skills-background-pattern: #{map.get($theme, skills-background-pattern)};
--gradient-skills-title: #{map.get($theme, gradient-skills-title)};
--skills-category-bg: #{map.get($theme, skills-category-bg)};
--skills-category-border: #{map.get($theme, skills-category-border)};
--skills-category-title-color: #{map.get($theme, skills-category-title-color)};
--skills-skill-name-color: #{map.get($theme, skills-skill-name-color)};
--skills-skill-level-color: #{map.get($theme, skills-skill-level-color)};
--skills-skill-percentage-color: #{map.get($theme, skills-skill-percentage-color)};
--skills-progress-bg: #{map.get($theme, skills-progress-bg)};
// Card-specific backgrounds and accents
--skills-category-bg-primary: #{map.get($theme, skills-category-bg-primary)};
--skills-category-border-primary: #{map.get($theme, skills-category-border-primary)};
--skills-gradient-primary: #{map.get($theme, skills-gradient-primary)};
--skills-accent-primary: #{map.get($theme, skills-accent-primary)};
--skills-category-bg-secondary: #{map.get($theme, skills-category-bg-secondary)};
--skills-category-border-secondary: #{map.get($theme, skills-category-border-secondary)};
--skills-gradient-secondary: #{map.get($theme, skills-gradient-secondary)};
--skills-accent-secondary: #{map.get($theme, skills-accent-secondary)};
--skills-category-bg-tertiary: #{map.get($theme, skills-category-bg-tertiary)};
--skills-category-border-tertiary: #{map.get($theme, skills-category-border-tertiary)};
--skills-gradient-tertiary: #{map.get($theme, skills-gradient-tertiary)};
--skills-accent-tertiary: #{map.get($theme, skills-accent-tertiary)};
--skills-category-bg-quaternary: #{map.get($theme, skills-category-bg-quaternary)};
--skills-category-border-quaternary: #{map.get($theme, skills-category-border-quaternary)};
--skills-gradient-quaternary: #{map.get($theme, skills-gradient-quaternary)};
--skills-accent-quaternary: #{map.get($theme, skills-accent-quaternary)};
--skills-category-bg-quinary: #{map.get($theme, skills-category-bg-quinary)};
--skills-category-border-quinary: #{map.get($theme, skills-category-border-quinary)};
--skills-gradient-quinary: #{map.get($theme, skills-gradient-quinary)};
--skills-accent-quinary: #{map.get($theme, skills-accent-quinary)};
--skills-category-bg-senary: #{map.get($theme, skills-category-bg-senary)};
--skills-category-border-senary: #{map.get($theme, skills-category-border-senary)};
--skills-gradient-senary: #{map.get($theme, skills-gradient-senary)};
--skills-accent-senary: #{map.get($theme, skills-accent-senary)};
// Progress bar colors
--skills-progress-primary: #{map.get($theme, skills-progress-primary)};
--skills-progress-secondary: #{map.get($theme, skills-progress-secondary)};
--skills-progress-tertiary: #{map.get($theme, skills-progress-tertiary)};
--skills-progress-quaternary: #{map.get($theme, skills-progress-quaternary)};
--skills-progress-quinary: #{map.get($theme, skills-progress-quinary)};
--skills-progress-senary: #{map.get($theme, skills-progress-senary)};
// Certifications section variables
--certifications-background: #{map.get($theme, certifications-background)};
--gradient-certifications-title: #{map.get($theme, gradient-certifications-title)};
--color-certifications-primary: #{map.get($theme, color-certifications-primary)};
--certifications-card-background: #{map.get($theme, certifications-card-background)};
--certifications-card-shadow: #{map.get($theme, certifications-card-shadow)};
--certifications-card-shadow-hover: #{map.get($theme, certifications-card-shadow-hover)};
--certifications-card-overlay: #{map.get($theme, certifications-card-overlay)};
--certifications-badge-background: #{map.get($theme, certifications-badge-background)};
--certifications-badge-border: #{map.get($theme, certifications-badge-border)};
--color-certifications-badge-text: #{map.get($theme, color-certifications-badge-text)};
// Projects section variables
--projects-background: #{map.get($theme, projects-background)};
--gradient-projects-title: #{map.get($theme, gradient-projects-title)};
--projects-card-background: #{map.get($theme, projects-card-background)};
--projects-card-border: #{map.get($theme, projects-card-border)};
--projects-card-shadow: #{map.get($theme, projects-card-shadow)};
--projects-card-shadow-hover: #{map.get($theme, projects-card-shadow-hover)};
--projects-overlay-background: #{map.get($theme, projects-overlay-background)};
--projects-button-primary-bg: #{map.get($theme, projects-button-primary-bg)};
--projects-button-primary-text: #{map.get($theme, projects-button-primary-text)};
--projects-button-primary-border: #{map.get($theme, projects-button-primary-border)};
--projects-button-primary-hover-bg: #{map.get($theme, projects-button-primary-hover-bg)};
--projects-button-secondary-bg: #{map.get($theme, projects-button-secondary-bg)};
--projects-button-secondary-text: #{map.get($theme, projects-button-secondary-text)};
--projects-button-secondary-border: #{map.get($theme, projects-button-secondary-border)};
--projects-button-secondary-hover-bg: #{map.get($theme, projects-button-secondary-hover-bg)};
--projects-tech-badge-bg: #{map.get($theme, projects-tech-badge-bg)};
--projects-tech-badge-text: #{map.get($theme, projects-tech-badge-text)};
--projects-tech-badge-border: #{map.get($theme, projects-tech-badge-border)};
// Contact section variables
--contact-background: #{map.get($theme, contact-background)};
--gradient-contact-title: #{map.get($theme, gradient-contact-title)};
--color-contact-primary: #{map.get($theme, color-contact-primary)};
--contact-form-bg: #{map.get($theme, contact-form-bg)};
--contact-form-border: #{map.get($theme, contact-form-border)};
--contact-form-shadow: #{map.get($theme, contact-form-shadow)};
--contact-input-bg: #{map.get($theme, contact-input-bg)};
--contact-input-border: #{map.get($theme, contact-input-border)};
--contact-input-focus-ring: #{map.get($theme, contact-input-focus-ring)};
--contact-button-bg: #{map.get($theme, contact-button-bg)};
--contact-button-text: #{map.get($theme, contact-button-text)};
--contact-button-hover-bg: #{map.get($theme, contact-button-hover-bg)};
--contact-social-bg: #{map.get($theme, contact-social-bg)};
--contact-social-text: #{map.get($theme, contact-social-text)};
--contact-social-border: #{map.get($theme, contact-social-border)};
--contact-social-hover-bg: #{map.get($theme, contact-social-hover-bg)};
--contact-social-hover-border: #{map.get($theme, contact-social-hover-border)};
}

View File

@ -0,0 +1,67 @@
// Projects section theme definitions
$projects-light-theme: (
// Projects section background (light orange/red tones)
'projects-background': linear-gradient(135deg, #fff7ed 0%, #fef2f2 100%),
// Projects title gradient (orange to red)
'gradient-projects-title': linear-gradient(to right, #ea580c, #dc2626),
// Card styling
'projects-card-background': linear-gradient(135deg, #ffffff 0%, #fefefe 100%),
'projects-card-border': rgba(234, 88, 12, 0.1),
'projects-card-shadow': 0 4px 6px -1px rgba(0, 0, 0, 0.1),
'projects-card-shadow-hover': 0 20px 25px -5px rgba(0, 0, 0, 0.1),
// Overlay styling
'projects-overlay-background': rgba(0, 0, 0, 0.6),
// Button styling
'projects-button-primary-bg': linear-gradient(135deg, #ea580c 0%, #dc2626 100%),
'projects-button-primary-text': #ffffff,
'projects-button-primary-border': rgba(234, 88, 12, 0.3),
'projects-button-primary-hover-bg': linear-gradient(135deg, #dc2626 0%, #b91c1c 100%),
'projects-button-secondary-bg': rgba(255, 255, 255, 0.9),
'projects-button-secondary-text': #374151,
'projects-button-secondary-border': rgba(255, 255, 255, 0.2),
'projects-button-secondary-hover-bg': #ffffff,
// Tech badge styling
'projects-tech-badge-bg': linear-gradient(135deg, #fed7aa 0%, #fecaca 100%),
'projects-tech-badge-text': #c2410c,
'projects-tech-badge-border': rgba(234, 88, 12, 0.2),
);
$projects-dark-theme: (
// Projects section background (dark orange/red tones)
'projects-background': linear-gradient(135deg, rgba(124, 45, 18, 0.2) 0%, rgba(127, 29, 29, 0.2) 100%),
// Projects title gradient (brighter orange to red for dark mode)
'gradient-projects-title': linear-gradient(to right, #fb923c, #f87171),
// Card styling (dark theme)
'projects-card-background': linear-gradient(135deg, #111827 0%, #1f2937 100%),
'projects-card-border': rgba(251, 146, 60, 0.2),
'projects-card-shadow': 0 4px 6px -1px rgba(0, 0, 0, 0.3),
'projects-card-shadow-hover': 0 20px 25px -5px rgba(0, 0, 0, 0.4),
// Overlay styling
'projects-overlay-background': rgba(0, 0, 0, 0.7),
// Button styling (dark theme)
'projects-button-primary-bg': linear-gradient(135deg, #ea580c 0%, #dc2626 100%),
'projects-button-primary-text': #ffffff,
'projects-button-primary-border': rgba(234, 88, 12, 0.3),
'projects-button-primary-hover-bg': linear-gradient(135deg, #fb923c 0%, #f87171 100%),
'projects-button-secondary-bg': rgba(31, 41, 55, 0.9),
'projects-button-secondary-text': #e5e7eb,
'projects-button-secondary-border': rgba(75, 85, 99, 0.3),
'projects-button-secondary-hover-bg': #374151,
// Tech badge styling (dark theme)
'projects-tech-badge-bg': linear-gradient(135deg, rgba(124, 45, 18, 0.3) 0%, rgba(127, 29, 29, 0.3) 100%),
'projects-tech-badge-text': #fed7aa,
'projects-tech-badge-border': rgba(251, 146, 60, 0.3),
);

View File

@ -0,0 +1,69 @@
$services-light-theme: (
// Services section colors - Tailwind inspired
services-background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 25%, #cbd5e1 70%, #94a3b8 100%),
gradient-services-title: linear-gradient(90deg, #0f172a, #1e293b, #334155),
// Service card colors using Tailwind color palette
service-card-primary-bg: linear-gradient(135deg, #dbeafe, #bfdbfe), // blue-100 to blue-200
service-card-secondary-bg: linear-gradient(135deg, #dcfce7, #bbf7d0), // green-100 to green-200
service-card-tertiary-bg: linear-gradient(135deg, #e9d5ff, #ddd6fe), // violet-100 to violet-200
service-card-quaternary-bg: linear-gradient(135deg, #ccfbf1, #99f6e4), // teal-100 to teal-200
service-card-quinary-bg: linear-gradient(135deg, #fed7aa, #fdba74), // orange-200 to orange-300
service-card-senary-bg: linear-gradient(135deg, #fecaca, #fca5a5), // red-200 to red-300
service-icon-primary: #2563eb, // blue-600
service-icon-secondary: #16a34a, // green-600
service-icon-tertiary: #7c3aed, // violet-600
service-icon-quaternary: #0d9488, // teal-600
service-icon-quinary: #ea580c, // orange-600
service-icon-senary: #dc2626, // red-600
service-title-primary: #1e40af, // blue-700
service-title-secondary: #166534, // green-700
service-title-tertiary: #6d28d9, // violet-700
service-title-quaternary: #0f766e, // teal-700
service-title-quinary: #c2410c, // orange-700
service-title-senary: #b91c1c, // red-700
service-description-primary: #1d4ed8, // blue-700
service-description-secondary: #15803d, // green-700
service-description-tertiary: #5b21b6, // violet-800
service-description-quaternary: #115e59, // teal-800
service-description-quinary: #9a3412, // orange-800
service-description-senary: #991b1b, // red-800
);
$services-dark-theme: (
// Services section colors - Dark mode with Tailwind palette
services-background: linear-gradient(135deg, #0f172a 0%, #1e293b 25%, #334155 70%, #475569 100%),
gradient-services-title: linear-gradient(90deg, #f1f5f9, #e2e8f0, #cbd5e1),
// Service card colors for dark theme - using Tailwind dark colors
service-card-primary-bg: linear-gradient(135deg, rgba(30, 58, 138, 0.3), rgba(37, 99, 235, 0.2)), // blue-800/30 to blue-600/20
service-card-secondary-bg: linear-gradient(135deg, rgba(22, 101, 52, 0.3), rgba(34, 197, 94, 0.2)), // green-800/30 to green-500/20
service-card-tertiary-bg: linear-gradient(135deg, rgba(91, 33, 182, 0.3), rgba(124, 58, 237, 0.2)), // violet-800/30 to violet-600/20
service-card-quaternary-bg: linear-gradient(135deg, rgba(17, 94, 89, 0.3), rgba(20, 184, 166, 0.2)), // teal-800/30 to teal-500/20
service-card-quinary-bg: linear-gradient(135deg, rgba(154, 52, 18, 0.3), rgba(249, 115, 22, 0.2)), // orange-800/30 to orange-500/20
service-card-senary-bg: linear-gradient(135deg, rgba(153, 27, 27, 0.3), rgba(239, 68, 68, 0.2)), // red-800/30 to red-500/20
service-icon-primary: #60a5fa, // blue-400
service-icon-secondary: #4ade80, // green-400
service-icon-tertiary: #a78bfa, // violet-400
service-icon-quaternary: #2dd4bf, // teal-400
service-icon-quinary: #fb923c, // orange-400
service-icon-senary: #f87171, // red-400
service-title-primary: #93c5fd, // blue-300
service-title-secondary: #86efac, // green-300
service-title-tertiary: #c4b5fd, // violet-300
service-title-quaternary: #5eead4, // teal-300
service-title-quinary: #fdba74, // orange-300
service-title-senary: #fca5a5, // red-300
service-description-primary: #bfdbfe, // blue-200
service-description-secondary: #bbf7d0, // green-200
service-description-tertiary: #ddd6fe, // violet-200
service-description-quaternary: #99f6e4, // teal-200
service-description-quinary: #fed7aa, // orange-200
service-description-senary: #fecaca, // red-200
);

View File

@ -0,0 +1,110 @@
$skills-light-theme: (
// Skills section colors
skills-background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 25%, #e2e8f0 75%, #cbd5e1 100%),
skills-background-pattern: radial-gradient(circle at 25% 25%, #3b82f6, transparent 50%),
gradient-skills-title: linear-gradient(90deg, #1e40af, #3b82f6, #10b981),
skills-category-bg: rgba(255, 255, 255, 0.7),
skills-category-border: rgba(148, 163, 184, 0.2),
skills-category-title-color: #1e293b,
skills-skill-name-color: #334155,
skills-skill-level-color: #64748b,
skills-skill-percentage-color: #475569,
skills-progress-bg: rgba(226, 232, 240, 0.8),
// Card 1 - Web Frameworks (Blue theme - matching hero)
skills-category-bg-primary: linear-gradient(135deg, rgba(239, 246, 255, 0.9), rgba(219, 234, 254, 0.95)),
skills-category-border-primary: rgba(59, 130, 246, 0.2),
skills-gradient-primary: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(37, 99, 235, 0.05)),
skills-accent-primary: #3b82f6,
// Card 2 - Styling & Design (Green theme - matching about)
skills-category-bg-secondary: linear-gradient(135deg, rgba(236, 253, 245, 0.9), rgba(209, 250, 229, 0.95)),
skills-category-border-secondary: rgba(16, 185, 129, 0.2),
skills-gradient-secondary: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(5, 150, 105, 0.05)),
skills-accent-secondary: #10b981,
// Card 3 - Backend Development (Purple theme)
skills-category-bg-tertiary: linear-gradient(135deg, rgba(245, 243, 255, 0.9), rgba(237, 233, 254, 0.95)),
skills-category-border-tertiary: rgba(139, 92, 246, 0.2),
skills-gradient-tertiary: linear-gradient(135deg, rgba(139, 92, 246, 0.1), rgba(124, 58, 237, 0.05)),
skills-accent-tertiary: #8b5cf6,
// Card 4 - Development Tools (Teal theme)
skills-category-bg-quaternary: linear-gradient(135deg, rgba(240, 253, 250, 0.9), rgba(204, 251, 241, 0.95)),
skills-category-border-quaternary: rgba(6, 182, 212, 0.2),
skills-gradient-quaternary: linear-gradient(135deg, rgba(6, 182, 212, 0.1), rgba(8, 145, 178, 0.05)),
skills-accent-quaternary: #06b6d4,
// Card 5 - Testing & Quality (Orange theme)
skills-category-bg-quinary: linear-gradient(135deg, rgba(255, 251, 235, 0.9), rgba(254, 243, 199, 0.95)),
skills-category-border-quinary: rgba(245, 158, 11, 0.2),
skills-gradient-quinary: linear-gradient(135deg, rgba(245, 158, 11, 0.1), rgba(217, 119, 6, 0.05)),
skills-accent-quinary: #f59e0b,
// Card 6 - AI-Tools (Indigo theme)
skills-category-bg-senary: linear-gradient(135deg, rgba(238, 242, 255, 0.9), rgba(224, 231, 255, 0.95)),
skills-category-border-senary: rgba(99, 102, 241, 0.2),
skills-gradient-senary: linear-gradient(135deg, rgba(99, 102, 241, 0.1), rgba(79, 70, 229, 0.05)),
skills-accent-senary: #6366f1,
// Enhanced progress bar colors
skills-progress-primary: linear-gradient(90deg, #3b82f6, #1d4ed8, #1e40af),
skills-progress-secondary: linear-gradient(90deg, #10b981, #047857, #065f46),
skills-progress-tertiary: linear-gradient(90deg, #8b5cf6, #7c3aed, #6d28d9),
skills-progress-quaternary: linear-gradient(90deg, #06b6d4, #0891b2, #0e7490),
skills-progress-quinary: linear-gradient(90deg, #f59e0b, #d97706, #b45309),
skills-progress-senary: linear-gradient(90deg, #6366f1, #4f46e5, #4338ca),
);
$skills-dark-theme: (
// Skills section colors
skills-background: linear-gradient(135deg, #0f172a 0%, #1e293b 25%, #334155 75%, #475569 100%),
skills-background-pattern: radial-gradient(circle at 25% 25%, #1e40af, transparent 50%),
gradient-skills-title: linear-gradient(90deg, #60a5fa, #34d399, #a78bfa),
skills-category-bg: rgba(30, 41, 55, 0.8),
skills-category-border: rgba(71, 85, 105, 0.3),
skills-category-title-color: #f1f5f9,
skills-skill-name-color: #cbd5e1,
skills-skill-level-color: #94a3b8,
skills-skill-percentage-color: #e2e8f0,
skills-progress-bg: rgba(51, 65, 85, 0.8),
// Dark theme card backgrounds
skills-category-bg-primary: linear-gradient(135deg, rgba(30, 58, 138, 0.4), rgba(29, 78, 216, 0.3)),
skills-category-border-primary: rgba(96, 165, 250, 0.3),
skills-gradient-primary: linear-gradient(135deg, rgba(96, 165, 250, 0.1), rgba(59, 130, 246, 0.05)),
skills-accent-primary: #60a5fa,
skills-category-bg-secondary: linear-gradient(135deg, rgba(6, 95, 70, 0.4), rgba(4, 120, 87, 0.3)),
skills-category-border-secondary: rgba(52, 211, 153, 0.3),
skills-gradient-secondary: linear-gradient(135deg, rgba(52, 211, 153, 0.1), rgba(16, 185, 129, 0.05)),
skills-accent-secondary: #34d399,
skills-category-bg-tertiary: linear-gradient(135deg, rgba(88, 28, 135, 0.4), rgba(109, 40, 217, 0.3)),
skills-category-border-tertiary: rgba(167, 139, 250, 0.3),
skills-gradient-tertiary: linear-gradient(135deg, rgba(167, 139, 250, 0.1), rgba(139, 92, 246, 0.05)),
skills-accent-tertiary: #a78bfa,
skills-category-bg-quaternary: linear-gradient(135deg, rgba(15, 118, 110, 0.4), rgba(17, 94, 89, 0.3)),
skills-category-border-quaternary: rgba(34, 211, 238, 0.3),
skills-gradient-quaternary: linear-gradient(135deg, rgba(34, 211, 238, 0.1), rgba(6, 182, 212, 0.05)),
skills-accent-quaternary: #22d3ee,
skills-category-bg-quinary: linear-gradient(135deg, rgba(180, 83, 9, 0.4), rgba(217, 119, 6, 0.3)),
skills-category-border-quinary: rgba(251, 191, 36, 0.3),
skills-gradient-quinary: linear-gradient(135deg, rgba(251, 191, 36, 0.1), rgba(245, 158, 11, 0.05)),
skills-accent-quinary: #fbbf24,
skills-category-bg-senary: linear-gradient(135deg, rgba(67, 56, 202, 0.4), rgba(79, 70, 229, 0.3)),
skills-category-border-senary: rgba(129, 140, 248, 0.3),
skills-gradient-senary: linear-gradient(135deg, rgba(129, 140, 248, 0.1), rgba(99, 102, 241, 0.05)),
skills-accent-senary: #818cf8,
// Enhanced progress bars for dark theme
skills-progress-primary: linear-gradient(90deg, #60a5fa, #3b82f6, #2563eb),
skills-progress-secondary: linear-gradient(90deg, #34d399, #10b981, #059669),
skills-progress-tertiary: linear-gradient(90deg, #a78bfa, #8b5cf6, #7c3aed),
skills-progress-quaternary: linear-gradient(90deg, #22d3ee, #06b6d4, #0891b2),
skills-progress-quinary: linear-gradient(90deg, #fbbf24, #f59e0b, #d97706),
skills-progress-senary: linear-gradient(90deg, #818cf8, #6366f1, #4f46e5),
);

View File

@ -59,4 +59,15 @@ $services-grid-gap: 1.5rem;
$services-grid-gap-mobile: 1rem; $services-grid-gap-mobile: 1rem;
$services-header-margin: 2rem; $services-header-margin: 2rem;
// Skills Section Variables
$skills-header-margin: 3rem;
$skills-category-gap: 2rem;
$skills-category-gap-mobile: 1.5rem;
$skills-skill-gap: 1.5rem;
$skills-skill-gap-mobile: 1rem;
$skills-progress-height: 0.75rem;
$skills-progress-radius: 9999px;
$skills-category-padding: 2rem;
$skills-category-padding-mobile: 1.5rem;
// Add any other global variables here // Add any other global variables here