initial commit

This commit is contained in:
ewen 2026-05-12 14:50:49 +02:00
commit 454039bc90
170 changed files with 84421 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

8
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/mon-portfolio.iml" filepath="$PROJECT_DIR$/.idea/mon-portfolio.iml" />
</modules>
</component>
</project>

12
.idea/mon-portfolio.iml Normal file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

119
404.html Normal file
View file

@ -0,0 +1,119 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>Page non trouvée - Ewen GADONNAUD</title>
<meta name="description" content="Page non trouvée">
<meta name="keywords" content="404, erreur, page non trouvée">
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="57x57" href="assets/img/favicons.ico/">
<link rel="apple-touch-icon" sizes="60x60" href="assets/img/favicons.ico/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="assets/img/favicons.ico/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="assets/img/favicons.ico/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="assets/img/favicons.ico/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="assets/img/favicons.ico/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="assets/img/favicons.ico/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="assets/img/favicons.ico/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="assets/img/favicons.ico/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="assets/img/favicons.ico/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/favicons.ico/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="assets/img/favicons.ico/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/img/favicons.ico/favicon-16x16.png">
<link rel="manifest" href="assets/img/favicons.ico/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="assets/img/favicons.ico/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Fonts -->
<link href="https://fonts.googleapis.com" rel="preconnect">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
<link href="assets/vendor/aos/aos.css" rel="stylesheet">
<link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
<link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
<!-- Main CSS File -->
<link href="assets/css/main.css" rel="stylesheet">
</head>
<body class="index-page">
<header id="header" class="header d-flex align-items-center light-background sticky-top">
<canvas class="matrix-bg-header" aria-hidden="true"></canvas>
<div class="container position-relative d-flex align-items-center justify-content-between">
<nav id="navmenu" class="navmenu">
<ul>
<li><a href="index.html">Accueil</a></li>
<li><a href="about.html">À propos de moi</a></li>
<li><a href="portfolio.html">Projets</a></li>
<li><a href="formation.html">Formation</a></li>
<li><a href="resume.html">Mon CV</a></li>
<li><a href="services.html">Mes services</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
<i class="mobile-nav-toggle d-xl-none bi bi-list"></i>
</nav>
</div>
</header>
<main class="main">
<section class="section d-flex align-items-center justify-content-center" style="min-height: 80vh;">
<div class="container text-center" data-aos="fade-up">
<h1 class="display-1 fw-bold text-primary">404</h1>
<h2 class="mb-4">Oups ! Page non trouvée.</h2>
<p class="mb-4">La page que vous recherchez semble avoir disparu ou n'existe pas.</p>
<a href="index.html" class="btn btn-primary btn-lg rounded-pill px-5">Retour à l'accueil</a>
</div>
</section>
</main>
<footer id="footer" class="footer">
<div class="container">
<div class="copyright text-center ">
<p>© <span>Copyright</span> <strong class="px-1 sitename">GADONNAUD Ewen</strong> <span>Tout droits
réservés<br></span></p>
</div>
<div class="social-links d-flex justify-content-center">
<a href="https://www.linkedin.com/in/ewen-gadonnaud-b17491283" aria-label="LinkedIn"><i
class="bi bi-linkedin"></i></a>
<a href="https://github.com/Azuneer" aria-label="GitHub"><i class="bi bi-github"></i></a>
</div>
<div class="credits">
Designé avec <a href="https://bootstrapmade.com/">BootstrapMade</a>
</div>
</div>
</footer>
<!-- Scroll Top -->
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
class="bi bi-arrow-up-short"></i></a>
<!-- Preloader -->
<div id="preloader"></div>
<!-- Vendor JS Files -->
<script src="assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/vendor/aos/aos.js"></script>
<script src="assets/vendor/typed.js/typed.umd.js"></script>
<script src="assets/vendor/waypoints/noframework.waypoints.js"></script>
<script src="assets/vendor/purecounter/purecounter_vanilla.js"></script>
<script src="assets/vendor/swiper/swiper-bundle.min.js"></script>
<script src="assets/vendor/imagesloaded/imagesloaded.pkgd.min.js"></script>
<script src="assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="assets/vendor/glightbox/js/glightbox.min.js"></script>
<!-- Main JS File -->
<script src="assets/js/main.js"></script>
</body>
</html>

493
about.html Normal file
View file

@ -0,0 +1,493 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>À Propos</title>
<meta name="description"
content="En savoir plus sur Ewen GADONNAUD : mon parcours, mes compétences en informatique (Linux, Cisco, AWS), mes certifications et mes ambitions professionnelles.">
<meta name="keywords"
content="portfolio, administrateur système, gestion de parc informatique, expérience, étudiant, stages, entreprise, cisco, linux, windows, devops">
<!-- Favicons -->
<link rel="apple-touch-icon" sizes="57x57" href="assets/img/favicons.ico/">
<link rel="apple-touch-icon" sizes="60x60" href="assets/img/favicons.ico/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="assets/img/favicons.ico/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="assets/img/favicons.ico/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="assets/img/favicons.ico/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="assets/img/favicons.ico/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="assets/img/favicons.ico/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="assets/img/favicons.ico/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="assets/img/favicons.ico/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="assets/img/favicons.ico/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="assets/img/favicons.ico/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="assets/img/favicons.ico/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/img/favicons.ico/favicon-16x16.png">
<link rel="manifest" href="assets/img/favicons.ico/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="assets/img/favicons.ico/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<!-- Fonts -->
<link href="https://fonts.googleapis.com" rel="preconnect">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Raleway:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="assets/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="assets/vendor/bootstrap-icons/bootstrap-icons.css" rel="stylesheet">
<link href="assets/vendor/aos/aos.css" rel="stylesheet">
<link href="assets/vendor/swiper/swiper-bundle.min.css" rel="stylesheet">
<link href="assets/vendor/glightbox/css/glightbox.min.css" rel="stylesheet">
<!-- Main CSS File -->
<link href="assets/css/main.css" rel="stylesheet">
</head>
<body class="about-page">
<header id="header" class="header d-flex align-items-center light-background sticky-top">
<canvas class="matrix-bg-header" aria-hidden="true"></canvas>
<div class="container position-relative d-flex align-items-center justify-content-between">
<nav id="navmenu" class="navmenu">
<ul>
<li><a href="index.html">Accueil</a></li>
<li><a href="about.html" class="active">À propos de moi</a></li>
<li><a href="portfolio.html">Projets</a></li>
<li><a href="formation.html">Formation</a></li>
<li><a href="resume.html">Mon CV</a></li>
<li><a href="services.html">Mes services</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
<i class="mobile-nav-toggle d-xl-none bi bi-list"></i>
</nav>
<div class="header-social-links">
<a href="https://www.linkedin.com/in/ewen-gadonnaud-b17491283" class="linkedin" target="_blank"
rel="noopener noreferrer" aria-label="LinkedIn"><i class="bi bi-linkedin"></i></a>
<a href="https://github.com/Azuneer" class="github" target="_blank" rel="noopener noreferrer"
aria-label="GitHub"><i class="bi bi-github"></i></a>
</div>
</div>
</header>
<main class="main">
<!-- About Section -->
<section id="about" class="about section">
<!-- Section Title -->
<div class="container section-title" data-aos="fade-up">
<h2>À Propos</h2>
<p>Depuis mon plus jeune âge, je suis passionné par les nouvelles technologies, surtout par internet et
toutes les micro-sphères qui en découlent. Il m'est paru alors naturel d'orienter ma carrière
académique et professionnelle vers un sujet que j'aime tant, le processus de mise en relation de
tout le monde sur terre grâce à de nouveaux moyens de communication qui florissent chaque jour.</p>
</div><!-- End Section Title -->
<div class="container" data-aos="fade-up" data-aos-delay="100">
<!-- Intro + Photo -->
<div class="row align-items-center justify-content-between gy-5 mb-5">
<div class="col-lg-7" data-aos="fade-right" data-aos-delay="150">
<div class="intro-content">
<span class="eyebrow">Bonjour</span>
<h2 class="headline">Je suis Ewen - étudiant en BTS SIO passionné par le DevOps, les réseaux
et le Cloud</h2>
<p class="lead">
Dans la vie de tous les jours, j'aime mettre en avant mon côté indépendant et ambitieux.
Je considère qu'il est primordial de ne jamais baisser les bras, quelle que soit la
situation.
</p>
<p>
Ce déterminisme et ce sens de l'autonomie sont à la hauteur de mes ambitions (qu'elles
soient professionnelles comme personnelles), et je n'accepterais pas de me voir baisser
les bras, car la vie est un combat de tous les jours.
</p>
<p>
Je pense également qu'il faut savoir être tolérant, tolérant envers les autres, mais
surtout envers soi-même. C'est pour ça qu'il ne faut pas avoir peur de tomber et
d'échouer pour repartir encore plus fort.
</p>
<p>
J'aime être souriant dans la vie de tous les jours, même quand la vie me met à
l'épreuve. Je sais qu'avant tout, le positif attire le positif, et les gens redonnent
généralement la pareille.
</p>
<div class="cta-group">
<a href="portfolio.html" class="btn-ghost">
Voir mes projets <i class="bi bi-arrow-up-right"></i>
</a>
<a href="assets/img/profile/CV_GADONNAUD_EWEN_2025.pdf" class="link-underline">
Télécharger mon CV <i class="bi bi-download"></i>
</a>
</div>
</div>
</div>
<div class="col-lg-5" data-aos="zoom-in" data-aos-delay="250">
<figure class="profile-figure text-center text-lg-end">
<img src="assets/img/profile/me.webp" alt="Portrait d'Ewen" class="img-fluid profile-photo">
</figure>
</div>
</div>
<!-- End Intro + Photo -->
<!-- Skills Grid -->
<div class="mb-5">
<div class="row g-4">
<div class="col-6 col-md-4 col-lg-3" data-aos="fade-up" data-aos-delay="120">
<div class="skill-item">
<i class="bi bi-hdd-network"></i>
<h3>Réseaux</h3>
<p>Configuration et gestion de réseaux Cisco.</p>
</div>
</div>
<div class="col-6 col-md-4 col-lg-3" data-aos="fade-up" data-aos-delay="180">
<div class="skill-item">
<i class="bi bi-terminal"></i>
<h3>Linux</h3>
<p>Administration système et lignes de commande.</p>
</div>
</div>
<div class="col-6 col-md-4 col-lg-3" data-aos="fade-up" data-aos-delay="240">
<div class="skill-item">
<i class="bi bi-pc-display"></i>
<h3>Virtualisation</h3>
<p>VirtualBox, VMware, Docker, bientôt Proxmox.</p>
</div>
</div>
<div class="col-6 col-md-4 col-lg-3" data-aos="fade-up" data-aos-delay="300">
<div class="skill-item">
<i class="bi bi-cloud"></i>
<h3>Cloud AWS</h3>
<p>EC2, S3, VPC, RDS - Certification AWS CPE.</p>
</div>
</div>
</div>
</div>
<!-- End Skills Grid -->
<!-- Journey Timeline -->
<div class="mb-5">
<div class="row g-4">
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="120">
<article class="timeline-item">
<span class="dot"></span>
<time>2025</time>
<h4>BTS SIO - 1ère année</h4>
<p>Lycée Paul-Louis Courier, Tours</p>
</article>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="140">
<article class="timeline-item">
<span class="dot"></span>
<time>2025</time>
<h4>Certification Cisco</h4>
<p>Notions de bases des réseaux informatiques</p>
</article>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="180">
<article class="timeline-item">
<span class="dot"></span>
<time>2025</time>
<h4>Certification AWS CPE</h4>
<p>Cloud Practitioner Essentials - Fondamentaux AWS</p>
</article>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="240">
<article class="timeline-item">
<span class="dot"></span>
<time>2023</time>
<h4>Certification ANSSI</h4>
<p>MOOC Cybersécurité - Fondamentaux de la sécurité</p>
</article>
</div>
</div>
</div>
</div>
<!-- End Journey Timeline -->
<!-- Quote -->
<blockquote class="personal-quote text-center mb-5" data-aos="fade-down" data-aos-delay="200">
<p>"Soyez vous-même, les autres sont déjà pris" - Oscar Wilde</p>
</blockquote>
<!-- End Quote -->
<!-- Fun Facts -->
<div class="row g-3 justify-content-center">
<div class="col-6 col-md-3 col-lg-2" data-aos="zoom-in" data-aos-delay="120">
<div class="fact-pill">
<i class="bi bi-laptop"></i>
<span>Technologies</span>
</div>
</div>
<div class="col-6 col-md-3 col-lg-2" data-aos="zoom-in" data-aos-delay="160">
<div class="fact-pill">
<i class="bi bi-lightbulb"></i>
<span>Innovation</span>
</div>
</div>
<div class="col-6 col-md-3 col-lg-2" data-aos="zoom-in" data-aos-delay="200">
<div class="fact-pill">
<i class="bi bi-trophy"></i>
<span>Ambition</span>
</div>
</div>
<div class="col-6 col-md-3 col-lg-2" data-aos="zoom-in" data-aos-delay="240">
<div class="fact-pill">
<i class="bi bi-emoji-smile"></i>
<span>Positivité</span>
</div>
</div>
</div>
<!-- End Fun Facts -->
</div>
</section><!-- /About Section -->
<!-- Skills Section -->
<section id="skills" class="skills section">
<!-- Section Title -->
<div class="container section-title" data-aos="fade-up">
<h2>Compétences Techniques</h2>
<p>Mes compétences acquises au cours de ma formation en BTS Services Informatiques aux Organisations et
de mes projets personnels</p>
</div><!-- End Section Title -->
<div class="container" data-aos="fade-up" data-aos-delay="100">
<div class="row g-4 skills-animation">
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="100">
<div class="skill-box">
<h3>Linux</h3>
<p>Administration système, lignes de commande et scripting</p>
<span class="text-end d-block">85%</span>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="85" aria-valuemin="0"
aria-valuemax="100" aria-label="Linux: 85%"></div>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="200">
<div class="skill-box">
<h3>Réseaux Cisco</h3>
<p>Configuration routeurs, switchs et protocoles réseau</p>
<span class="text-end d-block">80%</span>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="80" aria-valuemin="0"
aria-valuemax="100" aria-label="Réseaux Cisco: 80%"></div>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="300">
<div class="skill-box">
<h3>Docker / Containers</h3>
<p>Conteneurisation et orchestration d'applications</p>
<span class="text-end d-block">70%</span>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="70" aria-valuemin="0"
aria-valuemax="100" aria-label="Docker / Containers: 70%"></div>
</div>
</div>
</div>
<div class="col-md-6 col-lg-3" data-aos="fade-up" data-aos-delay="400">
<div class="skill-box">
<h3>Cloud AWS</h3>
<p>EC2, S3, VPC, RDS - Infrastructure cloud</p>
<span class="text-end d-block">55%</span>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="55" aria-valuemin="0"
aria-valuemax="100" aria-label="Cloud AWS: 55%">
</div>
</div>
</div>
</div>
</div>
</div>
</section><!-- /Skills Section -->
<!-- Stats Section -->
<section id="stats" class="stats section dark-background">
<div class="container" data-aos="fade-up" data-aos-delay="100">
<div class="row align-items-center">
<div class="col-lg-8">
<div class="row counters">
<div class="col-md-4" data-aos="fade-up" data-aos-delay="300">
<h2><span data-purecounter-start="0" data-purecounter-end="8"
data-purecounter-duration="1" class="purecounter"></span>+</h2>
<p>Projets réalisés</p>
</div>
<div class="col-md-4" data-aos="fade-up" data-aos-delay="400">
<h2><span data-purecounter-start="0" data-purecounter-end="5"
data-purecounter-duration="1" class="purecounter"></span></h2>
<p>Certifications</p>
</div>
<div class="col-md-4" data-aos="fade-up" data-aos-delay="500">
<h2><span data-purecounter-start="0" data-purecounter-end="100"
data-purecounter-duration="1" class="purecounter"></span>%</h2>
<p>Motivation</p>
</div>
</div>
</div>
</div>
</div>
</section><!-- /Stats Section -->
<!-- &lt;!&ndash; Testimonials Section &ndash;&gt;-->
<!-- <section id="testimonials" class="testimonials section">-->
<!-- &lt;!&ndash; Section Title &ndash;&gt;-->
<!-- <div class="container section-title" data-aos="fade-up">-->
<!-- <h2>Témoignages</h2>-->
<!-- <p>Les retours de mes collaborateurs et formateurs</p>-->
<!-- </div>&lt;!&ndash; End Section Title &ndash;&gt;-->
<!-- <div class="container" data-aos="fade-up" data-aos-delay="100">-->
<!-- <div class="swiper init-swiper">-->
<!-- <script type="application/json" class="swiper-config">-->
<!-- {-->
<!-- "loop": true,-->
<!-- "speed": 600,-->
<!-- "autoplay": {-->
<!-- "delay": 5000-->
<!-- },-->
<!-- "slidesPerView": "auto",-->
<!-- "pagination": {-->
<!-- "el": ".swiper-pagination",-->
<!-- "type": "bullets",-->
<!-- "clickable": true-->
<!-- }-->
<!-- }-->
<!-- </script>-->
<!-- <div class="swiper-wrapper">-->
<!-- <div class="swiper-slide">-->
<!-- <div class="testimonial-item">-->
<!-- <div class="row gy-4 justify-content-center">-->
<!-- <div class="col-lg-6">-->
<!-- <div class="testimonial-content">-->
<!-- <p>-->
<!-- <i class="bi bi-quote quote-icon-left"></i>-->
<!-- <span>Ewen fait preuve d'une grande autonomie et d'un excellent esprit d'équipe. Son sérieux et sa motivation sont remarquables.</span>-->
<!-- <i class="bi bi-quote quote-icon-right"></i>-->
<!-- </p>-->
<!-- <h3>Jean Dupont</h3>-->
<!-- <h4>Formateur BTS SIO</h4>-->
<!-- <div class="stars">-->
<!-- <i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="col-lg-2 text-center">-->
<!-- <img src="assets/img/person/person-m-9.webp" class="img-fluid testimonial-img" alt="">-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>&lt;!&ndash; End testimonial item &ndash;&gt;-->
<!-- <div class="swiper-slide">-->
<!-- <div class="testimonial-item">-->
<!-- <div class="row gy-4 justify-content-center">-->
<!-- <div class="col-lg-6">-->
<!-- <div class="testimonial-content">-->
<!-- <p>-->
<!-- <i class="bi bi-quote quote-icon-left"></i>-->
<!-- <span>Un étudiant passionné qui n'hésite pas à approfondir ses connaissances par lui-même. Son intérêt pour les technologies est authentique.</span>-->
<!-- <i class="bi bi-quote quote-icon-right"></i>-->
<!-- </p>-->
<!-- <h3>Marie Lambert</h3>-->
<!-- <h4>Responsable Pédagogique</h4>-->
<!-- <div class="stars">-->
<!-- <i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i><i class="bi bi-star-fill"></i>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="col-lg-2 text-center">-->
<!-- <img src="assets/img/person/person-f-5.webp" class="img-fluid testimonial-img" alt="">-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>&lt;!&ndash; End testimonial item &ndash;&gt;-->
<!-- </div>-->
<!-- <div class="swiper-pagination"></div>-->
<!-- </div>-->
<!-- </div>-->
<!-- </section>&lt;!&ndash; /Testimonials Section &ndash;&gt;-->
</main>
<footer id="footer" class="footer">
<div class="container">
<div class="copyright text-center ">
<p>© <span>Copyright</span> <strong class="px-1 sitename">GADONNAUD Ewen</strong> <span>Tout droits
réservés<br></span></p>
</div>
<div class="social-links d-flex justify-content-center">
<a href="https://www.linkedin.com/in/ewen-gadonnaud-b17491283" aria-label="LinkedIn"><i
class="bi bi-linkedin"></i></a>
<a href="https://github.com/Azuneer" aria-label="GitHub"><i class="bi bi-github"></i></a>
</div>
<div class="credits">
<!-- All the links in the footer should remain intact. -->
<!-- You can delete the links only if you've purchased the pro version. -->
<!-- Licensing information: https://bootstrapmade.com/license/ -->
<!-- Purchase the pro version with working PHP/AJAX contact form: [buy-url] -->
Designé avec <a href="https://bootstrapmade.com/">BootstrapMade</a>
</div>
</div>
</footer>
<!-- Scroll Top -->
<a href="#" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
class="bi bi-arrow-up-short"></i></a>
<!-- Preloader -->
<div id="preloader"></div>
<!-- Vendor JS Files -->
<script src="assets/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="assets/vendor/php-email-form/validate.js"></script>
<script src="assets/vendor/aos/aos.js"></script>
<script src="assets/vendor/typed.js/typed.umd.js"></script>
<script src="assets/vendor/waypoints/noframework.waypoints.js"></script>
<script src="assets/vendor/purecounter/purecounter_vanilla.js"></script>
<script src="assets/vendor/swiper/swiper-bundle.min.js"></script>
<script src="assets/vendor/imagesloaded/imagesloaded.pkgd.min.js"></script>
<script src="assets/vendor/isotope-layout/isotope.pkgd.min.js"></script>
<script src="assets/vendor/glightbox/js/glightbox.min.js"></script>
<!-- Main JS File -->
<script src="assets/js/main.js"></script>
</body>
</html>

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

3850
assets/css/main.css Normal file

File diff suppressed because it is too large Load diff

BIN
assets/img/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
assets/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,41 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
assets/img/logo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 KiB

BIN
assets/img/profile/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/img/profile/me.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
assets/img/profile/me.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

785
assets/js/main.js Normal file
View file

@ -0,0 +1,785 @@
/**
* Template Name: FolioOne
* Template URL: https://bootstrapmade.com/folioone-bootstrap-portfolio-website-template/
* Updated: Aug 23 2025 with Bootstrap v5.3.7
* Author: BootstrapMade.com
* License: https://bootstrapmade.com/license/
*/
(function () {
"use strict";
/**
* Apply .scrolled class to the body as the page is scrolled down
*/
function toggleScrolled() {
const selectBody = document.querySelector('body');
const selectHeader = document.querySelector('#header');
if (!selectHeader.classList.contains('scroll-up-sticky') && !selectHeader.classList.contains('sticky-top') && !selectHeader.classList.contains('fixed-top')) return;
window.scrollY > 100 ? selectBody.classList.add('scrolled') : selectBody.classList.remove('scrolled');
}
document.addEventListener('scroll', toggleScrolled);
window.addEventListener('load', toggleScrolled);
/**
* Mobile nav toggle
*/
const mobileNavToggleBtn = document.querySelector('.mobile-nav-toggle');
function mobileNavToogle() {
document.querySelector('body').classList.toggle('mobile-nav-active');
mobileNavToggleBtn.classList.toggle('bi-list');
mobileNavToggleBtn.classList.toggle('bi-x');
}
if (mobileNavToggleBtn) {
mobileNavToggleBtn.addEventListener('click', mobileNavToogle);
}
/**
* Hide mobile nav on same-page/hash links
*/
document.querySelectorAll('#navmenu a').forEach(navmenu => {
navmenu.addEventListener('click', () => {
if (document.querySelector('.mobile-nav-active')) {
mobileNavToogle();
}
});
});
/**
* Toggle mobile nav dropdowns
*/
document.querySelectorAll('.navmenu .toggle-dropdown').forEach(navmenu => {
navmenu.addEventListener('click', function (e) {
e.preventDefault();
this.parentNode.classList.toggle('active');
this.parentNode.nextElementSibling.classList.toggle('dropdown-active');
e.stopImmediatePropagation();
});
});
/**
* Preloader
*/
const preloader = document.querySelector('#preloader');
if (preloader) {
window.addEventListener('load', () => {
preloader.remove();
});
}
/**
* Scroll top button
*/
let scrollTop = document.querySelector('.scroll-top');
function toggleScrollTop() {
if (scrollTop) {
window.scrollY > 100 ? scrollTop.classList.add('active') : scrollTop.classList.remove('active');
}
}
scrollTop.addEventListener('click', (e) => {
e.preventDefault();
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
window.addEventListener('load', toggleScrollTop);
document.addEventListener('scroll', toggleScrollTop);
/**
* Init typed.js
*/
const selectTyped = document.querySelector('.typed');
if (selectTyped && typeof Typed !== 'undefined') {
let typed_strings = selectTyped.getAttribute('data-typed-items');
typed_strings = typed_strings.split(',');
new Typed('.typed', {
strings: typed_strings,
loop: true,
typeSpeed: 100,
backSpeed: 50,
backDelay: 2000
});
}
/**
* Animate the skills items on reveal
*/
let skillsAnimation = document.querySelectorAll('.skills-animation');
if (skillsAnimation.length > 0 && typeof Waypoint !== 'undefined') {
skillsAnimation.forEach((item) => {
new Waypoint({
element: item,
offset: '80%',
handler: function (direction) {
let progress = item.querySelectorAll('.progress .progress-bar');
progress.forEach(el => {
el.style.width = el.getAttribute('aria-valuenow') + '%';
});
}
});
});
}
/**
* Initiate Pure Counter
*/
if (typeof PureCounter !== 'undefined') {
new PureCounter();
}
/**
* Init swiper sliders
*/
function initSwiper() {
if (typeof Swiper !== 'undefined') {
document.querySelectorAll(".init-swiper").forEach(function (swiperElement) {
let config = JSON.parse(
swiperElement.querySelector(".swiper-config").innerHTML.trim()
);
if (swiperElement.classList.contains("swiper-tab")) {
initSwiperWithCustomPagination(swiperElement, config);
} else {
new Swiper(swiperElement, config);
}
});
}
}
window.addEventListener("load", initSwiper);
/**
* Init isotope layout and filters
*/
if (typeof Isotope !== 'undefined' && typeof imagesLoaded !== 'undefined') {
document.querySelectorAll('.isotope-layout').forEach(function (isotopeItem) {
let layout = isotopeItem.getAttribute('data-layout') ?? 'masonry';
let filter = isotopeItem.getAttribute('data-default-filter') ?? '*';
let sort = isotopeItem.getAttribute('data-sort') ?? 'original-order';
let initIsotope;
imagesLoaded(isotopeItem.querySelector('.isotope-container'), function () {
initIsotope = new Isotope(isotopeItem.querySelector('.isotope-container'), {
itemSelector: '.isotope-item',
layoutMode: layout,
filter: filter,
sortBy: sort
});
});
isotopeItem.querySelectorAll('.isotope-filters li').forEach(function (filters) {
filters.addEventListener('click', function () {
isotopeItem.querySelector('.isotope-filters .filter-active').classList.remove('filter-active');
this.classList.add('filter-active');
initIsotope.arrange({
filter: this.getAttribute('data-filter')
});
if (typeof aosInit === 'function') {
aosInit();
}
}, false);
});
});
}
/**
* Initiate glightbox
*/
if (typeof GLightbox !== 'undefined') {
const glightbox = GLightbox({
selector: '.glightbox'
});
}
})();
/**
* UX Enhancements - Custom Cursor (Optimized)
*/
(function () {
// Only enable on non-touch devices and desktops (not mobile)
if (window.matchMedia("(hover: hover) and (pointer: fine)").matches && window.innerWidth >= 1024) {
window.addEventListener('load', function () {
const cursor = document.createElement('div');
cursor.className = 'custom-cursor';
const cursorFollower = document.createElement('div');
cursorFollower.className = 'custom-cursor-follower';
document.body.appendChild(cursor);
document.body.appendChild(cursorFollower);
let mouseX = 0, mouseY = 0;
let followerX = 0, followerY = 0;
// Use transform for better performance
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
cursor.style.transform = `translate(${mouseX}px, ${mouseY}px)`;
});
// Smooth follower animation with requestAnimationFrame
function animateFollower() {
const distX = mouseX - followerX;
const distY = mouseY - followerY;
followerX += distX * 0.15; // Augmenté de 0.1 à 0.15 pour plus de réactivité
followerY += distY * 0.15;
cursorFollower.style.transform = `translate(${followerX}px, ${followerY}px)`;
requestAnimationFrame(animateFollower);
}
animateFollower();
// Add hover effects for interactive elements (avec délégation d'événements)
document.addEventListener('mouseenter', (e) => {
if (e.target.matches('a, button, .btn, input, textarea, select')) {
cursor.classList.add('hover');
cursorFollower.classList.add('hover');
}
}, true);
document.addEventListener('mouseleave', (e) => {
if (e.target.matches('a, button, .btn, input, textarea, select')) {
cursor.classList.remove('hover');
cursorFollower.classList.remove('hover');
}
}, true);
});
}
})();
/**
* UX Enhancements - Scroll Progress Indicator (Optimized with RAF)
*/
(function () {
const progressBar = document.createElement('div');
progressBar.className = 'scroll-progress';
document.body.appendChild(progressBar);
let ticking = false;
function updateScrollProgress() {
const windowHeight = window.innerHeight;
const documentHeight = document.documentElement.scrollHeight;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollPercent = Math.min((scrollTop / (documentHeight - windowHeight)) * 100, 100);
progressBar.style.width = scrollPercent + '%';
ticking = false;
}
window.addEventListener('scroll', function () {
if (!ticking) {
window.requestAnimationFrame(updateScrollProgress);
ticking = true;
}
}, { passive: true });
window.addEventListener('load', updateScrollProgress);
})();
/**
* UX Enhancements - Text Reveal on Scroll (Optimized with RAF)
*/
(function () {
window.addEventListener('load', function () {
const revealElements = document.querySelectorAll('.reveal-text');
if (revealElements.length === 0) return;
let ticking = false;
function checkReveal() {
revealElements.forEach(el => {
if (!el.classList.contains('revealed')) {
const elementTop = el.getBoundingClientRect().top;
const elementVisible = 150;
if (elementTop < window.innerHeight - elementVisible) {
el.classList.add('revealed');
}
}
});
ticking = false;
}
window.addEventListener('scroll', function () {
if (!ticking) {
window.requestAnimationFrame(checkReveal);
ticking = true;
}
}, { passive: true });
checkReveal(); // Initial check
});
})();
/**
* UX Enhancements - Smooth Parallax Effect (Optimized with RAF)
*/
(function () {
window.addEventListener('load', function () {
const parallaxElements = document.querySelectorAll('.parallax-bg');
if (parallaxElements.length === 0) return;
let ticking = false;
function updateParallax() {
const scrolled = window.pageYOffset;
parallaxElements.forEach(el => {
const rate = scrolled * 0.3;
el.style.transform = `translate3d(0, ${rate}px, 0)`;
});
ticking = false;
}
window.addEventListener('scroll', function () {
if (!ticking) {
window.requestAnimationFrame(updateParallax);
ticking = true;
}
}, { passive: true });
});
})();
/**
* UX Enhancements - Enhanced Card Tilt Effect (Subtle 3D) - Optimized
*/
(function () {
window.addEventListener('load', function () {
const tiltElements = document.querySelectorAll('.service-item, .portfolio-item');
if (tiltElements.length === 0) return; // Exit if no elements
tiltElements.forEach(el => {
let ticking = false;
el.addEventListener('mousemove', (e) => {
if (!ticking) {
window.requestAnimationFrame(() => {
const rect = el.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * 2; // Réduit à 2 pour plus de subtilité
const rotateY = ((centerX - x) / centerX) * 2;
// Préserve le translateY existant et ajoute la rotation 3D
const baseTranslateY = el.classList.contains('service-item') ? -5 : -10;
el.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(${baseTranslateY}px)`;
ticking = false;
});
ticking = true;
}
});
el.addEventListener('mouseleave', () => {
// Remet la transformation de base au survol (définie dans le CSS)
el.style.transform = '';
});
});
});
})();
/**
* UX Enhancements - Improved AOS Configuration (Optimized for Performance)
*/
function aosInit() {
if (typeof AOS !== 'undefined') {
AOS.init({
duration: 400, // Encore plus rapide pour éviter le "lag" visuel
easing: 'ease-out-cubic', // Easing plus dynamique
once: true,
mirror: false,
offset: 50, // Déclenchement très tôt
delay: 0,
anchorPlacement: 'top-bottom',
disable: function () {
// Désactiver sur mobile pour meilleures performances
return window.innerWidth < 768;
}
});
}
}
window.addEventListener('load', aosInit);
/**
* UX Enhancements - Smooth Scroll Enhancement (Optimized)
*/
window.addEventListener('load', function () {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
if (href !== '#' && href !== '#scroll-top') {
const target = document.querySelector(href);
if (target) {
e.preventDefault();
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
});
});
});
/**
* UX Enhancements - Add Loading States to Buttons (Optimized)
*/
/**
* UX Enhancements - Add Loading States to Buttons (Optimized)
* REMOVED: Interferes with Formspree submission
*/
// window.addEventListener('load', function () {
// const submitButtons = document.querySelectorAll('button[type="submit"], .btn[type="submit"]');
//
// submitButtons.forEach(btn => {
// btn.addEventListener('click', function (e) {
// if (this.form && this.form.checkValidity()) {
// const originalText = this.innerHTML;
// this.innerHTML = '<i class="bi bi-hourglass-split"></i> Envoi en cours...';
// this.disabled = true;
//
// // Reset after 3 seconds (adjust based on your needs)
// setTimeout(() => {
// this.innerHTML = originalText;
// this.disabled = false;
// }, 3000);
// }
// });
// });
// });
/**
* UX Enhancements - Ambient Light Effects with Parallax
*/
(function () {
// Only enable on desktop for performance
if (window.innerWidth >= 768) {
window.addEventListener('load', function () {
// Create ambient lights container
const ambientLights = document.createElement('div');
ambientLights.className = 'ambient-lights';
document.body.insertBefore(ambientLights, document.body.firstChild);
// Create light orbs
for (let i = 1; i <= 4; i++) {
const orb = document.createElement('div');
orb.className = `light-orb light-orb-${i}`;
ambientLights.appendChild(orb);
}
// Create light rays
for (let i = 1; i <= 3; i++) {
const ray = document.createElement('div');
ray.className = `light-ray light-ray-${i}`;
ambientLights.appendChild(ray);
}
// Create light particles (random positions)
for (let i = 0; i < 20; i++) {
const particle = document.createElement('div');
particle.className = 'light-particle';
particle.style.top = Math.random() * 100 + '%';
particle.style.left = Math.random() * 100 + '%';
particle.style.animationDelay = Math.random() * 3 + 's';
ambientLights.appendChild(particle);
}
// Create gradient spotlights
for (let i = 1; i <= 2; i++) {
const spotlight = document.createElement('div');
spotlight.className = `gradient-spotlight gradient-spotlight-${i}`;
ambientLights.appendChild(spotlight);
}
// Parallax effect on scroll (optimized with RAF and throttling)
const orbs = document.querySelectorAll('.light-orb');
const rays = document.querySelectorAll('.light-ray');
const spotlights = document.querySelectorAll('.gradient-spotlight');
let ticking = false;
function updateLightParallax() {
const scrollY = window.pageYOffset;
// Orbs: slow parallax (different speeds)
orbs.forEach((orb, index) => {
const speed = 0.1 + (index * 0.05); // Different speed for each orb
const yPos = scrollY * speed;
orb.style.transform = `translateY(${yPos}px)`;
});
// Rays: medium parallax
rays.forEach((ray, index) => {
const speed = 0.15 + (index * 0.03);
const yPos = scrollY * speed;
const rotation = 15 + (index * 5);
ray.style.transform = `translateY(${yPos}px) rotate(${rotation}deg)`;
});
// Spotlights: faster parallax
spotlights.forEach((spotlight, index) => {
const speed = 0.25 + (index * 0.1);
const yPos = scrollY * speed;
if (index === 0) {
spotlight.style.transform = `translate(-50%, ${yPos}px)`;
} else {
spotlight.style.transform = `translateY(${yPos}px)`;
}
});
ticking = false;
}
window.addEventListener('scroll', function () {
if (!ticking) {
window.requestAnimationFrame(updateLightParallax);
ticking = true;
}
}, { passive: true });
// Initial position
updateLightParallax();
});
}
})();
/* Matrix-like background animation confined to header canvases (slower) */
(function () {
// Only run on larger screens to avoid perf issues on mobile
function shouldEnableMatrix() {
// Force-enable on Services page regardless of viewport width
if (document.body && document.body.classList.contains('services-page')) {
return true;
}
// Otherwise keep default threshold to avoid perf issues on small screens
return window.innerWidth >= 900;
}
const canvases = Array.from(document.querySelectorAll('.matrix-bg-header'));
if (!canvases.length) return;
const instances = [];
const chars = '01<>/{}[]()\u25A0\u25A1'.split('');
function createInstance(canvas) {
const ctx = canvas.getContext('2d');
let width = 0;
let height = 0;
let columns = [];
let animationId = null;
function init() {
const dpr = Math.max(1, window.devicePixelRatio || 1);
const rect = canvas.parentElement.getBoundingClientRect();
width = canvas.width = Math.floor(rect.width * dpr);
// limit canvas height to header height
height = canvas.height = Math.floor(rect.height * dpr);
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
// slightly larger font for clarity, but scaled by DPR
const fontSize = Math.max(10, Math.floor((rect.width / 160) * dpr));
ctx.font = fontSize + 'px monospace';
ctx.textBaseline = 'top';
const columnCount = Math.ceil(width / fontSize);
columns = new Array(columnCount).fill(0).map(() => ({ y: Math.random() * -height }));
return fontSize;
}
function draw() {
// A darker translucent fill to keep effect subtle on header
ctx.fillStyle = 'rgba(16,26,32,0.35)';
ctx.fillRect(0, 0, width, height);
const computed = getComputedStyle(document.documentElement).getPropertyValue('--matrix-pale-blue').trim() || '#8fcbe9';
ctx.fillStyle = computed;
// Slightly increase text opacity to make the falling characters a bit more visible
// Use save/restore so only the text rendering is affected (background fill stays same)
const textAlpha = 0.78; // small increase from default for better visibility
ctx.save();
ctx.globalAlpha = textAlpha;
const fontSizeMatch = ctx.font.match(/(\d+)px/);
const fontSize = fontSizeMatch ? parseInt(fontSizeMatch[1], 10) : 12;
// slower motion: smaller increments
for (let i = 0; i < columns.length; i += 1) {
const col = columns[i];
// render only rarely to greatly reduce density (slower effect)
if (Math.random() < 0.88) continue;
const text = chars[Math.floor(Math.random() * chars.length)];
const x = i * fontSize;
ctx.fillText(text, x, col.y);
// much slower falling speed and subtle randomness
col.y += (fontSize * 0.18) + Math.random() * (fontSize * 0.08);
if (col.y > height + Math.random() * 200) {
col.y = Math.random() * -height * 0.6;
}
}
// restore alpha after drawing text so other canvas ops are unaffected
ctx.restore();
animationId = requestAnimationFrame(draw);
}
function start() {
cancelAnimationFrame(animationId);
init();
draw();
}
function stop() {
if (animationId) cancelAnimationFrame(animationId);
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
return { start, stop, init };
}
canvases.forEach(c => instances.push(createInstance(c)));
function startAll() {
if (!shouldEnableMatrix()) return;
console.debug('[matrix] startAll: starting matrix instances');
instances.forEach(i => i.start());
}
function stopAll() {
console.debug('[matrix] stopAll: stopping matrix instances');
instances.forEach(i => i.stop());
}
// Pause on tab hidden
document.addEventListener('visibilitychange', function () {
if (document.hidden) stopAll(); else startAll();
});
let resizeTimer = null;
window.addEventListener('resize', function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
if (shouldEnableMatrix()) startAll(); else stopAll();
}, 300);
});
window.addEventListener('load', function () {
if (shouldEnableMatrix()) startAll();
else console.debug('[matrix] load: matrix disabled by shouldEnableMatrix() (width=' + window.innerWidth + ')');
});
})();
/**
* Light/Dark Mode Toggle
*/
(function () {
const body = document.body;
const toggleBtn = document.createElement('button');
toggleBtn.className = 'theme-toggle-btn';
toggleBtn.innerHTML = '<i class="bi bi-moon-stars-fill"></i>';
toggleBtn.setAttribute('aria-label', 'Toggle theme');
// Style the button (fixed position)
Object.assign(toggleBtn.style, {
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: '9999',
width: '50px',
height: '50px',
borderRadius: '50%',
border: 'none',
backgroundColor: 'var(--accent-color)',
color: '#fff',
fontSize: '1.2rem',
cursor: 'pointer',
boxShadow: '0 4px 15px rgba(0,0,0,0.3)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transition: 'all 0.3s ease'
});
// Hover effect
toggleBtn.addEventListener('mouseenter', () => {
toggleBtn.style.transform = 'scale(1.1)';
});
toggleBtn.addEventListener('mouseleave', () => {
toggleBtn.style.transform = 'scale(1)';
});
document.body.appendChild(toggleBtn);
function setLightMode(isLight) {
if (isLight) {
body.classList.add('light-mode');
toggleBtn.innerHTML = '<i class="bi bi-sun-fill"></i>';
} else {
body.classList.remove('light-mode');
toggleBtn.innerHTML = '<i class="bi bi-moon-stars-fill"></i>';
}
}
// Check preference or time
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
setLightMode(savedTheme === 'light');
} else {
const hour = new Date().getHours();
// Light mode between 00:00 and 17:00
if (hour < 17) {
setLightMode(true);
}
}
// Toggle event
toggleBtn.addEventListener('click', () => {
const isLight = body.classList.contains('light-mode');
setLightMode(!isLight);
localStorage.setItem('theme', !isLight ? 'light' : 'dark');
});
/**
* UX Enhancements - Smooth Page Transitions
*/
document.addEventListener('DOMContentLoaded', () => {
const links = document.querySelectorAll('a:not([href^="#"]):not([target="_blank"]):not([href^="mailto:"]):not([href^="tel:"])');
links.forEach(link => {
link.addEventListener('click', (e) => {
const href = link.getAttribute('href');
// Check if it's a valid internal link
if (href && !href.startsWith('#') && !href.startsWith('javascript:')) {
e.preventDefault();
document.body.classList.add('fade-out');
setTimeout(() => {
window.location.href = href;
}, 300); // Match CSS transition duration
}
});
});
});
})();

File diff suppressed because one or more lines are too long

2
assets/scss/Readme.txt Normal file
View file

@ -0,0 +1,2 @@
The .scss (Sass) files are only available in the pro version.
You can buy it from: https://bootstrapmade.com/folioone-bootstrap-portfolio-website-template/

BIN
assets/vendor/.DS_Store vendored Normal file

Binary file not shown.

614
assets/vendor/aos/aos.cjs.js vendored Normal file
View file

@ -0,0 +1,614 @@
'use strict';
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var throttle = _interopDefault(require('lodash.throttle'));
var debounce = _interopDefault(require('lodash.debounce'));
var callback = function callback() {};
function containsAOSNode(nodes) {
var i = void 0,
currentNode = void 0,
result = void 0;
for (i = 0; i < nodes.length; i += 1) {
currentNode = nodes[i];
if (currentNode.dataset && currentNode.dataset.aos) {
return true;
}
result = currentNode.children && containsAOSNode(currentNode.children);
if (result) {
return true;
}
}
return false;
}
function check(mutations) {
if (!mutations) return;
mutations.forEach(function (mutation) {
var addedNodes = Array.prototype.slice.call(mutation.addedNodes);
var removedNodes = Array.prototype.slice.call(mutation.removedNodes);
var allNodes = addedNodes.concat(removedNodes);
if (containsAOSNode(allNodes)) {
return callback();
}
});
}
function getMutationObserver() {
return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
}
function isSupported() {
return !!getMutationObserver();
}
function ready(selector, fn) {
var doc = window.document;
var MutationObserver = getMutationObserver();
var observer = new MutationObserver(check);
callback = fn;
observer.observe(doc.documentElement, {
childList: true,
subtree: true,
removedNodes: true
});
}
var observer = { isSupported: isSupported, ready: ready };
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
/**
* Device detector
*/
var fullNameRe = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i;
var prefixRe = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i;
var fullNameMobileRe = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i;
var prefixMobileRe = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i;
function ua() {
return navigator.userAgent || navigator.vendor || window.opera || '';
}
var Detector = function () {
function Detector() {
classCallCheck(this, Detector);
}
createClass(Detector, [{
key: 'phone',
value: function phone() {
var a = ua();
return !!(fullNameRe.test(a) || prefixRe.test(a.substr(0, 4)));
}
}, {
key: 'mobile',
value: function mobile() {
var a = ua();
return !!(fullNameMobileRe.test(a) || prefixMobileRe.test(a.substr(0, 4)));
}
}, {
key: 'tablet',
value: function tablet() {
return this.mobile() && !this.phone();
}
// http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c
}, {
key: 'ie11',
value: function ie11() {
return '-ms-scroll-limit' in document.documentElement.style && '-ms-ime-align' in document.documentElement.style;
}
}]);
return Detector;
}();
var detect = new Detector();
/**
* Adds multiple classes on node
* @param {DOMNode} node
* @param {array} classes
*/
var addClasses = function addClasses(node, classes) {
return classes && classes.forEach(function (className) {
return node.classList.add(className);
});
};
/**
* Removes multiple classes from node
* @param {DOMNode} node
* @param {array} classes
*/
var removeClasses = function removeClasses(node, classes) {
return classes && classes.forEach(function (className) {
return node.classList.remove(className);
});
};
var fireEvent = function fireEvent(eventName, data) {
var customEvent = void 0;
if (detect.ie11()) {
customEvent = document.createEvent('CustomEvent');
customEvent.initCustomEvent(eventName, true, true, { detail: data });
} else {
customEvent = new CustomEvent(eventName, {
detail: data
});
}
return document.dispatchEvent(customEvent);
};
/**
* Set or remove aos-animate class
* @param {node} el element
* @param {int} top scrolled distance
*/
var applyClasses = function applyClasses(el, top) {
var options = el.options,
position = el.position,
node = el.node,
data = el.data;
var hide = function hide() {
if (!el.animated) return;
removeClasses(node, options.animatedClassNames);
fireEvent('aos:out', node);
if (el.options.id) {
fireEvent('aos:in:' + el.options.id, node);
}
el.animated = false;
};
var show = function show() {
if (el.animated) return;
addClasses(node, options.animatedClassNames);
fireEvent('aos:in', node);
if (el.options.id) {
fireEvent('aos:in:' + el.options.id, node);
}
el.animated = true;
};
if (options.mirror && top >= position.out && !options.once) {
hide();
} else if (top >= position.in) {
show();
} else if (el.animated && !options.once) {
hide();
}
};
/**
* Scroll logic - add or remove 'aos-animate' class on scroll
*
* @param {array} $elements array of elements nodes
* @return {void}
*/
var handleScroll = function handleScroll($elements) {
return $elements.forEach(function (el, i) {
return applyClasses(el, window.pageYOffset);
});
};
/**
* Get offset of DOM element
* like there were no transforms applied on it
*
* @param {Node} el [DOM element]
* @return {Object} [top and left offset]
*/
var offset = function offset(el) {
var _x = 0;
var _y = 0;
while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
_x += el.offsetLeft - (el.tagName != 'BODY' ? el.scrollLeft : 0);
_y += el.offsetTop - (el.tagName != 'BODY' ? el.scrollTop : 0);
el = el.offsetParent;
}
return {
top: _y,
left: _x
};
};
/**
* Get inline option with a fallback.
*
* @param {Node} el [Dom element]
* @param {String} key [Option key]
* @param {String} fallback [Default (fallback) value]
* @return {Mixed} [Option set with inline attributes or fallback value if not set]
*/
var getInlineOption = (function (el, key, fallback) {
var attr = el.getAttribute('data-aos-' + key);
if (typeof attr !== 'undefined') {
if (attr === 'true') {
return true;
} else if (attr === 'false') {
return false;
}
}
return attr || fallback;
});
/**
* Calculate offset
* basing on element's settings like:
* - anchor
* - offset
*
* @param {Node} el [Dom element]
* @return {Integer} [Final offset that will be used to trigger animation in good position]
*/
var getPositionIn = function getPositionIn(el, defaultOffset, defaultAnchorPlacement) {
var windowHeight = window.innerHeight;
var anchor = getInlineOption(el, 'anchor');
var inlineAnchorPlacement = getInlineOption(el, 'anchor-placement');
var additionalOffset = Number(getInlineOption(el, 'offset', inlineAnchorPlacement ? 0 : defaultOffset));
var anchorPlacement = inlineAnchorPlacement || defaultAnchorPlacement;
var finalEl = el;
if (anchor && document.querySelectorAll(anchor)) {
finalEl = document.querySelectorAll(anchor)[0];
}
var triggerPoint = offset(finalEl).top - windowHeight;
switch (anchorPlacement) {
case 'top-bottom':
// Default offset
break;
case 'center-bottom':
triggerPoint += finalEl.offsetHeight / 2;
break;
case 'bottom-bottom':
triggerPoint += finalEl.offsetHeight;
break;
case 'top-center':
triggerPoint += windowHeight / 2;
break;
case 'center-center':
triggerPoint += windowHeight / 2 + finalEl.offsetHeight / 2;
break;
case 'bottom-center':
triggerPoint += windowHeight / 2 + finalEl.offsetHeight;
break;
case 'top-top':
triggerPoint += windowHeight;
break;
case 'bottom-top':
triggerPoint += windowHeight + finalEl.offsetHeight;
break;
case 'center-top':
triggerPoint += windowHeight + finalEl.offsetHeight / 2;
break;
}
return triggerPoint + additionalOffset;
};
var getPositionOut = function getPositionOut(el, defaultOffset) {
var windowHeight = window.innerHeight;
var anchor = getInlineOption(el, 'anchor');
var additionalOffset = getInlineOption(el, 'offset', defaultOffset);
var finalEl = el;
if (anchor && document.querySelectorAll(anchor)) {
finalEl = document.querySelectorAll(anchor)[0];
}
var elementOffsetTop = offset(finalEl).top;
return elementOffsetTop + finalEl.offsetHeight - additionalOffset;
};
/* Clearing variables */
var prepare = function prepare($elements, options) {
$elements.forEach(function (el, i) {
var mirror = getInlineOption(el.node, 'mirror', options.mirror);
var once = getInlineOption(el.node, 'once', options.once);
var id = getInlineOption(el.node, 'id');
var customClassNames = options.useClassNames && el.node.getAttribute('data-aos');
var animatedClassNames = [options.animatedClassName].concat(customClassNames ? customClassNames.split(' ') : []).filter(function (className) {
return typeof className === 'string';
});
if (options.initClassName) {
el.node.classList.add(options.initClassName);
}
el.position = {
in: getPositionIn(el.node, options.offset, options.anchorPlacement),
out: mirror && getPositionOut(el.node, options.offset)
};
el.options = {
once: once,
mirror: mirror,
animatedClassNames: animatedClassNames,
id: id
};
});
return $elements;
};
/**
* Generate initial array with elements as objects
* This array will be extended later with elements attributes values
* like 'position'
*/
var elements = (function () {
var elements = document.querySelectorAll('[data-aos]');
return Array.prototype.map.call(elements, function (node) {
return { node: node };
});
});
/**
* *******************************************************
* AOS (Animate on scroll) - wowjs alternative
* made to animate elements on scroll in both directions
* *******************************************************
*/
/**
* Private variables
*/
var $aosElements = [];
var initialized = false;
/**
* Default options
*/
var options = {
offset: 120,
delay: 0,
easing: 'ease',
duration: 400,
disable: false,
once: false,
mirror: false,
anchorPlacement: 'top-bottom',
startEvent: 'DOMContentLoaded',
animatedClassName: 'aos-animate',
initClassName: 'aos-init',
useClassNames: false,
disableMutationObserver: false,
throttleDelay: 99,
debounceDelay: 50
};
// Detect not supported browsers (<=IE9)
// http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
var isBrowserNotSupported = function isBrowserNotSupported() {
return document.all && !window.atob;
};
var initializeScroll = function initializeScroll() {
// Extend elements objects in $aosElements with their positions
$aosElements = prepare($aosElements, options);
// Perform scroll event, to refresh view and show/hide elements
handleScroll($aosElements);
/**
* Handle scroll event to animate elements on scroll
*/
window.addEventListener('scroll', throttle(function () {
handleScroll($aosElements, options.once);
}, options.throttleDelay));
return $aosElements;
};
/**
* Refresh AOS
*/
var refresh = function refresh() {
var initialize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Allow refresh only when it was first initialized on startEvent
if (initialize) initialized = true;
if (initialized) initializeScroll();
};
/**
* Hard refresh
* create array with new elements and trigger refresh
*/
var refreshHard = function refreshHard() {
$aosElements = elements();
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
refresh();
};
/**
* Disable AOS
* Remove all attributes to reset applied styles
*/
var disable = function disable() {
$aosElements.forEach(function (el, i) {
el.node.removeAttribute('data-aos');
el.node.removeAttribute('data-aos-easing');
el.node.removeAttribute('data-aos-duration');
el.node.removeAttribute('data-aos-delay');
if (options.initClassName) {
el.node.classList.remove(options.initClassName);
}
if (options.animatedClassName) {
el.node.classList.remove(options.animatedClassName);
}
});
};
/**
* Check if AOS should be disabled based on provided setting
*/
var isDisabled = function isDisabled(optionDisable) {
return optionDisable === true || optionDisable === 'mobile' && detect.mobile() || optionDisable === 'phone' && detect.phone() || optionDisable === 'tablet' && detect.tablet() || typeof optionDisable === 'function' && optionDisable() === true;
};
/**
* Initializing AOS
* - Create options merging defaults with user defined options
* - Set attributes on <body> as global setting - css relies on it
* - Attach preparing elements to options.startEvent,
* window resize and orientation change
* - Attach function that handle scroll and everything connected to it
* to window scroll event and fire once document is ready to set initial state
*/
var init = function init(settings) {
options = _extends(options, settings);
// Create initial array with elements -> to be fullfilled later with prepare()
$aosElements = elements();
/**
* Disable mutation observing if not supported
*/
if (!options.disableMutationObserver && !observer.isSupported()) {
console.info('\n aos: MutationObserver is not supported on this browser,\n code mutations observing has been disabled.\n You may have to call "refreshHard()" by yourself.\n ');
options.disableMutationObserver = true;
}
/**
* Observe [aos] elements
* If something is loaded by AJAX
* it'll refresh plugin automatically
*/
if (!options.disableMutationObserver) {
observer.ready('[data-aos]', refreshHard);
}
/**
* Don't init plugin if option `disable` is set
* or when browser is not supported
*/
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
/**
* Set global settings on body, based on options
* so CSS can use it
*/
document.querySelector('body').setAttribute('data-aos-easing', options.easing);
document.querySelector('body').setAttribute('data-aos-duration', options.duration);
document.querySelector('body').setAttribute('data-aos-delay', options.delay);
/**
* Handle initializing
*/
if (['DOMContentLoaded', 'load'].indexOf(options.startEvent) === -1) {
// Listen to options.startEvent and initialize AOS
document.addEventListener(options.startEvent, function () {
refresh(true);
});
} else {
window.addEventListener('load', function () {
refresh(true);
});
}
if (options.startEvent === 'DOMContentLoaded' && ['complete', 'interactive'].indexOf(document.readyState) > -1) {
// Initialize AOS if default startEvent was already fired
refresh(true);
}
/**
* Refresh plugin on window resize or orientation change
*/
window.addEventListener('resize', debounce(refresh, options.debounceDelay, true));
window.addEventListener('orientationchange', debounce(refresh, options.debounceDelay, true));
return $aosElements;
};
/**
* Export Public API
*/
var aos = {
init: init,
refresh: refresh,
refreshHard: refreshHard
};
module.exports = aos;

1
assets/vendor/aos/aos.css vendored Normal file

File diff suppressed because one or more lines are too long

610
assets/vendor/aos/aos.esm.js vendored Normal file
View file

@ -0,0 +1,610 @@
import throttle from 'lodash.throttle';
import debounce from 'lodash.debounce';
var callback = function callback() {};
function containsAOSNode(nodes) {
var i = void 0,
currentNode = void 0,
result = void 0;
for (i = 0; i < nodes.length; i += 1) {
currentNode = nodes[i];
if (currentNode.dataset && currentNode.dataset.aos) {
return true;
}
result = currentNode.children && containsAOSNode(currentNode.children);
if (result) {
return true;
}
}
return false;
}
function check(mutations) {
if (!mutations) return;
mutations.forEach(function (mutation) {
var addedNodes = Array.prototype.slice.call(mutation.addedNodes);
var removedNodes = Array.prototype.slice.call(mutation.removedNodes);
var allNodes = addedNodes.concat(removedNodes);
if (containsAOSNode(allNodes)) {
return callback();
}
});
}
function getMutationObserver() {
return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
}
function isSupported() {
return !!getMutationObserver();
}
function ready(selector, fn) {
var doc = window.document;
var MutationObserver = getMutationObserver();
var observer = new MutationObserver(check);
callback = fn;
observer.observe(doc.documentElement, {
childList: true,
subtree: true,
removedNodes: true
});
}
var observer = { isSupported: isSupported, ready: ready };
var classCallCheck = function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
var createClass = function () {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
}();
var _extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
/**
* Device detector
*/
var fullNameRe = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i;
var prefixRe = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i;
var fullNameMobileRe = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i;
var prefixMobileRe = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i;
function ua() {
return navigator.userAgent || navigator.vendor || window.opera || '';
}
var Detector = function () {
function Detector() {
classCallCheck(this, Detector);
}
createClass(Detector, [{
key: 'phone',
value: function phone() {
var a = ua();
return !!(fullNameRe.test(a) || prefixRe.test(a.substr(0, 4)));
}
}, {
key: 'mobile',
value: function mobile() {
var a = ua();
return !!(fullNameMobileRe.test(a) || prefixMobileRe.test(a.substr(0, 4)));
}
}, {
key: 'tablet',
value: function tablet() {
return this.mobile() && !this.phone();
}
// http://browserhacks.com/#hack-acea075d0ac6954f275a70023906050c
}, {
key: 'ie11',
value: function ie11() {
return '-ms-scroll-limit' in document.documentElement.style && '-ms-ime-align' in document.documentElement.style;
}
}]);
return Detector;
}();
var detect = new Detector();
/**
* Adds multiple classes on node
* @param {DOMNode} node
* @param {array} classes
*/
var addClasses = function addClasses(node, classes) {
return classes && classes.forEach(function (className) {
return node.classList.add(className);
});
};
/**
* Removes multiple classes from node
* @param {DOMNode} node
* @param {array} classes
*/
var removeClasses = function removeClasses(node, classes) {
return classes && classes.forEach(function (className) {
return node.classList.remove(className);
});
};
var fireEvent = function fireEvent(eventName, data) {
var customEvent = void 0;
if (detect.ie11()) {
customEvent = document.createEvent('CustomEvent');
customEvent.initCustomEvent(eventName, true, true, { detail: data });
} else {
customEvent = new CustomEvent(eventName, {
detail: data
});
}
return document.dispatchEvent(customEvent);
};
/**
* Set or remove aos-animate class
* @param {node} el element
* @param {int} top scrolled distance
*/
var applyClasses = function applyClasses(el, top) {
var options = el.options,
position = el.position,
node = el.node,
data = el.data;
var hide = function hide() {
if (!el.animated) return;
removeClasses(node, options.animatedClassNames);
fireEvent('aos:out', node);
if (el.options.id) {
fireEvent('aos:in:' + el.options.id, node);
}
el.animated = false;
};
var show = function show() {
if (el.animated) return;
addClasses(node, options.animatedClassNames);
fireEvent('aos:in', node);
if (el.options.id) {
fireEvent('aos:in:' + el.options.id, node);
}
el.animated = true;
};
if (options.mirror && top >= position.out && !options.once) {
hide();
} else if (top >= position.in) {
show();
} else if (el.animated && !options.once) {
hide();
}
};
/**
* Scroll logic - add or remove 'aos-animate' class on scroll
*
* @param {array} $elements array of elements nodes
* @return {void}
*/
var handleScroll = function handleScroll($elements) {
return $elements.forEach(function (el, i) {
return applyClasses(el, window.pageYOffset);
});
};
/**
* Get offset of DOM element
* like there were no transforms applied on it
*
* @param {Node} el [DOM element]
* @return {Object} [top and left offset]
*/
var offset = function offset(el) {
var _x = 0;
var _y = 0;
while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
_x += el.offsetLeft - (el.tagName != 'BODY' ? el.scrollLeft : 0);
_y += el.offsetTop - (el.tagName != 'BODY' ? el.scrollTop : 0);
el = el.offsetParent;
}
return {
top: _y,
left: _x
};
};
/**
* Get inline option with a fallback.
*
* @param {Node} el [Dom element]
* @param {String} key [Option key]
* @param {String} fallback [Default (fallback) value]
* @return {Mixed} [Option set with inline attributes or fallback value if not set]
*/
var getInlineOption = (function (el, key, fallback) {
var attr = el.getAttribute('data-aos-' + key);
if (typeof attr !== 'undefined') {
if (attr === 'true') {
return true;
} else if (attr === 'false') {
return false;
}
}
return attr || fallback;
});
/**
* Calculate offset
* basing on element's settings like:
* - anchor
* - offset
*
* @param {Node} el [Dom element]
* @return {Integer} [Final offset that will be used to trigger animation in good position]
*/
var getPositionIn = function getPositionIn(el, defaultOffset, defaultAnchorPlacement) {
var windowHeight = window.innerHeight;
var anchor = getInlineOption(el, 'anchor');
var inlineAnchorPlacement = getInlineOption(el, 'anchor-placement');
var additionalOffset = Number(getInlineOption(el, 'offset', inlineAnchorPlacement ? 0 : defaultOffset));
var anchorPlacement = inlineAnchorPlacement || defaultAnchorPlacement;
var finalEl = el;
if (anchor && document.querySelectorAll(anchor)) {
finalEl = document.querySelectorAll(anchor)[0];
}
var triggerPoint = offset(finalEl).top - windowHeight;
switch (anchorPlacement) {
case 'top-bottom':
// Default offset
break;
case 'center-bottom':
triggerPoint += finalEl.offsetHeight / 2;
break;
case 'bottom-bottom':
triggerPoint += finalEl.offsetHeight;
break;
case 'top-center':
triggerPoint += windowHeight / 2;
break;
case 'center-center':
triggerPoint += windowHeight / 2 + finalEl.offsetHeight / 2;
break;
case 'bottom-center':
triggerPoint += windowHeight / 2 + finalEl.offsetHeight;
break;
case 'top-top':
triggerPoint += windowHeight;
break;
case 'bottom-top':
triggerPoint += windowHeight + finalEl.offsetHeight;
break;
case 'center-top':
triggerPoint += windowHeight + finalEl.offsetHeight / 2;
break;
}
return triggerPoint + additionalOffset;
};
var getPositionOut = function getPositionOut(el, defaultOffset) {
var windowHeight = window.innerHeight;
var anchor = getInlineOption(el, 'anchor');
var additionalOffset = getInlineOption(el, 'offset', defaultOffset);
var finalEl = el;
if (anchor && document.querySelectorAll(anchor)) {
finalEl = document.querySelectorAll(anchor)[0];
}
var elementOffsetTop = offset(finalEl).top;
return elementOffsetTop + finalEl.offsetHeight - additionalOffset;
};
/* Clearing variables */
var prepare = function prepare($elements, options) {
$elements.forEach(function (el, i) {
var mirror = getInlineOption(el.node, 'mirror', options.mirror);
var once = getInlineOption(el.node, 'once', options.once);
var id = getInlineOption(el.node, 'id');
var customClassNames = options.useClassNames && el.node.getAttribute('data-aos');
var animatedClassNames = [options.animatedClassName].concat(customClassNames ? customClassNames.split(' ') : []).filter(function (className) {
return typeof className === 'string';
});
if (options.initClassName) {
el.node.classList.add(options.initClassName);
}
el.position = {
in: getPositionIn(el.node, options.offset, options.anchorPlacement),
out: mirror && getPositionOut(el.node, options.offset)
};
el.options = {
once: once,
mirror: mirror,
animatedClassNames: animatedClassNames,
id: id
};
});
return $elements;
};
/**
* Generate initial array with elements as objects
* This array will be extended later with elements attributes values
* like 'position'
*/
var elements = (function () {
var elements = document.querySelectorAll('[data-aos]');
return Array.prototype.map.call(elements, function (node) {
return { node: node };
});
});
/**
* *******************************************************
* AOS (Animate on scroll) - wowjs alternative
* made to animate elements on scroll in both directions
* *******************************************************
*/
/**
* Private variables
*/
var $aosElements = [];
var initialized = false;
/**
* Default options
*/
var options = {
offset: 120,
delay: 0,
easing: 'ease',
duration: 400,
disable: false,
once: false,
mirror: false,
anchorPlacement: 'top-bottom',
startEvent: 'DOMContentLoaded',
animatedClassName: 'aos-animate',
initClassName: 'aos-init',
useClassNames: false,
disableMutationObserver: false,
throttleDelay: 99,
debounceDelay: 50
};
// Detect not supported browsers (<=IE9)
// http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805
var isBrowserNotSupported = function isBrowserNotSupported() {
return document.all && !window.atob;
};
var initializeScroll = function initializeScroll() {
// Extend elements objects in $aosElements with their positions
$aosElements = prepare($aosElements, options);
// Perform scroll event, to refresh view and show/hide elements
handleScroll($aosElements);
/**
* Handle scroll event to animate elements on scroll
*/
window.addEventListener('scroll', throttle(function () {
handleScroll($aosElements, options.once);
}, options.throttleDelay));
return $aosElements;
};
/**
* Refresh AOS
*/
var refresh = function refresh() {
var initialize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
// Allow refresh only when it was first initialized on startEvent
if (initialize) initialized = true;
if (initialized) initializeScroll();
};
/**
* Hard refresh
* create array with new elements and trigger refresh
*/
var refreshHard = function refreshHard() {
$aosElements = elements();
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
refresh();
};
/**
* Disable AOS
* Remove all attributes to reset applied styles
*/
var disable = function disable() {
$aosElements.forEach(function (el, i) {
el.node.removeAttribute('data-aos');
el.node.removeAttribute('data-aos-easing');
el.node.removeAttribute('data-aos-duration');
el.node.removeAttribute('data-aos-delay');
if (options.initClassName) {
el.node.classList.remove(options.initClassName);
}
if (options.animatedClassName) {
el.node.classList.remove(options.animatedClassName);
}
});
};
/**
* Check if AOS should be disabled based on provided setting
*/
var isDisabled = function isDisabled(optionDisable) {
return optionDisable === true || optionDisable === 'mobile' && detect.mobile() || optionDisable === 'phone' && detect.phone() || optionDisable === 'tablet' && detect.tablet() || typeof optionDisable === 'function' && optionDisable() === true;
};
/**
* Initializing AOS
* - Create options merging defaults with user defined options
* - Set attributes on <body> as global setting - css relies on it
* - Attach preparing elements to options.startEvent,
* window resize and orientation change
* - Attach function that handle scroll and everything connected to it
* to window scroll event and fire once document is ready to set initial state
*/
var init = function init(settings) {
options = _extends(options, settings);
// Create initial array with elements -> to be fullfilled later with prepare()
$aosElements = elements();
/**
* Disable mutation observing if not supported
*/
if (!options.disableMutationObserver && !observer.isSupported()) {
console.info('\n aos: MutationObserver is not supported on this browser,\n code mutations observing has been disabled.\n You may have to call "refreshHard()" by yourself.\n ');
options.disableMutationObserver = true;
}
/**
* Observe [aos] elements
* If something is loaded by AJAX
* it'll refresh plugin automatically
*/
if (!options.disableMutationObserver) {
observer.ready('[data-aos]', refreshHard);
}
/**
* Don't init plugin if option `disable` is set
* or when browser is not supported
*/
if (isDisabled(options.disable) || isBrowserNotSupported()) {
return disable();
}
/**
* Set global settings on body, based on options
* so CSS can use it
*/
document.querySelector('body').setAttribute('data-aos-easing', options.easing);
document.querySelector('body').setAttribute('data-aos-duration', options.duration);
document.querySelector('body').setAttribute('data-aos-delay', options.delay);
/**
* Handle initializing
*/
if (['DOMContentLoaded', 'load'].indexOf(options.startEvent) === -1) {
// Listen to options.startEvent and initialize AOS
document.addEventListener(options.startEvent, function () {
refresh(true);
});
} else {
window.addEventListener('load', function () {
refresh(true);
});
}
if (options.startEvent === 'DOMContentLoaded' && ['complete', 'interactive'].indexOf(document.readyState) > -1) {
// Initialize AOS if default startEvent was already fired
refresh(true);
}
/**
* Refresh plugin on window resize or orientation change
*/
window.addEventListener('resize', debounce(refresh, options.debounceDelay, true));
window.addEventListener('orientationchange', debounce(refresh, options.debounceDelay, true));
return $aosElements;
};
/**
* Export Public API
*/
var aos = {
init: init,
refresh: refresh,
refreshHard: refreshHard
};
export default aos;

1
assets/vendor/aos/aos.js vendored Normal file

File diff suppressed because one or more lines are too long

1
assets/vendor/aos/aos.js.map vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

BIN
assets/vendor/bootstrap/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more