diff --git a/README.md b/README.md
index 1ff4000..d1ef255 100644
--- a/README.md
+++ b/README.md
@@ -80,18 +80,18 @@ Configures what state of the toggle button should be shown to the user.
## Customize Dark Mode
-You can exclude elements from being inverted in dark mode using the `.nightowl-daylight` CSS class. Just add it to an element and it will show the element in the same way as the light mode.
+You can exclude elements from being inverted in dark mode using the `.nightowl-daylight` CSS class. Just add it to an element and it will show the element in the same way as the light mode.
```html
-
I'm inverted in Dark Mode
-
I'm not inverted in Dark Mode
+
I'm inverted in Dark Mode
+
I'm not inverted in Dark Mode
```
## Contribution Guidelines
-Please open an issue and wait for one of the Maintainers to approve it until you open a merge request.
+Please open an issue and wait for one of the Maintainers to approve it until you open a merge request.
## Credits
diff --git a/index.html b/index.html
index dc92526..bb453f6 100644
--- a/index.html
+++ b/index.html
@@ -2,9 +2,16 @@
-
- Vite + TS
+ Nightowl
+
+
+
+
+
-
+
- Nightowl Demo Site
- Nightowl
+
+
- A Card with some text
-
- Fancy Button
-
-
+
+
+
+
+
+
+
+ Contact Us
+
+
+
+
+
Lorem ipsum dolor sit amet consectetur adipisicing
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing
+ elit. A assumenda blanditiis esse ex inventore molestias
+ odit perferendis qui reprehenderit totam. Atque beatae
+ dicta, fuga illo laudantium porro rerum ullam vitae.
+
+
+ Contact Us
+
+
+
+
+
+
+
+
+
+ Features
+
+ Aut consequuntur cum esse ex explicabo iure, magnam maiores
+ perferendis qui tempora?
+
+
+
+
+ Fast
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing
+ elit. Architecto, error facere modi nobis pariatur
+ placeat quis quos unde vitae voluptate.
+
+
+
+
+ Fun
+
+ Amet animi earum error expedita hic illo, impedit in
+ laboriosam nam, necessitatibus optio provident quia
+ quibusdam sit tempore vel, voluptate?
+
+
+
+
+ Easy
+
+ Adipisci assumenda expedita ipsa necessitatibus
+ nihil pariatur quaerat quas recusandae reiciendis
+ tempore ullam, ut. Eum fugit iste iusto nostrum
+ quod?
+
+
+
+
+ Tunable
+
+ Alias autem blanditiis cupiditate doloremque illum
+ minima odit possimus provident quasi quidem
+ repellat, similique sunt tenetur ullam unde veniam
+ veritatis.
+
+
+
+
+
+
+
+
+
+
Statistics
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing
+ elit. A, aliquid, animi assumenda blanditiis cupiditate
+ debitis eligendi, enim facere fuga fugiat fugit ipsa
+ labore magnam quibusdam quo quos sapiente sunt velit
+ vitae voluptate! Accusantium aliquam animi assumenda,
+ necessitatibus quod rem repudiandae?
+
+
+ Read More
+
+
+
+
+ Our Team
+ Aliquid architecto nisi quisquam sapiente sed.
+
+
+
+
+
+
+
+
+
nisi quisquam
+
+ Beatae dolores eligendi fugit ipsam laudantium
+ neque quaerat rem vero vitae voluptatem!
+
+
+
+
+
+
+
+
+
+
+
eligendi fugit
+
+ Accusantium animi cumque enim excepturi fuga
+ ipsa non perferendis quasi sit voluptatibus.
+
+
+
+
+
+
+
+
+
+
+
excepturi fuga
+
+ Esse expedita iste laboriosam quis suscipit.
+ Cumque eum sit suscipit voluptatem voluptatum.
+
+
+
+
+
+
+
diff --git a/public/assets/illustrations/chart.svg b/public/assets/illustrations/chart.svg
new file mode 100644
index 0000000..74089c3
--- /dev/null
+++ b/public/assets/illustrations/chart.svg
@@ -0,0 +1 @@
+Direct Email Union Ads Video Ads
\ No newline at end of file
diff --git a/public/assets/images/contact.webp b/public/assets/images/contact.webp
new file mode 100644
index 0000000..4477582
Binary files /dev/null and b/public/assets/images/contact.webp differ
diff --git a/public/assets/images/hero.webp b/public/assets/images/hero.webp
new file mode 100644
index 0000000..59879af
Binary files /dev/null and b/public/assets/images/hero.webp differ
diff --git a/public/assets/images/teammate-1.jpg b/public/assets/images/teammate-1.jpg
new file mode 100644
index 0000000..71f449a
Binary files /dev/null and b/public/assets/images/teammate-1.jpg differ
diff --git a/public/assets/images/teammate-2.jpg b/public/assets/images/teammate-2.jpg
new file mode 100644
index 0000000..c97640f
Binary files /dev/null and b/public/assets/images/teammate-2.jpg differ
diff --git a/public/assets/images/teammate-3.jpg b/public/assets/images/teammate-3.jpg
new file mode 100644
index 0000000..8de99f8
Binary files /dev/null and b/public/assets/images/teammate-3.jpg differ
diff --git a/src/main.ts b/src/main.ts
index 0fa8334..dfe8413 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,3 +1,12 @@
+import './styles/global.css'
+import './styles/button.css'
+import './styles/header.css'
+import './styles/intro.css'
+import './styles/features.css'
+import './styles/statistics.css'
+import './styles/team.css'
+import './styles/contact.css'
+
const LOCAL_STORAGE_KEY = 'nightowl-color-scheme'
const LIGHT = 'light'
const DARK = 'dark'
diff --git a/src/scripts/header.ts b/src/scripts/header.ts
new file mode 100644
index 0000000..534c60e
--- /dev/null
+++ b/src/scripts/header.ts
@@ -0,0 +1,75 @@
+class HeaderService {
+ private headerElement = document.querySelector('body > header')!
+ private menuButton = document.querySelector('body > header button.menu')!
+ private closeButton = document.querySelector('body > header button.close')!
+ private navElement = document.querySelector('body > header nav')!
+ private navLinks = document.querySelectorAll(
+ 'body > header nav a'
+ )
+
+ public init(): void {
+ this.addMenuButtonClickListener()
+ this.addNavLinksClickListener()
+ this.addWindowResizeObserver()
+ this.addDocumentScrollListener()
+
+ this.updateStickiness()
+ }
+
+ private addMenuButtonClickListener(): void {
+ this.menuButton.addEventListener('click', () => {
+ this.showMobileNav()
+ })
+
+ this.closeButton.addEventListener('click', () => {
+ this.hideMobileNav()
+ })
+ }
+
+ private showMobileNav(): void {
+ this.navElement.classList.remove('hidden')
+ this.menuButton.classList.add('hidden')
+ this.closeButton.classList.remove('hidden')
+ }
+
+ private hideMobileNav(): void {
+ this.navElement.classList.add('hidden')
+ this.menuButton.classList.remove('hidden')
+ this.closeButton.classList.add('hidden')
+ }
+
+ private addNavLinksClickListener(): void {
+ this.navLinks.forEach((navLink) => {
+ navLink.addEventListener('click', () => {
+ this.hideMobileNav()
+ })
+ })
+ }
+
+ private addWindowResizeObserver(): void {
+ const observer = new ResizeObserver(() => {
+ if (window.innerWidth >= 800) {
+ this.hideMobileNav()
+ }
+ })
+
+ observer.observe(document.body)
+ }
+
+ private addDocumentScrollListener(): void {
+ document.addEventListener('scroll', () => {
+ this.updateStickiness()
+ })
+ }
+
+ private updateStickiness(): void {
+ if (window.scrollY > 50) {
+ this.headerElement.classList.add('stuck')
+ } else if (window.scrollY === 0) {
+ this.headerElement.classList.remove('stuck')
+ }
+ }
+}
+
+const headerService = new HeaderService()
+headerService.init()
diff --git a/src/styles/button.css b/src/styles/button.css
new file mode 100644
index 0000000..5c0d5f1
--- /dev/null
+++ b/src/styles/button.css
@@ -0,0 +1,54 @@
+.button {
+ border-radius: var(--border-radius);
+
+ font-weight: 500;
+
+ text-decoration: none;
+ text-transform: uppercase;
+
+ cursor: pointer;
+
+ &.button--solid {
+ background-color: var(--color-primary);
+ color: var(--color-primary-opposite);
+
+ padding: 1em 2em;
+
+ border: none;
+
+ transition: background-color var(--animation-duration-fast) ease-in-out;
+
+ &:hover {
+ background-color: var(--color-primary-darker);
+ }
+ }
+
+ &.button--outlined {
+ background-color: transparent;
+ color: var(--color-primary);
+
+ padding: 0.5em 1em;
+
+ border: 1px solid var(--color-primary);
+
+ transition: var(--animation-duration-fast) ease-in-out;
+ transition-property: background-color, color;
+
+ &:hover {
+ background-color: var(--color-primary);
+ color: var(--color-primary-opposite);
+ }
+ }
+
+ &.button--icon {
+ background-color: transparent;
+
+ border: none;
+
+ transition: background-color var(--animation-duration-fast) ease-in-out;
+
+ &:hover {
+ background-color: var(--color-gray-90);
+ }
+ }
+}
diff --git a/src/styles/contact.css b/src/styles/contact.css
new file mode 100644
index 0000000..ef19dab
--- /dev/null
+++ b/src/styles/contact.css
@@ -0,0 +1,84 @@
+#contact {
+ display: grid;
+ grid-template-areas: 'h2' 'p' 'visuals' 'form';
+ grid-template-columns: 1fr;
+ gap: 1rem;
+
+ padding-block: 4rem;
+ padding-inline: var(--page-padding-inline);
+
+ h2 {
+ grid-area: h2;
+ }
+
+ > p {
+ grid-area: p;
+
+ margin-block-end: 1rem;
+ }
+
+ .visuals {
+ grid-area: visuals;
+
+ display: grid;
+ place-items: center;
+
+ .shape {
+ box-shadow: var(--box-shadow-normal);
+
+ overflow: hidden;
+
+ max-block-size: 25rem;
+ max-inline-size: 80%;
+ aspect-ratio: 1;
+
+ border-radius: var(--border-radius-blob);
+
+ img {
+ block-size: 100%;
+ inline-size: 100%;
+ max-inline-size: unset;
+ object-fit: cover;
+ }
+ }
+ }
+
+ form {
+ grid-area: form;
+
+ display: grid;
+ align-content: start;
+ gap: 1.5rem;
+
+ label {
+ display: grid;
+ gap: 0.25rem;
+
+ input,
+ textarea {
+ padding: 0.5rem;
+
+ border: 1px solid var(--color-gray-50);
+ border-radius: var(--border-radius);
+
+ font-size: 1.25rem;
+ }
+
+ textarea {
+ resize: vertical;
+ }
+ }
+
+ button {
+ font-size: 1.2rem;
+ }
+ }
+}
+
+@media (width >= 800px) {
+ #contact {
+ grid-template-areas: 'h2 h2' 'p p' 'visuals form';
+ grid-template-columns: 1fr 1fr;
+ gap: 1rem;
+ }
+}
diff --git a/src/styles/features.css b/src/styles/features.css
new file mode 100644
index 0000000..8946595
--- /dev/null
+++ b/src/styles/features.css
@@ -0,0 +1,70 @@
+#features {
+ display: grid;
+ gap: 1rem;
+
+ padding-block: 4rem;
+ padding-inline: var(--page-padding-inline);
+
+ > p {
+ margin-block-end: 1rem;
+ }
+
+ > ul {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
+ gap: 2rem;
+
+ > li {
+ background-color: var(--color-gray-98);
+ box-shadow: var(--box-shadow-normal);
+
+ display: grid;
+ align-content: start;
+ justify-items: center;
+
+ padding: 1rem;
+
+ border-radius: var(--border-radius);
+
+ text-align: center;
+
+ .visual {
+ svg {
+ block-size: 1em;
+ inline-size: 1em;
+
+ font-size: 4rem;
+
+ path {
+ fill: var(--color);
+ }
+ }
+ }
+
+ .title {
+ color: var(--color);
+
+ margin-block-end: 1rem;
+
+ font-size: 1.5rem;
+ font-weight: 700;
+ }
+
+ &:nth-of-type(1) {
+ --color: hsl(10deg 70% 50%);
+ }
+
+ &:nth-of-type(2) {
+ --color: hsl(40deg 70% 50%);
+ }
+
+ &:nth-of-type(3) {
+ --color: hsl(90deg 70% 50%);
+ }
+
+ &:nth-of-type(4) {
+ --color: hsl(160deg 70% 50%);
+ }
+ }
+ }
+}
diff --git a/src/styles/global.css b/src/styles/global.css
new file mode 100644
index 0000000..084635a
--- /dev/null
+++ b/src/styles/global.css
@@ -0,0 +1,110 @@
+:root {
+ --color-gray-98: hsl(0deg 0% 98%);
+ --color-gray-95: hsl(0deg 0% 95%);
+ --color-gray-90: hsl(0deg 0% 90%);
+ --color-gray-80: hsl(0deg 0% 80%);
+ --color-gray-70: hsl(0deg 0% 70%);
+ --color-gray-60: hsl(0deg 0% 60%);
+ --color-gray-50: hsl(0deg 0% 50%);
+ --color-gray-40: hsl(0deg 0% 40%);
+ --color-gray-30: hsl(0deg 0% 30%);
+ --color-gray-20: hsl(0deg 0% 20%);
+ --color-gray-16: hsl(0deg 0% 16%);
+ --color-gray-14: hsl(0deg 0% 14%);
+ --color-gray-12: hsl(0deg 0% 12%);
+ --color-gray-10: hsl(0deg 0% 10%);
+
+ --color-primary: hsl(261deg 66% 69%);
+ --color-primary-darker: hsl(261deg 66% 60%);
+ --color-primary-opposite: var(--color-gray-98);
+
+ --color-box-shadow-subtle: hsl(0deg 0% 10% / 12%);
+ --box-shadow-subtle: 0 0.2rem 0.5rem 0 var(--color-box-shadow-subtle);
+
+ --color-box-shadow-normal: hsl(0deg 0% 10% / 20%);
+ --box-shadow-normal: 0 0.5rem 1rem 0 var(--color-box-shadow-subtle);
+
+ --border-radius: 0.25rem;
+ --border-radius-blob: 33% 67% 38% 62% / 26% 32% 68% 74%;
+
+ --page-max-inline-size: 75rem;
+ --page-padding-inline: calc(
+ max(100% - var(--page-max-inline-size), 2rem) / 2
+ );
+
+ --animation-duration-fast: 0.2s;
+ --animation-duration-normal: 0.5s;
+ --animation-duration-slow: 1s;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+
+ margin: 0;
+ padding: 0;
+}
+
+html {
+ accent-color: var(--color-primary);
+
+ scroll-behavior: smooth;
+ scroll-padding: 4rem;
+
+ font-family: 'Inter', sans-serif;
+ font-optical-sizing: auto;
+ font-weight: 400;
+ font-style: normal;
+ font-variation-settings: 'slnt' 0;
+}
+
+input,
+label,
+select,
+textarea,
+button,
+fieldset,
+legend,
+datalist,
+output,
+option,
+optgroup {
+ font-family: inherit;
+}
+
+p {
+ color: var(--color-gray-40);
+
+ line-height: 1.4;
+}
+
+ul {
+ list-style: none;
+}
+
+img {
+ block-size: auto;
+ max-inline-size: 100%;
+}
+
+body {
+ background-color: var(--color-gray-95);
+ color: var(--color-gray-10);
+
+ min-block-size: 100dvh;
+}
+
+h1 {
+ font-size: 3rem;
+ font-weight: 700;
+
+ line-height: 1;
+}
+
+h2 {
+ font-size: 2rem;
+ font-weight: 700;
+
+ line-height: 1;
+}
diff --git a/src/styles/header.css b/src/styles/header.css
new file mode 100644
index 0000000..00d4e19
--- /dev/null
+++ b/src/styles/header.css
@@ -0,0 +1,124 @@
+header {
+ background-color: inherit;
+
+ position: sticky;
+ inset-block-start: 0;
+ z-index: 2;
+
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 2rem;
+
+ padding-block: 2rem;
+ padding-inline: var(--page-padding-inline);
+
+ transition: var(--animation-duration-fast) ease-in-out;
+ transition-property: background-color, box-shadow, padding-block;
+
+ .logo {
+ margin-inline-end: auto;
+
+ font-size: 1.5rem;
+ font-weight: 700;
+ }
+
+ button {
+ z-index: 2;
+ }
+
+ nav {
+ ul {
+ li {
+ a {
+ color: inherit;
+
+ position: relative;
+
+ font-weight: 500;
+
+ text-decoration: none;
+
+ &::after {
+ content: '';
+
+ background-color: currentcolor;
+
+ position: absolute;
+ inset-block-end: 0;
+ inset-inline: 0;
+
+ block-size: 1px;
+
+ transform: scaleX(0);
+
+ transition: transform var(--animation-duration-fast)
+ ease-in-out;
+ }
+
+ &:hover {
+ &::after {
+ transform: scaleX(100%);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ &.stuck {
+ background-color: var(--color-gray-98);
+ box-shadow: var(--box-shadow-subtle);
+
+ padding-block: 1rem;
+ }
+}
+
+@media (width < 800px) {
+ header {
+ button {
+ order: 3;
+ }
+
+ nav {
+ background-color: var(--color-gray-98);
+
+ position: fixed;
+ inset: 0;
+ overflow: auto;
+ z-index: 1;
+
+ display: grid;
+ align-content: start;
+
+ padding: inherit;
+
+ font-size: 1.5rem;
+
+ ul {
+ display: grid;
+ gap: 2rem;
+ }
+ }
+
+ .hidden {
+ display: none;
+ }
+ }
+}
+
+@media (width >= 800px) {
+ header {
+ button {
+ display: none;
+ }
+
+ nav {
+ ul {
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+ }
+ }
+ }
+}
diff --git a/src/styles/intro.css b/src/styles/intro.css
new file mode 100644
index 0000000..db4eacb
--- /dev/null
+++ b/src/styles/intro.css
@@ -0,0 +1,89 @@
+#intro {
+ display: grid;
+ grid-template-areas: 'writings visuals';
+ grid-template-columns: 1fr 1fr;
+ align-items: center;
+ gap: 4rem;
+
+ padding-block: 8rem;
+ padding-inline: var(--page-padding-inline);
+
+ .writings {
+ grid-area: writings;
+
+ display: grid;
+ justify-items: start;
+ gap: 1rem;
+
+ p {
+ margin-block-end: 1rem;
+
+ font-size: 1.25rem;
+ }
+
+ a {
+ font-size: 1.2rem;
+ }
+ }
+
+ .visuals {
+ grid-area: visuals;
+
+ .shape {
+ --rotation: 45deg;
+
+ box-shadow: var(--box-shadow-normal);
+
+ overflow: hidden;
+
+ inline-size: 70%;
+ aspect-ratio: 1;
+
+ margin-inline: auto;
+
+ border-radius: 2rem;
+
+ transform: rotate(var(--rotation));
+
+ img {
+ block-size: 140%;
+ inline-size: 140%;
+ max-inline-size: unset;
+ object-fit: cover;
+
+ transform: translate(-15%, -15%)
+ rotate(calc(-1 * var(--rotation) + 0deg));
+ }
+ }
+ }
+}
+
+@media (width < 1000px) {
+ #intro {
+ grid-template-areas: 'visuals' 'writings';
+ grid-template-columns: 1fr;
+ justify-items: center;
+
+ padding-block: 4rem;
+
+ text-align: center;
+
+ .writings {
+ justify-items: center;
+
+ h1 {
+ max-inline-size: 20ch;
+ }
+
+ p {
+ max-inline-size: 50ch;
+ }
+ }
+
+ .visuals {
+ .shape {
+ max-inline-size: 20rem;
+ }
+ }
+ }
+}
diff --git a/src/styles/statistics.css b/src/styles/statistics.css
new file mode 100644
index 0000000..5f0712c
--- /dev/null
+++ b/src/styles/statistics.css
@@ -0,0 +1,40 @@
+#statistics {
+ display: grid;
+ align-items: center;
+ grid-template-columns: 1fr 1fr;
+ gap: 4rem;
+
+ padding-block: 4rem;
+ padding-inline: var(--page-padding-inline);
+
+ .visuals {
+ img {
+ max-block-size: 30rem;
+ inline-size: 100%;
+ }
+ }
+
+ .writings {
+ display: grid;
+ justify-items: start;
+ gap: 1rem;
+
+ p {
+ margin-block-end: 1rem;
+
+ max-inline-size: 60ch;
+ }
+ }
+}
+
+@media (width < 1000px) {
+ #statistics {
+ grid-template-columns: 1fr;
+
+ text-align: center;
+
+ .writings {
+ justify-items: center;
+ }
+ }
+}
diff --git a/src/styles/team.css b/src/styles/team.css
new file mode 100644
index 0000000..d420f25
--- /dev/null
+++ b/src/styles/team.css
@@ -0,0 +1,46 @@
+#team {
+ display: grid;
+ gap: 1rem;
+
+ padding-block: 4rem;
+ padding-inline: var(--page-padding-inline);
+
+ > p {
+ margin-block-end: 1rem;
+ }
+
+ > ul {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
+ gap: 2rem;
+
+ > li {
+ background-color: var(--color-gray-98);
+ box-shadow: var(--box-shadow-normal);
+
+ display: grid;
+ align-content: start;
+ justify-items: center;
+ gap: 1rem;
+
+ padding: 1rem;
+
+ border-radius: var(--border-radius);
+
+ text-align: center;
+
+ .writings {
+ .name {
+ font-size: 1.25rem;
+ font-weight: 700;
+
+ text-transform: capitalize;
+ }
+
+ p {
+ max-inline-size: 45ch;
+ }
+ }
+ }
+ }
+}