From 67202d5323c0d31da8d3c26bb2fb5dca7d66c1b7 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Sun, 6 Sep 2026 11:08:13 +0330 Subject: [PATCH] fix: resize and rearrange hero landing illustrations for laptop screens --- src/components/HeroSection.module.css | 164 ++++++++++---------- src/components/ScenicHeroJourney.module.css | 97 +++++++++++- src/components/ScenicHeroJourney.tsx | 30 +++- 3 files changed, 199 insertions(+), 92 deletions(-) diff --git a/src/components/HeroSection.module.css b/src/components/HeroSection.module.css index e481003..34febc5 100644 --- a/src/components/HeroSection.module.css +++ b/src/components/HeroSection.module.css @@ -1,20 +1,29 @@ +/* ============================================================ + HeroSection — central content overlay on the hero stage + ============================================================ */ + +/* ── Content wrapper ─────────────────────────────────────────── */ .heroContentWrapper { position: relative; width: 100%; - height: 680px; + height: 100%; z-index: 5; } +/* ── Top bar: theme toggle (left) + language (right) ─────────── */ .topBar { position: absolute; - inset: 0 0 auto; - z-index: 2; + top: 0; + left: 0; + right: 0; + z-index: 10; display: flex; align-items: center; justify-content: space-between; - padding: 72px 60px 0; + padding: clamp(18px, 2.5vw, 32px) var(--layout-page-gutter) 0; } +/* ── Icon buttons ───────────────────────────────────────────── */ .iconButton { display: inline-flex; align-items: center; @@ -50,26 +59,31 @@ fill: currentColor; } +/* ── Hero central content ────────────────────────────────────── */ .heroContent { position: relative; display: flex; flex-direction: column; align-items: center; - padding-top: 74px; + justify-content: center; + height: 100%; + /* Horizontal padding keeps text clear of illustration zones */ + padding: 0 clamp(160px, 22vw, 460px); text-align: center; } +/* ── Avatar ─────────────────────────────────────────────────── */ .avatarWrapper { - margin-bottom: 26px; + margin-bottom: clamp(14px, 1.8vw, 22px); } .avatarRingOuter { display: inline-block; - padding: 6px; - border: 3px solid var(--color-blue-700); + padding: clamp(4px, 0.5vw, 7px); + border: clamp(2px, 0.25vw, 3px) solid var(--color-blue-700); border-radius: 50%; background: transparent; - box-shadow: 0 8px 24px var(--shadow-color); + box-shadow: 0 8px 32px var(--shadow-color); } [data-theme="dark"] .avatarRingOuter { @@ -78,8 +92,8 @@ .avatarContainer { position: relative; - width: 208px; - height: 208px; + width: clamp(100px, 13vw, 168px); + height: clamp(100px, 13vw, 168px); overflow: hidden; border: 0; border-radius: 50%; @@ -91,43 +105,48 @@ object-fit: cover; } +/* ── Display title ──────────────────────────────────────────── */ .heroTitle { - margin-bottom: 14px; + margin-bottom: clamp(8px, 1vw, 14px); color: var(--text-primary); - font-size: var(--font-size-display-hero); - line-height: var(--line-height-display-hero); + /* Scale title fluidly so it never overflows into illustration zones */ + font-size: clamp(32px, 5vw, 64px); + line-height: 1.12; text-shadow: none; + white-space: nowrap; } +/* ── Subtitle ───────────────────────────────────────────────── */ .heroSubtitle { - margin-bottom: 40px; + margin-bottom: clamp(20px, 2.8vw, 36px); color: var(--text-primary); - font-size: 15px; + font-size: clamp(11px, 1vw, 15px); font-weight: 700; - letter-spacing: 0.16em; + letter-spacing: 0.18em; text-transform: uppercase; + white-space: nowrap; } +/* ── Action buttons ─────────────────────────────────────────── */ .actionButtons { display: flex; align-items: center; - gap: 20px; - margin-bottom: 34px; + gap: clamp(10px, 1.4vw, 20px); + margin-bottom: clamp(18px, 2.2vw, 30px); } .heroButton { - width: 176px; - height: 56px; - padding: 0 28px; - border-width: 3px; - font-size: var(--font-size-body-default); + min-width: clamp(80px, 9vw, 120px); + height: clamp(40px, 4.5vw, 52px); + padding: 0 clamp(16px, 2vw, 28px); + border-width: 2px; + font-size: clamp(13px, 1.1vw, 16px); } .heroButtonOutline { border-color: var(--color-blue-600); background: transparent; color: var(--color-blue-700); - backdrop-filter: none; } .heroButtonPrimary { @@ -153,17 +172,18 @@ color: var(--color-blue-950); } +/* ── Contact bar ─────────────────────────────────────────────── */ .contactBar { display: inline-flex; align-items: center; - gap: 16px; - padding: 0; + gap: clamp(10px, 1.4vw, 18px); border: 0; background: transparent; color: var(--color-blue-700); - font-size: var(--font-size-body-small); + font-size: clamp(11px, 1vw, 14px); font-weight: 500; - line-height: var(--line-height-body-small); + line-height: 1.6; + white-space: nowrap; } [data-theme="dark"] .contactBar { @@ -173,7 +193,7 @@ .contactItem { display: inline-flex; align-items: center; - gap: 8px; + gap: 6px; color: inherit; transition: opacity var(--motion-duration-fast) ease; } @@ -195,38 +215,22 @@ .contactDivider { width: 1px; - height: 22px; + height: 18px; background: var(--color-blue-500); - opacity: 0.7; -} - -@media (max-width: 1024px) { - .topBar { - padding: 48px var(--layout-page-gutter) 0; - } - - .heroContent { - padding: 72px var(--layout-page-gutter) 0; - } - - .heroTitle { - font-size: 54px; - line-height: 64px; - } - - .heroButton { - width: 156px; - } + opacity: 0.6; } +/* ================================================================ + MOBILE ≤ 640px + ================================================================ */ @media (max-width: 640px) { .heroContentWrapper { - min-height: 760px; height: auto; + min-height: 680px; } .topBar { - padding-top: 24px; + padding-top: 18px; } .iconButton { @@ -235,62 +239,47 @@ } .heroContent { - min-height: 760px; - padding: 82px var(--layout-page-gutter) 48px; - } - - .avatarWrapper { - margin-bottom: 20px; - } - - .avatarRingOuter { - padding: 4px; - border-width: 2px; - } - - .avatarContainer { - width: 148px; - height: 148px; + /* Switch to top-anchored layout on mobile */ + height: auto; + min-height: 680px; + padding: 72px 24px 40px; + justify-content: flex-start; } .heroTitle { + font-size: clamp(30px, 8.5vw, 42px); + white-space: normal; max-width: 300px; - margin-bottom: 10px; - font-size: 40px; - line-height: 48px; + line-height: 1.15; } .heroSubtitle { - max-width: 280px; - margin-bottom: 28px; - font-size: 12px; - line-height: 18px; + white-space: normal; + max-width: 260px; + letter-spacing: 0.14em; } .actionButtons { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; - max-width: 360px; + max-width: 320px; gap: 8px; - margin-bottom: 28px; } .heroButton { - width: auto; min-width: 0; - height: 48px; - padding: 0 12px; - border-width: 2px; - font-size: 14px; + width: auto; + height: 42px; + padding: 0 8px; + font-size: 13px; } .contactBar { flex-direction: column; - gap: 8px; - max-width: 100%; + gap: 6px; + white-space: normal; font-size: 12px; - line-height: 18px; } .contactItem { @@ -303,6 +292,9 @@ } } +/* ================================================================ + HOVER STATES + ================================================================ */ @media (hover: hover) and (pointer: fine) { .iconButton:hover { color: var(--color-blue-500); diff --git a/src/components/ScenicHeroJourney.module.css b/src/components/ScenicHeroJourney.module.css index 0fc9576..a0d2ece 100644 --- a/src/components/ScenicHeroJourney.module.css +++ b/src/components/ScenicHeroJourney.module.css @@ -1,23 +1,112 @@ +/* ============================================================ + ScenicHeroJourney — hero stage with fluid-scaling SVG backdrop + Strategy: illustrations use fluid width via clamp() so they + always leave a comfortable gap to the center content. + They are pushed left/right so ~half bleeds off the canvas edge, + clipped by heroStage overflow:hidden — matching the design. + ============================================================ */ + +/* ── Container ─────────────────────────────────────────────── */ .scenicContainer { position: relative; width: 100%; - max-width: 1440px; height: auto; - overflow: hidden; + overflow: visible; background-color: var(--bg-page); } +/* ── Hero Stage ─────────────────────────────────────────────── */ .heroStage { position: relative; width: 100%; - height: 680px; + /* fluid height: shrinks on narrower screens */ + height: clamp(360px, 46vw, 680px); overflow: hidden; background: var(--bg-page); } +/* ── Backdrop wrapper ───────────────────────────────────────── */ +.heroBackdrop { + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + user-select: none; +} + +/* ── All backdrop imgs are absolutely positioned ─────────────── */ +.heroBackdrop img { + position: absolute; + display: block; + height: auto; +} + +/* ── Dark-mode tint ─────────────────────────────────────────── */ +:global([data-theme="dark"]) .heroBackdrop { + opacity: 0.82; + filter: saturate(0.88) brightness(0.9); +} + +/* ================================================================ + LEFT illustration (SVG intrinsic: 397 × 600) + Strategy: width scales with viewport so it's always ~28% of + the canvas width. Pushed so its RIGHT edge aligns with the + leftmost ~22% of the canvas (the rest bleeds off the left edge). + ================================================================ */ +.backdropLeft { + /* Start below the topBar icon zone (padding ~32px + icon 44px = ~76px) */ + top: clamp(72px, 8vw, 100px); + left: clamp(-220px, calc(22% - 28vw), -40px); + width: clamp(240px, 28vw, 440px); +} + +/* ================================================================ + RIGHT illustration (SVG intrinsic: 435 × 533) + Mirror of left: right edge bleeds off the right edge. + ================================================================ */ +.backdropRight { + /* Slightly lower than left to maintain visual rhythm */ + top: clamp(80px, 9vw, 110px); + right: clamp(-240px, calc(22% - 29vw), -40px); + width: clamp(250px, 29vw, 460px); +} + +/* ================================================================ + SUN illustration (SVG intrinsic: 139 × 139) + Sits in the upper-right quadrant, between the center text and + the right cubes. Scales fluidly. + ================================================================ */ +.backdropSun { + top: clamp(20px, 3.5vw, 52px); + /* place sun between center (50%) and right illustration edge */ + right: clamp(100px, calc(22% + 2vw), 380px); + width: clamp(52px, 10vw, 139px); +} + +/* ================================================================ + MOBILE ≤ 640px — tighter crop, smaller presence + ================================================================ */ @media (max-width: 640px) { .heroStage { - min-height: 760px; height: auto; + min-height: 680px; + } + + .backdropLeft { + top: 130px; + left: -30px; + width: clamp(100px, 26vw, 160px); + } + + .backdropRight { + top: 136px; + right: -30px; + width: clamp(110px, 28vw, 170px); + } + + .backdropSun { + top: 44px; + right: 16px; + width: clamp(36px, 9vw, 56px); } } diff --git a/src/components/ScenicHeroJourney.tsx b/src/components/ScenicHeroJourney.tsx index 4e0075f..bbcb5c1 100644 --- a/src/components/ScenicHeroJourney.tsx +++ b/src/components/ScenicHeroJourney.tsx @@ -3,14 +3,40 @@ import React from 'react'; import { HeroSection } from './HeroSection'; import { RiverJourney } from './RiverJourney'; -import { HeroLandscapeScene } from './scenes/HeroLandscapeScene'; import styles from './ScenicHeroJourney.module.css'; +type BackdropImgProps = { + name: 'left' | 'right' | 'sun'; + className: string; +}; + +function BackdropImg({ name, className }: BackdropImgProps) { + return ( + + ); +} + +function HeroBackdrop() { + return ( + + ); +} + export const ScenicHeroJourney: React.FC = () => { return (
- +