index, css, js: convert to LF line endings

Signed-off-by: Naman Sood <mail@nsood.in>
This commit is contained in:
Naman Sood 2024-02-23 23:09:57 -05:00
parent 04b11c541a
commit c712cb5d8b
3 changed files with 725 additions and 725 deletions

View file

@ -1,457 +1,457 @@
*, *:before, *:after { *, *:before, *:after {
box-sizing: border-box; box-sizing: border-box;
} }
html { html {
overflow-x: hidden; overflow-x: hidden;
scroll-behavior: smooth; scroll-behavior: smooth;
} }
body { body {
margin: 0; margin: 0;
font-family: 'Nunito', sans-serif; font-family: 'Nunito', sans-serif;
background: var(--bgColor); background: var(--bgColor);
@media(prefers-color-scheme: light) { @media(prefers-color-scheme: light) {
--bgColor: white; --bgColor: white;
--textColor: #777; --textColor: #777;
--iconColor: black; --iconColor: black;
--boldColor: black; --boldColor: black;
} }
@media(prefers-color-scheme: dark) { @media(prefers-color-scheme: dark) {
--bgColor: black; --bgColor: black;
--iconColor: white; --iconColor: white;
--textColor: #aaa; --textColor: #aaa;
--boldColor: white; --boldColor: white;
} }
--liteColor: white; --liteColor: white;
--liteText: #777; --liteText: #777;
&.lite-mode { &.lite-mode {
--bgColor: white; --bgColor: white;
--textColor: #777; --textColor: #777;
--iconColor: black; --iconColor: black;
--boldColor: black; --boldColor: black;
} }
--darkColor: black; --darkColor: black;
--darkText: #aaa; --darkText: #aaa;
&.dark-mode { &.dark-mode {
--bgColor: black; --bgColor: black;
--iconColor: white; --iconColor: white;
--textColor: #aaa; --textColor: #aaa;
--boldColor: white; --boldColor: white;
} }
--mintColor: #c7fcee; --mintColor: #c7fcee;
--mintText: #5f8c80; --mintText: #5f8c80;
&.mint-mode { &.mint-mode {
--bgColor: #c7fcee; --bgColor: #c7fcee;
--iconColor: #486b61; --iconColor: #486b61;
--textColor: #5f8c80; --textColor: #5f8c80;
--boldColor: #10352b; --boldColor: #10352b;
} }
--purpColor: #cfc7fc; --purpColor: #cfc7fc;
--purpText: #7166af; --purpText: #7166af;
&.purp-mode { &.purp-mode {
--bgColor: #cfc7fc; --bgColor: #cfc7fc;
--iconColor: #5a518c; --iconColor: #5a518c;
--textColor: #7166af; --textColor: #7166af;
--boldColor: #312c4c; --boldColor: #312c4c;
} }
--yellColor: #fcfcbf; --yellColor: #fcfcbf;
--yellText: #8c8c5f; --yellText: #8c8c5f;
&.yell-mode { &.yell-mode {
--bgColor: #fcfcbf; --bgColor: #fcfcbf;
--iconColor: #54543f; --iconColor: #54543f;
--textColor: #8c8c5f; --textColor: #8c8c5f;
--boldColor: #353528; --boldColor: #353528;
} }
--blueColor: #ade3ff; --blueColor: #ade3ff;
--blueText: #46748c; --blueText: #46748c;
&.blue-mode { &.blue-mode {
--bgColor: #ade3ff; --bgColor: #ade3ff;
--iconColor: #394b54; --iconColor: #394b54;
--textColor: #46748c; --textColor: #46748c;
--boldColor: #242f35; --boldColor: #242f35;
} }
} }
.main { .main {
min-height: 100vh; min-height: 100vh;
position: relative; position: relative;
z-index: 10; z-index: 10;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: flex-start; align-items: flex-start;
flex-direction: column; flex-direction: column;
overflow-y: hidden; overflow-y: hidden;
> * { > * {
position: relative; position: relative;
} }
> canvas#bg { > canvas#bg {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
} }
.text-container { .text-container {
text-align: left; text-align: left;
max-width: 50rem; max-width: 50rem;
margin: auto auto auto 13vw; margin: auto auto auto 13vw;
} }
h1 { h1 {
font-size: 4rem; font-size: 4rem;
font-weight: 600; font-weight: 600;
margin: 0 0 2rem; margin: 0 0 2rem;
color: var(--boldColor); color: var(--boldColor);
} }
h3 { h3 {
margin: 1rem 0 0; margin: 1rem 0 0;
font-size: 1.7rem; font-size: 1.7rem;
line-height: 1.4; line-height: 1.4;
font-weight: normal; font-weight: normal;
color: var(--textColor); color: var(--textColor);
} }
em { em {
color: var(--boldColor); color: var(--boldColor);
font: inherit; font: inherit;
} }
h3 a { h3 a {
color: var(--boldColor); color: var(--boldColor);
text-decoration: none; text-decoration: none;
border-bottom: 0.2rem solid transparent; border-bottom: 0.2rem solid transparent;
white-space: nowrap; white-space: nowrap;
position: relative; position: relative;
&:before, &:after { &:before, &:after {
content: ''; content: '';
bottom: 0.4rem; bottom: 0.4rem;
left: 0; left: 0;
width: 100%; width: 100%;
height: 0.1rem; height: 0.1rem;
background: var(--boldColor); background: var(--boldColor);
position: absolute; position: absolute;
opacity: 0.04; opacity: 0.04;
transition: all 0.2s ease; transition: all 0.2s ease;
} }
&:before { &:before {
transform: scaleX(0); transform: scaleX(0);
transform-origin: center left; transform-origin: center left;
} }
&:after { &:after {
opacity: 0.1; opacity: 0.1;
} }
&:hover:before { &:hover:before {
transform: scaleX(1); transform: scaleX(1);
opacity: 0.2; opacity: 0.2;
} }
} }
h3 button { h3 button {
color: inherit; color: inherit;
font: inherit; font: inherit;
margin: 0; margin: 0;
padding: 0; padding: 0;
border: 0; border: 0;
background: none; background: none;
} }
.contact-methods { .contact-methods {
display: flex; display: flex;
margin-left: -1.5rem; margin-left: -1.5rem;
margin-top: 1rem; margin-top: 1rem;
a.contact-method { a.contact-method {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
position: relative; position: relative;
overflow: visible; overflow: visible;
width: 4rem; width: 4rem;
height: 4rem; height: 4rem;
i { i {
color: var(--iconColor); color: var(--iconColor);
} }
p { p {
position: absolute; position: absolute;
top: 90%; top: 90%;
left: -100rem; left: -100rem;
right: -100rem; right: -100rem;
margin: 0 auto; margin: 0 auto;
width: max-content; width: max-content;
opacity: 0; opacity: 0;
transition: all 0.2s ease; transition: all 0.2s ease;
color: #333; color: #333;
font-size: 0.85rem; font-size: 0.85rem;
} }
&:hover p { &:hover p {
opacity: 1; opacity: 1;
} }
&:last-child { &:last-child {
p { p {
left: auto; left: auto;
right: 1.5rem; right: 1.5rem;
margin: 0; margin: 0;
} }
} }
&:first-child { &:first-child {
p { p {
left: 1.5rem; left: 1.5rem;
right: auto; right: auto;
margin: 0; margin: 0;
} }
} }
} }
i { i {
width: 4rem; width: 4rem;
height: 4rem; height: 4rem;
line-height: 4rem; line-height: 4rem;
text-align: center; text-align: center;
position: relative; position: relative;
&:before { &:before {
position: relative; position: relative;
z-index: 10; z-index: 10;
} }
&:after { &:after {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
margin: auto; margin: auto;
width: 60%; width: 60%;
height: 60%; height: 60%;
border-radius: 50%; border-radius: 50%;
opacity: 0; opacity: 0;
transform: scale(0.7); transform: scale(0.7);
content: ''; content: '';
transition: all 0.2s ease; transition: all 0.2s ease;
background: #333; background: #333;
} }
} }
i.email { i.email {
position: relative; position: relative;
width: 4rem; width: 4rem;
height: 4rem; height: 4rem;
display: block; display: block;
&:before { &:before {
content: '@'; content: '@';
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
top: 50%; top: 50%;
left: 50%; left: 50%;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
text-align: center; text-align: center;
} }
} }
} }
button.change-color-button { button.change-color-button {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
margin: 1rem; margin: 1rem;
font: inherit; font: inherit;
color: inherit; color: inherit;
border: none; border: none;
border-radius: 100rem; border-radius: 100rem;
height: 3rem; height: 3rem;
width: 3rem; width: 3rem;
text-align: center; text-align: center;
line-height: 3rem; line-height: 3rem;
padding: 0; padding: 0;
background: var(--textColor); background: var(--textColor);
color: var(--bgColor); color: var(--bgColor);
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background: var(--boldColor); background: var(--boldColor);
} }
} }
dialog.change-color-dialog { dialog.change-color-dialog {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
margin: auto; margin: auto;
color: var(--bgColor); color: var(--bgColor);
background: var(--textColor); background: var(--textColor);
padding: 2rem; padding: 2rem;
border: 0; border: 0;
border-radius: 0 0 0.25rem 0.25rem; border-radius: 0 0 0.25rem 0.25rem;
width: 100%; width: 100%;
max-height: calc(100vh - 2rem); max-height: calc(100vh - 2rem);
overflow: scroll; overflow: scroll;
box-shadow: 0 0 0.25rem rgba(0, 0, 0, 0.3), box-shadow: 0 0 0.25rem rgba(0, 0, 0, 0.3),
0 0.15rem 1rem rgba(0, 0, 0, 0.1); 0 0.15rem 1rem rgba(0, 0, 0, 0.1);
font-size: 1.33rem; font-size: 1.33rem;
opacity: 0; opacity: 0;
transform: translateY(-10%); transform: translateY(-10%);
pointer-events: none; pointer-events: none;
transition: all 0.2s ease; transition: all 0.2s ease;
display: block; display: block;
&[open] { &[open] {
opacity: 1; opacity: 1;
transform: translateY(0%); transform: translateY(0%);
pointer-events: all; pointer-events: all;
} }
h4 { h4 {
margin: 0 0 1rem; margin: 0 0 1rem;
text-align: center; text-align: center;
font-size: 1.9rem; font-size: 1.9rem;
font-weight: 400; font-weight: 400;
} }
form { form {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
input[type='button'], input[type='submit'] { input[type='button'], input[type='submit'] {
font: inherit; font: inherit;
color: inherit; color: inherit;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
border: 0; border: 0;
margin: 1rem 0.5rem 0; margin: 1rem 0.5rem 0;
color: var(--textColor); color: var(--textColor);
background: var(--bgColor); background: var(--bgColor);
border-radius: 0.25rem; border-radius: 0.25rem;
cursor: pointer; cursor: pointer;
&:hover { &:hover {
color: var(--boldColor); color: var(--boldColor);
} }
} }
} }
.radio-buttons { .radio-buttons {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
> div { > div {
margin: 0.5rem 0; margin: 0.5rem 0;
input { input {
display: none; display: none;
} }
label div { label div {
display: inline-block; display: inline-block;
height: 2rem; height: 2rem;
width: 2rem; width: 2rem;
border-radius: 50%; border-radius: 50%;
margin: 0 0.25rem 0 0.75rem; margin: 0 0.25rem 0 0.75rem;
line-height: 2rem; line-height: 2rem;
text-align: center; text-align: center;
border: 0.5rem solid var(--textColor); border: 0.5rem solid var(--textColor);
background-clip: padding-box; background-clip: padding-box;
} }
input:checked + label div { input:checked + label div {
border: 0; border: 0;
} }
} }
} }
} }
dialog.change-color-dialog[open] + button.change-color-button { dialog.change-color-dialog[open] + button.change-color-button {
transition: all 0.2s ease; transition: all 0.2s ease;
opacity: 0; opacity: 0;
pointer-events: none; pointer-events: none;
} }
} }
@media(max-width: 69rem), (orientation: portrait) { @media(max-width: 69rem), (orientation: portrait) {
.main > .text-container { .main > .text-container {
margin: auto; margin: auto;
padding: 2rem; padding: 2rem;
} }
} }
@media(max-width: 30rem) { @media(max-width: 30rem) {
dialog.change-color-dialog br { dialog.change-color-dialog br {
display: none; display: none;
} }
.main { .main {
> .text-container { > .text-container {
h1 { h1 {
font-size: 3rem; font-size: 3rem;
} }
h3 { h3 {
font-size: 1.5rem; font-size: 1.5rem;
} }
} }
.contact-methods { .contact-methods {
justify-content: center; justify-content: center;
margin-top: 2rem; margin-top: 2rem;
} }
} }
} }
.clapper { .clapper {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 10rem; height: 10rem;
line-height: 10rem; line-height: 10rem;
text-align: center; text-align: center;
z-index: 100000; z-index: 100000;
font-size: 5rem; font-size: 5rem;
pointer-events: none; pointer-events: none;
transition: none; transition: none;
opacity: 0; opacity: 0;
color: var(--boldColor); color: var(--boldColor);
} }
.clapper.clapping { .clapper.clapping {
animation: clap 1s ease-in-out; animation: clap 1s ease-in-out;
} }
@keyframes clap { @keyframes clap {
0% { opacity: 1; } 0% { opacity: 1; }
49% { opacity: 0; } 49% { opacity: 0; }
51% { opacity: 1; } 51% { opacity: 1; }
100% { opacity: 0; } 100% { opacity: 0; }
} }
@media (prefers-reduced-motion) { @media (prefers-reduced-motion) {
canvas#bg { canvas#bg {
display: none; display: none;
} }
} }

View file

@ -1,69 +1,69 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
<title>Naman Sood</title> <title>Naman Sood</title>
<meta name="description" content="Developer and technology enthusiast who's never gonna give you up."> <meta name="description" content="Developer and technology enthusiast who's never gonna give you up.">
<meta name="keywords" content="nsood, nfool, naman sood, nachloride, nsdcars5, namansood, namandoesnotpanic, tendstofortytwo"> <meta name="keywords" content="nsood, nfool, naman sood, nachloride, nsdcars5, namansood, namandoesnotpanic, tendstofortytwo">
<meta property="og:url" content="https://nsood.in"> <meta property="og:url" content="https://nsood.in">
<meta property="og:type" content="website"> <meta property="og:type" content="website">
<meta property="og:title" content="Naman Sood"> <meta property="og:title" content="Naman Sood">
<meta property="og:description" content="Developer and technology enthusiast who's never gonna give you up."> <meta property="og:description" content="Developer and technology enthusiast who's never gonna give you up.">
<meta property="og:image" content="https://nsood.in/screenshot.php"> <meta property="og:image" content="https://nsood.in/screenshot.php">
<link rel="stylesheet" type="text/css" href="fonts/css/nunito.css"> <link rel="stylesheet" type="text/css" href="fonts/css/nunito.css">
<link rel="stylesheet" type="text/css" href="fonts/css/fontawesome.min.css"> <link rel="stylesheet" type="text/css" href="fonts/css/fontawesome.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css"> <link rel="stylesheet" type="text/css" href="css/style.css">
</head> </head>
<body> <body>
<section id="home" class="main"> <section id="home" class="main">
<!-- empty alt attribute informs screen readers that background graphic is purely decorative and should be ignored --> <!-- empty alt attribute informs screen readers that background graphic is purely decorative and should be ignored -->
<canvas id="bg" alt=""></canvas> <canvas id="bg" alt=""></canvas>
<div class="text-container"> <div class="text-container">
<h1>Hi, I&rsquo;m Naman.</h1> <h1>Hi, I&rsquo;m Naman.</h1>
<h3>I&rsquo;m a<span class="age"> twenty one</span> year-old who's fond of <em>coffee</em>, <em>math</em>, <em>writing</em>, <em>cars</em>, <button class="among">among</button> other things. I also enjoy <em>programming</em> enough to do that for a living. I&rsquo;m currently studying <em>computer science</em> at the <em>University of Waterloo</em>.</h3> <h3>I&rsquo;m a<span class="age"> twenty one</span> year-old who's fond of <em>coffee</em>, <em>math</em>, <em>writing</em>, <em>cars</em>, <button class="among">among</button> other things. I also enjoy <em>programming</em> enough to do that for a living. I&rsquo;m currently studying <em>computer science</em> at the <em>University of Waterloo</em>.</h3>
<h3>You can click to see my <a href="/resume.pdf">resume</a>, visit my <a href="https://prose.nsood.in">blog</a>, or check out ways to contact me below.</h3> <h3>You can click to see my <a href="/resume.pdf">resume</a>, visit my <a href="https://prose.nsood.in">blog</a>, or check out ways to contact me below.</h3>
<div class="contact-methods"> <div class="contact-methods">
<a href="mailto:mail@nsood.in" class="contact-method" aria-label="Email"> <a href="mailto:mail@nsood.in" class="contact-method" aria-label="Email">
<i class="email"></i> <i class="email"></i>
<p class="detail">mail@nsood.in</p> <p class="detail">mail@nsood.in</p>
</a> </a>
<a href="https://social.treehouse.systems/@tendstofortytwo" class="contact-method" aria-label="Mastodon" rel="me"> <a href="https://social.treehouse.systems/@tendstofortytwo" class="contact-method" aria-label="Mastodon" rel="me">
<i class="fab fa-mastodon"></i> <i class="fab fa-mastodon"></i>
<p class="detail">@tendstofortytwo@treehouse.systems</p> <p class="detail">@tendstofortytwo@treehouse.systems</p>
</a> </a>
<a href="https://linkedin.com/in/namansood" class="contact-method" aria-label="LinkedIn"> <a href="https://linkedin.com/in/namansood" class="contact-method" aria-label="LinkedIn">
<i class="fab fa-linkedin-in"></i> <i class="fab fa-linkedin-in"></i>
<p class="detail">Naman Sood</p> <p class="detail">Naman Sood</p>
</a> </a>
<a href="https://github.com/tendstofortytwo" class="contact-method" aria-label="GitHub"> <a href="https://github.com/tendstofortytwo" class="contact-method" aria-label="GitHub">
<i class="fab fa-github"></i> <i class="fab fa-github"></i>
<p class="detail">tendstofortytwo</p> <p class="detail">tendstofortytwo</p>
</a> </a>
</div> </div>
</div> </div>
<dialog class="change-color-dialog"> <dialog class="change-color-dialog">
<h4>If you could pick any color,<br> what color would you pick?</h4> <h4>If you could pick any color,<br> what color would you pick?</h4>
<form method="dialog"> <form method="dialog">
<div class="radio-buttons"></div> <div class="radio-buttons"></div>
<input type="button" value="save" id="color-change-save"> <input type="button" value="save" id="color-change-save">
<input type="submit" value="exit"> <input type="submit" value="exit">
</form> </form>
</dialog> </dialog>
<button class="change-color-button" aria-label="change color"> <button class="change-color-button" aria-label="change color">
<i class="fas fa-paint-brush"></i> <i class="fas fa-paint-brush"></i>
</button> </button>
<noscript> <noscript>
<style> <style>
button.change-color-button { display: none; } button.change-color-button { display: none; }
</style> </style>
</noscript> </noscript>
</section> </section>
<!-- I guess it doesn't make sense for a purely visual easter egg to be visible to screen readers..? --> <!-- I guess it doesn't make sense for a purely visual easter egg to be visible to screen readers..? -->
<div class="clapper" aria-hidden="true">👏👏👏</div> <div class="clapper" aria-hidden="true">👏👏👏</div>
<script src="js/script.js"></script> <script src="js/script.js"></script>
<script src="fonts/attribution.js"></script> <script src="fonts/attribution.js"></script>
</body> </body>
</html> </html>

View file

@ -1,199 +1,199 @@
const canvas = document.querySelector('canvas#bg'); const canvas = document.querySelector('canvas#bg');
canvas.width = window.innerWidth; canvas.width = window.innerWidth;
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
const FILL_STYLES = { const FILL_STYLES = {
light: 'rgba(0,0,0,0.05)', light: 'rgba(0,0,0,0.05)',
dark: 'rgba(255,255,255,0.15)' dark: 'rgba(255,255,255,0.15)'
}; };
const colorMode = localStorage.getItem('color-mode'); const colorMode = localStorage.getItem('color-mode');
if(colorMode) { if(colorMode) {
document.body.setAttribute('class', colorMode); document.body.setAttribute('class', colorMode);
} }
addEventListener('resize', () => { addEventListener('resize', () => {
canvas.width = window.innerWidth; canvas.width = window.innerWidth;
canvas.height = window.innerHeight; canvas.height = window.innerHeight;
}); });
function isDarkMode() { function isDarkMode() {
return document.body.classList.contains('dark-mode') || return document.body.classList.contains('dark-mode') ||
(document.body.classList.length === 0 && matchMedia('(prefers-color-scheme: dark)').matches); (document.body.classList.length === 0 && matchMedia('(prefers-color-scheme: dark)').matches);
} }
function Point() { function Point() {
const r = 8; const r = 8;
// progress below 0 is neglected, negative initial // progress below 0 is neglected, negative initial
// progress serves to introduce random delays - // progress serves to introduce random delays -
// at 0.05 progress points per second, for example // at 0.05 progress points per second, for example
// a dot with initial progress -0.15 will run 2 frames // a dot with initial progress -0.15 will run 2 frames
// after a dot with initial progress -0.05 // after a dot with initial progress -0.05
const initialProgress = -4 * Math.random(); const initialProgress = -4 * Math.random();
// moves point to a random location and // moves point to a random location and
// resets its progress // resets its progress
this.init = function() { this.init = function() {
this.progress = initialProgress; this.progress = initialProgress;
this.x = Math.random() * canvas.width; this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height; this.y = Math.random() * canvas.height;
this.r = 0; this.r = 0;
this.rng = Math.random(); this.rng = Math.random();
} }
this.draw = function() { this.draw = function() {
if(this.progress >= 0) { if(this.progress >= 0) {
ctx.fillStyle = isDarkMode() ? FILL_STYLES.dark : FILL_STYLES.light; ctx.fillStyle = isDarkMode() ? FILL_STYLES.dark : FILL_STYLES.light;
ctx.beginPath(); ctx.beginPath();
// radius calculation: maps progress from [0, 1] to [0, pi], // radius calculation: maps progress from [0, 1] to [0, pi],
// then takes sine of that to get an increase, then decrease // then takes sine of that to get an increase, then decrease
// in radius. absolute value to prevent floating point errors // in radius. absolute value to prevent floating point errors
// accidentally causing negative sine values which cause ctx.arc // accidentally causing negative sine values which cause ctx.arc
// to throw errors // to throw errors
ctx.arc(this.x, this.y, Math.abs(Math.sin(Math.PI*this.progress)*r), 0, 2*Math.PI); ctx.arc(this.x, this.y, Math.abs(Math.sin(Math.PI*this.progress)*r), 0, 2*Math.PI);
ctx.fill(); ctx.fill();
} }
}; };
this.render = function() { this.render = function() {
// stars come faster than they go // stars come faster than they go
// so user can look at them longer // so user can look at them longer
// i guess? idk this just looked pretty // i guess? idk this just looked pretty
if(this.progress > 0.5) this.progress += 0.005; if(this.progress > 0.5) this.progress += 0.005;
else this.progress += 0.05; else this.progress += 0.05;
this.draw(); this.draw();
if(this.progress >= 1) this.init(); if(this.progress >= 1) this.init();
} }
} }
const dots = []; const dots = [];
const n = 20; const n = 20;
for(let i = 0; i < n; i++) { for(let i = 0; i < n; i++) {
dots[i] = new Point(); dots[i] = new Point();
dots[i].init(); dots[i].init();
} }
function loop() { function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
for(let i = 0; i < n; i++) { for(let i = 0; i < n; i++) {
dots[i].render(); dots[i].render();
} }
requestAnimationFrame(loop); requestAnimationFrame(loop);
} }
loop(); loop();
// slight convenience: fix the header section with my correct age automatically // slight convenience: fix the header section with my correct age automatically
const birthday = { const birthday = {
date: 19, date: 19,
month: 0, month: 0,
year: 2001, year: 2001,
} }
const today = new Date(); const today = new Date();
let age = today.getFullYear() - birthday.year; let age = today.getFullYear() - birthday.year;
if(today.getMonth() < birthday.month || (today.getMonth() == birthday.month && today.getDate() < birthday.date)) { if(today.getMonth() < birthday.month || (today.getMonth() == birthday.month && today.getDate() < birthday.date)) {
--age; --age;
} }
const tens = ['', ' ten plus', ' twenty', ' thirty', ' forty', ' fifty', ' sixty', ' seventy', 'n eighty', ' ninety']; const tens = ['', ' ten plus', ' twenty', ' thirty', ' forty', ' fifty', ' sixty', ' seventy', 'n eighty', ' ninety'];
const ones = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']; const ones = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
document.querySelector('.age').textContent = `${tens[Math.floor(age / 10)]} ${ones[age % 10]}`; document.querySelector('.age').textContent = `${tens[Math.floor(age / 10)]} ${ones[age % 10]}`;
// easter egg // easter egg
const sequences = [ const sequences = [
'DARK', 'DARK',
'LITE', 'LITE',
'PURP', 'PURP',
'MINT', 'MINT',
'YELL', 'YELL',
'BLUE', 'BLUE',
'SAVE' 'SAVE'
].map(seq => ({ ].map(seq => ({
word: seq, word: seq,
combo: seq.split('').map(c => 'Key' + c) combo: seq.split('').map(c => 'Key' + c)
})); }));
const lastFourKeys = []; const lastFourKeys = [];
function changeColor(word) { function changeColor(word) {
const clapper = document.querySelector('.clapper'); const clapper = document.querySelector('.clapper');
clapper.classList.toggle('clapping'); clapper.classList.toggle('clapping');
setTimeout(() => { setTimeout(() => {
document.body.setAttribute('class', `${word.toLowerCase()}-mode`); document.body.setAttribute('class', `${word.toLowerCase()}-mode`);
document.querySelector(`#change-color-to-${word}`).checked = true; document.querySelector(`#change-color-to-${word}`).checked = true;
setTimeout(() => clapper.classList.toggle('clapping'), 500); setTimeout(() => clapper.classList.toggle('clapping'), 500);
}, 500); }, 500);
} }
addEventListener('keypress', e => { addEventListener('keypress', e => {
lastFourKeys.push(e.code); lastFourKeys.push(e.code);
while(lastFourKeys.length > 4) lastFourKeys.shift(); while(lastFourKeys.length > 4) lastFourKeys.shift();
sequences.forEach(({word, combo}) => { sequences.forEach(({word, combo}) => {
if(combo.every((v, i) => v === lastFourKeys[i])) { if(combo.every((v, i) => v === lastFourKeys[i])) {
if(word === 'SAVE') { if(word === 'SAVE') {
if(confirm('Would you like to save the current color mode to local browser storage?')) { if(confirm('Would you like to save the current color mode to local browser storage?')) {
localStorage.setItem('color-mode', document.body.getAttribute('class')); localStorage.setItem('color-mode', document.body.getAttribute('class'));
} }
return; return;
} }
changeColor(word); changeColor(word);
} }
}); });
}); });
document.querySelector('button.change-color-button').addEventListener('click', () => { document.querySelector('button.change-color-button').addEventListener('click', () => {
document.querySelector('dialog.change-color-dialog').show(); document.querySelector('dialog.change-color-dialog').show();
}); });
sequences.forEach(({word}) => { sequences.forEach(({word}) => {
if(word !== 'SAVE') { if(word !== 'SAVE') {
const container = document.createElement('div'); const container = document.createElement('div');
const radio = document.createElement('input'); const radio = document.createElement('input');
radio.type = 'radio'; radio.type = 'radio';
radio.name = 'change-color-radio'; radio.name = 'change-color-radio';
radio.id = `change-color-to-${word}`; radio.id = `change-color-to-${word}`;
radio.checked = document.body.classList.contains(`${word.toLowerCase()}-mode`) || radio.checked = document.body.classList.contains(`${word.toLowerCase()}-mode`) ||
(document.body.classList.length === 0 && (document.body.classList.length === 0 &&
((isDarkMode() && word === 'DARK') || (!isDarkMode() && word === 'LITE'))); ((isDarkMode() && word === 'DARK') || (!isDarkMode() && word === 'LITE')));
radio.addEventListener('click', () => { radio.addEventListener('click', () => {
changeColor(word); changeColor(word);
}); });
const label = document.createElement('label'); const label = document.createElement('label');
label.setAttribute('for', radio.id); label.setAttribute('for', radio.id);
const color = document.createElement('div'); const color = document.createElement('div');
color.setAttribute('style', color.setAttribute('style',
`background-color: var(--${word.toLowerCase()}Color); color: var(--${word.toLowerCase()}Text)`); `background-color: var(--${word.toLowerCase()}Color); color: var(--${word.toLowerCase()}Text)`);
label.appendChild(color); label.appendChild(color);
label.setAttribute('aria-label', word.toLowerCase()); label.setAttribute('aria-label', word.toLowerCase());
container.appendChild(radio); container.appendChild(radio);
container.appendChild(label); container.appendChild(label);
document.querySelector('.change-color-dialog .radio-buttons').appendChild(container); document.querySelector('.change-color-dialog .radio-buttons').appendChild(container);
} }
}); });
document.querySelector('#color-change-save').addEventListener('click', () => { document.querySelector('#color-change-save').addEventListener('click', () => {
localStorage.setItem('color-mode', document.body.getAttribute('class')); localStorage.setItem('color-mode', document.body.getAttribute('class'));
alert('Saved!'); alert('Saved!');
}); });
function among() { function among() {
alert('haha among us'); alert('haha among us');
} }
document.querySelector('.among').addEventListener('click', e => { document.querySelector('.among').addEventListener('click', e => {
e.preventDefault(); e.preventDefault();
among(); among();
}); });