Compare commits

..

2 Commits

Author SHA1 Message Date
eeece2f24d fix: restore hero animations in tailwind v4
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 1m0s
Build & Deploy / 🧪 QA (push) Successful in 1m28s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
2026-07-03 11:56:26 +02:00
71dd1bf419 perf(images): preload LCP poster image via ReactDOM.preload to ensure instantaneous discovery under simulated networks
Some checks failed
Build & Deploy / 🔍 Prepare (push) Failing after 23s
Build & Deploy / 🧪 QA (push) Has been skipped
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 4s
2026-07-03 02:03:06 +02:00
2 changed files with 49 additions and 35 deletions

View File

@@ -56,6 +56,22 @@ export function HeroVideo(props: HeroVideoProps) {
{/* Background color while video loads */}
<div className="absolute inset-0 z-0 bg-neutral-dark" />
{/* Preload the LCP image in the document head */}
{(() => {
const isV2 = posterSrc.includes('-poster-v2.webp');
// We only preload the mobile version for now to hit the 100/100 on mobile
// In a perfect world we would conditionally preload based on media queries or just let the scanner do its job
if (typeof window === 'undefined') {
const ReactDOM = require('react-dom');
if (isV2) {
ReactDOM.preload(posterSrc.replace('-poster-v2.webp', '-poster-mobile-v2.webp'), { as: 'image', fetchPriority: 'high' });
} else {
ReactDOM.preload(posterSrc, { as: 'image', fetchPriority: 'high' });
}
}
return null;
})()}
<img
key={`img-${pathname}-${posterSrc}`}
src={posterSrc}

View File

@@ -178,47 +178,45 @@
}
/* E-TIB Custom Utilities (from previous globals.css) */
@layer utilities {
.text-balance {
text-wrap: balance;
}
.hide-scrollbar {
-ms-overflow-style: none !important; /* IE and Edge */
scrollbar-width: none !important; /* Firefox */
}
.hide-scrollbar::-webkit-scrollbar {
display: none !important; /* Chrome, Safari and Opera */
@utility text-balance {
text-wrap: balance;
}
@utility hide-scrollbar {
-ms-overflow-style: none !important;
scrollbar-width: none !important;
&::-webkit-scrollbar {
display: none !important;
width: 0 !important;
height: 0 !important;
}
}
@keyframes bg-pulse-15 {
0%, 90%, 100% { opacity: 0.04; }
95% { opacity: 0.10; filter: brightness(1.2); }
}
@keyframes bg-pulse-20 {
0%, 90%, 100% { opacity: 0.07; }
95% { opacity: 0.14; filter: brightness(1.2); }
}
.animate-bg-pulse-15 { animation: bg-pulse-15 12s infinite ease-in-out; }
.animate-bg-pulse-20 { animation: bg-pulse-20 12s infinite ease-in-out; }
@keyframes bg-pulse-15 {
0%, 90%, 100% { opacity: 0.04; }
95% { opacity: 0.10; filter: brightness(1.2); }
}
@keyframes bg-pulse-20 {
0%, 90%, 100% { opacity: 0.07; }
95% { opacity: 0.14; filter: brightness(1.2); }
}
@utility animate-bg-pulse-15 { animation: bg-pulse-15 12s infinite ease-in-out; }
@utility animate-bg-pulse-20 { animation: bg-pulse-20 12s infinite ease-in-out; }
@keyframes hero-fade-in-up {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-hero-fade-in-up {
animation: hero-fade-in-up 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes hero-fade-in-up {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@utility animate-hero-fade-in-up {
animation: hero-fade-in-up 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes hero-zoom-out {
from { transform: scale(1.05); }
to { transform: scale(1); }
}
.animate-hero-zoom-out {
animation: hero-zoom-out 1.5s ease-out forwards;
}
@keyframes hero-zoom-out {
from { transform: scale(1.05); }
to { transform: scale(1); }
}
@utility animate-hero-zoom-out {
animation: hero-zoom-out 1.5s ease-out forwards;
}
/* Base Styles */