Skip to content

Commit 95eeab6

Browse files
committed
fix: enhance mobile navigation and adjust hero section layout for better responsiveness
1 parent 558febb commit 95eeab6

1 file changed

Lines changed: 164 additions & 12 deletions

File tree

website/index.html

Lines changed: 164 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@
2525
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
2626
background: linear-gradient(180deg, var(--bg-top) 0%, var(--bg-bottom) 100%);
2727
min-height: 100vh;
28-
overflow-x: hidden;
28+
overflow: hidden;
2929
color: var(--text-primary);
3030
}
3131

32+
@media (max-width: 768px) {
33+
body { overflow-y: auto; }
34+
}
35+
3236
/* ── Navigation ── */
3337
nav {
3438
position: fixed;
@@ -345,10 +349,18 @@
345349
}
346350

347351
.hero-visual {
348-
min-height: 400px;
352+
min-height: 350px;
353+
max-height: 400px;
349354
order: -1;
350355
}
351356

357+
#three-canvas {
358+
top: -15%;
359+
left: -15%;
360+
width: 130%;
361+
height: 130%;
362+
}
363+
352364
.hero-features {
353365
justify-content: center;
354366
}
@@ -364,28 +376,122 @@
364376
}
365377

366378
@media (max-width: 768px) {
367-
nav { padding: 0 1.25rem; }
379+
nav {
380+
padding: 0 1.25rem;
381+
}
368382

369-
.nav-links { display: none; }
383+
.nav-links {
384+
display: flex;
385+
flex-direction: column;
386+
position: absolute;
387+
top: 72px;
388+
left: 0;
389+
right: 0;
390+
background: var(--bg-top);
391+
gap: 0;
392+
padding: 0.5rem 1.25rem 1rem;
393+
border-bottom: 1px solid var(--border);
394+
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
395+
opacity: 0;
396+
visibility: hidden;
397+
transform: translateY(-8px);
398+
transition: opacity 0.25s ease, transform 0.25s ease, visibility 0.25s;
399+
pointer-events: none;
400+
}
370401

371-
.nav-toggle { display: block; }
402+
.nav-links.open {
403+
opacity: 1;
404+
visibility: visible;
405+
transform: translateY(0);
406+
pointer-events: auto;
407+
}
372408

373-
.hero-features {
374-
flex-direction: column;
375-
gap: 1rem;
409+
.nav-links li {
410+
width: 100%;
411+
}
412+
413+
.nav-links a {
414+
display: block;
415+
padding: 0.75rem 0;
416+
font-size: 1rem;
417+
border-bottom: 1px solid var(--border);
418+
}
419+
420+
.nav-links li:last-child a {
421+
border-bottom: none;
422+
}
423+
424+
.nav-cta {
425+
display: inline-flex !important;
376426
align-items: center;
427+
gap: 0.4rem;
428+
width: fit-content;
429+
margin-top: 0.5rem;
430+
padding: 0.75rem 1rem !important;
431+
}
432+
433+
.nav-toggle.open span:nth-child(1) {
434+
transform: rotate(45deg) translate(4px, 4px);
435+
}
436+
.nav-toggle.open span:nth-child(2) {
437+
opacity: 0;
438+
}
439+
.nav-toggle.open span:nth-child(3) {
440+
transform: rotate(-45deg) translate(4px, -4px);
441+
}
442+
443+
.nav-toggle { display: block; }
444+
445+
.hero {
446+
padding-top: 60px;
447+
padding-bottom: 2rem;
377448
}
378449

379450
.hero-visual {
380-
min-height: 320px;
451+
min-height: 240px;
452+
max-height: 280px;
453+
aspect-ratio: auto;
454+
}
455+
456+
#three-canvas {
457+
top: -10%;
458+
left: -10%;
459+
width: 120%;
460+
height: 120%;
461+
}
462+
463+
.hero-badge { margin-bottom: 1rem; }
464+
465+
.hero-code { display: none; }
466+
467+
.hero-title {
468+
font-size: 2.4rem;
469+
margin-bottom: 1rem;
470+
}
471+
472+
.hero-description {
473+
font-size: 0.95rem;
474+
margin-bottom: 1.5rem;
381475
}
382476

383477
.hero-actions {
384478
flex-direction: column;
385479
width: 100%;
480+
margin-bottom: 2rem;
386481
}
387482

388483
.btn { width: 100%; justify-content: center; }
484+
485+
.hero-features {
486+
flex-direction: row;
487+
flex-wrap: wrap;
488+
gap: 1rem 2rem;
489+
justify-content: center;
490+
margin-top: 1.5rem;
491+
padding-top: 1rem;
492+
}
493+
494+
.hero-feature { align-items: center; }
389495
}
390496
</style>
391497
</head>
@@ -484,6 +590,16 @@ <h1 class="hero-title">
484590
}
485591
}
486592
</script>
593+
<script>
594+
// ── Mobile nav toggle ──
595+
const navToggle = document.querySelector('.nav-toggle');
596+
const navLinks = document.querySelector('.nav-links');
597+
navToggle.addEventListener('click', () => {
598+
navToggle.classList.toggle('open');
599+
navLinks.classList.toggle('open');
600+
});
601+
</script>
602+
487603
<script type="module">
488604
import * as THREE from 'three';
489605

@@ -781,6 +897,39 @@ <h1 class="hero-title">
781897
isHovering = false;
782898
});
783899

900+
// Touch support — tap to explode, tap again or wait to reassemble
901+
let touchActive = false;
902+
renderer.domElement.addEventListener('touchstart', (e) => {
903+
const touch = e.touches[0];
904+
const rect = container.getBoundingClientRect();
905+
mouse.x = ((touch.clientX - rect.left) / rect.width) * 2 - 1;
906+
mouse.y = -((touch.clientY - rect.top) / rect.height) * 2 + 1;
907+
908+
// Check if touch hits the sphere
909+
raycaster.setFromCamera(mouse, camera);
910+
const hits = raycaster.intersectObject(hitSphere);
911+
if (hits.length > 0) {
912+
touchActive = !touchActive;
913+
isHovering = touchActive;
914+
e.preventDefault();
915+
}
916+
}, { passive: false });
917+
918+
renderer.domElement.addEventListener('touchmove', (e) => {
919+
if (!touchActive) return;
920+
const touch = e.touches[0];
921+
const rect = container.getBoundingClientRect();
922+
if (prevMouseX !== null) {
923+
mouseVelX = touch.clientX - prevMouseX;
924+
}
925+
prevMouseX = touch.clientX;
926+
e.preventDefault();
927+
}, { passive: false });
928+
929+
renderer.domElement.addEventListener('touchend', () => {
930+
prevMouseX = null;
931+
});
932+
784933
function easeOutQuart(t) { return 1 - Math.pow(1 - t, 4); }
785934
function easeInOutCubic(t) {
786935
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
@@ -791,9 +940,12 @@ <h1 class="hero-title">
791940
const dt = clock.getDelta();
792941
const elapsed = clock.getElapsedTime();
793942

794-
raycaster.setFromCamera(mouse, camera);
795-
const hits = raycaster.intersectObject(hitSphere);
796-
isHovering = hits.length > 0;
943+
// On touch devices, isHovering is toggled by tap; on desktop, by raycasting
944+
if (!touchActive) {
945+
raycaster.setFromCamera(mouse, camera);
946+
const hits = raycaster.intersectObject(hitSphere);
947+
isHovering = hits.length > 0;
948+
}
797949

798950
if (isHovering) {
799951
displaceFactor = Math.min(1, displaceFactor + dt * EXPAND_SPEED);

0 commit comments

Comments
 (0)