资产如水。
回报如光。

项目记录

这一页没有第二页。首屏是设计稿里的样子,往下滚,是它的来处、搭法和可以搬走的部分。

LŪMEN // ÍNDEX 是一个虚构的 DeFi / 私人银行品牌落地页。我把它搬进博客,当作一次完整的 「设计稿 → 可发布页面」移植练习。

01生态系统

项目背景

它没有真实业务,卖点是气质:纯黑底、冷蓝强调色 #AFDDFF、中性无衬线、1px 细网格加节点连线。整套视觉语言只为一件事服务——让人相信「精密、克制、有资本感」。

我真正想验证的不是把它做成独立站点,而是一个更窄的问题:一个完全不属于博客调性的单屏页面,能不能安静地住在博客里?不做 iframe,不做外链跳转,而是博客自己的一个路由,进入时没有博客导航、侧栏、页脚和壁纸装饰。

  • 还原目标:首屏占满视口,版式、时序、配色对齐设计稿。
  • 工程目标:不引入 React / GSAP / framer-motion 等运行时,动效全部走原生 CSS。
  • 最终形态:首屏之后接一份项目说明——也就是你现在读到的地方。页面内的导航项、CTA 都能点,会带你平滑滚动到对应小节;首屏那三个方框本身也能点开,见下。

首屏那三个方框在说什么

[ 核心实体 ]
跨 12 个区域同时驻留的推理内核。每一次呼吸都是一次全量校验,不合规的数据在到达账本之前就被拦下。
[ 流明洞察 ]
把行情、持仓与新闻压进同一个语义空间,再抽出可比对的结构。它不预测价格,只标出与你上一次决定不同的地方。
[ 连通 ]
结算层与托管层之间不经过任何中间账本。跨区传输的承诺上限是 40 毫秒,超时即撤回,不排队。
02流动性池

技术栈与移植路径

组件
LumenPage.astro(首屏与正文)+ JellyfishField.astro(首屏水母交互层),均在 src/components/lumen/
原稿
React 18 + Vite + Tailwind CSS v3
落地
Astro 7 + Tailwind v4 + 原生 CSS @keyframes,水母层是 canvas 2D
依赖
零。没有 React runtime,也没有动画库
接入
frontmatter 里一条 fullBleed: true,文章路由就把它渲染进裸布局,而不是博客主布局
边界
astro.config.mjs 的 swup ignore 登记这条路由,进出这一页走整页导航
字体
设计稿的 Graphik LCG / Manrope 未随项目分发,回退到已通过 Astro Font API 加载的 Inter(--font-inter)

顺带一个好消息:Tailwind v3 → v4 在这类页面上几乎 1:1。bg-white/[0.04]、text-[13px]、top-[178px]、ease-[cubic-bezier(0.16,1,0.3,1)]这些任意值语法两版通用,所以移植的主要成本不在类名,而在把 React 的组件状态与副作用,翻译成 CSS 加少量原生 JS。

03流明指数

设计要点

  • 网格骨架:4 条竖线(12.6% / 37.5% / 61.9% / 86.2%)乘 2 条横线(32.7% / 71.4%),1px、白色 4% 透明度,交叉点放 8 个十字标记。整页的「技术感」几乎全来自这一层。
  • 节点与连线:三组 80px(移动)/ 100px(桌面)的空心方框,配引出标签[ CORE_ENTITY ]、[ LUMINOUS_INSIGHT ]、[ CONNECTIVITY ],再用 1px 细线连到画面元素,制造「数据在系统里流动」的错觉。
  • 动效时序:入场从 200ms 铺到 2100ms,六种动画fadeUp / fadeIn / slideInLeft /slideInRight / scaleIn / gridReveal,统一缓动cubic-bezier(0.16, 1, 0.3, 1)。快出慢收,观感「贵」而不「飘」。
  • 缺角卡片:底部右侧的信息框不是矩形,而是用 <svg><polygon> 描边、左下角切掉一块。这是全套稿里最容易被忽略、却最提气质的一笔。
  • 排版层级:标题 32 / 48 / 68px 三档(移动 / 平板 / 桌面),正文标签固定 13px、行高 15.6px。小字号标签加大字号标题的强对比,撑住了「私人银行」的调性。
04治理

踩坑与可复用点

  • Tailwind v4 的 data-[...] 变体只作用于元素自身。 全屏菜单的data-menu-open 挂在 <section> 上,后代元素写data-[menu-open=true]: 永远匹配不到;必须给父元素加 group、改用group-data-[menu-open=true]:。这个坑当时让移动端菜单完全打不开。
  • 全幅页要显式关掉博客装饰。 樱花 canvas、欢迎 toast、背景壁纸层、顶部高光、背景装饰层,都要在这一页里display: none,否则会浮在首屏上面。
  • 远端背景视频必须留退路。 视频挂在外部 CDN,可能被网络拦掉。做法是先铺一层 CSS 冷光渐变当底,再监听 error 把 <video>摘掉。最差情况用户看到的是一块成品,而不是黑屏。
  • 滚动条是全局隐藏的。博客把根滚动条换成了顶部阅读进度条,全幅页不用额外处理,只要不锁overflow 就能正常滚——本页原本是「锁滚动」的单屏,现在改成了「可滚动」。
  • 远端视频里的水母改不了运动。首屏背景那三只是烤进 mp4 的像素,鼠标移到哪都不会有反应。所以想要「能互动的水母」只有两条路:换掉整段视频自己重做,或者在视频之上再叠一层可控的图层。选了后者。
  • 叠一层 canvas 线框水母。 5 只 1px #AFDDFF 描边的小水母(伞盖 26–38px、各 3 根 verlet 触须),用的是页面自己的视觉语言,刻意比主景更小更暗,当「前景里的小鱼群」。受力上让「实际距离 − 理想距离」的正负天然给出双向力:远则趋光、贴到 80px 内自动反转成斥力,再加一层彼此分离,最后落成一个会呼吸的小群落;点击首屏空白处从点击点向外辐射推力,1.5 秒衰减回趋光。兜底三条:prefers-reduced-motion 时整层不渲染,首屏滚出视口或标签页切后台就停掉动画循环,canvas 按devicePixelRatio 缩放保证 1px 描边不发虚。
  • 可复用:底层素材不可控,就在它上面叠一层可控的。这条对任何「效果很好但不能响应交互」的现成素材都成立——视频、GIF、第三方 iframe 都一样。关键是新图层的视觉语言必须跟页面一致(这里直接复用了已有的 1px 网格与 #AFDDFF),否则就会从「同一片海」变成「贴纸叠在照片上」。
  • opacity: 0 不挡命中测试。 方框的入场动画是scaleIn(opacity: 0 → 1),动画跑完之前它虽然看不见,却已经是合法的 hover / click 目标——鼠标推过去就能点亮一个看不见的方框,还能点开一块从空气里长出来的面板。 修法是动画结束前给它 pointer-events: none,等 animationend 再放开。这条对任何「先隐藏、再动画出现」的元素都成立。
  • 面板生长必须钉住连线端点。 六条折线的终点写死在60%,27% / 32%,58% / 50%,63%,正好是三个方框的左上角。所以面板只能朝右下长;一旦改成居中生长或向上翻,那六条线的坐标就全废了。
  • 两个组件之间用 CustomEvent 解耦。 方框绽开要顺手惊散水母,但水母层是独立组件、不该被页面 import。做法是在 #lumen-hero 上派发一个带坐标的 lumen-burst,水母层自己监听。这样水母的触发源可以是方框、也可以是别的东西,而页面完全不需要知道水母层内部长什么样。
  • 百分比定位 + 固定宽面板,必须算窄屏断裂点。 方框用left: 60% 这种百分比定位,面板却是固定宽。节点 2(32%)到节点 3(50%)只有 18vw,1440px 下放得下 240px、1280px 下就不够了。最后把宽度写成min(240px, 15vw)——只要它永远小于那个 18vw 的间隙,就不会碰到邻居。交互门槛同时提到lg:宁可窄屏不给,也不给一个被切掉的面板。
  • 可复用:这套「全幅 hero + 下方正文」的骨架可以整块搬走。以后做任何单屏落地页,复制组件、换素材、改 frontmatter 两条字段即可。
WELCOME欢迎来到载尘望星

很高兴在这里遇见你。