diff --git a/.gitignore b/.gitignore index 423807c..f47d438 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ dist/ # Local Codex agent skills and instructions .agents/ +skills-lock.json # Local environment files .env diff --git a/assets/css/main.css b/assets/css/main.css index 01b7fff..d584067 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -103,6 +103,10 @@ a:focus-visible { font-size: 16px; vertical-align: 1px; } +.mobile-menu-button, +.mobile-navigation { + display: none; +} .login-button { height: 31px; min-width: 70px; @@ -900,70 +904,212 @@ a:focus-visible { } } @media (max-width: 760px) { + html { + scroll-padding-top: 55px; + } + body { + overflow-x: hidden; + } .page-width { width: min(100% - 32px, 560px); } .site-header { height: 55px; + box-shadow: 0 1px 0 rgba(31, 92, 165, 0.08); + backdrop-filter: blur(16px); } .brand { - width: 150px; + width: 148px; } .desktop-nav { display: none; } + .login-button { + display: none; + } + .mobile-menu-button { + width: 44px; + height: 44px; + display: grid; + place-content: center; + gap: 5px; + margin-left: auto; + padding: 0; + border-radius: 50%; + color: #267cf5; + background: rgba(235, 245, 255, 0.88); + } + .mobile-menu-button .menu-glyph { + display: block; + font-size: 23px; + line-height: 1; + transform: translateY(-1px); + } + .mobile-menu-button.open .menu-glyph { + font-size: 28px; + } + .mobile-navigation { + position: fixed; + z-index: 19; + top: 55px; + right: 0; + bottom: 0; + left: 0; + display: block; + overflow-y: auto; + background: rgba(247, 251, 255, 0.97); + backdrop-filter: blur(20px); + } + .mobile-navigation-inner { + display: grid; + gap: 0; + padding-top: 20px; + padding-bottom: max(30px, env(safe-area-inset-bottom)); + } + .mobile-navigation-inner > button { + min-height: 58px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 4px; + color: #46505e; + border-bottom: 1px solid rgba(33, 106, 198, 0.1); + background: transparent; + font-size: 16px; + text-align: left; + } + .mobile-navigation-inner > button.active { + color: #1478fb; + font-weight: 700; + } + .mobile-navigation-inner > button b { + color: #78aaf0; + font-size: 18px; + font-weight: 400; + } + .mobile-navigation-inner .mobile-consult-button { + min-height: 50px; + justify-content: center; + gap: 10px; + margin-top: 24px; + padding: 0 20px; + color: #fff; + border: 0; + border-radius: 7px; + background: linear-gradient(100deg, #453cff, #00adf6); + box-shadow: 0 12px 24px rgba(25, 106, 255, 0.2); + } + .mobile-navigation-inner .mobile-consult-button b { + color: inherit; + } + .mobile-nav-enter-active, + .mobile-nav-leave-active { + transition: + opacity 0.25s ease, + transform 0.3s cubic-bezier(0.22, 1, 0.36, 1); + } + .mobile-nav-enter-from, + .mobile-nav-leave-to { + opacity: 0; + transform: translateY(-12px); + } .hero-section { - height: 500px; - min-height: 0; + height: min(720px, calc(100svh - 55px)); + min-height: 570px; + } + .hero-section::after { + position: absolute; + z-index: -1; + inset: 0; + content: ''; + background: linear-gradient( + 90deg, + rgba(246, 250, 255, 0.98) 0%, + rgba(246, 250, 255, 0.9) 46%, + rgba(246, 250, 255, 0.15) 100% + ); } .hero-art { - background-position: 62% center; - opacity: 0.72; + background-position: 66% center; + opacity: 0.86; + will-change: transform; + } + .hero-content { + align-items: flex-start; + padding-top: clamp(72px, 13vh, 112px); } .hero-copy { margin: 0; + max-width: 340px; } .hero-copy h1 { - font-size: 31px; + font-size: clamp(28px, 8.2vw, 36px); + line-height: 1.28; + letter-spacing: -0.5px; + text-wrap: balance; } .hero-points { - margin: 18px 0 22px; - gap: 8px 14px; + display: grid; + margin: 22px 0 27px; + gap: 10px; font-size: 13px; - max-width: 290px; + max-width: 300px; + } + .button-row { + width: min(100%, 310px); + gap: 10px; } .primary-button, .outline-button { - min-width: 124px; - height: 44px; - padding: 0 13px; + min-width: 0; + height: 46px; + flex: 1; + padding: 0 12px; + font-size: 13px; } .logo-strip { - height: 52px; + height: 56px; } .logo-track { - gap: 28px; + width: max-content; + min-width: 0; + justify-content: flex-start; + gap: 42px; + padding: 0 21px; + transform: none; + will-change: transform; } .intro-section, .industries-section { - padding-top: 55px; - padding-bottom: 58px; + padding-top: 62px; + padding-bottom: 66px; } .section-title h2 { - font-size: 25px; + font-size: clamp(24px, 7vw, 29px); + line-height: 1.32; + letter-spacing: -0.3px; + text-wrap: balance; } .section-title p { + max-width: 34em; + margin: 11px auto 0; font-size: 12px; + line-height: 1.6; + } + .section-title p br { + display: none; } .stats-panel { grid-template-columns: repeat(2, 1fr); min-height: 0; - padding: 20px; + padding: 13px; gap: 12px; + margin-top: 28px; + border-radius: 14px; } .stat-item { - min-height: 190px; - padding: 20px 7px; + min-height: 174px; + padding: 19px 7px; border-radius: 14px; } .stat-item img { @@ -984,19 +1130,26 @@ a:focus-visible { .cases-section, .delivery-section, .testimonial-section { - padding: 58px 0; + padding: 64px 0 70px; } .model-layout { grid-template-columns: 1fr 1fr; - gap: 7px; - margin-top: 36px; + gap: 4px; + margin-top: 40px; } .ring { max-width: 220px; + will-change: transform; } .core-value { grid-column: 1 / -1; - padding: 15px 0 0; + padding: 26px 0 0; + } + .core-value h3 { + font-size: 19px; + } + .core-point p { + font-size: 14px; } .lead-advantage { grid-template-columns: 1fr; @@ -1019,50 +1172,91 @@ a:focus-visible { min-height: 145px; } .case-panel { - grid-template-columns: 1fr 1fr; - gap: 18px 14px; - padding: 15px; + width: calc(100vw - 16px); + display: flex; + gap: 14px; + margin-right: -16px; + padding: 14px 16px 20px 0; margin-top: 35px; + overflow-x: auto; + scroll-snap-type: x mandatory; + scrollbar-width: none; + border-right: 0; + border-radius: 14px 0 0 14px; + } + .case-panel::-webkit-scrollbar, + .testimonial-track::-webkit-scrollbar { + display: none; + } + .case-panel article { + min-width: min(78vw, 310px); + scroll-snap-align: start; } .case-panel img { - height: 110px; + height: 172px; } .case-panel p { - margin-top: 10px; - font-size: 12px; + margin: 13px 5px 0; + font-size: 13px; } - .industry-grid { - margin-top: 45px; - } - .industry-grid article { - min-height: 255px; - } - .delivery-banner { - height: 105px; + .center-action { margin-top: 30px; } + .industry-grid { + margin-top: 40px; + } + .industry-grid article { + min-height: 280px; + padding: 23px; + } + .industry-grid h3 { + font-size: 23px; + } + .industry-grid img { + height: 130px; + } + .delivery-banner { + height: 118px; + margin-top: 30px; + background-position: center; + } .delivery-grid article { - min-height: 95px; - padding: 16px; + min-height: 104px; + padding: 17px; + border-radius: 10px; + } + .delivery-grid h3 { + font-size: 18px; } .testimonial-track { transform: none; overflow-x: auto; width: 100%; margin-top: 35px; + padding: 0 16px 16px; + margin-right: -16px; + margin-left: -16px; + scroll-snap-type: x mandatory; + scrollbar-width: none; } .testimonial-track article { - min-width: 280px; - width: 280px; + min-width: min(82vw, 330px); + width: min(82vw, 330px); + scroll-snap-align: center; } .cta-section { - min-height: 320px; + min-height: 350px; + } + .cta-art { + inset: -8% 0; + will-change: transform; } .cta-content { - padding: 65px 17px 0; + padding: 70px 20px 40px; } .cta-content h2 { font-size: 21px; + line-height: 1.5; } .cta-content h2 br { display: none; @@ -1070,19 +1264,68 @@ a:focus-visible { .footer-main { grid-template-columns: 1fr; gap: 26px; + padding: 38px 0 34px; } .footer-main > img { width: 240px; } .footer-links { - gap: 18px; + grid-template-columns: repeat(2, 1fr); + gap: 24px 18px; } .footer-links span { margin-top: 8px; } .footer-bottom { - padding: 0 12px; + height: auto; + min-height: 59px; + padding: 14px 16px; text-align: center; font-size: 10px; + line-height: 1.6; + } + .consult-dialog { + width: calc(100% - 28px); + padding: 30px 22px 24px; + border-radius: 16px; + } + .consult-dialog .primary-button { + width: 100%; + } + .toast { + right: 16px; + bottom: calc(16px + env(safe-area-inset-bottom)); + left: 16px; + transform: none; + text-align: center; + } +} + +@media (max-width: 390px) { + .page-width { + width: calc(100% - 24px); + } + .hero-content { + padding-top: 62px; + } + .hero-copy h1 { + font-size: 28px; + } + .stats-panel { + gap: 9px; + padding: 10px; + } + .stat-item { + min-height: 165px; + } + .stat-item span { + font-size: 12px; + } + .case-panel { + width: calc(100vw - 12px); + margin-right: -12px; + } + .footer-main > img { + width: min(240px, 100%); } } diff --git a/nuxt.config.js b/nuxt.config.js index bf77bd1..014e5aa 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -1,4 +1,7 @@ export default defineNuxtConfig({ + future: { + compatibilityVersion: 3 + }, modules: ['@nuxtjs/tailwindcss'], css: ['~/assets/css/main.css'], vite: { diff --git a/pages/index.vue b/pages/index.vue index 3e331c6..662e767 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -3,6 +3,7 @@ import { gsap } from 'gsap' import { ScrollTrigger } from 'gsap/ScrollTrigger' const consultationOpen = ref(false) +const mobileMenuOpen = ref(false) const notice = ref('') const pageRoot = ref(null) let animationContext @@ -98,9 +99,11 @@ const deliverySteps = [ ] function scrollToSection(id) { + mobileMenuOpen.value = false document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' }) } function openConsultation() { + mobileMenuOpen.value = false consultationOpen.value = true notice.value = '' } @@ -173,6 +176,52 @@ onMounted(async () => { reveal('.testimonial-section .section-title', '.testimonial-section') reveal('.testimonial-track article', '.testimonial-track', { y: 22, stagger: 0.1 }) reveal('.cta-content', '.cta-section', { y: 26 }) + + ScrollTrigger.matchMedia({ + '(max-width: 760px)': () => { + gsap.to('.logo-track', { + xPercent: -50, + duration: 24, + ease: 'none', + repeat: -1 + }) + + gsap.to('.ring:first-child', { + x: -12, + rotation: -2, + ease: 'none', + scrollTrigger: { + trigger: '.model-layout', + start: 'top bottom', + end: 'bottom top', + scrub: 0.8 + } + }) + + gsap.to('.ring:nth-child(2)', { + x: 12, + rotation: 2, + ease: 'none', + scrollTrigger: { + trigger: '.model-layout', + start: 'top bottom', + end: 'bottom top', + scrub: 0.8 + } + }) + + gsap.to('.cta-art', { + yPercent: -6, + ease: 'none', + scrollTrigger: { + trigger: '.cta-section', + start: 'top bottom', + end: 'bottom top', + scrub: 0.8 + } + }) + } + }) }, pageRoot.value) }) @@ -198,10 +247,45 @@ onBeforeUnmount(() => animationContext?.revert()) {{ label }} + + + + +