Repository: NoroffFEU/edu-gate-oct24ft
Pull request #21: Feature - Header  -#9
Author: login: larstp
Labels: name: html
description: All tasks regarding HTML implementation
name: css
description: All tasks regarding CSS implementation
name: JavaScript
description: All tasks regarding JavaScript implementation
Created: 2025-05-22T20:33:18Z | Merged: 2025-05-26T11:54:42Z

## Description

This pull request adds a header element that can be used on all pages.
Note that the Figma design prototype didn't link properly to everything so I have added things where it was missing.
I've tested it on 4 different screens including mobile and iPad, and it should work on everything but please give it a try.

Note: the mobile dropdown menu coming in from the right and covering the entire screen is deliberate, as it is how it is done in the Figma file (this confused me in the beginning). :)

## To test:

### Steps:

Open /public/index.html with live server.

Open DevTools (press F12 or right-click → Inspect).

Go to the Console tab.

Paste and run one of the following commands:

Log in as student: `localStorage.setItem('user', JSON.stringify({ username: 'student', role: 'student' }));`

Log in as teacher: `localStorage.setItem('user', JSON.stringify({ username: 'teacher', role: 'teacher' }));`

Log in as admin: `localStorage.setItem('user', JSON.stringify({ username: 'admin', role: 'admin' }));`

Refresh the page to see the header/menu update for that user type.

--

To log out: `localStorage.removeItem('user');`

Then refresh the page.



---

## Related Issue

Closes #9 

---

## Changes Made

- [X] Added Header for desktop and mobile
- [X] Added README in /components on how to insert
- [X] Matched all styling to figma design, including spacing, icon + text sizes etc. 
- [X] Finished header.js + header.html
- [X] Added styling for Header in components.css
- [X] Added media query for changing between desktop and mobile header in the media.css file.
- [X] Deleted deprecated CSS folder
- [X] Added JSON file in the /api folder to use as mockup

---

## Screenshots (if applicable)

![image](https://github.com/user-attachments/assets/168aa524-69fd-44b2-b84e-c312b9bd3d44)
---

## Acceptance Criteria


- [x] Changes have been tested locally (mobile + desktop)
- [x] Follows the style guide and naming conventions (e.g. kebab-case)
- [x] Matches design spec (e.g. from Figma)
- [x] No `console.log` or warnings
- [x] All images have `alt` text
- 
 [ ] Headings follow correct order (no skipping levels) 


Linked issue #9: Implement header(for desktop and mobile) and menu just for mobile version
Om desctop version:
![Image](https://github.com/user-attachments/assets/8b105cf9-0eef-4020-ad52-062ff9b51610)

![Image](https://github.com/user-attachments/assets/6188321d-631d-46e1-a0ff-07edfc5cd39b)


On mobile version 
![Image](https://github.com/user-attachments/assets/e8479a9e-e96d-498f-bf95-942d5b9126a3)

![Image](https://github.com/user-attachments/assets/a935c203-2b01-4754-81af-55dcbdaff05d)
 - Pages About and Contact should not be clickable because we don't have to do it

Create and implement a reusable header component based on the provided design.
Requirements:

- Display the Edugate School logo on the left side

- Include navigation links: "Dashboard", "About", and "Contact"

- Highlight the current active page (e.g. underlined "Dashboard")

- On the right side, display a user icon 

- The header must be responsive, maintaining proper layout on various screen sizes

- Ensure consistent font sizes, spacing, and hover states

- The header should be reusable across different pages (e.g. sign-up, dashboard)

Important:
On login and registration pages, the "Dashboard" link in the header should not be visible.

Diff:
diff --git a/css/base.css b/css/base.css
deleted file mode 100644
index c435d2d..0000000
--- a/css/base.css
+++ /dev/null
@@ -1,92 +0,0 @@
-:root {
-  --text-color: #333333;
-  --bg-color: #ffffff;
-  --link-hover-color: #0070f3;
-
-  --max-width: 1200px;
-}
-
-*,
-*::before,
-*::after {
-  box-sizing: border-box;
-  margin: 0;
-  padding: 0;
-}
-
-html {
-  font-size: 16px;
-  scroll-behavior: smooth;
-  -webkit-font-smoothing: antialiased;
-}
-
-body {
-  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
-  line-height: 1.6;
-  color: var(--text-color);
-  background-color: var(--bg-color);
-}
-
-a {
-  text-decoration: none;
-  color: inherit;
-}
-
-a:hover {
-  color: var(--link-hover-color);
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
-  font-weight: 600;
-  line-height: 1.25;
-  margin-bottom: 0.5em;
-}
-
-img {
-  max-width: 100%;
-  height: auto;
-  display: block;
-}
-
-ul,
-ol {
-  list-style: none;
-}
-
-button {
-  font-family: inherit;
-  cursor: pointer;
-  border: none;
-  background: none;
-}
-
-input,
-textarea,
-select,
-button {
-  font-family: inherit;
-  font-size: 1rem;
-  outline: none;
-}
-
-.container {
-  width: 90%;
-  max-width: var(--max-width);
-  margin: 0 auto;
-}
-
-.sr-only {
-  position: absolute;
-  width: 1px;
-  height: 1px;
-  margin: -1px;
-  padding: 0;
-  overflow: hidden;
-  clip: rect(0, 0, 0, 0);
-  border: 0;
-}
diff --git a/public/index.html b/public/index.html
index e69de29..174b1c1 100644
--- a/public/index.html
+++ b/public/index.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta name="description" content="Edu-gate landing page" />
+    <title>Edu-gate | Home</title>
+    <link rel="stylesheet" href="../src/css/style.css" />
+    <link rel="stylesheet" href="../src/css/components.css" />
+    <link rel="stylesheet" href="../src/css/media.css" />
+    <script src="../src/script/utils/header.js" defer></script>
+    <script src="../src/script/utils/footer.js" defer></script>
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
+      rel="stylesheet"
+    />
+  </head>
+  <body>
+    <header class="header-mobile"></header>
+    <header class="header-desktop"></header>
+    <main></main>
+  </body>
+</html>
diff --git a/src/components/README.md b/src/components/README.md
new file mode 100644
index 0000000..be774c5
--- /dev/null
+++ b/src/components/README.md
@@ -0,0 +1,7 @@
+## Component usage:
+
+### Header
+
+Insert the given code at the top of the <body> element. All other code will be handled by the header.js file in /src/script/utils.
+
+### Navbar usage:
diff --git a/src/components/footer.html b/src/components/footer.html
new file mode 100644
index 0000000..17d2a59
--- /dev/null
+++ b/src/components/footer.html
@@ -0,0 +1,4 @@
+/* Insert this at the bottom of the page after main. Everything else is made in
+JS */
+
+<footer class="footer-circles"></footer>
diff --git a/src/components/hamburger-menu.html b/src/components/hamburger-menu.html
deleted file mode 100644
index e69de29..0000000
diff --git a/src/components/header.html b/src/components/header.html
index e69de29..cae668f 100644
--- a/src/components/header.html
+++ b/src/components/header.html
@@ -0,0 +1,5 @@
+/* Insert this at the top of the page before main. Everything else is made in JS
+*/
+
+<header class="header-mobile"></header>
+<header class="header-desktop"></header>
diff --git a/src/components/navbar.html b/src/components/navbar.html
new file mode 100644
index 0000000..619bca3
--- /dev/null
+++ b/src/components/navbar.html
@@ -0,0 +1 @@
+/* This refers to the side navbar */
diff --git a/src/css/about.css b/src/css/about.css
new file mode 100644
index 0000000..c33cf16
--- /dev/null
+++ b/src/css/about.css
@@ -0,0 +1,36 @@
+/* About Page. This will be merged with style.css after testing, or kept as is*/
+
+.about-hero {
+  display: flex;
+  flex-direction: column;
+  max-width: 560px;
+  margin: auto;
+  padding-top: 115px;
+}
+
+.about-hero h1 {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 32px;
+  line-height: 1.5;
+  margin: auto;
+}
+
+.about-text {
+  font-family: 'Roboto', sans-serif;
+  font-weight: 400;
+  font-size: 14px;
+  line-height: 1.2;
+  margin: auto;
+  padding: 40px;
+  max-width: 560px;
+}
+
+.about-btns {
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: center;
+  gap: 2rem;
+  margin: auto;
+}
diff --git a/src/css/components.css b/src/css/components.css
index e69de29..f1c4915 100644
--- a/src/css/components.css
+++ b/src/css/components.css
@@ -0,0 +1,266 @@
+/* --------------------  Global Header ------------------- */
+
+.header-desktop {
+  display: none;
+}
+
+.desktop-nav {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.nav-links {
+  display: flex;
+  align-items: center;
+}
+
+.mobile-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  background: #fff;
+  border-bottom: 1px solid #eee;
+  height: 70px;
+}
+
+.header-logo {
+  height: 60px;
+}
+
+.nav-links li {
+  position: relative;
+  border-bottom: 3px solid transparent;
+  box-sizing: border-box;
+  transition: border-color 0.2s;
+}
+
+.nav-links li:hover::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: #4caf50;
+  border-radius: 2px;
+}
+
+.nav-links a {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 20px;
+  line-height: 1.2;
+  letter-spacing: 0.03em;
+}
+
+.current {
+  border-bottom: 3px solid #4caf50 !important;
+}
+
+.current a {
+  font-weight: 700;
+}
+
+/* ---------------  Hamburger-menu  --------------------- */
+
+.hamburger,
+.close-dropdown {
+  font-size: 2rem;
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.menu-icon,
+.hamburger-icon,
+.close-icon {
+  object-fit: contain;
+  pointer-events: none;
+}
+
+.menu-icon {
+  width: 32px;
+  margin-left: 8px;
+  vertical-align: middle;
+}
+
+.hamburger-icon {
+  width: 25px;
+  height: 24px;
+}
+
+.close-icon {
+  width: 24px;
+  height: 24px;
+}
+
+.dropdown-logo {
+  height: 60px;
+}
+
+.mobile-dropdown {
+  position: fixed;
+  top: 0;
+  right: 0;
+  width: 100vw;
+  height: 100vh;
+  background: rgba(0, 0, 0, 0.5);
+  z-index: 1000;
+  display: flex;
+  flex-direction: column;
+  align-items: flex-end;
+  justify-content: flex-start;
+  padding: 0;
+  transition: transform 0.3s ease;
+  transform: translateX(100%);
+}
+
+.logout-link {
+  border-top: 1px solid #eee;
+}
+
+.dropdown-spacer {
+  height: 32px;
+  background: transparent;
+  border: none;
+  padding: 0;
+  margin: 0;
+}
+
+.dropdown-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+  background: #f5f5f5;
+  border-bottom: 1px solid #eee;
+  box-sizing: border-box;
+  padding: 14px 16px 8px 16px;
+  height: 83px;
+}
+
+.mobile-dropdown .dropdown-panel {
+  background: #fff;
+  width: 100%;
+  height: 100vh;
+  padding: 0px;
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+}
+
+.mobile-dropdown.open {
+  transform: translateX(0);
+}
+
+.mobile-dropdown {
+  overflow: hidden;
+}
+
+.dropdown-links {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+  width: 100%;
+}
+
+.dropdown-links li {
+  padding: 32px 16px;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.dropdown-links a {
+  text-decoration: none;
+  color: #000000;
+  font-family: 'Poppins', sans-serif;
+  font-weight: 400;
+  font-size: 20px;
+  line-height: 7%;
+  letter-spacing: 0.03em;
+}
+
+/* -------------  Nav-bar  --------------- */
+
+/*-------------- Global Footer ---------------*/
+
+.footer-desktop {
+  display: none;
+}
+
+.footer-desktop,
+.footer-mobile {
+  margin-top: 80px;
+  width: 100%;
+  text-align: right;
+}
+
+.footer-mobile {
+  position: static;
+  text-align: right;
+  width: 100%;
+}
+
+.footer-img {
+  max-width: 100%;
+  height: auto;
+  display: inline-block;
+  margin-right: 0;
+  margin-bottom: 0;
+  padding: 0;
+  vertical-align: bottom;
+}
+
+/*---------------- CTA buttons -----------------*/
+
+.btn {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 6px;
+  padding: 10px 20px;
+  width: 110px;
+  height: 44px;
+  font-size: 16px;
+  font-family: 'Roboto', sans-serif;
+  font-weight: 600;
+  text-align: center;
+  letter-spacing: 0.02em;
+  text-decoration: none;
+  box-sizing: border-box;
+  transition: background 0.2s;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #4caf50;
+  border: none;
+}
+
+.btn-primary:hover {
+  background-color: #388e3c;
+}
+
+.btn-secondary {
+  color: #2196f3;
+  background: #fff;
+  border: 2px solid #2196f3;
+}
+.btn-secondary:hover {
+  background-color: #2196f3;
+  color: #fff;
+}
+
+.btn-alert {
+  color: #ff5722;
+  background: #fff;
+  border: none;
+}
+
+.btn-alert:hover {
+  background-color: #e64a19;
+  color: #fff;
+}
diff --git a/src/css/media.css b/src/css/media.css
new file mode 100644
index 0000000..3876b77
--- /dev/null
+++ b/src/css/media.css
@@ -0,0 +1,82 @@
+@media (min-width: 600px) {
+}
+
+@media (min-width: 900px) {
+  main {
+    min-height: calc(100vh - 80px - 246px);
+  }
+
+  .header-mobile {
+    display: none;
+  }
+
+  .header-logo {
+    height: 176px;
+    padding-left: 48px;
+  }
+
+  .header-desktop {
+    display: block;
+    height: 176px;
+    width: 100%;
+  }
+
+  .desktop-nav {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 2rem;
+    width: 100%;
+  }
+
+  .nav-links {
+    display: flex;
+    align-items: center;
+    gap: 2rem;
+    margin: 0;
+    padding: 0px 70px 0px 0px;
+  }
+
+  .nav-links li {
+    display: flex;
+    height: 74px;
+    width: 248px;
+    align-items: center;
+    list-style: none;
+  }
+
+  .nav-links a {
+    text-decoration: none;
+    color: black;
+    margin: auto;
+  }
+
+  .footer-desktop {
+    display: block;
+    position: static;
+    text-align: right;
+    width: 100%;
+  }
+
+  .footer-mobile {
+    display: none;
+  }
+
+  .footer-img {
+    display: flex;
+    max-width: 100%;
+    height: auto;
+    margin: auto;
+    vertical-align: bottom;
+  }
+
+  .btn {
+    width: 150px;
+    height: 58px;
+    font-size: 26px;
+  }
+
+  .about-btns {
+    flex-direction: row;
+  }
+}
diff --git a/src/css/style.css b/src/css/style.css
index e69de29..9a4031a 100644
--- a/src/css/style.css
+++ b/src/css/style.css
@@ -0,0 +1,15 @@
+html,
+body {
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+
+body {
+  min-height: 100vh;
+  position: relative;
+}
+
+main {
+  min-height: calc(100vh - 80px - 209px);
+}
diff --git a/src/css/tailwind.css b/src/css/tailwind.css
deleted file mode 100644
index e69de29..0000000
diff --git a/src/index.mjs b/src/index.mjs
index ee9a9be..b481a90 100644
--- a/src/index.mjs
+++ b/src/index.mjs
@@ -7,7 +7,7 @@ const params = {
   root: '.', // Set root directory that's being served. Defaults to cwd.
   open: false, // When false, it won't load your browser by default.
   ignore: 'scss,my/templates', // comma-separated string for paths to ignore
-  file: 'templates/index.html', // When set, serve this file (server root relative) for every 404 (useful for single-page applications)
+  file: 'public/index.html', // When set, serve this file (server root relative) for every 404 (useful for single-page applications)
   wait: 1000, // Waits for all changes, before reloading. Defaults to 0 sec.
   // mount: ['/templates'], // Mount a directory to a route.
   logLevel: 2, // 0 = errors only, 1 = some, 2 = lots
diff --git a/src/pages/about.html b/src/pages/about.html
new file mode 100644
index 0000000..2afa99f
--- /dev/null
+++ b/src/pages/about.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta name="description" content="Edu-gate about page" />
+    <title>Edu-gate | About</title>
+    <link rel="stylesheet" href="../css/style.css" />
+    <link rel="stylesheet" href="../css/components.css" />
+    <link rel="stylesheet" href="../css/about.css" />
+    <link rel="stylesheet" href="../css/media.css" />
+    <script src="../script/utils/header.js" defer></script>
+    <script src="../script/utils/footer.js" defer></script>
+    <script src="../script/about.js" defer></script>
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
+      rel="stylesheet"
+    />
+  </head>
+  <body>
+    <header class="header-mobile"></header>
+    <header class="header-desktop"></header>
+    <main class="about-main"></main>
+  </body>
+</html>
diff --git a/src/pages/contact.html b/src/pages/contact.html
new file mode 100644
index 0000000..01667bc
--- /dev/null
+++ b/src/pages/contact.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta name="description" content="Edu-gate contact page" />
+    <title>Edu-gate | Contact</title>
+    <link rel="stylesheet" href="../css/style.css" />
+    <link rel="stylesheet" href="../css/components.css" />
+    <link rel="stylesheet" href="../css/contact.css" />
+    <link rel="stylesheet" href="../css/media.css" />
+    <script src="../script/utils/header.js" defer></script>
+    <script src="../script/utils/footer.js" defer></script>
+    <script src="../script/contact.js" defer></script>
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
+      rel="stylesheet"
+    />
+  </head>
+  <body>
+    <header class="header-mobile"></header>
+    <header class="header-desktop"></header>
+    <main class="contact-main"></main>
+  </body>
+</html>
diff --git a/src/pages/dashboard-student.html b/src/pages/dashboard-student.html
index e69de29..0522694 100644
--- a/src/pages/dashboard-student.html
+++ b/src/pages/dashboard-student.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta name="description" content="Edu-gate student dashboard" />
+    <title>Edu-gate | Dashboard</title>
+    <link rel="stylesheet" href="/src/css/style.css" />
+    <link rel="stylesheet" href="/src/css/components.css" />
+    <link rel="stylesheet" href="/src/css/media.css" />
+    <script src="/src/script/utils/header.js" defer></script>
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap"
+      rel="stylesheet"
+    />
+  </head>
+  <body>
+    <header class="header-mobile"></header>
+    <header class="header-desktop"></header>
+  </body>
+</html>
diff --git a/src/script/about.js b/src/script/about.js
new file mode 100644
index 0000000..bdfc192
--- /dev/null
+++ b/src/script/about.js
@@ -0,0 +1,46 @@
+document.addEventListener('DOMContentLoaded', function () {
+  const aboutMain = document.querySelector('.about-main');
+  if (!aboutMain) return;
+
+  const aboutHero = document.createElement('section');
+  aboutHero.className = 'about-hero';
+
+  const h1 = document.createElement('h1');
+  h1.textContent = 'About';
+
+  const aboutText = document.createElement('section');
+  aboutText.className = 'about-text';
+
+  const p1 = document.createElement('p');
+  p1.textContent =
+    'Edugate was built to provide students with an easier way to access their exam results.';
+
+  const p2 = document.createElement('p');
+  p2.textContent =
+    'Schools can sign up, quickly register their students & create private accounts for them to access their results.';
+
+  aboutText.appendChild(p1);
+  aboutText.appendChild(p2);
+
+  const aboutBtns = document.createElement('section');
+  aboutBtns.className = 'about-btns';
+
+  const signUpBtn = document.createElement('a');
+  signUpBtn.href = '../pages/sign-up.html';
+  signUpBtn.className = 'btn btn-primary';
+  signUpBtn.textContent = 'Sign Up';
+
+  const logInBtn = document.createElement('a');
+  logInBtn.href = '../pages/log-in.html';
+  logInBtn.className = 'btn btn-secondary';
+  logInBtn.textContent = 'Log In';
+
+  aboutBtns.appendChild(signUpBtn);
+  aboutBtns.appendChild(logInBtn);
+
+  aboutHero.appendChild(h1);
+  aboutHero.appendChild(aboutText);
+  aboutHero.appendChild(aboutBtns);
+
+  aboutMain.appendChild(aboutHero);
+});
diff --git a/src/script/api/README.md b/src/script/api/README.md
new file mode 100644
index 0000000..542f023
--- /dev/null
+++ b/src/script/api/README.md
@@ -0,0 +1,41 @@
+# Usage of mockup JSON file
+
+## This mock login setup is only for local development and testing.
+
+## Do not use this code for real authentication or production use.
+
+### HTML example:
+
+<form id="loginForm">
+  <input type="text" id="username" placeholder="Username" required />
+  <input type="password" id="password" placeholder="Password" required />
+  <button type="submit">Log In</button>
+  <div id="loginError" style="color:red;"></div>
+</form>
+
+### JavaScript example:
+
+document.getElementById('loginForm').addEventListener('submit', function(e) {
+e.preventDefault();
+
+const username = document.getElementById('username').value.trim();
+const password = document.getElementById('password').value.trim();
+const errorDiv = document.getElementById('loginError');
+
+fetch('/src/script/api/user.json')
+.then(res => res.json())
+.then(users => {
+const user = users.find(
+u => u.username === username && u.password === password
+);
+if (user) {
+localStorage.setItem('user', JSON.stringify(user));
+window.location.href = '/src/pages/dashboard-' + user.role + '.html';
+} else {
+errorDiv.textContent = 'Invalid username or password';
+}
+})
+.catch(() => {
+errorDiv.textContent = 'Could not load user data.';
+});
+});
diff --git a/src/script/api/user.json b/src/script/api/user.json
new file mode 100644
index 0000000..bf6dd4f
--- /dev/null
+++ b/src/script/api/user.json
@@ -0,0 +1,5 @@
+[
+  { "username": "student", "password": "student123", "role": "student" },
+  { "username": "admin", "password": "admin123", "role": "admin" },
+  { "username": "teacher", "password": "teacher123", "role": "teacher" }
+]
diff --git a/css/index.css b/src/script/contact.js
similarity index 100%
rename from css/index.css
rename to src/script/contact.js
diff --git a/src/script/utils/footer.js b/src/script/utils/footer.js
new file mode 100644
index 0000000..8dfff48
--- /dev/null
+++ b/src/script/utils/footer.js
@@ -0,0 +1,22 @@
+const desktopFooter = document.createElement('footer');
+desktopFooter.className = 'footer-desktop';
+
+const desktopImg = document.createElement('img');
+desktopImg.src = '/public/assets/img/circle-footer.png';
+desktopImg.alt = 'Footer illustration desktop';
+desktopImg.className = 'footer-img';
+
+desktopFooter.appendChild(desktopImg);
+
+const mobileFooter = document.createElement('footer');
+mobileFooter.className = 'footer-mobile';
+
+const mobileImg = document.createElement('img');
+mobileImg.src = '/public/assets/img/Circles_illustration_mobile.png';
+mobileImg.alt = 'Footer illustration mobile';
+mobileImg.className = 'footer-img';
+
+mobileFooter.appendChild(mobileImg);
+
+document.body.appendChild(desktopFooter);
+document.body.appendChild(mobileFooter);
diff --git a/src/script/utils/header.js b/src/script/utils/header.js
new file mode 100644
index 0000000..2530093
--- /dev/null
+++ b/src/script/utils/header.js
@@ -0,0 +1,325 @@
+const desktopHeader = document.querySelector('.header-desktop');
+
+if (desktopHeader) {
+  const nav = document.createElement('nav');
+  nav.className = 'desktop-nav';
+
+  const logoLink = document.createElement('a');
+  logoLink.href = '/public/index.html';
+
+  const logo = document.createElement('img');
+  logo.src = '/public/assets/img/logo-header.png';
+  logo.alt = 'Edu-gate Logo';
+  logo.className = 'header-logo';
+
+  logoLink.appendChild(logo);
+
+  const ul = document.createElement('ul');
+  ul.className = 'nav-links';
+
+  const user = JSON.parse(localStorage.getItem('user'));
+
+  const excludedPages = [
+    '/public/index.html',
+    '/src/pages/log-in.html',
+    '/src/pages/register.html',
+    '/src/pages/sign-up.html',
+  ];
+  const currentPath = window.location.pathname;
+
+  const navLinks = [];
+  if (user && !excludedPages.includes(currentPath)) {
+    navLinks.push({
+      text: 'Dashboard',
+      href: '/src/pages/dashboard-student.html',
+    });
+  }
+  navLinks.push(
+    { text: 'About', href: '/src/pages/about.html' },
+    { text: 'Contact', href: '/src/pages/contact.html' }
+  );
+
+  if (user && !excludedPages.includes(currentPath)) {
+    navLinks.push({
+      icon: '/public/assets/icons/user-circle.png',
+      href: '#edit-profile',
+      isProfile: true,
+      alt: 'Edit profile icon',
+    });
+  }
+
+  navLinks.forEach((link) => {
+    const li = document.createElement('li');
+    if (currentPath.endsWith(link.href)) {
+      li.classList.add('current');
+    }
+    const a = document.createElement('a');
+    a.href = link.href;
+    if (link.isProfile) {
+      const img = document.createElement('img');
+      img.src = link.icon;
+      img.alt = link.alt || 'Profile icon';
+      img.style.width = '64px';
+      img.style.height = '64px';
+      img.style.verticalAlign = 'middle';
+      a.appendChild(img);
+    } else {
+      a.textContent = link.text;
+    }
+    li.appendChild(a);
+    ul.appendChild(li);
+  });
+
+  nav.appendChild(logoLink);
+  nav.appendChild(ul);
+
+  desktopHeader.appendChild(nav);
+}
+
+const mobileHeader = document.querySelector('.header-mobile');
+
+if (mobileHeader) {
+  const mobileNav = document.createElement('nav');
+  mobileNav.className = 'mobile-nav';
+
+  const logoLink = document.createElement('a');
+  logoLink.href = '/public/index.html';
+
+  const logo = document.createElement('img');
+  logo.src = '/public/assets/img/logo-header-cropped.png';
+  logo.alt = 'Edu-gate Logo';
+  logo.className = 'header-logo';
+
+  logoLink.appendChild(logo);
+
+  const hamburger = document.createElement('button');
+  hamburger.className = 'hamburger';
+  hamburger.setAttribute('aria-label', 'Open menu');
+
+  const hamburgerIcon = document.createElement('img');
+  hamburgerIcon.src = '/public/assets/icons/hamburger-menu.png';
+  hamburgerIcon.alt = 'Open menu icon';
+  hamburgerIcon.className = 'hamburger-icon';
+
+  hamburger.appendChild(hamburgerIcon);
+
+  const dropdown = document.createElement('div');
+  dropdown.className = 'mobile-dropdown';
+
+  const closeBtn = document.createElement('button');
+  closeBtn.className = 'close-dropdown';
+  closeBtn.setAttribute('aria-label', 'Close menu');
+
+  const closeIcon = document.createElement('img');
+  closeIcon.src = '/public/assets/icons/x-close(1).jpg';
+  closeIcon.alt = 'Close menu icon';
+  closeIcon.className = 'close-icon';
+
+  closeBtn.appendChild(closeIcon);
+
+  const menuList = document.createElement('ul');
+  menuList.className = 'dropdown-links';
+
+  const user = JSON.parse(localStorage.getItem('user'));
+  let links = [];
+
+  if (user && user.role === 'student') {
+    links = [
+      {
+        text: 'Dashboard',
+        href: '/src/pages/dashboard-student.html',
+        icon: '/public/assets/icons/dashboard.png',
+        alt: 'Dashboard icon',
+      },
+      {
+        text: 'Profile',
+        href: '#edit-profile',
+        icon: '/public/assets/icons/user-circle.png',
+        alt: 'Profile icon',
+      },
+      {
+        text: 'About',
+        href: '/src/pages/about.html',
+        icon: '/public/assets/icons/about.png',
+        alt: 'About icon',
+      },
+      {
+        text: 'Contact',
+        href: '/src/pages/contact.html',
+        icon: '/public/assets/icons/contact.png',
+        alt: 'Contact icon',
+      },
+    ];
+  } else if (user && user.role === 'admin') {
+    links = [
+      {
+        text: 'Dashboard',
+        href: '/src/pages/dashboard-admin.html',
+        icon: '/public/assets/icons/dashboard.png',
+        alt: 'Dashboard icon',
+      },
+      {
+        text: 'Profile',
+        href: '#edit-profile',
+        icon: '/public/assets/icons/user-circle.png',
+        alt: 'Profile icon',
+      },
+      {
+        text: 'Manage user',
+        href: '/src/pages/user-management.html',
+        icon: '/public/assets/icons/user-management.png',
+        alt: 'Manage user icon',
+      },
+      {
+        text: 'About',
+        href: '/src/pages/about.html',
+        icon: '/public/assets/icons/about.png',
+        alt: 'About icon',
+      },
+      {
+        text: 'Contact',
+        href: '/src/pages/contact.html',
+        icon: '/public/assets/icons/contact.png',
+        alt: 'Contact icon',
+      },
+    ];
+  } else if (user && user.role === 'teacher') {
+    links = [
+      {
+        text: 'Dashboard',
+        href: '/src/pages/dashboard-teacher.html',
+        icon: '/public/assets/icons/dashboard.png',
+        alt: 'Dashboard icon',
+      },
+      {
+        text: 'Profile',
+        href: '#edit-profile',
+        icon: '/public/assets/icons/user-circle.png',
+        alt: 'Profile icon',
+      },
+      {
+        text: 'Manage results',
+        href: '/src/pages/manage-results.html',
+        icon: '/public/assets/icons/results.png',
+        alt: 'Manage results icon',
+      },
+      {
+        text: 'About',
+        href: '/src/pages/about.html',
+        icon: '/public/assets/icons/about.png',
+        alt: 'About icon',
+      },
+      {
+        text: 'Contact',
+        href: '/src/pages/contact.html',
+        icon: '/public/assets/icons/contact.png',
+        alt: 'Contact icon',
+      },
+    ];
+  } else {
+    links = [
+      {
+        text: 'Login',
+        href: '/src/pages/log-in.html',
+        icon: '/public/assets/icons/login.png',
+        alt: 'Login icon',
+      },
+      {
+        text: 'Signup',
+        href: '/src/pages/sign-up.html',
+        icon: '/public/assets/icons/signup.png',
+        alt: 'Signup icon',
+      },
+      {
+        text: 'About',
+        href: '/src/pages/about.html',
+        icon: '/public/assets/icons/about.png',
+        alt: 'About icon',
+      },
+      {
+        text: 'Contact',
+        href: '/src/pages/contact.html',
+        icon: '/public/assets/icons/contact.png',
+        alt: 'Contact icon',
+      },
+    ];
+  }
+
+  links.forEach((link) => {
+    const li = document.createElement('li');
+    const a = document.createElement('a');
+    a.href = link.href;
+    a.textContent = link.text;
+
+    const icon = document.createElement('img');
+    icon.src = link.icon;
+    icon.alt = link.alt || `${link.text} icon`;
+    icon.className = 'menu-icon';
+
+    li.appendChild(a);
+    li.appendChild(icon);
+    menuList.appendChild(li);
+  });
+
+  const panel = document.createElement('div');
+  panel.className = 'dropdown-panel';
+
+  const dropdownHeader = document.createElement('div');
+  dropdownHeader.className = 'dropdown-header';
+
+  const dropdownLogo = document.createElement('img');
+  dropdownLogo.src = '/public/assets/img/logo-header-cropped.png';
+  dropdownLogo.alt = 'Edu-gate Logo';
+  dropdownLogo.className = 'dropdown-logo';
+
+  dropdownHeader.appendChild(dropdownLogo);
+  dropdownHeader.appendChild(closeBtn);
+
+  panel.appendChild(dropdownHeader);
+  panel.appendChild(menuList);
+  dropdown.appendChild(panel);
+
+  if (user) {
+    const spacerLi = document.createElement('li');
+    spacerLi.className = 'dropdown-spacer';
+    spacerLi.style.pointerEvents = 'none';
+    menuList.appendChild(spacerLi);
+
+    const logoutLi = document.createElement('li');
+    logoutLi.style.cursor = 'pointer';
+    logoutLi.classList.add('logout-link');
+
+    const logoutA = document.createElement('a');
+    logoutA.href = '#logout';
+    logoutA.textContent = 'Log out';
+
+    const logoutIcon = document.createElement('img');
+    logoutIcon.src = '/public/assets/icons/logout.png';
+    logoutIcon.alt = 'Log out icon';
+    logoutIcon.className = 'menu-icon';
+
+    logoutA.appendChild(logoutIcon);
+    logoutLi.appendChild(logoutA);
+
+    logoutLi.addEventListener('click', (e) => {
+      e.preventDefault();
+      localStorage.removeItem('user');
+      window.location.reload();
+    });
+
+    menuList.appendChild(logoutLi);
+  }
+
+  mobileNav.appendChild(logoLink);
+  mobileNav.appendChild(hamburger);
+  mobileHeader.appendChild(mobileNav);
+  mobileHeader.appendChild(dropdown);
+
+  hamburger.addEventListener('click', () => {
+    dropdown.classList.add('open');
+  });
+
+  closeBtn.addEventListener('click', () => {
+    dropdown.classList.remove('open');
+  });
+}
diff --git a/src/script/navbar.js b/src/script/utils/navbar.js
similarity index 100%
rename from src/script/navbar.js
rename to src/script/utils/navbar.js
diff --git a/templates/index.html b/templates/index.html
deleted file mode 100644
index a312eb8..0000000
--- a/templates/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!doctype html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Landing page Edugate</title>
-  </head>
-  <body>
-    <div class="container">
-      <h1>Welcome to the Edugate Landing Page</h1>
-    </div>
-  </body>
-</html>


Reviews:
user: login: emmelinlarina
body: ### Superb! 
Wow! It looks very clean!! Almost everything is superDRY:D I've marked some very minor things. 
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:21:16Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:29:19Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:32:25Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:36:33Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:44:09Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:44:16Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:45:18Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:48:35Z
user: login: larstp
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T13:50:24Z
user: login: emmelinlarina
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-23T14:00:55Z

Review comments:
path: src/pages/about.html
user: login: emmelinlarina
body: This file is missing the font you imported to `<index.html>`. Maybe move the font import to the global css? Or add it here for now
created_at: 2025-05-23T12:10:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,189 @@
+/* --------------------  Global Header ------------------- */
+
+.header-desktop {
+  display: none;
+}
+
+.desktop-nav {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.nav-links {
+  display: flex;
+  align-items: center;
+}
+
+.mobile-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  background: #fff;
+  border-bottom: 1px solid #eee;
+  height: 70px;
+}
+
+.header-logo {
+  height: 60px;
+}
+
+.nav-links li {
+  position: relative;
+  border-bottom: 3px solid transparent;
+  box-sizing: border-box;
+  transition: border-color 0.2s;
+}
+
+.nav-links li:hover::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: #4caf50;
+  border-radius: 2px;
+}
+
+.nav-links a {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 20px;
+  line-height: 7%;
path: src/css/components.css
user: login: emmelinlarina
body: The 7% line-height might cause weird spacing. Maybe change it to 1.2 - 1.4?
created_at: 2025-05-23T12:12:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,189 @@
+/* --------------------  Global Header ------------------- */
+
+.header-desktop {
+  display: none;
+}
+
+.desktop-nav {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.nav-links {
+  display: flex;
+  align-items: center;
+}
+
+.mobile-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  background: #fff;
+  border-bottom: 1px solid #eee;
+  height: 70px;
+}
+
+.header-logo {
+  height: 60px;
+}
+
+.nav-links li {
+  position: relative;
+  border-bottom: 3px solid transparent;
+  box-sizing: border-box;
+  transition: border-color 0.2s;
+}
+
+.nav-links li:hover::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: #4caf50;
+  border-radius: 2px;
+}
+
+.nav-links a {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 20px;
+  line-height: 7%;
+  letter-spacing: 0.03em;
+}
+
+.current {
+  border-bottom: 3px solid #4caf50 !important;
+}
+
+.current a {
+  font-weight: 700;
+}
+
+/* ---------------  Hamburger-menu  --------------------- */
+
+.hamburger {
+  font-size: 2rem;
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.hamburger-icon {
+  width: 25px;
+  height: 24px;
+  object-fit: contain;
+  pointer-events: none;
+}
+
+.close-icon {
+  width: 24px;
+  height: 24px;
+  object-fit: contain;
+  pointer-events: none;
+}
+
+.close-dropdown {
path: src/css/components.css
user: login: emmelinlarina
body: .hamburger and .close-dropdown could be together, since they both have the same style (to DRY it up)
created_at: 2025-05-23T12:13:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,49 @@
+@media (min-width: 600px) {
+}
+
+@media (min-width: 900px) {
+  .header-mobile {
+    display: none;
+  }
+
+  .header-logo {
+    height: 176px;
+    padding-left: 48px;
+  }
+
+  .header-desktop {
+    display: block;
+    height: 176px;
+    width: 100%;
+  }
+
+  .desktop-nav {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 2rem;
+    width: 100%;
+  }
+
+  .nav-links {
+    display: flex;
+    align-items: center;
+    gap: 2rem;
+    margin: 0;
+    padding: 0px 70px 0px 0px;
+  }
+
+  .nav-links li {
+    display: flex;
+    height: 74px;
+    width: 248px;
+    align-items: center;
+  }
+
+  .nav-links a {
+    list-style: none;
path: src/css/media.css
user: login: emmelinlarina
body: list-style can go in .nav-links `<li>`, since its not doing anything on the `<a>`
created_at: 2025-05-23T12:13:32Z
author_association: CONTRIBUTOR
path: src/pages/contact.html
user: login: emmelinlarina
body: This file is also missing the font you imported to <index.html>. Maybe move the font import to the global css? Or add it here for now
created_at: 2025-05-23T12:14:52Z
author_association: CONTRIBUTOR
path: src/script/api/README.md
user: login: emmelinlarina
body: Add this under Usage of mockup JSON file in readme: 

This mock login setup is only for local development and testing.
Do **not** use this code for real authentication or production use.
created_at: 2025-05-23T12:24:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,320 @@
+const desktopHeader = document.querySelector('.header-desktop');
+
+if (desktopHeader) {
+  const nav = document.createElement('nav');
+  nav.className = 'desktop-nav';
+
+  const logoLink = document.createElement('a');
+  logoLink.href = '/public/index.html';
+
+  const logo = document.createElement('img');
+  logo.src = '/public/assets/img/logo-header.png';
path: src/script/utils/header.js
user: login: emmelinlarina
body: Absolute paths like `</public/assets/...>` might cause issues in production, depending on how the site is hosted. It works fine for now, but something to keep in mind later. 
created_at: 2025-05-23T12:30:09Z
author_association: CONTRIBUTOR
path: src/script/utils/header.js
user: login: emmelinlarina
body: This is looking very good! Although there might be some repetition which makes the code longer, but at long as the code works I don't think its a problem for now. Unless you want to go over it some time later. :D 
created_at: 2025-05-23T12:55:58Z
author_association: CONTRIBUTOR
path: src/css/components.css
user: login: emmelinlarina
body: Very good! Looking clean and DRY! I just have to minor things for you to look at:D 
created_at: 2025-05-23T12:57:09Z
author_association: CONTRIBUTOR
path: src/css/media.css
user: login: emmelinlarina
body: Superb!
created_at: 2025-05-23T12:57:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,189 @@
+/* --------------------  Global Header ------------------- */
+
+.header-desktop {
+  display: none;
+}
+
+.desktop-nav {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.nav-links {
+  display: flex;
+  align-items: center;
+}
+
+.mobile-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  background: #fff;
+  border-bottom: 1px solid #eee;
+  height: 70px;
+}
+
+.header-logo {
+  height: 60px;
+}
+
+.nav-links li {
+  position: relative;
+  border-bottom: 3px solid transparent;
+  box-sizing: border-box;
+  transition: border-color 0.2s;
+}
+
+.nav-links li:hover::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: #4caf50;
+  border-radius: 2px;
+}
+
+.nav-links a {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 20px;
+  line-height: 7%;
path: src/css/components.css
user: login: larstp
body: You're right! I followed the Figma board but 7% does cause some problems. Changed to 1.2 
created_at: 2025-05-23T13:29:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,189 @@
+/* --------------------  Global Header ------------------- */
+
+.header-desktop {
+  display: none;
+}
+
+.desktop-nav {
+  display: flex;
+  justify-content: space-around;
+  align-items: center;
+}
+
+.nav-links {
+  display: flex;
+  align-items: center;
+}
+
+.mobile-nav {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0.5rem 1rem;
+  background: #fff;
+  border-bottom: 1px solid #eee;
+  height: 70px;
+}
+
+.header-logo {
+  height: 60px;
+}
+
+.nav-links li {
+  position: relative;
+  border-bottom: 3px solid transparent;
+  box-sizing: border-box;
+  transition: border-color 0.2s;
+}
+
+.nav-links li:hover::after {
+  content: '';
+  position: absolute;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  height: 1px;
+  background: #4caf50;
+  border-radius: 2px;
+}
+
+.nav-links a {
+  font-family: 'Poppins', sans-serif;
+  font-weight: 600;
+  font-size: 20px;
+  line-height: 7%;
+  letter-spacing: 0.03em;
+}
+
+.current {
+  border-bottom: 3px solid #4caf50 !important;
+}
+
+.current a {
+  font-weight: 700;
+}
+
+/* ---------------  Hamburger-menu  --------------------- */
+
+.hamburger {
+  font-size: 2rem;
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.hamburger-icon {
+  width: 25px;
+  height: 24px;
+  object-fit: contain;
+  pointer-events: none;
+}
+
+.close-icon {
+  width: 24px;
+  height: 24px;
+  object-fit: contain;
+  pointer-events: none;
+}
+
+.close-dropdown {
path: src/css/components.css
user: login: larstp
body: I'm blind. You are right. Merged!
created_at: 2025-05-23T13:32:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,49 @@
+@media (min-width: 600px) {
+}
+
+@media (min-width: 900px) {
+  .header-mobile {
+    display: none;
+  }
+
+  .header-logo {
+    height: 176px;
+    padding-left: 48px;
+  }
+
+  .header-desktop {
+    display: block;
+    height: 176px;
+    width: 100%;
+  }
+
+  .desktop-nav {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 2rem;
+    width: 100%;
+  }
+
+  .nav-links {
+    display: flex;
+    align-items: center;
+    gap: 2rem;
+    margin: 0;
+    padding: 0px 70px 0px 0px;
+  }
+
+  .nav-links li {
+    display: flex;
+    height: 74px;
+    width: 248px;
+    align-items: center;
+  }
+
+  .nav-links a {
+    list-style: none;
path: src/css/media.css
user: login: larstp
body: Done!
created_at: 2025-05-23T13:36:33Z
author_association: CONTRIBUTOR
path: src/pages/about.html
user: login: larstp
body: Added.
created_at: 2025-05-23T13:44:09Z
author_association: CONTRIBUTOR
path: src/pages/contact.html
user: login: larstp
body: Added.
created_at: 2025-05-23T13:44:16Z
author_association: CONTRIBUTOR
path: src/script/api/README.md
user: login: larstp
body: Added.
created_at: 2025-05-23T13:45:18Z
author_association: CONTRIBUTOR
path: src/script/utils/header.js
user: login: larstp
body: Yeah, I thought about creating more functions outside of the main two to separate and speed up the process, as well as keeping it more DRY, but I feel it might have to wait until we're all more comfortable with JS. :p 
It turned very advanced very quickly when I tried it..
created_at: 2025-05-23T13:48:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,320 @@
+const desktopHeader = document.querySelector('.header-desktop');
+
+if (desktopHeader) {
+  const nav = document.createElement('nav');
+  nav.className = 'desktop-nav';
+
+  const logoLink = document.createElement('a');
+  logoLink.href = '/public/index.html';
+
+  const logo = document.createElement('img');
+  logo.src = '/public/assets/img/logo-header.png';
path: src/script/utils/header.js
user: login: larstp
body: Yes! I've made a note to change that at a later date, as we're still in the process of creating the site and some things might move around. 

I'll change the paths closer to handoff when we have finished more pages :)
created_at: 2025-05-23T13:50:24Z
author_association: CONTRIBUTOR
path: src/script/utils/header.js
user: login: emmelinlarina
body: Very understandable! 
created_at: 2025-05-23T14:00:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: emmelinlarina
created_at: 2025-05-23T14:05:16Z
body: I think everything is ready from my side! Just need to click "ready for review" so we can merge it in 👍 
author_association: CONTRIBUTOR
user: login: larstp
created_at: 2025-05-23T17:25:31Z
body: Fixed all issues and added footer. 
Had to test on a page so made the About page to test on that one, so now we have that i guess. :p 

Let me know if there is more i need to fix :)
author_association: CONTRIBUTOR