├── .eslintignore ├── CNAME ├── .gitignore ├── .prettierrc ├── README.md ├── fav.png ├── dist ├── fav.png ├── imgs │ ├── js.f8a28e905c78dadb79434b7ceebd52a0.png │ ├── css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png │ ├── git.3092b5991e8accb9e7c36817c048a8d5.png │ ├── html.6aa56206be02cf6404844871df1d2da6.png │ ├── mail.4f2db89278f9ad3abef627211b414574.png │ ├── mongo.41ae1969f341d30268a13d57846efcc6.png │ ├── node.94a06c4b9dd29e984501e6407e77a918.png │ ├── react.cb15bfce2a9004ce61c5f79f805b067b.png │ ├── retro.d5a0a58727affa92cb80fdfa78a07a26.png │ ├── sass.3706567f8b353c748df3850c1aabca46.png │ ├── todo.af05ff37bdc5302d22530d5631e136cd.png │ ├── chatapp.d9f2104f9e2c15a0bcbba042541ca178.png │ ├── express.1eca086d2a78b4be3dd1f0a47b84b618.png │ ├── nextjs.ff373e2ef4f7fdf152425a8c5c30816c.png │ ├── github-logo.d03ce87cf6b5a432c44f847eefec1204.png │ └── lifeinvader.c25acb0a33904bc4e90c656d87c651cc.png ├── main.e7c7970a12833611eb02.js.LICENSE.txt ├── index.html └── main.40f27e161ba829c32fbb.css ├── src ├── assets │ ├── js.png │ ├── py.png │ ├── r.png │ ├── css.png │ ├── fav.png │ ├── git.png │ ├── html.png │ ├── mail.png │ ├── node.png │ ├── npm.png │ ├── sass.png │ ├── todo.png │ ├── chatapp.png │ ├── express.png │ ├── mongo.png │ ├── nextjs.png │ ├── propic.png │ ├── react.png │ ├── retro.png │ ├── weather.png │ ├── webpack.png │ ├── github-logo.png │ ├── lifeinvader.png │ ├── arrow_right.svg │ ├── arrow-right.svg │ ├── chevrons-up.svg │ └── avatar.svg ├── sass │ ├── _main-bg.scss │ ├── main.scss │ ├── _typography.scss │ ├── _animations.scss │ ├── _nav.scss │ ├── _base.scss │ ├── _footer.scss │ ├── _hero.scss │ ├── _contact.scss │ ├── _about.scss │ └── _projects.scss ├── heroCanvas.js ├── index.js ├── bgCanvas.js └── template.html ├── imgs ├── js.f8a28e905c78dadb79434b7ceebd52a0.png ├── py.624bcc94d9a32d8cddac41f381aa4395.png ├── r.7d32c114a558654d975f9186352ead77.png ├── css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png ├── git.3092b5991e8accb9e7c36817c048a8d5.png ├── html.6aa56206be02cf6404844871df1d2da6.png ├── mail.4f2db89278f9ad3abef627211b414574.png ├── npm.9657700bc507dfd98ae4f1e24554e890.png ├── react.cb15bfce2a9004ce61c5f79f805b067b.png ├── retro.d5a0a58727affa92cb80fdfa78a07a26.png ├── sass.3706567f8b353c748df3850c1aabca46.png ├── todo.af05ff37bdc5302d22530d5631e136cd.png ├── weather.bfcd270635125d60d55252c300c11a97.png ├── webpack.7a613eb3ec6549c39bfdf9774185c98a.png └── github-logo.d03ce87cf6b5a432c44f847eefec1204.png ├── webpack.dev.js ├── .eslintrc.json ├── webpack.common.js ├── webpack.prod.js ├── package.json ├── index.html └── main.a0ef648aaae13a2d3ab7.css /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | www.benscott.dev -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Portfolio site 2 | 3 | https://www.benscott.dev/ 4 | -------------------------------------------------------------------------------- /fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/fav.png -------------------------------------------------------------------------------- /dist/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/fav.png -------------------------------------------------------------------------------- /src/assets/js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/js.png -------------------------------------------------------------------------------- /src/assets/py.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/py.png -------------------------------------------------------------------------------- /src/assets/r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/r.png -------------------------------------------------------------------------------- /src/assets/css.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/css.png -------------------------------------------------------------------------------- /src/assets/fav.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/fav.png -------------------------------------------------------------------------------- /src/assets/git.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/git.png -------------------------------------------------------------------------------- /src/assets/html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/html.png -------------------------------------------------------------------------------- /src/assets/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/mail.png -------------------------------------------------------------------------------- /src/assets/node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/node.png -------------------------------------------------------------------------------- /src/assets/npm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/npm.png -------------------------------------------------------------------------------- /src/assets/sass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/sass.png -------------------------------------------------------------------------------- /src/assets/todo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/todo.png -------------------------------------------------------------------------------- /src/assets/chatapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/chatapp.png -------------------------------------------------------------------------------- /src/assets/express.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/express.png -------------------------------------------------------------------------------- /src/assets/mongo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/mongo.png -------------------------------------------------------------------------------- /src/assets/nextjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/nextjs.png -------------------------------------------------------------------------------- /src/assets/propic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/propic.png -------------------------------------------------------------------------------- /src/assets/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/react.png -------------------------------------------------------------------------------- /src/assets/retro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/retro.png -------------------------------------------------------------------------------- /src/assets/weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/weather.png -------------------------------------------------------------------------------- /src/assets/webpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/webpack.png -------------------------------------------------------------------------------- /src/assets/github-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/github-logo.png -------------------------------------------------------------------------------- /src/assets/lifeinvader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/src/assets/lifeinvader.png -------------------------------------------------------------------------------- /imgs/js.f8a28e905c78dadb79434b7ceebd52a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/js.f8a28e905c78dadb79434b7ceebd52a0.png -------------------------------------------------------------------------------- /imgs/py.624bcc94d9a32d8cddac41f381aa4395.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/py.624bcc94d9a32d8cddac41f381aa4395.png -------------------------------------------------------------------------------- /imgs/r.7d32c114a558654d975f9186352ead77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/r.7d32c114a558654d975f9186352ead77.png -------------------------------------------------------------------------------- /imgs/css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png -------------------------------------------------------------------------------- /imgs/git.3092b5991e8accb9e7c36817c048a8d5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/git.3092b5991e8accb9e7c36817c048a8d5.png -------------------------------------------------------------------------------- /imgs/html.6aa56206be02cf6404844871df1d2da6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/html.6aa56206be02cf6404844871df1d2da6.png -------------------------------------------------------------------------------- /imgs/mail.4f2db89278f9ad3abef627211b414574.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/mail.4f2db89278f9ad3abef627211b414574.png -------------------------------------------------------------------------------- /imgs/npm.9657700bc507dfd98ae4f1e24554e890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/npm.9657700bc507dfd98ae4f1e24554e890.png -------------------------------------------------------------------------------- /imgs/react.cb15bfce2a9004ce61c5f79f805b067b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/react.cb15bfce2a9004ce61c5f79f805b067b.png -------------------------------------------------------------------------------- /imgs/retro.d5a0a58727affa92cb80fdfa78a07a26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/retro.d5a0a58727affa92cb80fdfa78a07a26.png -------------------------------------------------------------------------------- /imgs/sass.3706567f8b353c748df3850c1aabca46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/sass.3706567f8b353c748df3850c1aabca46.png -------------------------------------------------------------------------------- /imgs/todo.af05ff37bdc5302d22530d5631e136cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/todo.af05ff37bdc5302d22530d5631e136cd.png -------------------------------------------------------------------------------- /dist/imgs/js.f8a28e905c78dadb79434b7ceebd52a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/js.f8a28e905c78dadb79434b7ceebd52a0.png -------------------------------------------------------------------------------- /imgs/weather.bfcd270635125d60d55252c300c11a97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/weather.bfcd270635125d60d55252c300c11a97.png -------------------------------------------------------------------------------- /imgs/webpack.7a613eb3ec6549c39bfdf9774185c98a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/webpack.7a613eb3ec6549c39bfdf9774185c98a.png -------------------------------------------------------------------------------- /dist/imgs/css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/css.0ce0f0a2b4c4aa34b64c40e5278af3d1.png -------------------------------------------------------------------------------- /dist/imgs/git.3092b5991e8accb9e7c36817c048a8d5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/git.3092b5991e8accb9e7c36817c048a8d5.png -------------------------------------------------------------------------------- /dist/imgs/html.6aa56206be02cf6404844871df1d2da6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/html.6aa56206be02cf6404844871df1d2da6.png -------------------------------------------------------------------------------- /dist/imgs/mail.4f2db89278f9ad3abef627211b414574.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/mail.4f2db89278f9ad3abef627211b414574.png -------------------------------------------------------------------------------- /dist/imgs/mongo.41ae1969f341d30268a13d57846efcc6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/mongo.41ae1969f341d30268a13d57846efcc6.png -------------------------------------------------------------------------------- /dist/imgs/node.94a06c4b9dd29e984501e6407e77a918.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/node.94a06c4b9dd29e984501e6407e77a918.png -------------------------------------------------------------------------------- /dist/imgs/react.cb15bfce2a9004ce61c5f79f805b067b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/react.cb15bfce2a9004ce61c5f79f805b067b.png -------------------------------------------------------------------------------- /dist/imgs/retro.d5a0a58727affa92cb80fdfa78a07a26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/retro.d5a0a58727affa92cb80fdfa78a07a26.png -------------------------------------------------------------------------------- /dist/imgs/sass.3706567f8b353c748df3850c1aabca46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/sass.3706567f8b353c748df3850c1aabca46.png -------------------------------------------------------------------------------- /dist/imgs/todo.af05ff37bdc5302d22530d5631e136cd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/todo.af05ff37bdc5302d22530d5631e136cd.png -------------------------------------------------------------------------------- /dist/imgs/chatapp.d9f2104f9e2c15a0bcbba042541ca178.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/chatapp.d9f2104f9e2c15a0bcbba042541ca178.png -------------------------------------------------------------------------------- /dist/imgs/express.1eca086d2a78b4be3dd1f0a47b84b618.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/express.1eca086d2a78b4be3dd1f0a47b84b618.png -------------------------------------------------------------------------------- /dist/imgs/nextjs.ff373e2ef4f7fdf152425a8c5c30816c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/nextjs.ff373e2ef4f7fdf152425a8c5c30816c.png -------------------------------------------------------------------------------- /imgs/github-logo.d03ce87cf6b5a432c44f847eefec1204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/imgs/github-logo.d03ce87cf6b5a432c44f847eefec1204.png -------------------------------------------------------------------------------- /dist/imgs/github-logo.d03ce87cf6b5a432c44f847eefec1204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/github-logo.d03ce87cf6b5a432c44f847eefec1204.png -------------------------------------------------------------------------------- /dist/imgs/lifeinvader.c25acb0a33904bc4e90c656d87c651cc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bscottnz/portfolio-site/HEAD/dist/imgs/lifeinvader.c25acb0a33904bc4e90c656d87c651cc.png -------------------------------------------------------------------------------- /src/sass/_main-bg.scss: -------------------------------------------------------------------------------- 1 | .main-bg { 2 | height: 100vh; 3 | position: fixed; 4 | top: 0; 5 | width: 100%; 6 | 7 | background-color: royalblue; 8 | 9 | // z-index: 999; 10 | } 11 | -------------------------------------------------------------------------------- /src/assets/arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | arrow_right 3 | 4 | -------------------------------------------------------------------------------- /src/sass/main.scss: -------------------------------------------------------------------------------- 1 | @import 'base.scss'; 2 | 3 | @import 'about.scss'; 4 | @import 'animations.scss'; 5 | @import 'contact.scss'; 6 | @import 'footer.scss'; 7 | @import 'hero.scss'; 8 | @import 'main-bg.scss'; 9 | @import 'nav.scss'; 10 | @import 'projects.scss'; 11 | @import 'typography.scss'; 12 | -------------------------------------------------------------------------------- /src/sass/_typography.scss: -------------------------------------------------------------------------------- 1 | .section-heading { 2 | position: relative; 3 | font-size: 5.5rem; 4 | font-weight: 700; 5 | margin-top: 9rem; 6 | margin-bottom: 13rem; 7 | 8 | // text-shadow: 0 0 1px $color-background, 0 0 1px $color-background, 9 | // 0 0 1px $color-background, 0 0 1px $color-background; 10 | 11 | z-index: 9999; 12 | 13 | @media (max-width: 1200px) { 14 | margin-bottom: 10rem; 15 | } 16 | 17 | @media (max-width: 1000px) { 18 | margin-top: 6rem; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | arrow-right 4 | 5 | 6 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { merge } = require('webpack-merge'); 3 | const common = require('./webpack.common'); 4 | 5 | module.exports = merge(common, { 6 | mode: 'development', 7 | output: { 8 | filename: 'main.js', 9 | path: path.resolve(__dirname, 'dist'), 10 | }, 11 | devtool: 'source-map', 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.scss$/, 16 | use: ['style-loader', 'css-loader', 'sass-loader'], 17 | }, 18 | ], 19 | }, 20 | }); 21 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier"], 3 | "plugins": ["prettier"], 4 | "rules": { 5 | "prettier/prettier": "warn", 6 | "no-unused-vars": "warn", 7 | "no-console": "off", 8 | "func-names": "off", 9 | "object-shorthand": "off", 10 | "class-methods-use-this": "off", 11 | "no-plusplus": "off", 12 | "import/no-extraneous-dependencies": [ 13 | "error", 14 | { 15 | "devDependencies": ["**/webpack.*.js"] 16 | } 17 | ] 18 | }, 19 | "env": { 20 | "browser": true, 21 | "node": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/assets/chevrons-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | chevrons-up 4 | 5 | 6 | -------------------------------------------------------------------------------- /webpack.common.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | 3 | module.exports = { 4 | entry: './src/index.js', 5 | plugins: [ 6 | new HtmlWebpackPlugin({ 7 | template: './src/template.html', 8 | favicon: `./src/assets/fav.png`, 9 | }), 10 | ], 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.html$/, 15 | use: ['html-loader'], 16 | }, 17 | { 18 | test: /\.(svg|png|jpg|jpeg|gif)$/i, 19 | use: { 20 | loader: 'file-loader', 21 | options: { 22 | esModule: false, 23 | name: '[name].[hash].[ext]', 24 | outputPath: 'imgs', 25 | }, 26 | }, 27 | }, 28 | ], 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/sass/_animations.scss: -------------------------------------------------------------------------------- 1 | @keyframes moveInLeft { 2 | 0% { 3 | opacity: 0; 4 | transform: translateX(-10rem); 5 | } 6 | 7 | 100% { 8 | opacity: 1; 9 | transform: translateX(0); 10 | } 11 | } 12 | 13 | @keyframes moveInRight { 14 | 0% { 15 | opacity: 0; 16 | transform: translateX(10rem); 17 | } 18 | 19 | 100% { 20 | opacity: 1; 21 | transform: translateX(0); 22 | } 23 | } 24 | 25 | @keyframes moveInBottom { 26 | 0% { 27 | opacity: 0; 28 | transform: translateY(4rem); 29 | } 30 | 31 | 100% { 32 | opacity: 1; 33 | transform: translateY(0); 34 | } 35 | } 36 | 37 | @keyframes bounce { 38 | 0% { 39 | transform: translateY(0); 40 | } 41 | 50% { 42 | transform: translateY(-1rem); 43 | } 44 | 45 | 100% { 46 | transform: translateY(0); 47 | } 48 | } 49 | 50 | @keyframes fadeIn { 51 | 0% { 52 | opacity: 0; 53 | } 54 | 55 | 100% { 56 | opacity: 1; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { merge } = require('webpack-merge'); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 5 | const common = require('./webpack.common'); 6 | 7 | module.exports = merge(common, { 8 | mode: 'production', 9 | output: { 10 | filename: 'main.[contenthash].js', 11 | path: path.resolve(__dirname, 'dist'), 12 | }, 13 | plugins: [ 14 | new MiniCssExtractPlugin({ 15 | filename: 'main.[contenthash].css', 16 | }), 17 | new CleanWebpackPlugin({ 18 | cleanAfterEveryBuildPatterns: ['dist'], 19 | }), 20 | ], 21 | module: { 22 | rules: [ 23 | { 24 | test: /\.scss$/, 25 | use: [ 26 | { 27 | loader: MiniCssExtractPlugin.loader, 28 | options: { 29 | publicPath: '', 30 | }, 31 | }, 32 | 'css-loader', 33 | 'sass-loader', 34 | ], 35 | }, 36 | ], 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /dist/main.e7c7970a12833611eb02.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! ***************************************************************************** 2 | Copyright (c) Microsoft Corporation. 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | ***************************************************************************** */ 15 | 16 | /** 17 | * @license 18 | * Copyright Google Inc. All Rights Reserved. 19 | * 20 | * Use of this source code is governed by an MIT-style license that can be 21 | * found in the LICENSE file at https://angular.io/license 22 | */ 23 | -------------------------------------------------------------------------------- /src/sass/_nav.scss: -------------------------------------------------------------------------------- 1 | .navigation { 2 | display: flex; 3 | margin-right: 10rem; 4 | 5 | font-size: 2rem; 6 | font-weight: 500; 7 | letter-spacing: 1px; 8 | 9 | @media (max-width: 1200px) { 10 | margin-right: 3rem; 11 | } 12 | 13 | @media (max-width: 700px) { 14 | margin-right: 0; 15 | } 16 | 17 | &-bar { 18 | position: sticky; 19 | position: -webkit-sticky; 20 | top: 0; 21 | display: flex; 22 | justify-content: flex-end; 23 | align-items: center; 24 | height: 6rem; 25 | border-bottom: 1px solid $color-background; 26 | background-color: rgba($color-background-light, 0.95); 27 | backdrop-filter: blur(8px); 28 | 29 | box-shadow: 0 4px 4px rgba(0, 0, 0, 0.3); 30 | 31 | z-index: 99999999999; 32 | 33 | @media (max-width: 700px) { 34 | justify-content: center; 35 | } 36 | } 37 | 38 | &__item { 39 | transition: all 0.2s; 40 | &:not(:last-child) { 41 | margin-right: 3rem; 42 | } 43 | 44 | &--active { 45 | color: $color-red; 46 | // font-weight: 600; 47 | } 48 | &:hover { 49 | color: $color-red; 50 | // font-weight: 600; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/sass/_base.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap'); 3 | 4 | $color-text: #fafafa; 5 | $color-red: #ff4d5a; 6 | $color-background: rgb(26, 26, 26); 7 | $color-background-light: rgb(40, 40, 40); 8 | $color-blue: rgb(81, 162, 233); 9 | $color-blue-dark: rgb(50, 22, 187); 10 | 11 | *, 12 | *::before, 13 | *::after { 14 | margin: 0; 15 | padding: 0; 16 | box-sizing: inherit; 17 | } 18 | 19 | html { 20 | box-sizing: border-box; 21 | 22 | font-size: 62.5%; // 1 rem = 10 px (browser default is 16) 23 | 24 | scroll-behavior: smooth; 25 | 26 | @media (max-width: 1500px) { 27 | font-size: 57.25%; 28 | } 29 | 30 | @media (max-width: 1200px) { 31 | font-size: 50%; 32 | } 33 | 34 | @media (max-width: 770px) { 35 | font-size: 43.75%; 36 | } 37 | 38 | @media (max-width: 615px) { 39 | font-size: 40%; 40 | } 41 | 42 | @media (max-width: 350px) { 43 | font-size: 35%; 44 | } 45 | } 46 | 47 | body { 48 | min-height: 100vh; 49 | color: $color-text; 50 | font-family: montserrat, sans-serif; 51 | background-color: $color-background; 52 | overflow-x: hidden; 53 | } 54 | 55 | li { 56 | list-style: none; 57 | } 58 | 59 | a { 60 | text-decoration: none; 61 | color: inherit; 62 | } 63 | 64 | button { 65 | border: none; 66 | outline: none; 67 | background-color: transparent; 68 | color: inherit; 69 | } 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "project-setup-webpack-notes", 3 | "version": "1.0.0", 4 | "description": "---", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack serve --config webpack.dev.js --open 'google-chrome'", 8 | "build": "webpack --config webpack.prod.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/bscottnz/project-setup-webpack-notes.git" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/bscottnz/project-setup-webpack-notes/issues" 19 | }, 20 | "homepage": "https://github.com/bscottnz/project-setup-webpack-notes#readme", 21 | "devDependencies": { 22 | "css-loader": "^5.0.2", 23 | "eslint": "^7.19.0", 24 | "eslint-config-airbnb": "^18.2.1", 25 | "eslint-config-node": "^4.1.0", 26 | "eslint-config-prettier": "^7.2.0", 27 | "eslint-plugin-import": "^2.22.1", 28 | "eslint-plugin-jsx-a11y": "^6.4.1", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-prettier": "^3.3.1", 31 | "eslint-plugin-react": "^7.22.0", 32 | "eslint-plugin-react-hooks": "^4.2.0", 33 | "file-loader": "^6.2.0", 34 | "html-loader": "^1.3.2", 35 | "html-webpack-plugin": "^5.0.0", 36 | "mini-css-extract-plugin": "^1.3.6", 37 | "node-sass": "^5.0.0", 38 | "prettier": "^2.2.1", 39 | "sass-loader": "^11.0.1", 40 | "style-loader": "^2.0.0", 41 | "webpack": "^5.21.2", 42 | "webpack-cli": "^4.5.0", 43 | "webpack-dev-server": "^3.11.2", 44 | "webpack-merge": "^5.7.3" 45 | }, 46 | "dependencies": { 47 | "clean-webpack-plugin": "^3.0.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/sass/_footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | align-items: center; 7 | height: 160px; 8 | background-color: $color-background-light; 9 | } 10 | 11 | .socials { 12 | display: flex; 13 | margin-bottom: 20px; 14 | &__github, 15 | &__email { 16 | display: flex; 17 | justify-content: center; 18 | align-items: center; 19 | // width: 25px; 20 | height: 35px; 21 | 22 | background-color: transparent; 23 | cursor: pointer; 24 | // border: 2px solid $color-background; 25 | transition: all 0.2s; 26 | 27 | &:hover { 28 | transform: scale(1.2); 29 | } 30 | } 31 | 32 | &__github { 33 | margin-right: 1rem; 34 | } 35 | &__email { 36 | margin-left: 1rem; 37 | } 38 | 39 | & img { 40 | height: 100%; 41 | } 42 | } 43 | 44 | .copyright { 45 | color: $color-text; 46 | font-size: 10px; 47 | font-weight: 500; 48 | } 49 | 50 | .return-home { 51 | position: absolute; 52 | top: -25px; 53 | 54 | width: 40px; 55 | height: 45px; 56 | margin-right: auto; 57 | margin-left: auto; 58 | left: 0; 59 | right: 0; 60 | text-align: center; 61 | 62 | // transform: translateX(-50%); 63 | 64 | background-color: $color-red; 65 | 66 | -webkit-animation-duration: 1s; 67 | animation-duration: 1s; 68 | -webkit-animation-fill-mode: both; 69 | animation-fill-mode: both; 70 | -webkit-animation-timing-function: ease-in-out; 71 | animation-timing-function: ease-in-out; 72 | animation-iteration-count: infinite; 73 | -webkit-animation-iteration-count: infinite; 74 | 75 | &:hover { 76 | cursor: pointer; 77 | animation-name: bounce; 78 | -moz-animation-name: bounce; 79 | } 80 | 81 | & svg { 82 | width: 100%; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/assets/avatar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 13 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/sass/_hero.scss: -------------------------------------------------------------------------------- 1 | .hero { 2 | position: relative; 3 | display: flex; 4 | height: 100vh; 5 | width: 100%; 6 | z-index: 999; 7 | } 8 | 9 | .canvas { 10 | position: absolute; 11 | top: 0; 12 | right: 0; 13 | left: 0; 14 | bottom: 0; 15 | 16 | width: 100%; 17 | height: 100vh; 18 | 19 | background-color: $color-background; 20 | overflow: hidden; 21 | } 22 | 23 | .connecting-dots { 24 | // position: fixed; 25 | 26 | height: 100%; 27 | width: 100%; 28 | // z-index: -1; 29 | } 30 | 31 | .heading { 32 | position: relative; 33 | align-self: center; 34 | justify-self: center; 35 | 36 | display: flex; 37 | flex-direction: column; 38 | align-items: center; 39 | line-height: normal; 40 | width: fit-content; 41 | height: auto; 42 | margin-left: auto; 43 | margin-right: auto; 44 | 45 | color: $color-text; 46 | font-weight: 300; 47 | 48 | z-index: 999; 49 | 50 | &__line-1 { 51 | animation-name: moveInLeft; 52 | 53 | & span { 54 | color: $color-red; 55 | font-weight: 400; 56 | } 57 | } 58 | 59 | &__line-2 { 60 | animation-name: moveInRight; 61 | } 62 | 63 | &__line-1, 64 | &__line-2 { 65 | font-size: 6rem; 66 | background-color: (rgba($color-background, 0.25)); 67 | 68 | animation-duration: 1.4s; 69 | animation-timing-function: cubic-bezier(0.21, 1.11, 0.81, 0.99); 70 | 71 | @media (max-width: 700px) { 72 | font-size: 5rem; 73 | text-align: center; 74 | margin-left: 4rem; 75 | margin-right: 4rem; 76 | } 77 | 78 | @media (max-width: 550px) { 79 | font-size: 5rem; 80 | } 81 | } 82 | 83 | &-cta { 84 | position: relative; 85 | 86 | display: flex; 87 | align-items: center; 88 | margin-top: 2.4rem; 89 | padding: 0.8rem 3rem; 90 | width: 27.5rem; 91 | height: 4.8rem; 92 | 93 | background-color: rgba($color-background, 0.6); 94 | border: 2px solid $color-red; 95 | border-radius: 2px; 96 | 97 | color: $color-red; 98 | font-size: 2.4rem; 99 | font-weight: 500; 100 | 101 | cursor: pointer; 102 | animation: moveInBottom 0.7s 1.2s; 103 | animation-fill-mode: backwards; 104 | animation-timing-function: cubic-bezier(0.21, 1.11, 0.81, 0.99); 105 | 106 | @media (max-width: 1500px) { 107 | width: auto; 108 | } 109 | 110 | @media (max-width: 700px) { 111 | margin-top: 1.8rem; 112 | } 113 | 114 | @media (max-width: 550px) { 115 | padding: 0.8rem 2rem; 116 | } 117 | 118 | // &:hover .heading__arrow { 119 | // transform: rotate(90deg); 120 | // margin-left: 14px; 121 | // } 122 | 123 | &:before, 124 | &:after { 125 | content: ''; 126 | position: absolute; 127 | 128 | top: -2px; 129 | left: -2px; 130 | width: 27.5rem; 131 | height: 4.8rem; 132 | 133 | border-radius: 3px; 134 | border: 2px solid rgba($color-red, 1); 135 | 136 | filter: blur(0); 137 | transform-origin: 50%; 138 | z-index: -1; 139 | 140 | @media (max-width: 1500px) { 141 | width: 27.8rem; 142 | } 143 | 144 | @media (max-width: 1200px) { 145 | width: 28.5rem; 146 | border: 2px solid transparent; 147 | } 148 | } 149 | &:hover { 150 | transform: translateY(-2px); 151 | 152 | &:before, 153 | &:after { 154 | border-color: transparent; 155 | 156 | filter: blur(2px); 157 | transform: scaleX(1.3) scaleY(2.2); 158 | transition: 800ms transform ease, 1900ms blur ease, 159 | 700ms border-color ease; 160 | pointer-events: none; 161 | } 162 | &:after { 163 | transition-delay: 150ms; 164 | } 165 | } 166 | 167 | &:active { 168 | transform: translateY(-1px); 169 | } 170 | } 171 | 172 | &__arrow { 173 | display: inline-block; 174 | height: 24px; 175 | width: 24px; 176 | margin-left: 15px; 177 | // margin-bottom: -3px; 178 | transform: rotate(90deg); 179 | 180 | fill: $color-red; 181 | 182 | transition: all 0.3s; 183 | 184 | @media (max-width: 770px) { 185 | height: 20px; 186 | width: 20px; 187 | } 188 | 189 | @media (max-width: 615px) { 190 | margin-left: 10px; 191 | } 192 | 193 | @media (max-width: 550px) { 194 | height: 16px; 195 | width: 16px; 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/sass/_contact.scss: -------------------------------------------------------------------------------- 1 | .contact { 2 | position: relative; 3 | margin-left: auto; 4 | margin-right: auto; 5 | display: flex; 6 | width: 500px; 7 | flex-direction: column; 8 | align-items: center; 9 | justify-content: center; 10 | 11 | z-index: 10; 12 | 13 | margin-bottom: 10rem; 14 | 15 | @media (max-width: 700px) { 16 | width: 400px; 17 | } 18 | 19 | @media (max-width: 470px) { 20 | width: 330px; 21 | } 22 | 23 | @media (max-width: 400px) { 24 | width: 260px; 25 | } 26 | 27 | &__heading { 28 | margin-top: -4rem !important; 29 | margin-bottom: 6rem !important; 30 | &:before { 31 | position: absolute; 32 | content: ''; 33 | border-bottom: 18px solid $color-red; 34 | width: 21rem; 35 | display: block; 36 | margin: 0 auto; 37 | position: relative; 38 | left: 3.5rem; 39 | top: 6.3rem; 40 | 41 | z-index: -1; 42 | 43 | @media (max-width: 770px) { 44 | // width: 14rem; 45 | border-bottom: 14px solid $color-red; 46 | } 47 | } 48 | } 49 | 50 | &__text { 51 | font-size: 1.8rem; 52 | margin-bottom: 6rem; 53 | } 54 | 55 | &__form { 56 | display: flex; 57 | flex-direction: column; 58 | align-items: center; 59 | justify-content: center; 60 | 61 | &-name, 62 | &-email { 63 | margin-bottom: 6px; 64 | padding: 1rem; 65 | height: 4rem; 66 | } 67 | 68 | &-message { 69 | height: 12rem; 70 | padding: 1rem; 71 | } 72 | 73 | &-submit-2 { 74 | align-self: flex-start; 75 | margin-top: 0 !important; 76 | } 77 | 78 | &-submit { 79 | align-self: flex-start; 80 | position: relative; 81 | // margin-top: 1.5rem; 82 | padding: 0.6rem 1rem; 83 | width: fit-content; 84 | 85 | font-size: 1.6rem; 86 | text-transform: uppercase; 87 | font-weight: 700; 88 | letter-spacing: 3px; 89 | // border-bottom: 2px solid $color-red; 90 | z-index: 9; 91 | cursor: pointer; 92 | 93 | &:hover { 94 | color: $color-background; 95 | font-weight: 700; 96 | } 97 | 98 | &:after { 99 | position: absolute; 100 | content: ''; 101 | border-bottom: 2px solid $color-red; 102 | 103 | width: calc(100% + 2rem); 104 | // height: 100%; 105 | left: -14%; 106 | top: 0.5rem; 107 | display: block; 108 | margin: 0 auto; 109 | position: relative; 110 | 111 | transform-origin: bottom; 112 | transition: all 0.2s; 113 | 114 | // left: -8rem; 115 | 116 | z-index: -1; 117 | } 118 | 119 | &:hover:after { 120 | transform: scaleY(17.5); 121 | 122 | @media (max-width: 1500px) { 123 | transform: scaleY(16.5); 124 | } 125 | 126 | @media (max-width: 1200px) { 127 | transform: scaleY(14); 128 | } 129 | 130 | @media (max-width: 770px) { 131 | transform: scaleY(12.5); 132 | } 133 | } 134 | } 135 | } 136 | 137 | & input, 138 | & textarea { 139 | width: 500px; 140 | resize: none; 141 | border: none; 142 | color: inherit; 143 | background-color: $color-background-light; 144 | font-size: 1.6rem; 145 | font-family: monserrat, sans-serif; 146 | 147 | border-left: 2px solid transparent; 148 | 149 | border-radius: 0; 150 | 151 | @media (max-width: 700px) { 152 | width: 400px; 153 | } 154 | 155 | @media (max-width: 470px) { 156 | width: 330px; 157 | } 158 | 159 | @media (max-width: 400px) { 160 | width: 260px; 161 | } 162 | 163 | &:focus { 164 | outline: none; 165 | } 166 | &::placeholder { 167 | /* Chrome, Firefox, Opera, Safari 10.1+ */ 168 | color: rgba($color-text, 0.6); 169 | opacity: 1; /* Firefox */ 170 | } 171 | 172 | :-ms-input-placeholder { 173 | /* Internet Explorer 10-11 */ 174 | color: rgba($color-text, 0.6); 175 | } 176 | 177 | ::-ms-input-placeholder { 178 | /* Microsoft Edge */ 179 | color: rgba($color-text, 0.6); 180 | } 181 | } 182 | } 183 | 184 | .contact__form-error-submit { 185 | margin-top: 1.5rem; 186 | height: 7rem; 187 | width: 100%; 188 | display: flex; 189 | justify-content: space-between; 190 | align-items: center; 191 | } 192 | 193 | .form-error { 194 | align-self: start; 195 | font-size: 1.6rem; 196 | font-weight: 500; 197 | line-height: 1.5; 198 | 199 | // all form error messages 200 | & > * { 201 | display: none; 202 | } 203 | } 204 | 205 | .input-error { 206 | border-left: 2px solid $color-red !important; 207 | } 208 | -------------------------------------------------------------------------------- /src/sass/_about.scss: -------------------------------------------------------------------------------- 1 | .about { 2 | // height: 800px; 3 | width: 1300px; 4 | margin-left: auto; 5 | margin-right: auto; 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | 10 | @media (max-width: 1500px) { 11 | width: 1100px; 12 | } 13 | 14 | @media (max-width: 1200px) { 15 | width: auto; 16 | } 17 | 18 | &__heading { 19 | // &:after { 20 | // content: ''; 21 | // border-bottom: 3px solid $color-red; 22 | // width: 15.5rem; 23 | // display: block; 24 | // margin: 0 auto; 25 | // position: relative; 26 | // left: -3rem; 27 | // } 28 | 29 | &:before { 30 | position: absolute; 31 | content: ''; 32 | border-bottom: 18px solid $color-red; 33 | width: 16rem; 34 | display: block; 35 | margin: 0 auto; 36 | position: relative; 37 | left: 3.5rem; 38 | top: 6.3rem; 39 | 40 | z-index: -1; 41 | 42 | @media (max-width: 770px) { 43 | // width: 14rem; 44 | border-bottom: 14px solid $color-red; 45 | } 46 | } 47 | } 48 | 49 | &__content { 50 | display: flex; 51 | justify-content: space-between; 52 | width: 100%; 53 | 54 | @media (max-width: 1300px) { 55 | flex-direction: column; 56 | } 57 | } 58 | } 59 | 60 | .profile { 61 | position: relative; 62 | 63 | display: flex; 64 | flex-direction: column; 65 | align-items: center; 66 | 67 | // background-color: $color-blue-dark; 68 | font-weight: 500; 69 | 70 | left: -300px; 71 | opacity: 0; 72 | transition: all 1.1s; 73 | 74 | // no fade in on small screen 75 | @media (max-width: 1301px) { 76 | margin-bottom: 10rem; 77 | left: 0; 78 | opacity: 1; 79 | } 80 | 81 | @media (max-width: 1000px) { 82 | margin-bottom: 7rem; 83 | } 84 | 85 | &__picture { 86 | height: 24rem; 87 | // width: 35rem; 88 | margin-bottom: 4rem; 89 | // background-color: $color-blue-dark; 90 | 91 | display: flex; 92 | justify-content: flex-start; 93 | align-items: center; 94 | & svg { 95 | transition: all 1.1s; 96 | } 97 | } 98 | &__blurb { 99 | font-size: 1.8rem; 100 | width: 500px; 101 | line-height: 1.8; 102 | 103 | @media (max-width: 600px) { 104 | width: 80vw; 105 | margin-left: auto; 106 | margin-right: auto; 107 | } 108 | } 109 | 110 | &__fade-in { 111 | opacity: 1; 112 | transform: translateX(300px); 113 | 114 | @media (max-width: 1300px) { 115 | transform: translateX(0); 116 | } 117 | } 118 | } 119 | 120 | .skills { 121 | display: flex; 122 | justify-content: center; 123 | 124 | &__row { 125 | display: flex; 126 | flex-direction: column; 127 | justify-content: center; 128 | 129 | &:not(:last-child) { 130 | margin-right: 25px; 131 | 132 | @media (max-width: 410px) { 133 | margin-right: 15px; 134 | } 135 | 136 | @media (max-width: 300px) { 137 | margin-right: 10px; 138 | } 139 | } 140 | } 141 | &__item { 142 | opacity: 0; 143 | position: relative; 144 | display: flex; 145 | flex-direction: column; 146 | align-items: center; 147 | justify-content: space-evenly; 148 | height: 100px; 149 | width: 160px; 150 | 151 | border: double 3px transparent; 152 | 153 | border-image-slice: 1; 154 | border-width: 3px; 155 | background-image: linear-gradient($color-background, $color-background), 156 | radial-gradient(circle at top left, $color-blue, $color-red); 157 | border-radius: 10px; 158 | background-origin: border-box; 159 | background-clip: content-box, border-box; 160 | 161 | transition: transform 0.2s, opacity 1.2s; 162 | overflow: hidden; 163 | 164 | @media (max-width: 1500px) { 165 | height: 90px; 166 | width: 145px; 167 | } 168 | 169 | @media (max-width: 1300px) { 170 | opacity: 1; 171 | border-width: 2px; 172 | } 173 | 174 | @media (max-width: 1000px) { 175 | height: 80px; 176 | width: 130px; 177 | } 178 | 179 | @media (max-width: 600px) { 180 | height: 70px; 181 | width: 115px; 182 | } 183 | 184 | @media (max-width: 500px) { 185 | height: 60px; 186 | width: 100px; 187 | } 188 | 189 | @media (max-width: 410px) { 190 | height: 50px; 191 | width: 80px; 192 | } 193 | 194 | @media (max-width: 340px) { 195 | height: 45px; 196 | width: 70px; 197 | } 198 | 199 | // @media (max-width: 350px) { 200 | // height: 40px; 201 | // width: 65px; 202 | // } 203 | 204 | &:not(:last-child) { 205 | margin-bottom: 3rem; 206 | 207 | @media (max-width: 410px) { 208 | margin-bottom: 15px; 209 | } 210 | } 211 | 212 | & img { 213 | // position: relative; 214 | // top: -0.8rem; 215 | height: 60px; 216 | width: auto; 217 | transition: all 0.2s; 218 | 219 | @media (max-width: 1500px) { 220 | height: 55px; 221 | } 222 | 223 | @media (max-width: 1000px) { 224 | height: 50px; 225 | } 226 | 227 | @media (max-width: 600px) { 228 | height: 45px; 229 | } 230 | 231 | @media (max-width: 500px) { 232 | height: 35px; 233 | } 234 | 235 | @media (max-width: 410px) { 236 | height: 26px; 237 | } 238 | } 239 | 240 | &-name { 241 | // position: absolute; 242 | // bottom: 0.5rem; 243 | font-size: 1.2rem; 244 | font-weight: 600; 245 | line-height: 1; 246 | // opacity: 0; 247 | 248 | transition: all 0.2s; 249 | letter-spacing: 1px; 250 | 251 | @media (max-width: 1200px) { 252 | font-size: 1.4rem; 253 | } 254 | } 255 | 256 | // &:hover { 257 | // transform: scale(1.1); 258 | 259 | // & img { 260 | // transform: translateY(-0.8rem); 261 | // } 262 | 263 | // & .skills__item-name { 264 | // opacity: 1; 265 | // transform: translateY(0.5rem); 266 | // } 267 | // } 268 | 269 | &-fade-in { 270 | opacity: 1; 271 | } 272 | 273 | &--js img { 274 | border-radius: 5px; 275 | } 276 | } 277 | } 278 | 279 | .skills__item--webpack img { 280 | border-radius: 50%; 281 | } 282 | -------------------------------------------------------------------------------- /src/heroCanvas.js: -------------------------------------------------------------------------------- 1 | const canvasDots = function () { 2 | const canvas = document.querySelector('canvas'), 3 | ctx = canvas.getContext('2d'), 4 | colorDot = [ 5 | 'rgb(81, 162, 233)', 6 | 'rgb(81, 162, 233)', 7 | 'rgb(81, 162, 233)', 8 | 'rgb(81, 162, 233)', 9 | 'rgb(255, 77, 90)', 10 | ], // 80% of dots are blue. 20% pink 11 | color = 'rgb(81, 162, 233)'; 12 | 13 | // ctx.globalAlpha = 0.8; 14 | canvas.width = document.body.scrollWidth; 15 | canvas.height = window.innerHeight; 16 | canvas.style.display = 'block'; 17 | // ctx.fillStyle = colorDot; 18 | // ctx.fillStyle = 'hsl(' + 360 * Math.random() + ', 50%, 50%)'; 19 | ctx.lineWidth = 0.3; 20 | ctx.strokeStyle = color; 21 | 22 | let mousePosition = { 23 | x: (30 * canvas.width) / 100, 24 | y: (30 * canvas.height) / 100, 25 | }; 26 | 27 | const windowSize = window.innerWidth; 28 | let dots; 29 | 30 | if (windowSize > 1600) { 31 | dots = { 32 | nb: 600, // number of particles 33 | distance: 70, // max distance between particles for them to link 34 | d_radius: 300, // radius from mouse location that particles will link 35 | array: [], 36 | }; 37 | } else if (windowSize > 1300) { 38 | dots = { 39 | nb: 575, 40 | distance: 60, 41 | d_radius: 280, 42 | array: [], 43 | }; 44 | } else if (windowSize > 1100) { 45 | dots = { 46 | nb: 500, 47 | distance: 55, 48 | d_radius: 250, 49 | array: [], 50 | }; 51 | } else if (windowSize > 800) { 52 | dots = { 53 | nb: 300, 54 | distance: 0, 55 | d_radius: 0, 56 | array: [], 57 | }; 58 | } else if (windowSize > 600) { 59 | dots = { 60 | nb: 200, 61 | distance: 0, 62 | d_radius: 0, 63 | array: [], 64 | }; 65 | } else { 66 | dots = { 67 | nb: 100, 68 | distance: 0, 69 | d_radius: 0, 70 | array: [], 71 | }; 72 | } 73 | 74 | // decided to turn off connecting dots under 1100px 75 | 76 | // } else if (windowSize > 650) { 77 | // dots = { 78 | // nb: 400, 79 | // distance: 50, 80 | // d_radius: 185, 81 | // array: [], 82 | // }; 83 | // } else if (windowSize > 500) { 84 | // dots = { 85 | // nb: 325, 86 | // distance: 45, 87 | // d_radius: 170, 88 | // array: [], 89 | // }; 90 | // } else { 91 | // dots = { 92 | // nb: 270, 93 | // distance: 45, 94 | // d_radius: 140, 95 | // array: [], 96 | // }; 97 | // } 98 | 99 | function Dot() { 100 | this.x = Math.random() * canvas.width; 101 | this.y = Math.random() * canvas.height; 102 | 103 | this.vx = -0.5 + Math.random(); 104 | this.vy = -0.5 + Math.random(); 105 | 106 | this.radius = Math.random() * 1.5; 107 | 108 | // this.colour = 'hsl(' + 360 * Math.random() + ', 50%, 50%)'; 109 | this.colour = colorDot[Math.floor(Math.random() * colorDot.length)]; 110 | } 111 | 112 | Dot.prototype = { 113 | create: function () { 114 | ctx.beginPath(); 115 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); 116 | // ctx.fillStyle = this.colour; 117 | 118 | // make the dot colour fade out the further they are from the mouse 119 | const dotDistance = 120 | ((this.x - mousePosition.x) ** 2 + (this.y - mousePosition.y) ** 2) ** 121 | 0.5; 122 | const distanceRatio = dotDistance / (windowSize / 1.7); 123 | 124 | // this chops the bracket off the rgb colour and ads an opacity 125 | ctx.fillStyle = this.colour.slice(0, -1) + `,${1 - distanceRatio})`; 126 | 127 | ctx.fill(); 128 | }, 129 | 130 | animate: function () { 131 | // dont animate the first dot, it will follow mouse 132 | for (let i = 1; i < dots.nb; i++) { 133 | const dot = dots.array[i]; 134 | 135 | if (dot.y < 0 || dot.y > canvas.height) { 136 | dot.vx = dot.vx; 137 | dot.vy = -dot.vy; 138 | } else if (dot.x < 0 || dot.x > canvas.width) { 139 | dot.vx = -dot.vx; 140 | dot.vy = dot.vy; 141 | } 142 | dot.x += dot.vx; 143 | dot.y += dot.vy; 144 | } 145 | }, 146 | 147 | line: function () { 148 | for (let i = 0; i < dots.nb; i++) { 149 | for (let j = 0; j < dots.nb; j++) { 150 | const i_dot = dots.array[i]; 151 | const j_dot = dots.array[j]; 152 | 153 | if ( 154 | i_dot.x - j_dot.x < dots.distance && 155 | i_dot.y - j_dot.y < dots.distance && 156 | i_dot.x - j_dot.x > -dots.distance && 157 | i_dot.y - j_dot.y > -dots.distance 158 | ) { 159 | if ( 160 | i_dot.x - mousePosition.x < dots.d_radius && 161 | i_dot.y - mousePosition.y < dots.d_radius && 162 | i_dot.x - mousePosition.x > -dots.d_radius && 163 | i_dot.y - mousePosition.y > -dots.d_radius 164 | ) { 165 | ctx.beginPath(); 166 | ctx.moveTo(i_dot.x, i_dot.y); 167 | ctx.lineTo(j_dot.x, j_dot.y); 168 | 169 | // make the fill colour fade out the further you are from the mouse 170 | const dotDistance = 171 | ((i_dot.x - mousePosition.x) ** 2 + 172 | (i_dot.y - mousePosition.y) ** 2) ** 173 | 0.5; 174 | let distanceRatio = dotDistance / dots.d_radius; 175 | 176 | // make it so it doesnt fade out completely 177 | distanceRatio -= 0.3; 178 | if (distanceRatio < 0) { 179 | distanceRatio = 0; 180 | } 181 | 182 | ctx.strokeStyle = `rgb(81, 162, 233, ${1 - distanceRatio})`; 183 | 184 | ctx.stroke(); 185 | ctx.closePath(); 186 | } 187 | } 188 | } 189 | } 190 | }, 191 | }; 192 | 193 | function createDots() { 194 | ctx.clearRect(0, 0, canvas.width, canvas.height); 195 | for (let i = 0; i < dots.nb; i++) { 196 | dots.array.push(new Dot()); 197 | var dot = dots.array[i]; 198 | 199 | dot.create(); 200 | } 201 | 202 | // first dot to be relativley large 203 | dots.array[0].radius = 1.5; 204 | 205 | // first dot to be blue 206 | dots.array[0].colour = '#51a2e9'; 207 | 208 | dot.line(); 209 | dot.animate(); 210 | } 211 | 212 | window.onmousemove = function (parameter) { 213 | mousePosition.x = parameter.pageX; 214 | mousePosition.y = parameter.pageY; 215 | 216 | // sometimes if the mouse is off screen on refresh, it bugs out 217 | try { 218 | // want the first dot to follow the mouse 219 | dots.array[0].x = parameter.pageX; 220 | dots.array[0].y = parameter.pageY; 221 | } catch { 222 | // 223 | } 224 | }; 225 | 226 | mousePosition.x = window.innerWidth / 2; 227 | mousePosition.y = window.innerHeight / 2; 228 | 229 | const draw = setInterval(createDots, 1000 / 30); 230 | 231 | window.onresize = function () { 232 | clearInterval(draw); 233 | canvasDots(); 234 | // console.log(yippe); 235 | }; 236 | }; 237 | 238 | export default canvasDots; 239 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './sass/main.scss'; 2 | import canvasDots from './heroCanvas.js'; 3 | import canvasDotsBg from './bgCanvas.js'; 4 | import { doc } from 'prettier'; 5 | 6 | window.onload = function () { 7 | canvasDotsBg(); 8 | canvasDots(); 9 | }; 10 | 11 | // loads in about section on scroll 12 | function aboutFadeIn(entries, observer) { 13 | entries.forEach((entry) => { 14 | if (entry.isIntersecting && document.body.scrollWidth > 1300) { 15 | // console.log('yo'); 16 | // fade in bio 17 | document.querySelector('.profile').classList.add('profile__fade-in'); 18 | 19 | // fade in skills 1 at a time after bio has loaded 20 | const sleep = (milliseconds) => { 21 | return new Promise((resolve) => setTimeout(resolve, milliseconds)); 22 | }; 23 | 24 | //html 25 | sleep(1000).then(() => { 26 | document 27 | .querySelector('.skills__item--html') 28 | .classList.add('skills__item-fade-in'); 29 | }); 30 | 31 | //webpack 32 | sleep(1100).then(() => { 33 | document 34 | .querySelector('.skills__item--webpack') 35 | .classList.add('skills__item-fade-in'); 36 | }); 37 | 38 | //js 39 | sleep(1200).then(() => { 40 | document 41 | .querySelector('.skills__item--js') 42 | .classList.add('skills__item-fade-in'); 43 | }); 44 | 45 | //git 46 | sleep(1300).then(() => { 47 | document 48 | .querySelector('.skills__item--git') 49 | .classList.add('skills__item-fade-in'); 50 | }); 51 | 52 | //sass 53 | sleep(1400).then(() => { 54 | document 55 | .querySelector('.skills__item--sass') 56 | .classList.add('skills__item-fade-in'); 57 | }); 58 | 59 | //node 60 | sleep(1500).then(() => { 61 | document 62 | .querySelector('.skills__item--npm') 63 | .classList.add('skills__item-fade-in'); 64 | }); 65 | 66 | //py 67 | sleep(1600).then(() => { 68 | document 69 | .querySelector('.skills__item--python') 70 | .classList.add('skills__item-fade-in'); 71 | }); 72 | 73 | //react 74 | sleep(1700).then(() => { 75 | document 76 | .querySelector('.skills__item--react') 77 | .classList.add('skills__item-fade-in'); 78 | }); 79 | 80 | //r 81 | sleep(1800).then(() => { 82 | document 83 | .querySelector('.skills__item--r') 84 | .classList.add('skills__item-fade-in'); 85 | }); 86 | 87 | //css 88 | sleep(1900).then(() => { 89 | document 90 | .querySelector('.skills__item--css') 91 | .classList.add('skills__item-fade-in'); 92 | }); 93 | } 94 | }); 95 | } 96 | 97 | let options = { 98 | root: null, 99 | rootMargin: '0px', 100 | threshold: 0.5, 101 | }; 102 | 103 | let options2 = { 104 | root: null, 105 | rootMargin: '0px', 106 | threshold: 0.2, 107 | }; 108 | 109 | let observer = new IntersectionObserver(aboutFadeIn, options); 110 | 111 | observer.observe(document.querySelector('.about__content')); 112 | 113 | // navigation items in nav bar 114 | const navLinks = document.querySelectorAll('.navigation__item'); 115 | 116 | // change highlighted nav link depending on page position 117 | function navFadeIn(entries, observer) { 118 | entries.forEach((entry) => { 119 | if (entry.isIntersecting) { 120 | // console.log(entry.target.id); 121 | 122 | navLinks.forEach((link) => { 123 | link.classList.remove('navigation__item--active'); 124 | }); 125 | 126 | document 127 | .querySelector(`#nav-${entry.target.id}`) 128 | .classList.add('navigation__item--active'); 129 | } 130 | }); 131 | } 132 | 133 | // projects section is a lot longer and needs custom settings 134 | function navFadeInProjects(entries, observer) { 135 | entries.forEach((entry) => { 136 | if (entry.isIntersecting) { 137 | // console.log(entry.target.id); 138 | 139 | navLinks.forEach((link) => { 140 | link.classList.remove('navigation__item--active'); 141 | }); 142 | 143 | document 144 | .querySelector(`#nav-${entry.target.id}`) 145 | .classList.add('navigation__item--active'); 146 | } 147 | }); 148 | } 149 | 150 | let observerNav = new IntersectionObserver(navFadeIn, options); 151 | 152 | observerNav.observe(document.querySelector('#hero')); 153 | observerNav.observe(document.querySelector('#about')); 154 | observerNav.observe(document.querySelector('#contact')); 155 | 156 | let observerNavProjects = new IntersectionObserver(navFadeInProjects, options2); 157 | 158 | observerNavProjects.observe(document.querySelector('#projects')); 159 | 160 | // parralax scrolling effect on hero canvas 161 | 162 | // window.onscroll = function (e) { 163 | // console.log(document.scrollTop); 164 | // }; 165 | 166 | // document.addEventListener('scroll', () => { 167 | // // console.log(window.scrollY); 168 | 169 | // document.querySelector('.connecting-dots').style.top = `${window.scrollY}px`; 170 | // }); 171 | 172 | // form validation 173 | 174 | const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 175 | document.querySelector('#form-submit').addEventListener('click', () => { 176 | const unameInput = document.querySelector('.contact__form-name'); 177 | const emailInput = document.querySelector('.contact__form-email'); 178 | const msgInput = document.querySelector('.contact__form-message'); 179 | 180 | const uname = unameInput.value; 181 | const email = emailInput.value; 182 | const msg = msgInput.value; 183 | 184 | const unameError = document.querySelector('.form-error__name'); 185 | const emailError = document.querySelector('.form-error__email'); 186 | const msgError = document.querySelector('.form-error__msg'); 187 | 188 | let validUname = false; 189 | let validEmail = false; 190 | let validMsg = false; 191 | 192 | // console.log(uname, email, msg); 193 | if (!uname) { 194 | validUname = false; 195 | unameInput.classList.add('input-error'); 196 | unameError.style.display = 'block'; 197 | } else { 198 | validUname = true; 199 | unameInput.classList.remove('input-error'); 200 | unameError.style.display = 'none'; 201 | } 202 | 203 | if (!email.match(re)) { 204 | validEmail = false; 205 | emailInput.classList.add('input-error'); 206 | emailError.style.display = 'block'; 207 | } else { 208 | validEmail = true; 209 | emailInput.classList.remove('input-error'); 210 | emailError.style.display = 'none'; 211 | } 212 | 213 | if (!msg) { 214 | validMsg = false; 215 | msgInput.classList.add('input-error'); 216 | msgError.style.display = 'block'; 217 | } else { 218 | validMsg = true; 219 | msgInput.classList.remove('input-error'); 220 | msgError.style.display = 'none'; 221 | } 222 | 223 | if (validUname && validEmail && validMsg) { 224 | document.querySelector('.contact__form').submit(); 225 | 226 | // clear form after a delay 227 | const sleep = (milliseconds) => { 228 | return new Promise((resolve) => setTimeout(resolve, milliseconds)); 229 | }; 230 | 231 | sleep(1500).then(() => { 232 | document.querySelector('.contact__form').reset(); 233 | }); 234 | } 235 | }); 236 | -------------------------------------------------------------------------------- /src/bgCanvas.js: -------------------------------------------------------------------------------- 1 | const canvasDotsBg = function () { 2 | const canvas = document.querySelector('.canvas-2'), 3 | ctx = canvas.getContext('2d'), 4 | colorDot = [ 5 | 'rgb(81, 162, 233)', 6 | 'rgb(81, 162, 233)', 7 | 'rgb(81, 162, 233)', 8 | 'rgb(255, 77, 90)', 9 | ], // 75% of dots are blue. 25% pink 10 | color = 'rgb(81, 162, 233)'; 11 | 12 | // ctx.globalAlpha = 0.8; 13 | canvas.width = document.body.scrollWidth; 14 | canvas.height = window.innerHeight; 15 | canvas.style.display = 'block'; 16 | // ctx.fillStyle = colorDot; 17 | // ctx.fillStyle = 'hsl(' + 360 * Math.random() + ', 50%, 50%)'; 18 | ctx.lineWidth = 0.3; 19 | ctx.strokeStyle = color; 20 | 21 | let mousePosition = { 22 | x: (30 * canvas.width) / 100, 23 | y: (30 * canvas.height) / 100, 24 | }; 25 | 26 | const windowSize = window.innerWidth; 27 | let dots; 28 | 29 | if (windowSize > 1600) { 30 | dots = { 31 | nb: 100, 32 | distance: 0, 33 | d_radius: 0, 34 | array: [], 35 | }; 36 | } else if (windowSize > 1300) { 37 | dots = { 38 | nb: 75, 39 | distance: 0, 40 | d_radius: 0, 41 | array: [], 42 | }; 43 | } else if (windowSize > 1100) { 44 | dots = { 45 | nb: 50, 46 | distance: 0, 47 | d_radius: 0, 48 | array: [], 49 | }; 50 | } else if (windowSize > 800) { 51 | dots = { 52 | nb: 1, 53 | distance: 0, 54 | d_radius: 0, 55 | array: [], 56 | }; 57 | ctx.globalAlpha = 0; 58 | } else if (windowSize > 600) { 59 | dots = { 60 | nb: 1, 61 | distance: 0, 62 | d_radius: 0, 63 | array: [], 64 | }; 65 | 66 | ctx.globalAlpha = 0; 67 | } else { 68 | dots = { 69 | nb: 1, 70 | distance: 0, 71 | d_radius: 0, 72 | array: [], 73 | }; 74 | 75 | ctx.globalAlpha = 0; 76 | } 77 | 78 | // decided to turn off connecting dots under 1100px 79 | 80 | // } else if (windowSize > 650) { 81 | // dots = { 82 | // nb: 400, 83 | // distance: 50, 84 | // d_radius: 185, 85 | // array: [], 86 | // }; 87 | // } else if (windowSize > 500) { 88 | // dots = { 89 | // nb: 325, 90 | // distance: 45, 91 | // d_radius: 170, 92 | // array: [], 93 | // }; 94 | // } else { 95 | // dots = { 96 | // nb: 270, 97 | // distance: 45, 98 | // d_radius: 140, 99 | // array: [], 100 | // }; 101 | // } 102 | 103 | function Dot() { 104 | this.x = Math.random() * canvas.width; 105 | this.y = Math.random() * canvas.height; 106 | 107 | this.vx = -0.5 + Math.random(); 108 | this.vy = -0.5 + Math.random(); 109 | 110 | this.radius = Math.random() * 1.5; 111 | 112 | // this.colour = 'hsl(' + 360 * Math.random() + ', 50%, 50%)'; 113 | this.colour = colorDot[Math.floor(Math.random() * colorDot.length)]; 114 | } 115 | 116 | Dot.prototype = { 117 | create: function () { 118 | ctx.beginPath(); 119 | ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); 120 | // ctx.fillStyle = this.colour; 121 | 122 | // meed to acount for scroll height since the bg is static and uses mouse position 123 | const top = 124 | (window.pageYOffset || document.scrollTop) - (document.clientTop || 0); 125 | 126 | // make the dot colour fade out the further they are from the mouse 127 | 128 | const dotDistance = 129 | ((this.x - mousePosition.x) ** 2 + 130 | (this.y - mousePosition.y + top) ** 2) ** 131 | 0.5; 132 | const distanceRatio = dotDistance / (windowSize / 2); 133 | 134 | // this chops the bracket off the rgb colour and ads an opacity 135 | ctx.fillStyle = this.colour.slice(0, -1) + `,${1 - distanceRatio})`; 136 | // ctx.fillStyle = this.colour; 137 | 138 | ctx.fill(); 139 | }, 140 | 141 | animate: function () { 142 | // dont animate the first dot, it will follow mouse 143 | for (let i = 1; i < dots.nb; i++) { 144 | const dot = dots.array[i]; 145 | 146 | if (dot.y < 0 || dot.y > canvas.height) { 147 | dot.vx = dot.vx; 148 | dot.vy = -dot.vy; 149 | } else if (dot.x < 0 || dot.x > canvas.width) { 150 | dot.vx = -dot.vx; 151 | dot.vy = dot.vy; 152 | } 153 | dot.x += dot.vx; 154 | dot.y += dot.vy; 155 | } 156 | }, 157 | 158 | line: function () { 159 | for (let i = 0; i < dots.nb; i++) { 160 | for (let j = 0; j < dots.nb; j++) { 161 | const i_dot = dots.array[i]; 162 | const j_dot = dots.array[j]; 163 | 164 | if ( 165 | i_dot.x - j_dot.x < dots.distance && 166 | i_dot.y - j_dot.y < dots.distance && 167 | i_dot.x - j_dot.x > -dots.distance && 168 | i_dot.y - j_dot.y > -dots.distance 169 | ) { 170 | if ( 171 | i_dot.x - mousePosition.x < dots.d_radius && 172 | i_dot.y - mousePosition.y < dots.d_radius && 173 | i_dot.x - mousePosition.x > -dots.d_radius && 174 | i_dot.y - mousePosition.y > -dots.d_radius 175 | ) { 176 | ctx.beginPath(); 177 | ctx.moveTo(i_dot.x, i_dot.y); 178 | ctx.lineTo(j_dot.x, j_dot.y); 179 | 180 | // make the fill colour fade out the further you are from the mouse 181 | const dotDistance = 182 | ((i_dot.x - mousePosition.x) ** 2 + 183 | (i_dot.y - mousePosition.y) ** 2) ** 184 | 0.5; 185 | let distanceRatio = dotDistance / dots.d_radius; 186 | 187 | // make it so it doesnt fade out completely 188 | distanceRatio -= 0.3; 189 | if (distanceRatio < 0) { 190 | distanceRatio = 0; 191 | } 192 | 193 | ctx.strokeStyle = `rgb(81, 162, 233, ${1 - distanceRatio})`; 194 | 195 | ctx.stroke(); 196 | ctx.closePath(); 197 | } 198 | } 199 | } 200 | } 201 | }, 202 | }; 203 | 204 | function createDots() { 205 | ctx.clearRect(0, 0, canvas.width, canvas.height); 206 | for (let i = 0; i < dots.nb; i++) { 207 | dots.array.push(new Dot()); 208 | var dot = dots.array[i]; 209 | 210 | dot.create(); 211 | } 212 | 213 | // first dot to be relativley large 214 | dots.array[0].radius = 1.5; 215 | 216 | // first dot to be blue 217 | dots.array[0].colour = '#51a2e9'; 218 | 219 | // dot.line(); 220 | dot.animate(); 221 | } 222 | 223 | // window.onmousemove = function (parameter) { 224 | // mousePosition.x = parameter.pageX; 225 | // mousePosition.y = parameter.pageY; 226 | 227 | // // sometimes if the mouse is off screen on refresh, it bugs out 228 | // try { 229 | // // want the first dot to follow the mouse 230 | // dots.array[0].x = parameter.pageX; 231 | // dots.array[0].y = parameter.pageY; 232 | // } catch { 233 | // // 234 | // } 235 | // }; 236 | 237 | window.onscroll = function (parameter) { 238 | mousePosition.x = window.innerWidth / 2; 239 | mousePosition.y = window.innerHeight / 2; 240 | 241 | const top = 242 | (window.pageYOffset || document.scrollTop) - (document.clientTop || 0); 243 | mousePosition.y += top; 244 | // console.log(top); 245 | 246 | // console.log(mousePosition.x); 247 | }; 248 | 249 | // mousePosition.x = window.innerWidth / 2; 250 | // mousePosition.y = window.innerHeight / 2; 251 | 252 | const draw = setInterval(createDots, 1000 / 30); 253 | 254 | window.onresize = function () { 255 | clearInterval(draw); 256 | canvasDotsBg(); 257 | 258 | // console.log('yoza'); 259 | }; 260 | }; 261 | 262 | export default canvasDotsBg; 263 | -------------------------------------------------------------------------------- /src/sass/_projects.scss: -------------------------------------------------------------------------------- 1 | // entire projects section 2 | .projects { 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | align-items: center; 7 | 8 | &__heading { 9 | // &:after { 10 | // content: ''; 11 | // border-bottom: 3px solid $color-red; 12 | // width: 19rem; 13 | // display: block; 14 | // margin: 0 auto; 15 | // position: relative; 16 | // left: -3.5rem; 17 | // } 18 | 19 | &:before { 20 | position: absolute; 21 | content: ''; 22 | border-bottom: 18px solid $color-red; 23 | width: 22.5rem; 24 | display: block; 25 | margin: 0 auto; 26 | position: relative; 27 | left: 3.5rem; 28 | top: 6.3rem; 29 | 30 | z-index: -1; 31 | 32 | @media (max-width: 770px) { 33 | // width: 14rem; 34 | border-bottom: 14px solid $color-red; 35 | } 36 | } 37 | } 38 | } 39 | 40 | // single project 41 | 42 | .project { 43 | position: relative; 44 | display: flex; 45 | margin-bottom: 14rem; 46 | justify-content: flex-start; 47 | 48 | @media (max-width: 560px) { 49 | margin-bottom: 12rem; 50 | } 51 | 52 | @media (max-width: 440px) { 53 | margin-bottom: 10rem; 54 | } 55 | 56 | &__image { 57 | &-container { 58 | position: relative; 59 | height: 70rem; 60 | width: 100rem; 61 | 62 | // border: 1px solid red; 63 | background-color: $color-blue-dark; 64 | transition: all 0.2s; 65 | cursor: pointer; 66 | 67 | @media (max-width: 1100px) { 68 | height: 64rem; 69 | width: 90rem; 70 | } 71 | 72 | @media (max-width: 970px) { 73 | height: 58rem; 74 | width: 80rem; 75 | } 76 | 77 | @media (max-width: 900px) { 78 | height: 54rem; 79 | width: 75rem; 80 | } 81 | 82 | @media (max-width: 700px) { 83 | height: 48rem; 84 | width: 64rem; 85 | } 86 | 87 | @media (max-width: 560px) { 88 | height: 40rem; 89 | width: 52rem; 90 | } 91 | 92 | @media (max-width: 440px) { 93 | height: 30rem; 94 | width: 39rem; 95 | } 96 | 97 | &:hover { 98 | transform: scale(0.95); 99 | } 100 | } 101 | 102 | &-image { 103 | width: 85%; 104 | position: relative; 105 | 106 | & img { 107 | width: 100%; 108 | } 109 | } 110 | } 111 | 112 | &__info { 113 | position: relative; 114 | top: 8rem; 115 | 116 | height: fit-content; 117 | padding: 1rem; 118 | 119 | // border: 1px solid red; 120 | // flex: 1; 121 | // left: -20px; 122 | z-index: 9999999; 123 | 124 | @media (max-width: 1000px) { 125 | width: fit-content; 126 | } 127 | 128 | @media (max-width: 700px) { 129 | background-color: rgba($color-background, 0.5); 130 | } 131 | 132 | @media (max-width: 560px) { 133 | top: 4rem; 134 | } 135 | 136 | @media (max-width: 440px) { 137 | top: 2rem; 138 | } 139 | 140 | @media (max-width: 400px) { 141 | top: 0; 142 | } 143 | } 144 | 145 | &__title { 146 | position: relative; 147 | z-index: 66; 148 | font-size: 3.5rem; 149 | // font-weight: 700; 150 | 151 | @media (max-width: 900px) { 152 | font-size: 3rem; 153 | } 154 | 155 | @media (max-width: 820px) { 156 | font-size: 2.7rem; 157 | } 158 | 159 | @media (max-width: 550px) { 160 | font-size: 2.5rem; 161 | // background-color: rgba($color-background, 0.6); 162 | } 163 | 164 | @media (max-width: 400px) { 165 | font-size: 2.2rem; 166 | } 167 | } 168 | 169 | &__description { 170 | position: relative; 171 | margin-top: 3rem; 172 | font-size: 1.8rem; 173 | font-weight: 500; 174 | 175 | z-index: 999909999; 176 | 177 | @media (max-width: 560px) { 178 | margin-top: 2rem; 179 | } 180 | } 181 | 182 | // new button styling that works on higher dpi screen 183 | &__live-2 { 184 | font-size: 1.6rem; 185 | font-weight: 700; 186 | letter-spacing: 3px; 187 | line-height: 1; 188 | text-transform: uppercase; 189 | display: flex; 190 | flex-direction: column; 191 | justify-content: center; 192 | align-items: center; 193 | 194 | width: fit-content; 195 | padding: 1rem 1.2rem; 196 | 197 | position: relative; 198 | margin-top: 3rem; 199 | 200 | cursor: pointer; 201 | 202 | @media (max-width: 560px) { 203 | margin-top: 2rem; 204 | } 205 | 206 | &:after { 207 | position: absolute; 208 | content: ''; 209 | height: 2px; 210 | background-color: $color-red; 211 | 212 | width: 100%; 213 | bottom: 1px; 214 | display: block; 215 | // margin: 0 auto; 216 | 217 | transform-origin: bottom; 218 | transition: all 0.25s; 219 | 220 | // left: -8rem; 221 | 222 | z-index: -1; 223 | } 224 | 225 | &:hover { 226 | color: $color-background; 227 | } 228 | 229 | &:hover:after { 230 | height: 100%; 231 | } 232 | } 233 | 234 | &__live, 235 | &__code { 236 | position: relative; 237 | margin-top: 3rem; 238 | padding: 0.6rem 1rem; 239 | width: fit-content; 240 | 241 | font-size: 1.6rem; 242 | text-transform: uppercase; 243 | font-weight: 700; 244 | letter-spacing: 3px; 245 | // border-bottom: 2px solid $color-red; 246 | z-index: 9; 247 | 248 | transition: all 0.2s; 249 | cursor: pointer; 250 | 251 | @media (max-width: 560px) { 252 | margin-top: 2rem; 253 | } 254 | 255 | &:hover { 256 | color: $color-background; 257 | font-weight: 700; 258 | } 259 | 260 | &:after { 261 | position: absolute; 262 | content: ''; 263 | border-bottom: 2px solid $color-red; 264 | 265 | width: calc(100% + 2rem); 266 | // height: 100%; 267 | left: -10%; 268 | top: 0.5rem; 269 | display: block; 270 | margin: 0 auto; 271 | position: relative; 272 | 273 | transform-origin: bottom; 274 | transition: all 0.2s; 275 | 276 | // left: -8rem; 277 | 278 | z-index: -1; 279 | } 280 | 281 | &:hover:after { 282 | transform: scaleY(17.5); 283 | 284 | @media (max-width: 1500px) { 285 | transform: scaleY(16.5); 286 | } 287 | 288 | @media (max-width: 1200px) { 289 | transform: scaleY(14); 290 | } 291 | 292 | @media (max-width: 770px) { 293 | transform: scaleY(12.5); 294 | } 295 | } 296 | 297 | @media (max-width: 550px) { 298 | // font-size: 2.5rem; 299 | // background-color: rgba($color-background, 0.6); 300 | } 301 | } 302 | 303 | &__code { 304 | &:after { 305 | width: calc(100% + 2rem); 306 | left: -8%; 307 | // transform: translateX(3px); 308 | } 309 | } 310 | 311 | &-left { 312 | align-self: flex-start; 313 | margin-left: 22rem; 314 | 315 | @media (max-width: 1700px) { 316 | margin-left: 11rem; 317 | } 318 | 319 | @media (max-width: 1500px) { 320 | margin-left: 0; 321 | } 322 | 323 | & .project__info { 324 | left: -8rem; 325 | margin-right: -2rem; 326 | 327 | @media (max-width: 800px) { 328 | // left: -4rem; 329 | margin-right: -4rem; 330 | } 331 | 332 | @media (max-width: 770px) { 333 | // left: -4rem; 334 | margin-right: -4rem; 335 | } 336 | 337 | @media (max-width: 600px) { 338 | // left: -4rem; 339 | margin-right: -6rem; 340 | } 341 | 342 | @media (max-width: 440px) { 343 | left: -10rem; 344 | margin-right: -7rem; 345 | } 346 | } 347 | } 348 | 349 | &-right { 350 | align-self: flex-end; 351 | margin-right: 22rem; 352 | 353 | @media (max-width: 1700px) { 354 | margin-right: 11rem; 355 | } 356 | 357 | @media (max-width: 1500px) { 358 | margin-right: 0; 359 | } 360 | 361 | & .project__info { 362 | right: -8rem; 363 | margin-left: -2rem; 364 | 365 | @media (max-width: 770px) { 366 | // left: -4rem; 367 | margin-left: -4rem; 368 | } 369 | 370 | @media (max-width: 600px) { 371 | // left: -4rem; 372 | margin-left: -6rem; 373 | } 374 | 375 | @media (max-width: 440px) { 376 | right: -10rem; 377 | margin-left: -7rem; 378 | } 379 | } 380 | } 381 | } 382 | 383 | .retro { 384 | display: flex; 385 | align-items: flex-end; 386 | justify-content: center; 387 | 388 | & img { 389 | margin-bottom: -3px; 390 | } 391 | } 392 | 393 | .todo { 394 | display: flex; 395 | align-items: center; 396 | justify-content: flex-end; 397 | // z-index: 0; 398 | } 399 | 400 | .weather { 401 | display: flex; 402 | align-items: center; 403 | justify-content: flex-start; 404 | } 405 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | Ben Scott | Front End Web Developer
Hello, I'm Ben.
I'm a front end web developer.
View my work arrow-right

About

Fully committed to the philosophy of life-long learning, I’m a front end developer with a deep passion for data, programming and all things web development. Coming from a background in chemistry, I bring an analytical yet creative approach to problem solving that lends itself well to the design and creation of aesthetic and intuitive user experiences.

HTML
REACT
NPM
JAVASCRIPT
CSS
PYTHON
GIT
SASS
WEBPACK
R

Projects

Retro-Sketch
Pixel Sketch App

Create pixel art with a variety of drawing tools.

Live app
view code

// TO-DO
Productivity App

Keep track of tasks with custom project folders and notes.

live app
view code

the.weather
Weather App

Retrieve daily and hourly weather forecast data.

live app
view code

Contact

Have a question or want to work together? Leave your details and I'll get back to you as soon as possible.

Please enter your name.
Please enter a message.
-------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | Ben Scott | Full Stack Web Developer
Hello, I'm Ben.
I'm a full stack web developer.
View my work arrow-right

About

Fully committed to the philosophy of life-long learning, I’m a full stack developer with a deep passion for JavaScript, React and all things web development. The unique combination of creativity, logic, technology and never running out of new things to discover, drives my excitement and passion for web development. When I’m not at my computer I like to spend my time reading, keeping fit and playing guitar.

HTML
REACT
EXPRESS.JS
JAVASCRIPT
CSS
MONGODB
GIT
SASS
NEXT.JS
NODE.JS

Projects

lifeinvader
Social Media App

Full stack social media application built with React, Node.js, Express.js, MongoDB, Socket.io and AWS S3.

Live app
learn more

Chakra Chat
Messaging App

Instant messaging app built with Next.JS, Firebase and Chakra UI.

live app
learn more

Retro-Sketch
Pixel Sketch App

Create pixel art with a variety of drawing tools.

Live app
learn more

// TO-DO
Productivity App

Keep track of tasks with custom project folders and notes.

live app
learn more

Contact

Have a question or want to work together? Leave your details and I'll get back to you as soon as possible.

Please enter your name.
Please enter a message.
-------------------------------------------------------------------------------- /src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Ben Scott | Full Stack Web Developer 7 | 8 | 9 |
10 |
11 | 12 |
13 |
14 |
Hello, I'm Ben.
15 |
I'm a full stack web developer.
16 | 17 |
18 | View my work 19 | 20 | 28 | arrow-right 29 | 32 | 33 |
34 |
35 |
36 |
37 | 45 |
46 |
47 | 48 |
49 |
50 |
51 |

About

52 | 53 |
54 |
55 |
56 | 70 | 71 | 80 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
112 |

113 | Fully committed to the philosophy of life-long learning, I’m a full stack developer with a deep passion for JavaScript, React and all things web development. The unique combination of creativity, logic, technology and never running out of new things to discover, drives my excitement and passion for web development. When I’m not at my computer I like to spend my time reading, keeping fit and playing guitar. 114 |

115 |
116 | 117 |
118 | 123 |
124 |
125 | 126 |
HTML
127 |
128 |
129 | 130 |
REACT
131 |
132 | 133 |
134 | 135 |
EXPRESS.JS
136 |
137 |
138 |
139 |
140 | 141 |
JAVASCRIPT
142 |
143 |
144 | 145 |
CSS
146 |
147 |
148 | 149 |
MONGODB
150 |
151 | 152 |
153 | 154 |
GIT
155 |
156 |
157 |
158 |
159 | 160 |
SASS
161 |
162 |
163 | 164 |
NEXT.JS
165 |
166 | 167 |
168 | 169 |
NODE.JS
170 |
171 |
172 | 177 |
178 |
179 |
180 |
181 |

Projects

182 | 183 |
184 | 185 |
186 |
187 | 188 |
189 |
190 |
191 |
192 |

lifeinvader
Social Media App

193 |

Full stack social media application built with React, Node.js, Express.js, MongoDB, Socket.io and AWS S3.

194 |
Live app
197 |
learn more
200 |
201 |
202 | 203 |
204 |
205 |

Chakra Chat
Messaging App

206 |

Instant messaging app built with Next.JS, Firebase and Chakra UI.

207 |
live app
210 |
learn more
213 |
214 | 215 |
216 |
217 | 218 |
219 |
220 |
221 |
222 | 223 |
224 | 225 |
226 |
227 | 228 |
229 |
230 |
231 |
232 |

Retro-Sketch
Pixel Sketch App

233 |

Create pixel art with a variety of drawing tools.

234 |
Live app
237 |
learn more
240 |
241 |
242 | 243 |
244 |
245 |

// TO-DO
Productivity App

246 |

Keep track of tasks with custom project folders and notes.

247 |
live app
250 |
learn more
253 |
254 | 255 |
256 |
257 | 258 |
259 |
260 |
261 |
262 | 263 |
264 |
265 |

Contact

266 |

Have a question or want to work together? Leave your details and I'll get back to you as soon as possible.

267 | 268 |
273 | 280 | 281 | 288 | 289 | 295 | 296 |
297 |
298 |
Please enter your name.
299 | 300 |
Please enter a message.
301 |
302 | 303 |
304 |
305 | 306 |
307 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /main.a0ef648aaae13a2d3ab7.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap); 2 | @import url(https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap); 3 | *,*::before,*::after{margin:0;padding:0;box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%;scroll-behavior:smooth}@media (max-width: 1500px){html{font-size:57.25%}}@media (max-width: 1200px){html{font-size:50%}}@media (max-width: 770px){html{font-size:43.75%}}@media (max-width: 615px){html{font-size:40%}}@media (max-width: 350px){html{font-size:35%}}body{min-height:100vh;color:#fafafa;font-family:montserrat, sans-serif;background-color:#1a1a1a}li{list-style:none}a{text-decoration:none;color:inherit}button{border:none;outline:none;background-color:transparent;color:inherit}.about{width:1300px;margin-left:auto;margin-right:auto;display:flex;flex-direction:column;align-items:center}@media (max-width: 1500px){.about{width:1100px}}@media (max-width: 1200px){.about{width:auto}}.about__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:16rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.about__heading:before{border-bottom:14px solid #ff4d5a}}.about__content{display:flex;justify-content:space-between;width:100%}@media (max-width: 1300px){.about__content{flex-direction:column}}.profile{position:relative;display:flex;flex-direction:column;align-items:center;font-weight:500;left:-300px;opacity:0;transition:all 1.1s}@media (max-width: 1301px){.profile{margin-bottom:10rem;left:0;opacity:1}}@media (max-width: 1000px){.profile{margin-bottom:7rem}}.profile__picture{height:24rem;margin-bottom:4rem;display:flex;justify-content:flex-start;align-items:center}.profile__picture svg{transition:all 1.1s}.profile__blurb{font-size:1.8rem;width:500px;line-height:1.8}@media (max-width: 600px){.profile__blurb{width:80vw;margin-left:auto;margin-right:auto}}.profile__fade-in{opacity:1;transform:translateX(300px)}@media (max-width: 1300px){.profile__fade-in{transform:translateX(0)}}.skills{display:flex;justify-content:center}.skills__row{display:flex;flex-direction:column;justify-content:center}.skills__row:not(:last-child){margin-right:25px}@media (max-width: 410px){.skills__row:not(:last-child){margin-right:15px}}@media (max-width: 300px){.skills__row:not(:last-child){margin-right:10px}}.skills__item{opacity:0;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:space-evenly;height:100px;width:160px;border:double 3px transparent;border-image-slice:1;border-width:3px;background-image:linear-gradient(#1a1a1a, #1a1a1a),radial-gradient(circle at top left, #51a2e9, #ff4d5a);border-radius:10px;background-origin:border-box;background-clip:content-box, border-box;transition:transform 0.2s, opacity 1.2s;overflow:hidden}@media (max-width: 1500px){.skills__item{height:90px;width:145px}}@media (max-width: 1300px){.skills__item{opacity:1;border-width:2px}}@media (max-width: 1000px){.skills__item{height:80px;width:130px}}@media (max-width: 600px){.skills__item{height:70px;width:115px}}@media (max-width: 500px){.skills__item{height:60px;width:100px}}@media (max-width: 410px){.skills__item{height:50px;width:80px}}@media (max-width: 340px){.skills__item{height:45px;width:70px}}.skills__item:not(:last-child){margin-bottom:3rem}@media (max-width: 410px){.skills__item:not(:last-child){margin-bottom:15px}}.skills__item img{height:60px;width:auto;transition:all 0.2s}@media (max-width: 1500px){.skills__item img{height:55px}}@media (max-width: 1000px){.skills__item img{height:50px}}@media (max-width: 600px){.skills__item img{height:45px}}@media (max-width: 500px){.skills__item img{height:35px}}@media (max-width: 410px){.skills__item img{height:26px}}.skills__item-name{font-size:1.2rem;font-weight:600;line-height:1;transition:all 0.2s;letter-spacing:1px}@media (max-width: 1200px){.skills__item-name{font-size:1.4rem}}.skills__item-fade-in{opacity:1}.skills__item--js img{border-radius:5px}@keyframes moveInLeft{0%{opacity:0;transform:translateX(-10rem)}100%{opacity:1;transform:translateX(0)}}@keyframes moveInRight{0%{opacity:0;transform:translateX(10rem)}100%{opacity:1;transform:translateX(0)}}@keyframes moveInBottom{0%{opacity:0;transform:translateY(4rem)}100%{opacity:1;transform:translateY(0)}}@keyframes bounce{0%{transform:translateY(0)}50%{transform:translateY(-1rem)}100%{transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.contact{position:relative;margin-left:auto;margin-right:auto;display:flex;width:500px;flex-direction:column;align-items:center;justify-content:center;z-index:10;margin-bottom:10rem}@media (max-width: 700px){.contact{width:400px}}@media (max-width: 470px){.contact{width:330px}}@media (max-width: 400px){.contact{width:260px}}.contact__heading{margin-top:-4rem !important;margin-bottom:6rem !important}.contact__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:21rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.contact__heading:before{border-bottom:14px solid #ff4d5a}}.contact__text{font-size:1.8rem;margin-bottom:6rem}.contact__form{display:flex;flex-direction:column;align-items:center;justify-content:center}.contact__form-name,.contact__form-email{margin-bottom:6px;padding:1rem;height:4rem}.contact__form-message{height:12rem;padding:1rem}.contact__form-submit{align-self:flex-start;position:relative;padding:0.6rem 1rem;width:fit-content;font-size:1.6rem;text-transform:uppercase;font-weight:700;letter-spacing:3px;z-index:9;cursor:pointer}.contact__form-submit:hover{color:#1a1a1a;font-weight:700}.contact__form-submit:after{position:absolute;content:'';border-bottom:2px solid #ff4d5a;width:calc(100% + 2rem);left:-14%;top:0.5rem;display:block;margin:0 auto;position:relative;transform-origin:bottom;transition:all 0.2s;z-index:-1}.contact__form-submit:hover:after{transform:scaleY(17.5)}@media (max-width: 1500px){.contact__form-submit:hover:after{transform:scaleY(16.5)}}@media (max-width: 1200px){.contact__form-submit:hover:after{transform:scaleY(14)}}@media (max-width: 770px){.contact__form-submit:hover:after{transform:scaleY(12.5)}}.contact input,.contact textarea{width:500px;resize:none;border:none;color:inherit;background-color:#282828;font-size:1.6rem;font-family:monserrat, sans-serif;border-left:2px solid transparent}@media (max-width: 700px){.contact input,.contact textarea{width:400px}}@media (max-width: 470px){.contact input,.contact textarea{width:330px}}@media (max-width: 400px){.contact input,.contact textarea{width:260px}}.contact input:focus,.contact textarea:focus{outline:none}.contact input::placeholder,.contact textarea::placeholder{color:rgba(250,250,250,0.6);opacity:1}.contact input :-ms-input-placeholder,.contact textarea :-ms-input-placeholder{color:rgba(250,250,250,0.6)}.contact input ::-ms-input-placeholder,.contact textarea ::-ms-input-placeholder{color:rgba(250,250,250,0.6)}.contact__form-error-submit{margin-top:1.5rem;height:7rem;width:100%;display:flex;justify-content:space-between;align-items:center}.form-error{align-self:start;font-size:1.6rem;font-weight:500;line-height:1.5}.form-error>*{display:none}.input-error{border-left:2px solid #ff4d5a !important}.footer{position:relative;display:flex;flex-direction:column;justify-content:center;align-items:center;height:160px;background-color:#282828}.socials{display:flex;margin-bottom:20px}.socials__github,.socials__email{display:flex;justify-content:center;align-items:center;height:35px;background-color:transparent;cursor:pointer;transition:all 0.2s}.socials__github:hover,.socials__email:hover{transform:scale(1.2)}.socials__github{margin-right:1rem}.socials__email{margin-left:1rem}.socials img{height:100%}.copyright{color:#fafafa;font-size:10px;font-weight:500}.return-home{position:absolute;top:-25px;width:40px;height:45px;margin-right:auto;margin-left:auto;left:0;right:0;text-align:center;background-color:#ff4d5a;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite}.return-home:hover{cursor:pointer;animation-name:bounce;-moz-animation-name:bounce}.return-home svg{width:100%}.hero{position:relative;display:flex;height:100vh;width:100%;z-index:999}.canvas{position:absolute;top:0;right:0;left:0;bottom:0;width:100%;height:100vh;background-color:#1a1a1a;overflow:hidden}.connecting-dots{height:100%;width:100%}.heading{position:relative;align-self:center;justify-self:center;display:flex;flex-direction:column;align-items:center;line-height:normal;width:fit-content;height:auto;margin-left:auto;margin-right:auto;color:#fafafa;font-weight:300;z-index:999}.heading__line-1{animation-name:moveInLeft}.heading__line-1 span{color:#ff4d5a;font-weight:400}.heading__line-2{animation-name:moveInRight}.heading__line-1,.heading__line-2{font-size:6rem;background-color:rgba(26,26,26,0.25);animation-duration:1.4s;animation-timing-function:cubic-bezier(0.21, 1.11, 0.81, 0.99)}@media (max-width: 700px){.heading__line-1,.heading__line-2{font-size:5rem;text-align:center;margin-left:4rem;margin-right:4rem}}@media (max-width: 550px){.heading__line-1,.heading__line-2{font-size:5rem}}.heading-cta{position:relative;display:flex;align-items:center;margin-top:2.4rem;padding:0.8rem 3rem;width:27.5rem;height:4.8rem;background-color:rgba(26,26,26,0.6);border:2px solid #ff4d5a;border-radius:2px;color:#ff4d5a;font-size:2.4rem;font-weight:500;cursor:pointer;animation:moveInBottom 0.7s 1.2s;animation-fill-mode:backwards;animation-timing-function:cubic-bezier(0.21, 1.11, 0.81, 0.99)}@media (max-width: 1500px){.heading-cta{width:auto}}@media (max-width: 700px){.heading-cta{margin-top:1.8rem}}@media (max-width: 550px){.heading-cta{padding:0.8rem 2rem}}.heading-cta:before,.heading-cta:after{content:'';position:absolute;top:-2px;left:-2px;width:27.5rem;height:4.8rem;border-radius:3px;border:2px solid #ff4d5a;filter:blur(0);transform-origin:50%;z-index:-1}@media (max-width: 1500px){.heading-cta:before,.heading-cta:after{width:27.8rem}}@media (max-width: 1200px){.heading-cta:before,.heading-cta:after{width:28.5rem;border:2px solid transparent}}.heading-cta:hover{transform:translateY(-2px)}.heading-cta:hover:before,.heading-cta:hover:after{border-color:transparent;filter:blur(2px);transform:scaleX(1.3) scaleY(2.2);transition:800ms transform ease, 1900ms blur ease, 700ms border-color ease;pointer-events:none}.heading-cta:hover:after{transition-delay:150ms}.heading-cta:active{transform:translateY(-1px)}.heading__arrow{display:inline-block;height:24px;width:24px;margin-left:15px;transform:rotate(90deg);fill:#ff4d5a;transition:all 0.3s}@media (max-width: 770px){.heading__arrow{height:20px;width:20px}}@media (max-width: 615px){.heading__arrow{margin-left:10px}}@media (max-width: 550px){.heading__arrow{height:16px;width:16px}}.main-bg{height:100vh;position:fixed;top:0;width:100%;background-color:royalblue}.navigation{display:flex;margin-right:10rem;font-size:2rem;font-weight:500;letter-spacing:1px}@media (max-width: 1200px){.navigation{margin-right:3rem}}@media (max-width: 700px){.navigation{margin-right:0}}.navigation-bar{position:sticky;position:-webkit-sticky;top:0;display:flex;justify-content:flex-end;align-items:center;height:6rem;border-bottom:1px solid #1a1a1a;background-color:#282828;box-shadow:0 7px 7px rgba(0,0,0,0.4);z-index:99999999999}@media (max-width: 700px){.navigation-bar{justify-content:center}}.navigation__item{transition:all 0.2s}.navigation__item:not(:last-child){margin-right:3rem}.navigation__item--active{color:#ff4d5a}.navigation__item:hover{color:#ff4d5a}.projects{display:flex;flex-direction:column;justify-content:center;align-items:center}.projects__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:22.5rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.projects__heading:before{border-bottom:14px solid #ff4d5a}}.project{position:relative;display:flex;margin-bottom:14rem;justify-content:flex-start}@media (max-width: 560px){.project{margin-bottom:12rem}}@media (max-width: 440px){.project{margin-bottom:10rem}}.project__image-container{position:relative;height:70rem;width:100rem;background-color:#3216bb;transition:all 0.2s;cursor:pointer}@media (max-width: 1100px){.project__image-container{height:64rem;width:90rem}}@media (max-width: 970px){.project__image-container{height:58rem;width:80rem}}@media (max-width: 900px){.project__image-container{height:54rem;width:75rem}}@media (max-width: 700px){.project__image-container{height:48rem;width:64rem}}@media (max-width: 560px){.project__image-container{height:40rem;width:52rem}}@media (max-width: 440px){.project__image-container{height:30rem;width:39rem}}.project__image-container:hover{transform:scale(0.95)}.project__image-image{width:85%;position:relative}.project__image-image img{width:100%}.project__info{position:relative;top:8rem;height:fit-content;padding:1rem;z-index:9999999}@media (max-width: 1000px){.project__info{width:fit-content}}@media (max-width: 700px){.project__info{background-color:rgba(26,26,26,0.5)}}@media (max-width: 560px){.project__info{top:4rem}}@media (max-width: 440px){.project__info{top:2rem}}@media (max-width: 400px){.project__info{top:0}}.project__title{position:relative;z-index:66;font-size:3.5rem}@media (max-width: 900px){.project__title{font-size:3rem}}@media (max-width: 820px){.project__title{font-size:2.7rem}}@media (max-width: 550px){.project__title{font-size:2.5rem}}@media (max-width: 400px){.project__title{font-size:2.2rem}}.project__description{position:relative;margin-top:3rem;font-size:1.8rem;font-weight:500;z-index:999909999}@media (max-width: 560px){.project__description{margin-top:2rem}}.project__live,.project__code{position:relative;margin-top:3rem;padding:0.6rem 1rem;width:fit-content;font-size:1.6rem;text-transform:uppercase;font-weight:700;letter-spacing:3px;z-index:9;transition:all 0.2s;cursor:pointer}@media (max-width: 560px){.project__live,.project__code{margin-top:2rem}}.project__live:hover,.project__code:hover{color:#1a1a1a;font-weight:700}.project__live:after,.project__code:after{position:absolute;content:'';border-bottom:2px solid #ff4d5a;width:calc(100% + 2rem);left:-10%;top:0.5rem;display:block;margin:0 auto;position:relative;transform-origin:bottom;transition:all 0.2s;z-index:-1}.project__live:hover:after,.project__code:hover:after{transform:scaleY(17.5)}@media (max-width: 1500px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(16.5)}}@media (max-width: 1200px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(14)}}@media (max-width: 770px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(12.5)}}.project__code:after{width:calc(100% + 2rem);left:-8%}.project-left{align-self:flex-start;margin-left:22rem}@media (max-width: 1700px){.project-left{margin-left:11rem}}@media (max-width: 1500px){.project-left{margin-left:0}}.project-left .project__info{left:-8rem;margin-right:-2rem}@media (max-width: 800px){.project-left .project__info{margin-right:-4rem}}@media (max-width: 770px){.project-left .project__info{margin-right:-4rem}}@media (max-width: 600px){.project-left .project__info{margin-right:-6rem}}@media (max-width: 440px){.project-left .project__info{left:-10rem;margin-right:-7rem}}.project-right{align-self:flex-end;margin-right:22rem}@media (max-width: 1700px){.project-right{margin-right:11rem}}@media (max-width: 1500px){.project-right{margin-right:0}}.project-right .project__info{right:-8rem;margin-left:-2rem}@media (max-width: 770px){.project-right .project__info{margin-left:-4rem}}@media (max-width: 600px){.project-right .project__info{margin-left:-6rem}}@media (max-width: 440px){.project-right .project__info{right:-10rem;margin-left:-7rem}}.retro{display:flex;align-items:flex-end;justify-content:center}.retro img{margin-bottom:-3px}.todo{display:flex;align-items:center;justify-content:flex-end}.weather{display:flex;align-items:center;justify-content:flex-start}.section-heading{position:relative;font-size:5.5rem;font-weight:700;margin-top:9rem;margin-bottom:13rem;z-index:9999}@media (max-width: 1200px){.section-heading{margin-bottom:10rem}}@media (max-width: 1000px){.section-heading{margin-top:6rem}} 4 | 5 | -------------------------------------------------------------------------------- /dist/main.40f27e161ba829c32fbb.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&display=swap); 2 | @import url(https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap); 3 | *,*::before,*::after{margin:0;padding:0;box-sizing:inherit}html{box-sizing:border-box;font-size:62.5%;scroll-behavior:smooth}@media (max-width: 1500px){html{font-size:57.25%}}@media (max-width: 1200px){html{font-size:50%}}@media (max-width: 770px){html{font-size:43.75%}}@media (max-width: 615px){html{font-size:40%}}@media (max-width: 350px){html{font-size:35%}}body{min-height:100vh;color:#fafafa;font-family:montserrat, sans-serif;background-color:#1a1a1a;overflow-x:hidden}li{list-style:none}a{text-decoration:none;color:inherit}button{border:none;outline:none;background-color:transparent;color:inherit}.about{width:1300px;margin-left:auto;margin-right:auto;display:flex;flex-direction:column;align-items:center}@media (max-width: 1500px){.about{width:1100px}}@media (max-width: 1200px){.about{width:auto}}.about__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:16rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.about__heading:before{border-bottom:14px solid #ff4d5a}}.about__content{display:flex;justify-content:space-between;width:100%}@media (max-width: 1300px){.about__content{flex-direction:column}}.profile{position:relative;display:flex;flex-direction:column;align-items:center;font-weight:500;left:-300px;opacity:0;transition:all 1.1s}@media (max-width: 1301px){.profile{margin-bottom:10rem;left:0;opacity:1}}@media (max-width: 1000px){.profile{margin-bottom:7rem}}.profile__picture{height:24rem;margin-bottom:4rem;display:flex;justify-content:flex-start;align-items:center}.profile__picture svg{transition:all 1.1s}.profile__blurb{font-size:1.8rem;width:500px;line-height:1.8}@media (max-width: 600px){.profile__blurb{width:80vw;margin-left:auto;margin-right:auto}}.profile__fade-in{opacity:1;transform:translateX(300px)}@media (max-width: 1300px){.profile__fade-in{transform:translateX(0)}}.skills{display:flex;justify-content:center}.skills__row{display:flex;flex-direction:column;justify-content:center}.skills__row:not(:last-child){margin-right:25px}@media (max-width: 410px){.skills__row:not(:last-child){margin-right:15px}}@media (max-width: 300px){.skills__row:not(:last-child){margin-right:10px}}.skills__item{opacity:0;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:space-evenly;height:100px;width:160px;border:double 3px transparent;border-image-slice:1;border-width:3px;background-image:linear-gradient(#1a1a1a, #1a1a1a),radial-gradient(circle at top left, #51a2e9, #ff4d5a);border-radius:10px;background-origin:border-box;background-clip:content-box, border-box;transition:transform 0.2s, opacity 1.2s;overflow:hidden}@media (max-width: 1500px){.skills__item{height:90px;width:145px}}@media (max-width: 1300px){.skills__item{opacity:1;border-width:2px}}@media (max-width: 1000px){.skills__item{height:80px;width:130px}}@media (max-width: 600px){.skills__item{height:70px;width:115px}}@media (max-width: 500px){.skills__item{height:60px;width:100px}}@media (max-width: 410px){.skills__item{height:50px;width:80px}}@media (max-width: 340px){.skills__item{height:45px;width:70px}}.skills__item:not(:last-child){margin-bottom:3rem}@media (max-width: 410px){.skills__item:not(:last-child){margin-bottom:15px}}.skills__item img{height:60px;width:auto;transition:all 0.2s}@media (max-width: 1500px){.skills__item img{height:55px}}@media (max-width: 1000px){.skills__item img{height:50px}}@media (max-width: 600px){.skills__item img{height:45px}}@media (max-width: 500px){.skills__item img{height:35px}}@media (max-width: 410px){.skills__item img{height:26px}}.skills__item-name{font-size:1.2rem;font-weight:600;line-height:1;transition:all 0.2s;letter-spacing:1px}@media (max-width: 1200px){.skills__item-name{font-size:1.4rem}}.skills__item-fade-in{opacity:1}.skills__item--js img{border-radius:5px}.skills__item--webpack img{border-radius:50%}@keyframes moveInLeft{0%{opacity:0;transform:translateX(-10rem)}100%{opacity:1;transform:translateX(0)}}@keyframes moveInRight{0%{opacity:0;transform:translateX(10rem)}100%{opacity:1;transform:translateX(0)}}@keyframes moveInBottom{0%{opacity:0;transform:translateY(4rem)}100%{opacity:1;transform:translateY(0)}}@keyframes bounce{0%{transform:translateY(0)}50%{transform:translateY(-1rem)}100%{transform:translateY(0)}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.contact{position:relative;margin-left:auto;margin-right:auto;display:flex;width:500px;flex-direction:column;align-items:center;justify-content:center;z-index:10;margin-bottom:10rem}@media (max-width: 700px){.contact{width:400px}}@media (max-width: 470px){.contact{width:330px}}@media (max-width: 400px){.contact{width:260px}}.contact__heading{margin-top:-4rem !important;margin-bottom:6rem !important}.contact__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:21rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.contact__heading:before{border-bottom:14px solid #ff4d5a}}.contact__text{font-size:1.8rem;margin-bottom:6rem}.contact__form{display:flex;flex-direction:column;align-items:center;justify-content:center}.contact__form-name,.contact__form-email{margin-bottom:6px;padding:1rem;height:4rem}.contact__form-message{height:12rem;padding:1rem}.contact__form-submit-2{align-self:flex-start;margin-top:0 !important}.contact__form-submit{align-self:flex-start;position:relative;padding:0.6rem 1rem;width:fit-content;font-size:1.6rem;text-transform:uppercase;font-weight:700;letter-spacing:3px;z-index:9;cursor:pointer}.contact__form-submit:hover{color:#1a1a1a;font-weight:700}.contact__form-submit:after{position:absolute;content:'';border-bottom:2px solid #ff4d5a;width:calc(100% + 2rem);left:-14%;top:0.5rem;display:block;margin:0 auto;position:relative;transform-origin:bottom;transition:all 0.2s;z-index:-1}.contact__form-submit:hover:after{transform:scaleY(17.5)}@media (max-width: 1500px){.contact__form-submit:hover:after{transform:scaleY(16.5)}}@media (max-width: 1200px){.contact__form-submit:hover:after{transform:scaleY(14)}}@media (max-width: 770px){.contact__form-submit:hover:after{transform:scaleY(12.5)}}.contact input,.contact textarea{width:500px;resize:none;border:none;color:inherit;background-color:#282828;font-size:1.6rem;font-family:monserrat, sans-serif;border-left:2px solid transparent;border-radius:0}@media (max-width: 700px){.contact input,.contact textarea{width:400px}}@media (max-width: 470px){.contact input,.contact textarea{width:330px}}@media (max-width: 400px){.contact input,.contact textarea{width:260px}}.contact input:focus,.contact textarea:focus{outline:none}.contact input::placeholder,.contact textarea::placeholder{color:rgba(250,250,250,0.6);opacity:1}.contact input :-ms-input-placeholder,.contact textarea :-ms-input-placeholder{color:rgba(250,250,250,0.6)}.contact input ::-ms-input-placeholder,.contact textarea ::-ms-input-placeholder{color:rgba(250,250,250,0.6)}.contact__form-error-submit{margin-top:1.5rem;height:7rem;width:100%;display:flex;justify-content:space-between;align-items:center}.form-error{align-self:start;font-size:1.6rem;font-weight:500;line-height:1.5}.form-error>*{display:none}.input-error{border-left:2px solid #ff4d5a !important}.footer{position:relative;display:flex;flex-direction:column;justify-content:center;align-items:center;height:160px;background-color:#282828}.socials{display:flex;margin-bottom:20px}.socials__github,.socials__email{display:flex;justify-content:center;align-items:center;height:35px;background-color:transparent;cursor:pointer;transition:all 0.2s}.socials__github:hover,.socials__email:hover{transform:scale(1.2)}.socials__github{margin-right:1rem}.socials__email{margin-left:1rem}.socials img{height:100%}.copyright{color:#fafafa;font-size:10px;font-weight:500}.return-home{position:absolute;top:-25px;width:40px;height:45px;margin-right:auto;margin-left:auto;left:0;right:0;text-align:center;background-color:#ff4d5a;-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;animation-iteration-count:infinite;-webkit-animation-iteration-count:infinite}.return-home:hover{cursor:pointer;animation-name:bounce;-moz-animation-name:bounce}.return-home svg{width:100%}.hero{position:relative;display:flex;height:100vh;width:100%;z-index:999}.canvas{position:absolute;top:0;right:0;left:0;bottom:0;width:100%;height:100vh;background-color:#1a1a1a;overflow:hidden}.connecting-dots{height:100%;width:100%}.heading{position:relative;align-self:center;justify-self:center;display:flex;flex-direction:column;align-items:center;line-height:normal;width:fit-content;height:auto;margin-left:auto;margin-right:auto;color:#fafafa;font-weight:300;z-index:999}.heading__line-1{animation-name:moveInLeft}.heading__line-1 span{color:#ff4d5a;font-weight:400}.heading__line-2{animation-name:moveInRight}.heading__line-1,.heading__line-2{font-size:6rem;background-color:rgba(26,26,26,0.25);animation-duration:1.4s;animation-timing-function:cubic-bezier(0.21, 1.11, 0.81, 0.99)}@media (max-width: 700px){.heading__line-1,.heading__line-2{font-size:5rem;text-align:center;margin-left:4rem;margin-right:4rem}}@media (max-width: 550px){.heading__line-1,.heading__line-2{font-size:5rem}}.heading-cta{position:relative;display:flex;align-items:center;margin-top:2.4rem;padding:0.8rem 3rem;width:27.5rem;height:4.8rem;background-color:rgba(26,26,26,0.6);border:2px solid #ff4d5a;border-radius:2px;color:#ff4d5a;font-size:2.4rem;font-weight:500;cursor:pointer;animation:moveInBottom 0.7s 1.2s;animation-fill-mode:backwards;animation-timing-function:cubic-bezier(0.21, 1.11, 0.81, 0.99)}@media (max-width: 1500px){.heading-cta{width:auto}}@media (max-width: 700px){.heading-cta{margin-top:1.8rem}}@media (max-width: 550px){.heading-cta{padding:0.8rem 2rem}}.heading-cta:before,.heading-cta:after{content:'';position:absolute;top:-2px;left:-2px;width:27.5rem;height:4.8rem;border-radius:3px;border:2px solid #ff4d5a;filter:blur(0);transform-origin:50%;z-index:-1}@media (max-width: 1500px){.heading-cta:before,.heading-cta:after{width:27.8rem}}@media (max-width: 1200px){.heading-cta:before,.heading-cta:after{width:28.5rem;border:2px solid transparent}}.heading-cta:hover{transform:translateY(-2px)}.heading-cta:hover:before,.heading-cta:hover:after{border-color:transparent;filter:blur(2px);transform:scaleX(1.3) scaleY(2.2);transition:800ms transform ease, 1900ms blur ease, 700ms border-color ease;pointer-events:none}.heading-cta:hover:after{transition-delay:150ms}.heading-cta:active{transform:translateY(-1px)}.heading__arrow{display:inline-block;height:24px;width:24px;margin-left:15px;transform:rotate(90deg);fill:#ff4d5a;transition:all 0.3s}@media (max-width: 770px){.heading__arrow{height:20px;width:20px}}@media (max-width: 615px){.heading__arrow{margin-left:10px}}@media (max-width: 550px){.heading__arrow{height:16px;width:16px}}.main-bg{height:100vh;position:fixed;top:0;width:100%;background-color:royalblue}.navigation{display:flex;margin-right:10rem;font-size:2rem;font-weight:500;letter-spacing:1px}@media (max-width: 1200px){.navigation{margin-right:3rem}}@media (max-width: 700px){.navigation{margin-right:0}}.navigation-bar{position:sticky;position:-webkit-sticky;top:0;display:flex;justify-content:flex-end;align-items:center;height:6rem;border-bottom:1px solid #1a1a1a;background-color:rgba(40,40,40,0.95);backdrop-filter:blur(8px);box-shadow:0 4px 4px rgba(0,0,0,0.3);z-index:99999999999}@media (max-width: 700px){.navigation-bar{justify-content:center}}.navigation__item{transition:all 0.2s}.navigation__item:not(:last-child){margin-right:3rem}.navigation__item--active{color:#ff4d5a}.navigation__item:hover{color:#ff4d5a}.projects{display:flex;flex-direction:column;justify-content:center;align-items:center}.projects__heading:before{position:absolute;content:'';border-bottom:18px solid #ff4d5a;width:22.5rem;display:block;margin:0 auto;position:relative;left:3.5rem;top:6.3rem;z-index:-1}@media (max-width: 770px){.projects__heading:before{border-bottom:14px solid #ff4d5a}}.project{position:relative;display:flex;margin-bottom:14rem;justify-content:flex-start}@media (max-width: 560px){.project{margin-bottom:12rem}}@media (max-width: 440px){.project{margin-bottom:10rem}}.project__image-container{position:relative;height:70rem;width:100rem;background-color:#3216bb;transition:all 0.2s;cursor:pointer}@media (max-width: 1100px){.project__image-container{height:64rem;width:90rem}}@media (max-width: 970px){.project__image-container{height:58rem;width:80rem}}@media (max-width: 900px){.project__image-container{height:54rem;width:75rem}}@media (max-width: 700px){.project__image-container{height:48rem;width:64rem}}@media (max-width: 560px){.project__image-container{height:40rem;width:52rem}}@media (max-width: 440px){.project__image-container{height:30rem;width:39rem}}.project__image-container:hover{transform:scale(0.95)}.project__image-image{width:85%;position:relative}.project__image-image img{width:100%}.project__info{position:relative;top:8rem;height:fit-content;padding:1rem;z-index:9999999}@media (max-width: 1000px){.project__info{width:fit-content}}@media (max-width: 700px){.project__info{background-color:rgba(26,26,26,0.5)}}@media (max-width: 560px){.project__info{top:4rem}}@media (max-width: 440px){.project__info{top:2rem}}@media (max-width: 400px){.project__info{top:0}}.project__title{position:relative;z-index:66;font-size:3.5rem}@media (max-width: 900px){.project__title{font-size:3rem}}@media (max-width: 820px){.project__title{font-size:2.7rem}}@media (max-width: 550px){.project__title{font-size:2.5rem}}@media (max-width: 400px){.project__title{font-size:2.2rem}}.project__description{position:relative;margin-top:3rem;font-size:1.8rem;font-weight:500;z-index:999909999}@media (max-width: 560px){.project__description{margin-top:2rem}}.project__live-2{font-size:1.6rem;font-weight:700;letter-spacing:3px;line-height:1;text-transform:uppercase;display:flex;flex-direction:column;justify-content:center;align-items:center;width:fit-content;padding:1rem 1.2rem;position:relative;margin-top:3rem;cursor:pointer}@media (max-width: 560px){.project__live-2{margin-top:2rem}}.project__live-2:after{position:absolute;content:'';height:2px;background-color:#ff4d5a;width:100%;bottom:1px;display:block;transform-origin:bottom;transition:all 0.25s;z-index:-1}.project__live-2:hover{color:#1a1a1a}.project__live-2:hover:after{height:100%}.project__live,.project__code{position:relative;margin-top:3rem;padding:0.6rem 1rem;width:fit-content;font-size:1.6rem;text-transform:uppercase;font-weight:700;letter-spacing:3px;z-index:9;transition:all 0.2s;cursor:pointer}@media (max-width: 560px){.project__live,.project__code{margin-top:2rem}}.project__live:hover,.project__code:hover{color:#1a1a1a;font-weight:700}.project__live:after,.project__code:after{position:absolute;content:'';border-bottom:2px solid #ff4d5a;width:calc(100% + 2rem);left:-10%;top:0.5rem;display:block;margin:0 auto;position:relative;transform-origin:bottom;transition:all 0.2s;z-index:-1}.project__live:hover:after,.project__code:hover:after{transform:scaleY(17.5)}@media (max-width: 1500px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(16.5)}}@media (max-width: 1200px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(14)}}@media (max-width: 770px){.project__live:hover:after,.project__code:hover:after{transform:scaleY(12.5)}}.project__code:after{width:calc(100% + 2rem);left:-8%}.project-left{align-self:flex-start;margin-left:22rem}@media (max-width: 1700px){.project-left{margin-left:11rem}}@media (max-width: 1500px){.project-left{margin-left:0}}.project-left .project__info{left:-8rem;margin-right:-2rem}@media (max-width: 800px){.project-left .project__info{margin-right:-4rem}}@media (max-width: 770px){.project-left .project__info{margin-right:-4rem}}@media (max-width: 600px){.project-left .project__info{margin-right:-6rem}}@media (max-width: 440px){.project-left .project__info{left:-10rem;margin-right:-7rem}}.project-right{align-self:flex-end;margin-right:22rem}@media (max-width: 1700px){.project-right{margin-right:11rem}}@media (max-width: 1500px){.project-right{margin-right:0}}.project-right .project__info{right:-8rem;margin-left:-2rem}@media (max-width: 770px){.project-right .project__info{margin-left:-4rem}}@media (max-width: 600px){.project-right .project__info{margin-left:-6rem}}@media (max-width: 440px){.project-right .project__info{right:-10rem;margin-left:-7rem}}.retro{display:flex;align-items:flex-end;justify-content:center}.retro img{margin-bottom:-3px}.todo{display:flex;align-items:center;justify-content:flex-end}.weather{display:flex;align-items:center;justify-content:flex-start}.section-heading{position:relative;font-size:5.5rem;font-weight:700;margin-top:9rem;margin-bottom:13rem;z-index:9999}@media (max-width: 1200px){.section-heading{margin-bottom:10rem}}@media (max-width: 1000px){.section-heading{margin-top:6rem}} 4 | 5 | --------------------------------------------------------------------------------