From 7d3fd0692c63b218439ff9533e31c78bd62bc809 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 4 Jan 2026 18:46:16 +0100 Subject: [PATCH 01/15] Add favicon --- public/img/favicon.svg | 5 +++++ public/index.html | 1 + 2 files changed, 6 insertions(+) create mode 100644 public/img/favicon.svg diff --git a/public/img/favicon.svg b/public/img/favicon.svg new file mode 100644 index 0000000..7262970 --- /dev/null +++ b/public/img/favicon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/index.html b/public/index.html index 19880b6..89bd90a 100644 --- a/public/index.html +++ b/public/index.html @@ -4,6 +4,7 @@ MagicMirror² + From e224d2423022883542acf3c329b96276c4e84cf8 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sun, 4 Jan 2026 19:46:22 +0100 Subject: [PATCH 02/15] Upgrade FontAwesome from 4.6.3 to 6.5.1 - Replace deprecated use.fontawesome.com script with cdnjs CSS link - Update all icons to FontAwesome 6 syntax (fa-solid, fa-brands) - Replace fa-diamond with fa-gem (diamond removed in FA5+) - Replace fa-simplybuilt with fa-discord for Discord link --- public/index.html | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/public/index.html b/public/index.html index 89bd90a..80b32ca 100644 --- a/public/index.html +++ b/public/index.html @@ -7,9 +7,9 @@ + - @@ -140,28 +146,6 @@

Interested in similar projects?

©2016 Michael Teeuw, Xonay Media. Video by Paul-Vincent Roll. - - - \ No newline at end of file + diff --git a/public/main.js b/public/main.js new file mode 100644 index 0000000..5de3879 --- /dev/null +++ b/public/main.js @@ -0,0 +1,46 @@ +// Mobile navbar toggle +const navToggle = document.getElementById('navToggle'); +const navMenu = document.getElementById('navMenu'); + +navToggle.addEventListener('click', () => { + navMenu.classList.toggle('active'); + navToggle.classList.toggle('active'); +}); + +// Fade-in animation on scroll +const observer = new IntersectionObserver((entries) => { + entries.forEach((entry, index) => { + if (entry.isIntersecting) { + setTimeout(() => entry.target.classList.add('visible'), index * 150); + observer.unobserve(entry.target); + } + }); +}, { threshold: 0.2, rootMargin: '0px 0px -50px 0px' }); + +document.querySelectorAll('.fade-in-up').forEach(el => observer.observe(el)); + +// Theme toggle +const themeToggle = document.getElementById('themeToggle'); +const themeIcon = themeToggle.querySelector('i'); + +// Check localStorage first, then system preference, fallback to light +const getInitialTheme = () => { + const stored = localStorage.getItem('theme'); + if (stored) return stored; + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +}; + +const setTheme = (theme) => { + document.documentElement.setAttribute('data-theme', theme); + themeIcon.className = theme === 'dark' + ? 'fa-solid fa-fw fa-sun' + : 'fa-solid fa-fw fa-moon'; + localStorage.setItem('theme', theme); +}; + +setTheme(getInitialTheme()); + +themeToggle.addEventListener('click', () => { + const currentTheme = document.documentElement.getAttribute('data-theme'); + setTheme(currentTheme === 'dark' ? 'light' : 'dark'); +}); diff --git a/public/style.css b/public/style.css index 2d1cc81..c554a9b 100644 --- a/public/style.css +++ b/public/style.css @@ -1,16 +1,54 @@ +:root { + --bg-primary: #ffffff; + --bg-secondary: #e9ecef; + --text-primary: #333; + --text-secondary: #666; + --text-tertiary: #777; + --text-muted: #999; + --border-color: #e7e7e7; + --border-light: #ddd; + --accent-color: #2B879E; +} + +[data-theme="dark"] { + --bg-primary: #1a1a1a; + --bg-secondary: #2d2d2d; + --text-primary: #e0e0e0; + --text-secondary: #b0b0b0; + --text-tertiary: #a0a0a0; + --text-muted: #808080; + --border-color: #404040; + --border-light: #4a4a4a; + --accent-color: #3fa8c4; +} + body { font-family: 'Roboto Condensed', sans-serif; scroll-behavior: smooth; margin: 0; padding: 0; - color: #333; + color: var(--text-primary); + background-color: var(--bg-primary); font-size: 14px; + transition: background-color 0.3s ease, color 0.3s ease; } * { box-sizing: border-box; } +/* Links */ +a { + color: var(--accent-color); + text-decoration: none; + transition: color 0.3s ease; +} + +a:hover { + color: var(--text-primary); + text-decoration: underline; +} + /* Container */ .container { max-width: 1170px; @@ -25,8 +63,8 @@ body { /* Navbar */ .navbar { - background: #fff; - border-top: 7px solid #2B879E; + background: var(--bg-primary); + border-top: 7px solid var(--accent-color); position: relative; } @@ -45,7 +83,7 @@ body { } .navbar-brand { - color: #666 !important; + color: var(--text-secondary) !important; font-weight: 400; font-size: 25px; text-decoration: none; @@ -53,13 +91,13 @@ body { } .navbar-brand .two { - color: #999; + color: var(--text-muted); } .navbar-toggle { display: none; background: none; - border: 1px solid #ddd; + border: 1px solid var(--border-light); border-radius: 4px; padding: 9px 10px; cursor: pointer; @@ -69,7 +107,7 @@ body { display: block; width: 22px; height: 2px; - background-color: #888; + background-color: var(--text-tertiary); border-radius: 1px; margin: 4px 0; } @@ -90,13 +128,13 @@ body { display: block; padding: 0 14px; line-height: 80px; - color: #777; + color: var(--text-tertiary); text-decoration: none; transition: color 0.3s; } .nav-menu a:hover { - color: #333; + color: var(--text-primary); } /* Responsive navbar */ @@ -134,7 +172,7 @@ body { .nav-menu a { line-height: 20px; padding: 10px 15px; - border-top: 1px solid #e7e7e7; + border-top: 1px solid var(--border-color); } } @@ -157,15 +195,15 @@ body { } .btn-primary { - color: #2B879E; - border-color: #2B879E; - background-color: white; + color: var(--accent-color); + border-color: var(--accent-color); + background-color: var(--bg-primary); } .btn-primary:hover { color: white; - border-color: #2B879E; - background-color: #2B879E; + border-color: var(--accent-color); + background-color: var(--accent-color); } .btn-lg { @@ -180,7 +218,7 @@ body { background-image: url('img/mirror.png'); background-position: 600px -100px; background-repeat: no-repeat; - background-color: #e9ecef; + background-color: var(--bg-secondary); padding: 50px 15px; margin-bottom: 20px; position: relative; @@ -217,7 +255,7 @@ body { left: 0; width: 100%; height: 100%; - border: 1px solid #999; + border: 1px solid var(--text-muted); } @media (max-width: 767px) { @@ -263,14 +301,14 @@ body { /* Footer */ .footer { - border-top: 1px solid #ddd; - color: #999; + border-top: 1px solid var(--border-light); + color: var(--text-muted); padding: 15px 0; margin-top: 0; } .footer a { - color: #999; + color: var(--text-muted); } /* Lead text */ @@ -326,7 +364,7 @@ h1.logo { } h1.logo .two { - color: #999; + color: var(--text-muted); } h2 { @@ -342,12 +380,12 @@ h3 { } p { - color: #666; + color: var(--text-secondary); line-height: 1.4; } .payoff { - color: #666; + color: var(--text-secondary); } .links { @@ -359,7 +397,7 @@ p { } .line { - border-bottom: 3px solid #2B879E; + border-bottom: 3px solid var(--accent-color); width: 75px; display: inline-block; } @@ -373,6 +411,21 @@ p { line-height: 40px !important; } +.theme-toggle { + background: none; + border: none; + color: var(--text-tertiary); + cursor: pointer; + padding: 0 14px; + line-height: 80px; + font-size: 16px; + transition: color 0.3s; +} + +.theme-toggle:hover { + color: var(--text-primary); +} + @media (max-width: 767px) { .nav-donate a { border-radius: 0; From 7925644081d8898e726df3b9f51c50c7493f13ff Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 00:38:44 +0100 Subject: [PATCH 08/15] Improve fluid typography and spacing - Convert fixed sizes to clamp(): h2, h3, lead, grid gap, jumbotron padding - magpi-watermark now scales with viewport - Adjust responsive breakpoint to 825px for better navbar layout" --- public/style.css | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/public/style.css b/public/style.css index c554a9b..4f919a9 100644 --- a/public/style.css +++ b/public/style.css @@ -138,7 +138,7 @@ a:hover { } /* Responsive navbar */ -@media (max-width: 767px) { +@media (max-width: 825px) { .navbar-inner { flex-wrap: wrap; } @@ -219,7 +219,7 @@ a:hover { background-position: 600px -100px; background-repeat: no-repeat; background-color: var(--bg-secondary); - padding: 50px 15px; + padding: clamp(30px, 8vw, 50px) 15px; margin-bottom: 20px; position: relative; } @@ -228,7 +228,7 @@ a:hover { margin-top: 0; } -@media (max-width: 767px) { +@media (max-width: 825px) { .jumbotron { background-image: none; } @@ -238,7 +238,7 @@ a:hover { .grid-4 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); - gap: 30px; + gap: clamp(20px, 4vw, 30px); } /* Video container */ @@ -258,7 +258,7 @@ a:hover { border: 1px solid var(--text-muted); } -@media (max-width: 767px) { +@media (max-width: 825px) { .video-container { max-width: 100%; } @@ -313,7 +313,7 @@ a:hover { /* Lead text */ .lead { - font-size: 21px; + font-size: clamp(18px, 3.5vw, 21px); font-weight: 300; line-height: 1.4; margin: 5px 5px 25px 5px; @@ -325,7 +325,7 @@ a:hover { z-index: 9999; top: 30px; right: 50%; - width: 125px; + width: clamp(60px, 12vw, 125px); animation-name: appear; animation-duration: 2s; animation-delay: 1s; @@ -344,13 +344,6 @@ a:hover { } } -@media (max-width: 767px) { - .magpi-watermark { - width: 60px; - top: 40px; - } -} - .section { margin-top: clamp(50px, 10vw, 100px); margin-bottom: 0; @@ -368,13 +361,13 @@ h1.logo .two { } h2 { - font-size: 30px; + font-size: clamp(24px, 5vw, 30px); font-weight: 500; margin-bottom: 10px; } h3 { - font-size: 24px; + font-size: clamp(20px, 4vw, 24px); font-weight: 400; margin-bottom: 0; } @@ -426,7 +419,7 @@ p { color: var(--text-primary); } -@media (max-width: 767px) { +@media (max-width: 825px) { .nav-donate a { border-radius: 0; margin: 0; From 3e7226999724852b4ba85a6432b0bfa61425f260 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 04:29:13 +0100 Subject: [PATCH 09/15] Update jumbotron background properties for improved responsiveness --- public/style.css | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/public/style.css b/public/style.css index 4f919a9..567d5f2 100644 --- a/public/style.css +++ b/public/style.css @@ -216,7 +216,8 @@ a:hover { /* Jumbotron */ .jumbotron { background-image: url('img/mirror.png'); - background-position: 600px -100px; + background-size: clamp(550px, 65vw, 1200px) auto; + background-position: bottom clamp(-425px, 90%, -200px) right -15em; background-repeat: no-repeat; background-color: var(--bg-secondary); padding: clamp(30px, 8vw, 50px) 15px; @@ -228,12 +229,6 @@ a:hover { margin-top: 0; } -@media (max-width: 825px) { - .jumbotron { - background-image: none; - } -} - /* Grid system */ .grid-4 { display: grid; From 7c501989c6e2cc6f1de87f3562ea120ea039961c Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 04:42:51 +0100 Subject: [PATCH 10/15] Add demo GIF section with modal functionality --- public/index.html | 16 +++++++++++++ public/main.js | 21 +++++++++++++++++ public/style.css | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/public/index.html b/public/index.html index a71b2b4..9b18bfc 100644 --- a/public/index.html +++ b/public/index.html @@ -95,6 +95,22 @@

Watch the video:

+
+
+

See it in action:

+

Click to enlarge · Short demo recording

+
+ MagicMirror² Demo +
+
+
+ + + +
From a173c2c207a351b0a24c5fd22479f2da1715348b Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 15:13:39 +0100 Subject: [PATCH 13/15] Use better MagPi image in dark mode --- public/index.html | 4 ++-- public/main.js | 7 +++++++ public/style.css | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/public/index.html b/public/index.html index 772f9b6..16c770b 100644 --- a/public/index.html +++ b/public/index.html @@ -43,7 +43,7 @@
- MagPi Top 50 + MagPi Top 50
@@ -112,7 +112,7 @@

See it in action:

Voted number 1 in the MagPi Top 50!

diff --git a/public/main.js b/public/main.js index bd88d4e..19b4656 100644 --- a/public/main.js +++ b/public/main.js @@ -36,6 +36,13 @@ const setTheme = (theme) => { ? 'fa-solid fa-fw fa-sun' : 'fa-solid fa-fw fa-moon'; localStorage.setItem('theme', theme); + + // Update magpi images + const magpiImages = document.querySelectorAll('.magpi-image'); + const imageSrc = theme === 'dark' + ? 'img/magpi-best-watermark.png' + : 'img/magpi-best-watermark-custom.png'; + magpiImages.forEach(img => img.src = imageSrc); }; setTheme(getInitialTheme()); diff --git a/public/style.css b/public/style.css index 4b090fb..308214f 100644 --- a/public/style.css +++ b/public/style.css @@ -335,16 +335,6 @@ a:hover { opacity: 1; transform: translateY(0); } -/* MagPi logo */ -.magpi-logo { - max-width: 150px; - margin: 0 auto 20px; -} - -.magpi-logo img { - max-width: 100%; - height: auto; -} /* Responsive image */ .responsive-img { @@ -374,8 +364,18 @@ a:hover { margin: 5px 5px 25px 5px; } -/* Existing custom styles */ -.magpi-watermark { +/* MagPi images */ +.magpi-logo { + max-width: 150px; + margin: 0 auto 20px; +} + +.magpi-logo img { + max-width: 100%; + height: auto; +} + +.magpi-floating { position: absolute; z-index: 9999; top: 30px; From 62dec263a024fc46635fa81238de96c5a58fc5d9 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:34:42 +0100 Subject: [PATCH 14/15] Enhance navbar and MagPi image styles for improved layout and responsiveness --- public/style.css | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/public/style.css b/public/style.css index 308214f..88432ae 100644 --- a/public/style.css +++ b/public/style.css @@ -66,20 +66,19 @@ a:hover { background: var(--bg-primary); border-top: 7px solid var(--accent-color); position: relative; + z-index: 500; } .navbar-inner { display: flex; justify-content: space-between; align-items: center; - min-height: 80px; padding: 0 15px; } .navbar-header { display: flex; align-items: center; - height: 80px; } .navbar-brand { @@ -147,6 +146,7 @@ a:hover { width: 100%; justify-content: space-between; flex-direction: row-reverse; + height: 60px; } .navbar-toggle { @@ -375,27 +375,43 @@ a:hover { height: auto; } +a:has(.magpi-floating) { + display: block; + text-align: center; + line-height: 0; + position: relative; +} + .magpi-floating { position: absolute; z-index: 9999; - top: 30px; - right: 50%; - width: clamp(60px, 12vw, 125px); + top: -55px; + left: 0; + right: 0; + margin: 0 auto; + width: clamp(80px, 20vw, 120px); animation-name: appear; animation-duration: 2s; animation-delay: 1s; transform: scale(0,0); animation-fill-mode: forwards; - transform-origin: 100% 50%; - filter: drop-shadow(3px 3px 0px rgba(0,0,0,0.1)); + filter: drop-shadow(2px 2px 0px rgba(0,0,0,0.1)); } @keyframes appear { from { - transform: scale(0,0) rotate(30deg) translateX(50%); + transform: scale(0,0) rotate(30deg); } to { - transform: scale(1,1) rotate(-1deg) translateX(50%); + transform: scale(1,1) rotate(-1deg); + } +} + +@media (max-width: 1500px) { + + + .jumbotron { + margin-top: 35px; } } @@ -455,8 +471,8 @@ p { border: 0; background-image: linear-gradient(100deg, rgb(0, 112, 186), rgb(0, 48, 135)); color: white !important; - margin-top: 20px; - line-height: 40px !important; + line-height: 40px; + margin: 20px 0; } .theme-toggle { @@ -465,9 +481,10 @@ p { color: var(--text-tertiary); cursor: pointer; padding: 0 14px; - line-height: 80px; font-size: 16px; transition: color 0.3s; + line-height: 40px; + margin: 20px 0; } .theme-toggle:hover { @@ -477,8 +494,14 @@ p { @media (max-width: 825px) { .nav-donate a { border-radius: 0; + line-height: inherit; margin: 0; } + + .theme-toggle { + line-height: inherit; + border-top: 1px solid var(--border-color + } } .donate-spacer { From 73ce1ac6a35841101e8b7423c1890c861417bc69 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Mon, 5 Jan 2026 16:57:32 +0100 Subject: [PATCH 15/15] Make demo max-width 100% on small screens --- public/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/style.css b/public/style.css index 88432ae..38ae66f 100644 --- a/public/style.css +++ b/public/style.css @@ -314,7 +314,8 @@ a:hover { } @media (max-width: 825px) { - .video-container { + .video-container, + .demo-container { max-width: 100%; } }