diff --git a/animations.js b/animations.js new file mode 100644 index 0000000..965b970 --- /dev/null +++ b/animations.js @@ -0,0 +1,209 @@ +class PortfolioAnimations { + constructor() { + this.init(); + } + + init() { + this.setupIntersectionObserver(); + this.setupMagneticEffects(); + this.setupParallaxEffects(); + this.addFloatingShapes(); + } + + + setupIntersectionObserver() { + const observerOptions = { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const element = entry.target; + const animation = element.dataset.animation; + const delay = element.dataset.delay || 0; + + setTimeout(() => { + element.classList.add(`animate-${animation}`); + + if (element.dataset.counter) { + this.animateCounter(element); + } + }, delay); + + observer.unobserve(element); + } + }); + }, observerOptions); + + document.querySelectorAll('.animate-on-scroll').forEach(el => { + observer.observe(el); + }); + } + + setupMagneticEffects() { + document.querySelectorAll('.magnetic').forEach(button => { + button.addEventListener('mousemove', (e) => { + const rect = button.getBoundingClientRect(); + const x = e.clientX - rect.left - rect.width / 2; + const y = e.clientY - rect.top - rect.height / 2; + + button.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px) scale(1.02)`; + }); + + button.addEventListener('mouseleave', () => { + button.style.transform = 'translate(0px, 0px) scale(1)'; + }); + }); + } + + setupParallaxEffects() { + window.addEventListener('scroll', () => { + const scrolled = window.pageYOffset; + const parallaxElements = document.querySelectorAll('.parallax'); + + parallaxElements.forEach(element => { + const speed = element.dataset.speed || 0.5; + const yPos = -(scrolled * speed); + element.style.transform = `translateY(${yPos}px)`; + }); + }); + } + + animateCounter(element) { + const target = parseInt(element.dataset.counter); + const duration = 2000; + const start = 0; + const increment = target / (duration / 16); + let current = start; + + const timer = setInterval(() => { + current += increment; + if (current >= target) { + current = target; + clearInterval(timer); + } + element.textContent = Math.floor(current); + }, 16); + } + + addFloatingShapes() { + const hero = document.querySelector('.hero-gradient'); + if (!hero) return; + + const shapesContainer = document.createElement('div'); + shapesContainer.className = 'floating-shapes'; + + for (let i = 0; i < 3; i++) { + const shape = document.createElement('div'); + shape.className = 'floating-shape'; + shapesContainer.appendChild(shape); + } + + hero.appendChild(shapesContainer); + } + + static typeWriter(element, text, speed = 100) { + let i = 0; + element.textContent = ''; + + function type() { + if (i < text.length) { + element.textContent += text.charAt(i); + i++; + setTimeout(type, speed); + } + } + + type(); + } + + static revealText(element) { + const text = element.textContent; + const words = text.split(' '); + element.innerHTML = ''; + + words.forEach((word, index) => { + const span = document.createElement('span'); + span.textContent = word + ' '; + span.style.opacity = '0'; + span.style.transform = 'translateY(20px)'; + span.style.transition = `all 0.6s ease ${index * 0.1}s`; + element.appendChild(span); + + setTimeout(() => { + span.style.opacity = '1'; + span.style.transform = 'translateY(0)'; + }, 100); + }); + } + + static setupSmoothScroll() { + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function (e) { + e.preventDefault(); + const target = document.querySelector(this.getAttribute('href')); + + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + }); + }); + } +} + +document.addEventListener('DOMContentLoaded', () => { + new PortfolioAnimations(); + PortfolioAnimations.setupSmoothScroll(); +}); + +window.PortfolioAnimations = PortfolioAnimations; + +function initScrollAnimations() { + const observerOptions = { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px' + }; + + const observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + const delay = entry.target.dataset.delay || 0; + setTimeout(() => { + entry.target.classList.add('visible'); + }, delay); + } + }); + }, observerOptions); + + document.querySelectorAll('.animate-on-scroll').forEach(el => { + observer.observe(el); + }); +} + +function initMagneticEffect() { + const magneticElements = document.querySelectorAll('.magnetic'); + + magneticElements.forEach(el => { + el.addEventListener('mousemove', (e) => { + const rect = el.getBoundingClientRect(); + const x = e.clientX - rect.left - rect.width / 2; + const y = e.clientY - rect.top - rect.height / 2; + + el.style.transform = `translate(${x * 0.1}px, ${y * 0.1}px) scale(1.02)`; + }); + + el.addEventListener('mouseleave', () => { + el.style.transform = 'translate(0px, 0px) scale(1)'; + }); + }); +} + +document.addEventListener('DOMContentLoaded', () => { + initScrollAnimations(); + initMagneticEffect(); +}); \ No newline at end of file diff --git a/apropos.html b/apropos.html new file mode 100644 index 0000000..7001fda --- /dev/null +++ b/apropos.html @@ -0,0 +1,251 @@ + + + + + + À propos - Jules Merienne + + + + + + + + + + + +
+
+

+ À propos de moi +

+ +
+
+

Qui suis-je ?

+

Je m'appelle Jules Merienne, étudiant en première année de BUT informatique à Clermont-Ferrand. Passionné par le développement web et le design, je combine créativité et rigueur technique dans mes projets.

+
+
+
+ + + +
+
+
+ +
+
+
+ + + +
+
+
+

Mon parcours

+

Depuis 2020, j'ai commencé mon apprentissage en autodidacte via Udemy et OpenClassrooms. Après une initiation au Python, je me suis spécialisé dans le développement web et l'UI/UX design, une passion qui m'anime depuis 2022.

+
+
+ +
+
+

Ma vision

+

Je m'efforce de créer des applications optimisées pour l'expérience utilisateur, en explorant constamment de nouvelles technologies et approches. Mon objectif est de devenir ingénieur en informatique après mon BUT.

+
+
+
+ + + +
+
+
+ +
+

+ Mon Parcours +

+ +
+
+ +
+
+
+
+

Freelance Designer & Développeur

+ 2024 - Présent +
+

Travail Indépendant

+

+ Création de solutions numériques complètes pour des clients variés. + Design UX/UI, développement web et mobile, conseil en stratégie digitale. +

+
+ React + Next.js + AdonisJS + Node.js + Figma +
+
+
+ +
+
+
+

BUT Informatique

+ 2024 - Présent +
+

Université Clermont Auvergne

+

+ Formation complète en développement logiciel, bases de données, réseaux et gestion de projet. + Projets pratiques en équipe et stage en entreprise. +

+
+ Linux + C# + SQL + Gestion de projet +
+
+
+ +
+
+
+

Baccalauréat Général

+ 2021 - 2024 +
+

Lycée Théodore de Banville

+

+ Spécialités Mathématiques et Numérique et Sciences Informatiques (NSI). + Mention Bien - Première approche de la programmation et de l'algorithmique. +

+
+ Python + Algorithmique + Mathématiques +
+
+
+
+
+
+ +
+

+ Stack Technique +

+ +
+

Développement Web

+
+
+
+ + + +
+ React +
+ +
+
+ + + +
+ Next.js +
+ +
+
+ TS +
+ TypeScript +
+ +
+
+ + + +
+ AdonisJS +
+ +
+
+ TW +
+ Tailwind +
+ +
+
+ FM +
+ Figma +
+
+
+ +
+

Langages de Programmation

+
+
+
+ + + +
+ Python +
+ +
+
+ + + +
+ C +
+ +
+
+ + + +
+ C++ +
+ +
+
+ + + +
+ C# +
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/contact.html b/contact.html new file mode 100644 index 0000000..cd50119 --- /dev/null +++ b/contact.html @@ -0,0 +1,287 @@ + + + + + + Contact - Jules Merienne + + + + + + + + + + + +
+
+
+

+ Contactez-moi +

+

+ Une idée de projet ? Une question ? N'hésitez pas à me contacter. + Je vous répondrai dans les plus brefs délais. +

+
+ +
+
+

+ Envoyez-moi un message +

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + + + +
+ +
+
+

+ Informations de contact +

+ +
+
+
+ + + +
+ +
+ +
+
+ + + + +
+
+

Localisation

+

Clermont-Ferrand, Disponible à distance

+
+
+
+
+ +
+

+ Retrouvez-moi sur +

+ + +
+ +
+

+ Disponibilité +

+
+
+ Disponible pour de nouveaux projets +
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/images/CodeFirstLogo.png b/images/CodeFirstLogo.png deleted file mode 100644 index a9741c8..0000000 Binary files a/images/CodeFirstLogo.png and /dev/null differ diff --git a/images/My_face.png b/images/My_face.png new file mode 100644 index 0000000..2bd9c2f Binary files /dev/null and b/images/My_face.png differ diff --git a/images/atelier_merienne.png b/images/atelier_merienne.png new file mode 100644 index 0000000..7ccba54 Binary files /dev/null and b/images/atelier_merienne.png differ diff --git a/images/atelier_merienne2.png b/images/atelier_merienne2.png new file mode 100644 index 0000000..82a6909 Binary files /dev/null and b/images/atelier_merienne2.png differ diff --git a/images/duckandcover.png b/images/duckandcover.png new file mode 100644 index 0000000..3a6caa2 Binary files /dev/null and b/images/duckandcover.png differ diff --git a/images/duckandcover2.png b/images/duckandcover2.png new file mode 100644 index 0000000..4f0f89a Binary files /dev/null and b/images/duckandcover2.png differ diff --git a/images/duckandcover3.png b/images/duckandcover3.png new file mode 100644 index 0000000..fe0e9e1 Binary files /dev/null and b/images/duckandcover3.png differ diff --git a/images/duckandcover4.png b/images/duckandcover4.png new file mode 100644 index 0000000..dae652f Binary files /dev/null and b/images/duckandcover4.png differ diff --git a/images/skillupnow.png b/images/skillupnow.png new file mode 100644 index 0000000..b45d568 Binary files /dev/null and b/images/skillupnow.png differ diff --git a/images/skillupnow2.png b/images/skillupnow2.png new file mode 100644 index 0000000..643bf97 Binary files /dev/null and b/images/skillupnow2.png differ diff --git a/images/skillupnow3.png b/images/skillupnow3.png new file mode 100644 index 0000000..e302cac Binary files /dev/null and b/images/skillupnow3.png differ diff --git a/index.html b/index.html index a297d60..9090fcb 100644 --- a/index.html +++ b/index.html @@ -1,34 +1,250 @@ - - + + - portfoliojules - One incredible styled html page - + + + Portfolio - Jules Merienne + + + + + + + + + +
+
+
+ +
+
+
+
+ + + Disponible pour de nouveaux projets + +
+ +

+ Bonjour, je suis + + Jules Merienne + +

+ +

+ Étudiant et freelance dev web + design, je transforme vos idées en + solutions numériques innovantes + et performantes. +

+ +
+ + +
+ + +
+ +
+
+
+
+ Jules Merienne - Étudiant et freelance dev web + design +
+ + + +
+
+
+
+
+
+
- +
+
+
+

+ Ce que je peux faire pour vous +

+

+ Des solutions complètes pour donner vie à vos projets numériques +

+
+ +
+
+
+ + + +
+

Développement Fullstack

+

Applications web modernes avec TypeScript, Adonis.js, React et Next.js pour des solutions robustes et performantes

+
+ +
+
+ + + +
+

Applications C#

+

Développement d'applications desktop et web avec C# pour des solutions enterprise robustes et évolutives

+
+ +
+
+ + + +
+

Design UI/UX

+

Création d'interfaces modernes et intuitives avec une attention particulière à l'expérience utilisateur

+
+
+
+
- - +
+
+

+ Prêt à concrétiser votre projet ? +

+

+ Discutons ensemble de vos besoins et transformons vos idées en réalité numérique. +

+ +
+
+
- -

portfoliojules is my first page, and it has got style!

+ + + + - \ No newline at end of file + \ No newline at end of file diff --git a/interets.html b/interets.html new file mode 100644 index 0000000..e2845fc --- /dev/null +++ b/interets.html @@ -0,0 +1,267 @@ + + + + + + Centres d'intérêt - Jules Merienne + + + + + + + + + + + +
+
+
+
+

+ Mes Passions +

+

+ Découvrez mes passions qui enrichissent mon quotidien et ma créativité. +

+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+
+ + + +
+

Tennis

+
+ +

+ Je pratique le tennis depuis 2 ans. Ce sport m'apporte équilibre et concentration dans mon quotidien. +

+ +
+
+ + + + Classement : 15/4 +
+
+
+
+ +
+
+
+
+ + + +
+

Piano

+
+ +

+ Je débute le piano depuis 6 mois. C'est un moment de détente et d'expression personnelle. +

+ +
+
+ + + + Pratique régulière +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ + + +
+

Technologie

+
+ +

+ Passionné par la technologie, je m'intéresse aux innovations et à leur impact sur notre quotidien. +

+ +
+
+ + + + Veille technologique +
+
+
+
+
+
+ +
+
+

+ Parlons de nos passions +

+

+ Vous partagez ces centres d'intérêt ? Contactez-moi ! +

+ +
+
+
+ + + + + + + Télécharger CV + + + + \ No newline at end of file diff --git a/mycoolstyle.css b/mycoolstyle.css deleted file mode 100644 index 92d69df..0000000 --- a/mycoolstyle.css +++ /dev/null @@ -1,32 +0,0 @@ -body { - padding-left: 11em; - font-family: Georgia, 'Georgia', "Times New Roman", - Times, serif; - color: darksalmon; - background-color: rgb(39, 39, 84) } - ul.navbar { - list-style-type: none; - padding: 0; - margin: 0; - position: absolute; - top: 2em; - left: 1em; - width: 9em } - h1 { - font-family: Helvetica, Geneva, Arial, - SunSans-Regular, sans-serif } - ul.navbar li { - background: white; - margin: 0.5em 0; - padding: 0.3em; - border-right: 1em solid darksalmon } - ul.navbar a { - text-decoration: none } - a:link { - color: blue } - a:visited { - color: darkblue } - address { - margin-top: 1em; - padding-top: 1em; - border-top: thin dotted } \ No newline at end of file diff --git a/navigation.js b/navigation.js new file mode 100644 index 0000000..d769e83 --- /dev/null +++ b/navigation.js @@ -0,0 +1,371 @@ +function createNavigation(activePage = 'home') { + const nav = document.getElementById('navbar'); + if (!nav) return; + + const currentPath = window.location.pathname; + const isInSubdir = currentPath.includes('/projets/') || currentPath.includes('/projects/'); + const prefix = isInSubdir ? '../' : ''; + + nav.innerHTML = ` +
+
+ +
+ + +
+ +
+
+ `; + + if (!document.getElementById('nav-styles')) { + const styles = document.createElement('style'); + styles.id = 'nav-styles'; + styles.textContent = ` + .nav-link { + position: relative; + font-weight: 500; + padding: 12px 20px; + border-radius: 8px; + color: rgb(75 85 99); + text-decoration: none; + transition: all 0.3s ease; + } + + .nav-link-text { + display: inline-block; + } + + .nav-link-text .letter { + display: inline-block; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + transform-origin: center bottom; + } + + .nav-link:hover .nav-link-text .letter { + color: #3b82f6; + transform: translateY(-2px) scale(1.05); + } + + .nav-link:hover .nav-link-text .letter:nth-child(1) { transition-delay: 0ms; } + .nav-link:hover .nav-link-text .letter:nth-child(2) { transition-delay: 50ms; } + .nav-link:hover .nav-link-text .letter:nth-child(3) { transition-delay: 100ms; } + .nav-link:hover .nav-link-text .letter:nth-child(4) { transition-delay: 150ms; } + .nav-link:hover .nav-link-text .letter:nth-child(5) { transition-delay: 200ms; } + .nav-link:hover .nav-link-text .letter:nth-child(6) { transition-delay: 250ms; } + .nav-link:hover .nav-link-text .letter:nth-child(7) { transition-delay: 300ms; } + .nav-link:hover .nav-link-text .letter:nth-child(8) { transition-delay: 350ms; } + .nav-link:hover .nav-link-text .letter:nth-child(9) { transition-delay: 400ms; } + .nav-link:hover .nav-link-text .letter:nth-child(10) { transition-delay: 450ms; } + .nav-link:hover .nav-link-text .letter:nth-child(11) { transition-delay: 500ms; } + .nav-link:hover .nav-link-text .letter:nth-child(12) { transition-delay: 550ms; } + .nav-link:hover .nav-link-text .letter:nth-child(13) { transition-delay: 600ms; } + .nav-link:hover .nav-link-text .letter:nth-child(14) { transition-delay: 650ms; } + .nav-link:hover .nav-link-text .letter:nth-child(15) { transition-delay: 700ms; } + .nav-link:hover .nav-link-text .letter:nth-child(16) { transition-delay: 750ms; } + .nav-link:hover .nav-link-text .letter:nth-child(17) { transition-delay: 800ms; } + .nav-link:hover .nav-link-text .letter:nth-child(18) { transition-delay: 850ms; } + + .nav-link::after { + content: ''; + position: absolute; + bottom: 8px; + left: 50%; + width: 0; + height: 1px; + background: linear-gradient(90deg, #3b82f6, #8b5cf6); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + transform: translateX(-50%); + } + + .nav-link:hover::after { + width: 80%; + } + + .nav-link-active { + color: rgb(37 99 235); + font-weight: 600; + } + + .nav-link-active::after { + width: 80%; + } + + .nav-link-active .nav-link-text .letter { + color: #3b82f6; + } + + .mobile-nav-link { + display: block; + padding: 8px 12px; + font-weight: 500; + border-radius: 6px; + transition: all 0.2s; + overflow: hidden; + position: relative; + } + + .mobile-nav-text { + display: inline-block; + } + + .mobile-nav-text .letter { + display: inline-block; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + transform-origin: center bottom; + } + + .mobile-nav-link:hover .mobile-nav-text .letter { + color: #3b82f6; + transform: translateY(-2px) scale(1.05); + } + + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(1) { transition-delay: 0ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(2) { transition-delay: 50ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(3) { transition-delay: 100ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(4) { transition-delay: 150ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(5) { transition-delay: 200ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(6) { transition-delay: 250ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(7) { transition-delay: 300ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(8) { transition-delay: 350ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(9) { transition-delay: 400ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(10) { transition-delay: 450ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(11) { transition-delay: 500ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(12) { transition-delay: 550ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(13) { transition-delay: 600ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(14) { transition-delay: 650ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(15) { transition-delay: 700ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(16) { transition-delay: 750ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(17) { transition-delay: 800ms; } + .mobile-nav-link:hover .mobile-nav-text .letter:nth-child(18) { transition-delay: 850ms; } + + .mobile-nav-link::after { + content: ''; + position: absolute; + bottom: 4px; + left: 50%; + width: 0; + height: 1px; + background: linear-gradient(90deg, #3b82f6, #8b5cf6); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); + transform: translateX(-50%); + } + + .mobile-nav-link:hover::after { + width: 80%; + } + + .btn-primary-nav { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 10px 24px; + font-size: 14px; + font-weight: 600; + color: white; + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + border-radius: 12px; + border: none; + transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); + box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3); + overflow: hidden; + cursor: pointer; + } + + .btn-primary-nav:hover { + transform: translateY(-3px) scale(1.02); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.4); + background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%); + } + + .btn-primary-nav::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.6s ease; + } + + .btn-primary-nav:hover::before { + left: 100%; + } + + .btn-primary-nav:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; + } + `; + document.head.appendChild(styles); + } + + if (!document.getElementById('cv-download-btn')) { + const cvButton = document.createElement('a'); + cvButton.id = 'cv-download-btn'; + cvButton.href = '../assets/cv.pdf'; + cvButton.className = 'cv-download-btn'; + cvButton.download = true; + cvButton.title = 'Télécharger mon CV'; + cvButton.innerHTML = `Télécharger CV `; + document.body.appendChild(cvButton); + } + + function splitTextIntoLetters() { + const navLinks = document.querySelectorAll('.nav-link-text, .mobile-nav-text'); + navLinks.forEach(link => { + const text = link.textContent; + link.innerHTML = text.split('').map(letter => + letter === ' ' ? ' ' : `${letter}` + ).join(''); + }); + } + + const mobileMenuButton = document.getElementById('mobile-menu-button'); + const mobileMenu = document.getElementById('mobile-menu'); + const menuIcon = document.getElementById('menu-icon'); + const closeIcon = document.getElementById('close-icon'); + let isMobileMenuOpen = false; + + mobileMenuButton.addEventListener('click', () => { + isMobileMenuOpen = !isMobileMenuOpen; + + if (isMobileMenuOpen) { + mobileMenu.style.maxHeight = '384px'; + mobileMenu.style.opacity = '1'; + menuIcon.classList.add('hidden'); + closeIcon.classList.remove('hidden'); + } else { + mobileMenu.style.maxHeight = '0'; + mobileMenu.style.opacity = '0'; + menuIcon.classList.remove('hidden'); + closeIcon.classList.add('hidden'); + } + }); + + splitTextIntoLetters(); +} + +function initNavigation(activePage) { + createNavigation(activePage); +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = { initNavigation }; +} \ No newline at end of file diff --git a/projets.html b/projets.html new file mode 100644 index 0000000..acf237c --- /dev/null +++ b/projets.html @@ -0,0 +1,192 @@ + + + + + + Projets - Jules Merienne + + + + + + + + + + + +
+
+
+

+ Mes Projets +

+

+ Découvrez une sélection de mes réalisations, alliant créativité et expertise technique. +

+
+ +
+
+
+ Atelier Merienne +
+
+

Atelier Merienne

+

+ Site e-commerce pour un atelier de maroquinerie, proposant des produits en cuir, des réparations et des créations sur mesure. +

+
+ AdonisJS + TypeScript + React +
+ +
+
+ +
+
+ Duck and cover +
+
+

DuckAndCover - Jeu de Société Numérique

+

+ Réalisation technique de l'année : transformation d'un jeu de plateau en jeu numérique multijoueur avec gestion de projet complète. +

+
+ C# .NET MAUI + XAML + Gestion de projet +
+ +
+
+ +
+
+ SkillUpNow +
+
+

SkillUpNow - Marketplace de Coaching Gaming

+

+ Design d'interface pour une marketplace de coaching gaming, connectant joueurs et coachs professionnels. +

+
+ Figma + UI/UX Design + Prototypage +
+ +
+
+
+ +
+

+ Vous avez un projet en tête ? +

+

+ Discutons ensemble de votre vision et donnons vie à vos idées. +

+ +
+
+
+ + + + + + + + + + Télécharger CV + + + + \ No newline at end of file diff --git a/projets/ateliermerienne.html b/projets/ateliermerienne.html new file mode 100644 index 0000000..d1319e2 --- /dev/null +++ b/projets/ateliermerienne.html @@ -0,0 +1,373 @@ + + + + + + Site E-commerce - Jules Merienne + + + + + + + + + + + + +
+ +
+
+
+
+ + +

+ Atelier Merienne 🛍️ +

+ +
+

Projet personnel complet

+

+ Résumé : Développement complet d'un site e-commerce pour un atelier de maroquinerie, + proposant des produits en cuir, des réparations et des créations sur mesure. Le site inclut un back office + intégré pour la gestion des produits, des stocks et des commandes. Ce projet m'a permis de développer + mes compétences en développement d'application (C1), optimisation d'applications (C2), + et gestion de projet (C5). +

+
+ +
+ AdonisJS + TypeScript + React + Tailwind CSS + Figma +
+ + +
+ +
+
+ +
+
+
+
+
+
+ Site E-commerce - Aperçu 1 +
+
+ Site E-commerce - Aperçu 2 +
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+
+
+ +
+

À propos du projet

+ +
+

+ Ce projet est un site e-commerce complet développé pour un atelier de maroquinerie, proposant + une gamme de produits en cuir, des services de réparation et des créations sur mesure. L'objectif + était de créer une plateforme moderne et intuitive permettant aux clients de découvrir les produits + et services, tout en offrant une gestion efficace des commandes et du stock. +

+ +

Fonctionnalités développées

+
    +
  • + + + + Catalogue de produits en maroquinerie +
  • +
  • + + + + Réservation de services de réparation +
  • +
  • + + + + Demandes de créations sur mesure +
  • +
  • + + + + Gestion des stocks en temps réel +
  • +
  • + + + + Suivi des commandes et réparations +
  • +
  • + + + + Interface d'administration intuitive +
  • +
+
+
+ + +
+
+

Informations du projet

+ +
+
+
Durée
+
3 mois
+
+ +
+
Équipe
+
Projet seul
+
+ +
+
Mon rôle
+
Développeur Full Stack
+
+ +
+
Technologies
+
AdonisJS, TypeScript, React
+
+ +
+
Statut
+
+
+ En cours +
+
+
+
+ + +
+

Compétences développées

+ +
+
+
+ C1 +
+
+
Développement d'application
+
Full Stack, TypeScript, React, Inertia.js
+
+
+ +
+
+ C2 +
+
+
Optimisation d'applications
+
Performance, SEO, Expérience utilisateur
+
+
+ +
+
+ C5 +
+
+
Gestion de projet
+
Planning, Organisation, Méthodologie
+
+
+
+
+
+
+
+
+ + +
+
+

Architecture technique

+ +
+
+
+ + + +
+

Frontend (React + Inertia.js)

+

Interface utilisateur moderne avec Tailwind CSS, animations fluides et design responsive, intégrée avec Inertia.js pour une expérience SPA.

+
+ +
+
+ + + +
+

Backend (AdonisJS)

+

Application full-stack avec AdonisJS et Inertia.js, permettant une intégration transparente entre le frontend et le backend.

+
+ +
+
+ + + +
+

Base de données

+

Modèle de données optimisé pour les performances et la scalabilité, avec gestion efficace des relations et des transactions.

+
+
+
+
+ + +
+
+

+ Vous avez un projet e-commerce ? +

+

+ De la conception à la réalisation, je peux vous accompagner dans votre projet avec une approche complète alliant design et développement. +

+ +
+
+
+ + + + + + + + Télécharger CV + + + + \ No newline at end of file diff --git a/projets/duckandcover.html b/projets/duckandcover.html new file mode 100644 index 0000000..10788cc --- /dev/null +++ b/projets/duckandcover.html @@ -0,0 +1,374 @@ + + + + + + DuckAndCover - Jules Merienne + + + + + + + + + + + + + +
+ +
+
+
+
+ + +

+ DuckAndCover 🦆 +

+ +
+

Réalisation technique de l'année en cours

+

+ Résumé : J'ai réalisé, en équipe de 4, la transformation du jeu de plateau DuckAndCover en jeu numérique. + Mon rôle a combiné développement et gestion de projet. Développé en C# .NET MAUI avec XAML, j'ai porté une attention + particulière à l'architecture évolutive et aux performances. J'ai mis en place un système de branches Git pour le travail + collaboratif et utilisé ClickUp pour la gestion de projet (planning, temps, attribution des tâches). Ce projet m'a permis + de développer mes compétences en développement d'applications (C1), optimisation (C2) et + gestion de projet (C5), tout en contribuant à la collaboration d'équipe (C6). +

+
+ +
+ C# .NET MAUI + XAML + Git/Branches + ClickUp + Multijoueur Local +
+ + +
+ +
+
+ +
+
+
+
+
+
+ DuckAndCover - Aperçu 1 +
+
+ DuckAndCover - Aperçu 2 +
+
+ DuckAndCover - Aperçu 3 +
+
+ DuckAndCover - Aperçu 4 +
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+
+
+ +
+

À propos du projet

+ +
+

+ DuckAndCover est un projet de transformation numérique d'un jeu de plateau existant. + L'objectif était de créer une version digitale fidèle tout en apportant des améliorations + comme l'intelligence artificielle et une interface moderne. +

+ +

Le jeu original

+

+ DuckAndCover est un jeu multijoueur local (2-7 joueurs) où les participants incarnent des canards + dans un univers coloré. L'objectif est de finir avec le moins de points possible après 3 manches. + Une manche se termine quand il ne reste qu'une pile à un joueur ou quand le nombre de joueurs + + cartes en défausse égale 11. +

+ +

Fonctionnalités développées

+
    +
  • + + + + Interface utilisateur intuitive en XAML +
  • +
  • + + + + Multijoueur local jusqu'à 7 joueurs +
  • +
  • + + + + Intelligence artificielle pour compléter les parties +
  • +
  • + + + + Architecture évolutive et maintenable +
  • +
  • + + + + Animations et effets visuels engageants +
  • +
  • + + + + Compatibilité cross-platform (Windows, Android, iOS) +
  • +
+
+
+ + +
+
+

Informations du projet

+ +
+
+
Durée
+
4 mois
+
+ +
+
Équipe
+
2 développeurs
+
+ +
+
Mon rôle
+
Développeur
+
+ +
+
Plateformes
+
Windows, Android, iOS
+
+ +
+
Statut
+
+
+ Terminé +
+
+
+
+ + +
+

Compétences développées

+ +
+
+
+ C1 +
+
+
Développement d'application
+
Architecture MVVM, C# .NET MAUI
+
+
+ +
+
+ C2 +
+
+
Optimisation d'applications
+
Performance, mémoire, animations
+
+
+ +
+
+ C5 +
+
+
Gestion de projet
+
ClickUp, planning, coordination équipe
+
+
+ +
+
+ C6 +
+
+
Collaboration d'équipe
+
Git, branches, travail collaboratif
+
+
+
+
+
+
+
+
+ + +
+
+

Architecture technique

+ +
+
+
+ + + +
+

Frontend (XAML)

+

Interface utilisateur responsive avec animations fluides et design moderne adapté au multijoueur local.

+
+ +
+
+ + + +
+

Backend (C#)

+

Logique métier robuste avec gestion d'état, intelligence artificielle et mécaniques de jeu optimisées.

+
+ +
+
+ + + +
+

Architecture MVVM

+

Séparation claire des responsabilités pour une maintenance facilitée et une évolutivité optimale.

+
+
+
+
+ + +
+
+

+ Vous avez un projet de jeu ou d'application ? +

+

+ De l'idée à la réalisation, je peux vous accompagner dans votre projet avec une approche complète alliant développement et gestion. +

+ +
+
+
+ + + + + + + + + Télécharger CV + + + + \ No newline at end of file diff --git a/projets/skillupnow.html b/projets/skillupnow.html new file mode 100644 index 0000000..e6e8d01 --- /dev/null +++ b/projets/skillupnow.html @@ -0,0 +1,282 @@ + + + + + + SkillUpNow - Jules Merienne + + + + + + + + + + + + + +
+ +
+
+
+
+ + +

+ SkillUpNow 🎮 +

+ +
+

Design d'interface pour une marketplace de coaching gaming

+

+ Résumé : Design d'interface pour une marketplace de coaching gaming, connectant joueurs et coachs professionnels. + J'ai créé une expérience utilisateur intuitive et moderne, facilitant la découverte et la réservation de séances de coaching. +

+
+ +
+ Figma + UI/UX Design + Prototypage +
+ + +
+ +
+
+ +
+
+
+
+
+
+ SkillUpNow - Aperçu 1 +
+
+ SkillUpNow - Aperçu 2 +
+
+ SkillUpNow - Aperçu 3 +
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+
+
+ +
+

À propos du projet

+ +
+

+ SkillUpNow est une marketplace innovante dédiée au coaching gaming, permettant aux joueurs de + trouver et réserver des séances avec des coachs professionnels. Mon rôle était de concevoir + une interface intuitive et moderne qui facilite la découverte et la réservation de séances. +

+ +

Contexte

+

+ Le projet visait à créer une plateforme qui connecte les joueurs souhaitant améliorer leurs + compétences avec des coachs professionnels. L'enjeu principal était de concevoir une interface + qui rende le processus de recherche et de réservation de coaching simple et agréable. +

+ +

Mon Rôle

+

+ En tant que designer d'interface, j'ai été responsable de la conception de l'expérience utilisateur + complète, de la recherche initiale jusqu'au prototypage final. J'ai travaillé en étroite collaboration + avec l'équipe de développement pour assurer une implémentation fidèle des designs. +

+ +

Processus de Design

+

+ Le processus de design a commencé par une analyse approfondie des besoins des utilisateurs et des + coachs. J'ai ensuite créé des wireframes et des prototypes interactifs pour tester différentes + approches de l'interface. Les retours des utilisateurs ont guidé les itérations successives jusqu'à + l'obtention d'une expérience optimale. +

+ +

Fonctionnalités Clés

+
    +
  • + + + + Interface de recherche intuitive avec filtres avancés +
  • +
  • + + + + Profils de coachs détaillés avec système de notation +
  • +
  • + + + + Processus de réservation simplifié en quelques clics +
  • +
  • + + + + Système de messagerie intégré pour la communication +
  • +
+ +

Résultats

+

+ Le design final a été très bien accueilli par les utilisateurs, avec une augmentation significative + des réservations et une réduction du temps nécessaire pour trouver et réserver un coach. L'interface + intuitive a contribué à une meilleure rétention des utilisateurs et à une expérience globale positive. +

+
+
+ + +
+
+

Informations du projet

+ +
+
+
Durée
+
3 mois
+
+ +
+
Équipe
+
Projet
+
+ +
+
Mon rôle
+
Designer d'interface
+
+ +
+
Outils
+
Figma
+
+ +
+
Statut
+
+
+ Terminé +
+
+
+
+
+
+
+
+ + +
+ +
+
+ + + + + + + + + Télécharger CV + + + + \ No newline at end of file diff --git a/slider.css b/slider.css new file mode 100644 index 0000000..bf8aac0 --- /dev/null +++ b/slider.css @@ -0,0 +1,36 @@ +.slider-container { + position: relative; + overflow: hidden; +} + +.slider-wrapper { + display: flex; + transition: transform 0.5s ease-in-out; +} + +.slider-slide { + min-width: 100%; +} + +.slider-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + background-color: rgba(255, 255, 255, 0.8); + padding: 0.5rem; + border-radius: 9999px; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; +} + +.slider-nav:hover { + background-color: white; +} + +.slider-nav.prev { + left: 0.5rem; +} + +.slider-nav.next { + right: 0.5rem; +} \ No newline at end of file diff --git a/slider.js b/slider.js new file mode 100644 index 0000000..5189133 --- /dev/null +++ b/slider.js @@ -0,0 +1,26 @@ +function initSlider() { + const sliderWrapper = document.querySelector('.slider-wrapper'); + const slides = document.querySelectorAll('.slider-slide'); + const prevBtn = document.querySelector('.slider-nav.prev'); + const nextBtn = document.querySelector('.slider-nav.next'); + let currentSlide = 0; + + function updateSlider() { + sliderWrapper.style.transform = `translateX(-${currentSlide * 100}%)`; + } + + prevBtn.addEventListener('click', () => { + currentSlide = (currentSlide - 1 + slides.length) % slides.length; + updateSlider(); + }); + + nextBtn.addEventListener('click', () => { + currentSlide = (currentSlide + 1) % slides.length; + updateSlider(); + }); + + setInterval(() => { + currentSlide = (currentSlide + 1) % slides.length; + updateSlider(); + }, 5000); +} \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..6183e14 --- /dev/null +++ b/styles.css @@ -0,0 +1,595 @@ +/* ======================================== + PORTFOLIO - JULES MERIENNE + Styles principaux +======================================== */ + +/* Variables CSS */ +:root { + --primary-blue: #3b82f6; + --primary-dark: #1d4ed8; + --secondary-blue: #2563eb; + --secondary-dark: #1e40af; + --purple-600: #9333ea; + --purple-500: #a855f7; + --green-500: #10b981; + --gray-900: #111827; + --gray-800: #1f2937; + --gray-700: #374151; + --gray-600: #4b5563; + --gray-50: #f9fafb; + --white: #ffffff; + --gradient-primary: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + --gradient-secondary: linear-gradient(135deg, #2563eb 0%, #1e40af 100%); + --shadow-primary: 0 4px 15px rgba(59, 130, 246, 0.3); + --shadow-primary-hover: 0 8px 25px rgba(59, 130, 246, 0.4); + --timing: cubic-bezier(0.4, 0, 0.2, 1); + --timing-magnetic: cubic-bezier(0.23, 1, 0.32, 1); +} + +/* Base styles */ +body { + font-family: 'Inter', sans-serif; +} + +/* ======================================== + ANIMATIONS +======================================== */ + +/* Animation base styles */ +.animate-on-scroll { + opacity: 0; + transform: translateY(30px); + transition: all 0.8s var(--timing); +} + +.animate-on-scroll.visible { + opacity: 1; + transform: translateY(0); +} + +.animate-fade-up { + opacity: 1; + transform: translateY(0); +} + +.animate-slide-right { + opacity: 1; + transform: translateX(0); +} + +.animate-scale-up { + opacity: 1; + transform: scale(1); +} + +.magnetic { + transition: all 0.2s var(--timing); +} + +/* Form focus animations */ +input:focus, +select:focus, +textarea:focus { + transform: translateY(-1px); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); +} + +/* ======================================== + BUTTONS +======================================== */ + +.btn-primary { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: var(--white); + background: var(--gradient-primary); + border-radius: 12px; + border: none; + transition: all 0.3s var(--timing-magnetic); + box-shadow: var(--shadow-primary); + overflow: hidden; + cursor: pointer; +} + +.btn-primary-orange { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: var(--white); + background: linear-gradient(135deg, #f97316 0%, #ea580c 100%); + border-radius: 12px; + border: none; + transition: all 0.3s var(--timing-magnetic); + box-shadow: 0 4px 15px rgba(249, 115, 22, 0.3); + overflow: hidden; + cursor: pointer; +} + +.btn-primary-orange:hover { + transform: translateY(-2px); + background: linear-gradient(135deg, #ea580c 0%, #c2410c 100%); + box-shadow: 0 8px 25px rgba(249, 115, 22, 0.4); +} + +.btn-primary-orange::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.6s ease; +} + +.btn-primary-orange:hover::before { + left: 100%; +} + +.btn-primary-orange:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-primary-hover); + background: var(--gradient-secondary); +} + +.btn-primary::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.6s ease; +} + +.btn-primary:hover::before { + left: 100%; +} + +.btn-primary:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; +} + +.btn-secondary { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: #374151; + background: var(--white); + border-radius: 12px; + border: 2px solid #e5e7eb; + transition: all 0.3s ease; + cursor: pointer; +} + +.btn-secondary:hover { + transform: translateY(-2px); + border-color: var(--primary-blue); + color: var(--primary-blue); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); +} + +.btn-white { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: var(--primary-dark); + background: var(--white); + border-radius: 12px; + border: none; + transition: all 0.3s ease; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + cursor: pointer; +} + +.btn-white:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); + background: #f8fafc; +} + +.btn-premium { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: var(--white); + background: var(--gradient-primary); + border-radius: 12px; + border: none; + transition: all 0.3s var(--timing-magnetic); + box-shadow: var(--shadow-primary); + overflow: hidden; + cursor: pointer; +} + +.btn-premium:hover { + transform: translateY(-3px) scale(1.02); + box-shadow: var(--shadow-primary-hover); + background: var(--gradient-secondary); +} + +.btn-premium::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + transition: left 0.6s ease; +} + +.btn-premium:hover::before { + left: 100%; +} + +.btn-premium:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; +} + +.btn-outline { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: var(--primary-blue); + background: transparent; + border-radius: 12px; + border: 2px solid var(--primary-blue); + transition: all 0.3s var(--timing-magnetic); + cursor: pointer; +} + +.btn-outline:hover { + transform: translateY(-2px); + background: var(--primary-blue); + color: var(--white); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.2); +} + +.btn-outline:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; +} + +.btn-outline-orange { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 14px 32px; + font-size: 16px; + font-weight: 600; + color: #f97316; + background: transparent; + border-radius: 12px; + border: 2px solid #f97316; + transition: all 0.3s var(--timing-magnetic); + cursor: pointer; +} + +.btn-outline-orange:hover { + transform: translateY(-2px); + background: #f97316; + color: var(--white); + box-shadow: 0 8px 25px rgba(249, 115, 22, 0.2); +} + +.btn-outline-orange:active { + transform: translateY(-1px) scale(0.98); + transition: all 0.1s ease; +} + +/* ======================================== + CARDS & COMPONENTS +======================================== */ + +.stats-card { + background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%); + border-radius: 16px; + padding: 24px; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + transition: all 0.3s var(--timing); + border: 1px solid #e5e7eb; +} + +.stats-card:hover { + transform: translateY(-4px); + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); + border-color: var(--primary-blue); +} + +.feature-card { + background: var(--white); + border-radius: 20px; + padding: 32px; + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + transition: all 0.3s var(--timing); + border: 1px solid #f3f4f6; +} + +.feature-card:hover { + transform: translateY(-6px); + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.15); + border-color: var(--primary-blue); +} + +.tech-stack-item { + display: flex; + align-items: center; + padding: 12px 20px; + background: linear-gradient(135deg, #f8fafc 0%, #ffffff 100%); + border-radius: 12px; + border: 1px solid #e5e7eb; + transition: all 0.3s var(--timing); + cursor: pointer; +} + +.tech-stack-item:hover { + transform: translateY(-2px) scale(1.02); + box-shadow: 0 8px 25px rgba(59, 130, 246, 0.15); + border-color: var(--primary-blue); + background: linear-gradient(135deg, #eff6ff 0%, #ffffff 100%); +} + +/* ======================================== + NAVIGATION ENHANCEMENTS +======================================== */ + +.nav-link { + position: relative; + overflow: hidden; +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 0; + height: 2px; + background: var(--gradient-primary); + transition: width 0.3s var(--timing); +} + +.nav-link:hover::after { + width: 100%; +} + +/* ======================================== + HERO SECTION +======================================== */ + +.hero-gradient { + background: linear-gradient(135deg, #eff6ff 0%, #ffffff 50%, #f3e8ff 100%); + position: relative; + overflow: hidden; +} + +.hero-gradient::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: + radial-gradient(circle at 25% 25%, rgba(59, 130, 246, 0.1) 0%, transparent 50%), + radial-gradient(circle at 75% 75%, rgba(147, 51, 234, 0.1) 0%, transparent 50%); + pointer-events: none; +} + +.floating-shapes { + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + pointer-events: none; +} + +.floating-shape { + position: absolute; + border-radius: 50%; + opacity: 0.6; + animation: float 6s ease-in-out infinite; +} + +.floating-shape:nth-child(1) { + width: 80px; + height: 80px; + background: linear-gradient(45deg, #3b82f6, #8b5cf6); + top: 20%; + left: 10%; +} + +.floating-shape:nth-child(2) { + width: 60px; + height: 60px; + background: linear-gradient(45deg, #10b981, #3b82f6); + top: 60%; + right: 15%; + animation-delay: 2s; +} + +.floating-shape:nth-child(3) { + width: 100px; + height: 100px; + background: linear-gradient(45deg, #8b5cf6, #ec4899); + bottom: 20%; + left: 20%; + animation-delay: 4s; +} + +/* ======================================== + KEYFRAMES +======================================== */ + +@keyframes float { + 0%, 100% { + transform: translateY(0px) rotate(0deg); + } + 50% { + transform: translateY(-20px) rotate(180deg); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideInRight { + from { + opacity: 0; + transform: translateX(30px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes scaleIn { + from { + opacity: 0; + transform: scale(0.8); + } + to { + opacity: 1; + transform: scale(1); + } +} + +/* ======================================== + RESPONSIVE DESIGN +======================================== */ + +@media (max-width: 768px) { + .floating-shape { + display: none; + } + + .stats-card { + padding: 20px; + } + + .feature-card { + padding: 24px; + } + + .btn-primary, + .btn-secondary, + .btn-white, + .btn-premium { + padding: 12px 24px; + font-size: 14px; + } +} + +/* ======================================== + UTILITY CLASSES +======================================== */ + +.gradient-text { + background: linear-gradient(135deg, var(--primary-blue) 0%, var(--purple-600) 100%); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.glassmorphism { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.text-shadow { + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.hover-lift { + transition: transform 0.3s var(--timing); +} + +.hover-lift:hover { + transform: translateY(-4px); +} + +.cv-download-btn { + position: fixed; + bottom: 24px; + right: 24px; + display: flex; + align-items: center; + gap: 0.5em; + padding: 10px 18px; + background: #2563eb; + color: #fff; + border-radius: 8px; + font-size: 1rem; + font-weight: 500; + box-shadow: 0 2px 8px rgba(37,99,235,0.15); + border: none; + z-index: 1000; + cursor: pointer; + text-decoration: none; + transition: background 0.2s, transform 0.2s; +} + +.cv-download-btn:hover { + background: #1d4ed8; + transform: translateY(-2px) scale(1.04); +} + +.cv-download-btn svg { + width: 18px; + height: 18px; + margin-left: 4px; +} + +@media (max-width: 600px) { + .cv-download-btn { + bottom: 12px; + right: 12px; + padding: 8px 12px; + font-size: 0.95rem; + } +} \ No newline at end of file