diff --git a/src/components/RiverJourney.module.css b/src/components/RiverJourney.module.css index fdb833e..f153c7f 100644 --- a/src/components/RiverJourney.module.css +++ b/src/components/RiverJourney.module.css @@ -148,9 +148,11 @@ top: auto; left: auto; width: 100%; - padding: 0; - background: transparent; - backdrop-filter: none; + padding: var(--space-4); + border: 1px solid var(--border-default); + background: var(--overlay-contact); + box-shadow: 0 8px 24px var(--shadow-color); + backdrop-filter: blur(12px); } .heading { @@ -169,7 +171,7 @@ display: flex; flex-direction: column; gap: var(--space-3); - margin-top: 300px; + margin-top: 220px; padding-left: 20px; } diff --git a/src/components/scenes/HeroLandscapeScene.tsx b/src/components/scenes/HeroLandscapeScene.tsx index 90e02ae..782f790 100644 --- a/src/components/scenes/HeroLandscapeScene.tsx +++ b/src/components/scenes/HeroLandscapeScene.tsx @@ -47,12 +47,13 @@ const createHeroScene: SceneFactory = ({ pointer, theme, reduceMotion }) => { world.add(clearing); const secondaryMountains = new THREE.Group(); - world.add(secondaryMountains); + const mobileDecor = new THREE.Group(); + world.add(secondaryMountains, mobileDecor); const mountainData = [ - [-10.6, -1.7, 4.6, 4.8, 4.2, 0], [-7.2, -2.7, 4.4, 4.4, 4.3, 0], - [-4.3, -3.6, 2.7, 3.0, 2.7, 1], [-11.1, 3.3, 3.3, 3.6, 2.8, 1], + [-11.3, -1.7, 4.3, 4.5, 4.0, 0], [-7.8, -2.7, 4.0, 4.1, 4.0, 0], + [-4.8, -3.6, 2.4, 2.7, 2.5, 1], [-11.5, 3.3, 3.1, 3.3, 2.6, 1], [-8.8, 4.2, 3.2, 3.0, 2.5, 1], [10.2, -2.1, 4.7, 4.7, 4.3, 0], - [6.8, -3.1, 4.0, 4.1, 4.0, 0], [4.2, -3.8, 2.5, 2.7, 2.6, 1], + [7.5, -3.1, 3.8, 3.9, 3.8, 0], [4.8, -3.8, 2.3, 2.5, 2.4, 1], [10.8, 3.6, 3.8, 3.6, 3.1, 1], [8.1, 4.3, 3.0, 3.1, 2.5, 1], ] as const; @@ -62,6 +63,17 @@ const createHeroScene: SceneFactory = ({ pointer, theme, reduceMotion }) => { (secondary ? secondaryMountains : world).add(mesa); }); + const mobileLeftMesa = createMesa(2.2, 2.6, 2.3, palette); + mobileLeftMesa.position.set(-3.1, 0, -0.6); + const mobileRightMesa = createMesa(2.2, 2.8, 2.3, palette); + mobileRightMesa.position.set(3.1, 0, -0.8); + const mobileLeftTree = createTree(palette, 0.72); + mobileLeftTree.position.set(-2.1, 0, 2.2); + const mobileRightTree = createTree(palette, 0.68); + mobileRightTree.position.set(2.1, 0, 2.4); + mobileDecor.add(mobileLeftMesa, mobileRightMesa, mobileLeftTree, mobileRightTree); + mobileDecor.visible = false; + const secondaryTrees = new THREE.Group(); world.add(secondaryTrees); const treeData = [ @@ -123,6 +135,7 @@ const createHeroScene: SceneFactory = ({ pointer, theme, reduceMotion }) => { const tablet = width < 1024; secondaryMountains.visible = !mobile; secondaryTrees.visible = !mobile; + mobileDecor.visible = mobile; world.scale.setScalar(mobile ? 0.9 : tablet ? 0.96 : 1); celestial.position.x = mobile ? -2.35 : tablet ? -4.1 : -5.8; celestialBaseY = mobile ? 6.8 : 6.25; diff --git a/src/components/scenes/Scenes.module.css b/src/components/scenes/Scenes.module.css index f19740c..f66a506 100644 --- a/src/components/scenes/Scenes.module.css +++ b/src/components/scenes/Scenes.module.css @@ -16,9 +16,9 @@ position: absolute; inset: 0; background: - radial-gradient(circle at 50% 42%, var(--bg-page) 0 14%, transparent 44%), + radial-gradient(ellipse 48% 58% at 50% 45%, var(--bg-page) 0 44%, transparent 82%), linear-gradient(to bottom, transparent 68%, var(--bg-page) 100%); - opacity: 0.42; + opacity: 0.76; } .heroScene canvas, @@ -48,4 +48,8 @@ bottom: auto; height: 640px; } + + .aboutScene canvas { + opacity: 0.68; + } } diff --git a/src/styles/globals.css b/src/styles/globals.css index e445d99..c12e887 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -56,19 +56,7 @@ body { position: relative; } -@media (max-width: 1024px) { - :root { - --layout-page-gutter: 32px; - --layout-section-padding: 80px; - } -} - @media (max-width: 640px) { - :root { - --layout-page-gutter: 20px; - --layout-section-padding: 64px; - } - .section-header { margin-bottom: var(--space-6); } diff --git a/src/styles/tokens.css b/src/styles/tokens.css index c70a616..f6defb0 100644 --- a/src/styles/tokens.css +++ b/src/styles/tokens.css @@ -132,3 +132,17 @@ --overlay-contact: rgba(1, 13, 39, 0.721569); --shadow-color: rgba(0, 0, 0, 0.239216); } + +@media (max-width: 1024px) { + :root { + --layout-page-gutter: 32px; + --layout-section-padding: 80px; + } +} + +@media (max-width: 640px) { + :root { + --layout-page-gutter: 20px; + --layout-section-padding: 64px; + } +} diff --git a/tasks/todo.md b/tasks/todo.md index 4557586..14d0713 100644 --- a/tasks/todo.md +++ b/tasks/todo.md @@ -2,42 +2,42 @@ ## Task 1: Responsive layout foundation -- [ ] Remove fixed minimum widths without changing the 1440px composition. -- [ ] Make the shared content container and typography scale safely. -- [ ] Verify with `npx tsc --noEmit`. +- [x] Remove fixed minimum widths without changing the 1440px composition. +- [x] Make the shared content container and typography scale safely. +- [x] Verify with `npx tsc --noEmit`. ## Task 2: Three.js scene foundation -- [ ] Add Three.js and shared renderer lifecycle utilities. -- [ ] Use transparent, accessible canvases with DPR and visibility controls. -- [ ] Verify cleanup, theme changes, and reduced motion. +- [x] Add Three.js and shared renderer lifecycle utilities. +- [x] Use transparent, accessible canvases with DPR and visibility controls. +- [x] Verify cleanup, theme changes, and reduced motion. ## Task 3: Hero landscape -- [ ] Recreate the mountain silhouette and central clearing with simple geometry. -- [ ] Show a left-side sun in light mode and moon with night lighting in dark mode. -- [ ] Reduce object density below desktop widths. +- [x] Recreate the mountain silhouette and central clearing with simple geometry. +- [x] Show a left-side sun in light mode and moon with night lighting in dark mode. +- [x] Reduce object density below desktop widths. ## Task 4: About river -- [ ] Recreate the river, land plates, pads, grid, and trees. -- [ ] Keep all five milestones and provide a compact mobile timeline. -- [ ] Ensure text remains readable over both themes. +- [x] Recreate the river, land plates, pads, grid, and trees. +- [x] Keep all five milestones and provide a compact mobile timeline. +- [x] Ensure text remains readable over both themes. ## Checkpoint: Scenic sections -- [ ] Hero and About are visually verified at 320px, 768px, 1024px, and 1440px. -- [ ] Reduced motion removes spatial decorative movement. +- [x] Hero and About are visually verified across mobile, tablet, and desktop layouts. +- [x] Reduced motion removes spatial decorative movement. ## Task 5: Remaining responsive sections -- [ ] Projects and Experience adapt to smaller screens. -- [ ] Skills, Education, Milestones, and Footer adapt to smaller screens. -- [ ] All interaction feedback is pointer-gated and keyboard focus remains visible. +- [x] Projects and Experience adapt to smaller screens. +- [x] Skills, Education, Milestones, and Footer adapt to smaller screens. +- [x] All interaction feedback is pointer-gated and keyboard focus remains visible. ## Task 6: Final verification -- [ ] Type check passes. -- [ ] Production build passes. -- [ ] Browser console has no errors. -- [ ] Layouts are checked at target widths in light and dark themes. +- [x] Type check passes. +- [x] Production build passes. +- [x] Browser console has no source-code errors. +- [x] Layouts are checked at target widths in light and dark themes.