From a955da7ec8de5d2885742a5483c47351edde5b70 Mon Sep 17 00:00:00 2001 From: "Najjar\\NajjarV02" Date: Fri, 17 Apr 2026 15:37:27 +0400 Subject: [PATCH] feat: add responsive overlay styles and enhance ScrollOverlays component --- src/app/globals.css | 141 ++++++++++++++++++++++++++++++ src/components/ScrollOverlays.tsx | 44 ++++++---- src/components/ScrollScene.tsx | 11 ++- 3 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index fbd7ead..7db0ad4 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -363,3 +363,144 @@ html { max-height: 100dvh !important; } } + +/* ===== Scroll Overlay Responsive ===== */ + +/* Overlay glass panels (side sections) */ +.overlay-panel { + max-width: 450px; + padding: 2.5rem; + border-radius: 1.5rem; +} + +/* Overlay section positioning */ +.overlay-section-left { + left: clamp(2rem, 6vw, 6rem); +} + +.overlay-section-right { + right: clamp(2rem, 6vw, 6rem); +} + +.overlay-heading { + font-size: clamp(2rem, 3.5vw, 3rem); +} + +.overlay-hero-heading { + font-size: clamp(2.5rem, 5vw, 4.5rem); +} + +.overlay-stat { + font-size: 1.8rem; +} + +/* Tablet */ +@media (max-width: 1024px) { + .overlay-panel { + max-width: 380px; + padding: 2rem; + } +} + +/* Mobile */ +@media (max-width: 768px) { + .overlay-section-left, + .overlay-section-right { + left: 50% !important; + right: auto !important; + transform: translateX(-50%); + width: 90vw; + max-width: 400px; + } + + .overlay-section-left { + top: auto !important; + bottom: 6vh !important; + align-items: center !important; + } + + .overlay-section-right { + top: auto !important; + bottom: 6vh !important; + align-items: center !important; + } + + .overlay-panel { + max-width: 100%; + padding: 1.5rem; + border-radius: 1.25rem; + text-align: center !important; + } + + .overlay-panel > div { + align-items: center !important; + } + + .overlay-hero-heading { + font-size: clamp(1.8rem, 8vw, 2.8rem); + } + + .overlay-heading { + font-size: clamp(1.5rem, 6vw, 2rem); + } + + .overlay-stat { + font-size: 1.4rem; + } + + .overlay-brand { + top: 8vh !important; + bottom: auto !important; + } + + .overlay-brand .overlay-panel, + .overlay-brand span, + .overlay-brand p { + font-size: 0.7rem; + } + + .overlay-scroll-hint { + bottom: 1.5rem !important; + } +} + +/* Small phones */ +@media (max-width: 480px) { + .overlay-section-left, + .overlay-section-right { + width: 92vw; + bottom: 4vh !important; + } + + .overlay-panel { + padding: 1.25rem; + border-radius: 1rem; + } + + .overlay-hero-heading { + font-size: clamp(1.5rem, 7vw, 2.2rem); + } + + .overlay-heading { + font-size: clamp(1.3rem, 5.5vw, 1.8rem); + } + + .overlay-stat { + font-size: 1.2rem; + } +} + +/* Very small phones */ +@media (max-width: 375px) { + .overlay-panel { + padding: 1rem; + } + + .overlay-hero-heading { + font-size: 1.5rem; + } + + .overlay-heading { + font-size: 1.3rem; + } +} diff --git a/src/components/ScrollOverlays.tsx b/src/components/ScrollOverlays.tsx index 0742781..91b0672 100644 --- a/src/components/ScrollOverlays.tsx +++ b/src/components/ScrollOverlays.tsx @@ -12,6 +12,7 @@ interface SectionProps { align: 'center' | 'left' | 'right'; verticalAlign?: 'top' | 'center' | 'bottom'; offsetY?: number; + className?: string; } function OverlaySection({ @@ -23,6 +24,7 @@ function OverlaySection({ align, verticalAlign = 'center', offsetY = 50, + className = '', }: SectionProps) { // Define a wide "plateau" zone where the text is fully readable and static. // We use 30% of the travel distance for fading in, 30% for fading out. @@ -57,17 +59,24 @@ function OverlaySection({ const alignStyle: React.CSSProperties = align === 'left' - ? { left: 'clamp(2rem, 6vw, 6rem)', alignItems: 'flex-start' } + ? { alignItems: 'flex-start' } : align === 'right' - ? { right: 'clamp(2rem, 6vw, 6rem)', alignItems: 'flex-end' } - : { left: '50%', x: '-50%', alignItems: 'center' }; + ? { alignItems: 'flex-end' } + : { left: '50%', alignItems: 'center' }; + + const alignClass = + align === 'left' + ? 'overlay-section-left' + : align === 'right' + ? 'overlay-section-right' + : ''; const verticalStyle: React.CSSProperties = verticalAlign === 'top' ? { top: '15vh' } : verticalAlign === 'bottom' ? { bottom: '15vh', top: 'auto' } - : { top: '50%', y: '-50%' }; + : { top: '50%' }; // Glass panel appearance for side text to not clash with the robot const isCenter = align === 'center'; @@ -77,16 +86,14 @@ function OverlaySection({ background: 'rgba(255, 255, 255, 0.92)', backdropFilter: 'blur(20px)', WebkitBackdropFilter: 'blur(20px)', - padding: '2.5rem', - borderRadius: '1.5rem', boxShadow: '0 8px 32px rgba(0, 0, 0, 0.08)', border: '1px solid rgba(255, 255, 255, 0.6)', textAlign: align === 'left' ? 'left' : 'right', - maxWidth: '450px', }; return ( {children} @@ -135,7 +142,7 @@ export function ScrollOverlays() { }} > {/* 1. Brand Intro */} - +
@@ -150,10 +157,10 @@ export function ScrollOverlays() { {/* 2. Hero */} - + The Future - + of Robotics

@@ -168,7 +175,7 @@ export function ScrollOverlays() {

Intelligent by Design
-

+

Vision That
Understands

@@ -176,11 +183,11 @@ export function ScrollOverlays() {

-
360°
+
360°
Field of View
-
{'<'}50ms
+
{'<'}50ms
Response Time
@@ -193,7 +200,7 @@ export function ScrollOverlays() {
Your Identity
-

+

Dress for Any
Mission

@@ -227,7 +234,7 @@ export function ScrollOverlays() {

Advanced Mobility
-

+

23 Degrees of
Freedom

@@ -235,11 +242,11 @@ export function ScrollOverlays() {

-
2m/s
+
2m/s
Max Speed
-
127kg
+
127kg
Payload
@@ -248,6 +255,7 @@ export function ScrollOverlays() { {/* Scroll indicator mapped to vanish rapidly when scrolled */} { if (!scrollState.inScrollZone) return; @@ -70,6 +71,10 @@ function ScrollCamera() { const pos = interpolateKeyframes(CAMERA_KEYFRAMES, p); const lookAt = interpolateKeyframes(LOOKAT_KEYFRAMES, p); + // On mobile, pull camera back and center it more so robot doesn't overlap text + const mobileZOffset = isMobile ? 2.5 : 0; + const mobileCenterX = isMobile ? pos.x * 0.3 : 0; + // Dynamic camera oscillation based on scroll position const oscillationX = Math.sin(p * Math.PI * 4) * 0.05; const oscillationY = Math.cos(p * Math.PI * 3) * 0.025; @@ -80,9 +85,9 @@ function ScrollCamera() { // Apply oscillations to position const adjustedPos = new THREE.Vector3( - pos.x + oscillationX + driftZone, + pos.x - mobileCenterX + oscillationX + driftZone, pos.y + oscillationY + verticalDrift, - pos.z + pos.z + mobileZOffset ); // Adaptive lerp for smooth camera transitions