{/* Skip link for keyboard navigation */}
diff --git a/src/scss/layout/topbar.scss b/src/scss/layout/topbar.scss
index 79c0e3b..fb3ee1d 100644
--- a/src/scss/layout/topbar.scss
+++ b/src/scss/layout/topbar.scss
@@ -33,14 +33,20 @@
&__container {
display: flex;
align-items: center;
- gap: 0.5rem;
+ // Fluid gap: 0.25rem at 1050px → 0.5rem at 1300px
+ gap: clamp(0.25rem, -0.8rem + 1.6vw, 0.5rem);
&__button {
@extend %button-reset;
@extend %hover-lift;
- padding: 0.6rem 1.2rem;
+ // Fluid padding: 0.5rem 0.5rem at 1050px → 0.6rem 1.2rem at 1300px
+ padding: clamp(0.5rem, 0.08rem + 0.64vw, 0.6rem)
+ clamp(0.5rem, -2.44rem + 4.48vw, 1.2rem);
border-radius: 8px;
color: var(--color-text-on-dark);
+ white-space: nowrap;
+ // Fluid font-size: 0.85rem at 1050px → 1rem at 1300px
+ font-size: clamp(0.85rem, 0.22rem + 0.96vw, 1rem);
transition:
color 0.2s ease,
box-shadow 0.2s ease,
@@ -113,6 +119,7 @@
top: 65px;
right: 0;
background: var(--color-background);
+ color: var(--color-text);
border: 1px solid var(--color-primary);
border-radius: 8px;
padding: 0;
@@ -172,8 +179,8 @@
}
}
-// Landing page has 7 menu items — switch to burger at a wider breakpoint
-@media (max-width: 1023px) {
+// Landing page has 7 menu items — switch to burger at same breakpoint as regular nav
+@media (max-width: 1049px) {
.navbar--landing .navbar__container__button {
display: none;
}
@@ -185,8 +192,8 @@
}
}
-// Keep burger visible for landing page up to 1023px
-@media (min-width: 769px) and (max-width: 1023px) {
+// Keep burger visible for landing page up to 1049px
+@media (min-width: 769px) and (max-width: 1049px) {
.navbar--landing .navbar__burger-button {
display: flex;
}
diff --git a/src/scss/sections/about-section.scss b/src/scss/sections/about-section.scss
index 6d70279..95514a1 100644
--- a/src/scss/sections/about-section.scss
+++ b/src/scss/sections/about-section.scss
@@ -74,6 +74,50 @@
background: var(--gradient-image-overlay);
}
+ &__pixel-bg {
+ position: absolute;
+ inset: 0 0 0 -35px;
+ background-color: #dbeafe;
+ opacity: 1;
+ transition: opacity 1.2s ease-in-out;
+ will-change: opacity;
+ pointer-events: none;
+
+ [data-theme='dark'] & {
+ background-color: #1e3a8a;
+ }
+
+ &--fade {
+ opacity: 0;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ display: none;
+ }
+ }
+
+ &__pixel-overlay {
+ position: absolute;
+ inset: 0 0 0 -35px;
+ width: calc(100% + 35px);
+ height: 100%;
+ object-fit: cover;
+ object-position: calc(30%) 50%;
+ border: 4px solid var(--color-background);
+ opacity: 1;
+ transition: opacity 1.2s ease-in-out;
+ will-change: opacity;
+ pointer-events: none;
+
+ &--fade {
+ opacity: 0;
+ }
+
+ @media (prefers-reduced-motion: reduce) {
+ display: none;
+ }
+ }
+
&__bio-section {
flex: 1;
text-align: center;
diff --git a/src/scss/sections/hero-section.scss b/src/scss/sections/hero-section.scss
index bf55578..9a193cc 100644
--- a/src/scss/sections/hero-section.scss
+++ b/src/scss/sections/hero-section.scss
@@ -17,6 +17,33 @@
}
}
+@keyframes hero-fade-up {
+ from {
+ opacity: 0;
+ transform: translate3d(0, 20px, 0);
+ }
+ to {
+ opacity: 1;
+ transform: translate3d(0, 0, 0);
+ }
+}
+
+@keyframes hero-bubble-before {
+ 0% { transform: scale(0.6) translate3d(0, 16px, 0); opacity: 0; }
+ 40% { transform: scale(1.1) translate3d(0, -5px, 0); opacity: 1; }
+ 65% { transform: scale(0.96) translate3d(0, 3px, 0); }
+ 82% { transform: scale(1.03) translate3d(0, -1px, 0); }
+ 100% { transform: scale(1) translate3d(0, 0, 0); opacity: 1; }
+}
+
+@keyframes hero-bubble-after {
+ 0% { transform: scale(0.5) translate3d(0, -12px, 0); opacity: 0; }
+ 45% { transform: scale(1.14) translate3d(0, 4px, 0); opacity: 1; }
+ 68% { transform: scale(0.94) translate3d(0, -2px, 0); }
+ 84% { transform: scale(1.04) translate3d(0, 1px, 0); }
+ 100% { transform: scale(1) translate3d(0, 0, 0); opacity: 1; }
+}
+
.hero-section {
@include flex-center;
min-height: 100vh;
@@ -34,6 +61,7 @@
border-radius: 50%;
border: 2px solid rgba(12, 68, 124, 0.15);
pointer-events: none;
+ will-change: transform, opacity;
}
&::after {
@@ -46,6 +74,7 @@
border-radius: 50%;
background: rgba(239, 159, 39, 0.08);
pointer-events: none;
+ will-change: transform, opacity;
}
[data-theme='dark'] & {
@@ -76,6 +105,7 @@
letter-spacing: -0.03em;
line-height: 1.1;
color: $color-heading;
+ will-change: transform, opacity;
}
&__description {
@@ -85,12 +115,14 @@
max-width: 600px;
margin-left: auto;
margin-right: auto;
+ will-change: transform, opacity;
}
&__buttons {
@include flex-center;
gap: $spacing-lg;
flex-wrap: wrap;
+ will-change: transform, opacity;
}
&__button {
@@ -148,6 +180,7 @@
text-align: center;
padding: $spacing-md;
border-radius: $border-radius-md;
+ will-change: transform, opacity;
&--1 {
background: var(--stat-primary-bg);
@@ -231,3 +264,37 @@
}
}
}
+
+// Animations fire only after the page has fully loaded (--loaded class added via JS)
+@media (prefers-reduced-motion: no-preference) {
+ .hero-section--loaded {
+ &::before {
+ animation: hero-bubble-before 4s cubic-bezier(0.34, 1.2, 0.64, 1) both 0.2s;
+ }
+
+ &::after {
+ animation: hero-bubble-after 4s cubic-bezier(0.34, 1.2, 0.64, 1) both 0.7s;
+ }
+
+ .hero-section__title {
+ animation: hero-fade-up 0.6s ease-out both 0.2s;
+ }
+
+ .hero-section__description {
+ animation: hero-fade-up 0.6s ease-out both 0.35s;
+ }
+
+ .hero-section__buttons {
+ animation: hero-fade-up 0.6s ease-out both 0.5s;
+ }
+
+ .hero-section__stat-item {
+ animation: hero-fade-up 0.7s ease-out both;
+
+ &--1 { animation-delay: 0.7s; }
+ &--2 { animation-delay: 0.85s; }
+ &--3 { animation-delay: 1s; }
+ &--4 { animation-delay: 1.15s; }
+ }
+ }
+}
diff --git a/src/scss/variables.scss b/src/scss/variables.scss
index 2a5db6e..fd83587 100644
--- a/src/scss/variables.scss
+++ b/src/scss/variables.scss
@@ -1,6 +1,6 @@
// Breakpoint variables
-$mobile-breakpoint: 768px;
-$desktop-breakpoint: 769px;
+$mobile-breakpoint: 1050px;
+$desktop-breakpoint: 1050px;
// Color variables
$color-primary: #042c53;