diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..632280c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/.vscode + +/assets/images/heavy_images +/assets/images/original_webp +/assets/images/compressor.py \ No newline at end of file diff --git a/.htaccess b/.htaccess index 2146110..eaecde4 100644 --- a/.htaccess +++ b/.htaccess @@ -1,5 +1,3 @@ -ErrorDocument 404 https://edwardgaibor.me/404.html - #remove html file extension https://example.com/page.html # to https://example.com/page RewriteEngine On diff --git a/404.html b/404.html deleted file mode 100644 index 6b06158..0000000 --- a/404.html +++ /dev/null @@ -1,38 +0,0 @@ - - - -
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
Whoops!
-
It seems like we couldn't find the page you were looking for
-
- - Go back -
- -
diff --git a/CNAME b/CNAME index 95c00e6..b1cfa9c 100644 --- a/CNAME +++ b/CNAME @@ -1 +1 @@ -edwardgaibor.me +edwardgaibor.me \ No newline at end of file diff --git a/Edward Gaibor Resume.pdf b/Edward Gaibor Resume.pdf deleted file mode 100644 index b616bfc..0000000 Binary files a/Edward Gaibor Resume.pdf and /dev/null differ diff --git a/Resume_EG.pdf b/Resume_EG.pdf deleted file mode 100644 index be117dd..0000000 Binary files a/Resume_EG.pdf and /dev/null differ diff --git a/achievements.html b/achievements.html deleted file mode 100644 index 61e6802..0000000 --- a/achievements.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Achievements | Edward Gaibor - - - - - - - -
-

Achievements

-

Check some of my Achievements!

- -
- -
- -
- Contact Me -
-
- - - - - - - diff --git a/assets/Resume.pdf b/assets/Resume.pdf new file mode 100644 index 0000000..e3148f0 Binary files /dev/null and b/assets/Resume.pdf differ diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 0000000..854e271 --- /dev/null +++ b/assets/css/style.css @@ -0,0 +1,1130 @@ +@import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&display=swap"); + +/*===== VARIABLES CSS =====*/ +:root { + --header-height: 3rem; + --title-font: 'Bricolage Grotesque', sans-serif; + /*===== Colors =====*/ + --first-color: #473C38; + --first-color-light: #A44F30; + --second-color-crazy: #9e262c; + --background-color: #FCFEF1; + /*===== Font and typography =====*/ + --body-font: 'Bricolage Grotesque', sans-serif; + --normal-font-size: 1rem; + --special-font: 'Bricolage Grotesque', cursive; + /*===== z index =====*/ + --z-fixed: 100; + --color-bg-1: #2f251e; + --color-bg-2: #43392f; + --color-bg-3: #18130e; + --color-bg-4: var(--color-bg-1); + --color-bg-5: var(--color-bg-2); + --color-bg-6: var(--color-bg-3); + --s: 1; + --img-ratio: 1.1; + --img-width: 190px; + --img-border-radius: 7px; + --img-offset-x: 20px; + --img-offset-y: 20px; + --cursor-dot: var(--second-color-crazy); + --cursor-circle: var(--second-color-crazy); +} + +/* Text Selection Color */ +::selection { + background-color: var(--second-color-crazy); + color: var(--background-color); +} + +::-moz-selection { + background-color: var(--second-color-crazy); + color: var(--background-color); +} + +html, body { + height: 100%; + font-family: var(--body-font); + background-color: var(--background-color); + /* A creme tone; adjust as needed */ + color: var(--first-color); + /* Soft contrast for elegance */ + margin: 0; + padding: 0; + cursor: none; +} + +body { + overflow-x: hidden; +} + +.body-text { + font-size: 1.5rem; + margin: 0; + text-align: center; +} + +.links { + color: var(--second-color-crazy); +} + +section { + padding: 2vh; + display: flex; + flex-direction: column; + align-items: center; + height: 100vh; + text-align: center; + + width: 80vw; + margin: 0 auto; +} + +.section-titles { + font-size: 7vw; + margin: 0; + font-weight: 800; + line-height: 0.8; + margin-bottom: 100px; +} + +.home { + justify-content: center; + +} + +.input-container { + position: fixed; + left: 0; + top: 1.5%; + left: 0.7%; + margin: 0 auto; + width: 100%; + max-width: 250px; + padding: 20px; + border-radius: 20px; + background-color: #FFFAEB; + transition: 1s; + z-index: 10000; + opacity: 0.3; + font-family: var(--body-font); + font-size: 15px; +} + +.input-container:hover { + + max-width: 500px; + opacity: 1; +} + +.input-box { + width: 100%; + padding: 10px; + border: none; + outline: none; + background: none; + font-size: 18px; + color: var(--first-color); + font-family: var(--body-font); +} + +.tooltip-icon { + position: absolute; + top: 50%; + right: 10px; + transform: translateY(-50%); + background-color: #FF9800; + color: #FFFFFF; + border: none; + border-radius: 50%; + width: 30px; + height: 30px; + font-size: 18px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + transition: background-color 1s; +} + +.tooltip-icon:hover { + background-color: #F57C00; +} + +.tooltip-container { + display: none; + position: absolute; + top: 100%; + left: 0; + width: 50%; + padding: 10px; + background-color: #FFFAEB; + border-radius: 10px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + z-index: 10; + opacity: 0; + transition: opacity 1s; + margin-top: 10px; +} + +.tooltip-icon:hover + .tooltip-container, +.tooltip-container:hover { + + display: block; + opacity: 1; +} + +.child{ + display: inline-block; + width: 30%; + height: auto; + margin: 0px auto; + text-align: left; + padding-left: 10px; + padding-right: 20px; + text-align: center; +} + +@media only screen and (max-width: 768px) { + .child{ + width: 100%; + } +} + + +/* .input-box:hover { + max-width: 500px; + opacity: 1; +} + +.input-box:hover ~ .input-text { + transition: 1s; + opacity: 1; +} + +.input-text { + width: 100%; + padding: 10px; + border: none; + outline: none; + background: none; + font-size: 18px; + color: var(--first-color); + font-family: var(--body-font); + position: fixed; + left: 0; + top: 8%; + left: 0.7%; + opacity: 0.3; + z-index: 10; + opacity: 0; + transition: 1s; + } */ + +.home h2 { + font-size: 20vw; + margin: 0; + font-weight: 800; + line-height: 0.8; +} + +.home-about { + font-size: 2.5vw; + margin: 0; + text-align: center; +} + +.contenth { + grid-area: content; + border-radius: 8px; + background: var(--background-color); + position: relative; + z-index: 100; +} + +@media (any-pointer:fine) { + .cursor { + position: fixed; + top: 0; + left: 0; + display: block; + pointer-events: none; + z-index: 900; + } + + .cursor--1 .cursor__inner { + fill: var(--cursor-dot); + } + + .cursor--2 .cursor__inner { + fill: none; + stroke: var(--cursor-circle); + stroke-width: 1px; + } + + .no-js .cursor { + display: none; + } +} + +.content__imgh { + width: var(--img-width); + aspect-ratio: var(--img-ratio); + border-radius: var(--img-border-radius); + position: absolute; + top: 0; + left: 0; + opacity: 0; + overflow: hidden; + will-change: transform, filter; +} + +.content__imgh-inner { + background-position: 50% 50%; + width: calc(100% + var(--img-offset-x)); + height: calc(100% + var(--img-offset-y)); + background-size: cover; + position: absolute; + top: calc( -1 * var(--img-offset-y) / 2 ); + left: calc( -1 * var(--img-offset-x) / 2 ); + filter: sepia(100%) contrast(0.95) brightness(0.7); +} + + + +.about { + background-color: var(--background-color); + justify-content: center; +} + +/* Style for the about section content container */ +.about-content { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; /* Ensure it fills the section */ +} + +/* Style for the text and image within the about section */ +.about-text, .about-image { + flex-basis: 60%; /* Each takes up half the space */ + padding: 20px; /* Add some padding for spacing */ +} + +/* Style for the image within the about section */ +.about-image img { + width: 100%; /* Ensure the image fills the container */ + border-radius: 20px; /* Add a slight border radius for softness */ + width: 80%; +} + +.resume-button { + display: inline-block; + padding: 10px 20px; + background-color: var(--first-color); + color: #FFFFFF; + text-decoration: none; + border-radius: 12px; + font-weight: bold; + margin-top: 20px; + transition: background-color 0.3s ease; +} + +.resume-button:hover { + background-color: var(--second-color); +} + + +.certificates { + background-color: var(--background-color); + padding: 50px 0; + text-align: center; +} + +.slider-container { + position: relative; + max-width: 800px; + margin: 0 auto; + overflow: hidden; +} + +.slider { + display: flex; + transition: transform 0.5s ease; +} + +.slider img { + width: 100%; + height: auto; + object-fit: cover; +} + +.slider-controls { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 100%; + display: flex; + justify-content: space-between; + z-index: 1; +} + +.prev-button, +.next-button { + background-color: var(--first-color); + color: #FFFFFF; + border: none; + padding: 10px 20px; + font-size: 18px; + cursor: pointer; +} + +.prev-button:hover, +.next-button:hover { + background-color: var(--second-color); +} + + + +.projects { + background-color: #FFFAEB; + border-radius: 20px; + height: auto; /* Adjusted to ensure content fits well */ + width: 70vw; + display: flex; + padding: 40px; +} + + +.tabs { + display: flex; + flex-wrap: wrap; + justify-content: flex-start; + align-items: flex-start; + background-color: #FFFAEB; + padding: 0; + margin: 0; /* Ensure no margin is pushing it away from the top */ + width: 100%; + z-index: 100; +} + +.tab-link { + cursor: none; + padding: 10px 15px; /* Adjust padding as needed */ + transition: background-color 0.3s; + border: none; /* Removes border if present */ + background: none; /* Removes any background styling */ + font-size: 16px; /* Adjust font size as needed */ + border-radius: 20px; + border-style: solid; + border-radius: 10px; + border-color: var(--first-color); + margin-right: 15px; + transition: 0.5s; + color: var(--first-color); +} + +.project-links { + cursor: none; + padding: 10px 15px; /* Adjust padding as needed */ + transition: background-color 0.3s; + border: none; /* Removes border if present */ + background: none; /* Removes any background styling */ + font-size: 16px; /* Adjust font size as needed */ + font-family: var(--body-font); + border-radius: 20px; + border-style: solid; + border-radius: 10px; + border-color: var(--first-color); + margin-right: 15px; + transition: 0.5s; + color: var(--first-color); + margin-top: 20px; +} + +.project-links:hover { + transition: 0.5s; + background-color: #9e262c; + border-style: solid; + border-radius: 20px; + font-size: 40px; + color: #FFFAEB; +} + + +.hydroponics { + position: relative; + z-index: 1; +} + + +.hydroponics::before { + content: ""; + position: absolute; + z-index: -1; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('https://images.squarespace-cdn.com/content/v1/63064607eb816a4d50027fd1/1678377484425-V3NTWBS29YJ0AR7J1AO6/vertical-greenhouse.jpg?format=500w') center no-repeat; + opacity: 0.2; +} + + +.deeplearning { + position: relative; + z-index: 1; +} + +.active { + border-color: var(--second-color-crazy); +} + +.deeplearning::before { + content: ""; + position: absolute; + z-index: -1; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('https://home.sophos.com/sites/default/files/2021-09/ai-article-pic8.jpeg') center no-repeat; + opacity: 0.2; + filter: brightness(0.3); +} + +.exoplanet { + position: relative; + z-index: 1; +} + +.exoplanet::before { + content: ""; + position: absolute; + z-index: -1; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: url('https://assets.newatlas.com/dims4/default/e071b94/2147483647/strip/true/crop/1320x742+0+0/resize/1320x742!/quality/90/?url=http%3A%2F%2Fnewatlas-brightspot.s3.amazonaws.com%2F80%2F97%2F8a6873d84d9bac122c6341588ad4%2F5000-exoplanets.jpg') center no-repeat; + opacity: 0.3; +} + +.tab-link:hover { + transition: 0.5s; + background-color: var(--background-color); + border-style: solid; + border-radius: 20px; +} + +.tab-content-wrapper { + clear: both; + width: 100%; + /* If you've added any specific styles that might center or otherwise affect the position of the tabs, reset them here */ +} + +.tab-content { + display: none; + position: relative; + padding-top: 20px; + padding-bottom: 20px; + box-sizing: border-box; + animation: slideEffect 0.5s; + text-align: left; + color: var(--first-color); +} + +.tab-content li { + margin-bottom: 10px; + line-height: 1.5; +} + +@keyframes slideEffect { + from {opacity: 0; transform: translateX(-20px);} + to {opacity: 1; transform: translateX(0);} +} + +/* Style for the active tab content */ +.active-content { + display: block; +} + + +@keyframes loaderAnim { + to { + opacity: 1; + transform: scale3d(0.5,0.5,1); + } +} + +a { + text-decoration: none; + color: var(--color-link); + outline: none; + cursor: pointer; +} + +a:hover { + color: var(--color-link-hover); + outline: none; +} + +/* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */ +a:focus { + /* Provide a fallback style for browsers + that don't support :focus-visible */ + outline: none; + background: lightgrey; +} + +a:focus:not(:focus-visible) { + /* Remove the focus indicator on mouse-focus for browsers + that do support :focus-visible */ + background: transparent; +} + +a:focus-visible { + /* Draw a very noticeable focus style for + keyboard-focus on browsers that do support + :focus-visible */ + outline: 2px solid red; + background: transparent; +} + +.unbutton { + background: none; + border: 0; + padding: 0; + margin: 0; + font: inherit; + cursor: pointer; +} + +.unbutton:focus { + outline: none; +} +.fancy { + position: relative; + white-space: nowrap; + &:after { + --deco-height: 0.3125em; + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: calc(var(--deco-height) * -0.625); + height: var(--deco-height); + background-image: url("data:image/svg+xml,%3Csvg width='100' height='64' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23a)'%3E%3Cpath d='M-17 30.5C-1 22 72-4 54 13 37.9 28.2-2.5 57.5 16 55.5s72-29 104-40' stroke='%239e262c' stroke-width='10'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath fill='%23fff' d='M0 0h100v64H0z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"); + background-size: auto 100%; + background-repeat: round; + background-position: 0em; + } +} +i { + font-style: normal; + font-variation-settings: "slnt" 0, "wdth" 100, "wght" 400, "INKT" 400; +} + +.gallery-title { + font-size: 7vw; + font-weight: 800; + margin: 0; + text-align: center; + padding-top: 10%; +} + +.projects-title { + font-size: 7vw; + font-weight: 800; + margin: 0; + text-align: center; + padding-bottom: 5%; +} + +.content { + padding: 1.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + +} + +.content--perspective { + perspective-origin: 50% 0%; + perspective: 1000px; +} + +.text-large { + font-size: clamp(1.5rem,5vw,3rem); + max-width: 900px; + margin: 0 0 0.85em 0; + line-height: 1.2; + font-variation-settings: "slnt" 0, "wdth" 100, "wght" 500, "INKT" 100; +} + +.content--sticky { + width: 100vw; + position: sticky; + top: 0; + --offset: 0px; + top: var(--offset); + height: calc(100vh - var(--offset)); +} + +.content--grid, +.content--grid .content__inner { + display: grid; + overflow: hidden; + grid-column-gap: 5vw; + grid-row-gap: 2vh; + align-content: center; + grid-template-areas: 'content-img' 'content-title' 'content-text'; + justify-items: center; +} + +.content--grid:has(.content__inner) { + display: block; + padding: 0; +} + +.content__inner { + width: 100%; + height: 100%; + border-radius: 0 0 2rem 2rem; +} + +.content--card { + display: flex; + flex-direction: column; + height: 80vh; + width: 95vw; + max-width: 500px; + aspect-ratio: 0.8; + top: 10vh; + margin: auto; + border-radius: 14px; + gap: 3vh; + text-align: center; + margin-bottom: 5vh; +} + +.content--card .content__title { + font-size: clamp(1.5rem,4vw,3.5rem); +} + +.content--card .content__title i { + display: block; +} + +.content--half { + display: flex; + flex-direction: column; + gap: 3vh; + text-align: center; +} + +.content--half:nth-child(odd) { + margin-left: auto; +} + +.content__img { + grid-area: content-img; + width: 50%; + max-width: 300px; + height: auto; +} + +.content__img--large { + width: 60%; + height: auto; +} + +.content__img--small { + height: 35%; + width: auto; +} + +.spacer { + margin-top: 20vh; +} + +.content__title { + grid-area: content-title; + text-transform: uppercase; + line-height: 1; + font-weight: 800; + font-size: clamp(1.5rem,5vw,4rem); + margin: 0; + color: #FFFAEB; +} + +.intro { + display: grid; + place-items: center; + text-align: center; +} + +.intro__info { + position: relative; + max-width: 20ch; + opacity: 0.6; + line-height: 1.2; + margin-bottom: 4rem; + padding-bottom: 1rem; + font-weight: 600; + font-size: 14px; +} + +.intro__info::after { + content: ''; + position: absolute; + left: 50%; + width: 1px; + height: 2rem; + background: var(--color-bg-1); + top: 100%; +} + + +.content__text { + margin: 0; + max-width: 600px; + grid-area: content-text; + text-align: center; + line-height: 1.5; + padding: 0 1rem; + backface-visibility: hidden; + color: #FFFAEB; + font-size: 25px; +} + +.content__text--narrow { + max-width: 300px; +} + +.content--intro { + padding-top: 25vh; + padding-bottom: 25vh; + z-index: 2; +} + +.content--outro { + padding-top: 30vh; + padding-bottom: 30vh; + display: block; + width: 100%; + text-align: center; + justify-content: center; +} + +.bg-1 { background: var(--color-bg-1); } +.bg-2 { background: var(--color-bg-2); } +.bg-3 { background: var(--color-bg-3); } +.bg-4 { background: var(--color-bg-4); } +.bg-5 { background: var(--color-bg-5); } +.bg-6 { background: var(--color-bg-6); } +.bg-7 { background: #473C38; } + + +.grid { + grid-template-columns: 100%; + grid-auto-rows: auto; + display: grid; + position: relative; + margin: 10vh 0 10vh; +} + +.grid__item { + position: relative; + margin: 0; +} + +.grid__item-img { + position: relative; + overflow: hidden; + display: grid; + place-items: center; + width: 100%; + height: auto; + aspect-ratio: 1.5; + filter: sepia(50%); +} + +.grid__item-img-inner { + width: 100%; + height: 100%; + background-position: 50%; + background-size: cover; + position: relative; +} + +.grid__item-caption { + position: absolute; + padding: 0.5rem; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.grid__item-caption h3 { + font-weight: bold; + font-size: inherit; + margin: 0; + color: var(--first-color); +} + +.grid__item-caption span { + font-weight: bold; + color: var(--second-color-crazy); +} + +.outro { + display: grid; + place-items: center; + margin: 40vh 0; +} + +.outro__title { + font-weight: 300; + font-size: clamp(1.5rem,10vw,2rem); +} + +.card-wrap { + margin-top: 5vh; + display: grid; + grid-gap: 2rem; + grid-auto-flow: row; + grid-template-columns: 250px; + text-align: center; +} + +.card__image { + display: block; + border-radius: 7px; + background-size: cover; + background-position: 50% 50%; + width: 100%; + height: auto; + aspect-ratio: 4 / 3; + filter: contrast(0.95); +} + +.card__title { + font-weight: 300; +} + +.credits { + font-size: 1.5rem; + text-align: center; + margin: 50vh auto 0; + padding-bottom: 50vh; +} + +@media screen and (min-width: 53em) { + .card-wrap { + grid-template-columns: repeat(2,300px); + } + + .grid { + grid-template-columns: repeat(8,1fr); + } + + .grid__item { + grid-column: var(--c) / span var(--s); + grid-row: var(--r); + } +} + + + + + + + + +/* Redirect Page Styles */ +.redirect-page { + font-family: var(--body-font); + background-color: var(--background-color); + color: var(--first-color); + text-align: center; + padding: 20px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 90vh; + margin: 0; +} + +.redirect-page h1 { + font-size: 3rem; + margin-bottom: 20px; + color: var(--second-color-crazy); +} + +.redirect-page p { + font-size: 1.5rem; + margin-bottom: 20px; +} + +.redirect-page a { + color: var(--second-color-crazy); + text-decoration: none; + font-weight: bold; +} + +.redirect-page a:hover { + text-decoration: underline; +} + +.redirectingImage { + width: 50%; + box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2); +} + + +.projects-header { + display: flex; + justify-content: flex-start; + align-items: center; + padding: 20px; + background-color: var(--background-color); +} + +.return-button { + padding: 10px 20px; + background-color: var(--first-color); + color: #FFFFFF; + text-decoration: none; + border-radius: 12px; + font-weight: bold; + transition: background-color 0.3s ease; + position: fixed; + top: 20px; + left: 20px; + + +} + +.return-button:hover { + background-color: var(--second-color); +} + +.project-grid-page { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 20px; + padding: 20px; +} + +.project-box-page { + background-color: var(--background-color); + padding: 20px; + border-radius: 12px; + text-align: center; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +.project-image-page { + width: 100%; + height: auto; + border-radius: 8px; + margin-bottom: 10px; +} + +.project-title-page { + font-size: 24px; + margin-bottom: 10px; +} + +.project-description-page { + font-size: 20px; + margin-bottom: 20px; +} + +.project-links-page { + display: flex; + justify-content: center; + align-items: center; +} + +.project-link-page { + font-size: 24px; + margin: 0 10px; + transition: color 0.3s ease; + color: var(--first-color); +} + +.project-link-page:hover { + color: var(--second-color-crazy); +} + +.project-tech-stack { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-bottom: 10px; +} + +.tech-item { + background-color: transparent; + border: 2px solid var(--first-color); + border-radius: 20px; + color: var(--first-color); + font-size: 14px; + padding: 5px 10px; + margin: 5px; +} + + +@media (max-width: 768px) { + .section-titles { + font-size: 10vw; + margin-bottom: 50px; + } + + .home h2 { + font-size: 25vw; + } + + .about-content { + flex-direction: column; + } + + .about-text, .about-image { + flex-basis: 100%; + padding: 10px; + font-size: 20px; + } + + .body-text { + font-size: 1.2rem; + margin-bottom: 20px; + } + + .projects { + width: 90vw; + padding: 20px; + } + + .content__text { + font-size: 18px; + } + + .tab-link { + padding: 5px 10px; + margin-right: 3px; /* Adjusted margin */ + margin-bottom: 10px; + + } + + .tabs { + justify-content: center; + } + + .project-grid-page { + grid-template-columns: repeat(1, 1fr); + } +} diff --git a/assets/css/styles.css b/assets/css/styles.css deleted file mode 100644 index e544f44..0000000 --- a/assets/css/styles.css +++ /dev/null @@ -1,1951 +0,0 @@ -/*===== GOOGLE FONTS =====*/ -@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"); -@import url('https://fonts.googleapis.com/css2?family=Bitter:wght@900&family=Caveat&family=Quicksand:wght@500&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=La+Belle+Aurore&display=swap'); - - - -/*===== VARIABLES CSS =====*/ -:root{ - --header-height: 3rem; - --nav-width: 68px; - --title-font: 'Montserrat', sans-serif; - - /*===== Colors =====*/ - --first-color: #0E2431; - --first-color-light: #00C2CB; - --white-color: #F7F6FB; - - /*===== Font and typography =====*/ - --body-font: 'Montserrat', sans-serif; - --normal-font-size: 1rem; - --special-font:'La Belle Aurore', cursive; - - - /*===== z index =====*/ - --z-fixed: 100; -} - - -/*===== Margenes =====*/ -:root{ - --mb-1: 0.5rem; - --mb-2: 1rem; - --mb-3: 1.5rem; - --mb-4: 2rem; - --mb-5: 2.5rem; - --mb-6: 3rem; -} - -/*===== z index =====*/ -:root{ - --z-back: -10; - --z-normal: 1; - --z-tooltip: 10; - --z-fixed: 100; -} - -/*===== BASE =====*/ -*,::before,::after{ - box-sizing: border-box; -} - -.index__body{ - margin: 0; - font-family: var(--body-font); - font-size: var(--normal-font-size); - transition: .5s; - scroll-behavior: smooth; -} - -a{ - text-decoration: none; -} - -img{ - max-width: 100%; - height: auto; - display: block; -} - -.body__about{ - position: relative; - margin: var(--header-height) 0 0 0; - padding: 0 1rem; - font-family: var(--body-font); - font-size: var(--normal-font-size); - transition: .5s; -} - -/*===== LAYOUT =====*/ - -::-webkit-scrollbar{ - width: 8px; -} - -::-webkit-scrollbar-thumb{ - background: linear-gradient(transparent, var(--first-color)); - border-radius: 6px; -} -::-webkit-scrollbar-thumb:hover{ - background: linear-gradient(transparent, var(--first-color-light)); -} - -.bd-grid{ - max-width: 1024px; - display: grid; - grid-template-columns: 100%; - grid-column-gap: 2rem; - width: calc(100% - 2rem); - margin-left: var(--mb-2); - margin-right: var(--mb-2); -} - -/*===== CLASS CSS ===== */ -.section-title{ - position: relative; - font-size: var(--h2-font-size); - color: var(--first-color); - margin-top: var(--mb-2); - margin-bottom: var(--mb-4); - text-align: center; - -} -.section-title::after{ - position: absolute; - content: ""; - width: 64px; - height: 0.18rem; - left: 0; - right: 0; - margin: auto; - top: 2rem; - background-color: var(--first-color-light); -} -.section{ - display: flex; - padding-top: 3rem; - padding-bottom: 2rem; - align-items: center; - margin-top: -6%; - width: 100%; - height: 100vh; -} - -.section-about{ - padding-top: 1rem; - padding-bottom: 2rem; -} - -/*===== HEADER =====*/ -.header{ - width: 100%; - height: var(--header-height); - position: fixed; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 1rem; - - z-index: var(--z-fixed); - transition: .5s; -} - -.header__toggle{ - color: var(--first-color); - font-size: 1.5rem; - cursor: pointer; -} - -.header__img{ - width: 35px; - height: 35px; - display: flex; - justify-content: center; - border-radius: 50%; - overflow: hidden; -} - -.header__img img{ - width: 40px; -} - -.body_bioinv{ - width: 100%; - height: 95vh; - padding: 0 1rem; - transition: .5s; - background-color: var(--first-color); -} - -.red_section{ - background-color: var(--first-color); - color: var(--white-color); - padding: var(--mb-2); - margin-top: var(--mb-2); - margin-bottom: var(--mb-2); - transition: .5s; - align-items: center; - justify-content: center; - width: 100%; -} - -.red_cards{ - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - grid-gap: 50px; - margin-top: var(--mb-2); - transition: 0.5s; - justify-content: space-evenly; - justify-items: center; - align-content: space-evenly; - align-items: center; -} - -.bio__data{ - display: flex; - justify-content: center; - align-items: center; -} - -.red_content{ - display: grid; - justify-content: center; - align-items: center; - height: auto; - width: 900px; -} - -.red_card{ - transition: 0.5s; - -} - -.red_card:hover{ - transition: 0.5s; - transform: translateY(-0.8%); -} - - -.red_content{ - line-height: 1.5; - font-size: 0.9em; - background: #FFF8F7; - transition: 0.5s; - border-radius: 10px; -} - - - -.red_content > h2:first-of-type{ - padding-top: 30px; - padding-bottom: 80px; - margin-top: 0; - margin-bottom: -10%; -} - -.red_content > p:first-of-type{ - padding: 15px; - margin-bottom: 0; - padding-bottom: 50px; -} - -.red__info{ - display: flex; - justify-content: center; - align-items: center; - font-size: 40px; - border-bottom: 2px solid #cccccc; - color: var(--first-color); - border-radius: 10px; - margin-top: 1%; - background-color: #A9C4DD; - transition: 0.5s; - padding-top: 7px; - z-index: 100; -} - -.red__info:hover{ - transition: 0.5s; - background-color: var(--first-color-light); -} - - -.red_title{ - transition: 0.5s; - display: flex; - text-align: center; - justify-content: center; - font-family: var(--title-font); - font-size: 35px; - margin-bottom: 4%; - color: var(--first-color); - line-height: 1.2cm; -} - -.red_title:hover { - transition: 0.2s; - color: #00C2CB; - cursor:default; -} - -.red_content p{ - display: flex; - margin-left: 40px; - margin-right: 40px; - margin-top: 800px; - color: var(--first-color); - font-family: var(--body-font); - font-weight: 600; - font-size: 16px; -} - - -.red2_content p{ - display: flex; - margin-left: 40px; - margin-right: 40px; - color: var(--first-color); - font-family: var(--body-font); - font-weight: 600; - font-size: 16px; -} - -.red2_content{ - height: 100%; - width: 90%; -} - - -.red2_title{ - transition: 0.5s; - display: flex; - text-align: center; - justify-content: center; - font-family: var(--title-font); - font-size: 35px; - padding-top: 30px; - padding-left: 25px; - padding-right: 25px; - margin-bottom: 4%; - color: var(--first-color); - line-height: 1.2cm; -} - -.red2_title:hover { - transition: 0.2s; - color: #A9C4DD; - cursor:default; - font-size: 40px; - -} - -.red2_content{ - font-size: 0.9em; - background: #FFF8F7; - transition: 0.5s; - border-radius: 10px; - margin-left: 4.5%; - height: auto; - padding-bottom: 3%; -} - -.sred_cards{ - display: grid; - grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); - grid-gap: 50px; - margin-top: var(--mb-2); - margin-bottom: var(--mb-2); - margin-left: -5.5%; - transition: 0.5s; - justify-content: space-evenly; - justify-items: center; - align-content: space-evenly; - align-items: center; -} - -div.gallery_r { - border: 1px solid #ccc; - border-radius: 10px; - transition: 1s; -} - -div.gallery_r:hover { - transition: 1.5s; - border: 1px solid #777; -} - -div.gallery_r img { - width: 100%; - height: auto; - border-radius: 10px; -} - -div.desc { - padding: 15px; - text-align: center; - font-family: var(--body-font); - font-weight: 600; -} -.responsive { - padding: 0 6px; - float: left; - width: 24.99999%; - padding-bottom: 15px; -} -.clearfix:after { - content: ""; - display: table; - clear: both; -} - -.gallery_holder_r{ - padding-left: 30px; - padding-right: 30px; -} - - -/*===== HOME =====*/ -.home__data{ - height: calc(100vh- 81.6px); - text-align: left; - width: 100%; -} - -.home__title { - text-align: center; - font-size: 45px; - margin-left: 2%; - margin-right: 2%; - font-family: var(--title-font); -} - -.home__subtitle { - text-align: center; - font-size: 15px; - color: #585858; -} - -.home__title-color{ - color: var(--first-color-light); -} -.home__title-color:before{ - content: "Edward Gaibor"; -} -.cite{ - color: var(--first-color-light); -} - -.icons__social{ - display: relative; - margin-top: 10%; -} - -.home__social-icon{ - color: var(--first-color); - font-size: 19px; - padding: 3px; -} - -.home__social-icon:hover{ - transition: all .5s; - color: var(--first-color-light); -} - -.button{ - display: block; - position: relative; - background: var(--first-color); - border: 1px solid transparent; - border-radius: 10px; - height: 50px; - text-align: center; - text-decoration: none; - color: #fff; - line-height: 50px; - font-size: 18px; - padding: 0 70px; - white-space: nowrap; - margin-top: 25px; - transition: background .5s ease; - overflow: hidden; - -webkit-mask-image: -webkit-radial-gradient(white, black); - mask-image: -webkit-radial-gradient(white, black); - display: inline-block; - width: 250px; -} - -.button_wrapper{ - display: flex; - align-items: center; - justify-content: center; -} - -.button:before{ - content: ''; - position: absolute; - width: 20px; - height: 100px; - background: #fff; - bottom: -25px; - left: 0; - border: 2px solid #fff; - transform: translateX(-50px) rotate(45deg); - transition: transform .5s ease; -} - -.button:hover{ - background: var(--first-color-light); - border-color: #fff; -} - -.button:hover::before{ - transform: translateX(250px) rotate(45deg); -} - - - -/*===== NAV =====*/ -.l-navbar{ - position: fixed; - top: 0; - left: -30%; - width: var(--nav-width); - height: 100vh; - background-color: var(--first-color); - padding: .5rem 1rem 0 0; - transition: .5s; - z-index: var(--z-fixed); -} - -.nav{ - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - overflow: hidden; -} - -.nav__logo, .nav__link{ - display: grid; - grid-template-columns: max-content max-content; - align-items: center; - column-gap: 1rem; - padding: .5rem 0 .5rem 1.5rem; -} - -.nav__logo{ - margin-bottom: 2rem; -} - -.nav__logo-icon{ - font-size: 1.25rem; - color: var(--white-color); -} - -.nav__logo-name{ - color: var(--white-color); - font-weight: 700; -} - -.nav__link{ - position: relative; - color: var(--first-color-light); - margin-bottom: 1.5rem; - transition: .3s; -} - -.nav__link:hover{ - color: var(--white-color); -} - -.nav__icon{ - font-size: 1.25rem; -} - -.badge{ - margin-top: 25px; - display: flex; - justify-content: center; - margin-bottom: -50px; -} - -.badge_2{ - display: none; -} - -/*Show navbar movil*/ -.show{ - left: 0; -} - -/*Add padding body movil*/ -.body-pd{ - padding-left: calc(var(--nav-width) + 1rem); -} - -/*Active links*/ -.active{ - color: var(--white-color); -} - -.active::before{ - content: ''; - position: absolute; - left: 0; - width: 2px; - height: 32px; - background-color: var(--white-color); -} - -/*===== ERROR 404 =====*/ -.box { - width: 350px; - height: 100%; - max-height: 600px; - min-height: 450px; - background: #272727; - border-radius: 20px; - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - padding: 30px 50px; -} -.box .box__ghost { - padding: 15px 25px 25px; - position: absolute; - left: 50%; - top: 30%; - transform: translate(-50%, -30%); -} -.box .box__ghost .symbol:nth-child(1) { - opacity: .2; - animation: shine 4s ease-in-out 3s infinite; -} -.box .box__ghost .symbol:nth-child(1):before, .box .box__ghost .symbol:nth-child(1):after { - content: ''; - width: 12px; - height: 4px; - background: #fff; - position: absolute; - border-radius: 5px; - bottom: 65px; - left: 0; -} -.box .box__ghost .symbol:nth-child(1):before { - transform: rotate(45deg); -} -.box .box__ghost .symbol:nth-child(1):after { - transform: rotate(-45deg); -} -.box .box__ghost .symbol:nth-child(2) { - position: absolute; - left: -5px; - top: 30px; - height: 18px; - width: 18px; - border: 4px solid; - border-radius: 50%; - border-color: #fff; - opacity: .2; - animation: shine 4s ease-in-out 1.3s infinite; -} -.box .box__ghost .symbol:nth-child(3) { - opacity: .2; - animation: shine 3s ease-in-out .5s infinite; -} -.box .box__ghost .symbol:nth-child(3):before, .box .box__ghost .symbol:nth-child(3):after { - content: ''; - width: 12px; - height: 4px; - background: #fff; - position: absolute; - border-radius: 5px; - top: 5px; - left: 40px; -} -.box .box__ghost .symbol:nth-child(3):before { - transform: rotate(90deg); -} -.box .box__ghost .symbol:nth-child(3):after { - transform: rotate(180deg); -} -.box .box__ghost .symbol:nth-child(4) { - opacity: .2; - animation: shine 6s ease-in-out 1.6s infinite; -} -.box .box__ghost .symbol:nth-child(4):before, .box .box__ghost .symbol:nth-child(4):after { - content: ''; - width: 15px; - height: 4px; - background: #fff; - position: absolute; - border-radius: 5px; - top: 10px; - right: 30px; -} -.box .box__ghost .symbol:nth-child(4):before { - transform: rotate(45deg); -} -.box .box__ghost .symbol:nth-child(4):after { - transform: rotate(-45deg); -} -.box .box__ghost .symbol:nth-child(5) { - position: absolute; - right: 5px; - top: 40px; - height: 12px; - width: 12px; - border: 3px solid; - border-radius: 50%; - border-color: #fff; - opacity: .2; - animation: shine 1.7s ease-in-out 7s infinite; -} -.box .box__ghost .symbol:nth-child(6) { - opacity: .2; - animation: shine 2s ease-in-out 6s infinite; -} -.box .box__ghost .symbol:nth-child(6):before, .box .box__ghost .symbol:nth-child(6):after { - content: ''; - width: 15px; - height: 4px; - background: #fff; - position: absolute; - border-radius: 5px; - bottom: 65px; - right: -5px; -} -.box .box__ghost .symbol:nth-child(6):before { - transform: rotate(90deg); -} -.box .box__ghost .symbol:nth-child(6):after { - transform: rotate(180deg); -} -.box .box__ghost .box__ghost-container { - background: #fff; - width: 100px; - height: 100px; - border-radius: 100px 100px 0 0; - position: relative; - margin: 0 auto; - animation: upndown 3s ease-in-out infinite; -} -.box .box__ghost .box__ghost-container .box__ghost-eyes { - position: absolute; - left: 50%; - top: 45%; - height: 12px; - width: 70px; -} -.box .box__ghost .box__ghost-container .box__ghost-eyes .box__eye-left { - width: 12px; - height: 12px; - background: #332F63; - border-radius: 50%; - margin: 0 10px; - position: absolute; - left: 0; -} -.box .box__ghost .box__ghost-container .box__ghost-eyes .box__eye-right { - width: 12px; - height: 12px; - background: #332F63; - border-radius: 50%; - margin: 0 10px; - position: absolute; - right: 0; -} -.box .box__ghost .box__ghost-container .box__ghost-bottom { - display: flex; - position: absolute; - top: 100%; - left: 0; - right: 0; -} -.box .box__ghost .box__ghost-container .box__ghost-bottom div { - flex-grow: 1; - position: relative; - top: -10px; - height: 20px; - border-radius: 100%; - background-color: #fff; -} -.box .box__ghost .box__ghost-container .box__ghost-bottom div:nth-child(2n) { - top: -12px; - margin: 0 -0px; - border-top: 15px solid #332F63; - background: transparent; -} -.box .box__ghost .box__ghost-shadow { - height: 20px; - box-shadow: 0 50px 15px 5px #3B3769; - border-radius: 50%; - margin: 0 auto; - animation: smallnbig 3s ease-in-out infinite; -} -.box .box__description { - position: absolute; - bottom: 30px; - left: 50%; - transform: translateX(-50%); -} -.box .box__description .box__description-container { - color: #fff; - text-align: center; - width: 200px; - font-size: 16px; - margin: 0 auto; -} -.box .box__description .box__description-container .box__description-title { - font-size: 24px; - letter-spacing: .5px; -} -.box .box__description .box__description-container .box__description-text { - color: #8C8AA7; - line-height: 20px; - margin-top: 20px; -} -.box .box__description .box__button { - display: block; - position: relative; - background: #FF5E65; - border: 1px solid transparent; - border-radius: 50px; - height: 50px; - text-align: center; - text-decoration: none; - color: #fff; - line-height: 50px; - font-size: 18px; - padding: 0 70px; - white-space: nowrap; - margin-top: 25px; - transition: background .5s ease; - overflow: hidden; - -webkit-mask-image: -webkit-radial-gradient(white, black); - mask-image: -webkit-radial-gradient(white, black); -} - -.box .box__description .box__button:before { - content: ''; - position: absolute; - width: 20px; - height: 100px; - background: #fff; - bottom: -25px; - left: 0; - border: 2px solid #fff; - transform: translateX(-50px) rotate(45deg); - transition: transform .5s ease; -} -.box .box__description .box__button:hover { - background: transparent; - border-color: #fff; -} -.box .box__description .box__button:hover:before { - transform: translateX(250px) rotate(45deg); -} - -.video_container{ - position: absolute; - top: 0; - left: 0; - width: 100%; - z-index: -10; -} - -.vid-home{ - width: 100%; - height: 100vh; - object-fit: cover; - z-index: -100; -} -.color-overlay{ - position: absolute; - top: 0; - left: 0; - background-color: #fff; - width: 100%; - height: 100vh; - opacity: 0.6; -} - -.inat-widget-div{ - display: flex; - justify-content: center; - align-items: center; -} - - -/*===== About =====*/ - -.about_section{ - margin-top: 6%; - margin-left: 2%; - align-self: left; - margin-bottom: 2%; -} -.skills__container{ - row-gap: 2rem; - text-align: left; -} -.skills__subtitle{ - margin-bottom: var(--mb-2); - font-size: 35px; - font-family: var(--title-font); - color: var(--first-color); - -} - -.r-title{ - margin-top: var(--rTitleMarginTop, 0) !important; - margin-bottom: var(--rTitleMarginBottom, 0) !important; -} - - -p:not([class]){ - line-height: var(--cssTypographyLineHeight, 1.78); - margin-top: var(--cssTypographyBasicMargin, 1em); - margin-bottom: 0; -} - -p:not([class]):first-child{ - margin-top: 0; -} - -/* -text component -*/ - -.text{ - display: var(--textDisplay, inline-flex); - font-size: var(--textFontSize, 1rem); -} - -/* -time component -*/ - -/* -core styles -*/ - -.time{ - display: var(--timeDisplay, inline-flex); - -} - -/* -extensions -*/ - -.time__month{ - margin-left: var(--timelineMounthMarginLeft, .25em); -} - -/* -skin -*/ - -.time{ - padding: var(--timePadding, .25rem 1.25rem .25rem); - background-color: var(--timeBackgroundColor, #f0f0f0); - - font-size: var(--timeFontSize, .75rem); - font-weight: var(--timeFontWeight, 700); - text-transform: var(--timeTextTransform, uppercase); - color: var(--timeColor, currentColor); -} - -/* -card component -*/ - -/* -core styles -*/ - -.card{ - padding: var(--timelineCardPadding, 1.5rem 1.5rem 1.25rem); -} - -.card__content{ - margin-top: var(--cardContentMarginTop, .5rem); -} - -/* -skin -*/ - -.card{ - border-radius: var(--timelineCardBorderRadius, 2px); - border-left: var(--timelineCardBorderLeftWidth, 3px) solid var(--timelineCardBorderLeftColor, var(--uiTimelineMainColor)); - box-shadow: var(--timelineCardBoxShadow, 0 1px 3px 0 rgba(0, 0, 0, .12), 0 1px 2px 0 rgba(0, 0, 0, .24)); - background-color: var(--timelineCardBackgroundColor, #fff); -} - -/* -extensions -*/ - -.card__title{ - --rTitleMarginTop: var(--cardTitleMarginTop, 1rem); - font-size: var(--cardTitleFontSize, 1.25rem); -} - -/* -===== -CORE STYLES -===== -*/ - -.timeline{ - display: var(--timelineDisplay, grid); - grid-row-gap: var(--timelineGroupsGap, 2rem); -} - -/* -1. If timeline__year isn't displaed the gap between it and timeline__cards isn't displayed too -*/ - -.timeline__year{ - margin-bottom: 1.25rem; /* 1 */ -} - -.timeline__cards{ - display: var(--timeloneCardsDisplay, grid); - grid-row-gap: var(--timeloneCardsGap, 1.5rem); -} - - -/* -===== -SKIN -===== -*/ - -.timeline{ - --uiTimelineMainColor: var(--timelineMainColor, #222); - --uiTimelineSecondaryColor: var(--timelineSecondaryColor, #fff); - - border-left: var(--timelineLineWidth, 3px) solid var(--timelineLineBackgroundColor, var(--uiTimelineMainColor)); - padding-top: 1rem; - padding-bottom: 1.5rem; -} - -.timeline__year{ - --timePadding: var(--timelineYearPadding, .5rem 1.5rem); - --timeColor: var(--uiTimelineSecondaryColor); - --timeBackgroundColor: var(--uiTimelineMainColor); - --timeFontWeight: var(--timelineYearFontWeight, 400); -} - -.timeline__card{ - position: relative; - margin-left: var(--timelineCardLineGap, 1rem); -} - -/* -1. Stoping cut box shadow -*/ - -.timeline__cards{ - overflow: hidden; - padding-top: .25rem; /* 1 */ - padding-bottom: .25rem; /* 1 */ -} - -.timeline__card::before{ - content: ""; - width: 100%; - height: var(--timelineCardLineWidth, 2px); - background-color: var(--timelineCardLineBackgroundColor, var(--uiTimelineMainColor)); - - position: absolute; - top: var(--timelineCardLineTop, 1rem); - left: -50%; - z-index: -1; -} - -/* -===== -SETTINGS -===== -*/ -/**/ -.timeline{ - --timelineMainColor: #39a9b1; -} - -/* -===== -DEMO -===== -*/ - - -p{ - margin-top: 0; - margin-bottom: 1rem; - line-height: 1.5; -} - -p:last-child{ - margin-bottom: 0; -} - -.page{ - max-width: 47rem; - padding: 5rem 2rem 3rem; - margin-left: auto; - margin-right: auto; -} - - -.substack{ - border:1px solid #EEE; - background-color: #fff; - width: 100%; - max-width: 480px; - height: 280px; - margin: 1rem auto;; -} - - -.linktr{ - display: flex; - justify-content: flex-end; - padding: 2rem; - text-align: center; -} - -.linktr__goal{ - background-color: rgb(209, 246, 255); - color: rgb(8, 49, 112); - box-shadow: rgb(8 49 112 / 24%) 0px 2px 8px 0px; - border-radius: 2rem; - padding: .75rem 1.5rem; -} - -.r-link{ - --uirLinkDisplay: var(--rLinkDisplay, inline-flex); - --uirLinkTextColor: var(--rLinkTextColor); - --uirLinkTextDecoration: var(--rLinkTextDecoration, none); - - display: var(--uirLinkDisplay) !important; - color: var(--uirLinkTextColor) !important; - text-decoration: var(--uirLinkTextDecoration) !important; -} - - -.skills-grid { - display: grid; - grid-gap: 20px; /* Adjust this value to add spacing between skills */ -} - -.skills__text{ - margin-bottom: var(--mb-4); - font-size: 14px; - font-family: var(--body-font); - line-height: 25px; -} - -.underlined_text{ - text-decoration: underline; - text-decoration-color: #00C2CB; - color: #0E2431; - position: relative; -} -.underlined_text:hover{ - transition: .5s; - color: #00C2CB; -} - -.underlined_text:hover .tooltip-box{ - display: inline-block; -} - - -.tooltip-box{ - display: none; - position: absolute; - background-color: #0E2431; - line-height: 20px; - z-index: 500; - text-align: center; - font-size: 14px; - padding: 5px 10px; - color: #FFF; - border-radius: 5px; - left: -50%; - bottom: 30px; -} - -.tooltip-box::after{ - content: ""; - display: block; - border-top: 7px solid #0E2431; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - position: absolute; - bottom: -7px; - left: calc(50% - 7px); -} -.skills__data{ - display: flex; - justify-content: space-between; - align-items: center; - position: relative; - font-weight: 900; - padding: .5rem 1rem; - margin-bottom: 10px; - border-radius: .5rem; - box-shadow: 0 4px 25px rgba(14,36,49,.15); -} - -.skills__icon{ - font-size: 2rem; - margin-right: var(--mb-2); - color: var(--first-color); -} -.skills__icon1{ - font-size: 1.6rem; - margin-right: var(--mb-3); - margin-left: 5px; -} -.skills__names{ - display: flex; - align-items: center; -} -.skills__bar{ - position: absolute; - left: 0; - bottom: 0; - background-color: var(--first-color-light); - height: .25rem; - border-radius: .5rem; - z-index: -10; -} -.skills__html{ - width: 95%; -} -.skills__css{ - width: 85%; -} -.skills__js{ - width: 90%; -} -.skills__ux{ - width: 75%; -} -.skills__img{ - border-radius: .5rem; - box-shadow: 0 20px 20px rgba(0,0,0,0.2); -} -.skills__html2{ - width: 100%; -} -.skills__css2{ - width: 60%; -} -.skills__js2{ - width: 80%; -} -.skills__ux2{ - width: 70%; -} -.skills__ux3{ - width: 50%; -} -.skills__img2{ - border-radius: .5rem; - box-shadow: 0 20px 20px rgba(0,0,0,0.2); -} - -.about-title:before{ - content: ""; - font-family: var(--special-font); -} - -.about-title{ - text-align: left; - font-size: 15px; - margin-left: -4%; - margin-bottom: -50%; -} - -.about-title2:before{ - content: ""; - font-family: var(--special-font); -} - -.about-title2{ - margin-top: -3%; - text-align: left; - font-size: 15px; - margin-left: -4%; -} - -@keyframes upndown { - 0% { - transform: translateY(5px); - } - 50% { - transform: translateY(15px); - } - 100% { - transform: translateY(5px); - } -} -@keyframes smallnbig { - 0% { - width: 90px; - } - 50% { - width: 100px; - } - 100% { - width: 90px; - } -} -@keyframes shine { - 0% { - opacity: .2; - } - 25% { - opacity: .1; - } - 50% { - opacity: .2; - } - 100% { - opacity: .2; - } -} - - -/* ===== Projects Box =====*/ - -.projects_section{ - padding: 10px; -} -.body__projects{ - background-color: #fff; - font-family: var(--body-font); - font-size: var(--normal-font-size); - min-height: 100vh; - margin-left: 4%; - margin-bottom: 2%; -} - -.projects_div{ - display: flex; -} - -.project_cards{ - position: relative; - margin: 0 auto; - width: 1000px; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - grid-template-rows: minmax(100px, auto); - grid-auto-flow: dense; - gap: 20px; - align-items: start; -} - -.project_card{ - transition: 0.5s; -} - -.project_card:hover{ - transition: 0.5s; - transform: translateY(-0.8%); -} - -.project_image{ - width: 100%; - display: block; - border-radius: 10px; - margin-bottom: -2%; -} - - -.project_content{ - line-height: 1.5; - font-size: 0.9em; - background: linear-gradient(#fafafa, #ecfeff); - transition: 0.5s; - border-radius: 10px; - padding-bottom: 200px; -} - -.project_content:hover{ - transition: 0.5s; - transform: translateY(-0.8%); -} - -.project_content > h2:first-of-type{ - padding-left: 15px; - padding-right: 15px; - padding-top: 10px; -} - -.project_content > p:first-of-type{ - padding-left: 15px; - padding-right: 15px; -} - -.project__info{ - display: flex; - justify-content: center; - align-items: center; - font-size: 40px; - border-bottom: 2px solid #cccccc; - color: var(--first-color); - border-radius: 10px; - margin-top: 1%; - background-color: #ebebeb; - transition: 0.5s; - padding-top: 7px; -} - -.project__info:hover{ - transition: 0.5s; - background-color: var(--first-color-light); -} - - -.projects_title{ - transition: 0.5s; - display: flex; - text-align: center; - justify-content: center; - font-family: var(--title-font); - font-size: 35px; - margin-bottom: 4%; - -} - -.projects_title:hover { - transition: 0.2s; - color: #00C2CB; - cursor:default; -} - -.projects_section{ - margin-top: 3.5%; - margin-bottom: 4%; -} - -.button_2{ - background: var(--first-color); - border: 1px solid transparent; - border-radius: 10px; - height: 50px; - text-align: center; - text-decoration: none; - color: #fff; - line-height: 50px; - font-size: 18px; - padding: 0 70px; - white-space: nowrap; - margin-top: 25px; - transition: background .5s ease; - overflow: hidden; - -webkit-mask-image: -webkit-radial-gradient(white, black); - mask-image: -webkit-radial-gradient(white, black); -} - -.button_2 i{ - margin-left: 6px; -} - -.button_project{ - display: flex; - justify-content: center; -} - -.button_2:hover{ - background: var(--first-color-light); - border-color: #fff; -} - - - -/* ===== WORK =====*/ - -.work_section{ - margin-bottom: 5%; -} - -.work_section2{ - margin-top: 5%; - margin-bottom: 5%; -} - -.work__title{ - position: relative; - font-size: var(--h2-font-size); - color: var(--first-color); - margin-top: var(--mb-2); - margin-bottom: var(--mb-4); - text-align: center; - font-size: 35px; - transition: 0.5s; -} - -.work__title:hover{ - transition: 0.5s; - color: var(--first-color-light); -} - -.work__title::after{ - position: absolute; - content: ""; - width: 100px; - height: 0.18rem; - left: 0; - right: 0; - margin: auto; - top: 3rem; - background-color: var(--first-color); -} -.work__subtitle{ - text-align: center; - margin-bottom: var(--mb-6); -} - -.gallery{ - position: relative; - padding: 20px; - display: flex; - justify-content: center; - align-items: center; - flex-wrap: wrap; -} - -.gallery img{ - position: relative; - display: flex; - object-fit: cover; - object-position: top; -} - -.gallery img:hover{ - transition: 0.5s; -} - -.codeacademy_cert { - width: 83.2%; - margin-left: 9%; -} - -.container_certs{ - position: relative; - width: 1150px; - padding: 20px; - display: flex; - justify-content: center; - align-items: center; - flex-wrap: wrap; -} - -.container_certs .card_cert{ - position: relative; - width: 300px; - height: 420px; - background: #bbb; - margin: 20px; - border-radius: 20px; - overflow: hidden; - box-shadow: 0 15px 25px rgba(0, 0, 0, 0.2); - transition: 0.5s; -} - -.container_certs .card_cert .card_circ{ - position: relative; - width: 100%; - height: 100%; - background: #000; - clip-path: circle(180px at center 0); - text-align: center; - margin-top: -20%; -} - -.container_certs .card_cert .card_circ h2{ - color: #fff; - font-size: 4.5em; - padding: 30px 0; - -} -.container_certs .card_cert .content_cert{ - - position: absolute; - bottom: 10px; - padding: 20px; - text-align: center; - -} - -.container_certs .card_cert .content_cert p{ - color: #666; -} -.container_certs .card_cert .content_cert a{ - margin-top: 20px; -} - - - - -/* ===== CONTACT =====*/ -.body__contact{ - font-family: var(--body-font); - font-size: var(--normal-font-size); - background-color: #00c1cb1c; - background-repeat: no-repeat; -} -.contact{ - padding-bottom: 5%; -} - -.contact_2{ - padding-bottom: 5%; - padding-top: 5%; - background-size: cover; -} - -.contact_form{ - max-width: 600px; - margin:auto; - padding: 0 10px; - overflow: hidden; -} - -.contact_form_text{ - display: block; - width: 100%; - box-sizing: border-box; - margin: 16px 0; - border: 0; - background: var(--first-color); - padding: 20px 40px; - outline: none; - color: #ddd; - transition: 0.5s; -} - -.contact_form_text:hover{ - box-shadow: 0 0 10px 4px #34495e; - font-family: var(--body-font); -} - -textarea.contact_form_text{ - resize: none; - height: 120px; - font-family: var(--body-font); -} - -.button_c{ - float: right; - border: 0; - background: var(--first-color); - color: #fff; - padding: 12px 50px; - border-radius: 8px; - cursor: pointer; - font-family: var(--body-font); - transition: 0.5s; -} - -.button_c:hover{ - transition: 0.5s; - background: #00C2CB; -} - - -.contact_title{ - font-size: 35px; - text-align: center; - transition: 0.5s; -} - -.contact_title:hover{ - transition: 0.5s; - color: var(--first-color-light) -} - -/* ===== Thanks =====*/ -.body__thanks{ - font-family: var(--body-font); - font-size: var(--normal-font-size); -} - -.thanks__title{ - text-align: center; - font-size: 40px; -} - -.thanks_icon{ - text-align: center; - margin-top: 25%; - font-size: 150px; - transition: 0.5s; -} - -.thanks_icon:hover{ - transition: 0.5s; - font-size: 180px; - color: #00C2CB; -} - -.thanks_content{ - display: flex; - align-items: center; - justify-content: center; -} - -.thanks_button{ - - display: flex; - align-items: center; - justify-content: center; -} - -.button_3{ - display: block; - position: relative; - background: var(--first-color); - border: 1px solid transparent; - border-radius: 10px; - height: 50px; - text-align: center; - text-decoration: none; - color: #fff; - line-height: 50px; - font-size: 18px; - padding: 0 70px; - white-space: nowrap; - margin-top: 25px; - transition: background .5s ease; - overflow: hidden; - -webkit-mask-image: -webkit-radial-gradient(white, black); - mask-image: -webkit-radial-gradient(white, black); - display: inline-block; - width: 250px; -} - -.button_3:before{ - content: ''; - position: absolute; - width: 20px; - height: 100px; - background: #fff; - bottom: -25px; - left: 0; - border: 2px solid #fff; - transform: translateX(-50px) rotate(45deg); - transition: transform .5s ease; -} - -.button_3:hover{ - background: var(--first-color-light); - border-color: #fff; -} - -.button_3:hover::before{ - transform: translateX(250px) rotate(45deg); -} - - -/* ===== MEDIA QUERIES=====*/ -@media screen and (min-width: 768px){ - .index__body{ - margin: calc(var(--header-height) + 1rem) 0 0 0; - padding-left: calc(var(--nav-width) + 2rem); - /*background: linear-gradient(90deg, rgba(255,255,255,0.8267682072829132) 0%, rgba(179,179,179,1) 54%, rgba(14,36,49,0.9556197478991597) 100%); - background: cover; - background-repeat: none;*/ - } - - .section{ - padding-bottom: 3rem; - height: 100vh; - } - .section-title{ - margin-bottom: var(--mb-6); - } - .section-title::after{ - width: 80px; - top: 3rem; - } - - .body__about{ - margin: calc(var(--header-height) + 1rem) 0 0 0; - padding-left: calc(var(--nav-width) + 2rem); - background: rgb(255,255,255); - } - - .header{ - height: calc(var(--header-height) + 1rem); - padding: 0 2rem 0 calc(var(--nav-width) + 2rem); - } - - .header__img{ - width: 40px; - height: 40px; - } - - .header__img img{ - width: 45px; - } - - .home__title{ - font-size: 60px; - font-weight: 1000; - text-align: left; - margin-bottom: -5px; - margin-left: 2%; - line-height: 70px; - } - - .home__subtitle{ - font-size: 15px; - text-align: left; - margin-left: 2%; - } - - .about_section{ - margin-left: -2%; - align-self: left; - } - - .button{ - margin-left: 2%; - display: inline-block; - width: 250px; - border-radius: 5px; - } - - .skills-grid { - grid-template-columns: repeat(4, 1fr); - } - - .button_wrapper{ - display: flex; - align-items: left; - justify-content: left; - } - - .thanks_button{ - margin-top: -2%; - display: flex; - align-items: center; - justify-content: center; - } - .button_3{ - display: inline-block; - width: 250px; - border-radius: 5px; - } - - .button_2{ - display: flex; - width: 250px; - border-radius: 5px; - justify-content: center; - align-items: center; - } - - .thanks__title{ - - text-align: center; - font-size: 60px; - } - - .thanks_icon{ - text-align: center; - margin-top: 10%; - font-size: 150px; - transition: 0.5s; - } - - .thanks_icon:hover{ - transition: 0.5s; - font-size: 180px; - color: #00C2CB; - } - - .thanks_content{ - display: flex; - align-items: center; - justify-content: center; - } - - .l-navbar{ - left: 0; - padding: 1rem 1rem 0 0; - } - - /*Show navbar desktop*/ - .show{ - width: calc(var(--nav-width) + 156px); - } - - /*Add padding body desktop*/ - .body-pd{ - padding-left: calc(var(--nav-width) + 188px); - } - - .project_content{ - height: 325px; - } - - .wrapper{ - display: flex; - justify-content: center; - } - - .gallery{ - display: grid; - grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); - } - - .ibm_certificate{ - height: 410px; - margin-left: 5%; - } - - .badge{ - display: none; - } - - .badge_2{ - margin-right: 5%; - } -} - -@media screen and (min-width: 1024px){ - .bd-grid{ - margin-left: auto; - margin-right: auto; - } -} - -@media only screen and (max-width: 700px) { - .responsive { - width: 49.99999%; - margin: 6px 0; - } -} - -@media only screen and (max-width: 500px) { - .responsive { - width: 100%; - } -} \ No newline at end of file diff --git a/assets/images/1.webp b/assets/images/1.webp new file mode 100644 index 0000000..7ff9de3 Binary files /dev/null and b/assets/images/1.webp differ diff --git a/assets/images/10.webp b/assets/images/10.webp new file mode 100644 index 0000000..9d7e995 Binary files /dev/null and b/assets/images/10.webp differ diff --git a/assets/images/11.png b/assets/images/11.png new file mode 100644 index 0000000..0430531 Binary files /dev/null and b/assets/images/11.png differ diff --git a/assets/images/11.webp b/assets/images/11.webp new file mode 100644 index 0000000..936ba54 Binary files /dev/null and b/assets/images/11.webp differ diff --git a/assets/images/12.webp b/assets/images/12.webp new file mode 100644 index 0000000..0cde36b Binary files /dev/null and b/assets/images/12.webp differ diff --git a/assets/images/13.webp b/assets/images/13.webp new file mode 100644 index 0000000..c727e07 Binary files /dev/null and b/assets/images/13.webp differ diff --git a/assets/images/14.webp b/assets/images/14.webp new file mode 100644 index 0000000..e4ca400 Binary files /dev/null and b/assets/images/14.webp differ diff --git a/assets/images/15.webp b/assets/images/15.webp new file mode 100644 index 0000000..6a16d3f Binary files /dev/null and b/assets/images/15.webp differ diff --git a/assets/images/16.webp b/assets/images/16.webp new file mode 100644 index 0000000..f163f70 Binary files /dev/null and b/assets/images/16.webp differ diff --git a/assets/images/17.webp b/assets/images/17.webp new file mode 100644 index 0000000..b3b4b3b Binary files /dev/null and b/assets/images/17.webp differ diff --git a/assets/images/18.webp b/assets/images/18.webp new file mode 100644 index 0000000..c9eef5c Binary files /dev/null and b/assets/images/18.webp differ diff --git a/assets/images/19.webp b/assets/images/19.webp new file mode 100644 index 0000000..48da85e Binary files /dev/null and b/assets/images/19.webp differ diff --git a/assets/images/2.webp b/assets/images/2.webp new file mode 100644 index 0000000..8710ca3 Binary files /dev/null and b/assets/images/2.webp differ diff --git a/assets/images/20.webp b/assets/images/20.webp new file mode 100644 index 0000000..af1afa4 Binary files /dev/null and b/assets/images/20.webp differ diff --git a/assets/images/21.webp b/assets/images/21.webp new file mode 100644 index 0000000..e95b0ca Binary files /dev/null and b/assets/images/21.webp differ diff --git a/assets/images/22.webp b/assets/images/22.webp new file mode 100644 index 0000000..ab3b68a Binary files /dev/null and b/assets/images/22.webp differ diff --git a/assets/images/23.webp b/assets/images/23.webp new file mode 100644 index 0000000..7262ac0 Binary files /dev/null and b/assets/images/23.webp differ diff --git a/assets/images/3.webp b/assets/images/3.webp new file mode 100644 index 0000000..4ebd34f Binary files /dev/null and b/assets/images/3.webp differ diff --git a/assets/images/4.webp b/assets/images/4.webp new file mode 100644 index 0000000..11b11cd Binary files /dev/null and b/assets/images/4.webp differ diff --git a/assets/images/5.webp b/assets/images/5.webp new file mode 100644 index 0000000..219bf18 Binary files /dev/null and b/assets/images/5.webp differ diff --git a/assets/images/6.webp b/assets/images/6.webp new file mode 100644 index 0000000..54fc0cb Binary files /dev/null and b/assets/images/6.webp differ diff --git a/assets/images/7.webp b/assets/images/7.webp new file mode 100644 index 0000000..801d3ff Binary files /dev/null and b/assets/images/7.webp differ diff --git a/assets/images/8.webp b/assets/images/8.webp new file mode 100644 index 0000000..e050bd3 Binary files /dev/null and b/assets/images/8.webp differ diff --git a/assets/images/9.webp b/assets/images/9.webp new file mode 100644 index 0000000..dca3bd5 Binary files /dev/null and b/assets/images/9.webp differ diff --git a/assets/images/PDFGPT.jpg b/assets/images/PDFGPT.jpg new file mode 100644 index 0000000..572dd7d Binary files /dev/null and b/assets/images/PDFGPT.jpg differ diff --git a/assets/images/air.jpg b/assets/images/air.jpg new file mode 100644 index 0000000..2244d33 Binary files /dev/null and b/assets/images/air.jpg differ diff --git a/assets/images/assistant.jpg b/assets/images/assistant.jpg new file mode 100644 index 0000000..46bba54 Binary files /dev/null and b/assets/images/assistant.jpg differ diff --git a/assets/images/bar.webp b/assets/images/bar.webp new file mode 100644 index 0000000..197d89a Binary files /dev/null and b/assets/images/bar.webp differ diff --git a/assets/images/brain.webp b/assets/images/brain.webp new file mode 100644 index 0000000..3bd7605 Binary files /dev/null and b/assets/images/brain.webp differ diff --git a/assets/img/DL_crt.png b/assets/images/certs/DL_crt.png similarity index 100% rename from assets/img/DL_crt.png rename to assets/images/certs/DL_crt.png diff --git a/assets/img/certificate_1.webp b/assets/images/certs/certificate_1.webp similarity index 100% rename from assets/img/certificate_1.webp rename to assets/images/certs/certificate_1.webp diff --git a/assets/img/certificate_2.webp b/assets/images/certs/certificate_2.webp similarity index 100% rename from assets/img/certificate_2.webp rename to assets/images/certs/certificate_2.webp diff --git a/assets/img/certificate_3.webp b/assets/images/certs/certificate_3.webp similarity index 100% rename from assets/img/certificate_3.webp rename to assets/images/certs/certificate_3.webp diff --git a/assets/img/certificate_4.webp b/assets/images/certs/certificate_4.webp similarity index 100% rename from assets/img/certificate_4.webp rename to assets/images/certs/certificate_4.webp diff --git a/assets/img/certificate_5.webp b/assets/images/certs/certificate_5.webp similarity index 100% rename from assets/img/certificate_5.webp rename to assets/images/certs/certificate_5.webp diff --git a/assets/img/certificate_ibm.png b/assets/images/certs/certificate_ibm.png similarity index 100% rename from assets/img/certificate_ibm.png rename to assets/images/certs/certificate_ibm.png diff --git a/assets/img/kncert.png b/assets/images/certs/kncert.png similarity index 100% rename from assets/img/kncert.png rename to assets/images/certs/kncert.png diff --git a/assets/img/perceptronscert.png b/assets/images/certs/perceptronscert.png similarity index 100% rename from assets/img/perceptronscert.png rename to assets/images/certs/perceptronscert.png diff --git a/assets/img/regressioncert.png b/assets/images/certs/regressioncert.png similarity index 100% rename from assets/img/regressioncert.png rename to assets/images/certs/regressioncert.png diff --git a/assets/images/clubgs.jpg b/assets/images/clubgs.jpg new file mode 100644 index 0000000..9d9bc2b Binary files /dev/null and b/assets/images/clubgs.jpg differ diff --git a/assets/images/clubgs.webp b/assets/images/clubgs.webp new file mode 100644 index 0000000..bc89e14 Binary files /dev/null and b/assets/images/clubgs.webp differ diff --git a/assets/images/discordfeedback.jpg b/assets/images/discordfeedback.jpg new file mode 100644 index 0000000..22b7b88 Binary files /dev/null and b/assets/images/discordfeedback.jpg differ diff --git a/assets/images/dns.jpg b/assets/images/dns.jpg new file mode 100644 index 0000000..7b1e5a0 Binary files /dev/null and b/assets/images/dns.jpg differ diff --git a/assets/images/drug.jpg b/assets/images/drug.jpg new file mode 100644 index 0000000..07c44bf Binary files /dev/null and b/assets/images/drug.jpg differ diff --git a/assets/images/exoplanet.jpg b/assets/images/exoplanet.jpg new file mode 100644 index 0000000..f7f04d6 Binary files /dev/null and b/assets/images/exoplanet.jpg differ diff --git a/assets/images/gpu.webp b/assets/images/gpu.webp new file mode 100644 index 0000000..3b4afa5 Binary files /dev/null and b/assets/images/gpu.webp differ diff --git a/assets/images/greenhouse.jpg b/assets/images/greenhouse.jpg new file mode 100644 index 0000000..81a2392 Binary files /dev/null and b/assets/images/greenhouse.jpg differ diff --git a/assets/images/heart.webp b/assets/images/heart.webp new file mode 100644 index 0000000..2eb785e Binary files /dev/null and b/assets/images/heart.webp differ diff --git a/assets/images/lab.webp b/assets/images/lab.webp new file mode 100644 index 0000000..96ba217 Binary files /dev/null and b/assets/images/lab.webp differ diff --git a/assets/images/melanoma.jpg b/assets/images/melanoma.jpg new file mode 100644 index 0000000..8af9ef2 Binary files /dev/null and b/assets/images/melanoma.jpg differ diff --git a/assets/images/pc.webp b/assets/images/pc.webp new file mode 100644 index 0000000..dc07b7a Binary files /dev/null and b/assets/images/pc.webp differ diff --git a/assets/images/peltier.jpg b/assets/images/peltier.jpg new file mode 100644 index 0000000..4b3c236 Binary files /dev/null and b/assets/images/peltier.jpg differ diff --git a/assets/images/podcast.jpg b/assets/images/podcast.jpg new file mode 100644 index 0000000..74b161a Binary files /dev/null and b/assets/images/podcast.jpg differ diff --git a/assets/images/profile.webp b/assets/images/profile.webp new file mode 100644 index 0000000..e38b861 Binary files /dev/null and b/assets/images/profile.webp differ diff --git a/assets/images/qrpigeon.png b/assets/images/qrpigeon.png new file mode 100644 index 0000000..2d4eec0 Binary files /dev/null and b/assets/images/qrpigeon.png differ diff --git a/assets/images/redirectingProjects.png b/assets/images/redirectingProjects.png new file mode 100644 index 0000000..faf42e2 Binary files /dev/null and b/assets/images/redirectingProjects.png differ diff --git a/assets/images/server_profile.webp b/assets/images/server_profile.webp new file mode 100644 index 0000000..417e59e Binary files /dev/null and b/assets/images/server_profile.webp differ diff --git a/assets/images/sklearn.jpg b/assets/images/sklearn.jpg new file mode 100644 index 0000000..7b32030 Binary files /dev/null and b/assets/images/sklearn.jpg differ diff --git a/assets/images/swe.webp b/assets/images/swe.webp new file mode 100644 index 0000000..79d55d6 Binary files /dev/null and b/assets/images/swe.webp differ diff --git a/assets/images/tensorflow.jpg b/assets/images/tensorflow.jpg new file mode 100644 index 0000000..95fe929 Binary files /dev/null and b/assets/images/tensorflow.jpg differ diff --git a/assets/images/weather.jpg b/assets/images/weather.jpg new file mode 100644 index 0000000..ac2dee4 Binary files /dev/null and b/assets/images/weather.jpg differ diff --git a/assets/img/BEO.mp4 b/assets/img/BEO.mp4 deleted file mode 100644 index 3b5747b..0000000 Binary files a/assets/img/BEO.mp4 and /dev/null differ diff --git a/assets/img/DL.png b/assets/img/DL.png deleted file mode 100644 index 1aadcea..0000000 Binary files a/assets/img/DL.png and /dev/null differ diff --git a/assets/img/Tutorial-Sklearn.jpg b/assets/img/Tutorial-Sklearn.jpg deleted file mode 100644 index ba04179..0000000 Binary files a/assets/img/Tutorial-Sklearn.jpg and /dev/null differ diff --git a/assets/img/air_p.jpg b/assets/img/air_p.jpg deleted file mode 100644 index 3d052a1..0000000 Binary files a/assets/img/air_p.jpg and /dev/null differ diff --git a/assets/img/arduino.png b/assets/img/arduino.png deleted file mode 100644 index 496f43e..0000000 Binary files a/assets/img/arduino.png and /dev/null differ diff --git a/assets/img/bioinv/1.jpeg b/assets/img/bioinv/1.jpeg deleted file mode 100644 index c2e9532..0000000 Binary files a/assets/img/bioinv/1.jpeg and /dev/null differ diff --git a/assets/img/bioinv/2.jpeg b/assets/img/bioinv/2.jpeg deleted file mode 100644 index 38f3397..0000000 Binary files a/assets/img/bioinv/2.jpeg and /dev/null differ diff --git "a/assets/img/bioinv/Estaci\303\263n de Control.jpeg" "b/assets/img/bioinv/Estaci\303\263n de Control.jpeg" deleted file mode 100644 index 4b2bf1e..0000000 Binary files "a/assets/img/bioinv/Estaci\303\263n de Control.jpeg" and /dev/null differ diff --git a/assets/img/bioinv/Foto #2 Transplante.jpeg b/assets/img/bioinv/Foto #2 Transplante.jpeg deleted file mode 100644 index 12f951f..0000000 Binary files a/assets/img/bioinv/Foto #2 Transplante.jpeg and /dev/null differ diff --git a/assets/img/bioinv/Invernadero -1.jpeg b/assets/img/bioinv/Invernadero -1.jpeg deleted file mode 100644 index 174ab5b..0000000 Binary files a/assets/img/bioinv/Invernadero -1.jpeg and /dev/null differ diff --git a/assets/img/bioinv/Invernadero -2.jpeg b/assets/img/bioinv/Invernadero -2.jpeg deleted file mode 100644 index 5467293..0000000 Binary files a/assets/img/bioinv/Invernadero -2.jpeg and /dev/null differ diff --git a/assets/img/bioinv/Invernadero -3.jpeg b/assets/img/bioinv/Invernadero -3.jpeg deleted file mode 100644 index ff0c233..0000000 Binary files a/assets/img/bioinv/Invernadero -3.jpeg and /dev/null differ diff --git "a/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 1.jpeg" "b/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 1.jpeg" deleted file mode 100644 index 7066bfd..0000000 Binary files "a/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 1.jpeg" and /dev/null differ diff --git "a/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 2.jpeg" "b/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 2.jpeg" deleted file mode 100644 index df926c7..0000000 Binary files "a/assets/img/bioinv/Medici\303\263n_y_Correcci\303\263n 2.jpeg" and /dev/null differ diff --git "a/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos - 2.jpeg" "b/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos - 2.jpeg" deleted file mode 100644 index dbee8d8..0000000 Binary files "a/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos - 2.jpeg" and /dev/null differ diff --git "a/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos.jpeg" "b/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos.jpeg" deleted file mode 100644 index 0a3afac..0000000 Binary files "a/assets/img/bioinv/Primera Fase - Distribuci\303\263n de los tratamientos.jpeg" and /dev/null differ diff --git a/assets/img/bioinv/inv1.png b/assets/img/bioinv/inv1.png deleted file mode 100644 index 91df37c..0000000 Binary files a/assets/img/bioinv/inv1.png and /dev/null differ diff --git a/assets/img/cas_inf.jfif b/assets/img/cas_inf.jfif deleted file mode 100644 index f9854ca..0000000 Binary files a/assets/img/cas_inf.jfif and /dev/null differ diff --git a/assets/img/drug-medicator/example.png b/assets/img/drug-medicator/example.png deleted file mode 100644 index fac92b8..0000000 Binary files a/assets/img/drug-medicator/example.png and /dev/null differ diff --git a/assets/img/drug-medicator/github.png b/assets/img/drug-medicator/github.png deleted file mode 100644 index 20d7fc6..0000000 Binary files a/assets/img/drug-medicator/github.png and /dev/null differ diff --git a/assets/img/drug.jpg b/assets/img/drug.jpg deleted file mode 100644 index f816adf..0000000 Binary files a/assets/img/drug.jpg and /dev/null differ diff --git a/assets/img/exoplanet.jpg b/assets/img/exoplanet.jpg deleted file mode 100644 index 1f979ce..0000000 Binary files a/assets/img/exoplanet.jpg and /dev/null differ diff --git a/assets/img/exoplanet/cliui.png b/assets/img/exoplanet/cliui.png deleted file mode 100644 index 5ade69d..0000000 Binary files a/assets/img/exoplanet/cliui.png and /dev/null differ diff --git a/assets/img/exoplanet/graphs.png b/assets/img/exoplanet/graphs.png deleted file mode 100644 index 9503a77..0000000 Binary files a/assets/img/exoplanet/graphs.png and /dev/null differ diff --git a/assets/img/exoplanet/planet_vs_rvelocity.jpg b/assets/img/exoplanet/planet_vs_rvelocity.jpg deleted file mode 100644 index 3fe914d..0000000 Binary files a/assets/img/exoplanet/planet_vs_rvelocity.jpg and /dev/null differ diff --git a/assets/img/exoplanet/usage.png b/assets/img/exoplanet/usage.png deleted file mode 100644 index a0591b2..0000000 Binary files a/assets/img/exoplanet/usage.png and /dev/null differ diff --git a/assets/img/iot.jpeg b/assets/img/iot.jpeg deleted file mode 100644 index 7ecb098..0000000 Binary files a/assets/img/iot.jpeg and /dev/null differ diff --git a/assets/img/pdfgpt.png b/assets/img/pdfgpt.png deleted file mode 100644 index cd1603a..0000000 Binary files a/assets/img/pdfgpt.png and /dev/null differ diff --git a/assets/img/peltier.png b/assets/img/peltier.png deleted file mode 100644 index f5d2e3c..0000000 Binary files a/assets/img/peltier.png and /dev/null differ diff --git a/assets/img/perfil.png b/assets/img/perfil.png deleted file mode 100644 index b5d4040..0000000 Binary files a/assets/img/perfil.png and /dev/null differ diff --git a/assets/img/perfil_2.jfif b/assets/img/perfil_2.jfif deleted file mode 100644 index ef391de..0000000 Binary files a/assets/img/perfil_2.jfif and /dev/null differ diff --git a/assets/img/pod.jpg b/assets/img/pod.jpg deleted file mode 100644 index 4f47b33..0000000 Binary files a/assets/img/pod.jpg and /dev/null differ diff --git a/assets/img/pod_2.png b/assets/img/pod_2.png deleted file mode 100644 index 8307701..0000000 Binary files a/assets/img/pod_2.png and /dev/null differ diff --git a/assets/img/python-logo.png b/assets/img/python-logo.png deleted file mode 100644 index ef08f0c..0000000 Binary files a/assets/img/python-logo.png and /dev/null differ diff --git a/assets/img/resp.jpg b/assets/img/resp.jpg deleted file mode 100644 index c0be65f..0000000 Binary files a/assets/img/resp.jpg and /dev/null differ diff --git a/assets/img/temp-hum.png b/assets/img/temp-hum.png deleted file mode 100644 index 98b628a..0000000 Binary files a/assets/img/temp-hum.png and /dev/null differ diff --git a/assets/img/temphumpredictor/geo.png b/assets/img/temphumpredictor/geo.png deleted file mode 100644 index 03bf4d8..0000000 Binary files a/assets/img/temphumpredictor/geo.png and /dev/null differ diff --git a/assets/img/temphumpredictor/inv.png b/assets/img/temphumpredictor/inv.png deleted file mode 100644 index 6b226f7..0000000 Binary files a/assets/img/temphumpredictor/inv.png and /dev/null differ diff --git a/assets/img/temphumpredictor/ui.png b/assets/img/temphumpredictor/ui.png deleted file mode 100644 index 49a9f49..0000000 Binary files a/assets/img/temphumpredictor/ui.png and /dev/null differ diff --git a/assets/img/temphumpredictor/usage.png b/assets/img/temphumpredictor/usage.png deleted file mode 100644 index da02c81..0000000 Binary files a/assets/img/temphumpredictor/usage.png and /dev/null differ diff --git a/assets/img/voice.jpeg b/assets/img/voice.jpeg deleted file mode 100644 index 14507e9..0000000 Binary files a/assets/img/voice.jpeg and /dev/null differ diff --git a/assets/img/ytqp.png b/assets/img/ytqp.png deleted file mode 100644 index f5b5a4d..0000000 Binary files a/assets/img/ytqp.png and /dev/null differ diff --git a/assets/img/ytqp_web.png b/assets/img/ytqp_web.png deleted file mode 100644 index e1240af..0000000 Binary files a/assets/img/ytqp_web.png and /dev/null differ diff --git a/assets/js/ScrollTrigger.min.js b/assets/js/ScrollTrigger.min.js new file mode 100644 index 0000000..070c4cd --- /dev/null +++ b/assets/js/ScrollTrigger.min.js @@ -0,0 +1,11 @@ +/*! + * ScrollTrigger 3.12.2 + * https://greensock.com + * + * @license Copyright 2023, GreenSock. All rights reserved. + * Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership. + * @author: Jack Doyle, jack@greensock.com + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function _defineProperties(e,t){for(var r=0;r=Math.abs(r)?t:r}function O(){(Ae=Se.core.globals().ScrollTrigger)&&Ae.core&&function _integrate(){var e=Ae.core,r=e.bridge||{},t=e._scrollers,n=e._proxies;t.push.apply(t,ze),n.push.apply(n,Ie),ze=t,Ie=n,i=function _bridge(e,t){return r[e](t)}}()}function P(e){return(Se=e||r())&&"undefined"!=typeof document&&document.body&&(Te=window,Pe=(Ce=document).documentElement,Me=Ce.body,t=[Te,Ce,Pe,Me],Se.utils.clamp,De=Se.core.context||function(){},Oe="onpointerenter"in Me?"pointer":"mouse",Ee=E.isTouch=Te.matchMedia&&Te.matchMedia("(hover: none), (pointer: coarse)").matches?1:"ontouchstart"in Te||0=o,n=Math.abs(t)>=o;k&&(r||n)&&k(se,e,t,be,me),r&&(m&&0Math.abs(t)?"x":"y",ie=!0),"y"!==ae&&(be[2]+=e,se._vx.update(e,!0)),"x"!==ae&&(me[2]+=t,se._vy.update(t,!0)),n?ee=ee||requestAnimationFrame(bf):bf()}function ef(e){if(!_e(e,1)){var t=(e=M(e,s)).clientX,r=e.clientY,n=t-se.x,o=r-se.y,i=se.isDragging;se.x=t,se.y=r,(i||Math.abs(se.startX-t)>=a||Math.abs(se.startY-r)>=a)&&(h&&(re=!0),i||(se.isDragging=!0),df(n,o),i||p&&p(se))}}function hf(e){return e.touches&&1=e)return a[n];return a[n-1]}for(n=a.length,e+=r;n--;)if(a[n]<=e)return a[n];return a[0]}:function(e,t,r){void 0===r&&(r=.001);var n=i(e);return!t||Math.abs(n-e)r&&(n*=t/100),e=e.substr(0,r-1)),e=n+(e in q?q[e]*t:~e.indexOf("%")?parseFloat(e)*t/100:parseFloat(e)||0)}return e}function Bb(e,t,r,n,o,i,a,s){var l=o.startColor,c=o.endColor,u=o.fontSize,f=o.indent,d=o.fontWeight,p=Xe.createElement("div"),g=Ja(r)||"fixed"===z(r,"pinType"),h=-1!==e.indexOf("scroller"),v=g?We:r,b=-1!==e.indexOf("start"),m=b?l:c,y="border-color:"+m+";font-size:"+u+";color:"+m+";font-weight:"+d+";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";return y+="position:"+((h||s)&&g?"fixed;":"absolute;"),!h&&!s&&g||(y+=(n===He?D:I)+":"+(i+parseFloat(f))+"px;"),a&&(y+="box-sizing:border-box;text-align:left;width:"+a.offsetWidth+"px;"),p._isStart=b,p.setAttribute("class","gsap-marker-"+e+(t?" marker-"+t:"")),p.style.cssText=y,p.innerText=t||0===t?e+"-"+t:e,v.children[0]?v.insertBefore(p,v.children[0]):v.appendChild(p),p._offset=p["offset"+n.op.d2],H(p,0,n,b),p}function Gb(){return 34We.clientWidth)||(ze.cache++,v?k=k||requestAnimationFrame(Q):Q(),st||V("scrollStart"),st=at())}function Ib(){y=Ne.innerWidth,m=Ne.innerHeight}function Jb(){ze.cache++,je||h||Xe.fullscreenElement||Xe.webkitFullscreenElement||b&&y===Ne.innerWidth&&!(Math.abs(Ne.innerHeight-m)>.25*Ne.innerHeight)||c.restart(!0)}function Mb(){return vb(re,"scrollEnd",Mb)||Pt(!0)}function Pb(e){for(var t=0;tt)&&e.setPositions(e.start,Math.max(e.start+1,t),!0)}),r.forEach(function(e){return e&&e.render&&e.render(-1)}),ze.forEach(function(e){Ra(e)&&(e.smooth&&requestAnimationFrame(function(){return e.target.style.scrollBehavior="smooth"}),e.rec&&e(e.rec))}),Rb(_,1),c.pause(),Ct++,Q(rt=2),kt.forEach(function(e){return Ra(e.vars.onRefresh)&&e.vars.onRefresh(e)}),rt=re.isRefreshing=!1,V("refresh")}else ub(re,"scrollEnd",Mb)},j=0,Mt=1,Q=function _updateAll(e){if(!rt||2===e){re.isUpdating=!0,ot&&ot.update(0);var t=kt.length,r=at(),n=50<=r-T,o=t&&kt[0].scroll();if(Mt=o=F})},ke.update=function(e,t,r){if(!de||r||e){var n,o,i,a,s,l,c,u=!0===rt?re:ke.scroll(),f=e?0:(u-D)/N,d=f<0?0:1=Oa(be,he),fe)if(e||!n&&!l)lc(ae,V);else{var g=_t(ae,!0),h=u-D;lc(ae,We,g.top+(he===He?h:0)+xt,g.left+(he===He?0:h)+xt)}Et(n||l?W:G),Z&&d<1&&n||b(j+(1!==d||l?0:Q))}}else b(Ga(j+Q*d));!ue||A.tween||je||it||te.restart(!0),T&&(s||ce&&d&&(d<1||!tt))&&Ge(T.targets).forEach(function(e){return e.classList[n||ce?"add":"remove"](T.className)}),!k||ve||e||k(ke),a&&!je?(ve&&(c&&("complete"===i?O.pause().totalProgress(1):"reset"===i?O.restart(!0).pause():"restart"===i?O.restart(!0):O[i]()),k&&k(ke)),!s&&tt||(C&&s&&Va(ke,C),xe[o]&&Va(ke,xe[o]),ce&&(1===d?ke.kill(!1,1):xe[o]=0),s||xe[o=1===d?1:3]&&Va(ke,xe[o])),pe&&!n&&Math.abs(ke.getVelocity())>(Sa(pe)?pe:2500)&&(Ua(ke.callbackAnimation),ee?ee.progress(1):Ua(O,"reverse"===i?1:!d,1))):ve&&k&&!je&&k(ke)}if(x){var v=de?u/de.duration()*(de._caScrollDist||0):u;y(v+(q._isFlipped?1:0)),x(v)}S&&S(-u/de.duration()*(de._caScrollDist||0))}},ke.enable=function(e,t){ke.enabled||(ke.enabled=!0,ub(be,"resize",Jb),me||ub(be,"scroll",Hb),Te&&ub(ScrollTrigger,"refreshInit",Te),!1!==e&&(ke.progress=Oe=0,R=B=Me=Ae()),!1!==t&&ke.refresh())},ke.getTween=function(e){return e&&A?A.tween:ee},ke.setPositions=function(e,t,r,n){if(de){var o=de.scrollTrigger,i=de.duration(),a=o.end-o.start;e=o.start+a*e/i,t=o.start+a*t/i}ke.refresh(!1,!1,{start:Ba(e,r&&!!ke._startClamp),end:Ba(t,r&&!!ke._endClamp)},n),ke.update()},ke.adjustPinSpacing=function(e){if($&&e){var t=$.indexOf(he.d)+1;$[t]=parseFloat($[t])+e+xt,$[1]=parseFloat($[1])+e+xt,Et($)}},ke.disable=function(e,t){if(ke.enabled&&(!1!==e&&ke.revert(!0,!0),ke.enabled=ke.isActive=!1,t||ee&&ee.pause(),re=0,n&&(n.uncache=1),Te&&vb(ScrollTrigger,"refreshInit",Te),te&&(te.pause(),A.tween&&A.tween.kill()&&(A.tween=0)),!me)){for(var r=kt.length;r--;)if(kt[r].scroller===be&&kt[r]!==ke)return;vb(be,"resize",Jb),me||vb(be,"scroll",Hb)}},ke.kill=function(e,t){ke.disable(e,t),ee&&!t&&ee.kill(),a&&delete Tt[a];var r=kt.indexOf(ke);0<=r&&kt.splice(r,1),r===Qe&&0i&&(b()>i?a.progress(1)&&b(i):a.resetTo("scrollY",i))}Ta(e)||(e={}),e.preventDefault=e.isNormalizer=e.allowClicks=!0,e.type||(e.type="wheel,touch"),e.debounce=!!e.debounce,e.id=e.id||"normalizer";var n,i,l,o,a,c,u,s,f=e.normalizeScrollX,t=e.momentum,r=e.allowNestedScroll,d=e.onRelease,p=J(e.target)||Je,g=Le.core.globals().ScrollSmoother,h=g&&g.get(),v=R&&(e.content&&J(e.content)||h&&!1!==e.content&&!h.smooth()&&h.content()),b=K(p,He),m=K(p,qe),y=1,x=(E.isTouch&&Ne.visualViewport?Ne.visualViewport.scale*Ne.visualViewport.width:Ne.outerWidth)/Ne.innerWidth,_=0,w=Ra(t)?function(){return t(n)}:function(){return t||2.8},S=uc(p,e.type,!0,r),k=Fa,T=Fa;return v&&Le.set(v,{y:"+=0"}),e.ignoreCheck=function(e){return R&&"touchmove"===e.type&&function ignoreDrag(){if(o){requestAnimationFrame(rq);var e=Ga(n.deltaY/2),t=T(b.v-e);if(v&&t!==b.v+b.offset){b.offset=t-b.v;var r=Ga((parseFloat(v&&v._gsap.y)||0)-b.offset);v.style.transform="matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, "+r+", 0, 1)",v._gsap.y=r+"px",b.cacheID=ze.cache,Q()}return!0}b.offset&&vq(),o=!0}()||1.05=i||i-1<=r)&&Le.to({},{onUpdate:Bq,duration:o})}else s.restart(!0);d&&d(e)},e.onWheel=function(){a._ts&&a.pause(),1e3 (1 - n) * a + n * b; + + /** + * Gets the cursor position + * @param {Event} ev - mousemove event + */ + const getCursorPos = ev => { + return { + x : ev.clientX, + y : ev.clientY + }; + }; + + // Track the cursor position + let cursor = {x: 0, y: 0}; + window.addEventListener('mousemove', ev => cursor = getCursorPos(ev)); + + /** + * Class representing a custom cursor. + * A Cursor can have multiple elements/svgs + */ + class Cursor { + // DOM elements + DOM = { + // cursor elements (SVGs .cursor) + elements: null, + } + // All CursorElement instances + cursorElements = []; + + /** + * Constructor. + * @param {NodeList} Dom_elems - all .cursor elements + * @param {String} triggerSelector - Trigger the cursor enter/leave method on the this selector returned elements. Default is all . + */ + constructor(Dom_elems, triggerSelector = 'a') { + this.DOM.elements = Dom_elems; + + [...this.DOM.elements].forEach(el => this.cursorElements.push(new CursorElement(el))); + + [...document.querySelectorAll(triggerSelector)].forEach(link => { + link.addEventListener('mouseenter', () => this.enter()); + link.addEventListener('mouseleave', () => this.leave()); + }); + } + /** + * Mouseenter event + */ + enter() { + for (const el of this.cursorElements) { + el.enter(); + } + } + + /** + * Mouseleave event + */ + leave() { + for (const el of this.cursorElements) { + el.leave(); + } + } + } + + /** + * Class representing a .cursor element + */ + class CursorElement { + // DOM elements + DOM = { + // Main element (.cursor) + el: null, + // Inner element (.cursor__inner) + inner: null, + } + // Scales value when entering an element + scaleOnEnter = 1; + // Opacity value when entering an element + opacityOnEnter = 1; + // Element style properties + renderedStyles = { + // With interpolation, we can achieve a smooth animation effect when moving the cursor. + // The "previous" and "current" values are the values that will interpolate. + // The returned value will be one between these two (previous and current) at a specific increment. + // The "amt" is the amount to interpolate. + // As an example, the following formula calculates the x-axis translation value to apply to the cursor element: + // this.renderedStyles.tx.previous = lerp(this.renderedStyles.tx.previous, this.renderedStyles.tx.current, this.renderedStyles.tx.amt); + + // translation, scale and opacity values + // The lower the amt, the slower the cursor "follows" the user gesture + tx: {previous: 0, current: 0, amt: 0.2}, + ty: {previous: 0, current: 0, amt: 0.2}, + // The scale and opacity will change when hovering over any element specified in [triggerSelector] + // Defaults are 1 for both properties + scale: {previous: 1, current: 1, amt: 0.2}, + opacity: {previous: 1, current: 1, amt: 0.2} + }; + // Element size and position + bounds; + + /** + * Constructor. + */ + constructor(DOM_el) { + this.DOM.el = DOM_el; + this.DOM.inner = this.DOM.el.querySelector('.cursor__inner'); + + // Hide it initially + this.DOM.el.style.opacity = 0; + + // Calculate size and position + this.bounds = this.DOM.el.getBoundingClientRect(); + + // Check if any options passed in data attributes + this.scaleOnEnter = this.DOM.el.dataset.scaleEnter || this.scaleOnEnter; + this.opacityOnEnter = this.DOM.el.dataset.opacityEnter || this.opacityOnEnter; + for (const key in this.renderedStyles) { + this.renderedStyles[key].amt = this.DOM.el.dataset.amt || this.renderedStyles[key].amt; + } + + // Show the element and start tracking its position as soon as the user moves the cursor. + const onMouseMoveEv = () => { + // Set up the initial values to be the same + this.renderedStyles.tx.previous = this.renderedStyles.tx.current = cursor.x - this.bounds.width/2; + this.renderedStyles.ty.previous = this.renderedStyles.ty.previous = cursor.y - this.bounds.height/2; + // Show it + this.DOM.el.style.opacity = 1; + // Start rAF loop + requestAnimationFrame(() => this.render()); + // Remove the initial mousemove event + window.removeEventListener('mousemove', onMouseMoveEv); + }; + window.addEventListener('mousemove', onMouseMoveEv); + } + + /** + * Mouseenter event + * Scale up and fade out. + */ + enter() { + this.renderedStyles['scale'].current = this.scaleOnEnter; + this.renderedStyles['opacity'].current = this.opacityOnEnter; + } + + /** + * Mouseleave event + * Reset scale and opacity. + */ + leave() { + this.renderedStyles['scale'].current = 1; + this.renderedStyles['opacity'].current = 1; + } + + /** + * Loop / Interpolation + */ + render() { + // New cursor positions + this.renderedStyles['tx'].current = cursor.x - this.bounds.width/2; + this.renderedStyles['ty'].current = cursor.y - this.bounds.height/2; + + // Interpolation + for (const key in this.renderedStyles ) { + this.renderedStyles[key].previous = lerp(this.renderedStyles[key].previous, this.renderedStyles[key].current, this.renderedStyles[key].amt); + } + + // Apply interpolated values (smooth effect) + this.DOM.el.style.transform = `translateX(${(this.renderedStyles['tx'].previous)}px) translateY(${this.renderedStyles['ty'].previous}px) scale(${this.renderedStyles['scale'].previous})`; + this.DOM.el.style.opacity = this.renderedStyles['opacity'].previous; + + // loop... + requestAnimationFrame(() => this.render()); + } + } + +// Initialize custom cursor +const customCursor = new Cursor(document.querySelectorAll('.cursor')); \ No newline at end of file diff --git a/assets/js/dist/main.dev.js b/assets/js/dist/main.dev.js deleted file mode 100644 index e578a88..0000000 --- a/assets/js/dist/main.dev.js +++ /dev/null @@ -1,120 +0,0 @@ -"use strict"; - -/*===== SHOW NAVBAR =====*/ -var showNavbar = function showNavbar(toggleId, navId, bodyId, headerId) { - var toggle = document.getElementById(toggleId), - nav = document.getElementById(navId), - bodypd = document.getElementById(bodyId), - headerpd = document.getElementById(headerId); // Validate that all variables exist - - if (toggle && nav && bodypd && headerpd) { - toggle.addEventListener('click', function () { - // show navbar - nav.classList.toggle('show'); // change icon - - toggle.classList.toggle('bx-x'); // add padding to body - - bodypd.classList.toggle('body-pd'); // add padding to header - - headerpd.classList.toggle('body-pd'); - }); - } -}; - -showNavbar('header-toggle', 'nav-bar', 'body-pd', 'header'); -/*===== LINK ACTIVE =====*/ - -var linkColor = document.querySelectorAll('.nav__link'); - -function colorLink() { - if (linkColor) { - linkColor.forEach(function (l) { - return l.classList.remove('active'); - }); - this.classList.add('active'); - } -} - -linkColor.forEach(function (l) { - return l.addEventListener('click', colorLink); -}); -/*===== SCROLL REVEAL ANIMATION =====*/ - -var sr = ScrollReveal({ - origin: 'top', - distance: '80px', - duration: 2000, - reset: true -}); -/*SCROLL HOME*/ - -sr.reveal('.home__title', { - delay: 200 -}); -sr.reveal('.button', { - delay: 200 -}); -sr.reveal('.home__subtitle', { - interval: 200 -}); -/*SCROLL ABOUT*/ - -sr.reveal('.about-title', { - delay: 200 -}); -sr.reveal('.skills__data', { - delay: 200 -}); -sr.reveal('.skills__text', { - delay: 200 -}); -/*SCROLL Projects*/ - -sr.reveal('.project_card', { - delay: 100 -}); -sr.reveal('.button_project', { - delay: 100 -}); -/*SCROLL WORK*/ - -sr.reveal('.work__title', { - interval: 200 -}); -sr.reveal('.wrapper', { - interval: 300 -}); -/*SCROLL CONTACT*/ - -sr.reveal('.contact_title', { - interval: 200 -}); -sr.reveal('.contact_form_text', { - interval: 300 -}); -sr.reveal('.button_c', { - interval: 350 -}); //typing animation - -var typed = new Typed(".typing", { - strings: ["Student from the IB.", "Junior Developer.", "Python Lover.", "Future CS major."], - typeSpeed: 100, - backSpeed: 60, - loop: true -}); -var pageX = $(document).width(); -var pageY = $(document).height(); -var mouseY = 0; -var mouseX = 0; -$(document).mousemove(function (event) { - //verticalAxis - mouseY = event.pageY; - yAxis = (pageY / 2 - mouseY) / pageY * 300; //horizontalAxis - - mouseX = event.pageX / -pageX; - xAxis = -mouseX * 100 - 100; - $(".box__ghost-eyes").css({ - transform: "translate(" + xAxis + "%,-" + yAxis + "%)" - }); - console.log("X: " + xAxis); -}); \ No newline at end of file diff --git a/assets/js/galleryeffects.js b/assets/js/galleryeffects.js new file mode 100644 index 0000000..bf4fd61 --- /dev/null +++ b/assets/js/galleryeffects.js @@ -0,0 +1,9 @@ +import { preloadImages } from './utils.js'; +import { ImageTrail } from './imageTrail.js'; + +// Preload all images +preloadImages('.content__imgh-inner').then(() => { + // Instantiate a new ImageTrail object, initializing it with the element that has the class 'content'. + // The ImageTrail instance starts managing and animating the sequence of images within the specified element, reacting to mouse movements. + new ImageTrail(document.querySelector('.contenth')); +}); \ No newline at end of file diff --git a/assets/js/gsap.min.js b/assets/js/gsap.min.js new file mode 100644 index 0000000..0c38bc4 --- /dev/null +++ b/assets/js/gsap.min.js @@ -0,0 +1,11 @@ +/*! + * GSAP 3.12.2 + * https://greensock.com + * + * @license Copyright 2023, GreenSock. All rights reserved. + * Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership. + * @author: Jack Doyle, jack@greensock.com + */ + +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).window=t.window||{})}(this,function(e){"use strict";function _inheritsLoose(t,e){t.prototype=Object.create(e.prototype),(t.prototype.constructor=t).__proto__=e}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function r(t){return"string"==typeof t}function s(t){return"function"==typeof t}function t(t){return"number"==typeof t}function u(t){return void 0===t}function v(t){return"object"==typeof t}function w(t){return!1!==t}function x(){return"undefined"!=typeof window}function y(t){return s(t)||r(t)}function P(t){return(i=yt(t,ot))&&Ee}function Q(t,e){return console.warn("Invalid property",t,"set to",e,"Missing plugin? gsap.registerPlugin()")}function R(t,e){return!e&&console.warn(t)}function S(t,e){return t&&(ot[t]=e)&&i&&(i[t]=e)||ot}function T(){return 0}function ea(t){var e,r,i=t[0];if(v(i)||s(i)||(t=[t]),!(e=(i._gsap||{}).harness)){for(r=gt.length;r--&&!gt[r].targetTest(i););e=gt[r]}for(r=t.length;r--;)t[r]&&(t[r]._gsap||(t[r]._gsap=new Vt(t[r],e)))||t.splice(r,1);return t}function fa(t){return t._gsap||ea(Ot(t))[0]._gsap}function ga(t,e,r){return(r=t[e])&&s(r)?t[e]():u(r)&&t.getAttribute&&t.getAttribute(e)||r}function ha(t,e){return(t=t.split(",")).forEach(e)||t}function ia(t){return Math.round(1e5*t)/1e5||0}function ja(t){return Math.round(1e7*t)/1e7||0}function ka(t,e){var r=e.charAt(0),i=parseFloat(e.substr(2));return t=parseFloat(t),"+"===r?t+i:"-"===r?t-i:"*"===r?t*i:t/i}function la(t,e){for(var r=e.length,i=0;t.indexOf(e[i])<0&&++ia;)s=s._prev;return s?(e._next=s._next,s._next=e):(e._next=t[r],t[r]=e),e._next?e._next._prev=e:t[i]=e,e._prev=s,e.parent=e._dp=t,e}function ya(t,e,r,i){void 0===r&&(r="_first"),void 0===i&&(i="_last");var n=e._prev,a=e._next;n?n._next=a:t[r]===e&&(t[r]=a),a?a._prev=n:t[i]===e&&(t[i]=n),e._next=e._prev=e.parent=null}function za(t,e){t.parent&&(!e||t.parent.autoRemoveChildren)&&t.parent.remove&&t.parent.remove(t),t._act=0}function Aa(t,e){if(t&&(!e||e._end>t._dur||e._start<0))for(var r=t;r;)r._dirty=1,r=r.parent;return t}function Ca(t,e,r,i){return t._startAt&&(L?t._startAt.revert(ht):t.vars.immediateRender&&!t.vars.autoRevert||t._startAt.render(e,!0,i))}function Ea(t){return t._repeat?Tt(t._tTime,t=t.duration()+t._rDelay)*t:0}function Ga(t,e){return(t-e._start)*e._ts+(0<=e._ts?0:e._dirty?e.totalDuration():e._tDur)}function Ha(t){return t._end=ja(t._start+(t._tDur/Math.abs(t._ts||t._rts||X)||0))}function Ia(t,e){var r=t._dp;return r&&r.smoothChildTiming&&t._ts&&(t._start=ja(r._time-(0X)&&e.render(r,!0)),Aa(t,e)._dp&&t._initted&&t._time>=t._dur&&t._ts){if(t._dur(n=Math.abs(n))&&(a=i,o=n);return a}function tb(t){return za(t),t.scrollTrigger&&t.scrollTrigger.kill(!!L),t.progress()<1&&At(t,"onInterrupt"),t}function wb(t){if(x()&&t){var e=(t=!t.name&&t.default||t).name,r=s(t),i=e&&!r&&t.init?function(){this._props=[]}:t,n={init:T,render:he,add:Qt,kill:ce,modifier:fe,rawVars:0},a={targetTest:0,get:0,getSetter:ne,aliases:{},register:0};if(Ft(),t!==i){if(pt[e])return;qa(i,qa(ua(t,n),a)),yt(i.prototype,yt(n,ua(t,a))),pt[i.prop=e]=i,t.targetTest&&(gt.push(i),ft[e]=1),e=("css"===e?"CSS":e.charAt(0).toUpperCase()+e.substr(1))+"Plugin"}S(e,i),t.register&&t.register(Ee,i,_e)}else t&&Ct.push(t)}function zb(t,e,r){return(6*(t+=t<0?1:1>16,e>>8&St,e&St]:0:Et.black;if(!p){if(","===e.substr(-1)&&(e=e.substr(0,e.length-1)),Et[e])p=Et[e];else if("#"===e.charAt(0)){if(e.length<6&&(e="#"+(n=e.charAt(1))+n+(a=e.charAt(2))+a+(s=e.charAt(3))+s+(5===e.length?e.charAt(4)+e.charAt(4):"")),9===e.length)return[(p=parseInt(e.substr(1,6),16))>>16,p>>8&St,p&St,parseInt(e.substr(7),16)/255];p=[(e=parseInt(e.substr(1),16))>>16,e>>8&St,e&St]}else if("hsl"===e.substr(0,3))if(p=d=e.match(tt),r){if(~e.indexOf("="))return p=e.match(et),i&&p.length<4&&(p[3]=1),p}else o=+p[0]%360/360,u=p[1]/100,n=2*(h=p[2]/100)-(a=h<=.5?h*(u+1):h+u-h*u),3=U?u.endTime(!1):t._dur;return r(e)&&(isNaN(e)||e in o)?(a=e.charAt(0),s="%"===e.substr(-1),n=e.indexOf("="),"<"===a||">"===a?(0<=n&&(e=e.replace(/=/,"")),("<"===a?u._start:u.endTime(0<=u._repeat))+(parseFloat(e.substr(1))||0)*(s?(n<0?u:i).totalDuration()/100:1)):n<0?(e in o||(o[e]=h),o[e]):(a=parseFloat(e.charAt(n-1)+e.substr(n+1)),s&&i&&(a=a/100*($(i)?i[0]:i).totalDuration()),1=r&&te)return i;i=i._next}else for(i=t._last;i&&i._start>=r;){if("isPause"===i.data&&i._start=n._start)&&n._ts&&h!==n){if(n.parent!==this)return this.render(t,e,r);if(n.render(0=this.totalDuration()||!v&&_)&&(f!==this._start&&Math.abs(l)===Math.abs(this._ts)||this._lock||(!t&&g||!(v===m&&0=i&&(a instanceof Zt?e&&n.push(a):(r&&n.push(a),t&&n.push.apply(n,a.getChildren(!0,e,r)))),a=a._next;return n},e.getById=function getById(t){for(var e=this.getChildren(1,1,1),r=e.length;r--;)if(e[r].vars.id===t)return e[r]},e.remove=function remove(t){return r(t)?this.removeLabel(t):s(t)?this.killTweensOf(t):(ya(this,t),t===this._recent&&(this._recent=this._last),Aa(this))},e.totalTime=function totalTime(t,e){return arguments.length?(this._forcing=1,!this._dp&&this._ts&&(this._start=ja(Rt.time-(0r:!r||s.isActive())&&n.push(s):(i=s.getTweensOf(a,r)).length&&n.push.apply(n,i),s=s._next;return n},e.tweenTo=function tweenTo(t,e){e=e||{};var r,i=this,n=xt(i,t),a=e.startAt,s=e.onStart,o=e.onStartParams,u=e.immediateRender,h=Zt.to(i,qa({ease:e.ease||"none",lazy:!1,immediateRender:!1,time:n,overwrite:"auto",duration:e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale())||X,onStart:function onStart(){if(i.pause(),!r){var t=e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale());h._dur!==t&&Ra(h,t,0,1).render(h._time,!0,!0),r=1}s&&s.apply(h,o||[])}},e));return u?h.render(0):h},e.tweenFromTo=function tweenFromTo(t,e,r){return this.tweenTo(e,qa({startAt:{time:xt(this,t)}},r))},e.recent=function recent(){return this._recent},e.nextLabel=function nextLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t))},e.previousLabel=function previousLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t),1)},e.currentLabel=function currentLabel(t){return arguments.length?this.seek(t,!0):this.previousLabel(this._time+X)},e.shiftChildren=function shiftChildren(t,e,r){void 0===r&&(r=0);for(var i,n=this._first,a=this.labels;n;)n._start>=r&&(n._start+=t,n._end+=t),n=n._next;if(e)for(i in a)a[i]>=r&&(a[i]+=t);return Aa(this)},e.invalidate=function invalidate(t){var e=this._first;for(this._lock=0;e;)e.invalidate(t),e=e._next;return i.prototype.invalidate.call(this,t)},e.clear=function clear(t){void 0===t&&(t=!0);for(var e,r=this._first;r;)e=r._next,this.remove(r),r=e;return this._dp&&(this._time=this._tTime=this._pTime=0),t&&(this.labels={}),Aa(this)},e.totalDuration=function totalDuration(t){var e,r,i,n=0,a=this,s=a._last,o=U;if(arguments.length)return a.timeScale((a._repeat<0?a.duration():a.totalDuration())/(a.reversed()?-t:t));if(a._dirty){for(i=a.parent;s;)e=s._prev,s._dirty&&s.totalDuration(),o<(r=s._start)&&a._sort&&s._ts&&!a._lock?(a._lock=1,Ka(a,s,r-s._delay,1)._lock=0):o=r,r<0&&s._ts&&(n-=r,(!i&&!a._dp||i&&i.smoothChildTiming)&&(a._start+=r/a._ts,a._time-=r,a._tTime-=r),a.shiftChildren(-r,!1,-Infinity),o=0),s._end>n&&s._ts&&(n=s._end),s=e;Ra(a,a===I&&a._time>n?a._time:n,1,1),a._dirty=0}return a._tDur},Timeline.updateRoot=function updateRoot(t){if(I._ts&&(na(I,Ga(t,I)),f=Rt.frame),Rt.frame>=mt){mt+=q.autoSleep||120;var e=I._first;if((!e||!e._ts)&&q.autoSleep&&Rt._listeners.length<2){for(;e&&!e._ts;)e=e._next;e||Rt.sleep()}}},Timeline}(Ut);qa(Xt.prototype,{_lock:0,_hasPause:0,_forcing:0});function ac(t,e,i,n,a,o){var u,h,l,f;if(pt[t]&&!1!==(u=new pt[t]).init(a,u.rawVars?e[t]:function _processVars(t,e,i,n,a){if(s(t)&&(t=Kt(t,a,e,i,n)),!v(t)||t.style&&t.nodeType||$(t)||Z(t))return r(t)?Kt(t,a,e,i,n):t;var o,u={};for(o in t)u[o]=Kt(t[o],a,e,i,n);return u}(e[t],n,a,o,i),i,n,o)&&(i._pt=h=new _e(i._pt,a,t,0,1,u.render,u,0,u.priority),i!==c))for(l=i._ptLookup[i._targets.indexOf(a)],f=u._props.length;f--;)l[u._props[f]]=h;return u}function gc(t,r,e,i){var n,a,s=r.ease||i||"power1.inOut";if($(r))a=e[t]||(e[t]=[]),r.forEach(function(t,e){return a.push({t:e/(r.length-1)*100,v:t,e:s})});else for(n in r)a=e[n]||(e[n]=[]),"ease"===n||a.push({t:parseFloat(t),v:r[n],e:s})}var Nt,Wt,Qt=function _addPropTween(t,e,i,n,a,o,u,h,l,f){s(n)&&(n=n(a||0,t,o));var c,d=t[e],p="get"!==i?i:s(d)?l?t[e.indexOf("set")||!s(t["get"+e.substr(3)])?e:"get"+e.substr(3)](l):t[e]():d,_=s(d)?l?re:te:$t;if(r(n)&&(~n.indexOf("random(")&&(n=ob(n)),"="===n.charAt(1)&&(!(c=ka(p,n)+(Ya(p)||0))&&0!==c||(n=c))),!f||p!==n||Wt)return isNaN(p*n)||""===n?(d||e in t||Q(e,n),function _addComplexStringPropTween(t,e,r,i,n,a,s){var o,u,h,l,f,c,d,p,_=new _e(this._pt,t,e,0,1,ue,null,n),m=0,g=0;for(_.b=r,_.e=i,r+="",(d=~(i+="").indexOf("random("))&&(i=ob(i)),a&&(a(p=[r,i],t,e),r=p[0],i=p[1]),u=r.match(it)||[];o=it.exec(i);)l=o[0],f=i.substring(m,o.index),h?h=(h+1)%5:"rgba("===f.substr(-5)&&(h=1),l!==u[g++]&&(c=parseFloat(u[g-1])||0,_._pt={_next:_._pt,p:f||1===g?f:",",s:c,c:"="===l.charAt(1)?ka(c,l)-c:parseFloat(l)-c,m:h&&h<4?Math.round:0},m=it.lastIndex);return _.c=m")}),s.duration();else{for(l in u={},x)"ease"===l||"easeEach"===l||gc(l,x[l],u,x.easeEach);for(l in u)for(C=u[l].sort(function(t,e){return t.t-e.t}),o=D=0;o=t._tDur||e<0)&&t.ratio===u&&(u&&za(t,1),r||L||(At(t,u?"onComplete":"onReverseComplete",!0),t._prom&&t._prom()))}else t._zTime||(t._zTime=e)}(this,t,e,r);return this},e.targets=function targets(){return this._targets},e.invalidate=function invalidate(t){return t&&this.vars.runBackwards||(this._startAt=0),this._pt=this._op=this._onUpdate=this._lazy=this.ratio=0,this._ptLookup=[],this.timeline&&this.timeline.invalidate(t),z.prototype.invalidate.call(this,t)},e.resetTo=function resetTo(t,e,r,i){d||Rt.wake(),this._ts||this.play();var n,a=Math.min(this._dur,(this._dp._time-this._start)*this._ts);return this._initted||Gt(this,a),n=this._ease(a/this._dur),function _updatePropTweens(t,e,r,i,n,a,s){var o,u,h,l,f=(t._pt&&t._ptCache||(t._ptCache={}))[e];if(!f)for(f=t._ptCache[e]=[],h=t._ptLookup,l=t._targets.length;l--;){if((o=h[l][e])&&o.d&&o.d._pt)for(o=o.d._pt;o&&o.p!==e&&o.fp!==e;)o=o._next;if(!o)return Wt=1,t.vars[e]="+=0",Gt(t,s),Wt=0,1;f.push(o)}for(l=f.length;l--;)(o=(u=f[l])._pt||u).s=!i&&0!==i||n?o.s+(i||0)+a*o.c:i,o.c=r-o.s,u.e&&(u.e=ia(r)+Ya(u.e)),u.b&&(u.b=o.s+Ya(u.b))}(this,t,e,r,i,n,a)?this.resetTo(t,e,r,i):(Ia(this,0),this.parent||xa(this._dp,this,"_first","_last",this._dp._sort?"_start":0),this.render(0))},e.kill=function kill(t,e){if(void 0===e&&(e="all"),!(t||e&&"all"!==e))return this._lazy=this._pt=0,this.parent?tb(this):this;if(this.timeline){var i=this.timeline.totalDuration();return this.timeline.killTweensOf(t,e,Nt&&!0!==Nt.vars.overwrite)._first||tb(this),this.parent&&i!==this.timeline.totalDuration()&&Ra(this,this._dur*this.timeline._tDur/i,0,1),this}var n,a,s,o,u,h,l,f=this._targets,c=t?Ot(t):f,d=this._ptLookup,p=this._pt;if((!e||"all"===e)&&function _arraysMatch(t,e){for(var r=t.length,i=r===e.length;i&&r--&&t[r]===e[r];);return r<0}(f,c))return"all"===e&&(this._pt=0),tb(this);for(n=this._op=this._op||[],"all"!==e&&(r(e)&&(u={},ha(e,function(t){return u[t]=1}),e=u),e=function _addAliasesToVars(t,e){var r,i,n,a,s=t[0]?fa(t[0]).harness:0,o=s&&s.aliases;if(!o)return e;for(i in r=yt({},e),o)if(i in r)for(n=(a=o[i].split(",")).length;n--;)r[a[n]]=r[i];return r}(f,e)),l=f.length;l--;)if(~c.indexOf(f[l]))for(u in a=d[l],"all"===e?(n[l]=e,o=a,s={}):(s=n[l]=n[l]||{},o=e),o)(h=a&&a[u])&&("kill"in h.d&&!0!==h.d.kill(u)||ya(this,h,"_pt"),delete a[u]),"all"!==s&&(s[u]=1);return this._initted&&!this._pt&&p&&tb(this),this},Tween.to=function to(t,e,r){return new Tween(t,e,r)},Tween.from=function from(t,e){return Va(1,arguments)},Tween.delayedCall=function delayedCall(t,e,r,i){return new Tween(e,0,{immediateRender:!1,lazy:!1,overwrite:!1,delay:t,onComplete:e,onReverseComplete:e,onCompleteParams:r,onReverseCompleteParams:r,callbackScope:i})},Tween.fromTo=function fromTo(t,e,r){return Va(2,arguments)},Tween.set=function set(t,e){return e.duration=0,e.repeatDelay||(e.repeat=0),new Tween(t,e)},Tween.killTweensOf=function killTweensOf(t,e,r){return I.killTweensOf(t,e,r)},Tween}(Ut);qa(Zt.prototype,{_targets:[],_lazy:0,_startAt:0,_op:0,_onInit:0}),ha("staggerTo,staggerFrom,staggerFromTo",function(r){Zt[r]=function(){var t=new Xt,e=Mt.call(arguments,0);return e.splice("staggerFromTo"===r?5:4,0,0),t[r].apply(t,e)}});function oc(t,e,r){return t.setAttribute(e,r)}function wc(t,e,r,i){i.mSet(t,e,i.m.call(i.tween,r,i.mt),i)}var $t=function _setterPlain(t,e,r){return t[e]=r},te=function _setterFunc(t,e,r){return t[e](r)},re=function _setterFuncWithParam(t,e,r,i){return t[e](i.fp,r)},ne=function _getSetter(t,e){return s(t[e])?te:u(t[e])&&t.setAttribute?oc:$t},ae=function _renderPlain(t,e){return e.set(e.t,e.p,Math.round(1e6*(e.s+e.c*t))/1e6,e)},se=function _renderBoolean(t,e){return e.set(e.t,e.p,!!(e.s+e.c*t),e)},ue=function _renderComplexString(t,e){var r=e._pt,i="";if(!t&&e.b)i=e.b;else if(1===t&&e.e)i=e.e;else{for(;r;)i=r.p+(r.m?r.m(r.s+r.c*t):Math.round(1e4*(r.s+r.c*t))/1e4)+i,r=r._next;i+=e.c}e.set(e.t,e.p,i,e)},he=function _renderPropTweens(t,e){for(var r=e._pt;r;)r.r(t,r.d),r=r._next},fe=function _addPluginModifier(t,e,r,i){for(var n,a=this._pt;a;)n=a._next,a.p===i&&a.modifier(t,e,r),a=n},ce=function _killPropTweensOf(t){for(var e,r,i=this._pt;i;)r=i._next,i.p===t&&!i.op||i.op===t?ya(this,i,"_pt"):i.dep||(e=1),i=r;return!e},pe=function _sortPropTweensByPriority(t){for(var e,r,i,n,a=t._pt;a;){for(e=a._next,r=i;r&&r.pr>a.pr;)r=r._next;(a._prev=r?r._prev:n)?a._prev._next=a:i=a,(a._next=r)?r._prev=a:n=a,a=e}t._pt=i},_e=(PropTween.prototype.modifier=function modifier(t,e,r){this.mSet=this.mSet||this.set,this.set=wc,this.m=t,this.mt=r,this.tween=e},PropTween);function PropTween(t,e,r,i,n,a,s,o,u){this.t=e,this.s=i,this.c=n,this.p=r,this.r=a||ae,this.d=s||this,this.set=o||$t,this.pr=u||0,(this._next=t)&&(t._prev=this)}ha(vt+"parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger",function(t){return ft[t]=1}),ot.TweenMax=ot.TweenLite=Zt,ot.TimelineLite=ot.TimelineMax=Xt,I=new Xt({sortChildren:!1,defaults:V,autoRemoveChildren:!0,id:"root",smoothChildTiming:!0}),q.stringFilter=Fb;function Ec(t){return(ye[t]||Te).map(function(t){return t()})}function Fc(){var t=Date.now(),o=[];2 { + // Reset the image styles to default values using GSAP. + gsap.set(this.DOM.el, this.defaultStyle); + + // Recalculate and update the size and position of the image element. + this.getRect(); + }; + + // Add a window resize event listener that calls the defined resize method to handle image adjustments on window resize. + window.addEventListener('resize', () => this.resize()); + } + + /** + * The getRect method calculates and stores the size and position of the image element in the 'rect' property. + * @returns {void} + */ + getRect() { + // Use the getBoundingClientRect method to calculate and assign the size and position of the image element to the 'rect' property. + this.rect = this.DOM.el.getBoundingClientRect(); + } +} \ No newline at end of file diff --git a/assets/js/imageTrail.js b/assets/js/imageTrail.js new file mode 100644 index 0000000..77d9232 --- /dev/null +++ b/assets/js/imageTrail.js @@ -0,0 +1,233 @@ +// Importing utility functions from 'utils.js' +import { getPointerPos, getMouseDistance, lerp } from './utils.js'; +import { Image } from './image.js'; + + +// Initial declaration of mouse position variables with default values +let mousePos, lastMousePos, cacheMousePos; +mousePos = {x: 0, y: 0}; // current mouse position +cacheMousePos = {...mousePos}; // previous mouse position +lastMousePos = {...mousePos}; // stores the position of the mouse at the time the most recent image was displayed, serving as a reference point for calculating the distance the cursor has moved in subsequent frames + +// This function will be used to handle both mouse and touch events +const handlePointerMove = (ev) => { + // If it's a touch event, we'll use the first touch point + if (ev.touches) { + mousePos = getPointerPos(ev.touches[0]); + } else { + // If it's a mouse event, proceed as usual + mousePos = getPointerPos(ev); + } +}; + +let firstSection = document.querySelector('.home'); + +// Adding an event listener to the window to update mouse position on mousemove event +window.addEventListener('mousemove', (event) => { + let rect = firstSection.getBoundingClientRect(); + if (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom) { + handlePointerMove(event); + } + +}); + +window.addEventListener('touchmove', (event) => { + let rect = firstSection.getBoundingClientRect(); + if (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom) { + handlePointerMove(event); + } +}); + +let winsize = {width: window.innerWidth, height: window.innerHeight}; +window.addEventListener('resize', () => { + winsize = {width: window.innerWidth, height: window.innerHeight}; +}); + +export class ImageTrail { + // Class properties initialization + DOM = {el: null}; // Object to hold DOM elements + images = []; // Array to store Image objects + imagesTotal = 0; // Variable to store total number of images + imgPosition = 0; // Variable to store the position of the upcoming image + zIndexVal = 1; // z-index value for the upcoming image + activeImagesCount = 0; // Counter for active images + isIdle = true; // Flag to check if all images are inactive + // Mouse distance from the previous trigger, required to show the next image + threshold = 80; + // Rotation and transform (z) values and cached values + rotation = {x: 0, y: 0}; + cachedRotation = {...this.rotation}; + zValue = 0; + cachedZValue = 0; + /** + * Constructor for the ImageTrail class. + * Initializes the instance, sets up the DOM elements, creates Image objects for each image element, and starts the rendering loop. + * @param {HTMLElement} DOM_el - The parent DOM element containing all image elements. + */ + constructor(DOM_el) { + // Store the reference to the parent DOM element. + this.DOM.el = DOM_el; + + // Create and store Image objects for each image element found within the parent DOM element. + this.images = [...this.DOM.el.querySelectorAll('.content__imgh')].map(img => new Image(img)); + + // Store the total number of images. + this.imagesTotal = this.images.length; + + const onPointerMoveEv = () => { + // Initialize cacheMousePos with the current mousePos values. + // This is necessary to have a reference point for the initial mouse position. + cacheMousePos = {...mousePos}; + // Initiate the rendering loop. + requestAnimationFrame(() => this.render()); + // Remove this mousemove event listener after it runs once to avoid reinitialization. + window.removeEventListener('mousemove', onPointerMoveEv); + window.removeEventListener('touchmove', onPointerMoveEv); + }; + // Set up an initial mousemove event listener to run onMouseMoveEv once. + window.addEventListener('mousemove', onPointerMoveEv); + window.addEventListener('touchmove', onPointerMoveEv); + } + + /** + * The `render` function is the main rendering loop for the `ImageTrail` class, updating images based on mouse movement. + * It calculates the distance between the current and the last mouse position, then decides whether to show the next image. + * @returns {void} + */ + render() { + // Calculate distance between current mouse position and last recorded mouse position. + let distance = getMouseDistance(mousePos, lastMousePos); + + // Smoothly interpolate between cached mouse position and current mouse position for smoother visual effects. + cacheMousePos.x = lerp(cacheMousePos.x || mousePos.x, mousePos.x, 0.1); + cacheMousePos.y = lerp(cacheMousePos.y || mousePos.y, mousePos.y, 0.1); + + // If the calculated distance is greater than the defined threshold, show the next image and update lastMousePos. + if ( distance > this.threshold ) { + this.showNextImage(); + lastMousePos = mousePos; + } + + // If all images are inactive (isIdle is true) and zIndexVal is not 1, reset zIndexVal to avoid endless incrementation. + if ( this.isIdle && this.zIndexVal !== 1 ) { + this.zIndexVal = 1; + } + + // Request the next animation frame, creating a recursive loop for continuous rendering. + requestAnimationFrame(() => this.render()); + } + + /** + * The `showNextImage` function is responsible for displaying, animating, and managing the next image in the sequence. + * It increments the zIndexVal, selects the next image, stops ongoing animations, and defines a series of GSAP animations. + * @returns {void} + */ + showNextImage() { + // Get the window's center coordinates + const centerX = winsize.width / 2; + const centerY = winsize.height / 2; + + // Calculate the mouse position relative to the center of the window + const relX = mousePos.x - centerX; + const relY = mousePos.y - centerY; + + // Convert these distances into rotation values (these constants can be adjusted) + // Here we're saying the full width/height of the window corresponds to a 30 degree rotation + this.rotation.x = -(relY / centerY) * 30; + this.rotation.y = (relX / centerX) * 30; + // Cache these values + this.cachedRotation = { ...this.rotation }; + + // Calculate the distance of the mouse from the center. + const distanceFromCenter = Math.sqrt(relX * relX + relY * relY); + // Assuming the maximum distance is the diagonal of the screen. + const maxDistance = Math.sqrt(centerX * centerX + centerY * centerY); + // Calculate the proportion of the distance to the maximum possible (which is the diagonal). + const proportion = distanceFromCenter / maxDistance; + // Map this to the Z-axis range (-600 to 600). The overall range is 1200. + this.zValue = proportion * 1200 - 600; + // Cache this value + this.cachedZValue = this.zValue; + + // Now, calculate brightness based on z-value. Assume the brightness should be between 0.5 and 1.5 for effect. + // Normalize the zValue from range -600 to 600 to a range of 0.5 to 1.5 for brightness. + // As the zValue increases, the brightness increases, meaning the object is closer and thus brighter. + const normalizedZ = (this.zValue + 600) / 1200; // This will convert the range from -600 - 600 to 0 - 1. + const brightness = 0.2 + (normalizedZ * 2.3); // This will map the 0 - 1 range into 0.5 - 2.5 (adjust if necessary). + + // Increment zIndexVal for next image. + ++this.zIndexVal; + + // Select the next image in the sequence, or revert to the first image if at the end of the sequence. + this.imgPosition = this.imgPosition < this.imagesTotal-1 ? this.imgPosition+1 : 0; + + // Retrieve the Image object for the selected position. + const img = this.images[this.imgPosition]; + + // Stop any ongoing GSAP animations on the target image element to prepare for new animations. + gsap.killTweensOf(img.DOM.el); + + // Define GSAP timeline. + img.timeline = gsap.timeline({ + onStart: () => this.onImageActivated(), + onComplete: () => this.onImageDeactivated() + }) + .set(this.DOM.el, { + perspective: 1000 + }, 0) + .fromTo(img.DOM.el, { + opacity: 1, + z: 0, + scale: 1 + (this.cachedZValue / 1000), + zIndex: this.zIndexVal, + x: cacheMousePos.x - img.rect.width/2 , + y: cacheMousePos.y - img.rect.height/2, + rotationX: this.cachedRotation.x, + rotationY: this.cachedRotation.y, + filter: `brightness(${brightness})` + }, { + duration: 1, + ease: 'expo', + scale: 1 + (this.zValue / 1000), + x: mousePos.x - img.rect.width/2, + y: mousePos.y - img.rect.height/2, + rotationX: this.rotation.x, + rotationY: this.rotation.y, + }, 0) + // then make it disappear + .to(img.DOM.el, { + duration: 0.4, + ease: 'power2', + opacity: 0, + z: -800 + }, 0.3) + } + + /** + * onImageActivated function is called when an image's activation (display) animation begins. + * It increments the activeImagesCount and sets isIdle flag to false. + * @returns {void} + */ + onImageActivated = () => { + // Increment the counter for active images. + this.activeImagesCount++; + + // Set the isIdle flag to false as there's at least one active image. + this.isIdle = false; + } + + /** + * onImageDeactivated function is called when an image's deactivation (disappearance) animation ends. + * It decrements the activeImagesCount and sets isIdle flag to true if no images are active. + * @returns {void} + */ + onImageDeactivated = () => { + // Decrement the counter for active images. + this.activeImagesCount--; + + // If there are no active images, set the isIdle flag to true. + if (this.activeImagesCount === 0) { + this.isIdle = true; + } + } +} \ No newline at end of file diff --git a/assets/js/imagesloaded.pkgd.min.js b/assets/js/imagesloaded.pkgd.min.js new file mode 100644 index 0000000..b55bea2 --- /dev/null +++ b/assets/js/imagesloaded.pkgd.min.js @@ -0,0 +1,12 @@ +/*! + * imagesLoaded PACKAGED v5.0.0 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ +!function(t,e){"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}("undefined"!=typeof window?window:this,(function(){function t(){}let e=t.prototype;return e.on=function(t,e){if(!t||!e)return this;let i=this._events=this._events||{},s=i[t]=i[t]||[];return s.includes(e)||s.push(e),this},e.once=function(t,e){if(!t||!e)return this;this.on(t,e);let i=this._onceEvents=this._onceEvents||{};return(i[t]=i[t]||{})[e]=!0,this},e.off=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;let s=i.indexOf(e);return-1!=s&&i.splice(s,1),this},e.emitEvent=function(t,e){let i=this._events&&this._events[t];if(!i||!i.length)return this;i=i.slice(0),e=e||[];let s=this._onceEvents&&this._onceEvents[t];for(let n of i){s&&s[n]&&(this.off(t,n),delete s[n]),n.apply(this,e)}return this},e.allOff=function(){return delete this._events,delete this._onceEvents,this},t})), +/*! + * imagesLoaded v5.0.0 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ +function(t,e){"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}("undefined"!=typeof window?window:this,(function(t,e){let i=t.jQuery,s=t.console;function n(t,e,o){if(!(this instanceof n))return new n(t,e,o);let r=t;var h;("string"==typeof t&&(r=document.querySelectorAll(t)),r)?(this.elements=(h=r,Array.isArray(h)?h:"object"==typeof h&&"number"==typeof h.length?[...h]:[h]),this.options={},"function"==typeof e?o=e:Object.assign(this.options,e),o&&this.on("always",o),this.getImages(),i&&(this.jqDeferred=new i.Deferred),setTimeout(this.check.bind(this))):s.error(`Bad element for imagesLoaded ${r||t}`)}n.prototype=Object.create(e.prototype),n.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)};const o=[1,9,11];n.prototype.addElementImages=function(t){"IMG"===t.nodeName&&this.addImage(t),!0===this.options.background&&this.addElementBackgroundImages(t);let{nodeType:e}=t;if(!e||!o.includes(e))return;let i=t.querySelectorAll("img");for(let t of i)this.addImage(t);if("string"==typeof this.options.background){let e=t.querySelectorAll(this.options.background);for(let t of e)this.addElementBackgroundImages(t)}};const r=/url\((['"])?(.*?)\1\)/gi;function h(t){this.img=t}function d(t,e){this.url=t,this.element=e,this.img=new Image}return n.prototype.addElementBackgroundImages=function(t){let e=getComputedStyle(t);if(!e)return;let i=r.exec(e.backgroundImage);for(;null!==i;){let s=i&&i[2];s&&this.addBackground(s,t),i=r.exec(e.backgroundImage)}},n.prototype.addImage=function(t){let e=new h(t);this.images.push(e)},n.prototype.addBackground=function(t,e){let i=new d(t,e);this.images.push(i)},n.prototype.check=function(){if(this.progressedCount=0,this.hasAnyBroken=!1,!this.images.length)return void this.complete();let t=(t,e,i)=>{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n})); \ No newline at end of file diff --git a/assets/js/lenis.min.js b/assets/js/lenis.min.js new file mode 100644 index 0000000..bd31f9e --- /dev/null +++ b/assets/js/lenis.min.js @@ -0,0 +1 @@ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t||self).Lenis=e()}(this,function(){function t(t,e){for(var i=0;i=1)?1:this.easing(s);this.value=this.from+(this.to-this.from)*r}null==(e=this.onUpdate)||e.call(this,this.value,{completed:n}),n&&this.stop()}},e.stop=function(){this.isRunning=!1},e.fromTo=function(t,e,i){var o=i.lerp,n=void 0===o?.1:o,s=i.duration,r=void 0===s?1:s,l=i.easing,h=void 0===l?function(t){return t}:l,a=i.onUpdate;this.from=this.value=t,this.to=e,this.lerp=n,this.duration=r,this.easing=h,this.currentTime=0,this.isRunning=!0,this.onUpdate=a},t}();function s(t,e){var i;return function(){var o=arguments,n=this;clearTimeout(i),i=setTimeout(function(){t.apply(n,o)},e)}}var r=/*#__PURE__*/function(){function t(t,e){var i=this;this.onWindowResize=function(){i.width=window.innerWidth,i.height=window.innerHeight},this.onWrapperResize=function(){i.width=i.wrapper.clientWidth,i.height=i.wrapper.clientHeight},this.onContentResize=function(){var t=i.wrapper===window?document.documentElement:i.wrapper;i.scrollHeight=t.scrollHeight,i.scrollWidth=t.scrollWidth},this.wrapper=t,this.content=e,this.wrapper===window?(window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize()):(this.wrapperResizeObserver=new ResizeObserver(s(this.onWrapperResize,100)),this.wrapperResizeObserver.observe(this.wrapper),this.onWrapperResize()),this.contentResizeObserver=new ResizeObserver(s(this.onContentResize,100)),this.contentResizeObserver.observe(this.content),this.onContentResize()}return t.prototype.destroy=function(){var t,e;window.removeEventListener("resize",this.onWindowResize,!1),null==(t=this.wrapperResizeObserver)||t.disconnect(),null==(e=this.contentResizeObserver)||e.disconnect()},e(t,[{key:"limit",get:function(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}}]),t}(),l=/*#__PURE__*/function(){function t(t,e){var i=this,n=e.wheelMultiplier,s=void 0===n?1:n,r=e.touchMultiplier,l=void 0===r?2:r,h=e.normalizeWheel,a=void 0!==h&&h;this.onTouchStart=function(t){var e=t.targetTouches?t.targetTouches[0]:t,o=e.clientY;i.touchStart.x=e.clientX,i.touchStart.y=o,i.lastDelta={x:0,y:0}},this.onTouchMove=function(t){var e=t.targetTouches?t.targetTouches[0]:t,o=e.clientX,n=e.clientY,s=-(o-i.touchStart.x)*i.touchMultiplier,r=-(n-i.touchStart.y)*i.touchMultiplier;i.touchStart.x=o,i.touchStart.y=n,i.lastDelta={x:s,y:r},i.emitter.emit("scroll",{type:"touch",deltaX:s,deltaY:r,event:t})},this.onTouchEnd=function(t){i.emitter.emit("scroll",{type:"touch",inertia:!0,deltaX:i.lastDelta.x,deltaY:i.lastDelta.y,event:t})},this.onWheel=function(t){var e=t.deltaX,n=t.deltaY;i.normalizeWheel&&(e=o(-100,e,100),n=o(-100,n,100)),i.emitter.emit("scroll",{type:"wheel",deltaX:e*=i.wheelMultiplier,deltaY:n*=i.wheelMultiplier,event:t})},this.element=t,this.wheelMultiplier=s,this.touchMultiplier=l,this.normalizeWheel=a,this.touchStart={x:null,y:null},this.emitter={events:{},emit:function(t){for(var e=this.events[t]||[],i=0,o=e.length;iMath.abs(s)?r:s:"horizontal"===e.options.gestureOrientation&&(c=s);var u=h&&e.options.syncTouch,p=h&&n&&Math.abs(c)>1;p&&(c=e.velocity*e.options.touchInertiaMultiplier),e.scrollTo(e.targetScroll+c,i({programmatic:!1},u&&{lerp:p?e.syncTouchLerp:.4}))}}},this.onScroll=function(){if(!e.isScrolling){var t=e.animatedScroll;e.animatedScroll=e.targetScroll=e.actualScroll,e.velocity=0,e.direction=Math.sign(e.animatedScroll-t),e.emit()}},s&&console.warn("Lenis: `direction` option is deprecated, use `orientation` instead"),h&&console.warn("Lenis: `gestureDirection` option is deprecated, use `gestureOrientation` instead"),a&&console.warn("Lenis: `mouseMultiplier` option is deprecated, use `wheelMultiplier` instead"),c&&console.warn("Lenis: `smooth` option is deprecated, use `smoothWheel` instead"),window.lenisVersion="1.0.11",p!==document.documentElement&&p!==document.body||(p=window),this.options={wrapper:p,content:v,wheelEventsTarget:f,smoothWheel:w,smoothTouch:y,syncTouch:b,syncTouchLerp:M,touchInertiaMultiplier:L,duration:W,easing:O,lerp:k,infinite:H,gestureOrientation:Y,orientation:D,touchMultiplier:P,wheelMultiplier:A,normalizeWheel:V},this.dimensions=new r(p,v),this.rootElement.classList.add("lenis"),this.velocity=0,this.isStopped=!1,this.isSmooth=w||y,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.animate=new n,this.emitter={events:{},emit:function(t){for(var e=this.events[t]||[],i=0,o=e.length;i0&&e<0||t<0&&e>0)&&(e+=t),e):this.animatedScroll;var t,e}},{key:"progress",get:function(){return 0===this.limit?1:this.scroll/this.limit}},{key:"isSmooth",get:function(){return this.__isSmooth},set:function(t){this.__isSmooth!==t&&(this.rootElement.classList.toggle("lenis-smooth",t),this.__isSmooth=t)}},{key:"isScrolling",get:function(){return this.__isScrolling},set:function(t){this.__isScrolling!==t&&(this.rootElement.classList.toggle("lenis-scrolling",t),this.__isScrolling=t)}},{key:"isStopped",get:function(){return this.__isStopped},set:function(t){this.__isStopped!==t&&(this.rootElement.classList.toggle("lenis-stopped",t),this.__isStopped=t)}}]),t}();return h}); \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js index b36b5ac..6480169 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,97 +1,72 @@ -if (window.location.href !== window.location.href.toLowerCase()) { - window.location.href = window.location.href.toLowerCase(); -} - -/*===== SHOW NAVBAR =====*/ -const showNavbar = (toggleId, navId, bodyId, headerId) =>{ - const toggle = document.getElementById(toggleId), - nav = document.getElementById(navId), - bodypd = document.getElementById(bodyId), - headerpd = document.getElementById(headerId) - - // Validate that all variables exist - if(toggle && nav && bodypd && headerpd){ - toggle.addEventListener('click', ()=>{ - // show navbar - nav.classList.toggle('show') - // change icon - toggle.classList.toggle('bx-x') - // add padding to body - bodypd.classList.toggle('body-pd') - // add padding to header - headerpd.classList.toggle('body-pd') - }) - } -} - -showNavbar('header-toggle','nav-bar','body-pd','header') - -/*===== LINK ACTIVE =====*/ -const linkColor = document.querySelectorAll('.nav__link') - -function colorLink(){ - if(linkColor){ - linkColor.forEach(l=> l.classList.remove('active')) - this.classList.add('active') - } -} -linkColor.forEach(l=> l.addEventListener('click', colorLink)) +document.addEventListener('DOMContentLoaded', () => { + const tabs = document.querySelectorAll('.tab-link'); + const content = document.querySelectorAll('.tab-content'); + + tabs.forEach(tab => { + tab.addEventListener('click', () => { + // Hide all content + content.forEach(c => c.style.display = 'none'); + + // Remove active class from all tabs + tabs.forEach(t => t.classList.remove('active')); + + // Show target content + const target = document.getElementById(tab.getAttribute('data-target')); + target.style.display = 'block'; + target.classList.add('active-content'); + + // Add active class to current tab + tab.classList.add('active'); + }); + }); -/*===== SCROLL REVEAL ANIMATION =====*/ -const sr = ScrollReveal({ - origin: 'top', - distance: '80px', - duration: 2000, - reset: true + // Trigger click on the first tab to show first content by default + if(tabs.length > 0) tabs[0].click(); }); -/*SCROLL HOME*/ -sr.reveal('.home__title',{delay: 200}); -sr.reveal('.button',{delay: 200}); -sr.reveal('.home__subtitle',{ interval: 200}); - -/*SCROLL ABOUT*/ -sr.reveal('.about-title',{delay: 200}); -sr.reveal('.skills__data',{delay: 200}); -sr.reveal('.skills__text',{delay: 200}); - -/*SCROLL Projects*/ -sr.reveal('.project_card',{delay: 100}); -sr.reveal('.button_project',{delay: 100}); -/*SCROLL WORK*/ -sr.reveal('.work__title',{interval: 200}); -sr.reveal('.wrapper',{interval: 300}); - -/*SCROLL CONTACT*/ -sr.reveal('.contact_title',{interval: 200}); -sr.reveal('.contact_form_text',{interval: 300}); -sr.reveal('.button_c',{interval: 350}); - -//typing animation -var typed = new Typed(".typing", { - strings: ["Programmer.", "Python Lover.", "Future CS major.", "Research Fellow.", "Machine Learning Enthusiast.", "CS Club Event Planner."], - typeSpeed: 100, - backSpeed: 60, - loop: true +document.getElementById('commandInput').addEventListener('keypress', function(e) { + // Check if the Enter key is pressed + if (e.key === 'Enter') { + // Prevent the default action to avoid submitting a form if the input is inside one + e.preventDefault(); + + // Get the command from the input + var command = this.value; + + // Parse the command to find the section name (assuming the format is "cd sectionName") + var sectionName = command.split(' ')[1]; // This splits the command by space and gets the second part + + // Check if the section exists + var section = document.getElementById(sectionName); + if (section) { + // Scroll to the section if it exists + section.scrollIntoView({behavior: 'smooth'}); + } else { + // Optionally handle the case where the section does not exist + alert("Section '" + sectionName + "' not found."); + } + + // Clear the command input + this.value = ''; + } }); -var pageX = $(document).width(); -var pageY = $(document).height(); -var mouseY = 0; -var mouseX = 0; - -$(document).mousemove(function (event) { - //verticalAxis - mouseY = event.pageY; - yAxis = ((pageY / 2 - mouseY) / pageY) * 300; - //horizontalAxis - mouseX = event.pageX / -pageX; - xAxis = -mouseX * 100 - 100; - - $(".box__ghost-eyes").css({ - transform: "translate(" + xAxis + "%,-" + yAxis + "%)" - }); - - console.log("X: " + xAxis); +const slider = document.querySelector('.slider'); +const prevButton = document.querySelector('.prev-button'); +const nextButton = document.querySelector('.next-button'); +const certificateWidth = slider.querySelector('img').clientWidth; +let currentPosition = 0; + +prevButton.addEventListener('click', () => { + if (currentPosition < 0) { + currentPosition += certificateWidth; + slider.style.transform = `translateX(${currentPosition}px)`; + } }); +nextButton.addEventListener('click', () => { + if (currentPosition > -(slider.scrollWidth - certificateWidth)) { + currentPosition -= certificateWidth; + slider.style.transform = `translateX(${currentPosition}px)`; + } +}); \ No newline at end of file diff --git a/assets/js/scrollE.js b/assets/js/scrollE.js new file mode 100644 index 0000000..48001cd --- /dev/null +++ b/assets/js/scrollE.js @@ -0,0 +1,94 @@ +import { preloadImages } from './utils.js'; + +// Combine all selectors for preloading images +const imageSelectors = '.grid__item-img-inner, .content__img'; + +// Selecting DOM elements for both functionalities +const gridItems = document.querySelectorAll('.grid__item'); +const contentElements = [...document.querySelectorAll('.content--sticky')]; +const totalContentElements = contentElements.length; + +const initSmoothScrolling = () => { + const lenis = new Lenis() + + lenis.on('scroll', (e) => { + console.log(e) + }) + + function raf(time) { + lenis.raf(time) + requestAnimationFrame(raf) + } + + requestAnimationFrame(raf) +}; + +const handleGridAnimations = () => { + gridItems.forEach((item) => { + const isLeftSide = item.previousElementSibling && (item.offsetLeft + item.offsetWidth <= item.previousElementSibling.offsetLeft + 1); + const originX = isLeftSide ? 100 : 0; + + gsap.timeline({ + defaults: { ease: 'none' }, + scrollTrigger: { + trigger: item, + start: 'top bottom-=15%', + end: '+=50%', + scrub: true + } + }) + .fromTo(item.querySelector('.grid__item-img'), { + yPercent: -100, + xPercent: isLeftSide ? 100 : -100 + }, { + yPercent: 0, + xPercent: 0, + }) + .fromTo(item.querySelector('.grid__item-img-inner'), { + yPercent: 100, + xPercent: isLeftSide ? -100 : 100, + filter: 'brightness(200%) contrast(300%)' + }, { + yPercent: 0, + xPercent: 0, + filter: 'brightness(100%) contrast(100%)' + }, 0) + .fromTo(item.querySelector('.grid__item-caption'), { + yPercent: 200, + xPercent: 50, + opacity: 0 + }, { + yPercent: 0, + xPercent: 0, + opacity: 1 + }, 0); + }); +}; + +const handleContentAnimations = () => { + contentElements.forEach((el, position) => { + gsap.timeline({ + scrollTrigger: { + trigger: el, + start: 'top top', + end: '+=100%', + scrub: true + } + }) + .fromTo(el.querySelector('.content__img'), { + yPercent: 10, + rotation: 20, + }, { + ease: 'power1', + yPercent: -60, + rotation: -20, + }, 0); + }); +}; + +// Preload images then initialize everything +preloadImages(imageSelectors).then(() => { + // initSmoothScrolling(); + handleGridAnimations(); + handleContentAnimations(); +}); diff --git a/assets/js/scrollGallery.js b/assets/js/scrollGallery.js new file mode 100644 index 0000000..cc81886 --- /dev/null +++ b/assets/js/scrollGallery.js @@ -0,0 +1,67 @@ +import { preloadImages } from './utils.js'; + +// Get the grid element +const grid = document.querySelector('.grid'); + +// Get all grid items within the grid +const gridItems = document.querySelectorAll('.grid__item'); + +const scroller = () => { + const viewportHeight = window.innerHeight; + const endValue = viewportHeight / 2; + + // Loop through each grid item to add animations + gridItems.forEach((item, index) => { + // Get the previous element sibling for the current item + const previousElementSibling = item.previousElementSibling; + // Determine if the current item is on the left side based on its position relative to the previous item + const isLeftSide = previousElementSibling && (item.offsetLeft + item.offsetWidth <= previousElementSibling.offsetLeft + 1); + // Determine the origin for transformations (either 100 or 0 depending on position) + const originX = isLeftSide ? 100 : 0; + + gsap + .timeline({ + defaults: { + ease: 'none' + }, + scrollTrigger: { + trigger: item, + start: 'top bottom-=15%', + end: '+=50%', + scrub: true + } + }) + .fromTo(item.querySelector('.grid__item-img'), { + yPercent: -100, + xPercent: isLeftSide ? 100 : -100 + }, { + yPercent: 0, + xPercent: 0, + }) + .fromTo(item.querySelector('.grid__item-img-inner'), { + yPercent: 100, + xPercent: isLeftSide ? -100 : 100, + filter: 'brightness(200%) contrast(300%)' + }, { + yPercent: 0, + xPercent: 0, + filter: 'brightness(100%) contrast(100%)' + }, 0) + .fromTo(item.querySelector('.grid__item-caption'), { + yPercent: 200, + xPercent: 50, + opacity: 0 + }, { + //ease: 'power1', + yPercent: 0, + xPercent: 0, + opacity: 1 + }, 0); + + }); +} + +// Preload images, initialize smooth scrolling, apply scroll-triggered animations, and remove loading class from body +preloadImages('.grid__item-img-inner').then(() => { + scroller(); +}); \ No newline at end of file diff --git a/assets/js/utils.js b/assets/js/utils.js new file mode 100644 index 0000000..ec5ad09 --- /dev/null +++ b/assets/js/utils.js @@ -0,0 +1,163 @@ + +const preloadImages = (selector = 'img') => { + return new Promise((resolve) => { + // The imagesLoaded library is used to ensure all images (including backgrounds) are fully loaded. + imagesLoaded(document.querySelectorAll(selector), {background: true}, resolve); + }); +}; + +const getGrid = selector => { + let elements = gsap.utils.toArray(selector), + bounds, + getSubset = (axis, dimension, alternating, merge) => { + let a = [], + subsets = {}, + onlyEven = alternating === "even", + p; + bounds.forEach((b, i) => { + let position = Math.round(b[axis] + b[dimension] / 2), + subset = subsets[position]; + subset || (subsets[position] = subset = []); + subset.push(elements[i]); + }); + for (p in subsets) { + a.push(subsets[p]); + } + if (onlyEven || alternating === "odd") { + a = a.filter((el, i) => !(i % 2) === onlyEven); + } + if (merge) { + let a2 = []; + a.forEach(subset => a2.push(...subset)); + return a2; + } + return a; + }; + elements.refresh = () => bounds = elements.map(el => el.getBoundingClientRect()); + elements.columns = (alternating, merge) => getSubset("left", "width", alternating, merge); + elements.rows = (alternating, merge) => getSubset("top", "height", alternating, merge); + elements.refresh(); + + return elements; +} + + +const lerp = (a, b, n) => (1 - n) * a + n * b; + +const distance = (x1, y1, x2, y2) => Math.hypot(x2 - x1, y2 - y1); + +const getCursorPos = ev => { + return { + x : ev.clientX, + y : ev.clientY + }; + }; + + +const map = (x, a, b, c, d) => (x - a) * (d - c) / (b - a) + c; + + +const calcWinsize = () => { + return { + width: window.innerWidth, + height: window.innerHeight + } +} + +const getPointerPos = ev => { + let posx = 0; + let posy = 0; + + // If the event is not provided, use the global window event object. + if (!ev) ev = window.event; + + // Handle touch events + if (ev.touches) { + if (ev.touches.length > 0) { // Check if there are any touches available + posx = ev.touches[0].pageX; + posy = ev.touches[0].pageY; + } + } + // Handle mouse events + else if (ev.pageX || ev.pageY) { + posx = ev.pageX; + posy = ev.pageY; + } + else if (ev.clientX || ev.clientY) { + posx = ev.clientX + body.scrollLeft + docEl.scrollLeft; + posy = ev.clientY + body.scrollTop + docEl.scrollTop; + } + + // Return the position. + return {x: posx, y: posy}; +} + +const getMouseDistance = (mousePos, lastMousePos) => { + return distance(mousePos.x, mousePos.y, lastMousePos.x, lastMousePos.y); +}; + +/** +* Computes the new position in an array after moving by a given offset. +* The array is treated as circular, meaning subtracting from the beginning +* wraps to the end of the array. +* +* @function +* @param {number} position - The starting position in the array. +* @param {number} offset - The number of positions to move backward. +* @param {Array} arr - The array in which to compute the new position. +* @returns {number} The new position in the array after moving by the offset. +*/ +const getNewPosition = (position, offset, arr) => { + // Ensure offset is non-negative and is within the range of the array's length + const realOffset = Math.abs(offset) % arr.length; + + // Check if subtracting the offset stays within the array's bounds + if (position - realOffset >= 0) { + return position - realOffset; + } else { + // If not, wrap around to the end of the array and compute the new position + return arr.length - (realOffset - position); + } +}; + +/** +* Set the clip path for each of the clipInnerElements based on the provided grid dimensions. +* @param {Array} clipInnerElements - The list of elements to set the clip paths on. +* @param {number} numRows - The number of rows in the grid. +* @param {number} numCols - The number of columns in the grid. +*/ +const setClipPath = (clipInnerElements, numRows, numCols) => { + if (clipInnerElements.length !== numRows * numCols) { + console.error('Mismatch between provided grid dimensions and number of elements.'); + return; + } + + for (let i = 0; i < numRows; i++) { + for (let j = 0; j < numCols; j++) { + const idx = i * numCols + j; + + const top = (100 / numRows) * i + '%'; + const bottom = (100 / numRows) * (i + 1) + '%'; + const left = (100 / numCols) * j + '%'; + const right = (100 / numCols) * (j + 1) + '%'; + + const clipPathValue = `polygon(${left} ${top}, ${right} ${top}, ${right} ${bottom}, ${left} ${bottom})`; + + clipInnerElements[idx].style.clipPath = clipPathValue; + } + } +} + +export { + preloadImages, + getGrid, + lerp, + getCursorPos, + map, + calcWinsize, + getPointerPos, + getMouseDistance, + getNewPosition, + setClipPath, + distance +}; \ No newline at end of file diff --git a/assets/scss/dist/styles.css b/assets/scss/dist/styles.css deleted file mode 100644 index 0ae2675..0000000 --- a/assets/scss/dist/styles.css +++ /dev/null @@ -1,175 +0,0 @@ -/*===== GOOGLE FONTS =====*/ -@import url("https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"); -/*===== VARIABLES CSS =====*/ -:root { - --header-height: 3rem; - --nav-width: 68px; - /*===== Colors =====*/ - --first-color: #4723D9; - --first-color-light: #AFA5D9; - --white-color: #F7F6FB; - /*===== Font and typography =====*/ - --body-font: "Nunito", sans-serif; - --normal-font-size: 1rem; - /*===== z index =====*/ - --z-fixed: 100; -} - -/*===== BASE =====*/ -*, ::before, ::after { - box-sizing: border-box; -} - -body { - position: relative; - margin: var(--header-height) 0 0 0; - padding: 0 1rem; - font-family: var(--body-font); - font-size: var(--normal-font-size); - transition: 0.5s; -} - -a { - text-decoration: none; -} - -/*===== HEADER =====*/ -.header { - width: 100%; - height: var(--header-height); - position: fixed; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 1rem; - background-color: var(--white-color); - z-index: var(--z-fixed); - transition: 0.5s; -} -.header__toggle { - color: var(--first-color); - font-size: 1.5rem; - cursor: pointer; -} -.header__img { - width: 35px; - height: 35px; - display: flex; - justify-content: center; - border-radius: 50%; - overflow: hidden; -} -.header__img img { - width: 40px; -} - -/*===== NAV =====*/ -.l-navbar { - position: fixed; - top: 0; - left: -30%; - width: var(--nav-width); - height: 100vh; - background-color: var(--first-color); - padding: 0.5rem 1rem 0 0; - transition: 0.5s; - z-index: var(--z-fixed); -} - -.nav { - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - overflow: hidden; -} -.nav__logo, .nav__link { - display: grid; - grid-template-columns: max-content max-content; - align-items: center; - column-gap: 1rem; - padding: 0.5rem 0 0.5rem 1.5rem; -} -.nav__logo { - margin-bottom: 2rem; -} -.nav__logo-icon { - font-size: 1.25rem; - color: var(--white-color); -} -.nav__logo-name { - color: var(--white-color); - font-weight: 700; -} -.nav__link { - position: relative; - color: var(--first-color-light); - margin-bottom: 1.5rem; - transition: 0.3s; -} -.nav__link:hover { - color: var(--white-color); -} -.nav__icon { - font-size: 1.25rem; -} - -/*Show navbar movil*/ -.show { - left: 0; -} - -/*Add padding body movil*/ -.body-pd { - padding-left: calc(var(--nav-width) + 1rem); -} - -/*Active links*/ -.active { - color: var(--white-color); -} -.active::before { - content: ""; - position: absolute; - left: 0; - width: 2px; - height: 32px; - background-color: var(--white-color); -} - -/* ===== MEDIA QUERIES=====*/ -@media screen and (min-width: 768px) { - body { - margin: calc(var(--header-height) + 1rem) 0 0 0; - padding-left: calc(var(--nav-width) + 2rem); - } - - .header { - height: calc(var(--header-height) + 1rem); - padding: 0 2rem 0 calc(var(--nav-width) + 2rem); - } - .header__img { - width: 40px; - height: 40px; - } - .header__img img { - width: 45px; - } - - .l-navbar { - left: 0; - padding: 1rem 1rem 0 0; - } - - /*Show navbar desktop*/ - .show { - width: calc(var(--nav-width) + 156px); - } - - /*Add padding body desktop*/ - .body-pd { - padding-left: calc(var(--nav-width) + 188px); - } -} \ No newline at end of file diff --git a/assets/scss/styles.scss b/assets/scss/styles.scss deleted file mode 100644 index 6157057..0000000 --- a/assets/scss/styles.scss +++ /dev/null @@ -1,189 +0,0 @@ -/*===== GOOGLE FONTS =====*/ -@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap'); - -/*===== VARIABLES CSS =====*/ -:root{ - --header-height: 3rem; - --nav-width: 68px; - - /*===== Colors =====*/ - --first-color: #4723D9; - --first-color-light: #AFA5D9; - --white-color: #F7F6FB; - - /*===== Font and typography =====*/ - --body-font: 'Nunito', sans-serif; - --normal-font-size: 1rem; - - /*===== z index =====*/ - --z-fixed: 100; -} - -/*===== BASE =====*/ -*,::before,::after{ - box-sizing: border-box; -} - -body{ - position: relative; - margin: var(--header-height) 0 0 0; - padding: 0 1rem; - font-family: var(--body-font); - font-size: var(--normal-font-size); - transition: .5s; -} - -a{ - text-decoration: none; -} - -/*===== HEADER =====*/ -.header{ - width: 100%; - height: var(--header-height); - position: fixed; - top: 0; - left: 0; - display: flex; - align-items: center; - justify-content: space-between; - padding: 0 1rem; - background-color: var(--white-color); - z-index: var(--z-fixed); - transition: .5s; - - &__toggle{ - color: var(--first-color); - font-size: 1.5rem; - cursor: pointer; - } - &__img{ - width: 35px; - height: 35px; - display: flex; - justify-content: center; - border-radius: 50%; - overflow: hidden; - - & img{ - width: 40px; - } - } -} - -/*===== NAV =====*/ -.l-navbar{ - position: fixed; - top: 0; - left: -30%; - width: var(--nav-width); - height: 100vh; - background-color: var(--first-color); - padding: .5rem 1rem 0 0; - transition: .5s; - z-index: var(--z-fixed); -} - -.nav{ - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - overflow: hidden; - - &__logo, &__link{ - display: grid; - grid-template-columns: max-content max-content; - align-items: center; - column-gap: 1rem; - padding: .5rem 0 .5rem 1.5rem; - } - &__logo{ - margin-bottom: 2rem; - - &-icon{ - font-size: 1.25rem; - color: var(--white-color); - } - &-name{ - color: var(--white-color); - font-weight: 700; - } - } - - &__link{ - position: relative; - color: var(--first-color-light); - margin-bottom: 1.5rem; - transition: .3s; - - &:hover{ - color: var(--white-color); - } - } - - &__icon{ - font-size: 1.25rem; - } -} - -/*Show navbar movil*/ -.show{ - left: 0; -} - -/*Add padding body movil*/ -.body-pd{ - padding-left: calc(var(--nav-width) + 1rem); -} - -/*Active links*/ -.active{ - color: var(--white-color); - - &::before{ - content: ''; - position: absolute; - left: 0; - width: 2px; - height: 32px; - background-color: var(--white-color); - } -} - - -/* ===== MEDIA QUERIES=====*/ -@media screen and (min-width: 768px){ - body{ - margin: calc(var(--header-height) + 1rem) 0 0 0; - padding-left: calc(var(--nav-width) + 2rem); - } - .header{ - height: calc(var(--header-height) + 1rem); - padding: 0 2rem 0 calc(var(--nav-width) + 2rem); - - &__img{ - width: 40px; - height: 40px; - - & img{ - width: 45px; - } - } - } - - .l-navbar{ - left: 0; - padding: 1rem 1rem 0 0; - } - - /*Show navbar desktop*/ - .show{ - width: calc(var(--nav-width) + 156px); - } - - /*Add padding body desktop*/ - .body-pd{ - padding-left: calc(var(--nav-width) + 188px); - } -} diff --git a/bioinviot.html b/bioinviot.html deleted file mode 100644 index 7957910..0000000 --- a/bioinviot.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - Bio Inv IOT - - - - -
- - -
-
- - -
-
-

BIO_INV IoT = Automated Greenhouse with Abiotic prediction model

-

As the creator of this project, my role was:
-
- => Design a fully automated hydroponic greenhouse for lettuce crops with NFT and Dutch Bucket system technique by automating the watering system, temperature, humidity control, refill system for water reservoirs with Arduino (C++), 24/7 monitoring system, and Abiotic data sent to ThingSpeak in real-time. -

- => Track the lettuce crop growth, regulate pH and EC parameters with Hanna instruments, and create a Temperature-Humidity algorithm with Python forfuture crop quality prediction. -

- => Compare the influence on the final mass of the crop within four different substrate systems as an extended essay investigation. Concluding that coconut fiber is the best substrate capable of optimizing water consumption and other parameters, so I implemented the project in my high school. -

- => Participated in a national competition for water care. Achieved second place with a score of 0.30 difference from first place.

-
- -
-
-
- -
-
-
- - - -
- -
-
- -
-
-

BIO_INV IoT Project Gallery

- - -
-
-
- - - - - - - \ No newline at end of file diff --git a/contact.html b/contact.html deleted file mode 100644 index 3cc0780..0000000 --- a/contact.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Contact Me | Edward Gaibor - - - - - - - - -
- -

Contact Me

-
- - - - - - - - -
- - -
- - - - - - - - diff --git a/drug-medication.html b/drug-medication.html deleted file mode 100644 index c31a217..0000000 --- a/drug-medication.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - Drug Medicator - - - - -
- - -
-
- -
-
- -
-
- -
-
-

Drug Medicator based on the condition given.

-

As the creator of this project, my role was:
-
- => Download the database. -

- => Analyze the database to organize the possible ideas for the project, as the file had more infomation than just the medical condition. Such as the drug used for each condition, its review and score. -

- => Import the sentiment analysis library to get a score from the drug review at the database, and therefore filter the recommended drugs. -

- => Classify drugs and use user interaction to prompt the user the top 10 drugs for the condition they entered. This is not a medical prescription system. It is just for the user to have a clear panorama of the possible routes they can go with medical supervision and the experience of others that already have gone through that route. -

- => Publish it with GIT. -

-
- -
-
-
- -
-
-
- - - -
- -
-
- -
-
-

Drug Suggestion System Gallery

- - -
-
-
- - - - - - - \ No newline at end of file diff --git a/exoplanets.html b/exoplanets.html deleted file mode 100644 index 0171cbf..0000000 --- a/exoplanets.html +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - Exoplanet Predictor - - - - -
- - -
-
-
-
- -
-
- -
-
-

Exoplanet Prediction Algorithm with a 92% accuracy score.

-

- The Exoplanet Predictor Version 1.0 is a command line tool that predicts the number of planets in a system based on its stellar characteristics. The user has two options for usage: single prediction and multiple predictions. The tool was trained using a database from the NASA Exoplanet Archive. For a web-based experience, the user can visit the GitHub repository for the Interactive Exoplanet Predictor. -

- In addition to being a standalone command-line tool, this project was also used to collaborate with a fellow student on an interactive web app. The web app provides users with a more enjoyable and user-friendly interface for interacting with the Exoplanet Predictor tool.

- This information is important in the field of astronomy, where understanding the properties of exoplanets and their host stars can help us better understand the formation and evolution of planetary systems. -

-
- -
-
-
- -
-
- -
- - - -
- -
-
- -
-
-

Exoplanet Predictor Project Gallery

- - -
-
-
- - - - - - - \ No newline at end of file diff --git a/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.ttf b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.ttf new file mode 100644 index 0000000..99955c2 Binary files /dev/null and b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.ttf differ diff --git a/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff new file mode 100644 index 0000000..f3bd438 Binary files /dev/null and b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff differ diff --git a/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff2 b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff2 new file mode 100644 index 0000000..bbc774f Binary files /dev/null and b/fonts/BricolageGrotesque-VariableFont_opsz,wdth,wght.woff2 differ diff --git a/index.html b/index.html index 25ca4a6..920b376 100644 --- a/index.html +++ b/index.html @@ -1,353 +1,397 @@ - + + - - - - - - - - - - - - - - - - - - - - - Edward Gaibor - + My Portfolio - Edward Gaibor + + + - - - - - - -
-
-

Hi!
I'm , a:

-

My personal interests are Machine Learning/DL, SWE and Web development.” -
I am always open to collaboration and new opportunities/challenges.

- - -
-
+ +

My Favorite Projects

+
+
+ + + +
- -
- -
-
-
- -
-
- -
- - -
- -
- -
-

-
- -

Something About Me

-

- Hey there! I'm Edward, my tech stack is Python, HTML, CSS, Java, and C. I also like to use sci-kit-learn, NumPy, Pandas, Flask, and more, unleashing their full potential to create exciting projects that push boundaries. As a ML and Neuroscience student Research Fellow, I'm rocking the academic scene while immersing myself in mind-boggling research. My recent internship at MIT had me tinkering with "NoBrainer," an awe-inspiring project focusing on 3D image processing. But coding is just the beginning of my story! I also find web design fun, and I've mastered the art of customer service and troubleshooting. I also support open-science and collaborative learning, for example, I organized UMass Boston's first-ever hackathon and promoted collaboration between participants. -

+
-
-
-
-
- -

Python

-
-
+
+

QR Pigeon - Share images fast and cross-platform

+
    +
  • We realized that all tools for sharing images from your phone to your laptop have a certain level of friction. Thus, we aim to make the sharing process as smooth as possible. No apps. No account setup. No clutter.
  • -
    -
    - -

    C

    -
    -
    +
  • All you have to do is open https://www.qrpigeon.pics/ on your computer, scan the QR code on your phone, upload or take any image, and refresh the website on your computer! Boom, your pigeon has flown faster than light! Now you can download or copy the images with max quality and use them however you need, 100% free 🤯.
  • -
    -
    - -

    Java

    -
    -
    - - -
    -
    - -

    HTML5

    -
    -
    +
-
-
- -

CSS3

-
-
- -
-
- -

Communicator / Podcaster

-
-
- -
-
- -

Cybersecurity with Python

-
-
+ + + + + + +
-
-
- -

Livestreaming With OBS

-
-
-
-
- -

Wordpress Sites

-
-
+
+

Hydroponic IoT Greenhouse "BioInv_IoT"

+
    +
  • Improved water consumption by +90 percent. As result, got second place in the national competition Junior Water Prize of Ecuador and participated in “Innovadores” – Ecuador’s innovation tournament, leading to a reduction of 50 dollars in weekly spending for my school’s dining service.
  • +
  • I created a refill system for water reservoirs with Arduino (C++) and a 24/7 monitoring system of abiotic data using ThingSpeak with MatLab triggers.
  • -
    -
    - -

    C++

    -
    -
    +
-
-
- -

Machine Learning

-
-
+ + + + + + +
+
+

6 Deep learning projects with Tensorflow

+
    +
  • I did six projects related to deep learning, which include regression and classification, such as CNN model to predict + Pneumonia via images, CNN model to predict galaxy type, Life Expectancy within countries, Medical Cost prediction with + patient data, Patient survival rate, Air Quality predictor, and Forest Cover Type Classifier. As a result, I achieved a + certification.
  • +
+ + + -
-
- -

Spanish & English

-
-
+ + + -
- -
+
+
+

Interactive Exoplanet Predictor

+
    +
  • I predicted the number of planets based on the stellar characteristics using the Random Forest Classifier by scikit-learn + algorithm, resulting in Systems with one star with a 98% Accuracy score
  • +
  • In collaboration, an extended version of this project was made available through a 3D front-end. Collaborator: Ayden Diel.
  • +
+ + + + +
- - +
+

👀 View more projects here.

-

- - - -
- -

Projects

- -
-
- -
- -
-

Exoplanet Predictor Algorithm

-

In this project I build a Machine Learning Algorithm in order to predict how many planets can a certain system have based on its mass, age, etc. It was a very interesting project built with python and Decision Tree Algorithmic aplication, but it can also be applied with polinomial models.

+ + + - - -
- -
-

- BioInv_IoT -

-

- This project references more the circuit part of the modeling - inside a greenhouse, in order to automate Lettuce growing using - hidroponic tecniques and Sensors data. The data processing was - implemented using ThinkSpeak and API's. -

+

Boostlet Presentation in SCU

2023
+ +
+
+
-
-
- -
-
- -
-
- -
+

Boostlet Presentation in Sloan Meeting

2023
+
+
+
+
-
- - -
- -
-

- Deep Learning Projects with Tensorflow -

-

- Collection of Deep Learning projects implemented using TensorFlow. These projects showcase various applications and techniques of Deep Learning, providing hands-on examples for building neural networks and solving real-world problems. -

+

MIT Media Lab AI Conference

2023
+ +
+
+
-
-
- -
+

Boston Bridge Hackathon

2024
+
+
+
+
-
-
+

MIT Media Lab AI Conference

2023
+ +
+
+
+
+

Boston Bridge Hackathon

2024
+
+
+
+
+
+

Niivue Hackathon @ SCU

2023
+
+
+
+
+
+

Internship Conference

2023
+
+
+
+
+
+

MIT Media Lab AI for Architecture Conference

2023
+
+
+
+
+
+

Boston Bridge Hackathon

2024
+
+
+
+
+
+

Google DevFest

2023
+
+
+
+
+
+

South Carolina University

2023
+
+
+
+
+
+

UMB CS Club Guest Speaker - Anthony Hannon

2024
+
+ - -
-
-

Achievements

-

Check some of my Achievements!

-
- - +
+
+

My Working Experience

+
+ SWE Intern +

Upcoming SWE Intern

+

+ This upcoming summer 2024 I will be working as a SWE intern @ John Hancock. +

+
+
+ Heart Icon +

Biomedical Signal and Image Processing

+

+ Grader @ UMB for 20 students, where I had to review homework. I also built a Discord bot to automate the grading process. +

+
+
+ Brain Icon +

Neuroimaging Edge Computing Research

+

+ Research assistantship @ UMB for Boostlet.js to enable framework-agnostic image + processing on the web. +

+
+
+ GPU +

Graphics Programming

+

Grader @ UMB, reviewed weekly homework assignments for 30+ senior and graduate students and solved multiple issues + related to XTK.js, Three.js, WebGL, and more.

+
+
+ Data +

Data Visualization on the Web

+

Grader @ UMB for 20 students, where I had to review homework. I also built a Discord bot to automate the grading process.

+
+
+ Lab +

Research Intern

+

Developed scientific software for neuroimaging and other biomedical signals @ MIT, including neural network models.

+
+
+ PC +

Technical Intern

+

Added a CI/CD pipeline @ MIT that automated the handling of new neuroimaging models using GitHub Actions, Amazon’s EC2 + machines, and LinkML.

+
+
+
+
+

Certificates

+
+
+ Certificate 1 + Certificate 2 + Certificate 3 + Certificate 4 + Certificate 5 + Certificate 6 + Certificate 7 + Certificate 8 + Certificate 9 + Certificate 10 +
+
+ + +
+
+
+ +
+

Acknowledgements

+

+ This website was inspired by the font Bricolage Grotesque, designed by Mathieu Triay. I used a similar style with brown, red and sepia tones to create a vintage look. I was also inspired by their font's website. When I travel, I like to take pictures of the places I visit, so I decided to integrate that passion within the cursor effect on the home page. All the pictures taken in the gallery are from my personal collection.

-

- -
- -

Contact Me

-
- - - - - - - - -
+ For the effects used on this website, I used the repository CoDrops as inspiration, without their tutorials and help this website would not have been possible.

+ + I was also inspired by the minimalist approach of Hesham Eissa and Lindsey Poulter on their website Ben & Jerry's. + + I would also want to acknowledge the documentation of css and html, which helped me to create this website. +

+ + +
- - + - + + + + + + + - - - + + + + + + + + + + + + - + \ No newline at end of file diff --git a/projects.html b/projects.html index 49fd825..fbfe16a 100644 --- a/projects.html +++ b/projects.html @@ -1,453 +1,306 @@ - - - - - - - - - - - - - - - - - + + + Projects + + + + +
+ Return to Homepage +
- Projects | Edward Gaibor - +
+ +
+ Project Image +

QR Pigeon

+
+ Flask + HTML + CSS + JavaScript + Cloud Computing + Python +
- - - +
+ Project Image +

Class assignment feedback discord bot

+
+ Python + Linux +
+

Feedback Wizard Bot is a Discord bot designed to enhance the feedback and grading process within educational or training-oriented Discord servers. It simplifies the distribution and management of assignment feedback and grade distributions. Currently 2 university courses are using this discord bot to power their feedback distribution to students through Discord 😁

+ +
-
-

Projects

+
+ Project Image +

DNS Traffic Control

+
+ Python + Linux +
+

The DNS Traffic Control Project is a machine learning project that aims to classify DNS traffic as either benign or malicious using stateless and stateful datasets. The purpose of this project is to build a model that can accurately detect and prevent malicious DNS traffic.

+ +
-
-
-
- -
-

- Streamlit, OpenAI, LLMs, LangChain “PDF GPT” -

-

- Built a multi-pdf analyzer and question-answer bot with five auto-generated preview questions. -

-
-
-
- -
-
-
+
+ Project Image +

9 Machine Learning Projects with Sklearn

+
+ Python + Sklearn + Jupyter Notebooks +
+

Built 9 ML projects on developing models for Handwriting recognition, Titanic survival prediction, Baseball Strikes prediction, Tweet classification, Income prediction, Naive Bayes, Perceptrons, and more, using sklearn. As a result, I achieved a certification.

+ +
-
- -
-

- 9 Machine Learning Projects with Tensorflow -

-

- I did nine projects on developing models for Handwriting recognition, Titanic survival prediction, Baseball Strikes prediction, Tweet classification, Income prediction, Naive Bayes, Perceptrons, and more, using sklearn. As a result, I achieved a certification. -

-
-
-
- -
-
-
+
+ Project Image +

6 Deep Learning Projects with Tensorflow

+
+ Python + Tensorflow + Jupyter Notebooks +
+

Collection of 6 Deep Learning projects implemented using TensorFlow. These include Air Quality Prediction, CNN for Pneumoniua prediction, galaxy type prediction, life expectancy predictor, medical cost preditor, patient survival predictor, x-ray lung predictor, and more!

+ +
-
- -
-

- 6 Deep Learning Projects with Tensorflow -

-

- Collection of 6 Deep Learning projects implemented using TensorFlow. These projects showcase various applications and techniques of Deep Learning, providing hands-on examples for building neural networks and solving real-world problems. -

-
-
-
- -
-
+
+ Project Image +

Exoplanet Predictor

+
+ Python + Sklearn + Jupyter Notebooks +
+

In this project I build a Machine Learning Algorithm in order to predict how many planets can a certain system have based on its mass, age, etc. It was a very interesting project built with python and Decision Tree Algorithmic aplication, but it can also be applied with polinomial models. It later scaled as a collaborative project for the web!

+ - -
- -
-

Exoplanet Predictor Algorithm

-

In this project I build a Machine Learning Algorithm in order to predict how many planets can a certain system have based on its mass, age, etc. It was a very interesting project built with python and Decision Tree Algorithmic aplication, but it can also be applied with polinomial models.

-
-
-
- -
-
- -
-
-
+
-
- -
-

Drug Medication based on Condition

-

- Classify drugs and use user interaction to prompt the user the top 10 drugs for the condition they entered. This is not a medical prescription system. It is just for the user to have a clear panorama of the possible routes they can go with medical supervision and the experience of others that already have gone through that route. -

-
-
-
- -
-
- -
-
-
+
+ Project Image +

Drug Medication based on Condition

+
+ Python + Jupyter Notebooks +
+

Classify drugs and use user interaction to prompt the user the top 10 drugs for the condition they entered. This is not a medical prescription system. It is just for the user to have a clear panorama of the possible routes they can go with medical supervision and the experience of others that already have gone through that route.

+ +
-
- -
-

Temperature vs. Humidity Model inside a greenhouse

-

In this project with the help of Python I used the data recollected in my greenhouse. With this data I obtained a mathematical model in order to predict Humidity within a data of Temperature inside my hidroponic greenhouse.

-
-
-
- -
-
- -
-
-
+
+ Project Image +

Temperature vs. Humidity Model inside a greenhouse

+
+ Python + Arduino +
+

In this project with the help of Python I used the data recollected in my greenhouse. With this data I obtained a mathematical model in order to predict Humidity within a data of Temperature inside my hidroponic greenhouse.

+ +
-
- -
-

Local Weather Predictor

-

In this project with the help of Python I used the data recollected in my town area. With this data I used a machine learning algorithm to predict either temperature or humidity conditions. I also used arduino sensors to recollect the data.

-
-
-
- -
-
-
+
+ Project Image +

Local Weather Predictor

+
+ Python + Arduino + Sklearn + Joblib + Tkinter +
+

In this project with the help of Python I used the data recollected in my town area. With this data I used a machine learning algorithm to predict either temperature or humidity conditions. I also used arduino sensors to recollect the data.

+ +
+
+ Project Image +

Responsive Podcast Website

+
+ HTML + CSS + JavaScript +
+

In this project I design my podcast website, considering its responsiveness. During the development of the website, I used HTML5, CSS3, and Javascript for the animation. I also implemented the scrollreveal framework, in order to add a much more personalized effect. The typing animation is also an iconic element of the site.

+ +
-
- -
-

Responsive Podcast Website

-

- In this project I design my podcast website, considering its - responsiveness. During the development of the website, I used - HTML5, CSS3, and Javascript for the animation. I also implemented the scrollreveal framework, in - order to add a much more personalized effect. The typing - animation is also an iconic element of the site. -

-
-
-
- -
-
-
-
- -
-

¿Y Tú, Que Piensas? - Podcast

-

- This project is a personal boosted idea that I decided to - implement since 2019 to the present date. I see this podcast as - an excellent way to communicate my ideas, learn from - professional people in the topic, and discuss about - environmental issues or give specific information about some of - the IB topics. -

-
-
-
- -
-
-
-
- -
-

- Hourly variation in concentration levels (μg/m3) of PM2.5, O3, SO2, and CO -

-

- This project focuses on comparing the Air Pollution data before and during the Pandemic of the Covid-19, to stablish environmental conclusions of its impact. -

-
-
-
- -
-
- -
-
-
-
- -
-

"Andromeda" Assitant

-

- In this project I created a Voice Assistant named Andromeda. The - main language I used was Python and its libraries. I used - OpenCv to add facial recognition and activation of the Voice - Assistant. This was the first project I coded using Python. -

-
-
-
- -
-
-
+
+ Project Image +

Hourly variation in concentration levels (μg/m3) of PM2.5, O3, SO2, and CO

+
+ Python + Matplotlib + Pandas + Seaborn +
-
- -
-

- BioInv_IoT -

-

- This project references more the circuit part of the modeling - inside a greenhouse, in order to automate Lettuce growing using - hidroponic tecniques and Sensors data. The data processing was - implemented using ThinkSpeak and API's. -

-
-
-
- -
-
- -
-
- -
-
-
-
- -
-

"CAS INFORMA" - Community Project

-

- This is a social project to spread information about Covid-19 during - the Pandemic. The project focuses in Creativity, Action and - Service. So, we covered environmental, health, Elderly care, and - educational ideas such as building organic gardens, publishing - informational videos and supporting the betterment in the local - community. -

-
-
-
- -
-
-
+

This project focuses on comparing the Air Pollution data before and during the Pandemic of the Covid-19, to stablish environmental conclusions of its impact.

+ +
-
- -
-

CASInformando - Podcast

-

- A podcast dedicated to inform our community about COVID-19 news, - self-care strategies, recommendations, and more. In this podcast - I am one of the 6 Hosts that take part of this wonderful - project. -

-
-
-
- -
-
-
-
- -
-

Model to represent temperature and electric current of a Peltier cell

-

- Recollect data by measuring 50 times the temperature of the Peltier cell while variating the electric current with a circuit I built (see paper). Create models with the data and conclude that the relationship between the current and temperature of a Peltier cell is negative quadratic. -

-
-
-
- -
-
-
+
+ Project Image +

Model to represent temperature and electric current of a Peltier cell

+
+ Python + Matplotlib + Pandas - +
+

Recollect data by measuring 50 times the temperature of the Peltier cell while variating the electric current with a circuit I built (see paper). Create models with the data and conclude that the relationship between the current and temperature of a Peltier cell is negative quadratic.

+ +
+
+ Project Image +

Andromeda AI

+
+ Python + CLI
+

This was my first project ever 😅, it was what I considered back then as "AI assistant." I am including it in my portfolio only because it has sentimental value, but also because it has facial recognition to personalize the assitance lol (A.K.A 1000 if statements).

+
-
- -
-
-
- iNaturalist Ecuador -
- - - - - - - -
-
- - - - - - - +
- + + + \ No newline at end of file diff --git a/projectsRedirect.html b/projectsRedirect.html new file mode 100644 index 0000000..6afbeb0 --- /dev/null +++ b/projectsRedirect.html @@ -0,0 +1,31 @@ + + + + Redirecting... + + + + + + +

Redirecting...

+

Please wait while we redirect you to the new page.

+ Redirecting... +

If you are not automatically redirected, please click here.

+ + + + + + + + + + + + + \ No newline at end of file diff --git a/tempandhum.html b/tempandhum.html deleted file mode 100644 index e0896ee..0000000 --- a/tempandhum.html +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - Temperatura and Humidity Predictor - - - - -
- - -
-
-
-
- -
-
- -
-
-

Temperature & Humidity Predictor with Python and IoT to improve the local weather forecast.

-

As the creator of this project, my role was:
-
- => Build an Arduino system to collect local environmental data and connect the electronics structure to ThingSpeak through C++. -

- => Utilize libraries such as Pandas, Numpy, Sklearn, and JobLib to adjust the data to train the model with both temperature and humidity variables and dump it into a JobLib file to use later as a GUI backend process. -

- => Create a live-prediction option for the variables with Python to get the result with the immediate data sent from the weather station to the server, utilizing APIs and Joblib. -

- => Create the GUI app with Tkinter and transform the format to .exe. And publish the project with GIT. -

- => Write an extended essay about the mathematical relation between Temperature and Humidity to show the calculus background of the code. -

-
- -
-
-
- -
-
-
- - - -
- -
-
- -
-
-

Temperature-Humidity Predictor Project Gallery

- - -
-
-
- - - - - - - \ No newline at end of file diff --git a/thanks.html b/thanks.html deleted file mode 100644 index 01d4ae2..0000000 --- a/thanks.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - Thanks! | Edward Gaibor - - - - - - - - -
- -
- - - -
- -

Thanks for the submission!

- - -
- - - - - - - - -