2026-01-26 13:00:54 +08:00
|
|
|
|
<script setup>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
import { ref, onMounted, onUnmounted, computed } from 'vue'
|
2026-01-26 13:00:54 +08:00
|
|
|
|
import { useRouter, withBase, useData } from 'vitepress'
|
|
|
|
|
|
import GitHubStars from './GitHubStars.vue'
|
2026-03-28 23:26:53 +08:00
|
|
|
|
import VibeStories from './VibeStories.vue'
|
|
|
|
|
|
import { provide } from 'vue'
|
2026-05-14 11:09:48 +08:00
|
|
|
|
import { i18n } from './home/HomeI18n'
|
|
|
|
|
|
import { locales } from './home/HomeData'
|
|
|
|
|
|
import HomeStage1 from './home/HomeStage1.vue'
|
|
|
|
|
|
import HomeStage2 from './home/HomeStage2.vue'
|
|
|
|
|
|
import HomeStage3 from './home/HomeStage3.vue'
|
|
|
|
|
|
import HomeAppendix from './home/HomeAppendix.vue'
|
|
|
|
|
|
import HomeAppleFooter from './home/HomeAppleFooter.vue'
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
|
|
|
|
const { site, page, lang } = useData()
|
|
|
|
|
|
const activeTab = ref('home')
|
|
|
|
|
|
const showLangMenu = ref(false)
|
2026-03-16 00:26:59 +08:00
|
|
|
|
const topPromoProgress = ref(1)
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const topPromoDismissed = ref(false)
|
2026-03-18 12:12:42 +08:00
|
|
|
|
const topPromoIntroProgress = ref(0)
|
|
|
|
|
|
const topPromoColorProgress = ref(0)
|
|
|
|
|
|
let topPromoIntroRaf = 0
|
|
|
|
|
|
let topPromoColorRaf = 0
|
|
|
|
|
|
let topPromoColorTimer = 0
|
2026-03-16 14:07:54 +08:00
|
|
|
|
const WELCOME_SEEN_KEY = 'easy-vibe-welcome-seen'
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const vibeStoriesSection = ref(null)
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
|
|
|
|
|
const t = computed(() => {
|
|
|
|
|
|
const code = lang.value ? lang.value.toLowerCase() : 'zh-cn'
|
2026-05-14 11:09:48 +08:00
|
|
|
|
const result = i18n[code] || i18n['en']
|
|
|
|
|
|
result._locale = code
|
|
|
|
|
|
return result
|
2026-01-26 13:00:54 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2026-03-28 23:26:53 +08:00
|
|
|
|
provide('t', t)
|
|
|
|
|
|
|
2026-03-15 13:41:39 +08:00
|
|
|
|
const isCjkLocale = computed(() => {
|
|
|
|
|
|
const code = lang.value ? lang.value.toLowerCase() : ''
|
|
|
|
|
|
if (['zh-cn', 'zh-tw', 'ja-jp', 'ko-kr'].includes(code)) {
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
const path = router.route.path.toLowerCase()
|
|
|
|
|
|
return /^\/(zh-cn|zh-tw|ja-jp|ko-kr)\//.test(path)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const topPromo = computed(() => {
|
|
|
|
|
|
const code = lang.value ? lang.value.toLowerCase() : 'en'
|
|
|
|
|
|
if (code === 'zh-cn' || code === 'zh-tw') {
|
|
|
|
|
|
return {
|
|
|
|
|
|
text: '用 Easy-Vibe 构建你的第一个 AI 应用,最快当天可上线原型。',
|
|
|
|
|
|
cta: '开始学习 ›',
|
2026-04-02 13:48:55 +08:00
|
|
|
|
link: '/zh-cn/stage-1/learning-map/'
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
text: 'Build your first AI app with Easy-Vibe and ship a working prototype fast.',
|
|
|
|
|
|
cta: 'Start learning ›',
|
2026-04-02 13:48:55 +08:00
|
|
|
|
link: '/en/stage-1/learning-map/'
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
const toggleLangMenu = () => {
|
|
|
|
|
|
showLangMenu.value = !showLangMenu.value
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const updateHash = (id) => {
|
|
|
|
|
|
const targetHash = id === 'home' ? '#home' : `#${id}`
|
|
|
|
|
|
const currentUrl = `${window.location.pathname}${window.location.search}${window.location.hash}`
|
|
|
|
|
|
const nextUrl = `${window.location.pathname}${window.location.search}${targetHash}`
|
|
|
|
|
|
if (currentUrl !== nextUrl) {
|
|
|
|
|
|
window.history.replaceState(null, '', nextUrl)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const syncTopPromoWithHash = () => {
|
|
|
|
|
|
const rawHash = window.location.hash.replace(/^#/, '')
|
|
|
|
|
|
const targetId = rawHash || 'home'
|
|
|
|
|
|
if (targetId === 'home') {
|
|
|
|
|
|
topPromoDismissed.value = false
|
|
|
|
|
|
topPromoProgress.value = 1
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
topPromoDismissed.value = true
|
|
|
|
|
|
topPromoProgress.value = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
const changeLang = (targetLocale) => {
|
|
|
|
|
|
const currentPath = router.route.path
|
2026-02-01 23:42:12 +08:00
|
|
|
|
const currentLocale = locales.find((l) =>
|
|
|
|
|
|
currentPath.startsWith(`/${l.code}/`)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
let newPath
|
|
|
|
|
|
if (currentLocale) {
|
2026-02-01 23:42:12 +08:00
|
|
|
|
newPath = currentPath.replace(
|
|
|
|
|
|
`/${currentLocale.code}/`,
|
|
|
|
|
|
`/${targetLocale}/`
|
|
|
|
|
|
)
|
2026-01-26 13:00:54 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
newPath = `/${targetLocale}/`
|
|
|
|
|
|
}
|
2026-02-01 23:42:12 +08:00
|
|
|
|
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const hash = window.location.hash || ''
|
|
|
|
|
|
router.go(withBase(`${newPath}${hash}`))
|
2026-01-26 13:00:54 +08:00
|
|
|
|
showLangMenu.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const scrollTo = (id) => {
|
|
|
|
|
|
if (id === 'home') {
|
|
|
|
|
|
window.scrollTo({ top: 0, behavior: 'smooth' })
|
|
|
|
|
|
activeTab.value = 'home'
|
2026-03-28 23:26:53 +08:00
|
|
|
|
updateHash('home')
|
|
|
|
|
|
syncTopPromoWithHash()
|
|
|
|
|
|
updateTopPromoVisibility()
|
2026-01-26 13:00:54 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const el = document.getElementById(id)
|
|
|
|
|
|
if (el) {
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const navHeight = 48
|
2026-01-27 02:06:42 +08:00
|
|
|
|
const elementPosition = el.getBoundingClientRect().top + window.pageYOffset
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const extraOffset = id === 'vibe-stories' ? 20 : 40
|
|
|
|
|
|
const offset = elementPosition - navHeight - extraOffset
|
2026-01-26 13:00:54 +08:00
|
|
|
|
window.scrollTo({ top: offset, behavior: 'smooth' })
|
|
|
|
|
|
activeTab.value = id
|
2026-03-28 23:26:53 +08:00
|
|
|
|
updateHash(id)
|
|
|
|
|
|
syncTopPromoWithHash()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const scrollToHashTarget = (behavior = 'auto') => {
|
|
|
|
|
|
const rawHash = window.location.hash.replace(/^#/, '')
|
|
|
|
|
|
const targetId = rawHash || 'home'
|
|
|
|
|
|
if (targetId === 'home') {
|
|
|
|
|
|
window.scrollTo({ top: 0, behavior })
|
|
|
|
|
|
activeTab.value = 'home'
|
|
|
|
|
|
syncTopPromoWithHash()
|
|
|
|
|
|
updateTopPromoVisibility()
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const el = document.getElementById(targetId)
|
|
|
|
|
|
if (el) {
|
|
|
|
|
|
const navHeight = 48
|
|
|
|
|
|
const elementPosition = el.getBoundingClientRect().top + window.pageYOffset
|
|
|
|
|
|
const extraOffset = targetId === 'vibe-stories' ? 20 : 40
|
|
|
|
|
|
const offset = elementPosition - navHeight - extraOffset
|
|
|
|
|
|
window.scrollTo({ top: offset, behavior })
|
|
|
|
|
|
activeTab.value = targetId
|
|
|
|
|
|
syncTopPromoWithHash()
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const closeLangMenu = (e) => {
|
|
|
|
|
|
if (!e.target.closest('.lang-switch-wrapper')) {
|
|
|
|
|
|
showLangMenu.value = false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-16 00:26:59 +08:00
|
|
|
|
const updateTopPromoVisibility = () => {
|
2026-03-28 23:26:53 +08:00
|
|
|
|
if (topPromoDismissed.value) {
|
|
|
|
|
|
topPromoProgress.value = 0
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!vibeStoriesSection.value) {
|
2026-03-16 00:26:59 +08:00
|
|
|
|
topPromoProgress.value = 1
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
const navHeight = 44
|
2026-03-28 23:26:53 +08:00
|
|
|
|
const sectionTop =
|
|
|
|
|
|
vibeStoriesSection.value.getBoundingClientRect().top + window.pageYOffset
|
2026-03-16 00:26:59 +08:00
|
|
|
|
const endY = sectionTop - navHeight
|
|
|
|
|
|
const startY = endY - 96
|
|
|
|
|
|
const scrollY = window.pageYOffset
|
|
|
|
|
|
if (scrollY <= startY) {
|
|
|
|
|
|
topPromoProgress.value = 1
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
if (scrollY >= endY) {
|
|
|
|
|
|
topPromoProgress.value = 0
|
2026-03-28 23:26:53 +08:00
|
|
|
|
topPromoDismissed.value = true
|
2026-03-16 00:26:59 +08:00
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
topPromoProgress.value = (endY - scrollY) / (endY - startY)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const topPromoStyle = computed(() => {
|
2026-03-18 12:12:42 +08:00
|
|
|
|
const scrollProgress = topPromoProgress.value
|
|
|
|
|
|
const introProgress = topPromoIntroProgress.value
|
|
|
|
|
|
const colorProgress = topPromoColorProgress.value
|
|
|
|
|
|
const progress = scrollProgress * introProgress
|
|
|
|
|
|
const scrollOffset = -100 * (1 - scrollProgress)
|
|
|
|
|
|
const startTextColor = { r: 255, g: 255, b: 255 }
|
|
|
|
|
|
const endTextColor = { r: 29, g: 29, b: 31 }
|
|
|
|
|
|
const startBgColor = { r: 0, g: 113, b: 227 }
|
|
|
|
|
|
const endBgColor = { r: 245, g: 245, b: 247 }
|
|
|
|
|
|
const startLinkColor = { r: 255, g: 255, b: 255 }
|
|
|
|
|
|
const endLinkColor = { r: 0, g: 102, b: 204 }
|
|
|
|
|
|
const textColor = `rgb(${Math.round(startTextColor.r + (endTextColor.r - startTextColor.r) * colorProgress)}, ${Math.round(startTextColor.g + (endTextColor.g - startTextColor.g) * colorProgress)}, ${Math.round(startTextColor.b + (endTextColor.b - startTextColor.b) * colorProgress)})`
|
|
|
|
|
|
const bgColor = `rgb(${Math.round(startBgColor.r + (endBgColor.r - startBgColor.r) * colorProgress)}, ${Math.round(startBgColor.g + (endBgColor.g - startBgColor.g) * colorProgress)}, ${Math.round(startBgColor.b + (endBgColor.b - startBgColor.b) * colorProgress)})`
|
|
|
|
|
|
const linkColor = `rgb(${Math.round(startLinkColor.r + (endLinkColor.r - startLinkColor.r) * colorProgress)}, ${Math.round(startLinkColor.g + (endLinkColor.g - startLinkColor.g) * colorProgress)}, ${Math.round(startLinkColor.b + (endLinkColor.b - startLinkColor.b) * colorProgress)})`
|
2026-03-16 00:26:59 +08:00
|
|
|
|
return {
|
|
|
|
|
|
opacity: progress,
|
2026-03-18 12:12:42 +08:00
|
|
|
|
transform: `translateY(${scrollOffset}%)`,
|
2026-03-16 00:26:59 +08:00
|
|
|
|
maxHeight: `${30 * progress}px`,
|
2026-03-18 12:12:42 +08:00
|
|
|
|
backgroundColor: bgColor,
|
|
|
|
|
|
color: textColor,
|
|
|
|
|
|
'--top-promo-link-color': linkColor,
|
2026-03-16 00:26:59 +08:00
|
|
|
|
pointerEvents: progress < 0.02 ? 'none' : 'auto'
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
const resolveFooterHref = (link) => {
|
|
|
|
|
|
if (link.startsWith('http://') || link.startsWith('https://')) {
|
|
|
|
|
|
return link
|
|
|
|
|
|
}
|
|
|
|
|
|
return withBase(link)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
onMounted(() => {
|
2026-03-18 12:12:42 +08:00
|
|
|
|
const introDuration = 1800
|
|
|
|
|
|
const colorDelay = 500
|
|
|
|
|
|
const colorDuration = 1800
|
|
|
|
|
|
const introStart = performance.now()
|
|
|
|
|
|
const stepTopPromoIntro = (now) => {
|
|
|
|
|
|
const raw = Math.min(1, (now - introStart) / introDuration)
|
|
|
|
|
|
const eased = 1 - Math.pow(1 - raw, 3)
|
|
|
|
|
|
topPromoIntroProgress.value = eased
|
|
|
|
|
|
if (raw < 1) {
|
|
|
|
|
|
topPromoIntroRaf = window.requestAnimationFrame(stepTopPromoIntro)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
topPromoColorTimer = window.setTimeout(() => {
|
|
|
|
|
|
const colorStart = performance.now()
|
|
|
|
|
|
const stepTopPromoColor = (time) => {
|
|
|
|
|
|
const colorRaw = Math.min(1, (time - colorStart) / colorDuration)
|
|
|
|
|
|
const colorEased = 1 - Math.pow(1 - colorRaw, 3)
|
|
|
|
|
|
topPromoColorProgress.value = colorEased
|
|
|
|
|
|
if (colorRaw < 1) {
|
|
|
|
|
|
topPromoColorRaf = window.requestAnimationFrame(stepTopPromoColor)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
topPromoColorRaf = window.requestAnimationFrame(stepTopPromoColor)
|
|
|
|
|
|
}, colorDelay)
|
|
|
|
|
|
}
|
|
|
|
|
|
topPromoIntroRaf = window.requestAnimationFrame(stepTopPromoIntro)
|
|
|
|
|
|
|
2026-03-16 14:07:54 +08:00
|
|
|
|
const currentPath = window.location.pathname
|
|
|
|
|
|
const basePath = site.value.base || '/'
|
|
|
|
|
|
const normalizedBase = basePath.endsWith('/') ? basePath : `${basePath}/`
|
|
|
|
|
|
const normalizedPath = currentPath.endsWith('/')
|
|
|
|
|
|
? currentPath
|
|
|
|
|
|
: `${currentPath}/`
|
|
|
|
|
|
const localeHomeSuffixes = [
|
|
|
|
|
|
'/zh-cn/',
|
|
|
|
|
|
'/en/',
|
|
|
|
|
|
'/zh-tw/',
|
|
|
|
|
|
'/ja-jp/',
|
|
|
|
|
|
'/ko-kr/',
|
|
|
|
|
|
'/es-es/',
|
|
|
|
|
|
'/fr-fr/',
|
|
|
|
|
|
'/de-de/',
|
|
|
|
|
|
'/ar-sa/',
|
|
|
|
|
|
'/vi-vn/'
|
|
|
|
|
|
]
|
|
|
|
|
|
const isLocaleHome = localeHomeSuffixes.some(
|
|
|
|
|
|
(suffix) =>
|
|
|
|
|
|
currentPath.endsWith(suffix) ||
|
|
|
|
|
|
currentPath.endsWith(`${suffix}index.html`)
|
|
|
|
|
|
)
|
|
|
|
|
|
const isRootHome =
|
|
|
|
|
|
normalizedPath === normalizedBase ||
|
|
|
|
|
|
currentPath === `${normalizedBase}index.html`
|
|
|
|
|
|
if (isRootHome && !isLocaleHome) {
|
|
|
|
|
|
const hasSeenWelcome = window.localStorage.getItem(WELCOME_SEEN_KEY) === '1'
|
|
|
|
|
|
if (!hasSeenWelcome) {
|
|
|
|
|
|
router.go(withBase(`/welcome/?next=${encodeURIComponent(currentPath)}`))
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-28 23:26:53 +08:00
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
document.addEventListener('click', closeLangMenu)
|
2026-03-28 23:26:53 +08:00
|
|
|
|
syncTopPromoWithHash()
|
|
|
|
|
|
window.setTimeout(() => {
|
|
|
|
|
|
scrollToHashTarget('auto')
|
|
|
|
|
|
}, 0)
|
2026-03-16 00:26:59 +08:00
|
|
|
|
updateTopPromoVisibility()
|
|
|
|
|
|
window.addEventListener('scroll', updateTopPromoVisibility, { passive: true })
|
|
|
|
|
|
window.addEventListener('resize', updateTopPromoVisibility)
|
2026-03-28 23:26:53 +08:00
|
|
|
|
window.addEventListener('hashchange', scrollToHashTarget)
|
2026-01-26 13:00:54 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
onUnmounted(() => {
|
2026-03-18 12:12:42 +08:00
|
|
|
|
if (topPromoIntroRaf) {
|
|
|
|
|
|
window.cancelAnimationFrame(topPromoIntroRaf)
|
|
|
|
|
|
topPromoIntroRaf = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if (topPromoColorRaf) {
|
|
|
|
|
|
window.cancelAnimationFrame(topPromoColorRaf)
|
|
|
|
|
|
topPromoColorRaf = 0
|
|
|
|
|
|
}
|
|
|
|
|
|
if (topPromoColorTimer) {
|
|
|
|
|
|
window.clearTimeout(topPromoColorTimer)
|
|
|
|
|
|
topPromoColorTimer = 0
|
|
|
|
|
|
}
|
2026-01-26 13:00:54 +08:00
|
|
|
|
document.removeEventListener('click', closeLangMenu)
|
2026-03-16 00:26:59 +08:00
|
|
|
|
window.removeEventListener('scroll', updateTopPromoVisibility)
|
|
|
|
|
|
window.removeEventListener('resize', updateTopPromoVisibility)
|
2026-03-28 23:26:53 +08:00
|
|
|
|
window.removeEventListener('hashchange', scrollToHashTarget)
|
2026-01-26 13:00:54 +08:00
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="apple-container">
|
|
|
|
|
|
<nav class="sticky-nav glass">
|
|
|
|
|
|
<div class="nav-content">
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<div class="nav-cluster">
|
2026-03-18 14:30:37 +08:00
|
|
|
|
<div
|
2026-03-16 14:07:54 +08:00
|
|
|
|
class="nav-title"
|
2026-03-18 14:30:37 +08:00
|
|
|
|
:aria-label="t.nav.title"
|
2026-03-16 14:07:54 +08:00
|
|
|
|
>
|
2026-03-18 14:30:37 +08:00
|
|
|
|
<img
|
2026-03-18 14:38:54 +08:00
|
|
|
|
class="nav-title-logo no-viewer"
|
2026-03-18 14:30:37 +08:00
|
|
|
|
:src="withBase('/assets/easy-vibe-logo-hd.svg')"
|
|
|
|
|
|
:alt="t.nav.title"
|
|
|
|
|
|
width="64"
|
|
|
|
|
|
height="30"
|
|
|
|
|
|
draggable="false"
|
|
|
|
|
|
>
|
|
|
|
|
|
</div>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<div class="nav-links">
|
|
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'home' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('home')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.home }}
|
|
|
|
|
|
</button>
|
2026-03-28 23:26:53 +08:00
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'vibe-stories' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('vibe-stories')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.stories || 'Vibe 故事' }}
|
|
|
|
|
|
</button>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'pm' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('pm')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.pm }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'junior' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('junior')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.junior }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'senior' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('senior')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.senior }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
:class="{ active: activeTab === 'appendix' }"
|
|
|
|
|
|
class="nav-link-item"
|
|
|
|
|
|
@click="scrollTo('appendix')"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ t.nav.appendix }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="nav-action">
|
|
|
|
|
|
<div class="nav-icons">
|
|
|
|
|
|
<div class="lang-switch-wrapper">
|
2026-02-01 23:42:12 +08:00
|
|
|
|
<button
|
2026-03-15 13:41:39 +08:00
|
|
|
|
type="button"
|
|
|
|
|
|
class="button"
|
|
|
|
|
|
aria-haspopup="true"
|
|
|
|
|
|
:aria-expanded="showLangMenu"
|
|
|
|
|
|
aria-label="Change language"
|
|
|
|
|
|
@click.stop="toggleLangMenu"
|
2026-01-26 13:00:54 +08:00
|
|
|
|
>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<span class="text">
|
|
|
|
|
|
<span class="vpi-languages option-icon" />
|
|
|
|
|
|
<span class="vpi-chevron-down text-icon" />
|
|
|
|
|
|
</span>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</button>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<div
|
|
|
|
|
|
v-if="showLangMenu"
|
|
|
|
|
|
class="lang-dropdown glass"
|
|
|
|
|
|
>
|
|
|
|
|
|
<button
|
|
|
|
|
|
v-for="locale in locales"
|
|
|
|
|
|
:key="locale.code"
|
|
|
|
|
|
class="lang-item"
|
|
|
|
|
|
@click="changeLang(locale.code)"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ locale.text }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</div>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<GitHubStars class="nav-github-stars" />
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</div>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<a
|
|
|
|
|
|
class="buy-btn"
|
|
|
|
|
|
:href="withBase(t.stage1.cards[0].link)"
|
|
|
|
|
|
>{{ t.footer.btn }}</a>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-16 00:26:59 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="nav-promo"
|
|
|
|
|
|
:style="topPromoStyle"
|
|
|
|
|
|
>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
<span>{{ topPromo.text }}</span>
|
|
|
|
|
|
<a :href="resolveFooterHref(topPromo.link)">{{ topPromo.cta }}</a>
|
|
|
|
|
|
</div>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</nav>
|
|
|
|
|
|
|
2026-02-18 17:38:10 +08:00
|
|
|
|
<div
|
|
|
|
|
|
id="home"
|
|
|
|
|
|
style="height: 0"
|
|
|
|
|
|
/>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
2026-03-28 23:26:53 +08:00
|
|
|
|
<section
|
|
|
|
|
|
id="vibe-stories"
|
|
|
|
|
|
ref="vibeStoriesSection"
|
|
|
|
|
|
class="section-container"
|
|
|
|
|
|
>
|
|
|
|
|
|
<VibeStories />
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
2026-03-27 18:17:31 +08:00
|
|
|
|
<div class="section-band section-band-learning">
|
2026-05-14 11:09:48 +08:00
|
|
|
|
<HomeStage1 />
|
|
|
|
|
|
<HomeStage2 />
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</div>
|
2026-03-15 13:41:39 +08:00
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
<HomeStage3 />
|
|
|
|
|
|
<HomeAppendix />
|
|
|
|
|
|
<HomeAppleFooter :is-cjk-locale="isCjkLocale" />
|
2026-01-26 13:00:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
.apple-container {
|
2026-02-01 23:42:12 +08:00
|
|
|
|
font-family:
|
2026-03-15 13:41:39 +08:00
|
|
|
|
-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'PingFang SC',
|
|
|
|
|
|
'Helvetica Neue', sans-serif;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
color: var(--vp-c-text-1);
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: transparent;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 11:03:08 +08:00
|
|
|
|
#vibe-stories,
|
|
|
|
|
|
#vibe-stories:focus,
|
|
|
|
|
|
#vibe-stories:focus-visible,
|
|
|
|
|
|
#vibe-stories:target {
|
|
|
|
|
|
outline: none !important;
|
|
|
|
|
|
box-shadow: none !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
a {
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
color: inherit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
:is(.buy-btn) {
|
2026-03-27 18:17:31 +08:00
|
|
|
|
border-bottom: none !important;
|
|
|
|
|
|
outline: none !important;
|
|
|
|
|
|
-webkit-tap-highlight-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
:is(.buy-btn):is(:hover, :focus, :focus-visible, :active) {
|
2026-03-27 18:17:31 +08:00
|
|
|
|
border-bottom-color: transparent !important;
|
|
|
|
|
|
text-decoration: none !important;
|
|
|
|
|
|
outline: none !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
.highlight {
|
|
|
|
|
|
color: var(--vp-c-text-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.sticky-nav {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
z-index: 100;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
border-bottom: 1px solid #d2d2d7;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
transition: all 0.3s ease;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: rgba(245, 245, 247, 0.82);
|
2026-01-26 13:00:54 +08:00
|
|
|
|
backdrop-filter: blur(20px);
|
|
|
|
|
|
-webkit-backdrop-filter: blur(20px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:root.dark .sticky-nav {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: rgba(18, 18, 20, 0.8);
|
|
|
|
|
|
border-bottom: 1px solid rgba(255, 255, 255, 0.12);
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-content {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
max-width: 1280px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
margin: 0 auto;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
padding: 0 28px;
|
|
|
|
|
|
height: 44px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
justify-content: center;
|
|
|
|
|
|
position: relative;
|
2026-03-16 00:26:59 +08:00
|
|
|
|
z-index: 2;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-cluster {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 20px;
|
|
|
|
|
|
max-width: 100%;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-title {
|
2026-01-27 02:06:42 +08:00
|
|
|
|
flex-shrink: 0;
|
2026-03-16 14:07:54 +08:00
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
margin: 0;
|
2026-03-18 14:30:37 +08:00
|
|
|
|
cursor: default;
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-title-logo {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
max-width: 64px !important;
|
|
|
|
|
|
max-height: 30px !important;
|
|
|
|
|
|
height: 30px !important;
|
|
|
|
|
|
width: 64px !important;
|
|
|
|
|
|
min-width: 64px;
|
|
|
|
|
|
min-height: 30px;
|
|
|
|
|
|
object-fit: contain;
|
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
|
filter: grayscale(1) brightness(0.28) contrast(1.05);
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-links {
|
|
|
|
|
|
display: flex;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
gap: 20px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
align-items: center;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
margin: 0;
|
|
|
|
|
|
white-space: nowrap;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-01 23:42:12 +08:00
|
|
|
|
.nav-links button,
|
|
|
|
|
|
.nav-link-item {
|
2026-01-26 13:00:54 +08:00
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
font-size: 12px;
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
cursor: pointer;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
transition: opacity 0.2s;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
padding: 0;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
line-height: 1;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
font-weight: 400;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
opacity: 0.76;
|
|
|
|
|
|
text-decoration: none;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-links button:hover,
|
|
|
|
|
|
.nav-links button.active,
|
|
|
|
|
|
.nav-link-item:hover {
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
opacity: 1;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-action {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
gap: 10px;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
flex-shrink: 0;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-icons {
|
|
|
|
|
|
display: flex;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
gap: 10px;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
align-items: center;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 13:41:39 +08:00
|
|
|
|
:deep(.nav-github-stars) {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.nav-github-stars .github-stars-link) {
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
gap: 4px;
|
|
|
|
|
|
text-decoration: none;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 13:41:39 +08:00
|
|
|
|
:deep(.nav-github-stars .github-stars-link:hover) {
|
2026-01-27 02:06:42 +08:00
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-15 13:41:39 +08:00
|
|
|
|
:deep(.nav-github-stars .github-stars-wrapper) {
|
|
|
|
|
|
padding-left: 0 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-promo {
|
2026-03-18 12:12:42 +08:00
|
|
|
|
height: 30px;
|
2026-03-16 00:26:59 +08:00
|
|
|
|
max-height: 30px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
gap: 6px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: #1d1d1f;
|
|
|
|
|
|
padding: 0 16px;
|
2026-03-16 00:26:59 +08:00
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
transform-origin: top center;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 1;
|
2026-03-18 12:12:42 +08:00
|
|
|
|
will-change: transform, opacity, max-height, background-color, color;
|
2026-03-16 00:26:59 +08:00
|
|
|
|
transition:
|
|
|
|
|
|
transform 0.16s ease-out,
|
|
|
|
|
|
opacity 0.16s ease-out,
|
|
|
|
|
|
max-height 0.16s ease-out,
|
2026-03-18 12:12:42 +08:00
|
|
|
|
background-color 0.22s ease-out,
|
|
|
|
|
|
color 0.22s ease-out;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.nav-promo a {
|
2026-03-18 12:12:42 +08:00
|
|
|
|
color: var(--top-promo-link-color, #0066cc);
|
2026-03-15 13:41:39 +08:00
|
|
|
|
text-decoration: none;
|
2026-03-18 12:12:42 +08:00
|
|
|
|
transition: color 0.25s ease-out;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-27 02:06:42 +08:00
|
|
|
|
.button {
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 0;
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
opacity: 1;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
transition: opacity 0.2s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.button:hover {
|
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.button .text {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.button .option-icon {
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
height: 20px;
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.button .text-icon {
|
|
|
|
|
|
width: 14px;
|
|
|
|
|
|
height: 14px;
|
2026-02-24 18:22:58 +08:00
|
|
|
|
color: var(--vp-c-text-1) !important;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
.lang-switch-wrapper {
|
|
|
|
|
|
position: relative;
|
2026-01-27 02:06:42 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.lang-dropdown {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 100%;
|
2026-05-14 11:09:48 +08:00
|
|
|
|
right: -10px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
margin-top: 12px;
|
|
|
|
|
|
background: var(--vp-c-bg);
|
|
|
|
|
|
border: 1px solid var(--vp-c-divider);
|
2026-03-15 13:41:39 +08:00
|
|
|
|
border-radius: 16px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
padding: 6px;
|
|
|
|
|
|
min-width: 140px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.14);
|
2026-01-26 13:00:54 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 2px;
|
|
|
|
|
|
max-height: 300px;
|
|
|
|
|
|
overflow-y: auto;
|
2026-03-16 00:26:59 +08:00
|
|
|
|
z-index: 20;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.lang-item {
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
color: var(--vp-c-text-1);
|
|
|
|
|
|
transition: background 0.2s;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.lang-item:hover {
|
|
|
|
|
|
background: var(--vp-c-bg-soft);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.buy-btn {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: #0071e3;
|
|
|
|
|
|
color: #fff !important;
|
|
|
|
|
|
padding: 7px 16px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
border-radius: 980px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
font-size: 13px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
font-weight: 500;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
line-height: 1;
|
|
|
|
|
|
transition: all 0.2s ease;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.buy-btn:hover {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: #0077ed;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
transform: scale(1.02);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.buy-btn.large {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
|
font-size: 15px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
margin-top: 20px;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-container {
|
|
|
|
|
|
max-width: 1280px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
margin: 0 auto 96px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
padding: 0 40px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 18:17:31 +08:00
|
|
|
|
.section-band-learning {
|
|
|
|
|
|
width: 100vw;
|
|
|
|
|
|
max-width: none;
|
|
|
|
|
|
margin: 0 calc(50% - 50vw) 96px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: #f5f5f7;
|
2026-03-27 18:17:31 +08:00
|
|
|
|
border-radius: 0;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
padding-top: 64px;
|
|
|
|
|
|
padding-bottom: 64px;
|
2026-03-27 18:17:31 +08:00
|
|
|
|
padding-left: max(40px, calc((100vw - 1280px) / 2 + 40px));
|
|
|
|
|
|
padding-right: max(40px, calc((100vw - 1280px) / 2 + 40px));
|
2026-03-15 13:41:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-27 18:17:31 +08:00
|
|
|
|
.section-band-learning .section-container {
|
|
|
|
|
|
max-width: 1280px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-band-learning .section-junior {
|
|
|
|
|
|
margin-top: 72px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dark .section-band-learning {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
background: rgba(255, 255, 255, 0.03);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-26 13:00:54 +08:00
|
|
|
|
.section-header {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
margin-bottom: 44px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-category {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
margin-bottom: 14px;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 0;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
color: #1d1d1f;
|
|
|
|
|
|
letter-spacing: -0.024em;
|
|
|
|
|
|
font-family:
|
|
|
|
|
|
-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'PingFang SC',
|
|
|
|
|
|
sans-serif;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-headline {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
font-size: 64px;
|
|
|
|
|
|
line-height: 1.08;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
letter-spacing: -0.034em;
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
color: #1d1d1f;
|
|
|
|
|
|
font-family:
|
|
|
|
|
|
-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'PingFang SC',
|
|
|
|
|
|
sans-serif;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.section-sub {
|
|
|
|
|
|
font-size: 21px;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
line-height: 1.4;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
font-weight: 400;
|
2026-03-15 13:41:39 +08:00
|
|
|
|
letter-spacing: -0.01em;
|
|
|
|
|
|
color: #6e6e73;
|
|
|
|
|
|
max-width: 760px;
|
|
|
|
|
|
font-family:
|
|
|
|
|
|
-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'PingFang SC',
|
|
|
|
|
|
sans-serif;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-12 02:26:21 -04:00
|
|
|
|
.dark .section-category,
|
|
|
|
|
|
.dark .section-headline {
|
|
|
|
|
|
color: var(--vp-c-text-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.dark .section-sub {
|
|
|
|
|
|
color: var(--vp-c-text-2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.section-headline {
|
|
|
|
|
|
font-size: 42px;
|
|
|
|
|
|
}
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
.nav-links {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
.nav-promo {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
height: 28px;
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
.section-band-learning {
|
|
|
|
|
|
margin-bottom: 96px;
|
|
|
|
|
|
padding-top: 42px;
|
|
|
|
|
|
padding-bottom: 42px;
|
|
|
|
|
|
padding-left: 24px;
|
|
|
|
|
|
padding-right: 24px;
|
|
|
|
|
|
}
|
2026-03-27 18:17:31 +08:00
|
|
|
|
|
2026-05-14 11:09:48 +08:00
|
|
|
|
.section-band-learning .section-junior {
|
|
|
|
|
|
margin-top: 56px;
|
|
|
|
|
|
}
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
2026-05-14 11:09:48 +08:00
|
|
|
|
</style>
|
2026-01-26 13:00:54 +08:00
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
.VPHome {
|
2026-03-15 13:41:39 +08:00
|
|
|
|
padding-top: 84px !important;
|
2026-01-26 13:00:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|