/* ============================================================
   Live OnBoard — 站点样式
   首屏是固定深色「品牌舞台」：认可的字标动画只有浅色版（配深底），
   深色字标动画不存在，所以首屏不跟随系统亮暗。
   ============================================================ */

:root {
  --ink:          #03070D;
  --ink-raised:   #08111F;
  --text:         #EDF2F9;
  --text-body:    #A9B7CC;
  --text-muted:   #8595AE;
  --text-dim:     #66768D;
  --cobalt:       #2F76FF;
  --cobalt-lift:  #4384FF;
  --line:         rgba(255, 255, 255, .13);

  --ease: cubic-bezier(.2, .7, .3, 1);

  /* 一套间距刻度，全站只用这几个值。
     之前每处间距各写一个 clamp()，六个互不相干的数堆在一起，
     读起来就是「密」—— 不是间距不够，是间距之间没有关系。 */
  --sp-1: 8px;
  --sp-2: 12px;
  --sp-3: 18px;
  --sp-4: 26px;
  --sp-5: 36px;
  --sp-6: 52px;
  --sp-7: 72px;

  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-width: 320px;
  background: var(--ink);
  color: var(--text-body);
  /* 中文字形交给 PingFang SC（Mac 原生）/ 微软雅黑（Windows），不加载 web font */
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
               Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
               Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; }

img { max-width: 100%; height: auto; display: block; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 18px;
  border-radius: 0 0 10px 0;
  background: var(--cobalt);
  color: #fff;
  font-size: 14px;
  text-decoration: none;
}
.skip-link:focus { left: 0; }

/* ---------- 顶栏 ---------- */

/* 顶栏跟着页面走：贴顶时透明无形，一开始滚就加毛玻璃和细底边。 */
.topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 20;
  height: 68px;
  transition: background-color .35s var(--ease), border-color .35s var(--ease),
              backdrop-filter .35s var(--ease);
  border-bottom: 1px solid transparent;
}
.past-hero .topbar {
  background: rgba(3, 7, 13, .72);
  border-bottom-color: rgba(255, 255, 255, .07);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
}

/* 字标常驻顶栏 —— 这是全页唯一的品牌位。
   基线（爬虫 / 无 JS / reduced-motion / 本次会话已看过）第一帧就在。
   只有首访播入场动画时先藏起来，等那张大字标飞上来落位再显形；
   于是屏幕上任何时刻都只有一个 logo。 */
.topbar-brand {
  display: block;
  flex: none;        /* 否则窄屏下会被导航压小，字标越挤越瘦 */
  width: 132px;
  opacity: .92;
}
.intro-play .topbar-brand { opacity: 0; }
.intro-play.wm-landed .topbar-brand { opacity: .92; transition: opacity .3s var(--ease); }
.topbar-brand img { width: 100%; }
a.topbar-brand:hover { opacity: 1; }

.topbar-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  padding: 0 clamp(18px, 3vw, 34px);
}

.nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.nav-link {
  flex: none;
  padding: 7px 13px;
  border-radius: 9px;
  color: var(--text-muted);
  font-size: 14px;
  white-space: nowrap;   /* 否则窄屏下 flex 会把「功 能」压成竖排 */
  text-decoration: none;
  transition: color .25s var(--ease), background-color .25s var(--ease);
}
a.nav-link:hover { color: var(--text); background: rgba(255, 255, 255, .06); }

/* 全站统一的链接反馈：变色 + 1px 上移。
   四种不同的 hover 会让页面显得是四个人做的。 */
a.nav-link, a.foot-link, a.section-link, .cap-card {
  transition: color .22s var(--ease), background-color .22s var(--ease),
              border-color .22s var(--ease), transform .22s var(--ease);
}
a.nav-link:hover, a.foot-link:hover, a.section-link:hover { transform: translateY(-1px); }
.cap-card:hover { transform: translateY(-2px); }

/* 还没做好的页面：不是链接，点不动。同时是「还欠什么」的提醒。 */
.nav-link.is-pending {
  color: #4C5A6E;
  cursor: default;
  user-select: none;
}

/* 语言切换：跟功能导航拉开一点距离，加一道细分隔 */
.nav-link.is-lang {
  margin-left: 8px;
  padding-left: 17px;
  border-left: 1px solid var(--line);
  border-radius: 0 9px 9px 0;
}

/* ---------- 首屏 ---------- */

/* 首屏 = 五格文字 + 一件被视口下沿切掉的产品实体。
   文字块高度固定，剩下的全归舞台 —— 于是无论多高的屏，切口都正好落在折线上。 */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 100svh;
  padding: calc(68px + var(--sp-3)) clamp(20px, 5vw, 48px) 0;
  overflow: hidden;
  text-align: center;
}

/* 一束从顶栏后面打下来的光，落在下方的面板上。
   之前是一个平的径向渐变居中放着，读起来就是「一块 CSS 渐变」；
   光要有来处才像光。 */
.hero-glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(62rem 34rem at 50% -6%, rgba(47, 118, 255, .24), transparent 66%),
    radial-gradient(24rem 14rem at 50% -3%, rgba(146, 199, 255, .16), transparent 70%),
    radial-gradient(86rem 30rem at 50% 132%, rgba(3, 7, 13, .8), transparent 62%);
}

/* 极轻的颗粒。大面积深色渐变一定会有色带，加一层噪点就没了。 */
.hero-glow::after {
  content: '';
  position: absolute;
  inset: 0;
  opacity: .04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* 上下 auto 外边距：屏幕越高，多出来的高度**平分**到文字块的上下两侧，
   于是文字始终在「顶栏到实体之间」那段空间里居中，
   实体自己贴着首屏底。全堆到下面会在高屏上空出三百多像素。 */
.hero-inner {
  position: relative;
  z-index: 2;
  flex: none;
  width: 100%;
  max-width: 880px;
  margin: auto 0;
}

/* ---------- 入场舞台 ----------
 *
 * 那张大字标只在首访、允许动效、JS 可用时出现，播完自己飞进顶栏。
 * 它是一次运镜，不是页面家具 —— 所以基线里根本不存在，
 * 品牌位由顶栏那枚常驻字标承担（爬虫和无 JS 第一帧就看得到）。 */

.intro-stage { display: none; }

.intro-play .intro-stage {
  display: grid;
  place-items: center;
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
}
.intro-play.wm-gone .intro-stage { display: none; }

.intro-wm {
  width: min(880px, 84vw);
  height: auto;
  transform-origin: top left;   /* 落点由 JS 实测顶栏字标的位置算出 */
}
.intro-play.wm-flying .intro-wm {
  transition: transform .95s cubic-bezier(.62, .02, .2, 1);
}

/* ---------- 文字 ----------
 *
 * 五格，字号层层拉开：
 *   口号（小·全大写·宽字距）→ 标题（全页最响）→ 副文 → 按钮 → 小字
 * 之前是七格挤在一屏里，而且最响的是 880px 的字标、标题只有 35px ——
 * 层级是倒的，标题读起来像字标的图注。 */

.tagline {
  margin: 0;
  color: #7E9AC4;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .19em;
  text-transform: uppercase;
}

/* 中文没有大小写，全大写这条失效。改用疏排 + 更大字号来对应同样的视觉重量。
   letter-spacing 会在末字后面留一格，用负 margin 补回来，保持居中。 */
html[lang="zh-Hans"] .tagline {
  text-transform: none;
  font-size: 15px;
  letter-spacing: .3em;
  margin-right: -.3em;
}

.hero h1 {
  margin: var(--sp-3) 0 0;
  color: #F4F7FC;
  font-size: clamp(33px, 5.4vw, 62px);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -.032em;
  text-wrap: balance;   /* 两行等长，不留孤字 */
}

/* 中文全角字比拉丁字宽得多，同字号下要单独调小。
   更要紧的是断行：中日韩几乎每个字后面都能断，880px 栏宽下
   「全双工语音架构，思考、| 写作、编码样样精通」会把并列关系拦腰劈开，
   而 CSS 没有任何办法把断点挪到「，」上（贪心填行一定先填满）。
   所以中文标题不设栏宽，一行走完 —— 20 个字 × 4.4vw 恒小于可用宽度。 */
html[lang="zh-Hans"] .hero-inner { max-width: 1060px; }
html[lang="zh-Hans"] .hero h1 {
  font-size: clamp(27px, 4.3vw, 50px);   /* 20 字 = 86vw，可用宽度 90vw，恒有余量 */
  line-height: 1.26;
  letter-spacing: 0;
}

.hero-lede {
  max-width: 640px;
  margin: var(--sp-3) auto 0;
  color: #94A6BF;
  font-size: clamp(16.5px, 1.5vw, 19.5px);
  line-height: 1.6;
  text-wrap: balance;   /* 否则末行只剩两个词，吊在那里 */
}
html[lang="zh-Hans"] .hero-lede { line-height: 1.8; }

/* ---------- 按钮 ---------- */

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: var(--sp-5);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  height: 54px;
  padding: 0 30px;
  border: 1px solid transparent;
  border-radius: 13px;
  font-size: 16px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .25s var(--ease), border-color .25s var(--ease),
              transform .25s var(--ease), box-shadow .25s var(--ease);
}

.btn-primary {
  background: var(--cobalt);
  color: #fff;
  box-shadow: 0 6px 26px rgba(47, 118, 255, .3);
}
.btn-primary:hover {
  background: var(--cobalt-lift);
  transform: translateY(-1px);
  box-shadow: 0 10px 32px rgba(47, 118, 255, .38);
}

.btn-ghost {
  border-color: var(--line);
  color: var(--text);
}
.btn-ghost:hover {
  background: rgba(255, 255, 255, .06);
  border-color: rgba(255, 255, 255, .22);
}

.btn:focus-visible {
  outline: 2px solid var(--cobalt-lift);
  outline-offset: 3px;
}

/* ---------- 小字 ---------- */

.hero-meta {
  margin: var(--sp-3) 0 0;
  color: var(--text-dim);
  font-size: 13px;
}
.hero-meta .dot { margin: 0 .55em; opacity: .6; }
.hero-meta .version::before { content: '·'; margin: 0 .55em; opacity: .6; }

.hero-fallback {
  margin: 14px 0 0;
  color: var(--text-dim);
  font-size: 13px;
}
.hero-fallback a { color: var(--text-muted); text-underline-offset: 3px; }

/* ---------- 入场淡入 ----------
   基线是「全部可见」。只有 JS 确认要播动画时才允许藏起来。
   → 无 JS / 爬虫 / reduced-motion / 重复访问：文字第一帧就在。 */

.intro-play .reveal {
  opacity: 0;
  transform: translateY(14px);
}
.intro-play .reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity .85s var(--ease), transform .85s var(--ease);
}

.intro-play .hero-glow {
  opacity: 0;
  animation: glow-in 1.1s var(--ease) .1s forwards;
}
@keyframes glow-in { to { opacity: 1; } }

/* ---------- 向下提示（双箭头） ---------- */

/* 在流里，落在小字和产品面板之间的空当。
   面板被下沿切掉本身已经是「下面还有」，这两道箭头是补一句，所以压得很轻。 */
.scroll-cue {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-top: var(--sp-2);
  border-radius: 50%;
  color: #4C5D77;
  transition: color .25s var(--ease), background-color .25s var(--ease), opacity .4s var(--ease);
}
.scroll-cue:hover { color: var(--text); background: rgba(255, 255, 255, .05); }

/* 两道箭头依次下沉，间隔明显，不抢戏 */
.scroll-cue .cue-1 { animation: cue-drift 2.4s ease-in-out infinite; }
.scroll-cue .cue-2 { animation: cue-drift 2.4s ease-in-out .18s infinite; opacity: .45; }

@keyframes cue-drift {
  0%, 60%, 100% { transform: translateY(0);   opacity: inherit; }
  30%           { transform: translateY(3px); }
}

/* 滚动之后就没用了，淡出。只动 opacity —— 它在流里，收掉会让版面跳。 */
.has-scrolled .scroll-cue { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .scroll-cue .cue-1, .scroll-cue .cue-2 { animation: none; }
}

/* ---------- 首屏底部的产品实体 ----------
 *
 * 一次正在进行的会话，被视口下沿切掉。它同时干三件事：
 * 说清产品是什么、给首屏一个可以落眼的实体、告诉你下面还有。
 * 结构和「为什么不是一扇窗口」写在 templates/hero-session.mjs。 */

.hero-stage {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  flex: none;
  width: min(1060px, 100%);
  margin: var(--sp-4) 0 0;
}

/* 窗口周围的一圈冷光 —— 最亮的一道正好压在窗口上沿，
   于是它是「浮」在页面上的，不是「贴」上去的。
   窗口本身不透明，所以这团光只从边缘漏出来。 */
.hero-stage::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(1040px, 145%);
  height: 420px;
  transform: translate(-50%, -46%);
  background: radial-gradient(closest-side, rgba(47, 118, 255, .36), rgba(47, 118, 255, .10) 54%, transparent 78%);
  filter: blur(44px);
  pointer-events: none;
}

/* App 真实的 HUD 胶囊，HTML/CSS 复刻 —— 不是截图，也不是视频。
   左边一颗蓝点（在听），中间一条蓝紫渐变的声波，右边隔出一格放「回看历史」。
   它是完整的一件东西，所以**不切** —— 切一颗胶囊只会让它看着像坏了。 */
.hud {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2.2vw, 28px);
  width: min(820px, 100%);
  height: clamp(88px, 10.6vw, 150px);
  padding-left: clamp(22px, 2.6vw, 34px);
  position: relative;
  border: 1px solid rgba(255, 255, 255, .10);
  border-bottom: 0;
  border-radius: clamp(30px, 4vw, 52px) clamp(30px, 4vw, 52px) 0 0;
  background: linear-gradient(180deg, #1b1b22, #121218);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .07) inset, 0 -14px 60px rgba(0, 0, 0, .5);
  overflow: hidden;
}

/* 身子往下续到窗口边。
   胶囊本身高度不动（拉长了就不像那颗胶囊了），只是把它的底色和左右边框
   接着往下画，多出来的部分被 .hero 的 overflow 裁掉。
   于是「上面留圆角、下面贴住窗口」，而不是把一颗胶囊抻成一个盒子。 */
.hud::after {
  content: '';
  position: absolute;
  left: -1px;
  right: -1px;
  top: 100%;
  height: 30vh;
  border-left: 1px solid rgba(255, 255, 255, .10);
  border-right: 1px solid rgba(255, 255, 255, .10);
  background: #121218;
}

/* 在听 */
.hud-dot {
  flex: none;
  width: clamp(11px, 1.2vw, 16px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--cobalt-lift);
  box-shadow: 0 0 14px rgba(67, 132, 255, .85);
}
.js .hud-dot { animation: hud-pulse 2.1s var(--ease) infinite; }
@keyframes hud-pulse {
  0%   { box-shadow: 0 0 14px rgba(67, 132, 255, .85), 0 0 0 0 rgba(67, 132, 255, .45); }
  70%  { box-shadow: 0 0 14px rgba(67, 132, 255, .85), 0 0 0 9px rgba(67, 132, 255, 0); }
  100% { box-shadow: 0 0 14px rgba(67, 132, 255, .85), 0 0 0 0 rgba(67, 132, 255, 0); }
}

/* 声波。每根竖条自己一个颜色，从蓝渐到品红 —— 颜色在构建时算好写进 --c。
   基线就是这组静止高度：无 JS / 爬虫 / reduced-motion 看到的是一条静止的波形，
   不是一排等高的柱子。 */
.hud-wave {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
  height: clamp(28px, 5vw, 70px);   /* 真机上波形占胶囊高度近一半，太矮就不像声音了 */
  overflow: hidden;
}
.hud-wave i {
  flex: none;
  width: 2px;
  height: 100%;
  border-radius: 1px;
  background: var(--c);
  transform: scaleY(var(--s));
}
.js .hud-wave i {
  animation: hud-wave var(--d) ease-in-out infinite alternate;
  animation-delay: calc(var(--i) * -.055s);
}
@keyframes hud-wave {
  from { transform: scaleY(calc(var(--s) * .28)); }
  to   { transform: scaleY(var(--s)); }
}

/* 右边隔出来的那一格 */
.hud-tail {
  display: grid;
  place-items: center;
  flex: none;
  align-self: stretch;
  width: clamp(74px, 8vw, 104px);
  border-left: 1px solid rgba(255, 255, 255, .08);
  background: rgba(255, 255, 255, .035);
}
.hud-btn {
  display: grid;
  place-items: center;
  width: clamp(38px, 3.9vw, 50px);
  aspect-ratio: 1;
  border: 1px solid rgba(255, 255, 255, .17);
  border-radius: 50%;
  color: #C4D0E2;
}
.hud-glyph { width: 48%; height: 48%; }

/* ---------- 首屏之下的窄带 ----------
 *
 * 一句产品定义、一句它接得上谁。这两句原来挤在首屏 h1 底下。 */

.overview {
  padding: clamp(56px, 9vh, 96px) clamp(20px, 5vw, 48px);
  text-align: center;
}

.overview-inner { max-width: 720px; margin: 0 auto; }

.overview-def {
  margin: 0;
  color: var(--text);
  font-size: clamp(19px, 1.9vw, 25px);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -.015em;
  text-wrap: balance;
}
html[lang="zh-Hans"] .overview-def { font-size: clamp(18px, 1.7vw, 23px); letter-spacing: 0; line-height: 1.55; }

.overview-works {
  margin: var(--sp-3) 0 0;
  color: var(--text-muted);
  font-size: clamp(15px, 1.25vw, 16.5px);
  line-height: 1.7;
  /* balance 而不是 pretty：两行均分，断点就落在破折号前，
     不会把「Claude Code」这样的产品名劈成两行。 */
  text-wrap: balance;
}

/* ---------- 首屏之下的区块 ---------- */

.section {
  padding: clamp(80px, 12vh, 140px) 0;
  border-top: 1px solid rgba(255, 255, 255, .06);
}

.section-inner {
  display: grid;
  grid-template-columns: minmax(280px, 5fr) minmax(320px, 7fr);
  gap: clamp(36px, 6vw, 80px);
  align-items: center;
  width: min(1120px, 100% - clamp(40px, 10vw, 96px));
  margin: 0 auto;
}

/* 满宽版式：文案居中在上，组件在下。
   实测：Cowork 表格工具栏 8 个分组需要约 1100px，两栏只能给到 762px（溢出 486px），
   所以这一屏必须走上下布局，容器也放到最宽。 */
.section--full .section-inner {
  display: block;
  width: min(1180px, 100% - clamp(32px, 6vw, 72px));
  max-width: none;
  text-align: center;
}
.section--full .section-copy p { max-width: 62ch; margin-left: auto; margin-right: auto; }
.section--full .section-component { margin-top: 4px; text-align: left; }
.section--full .cw-tabs { margin-left: auto; margin-right: auto; }

/* 居中版式：没有配图、也不该有配图的那一屏。
   夹在「两栏 + 视频」和「满宽演示」中间，纯排版反而是节奏上的喘息。
   拿不出真素材时宁可留白 —— 摆一张架构示意图，这页就从产品变成研究报告了。 */
.section--center {
  text-align: center;
  border-top: 0;   /* 上一屏已经有分隔线，这里再来一条就把喘息切断了 */
}

.section--center .section-inner {
  display: block;
  width: min(880px, 100% - clamp(40px, 10vw, 96px));
}

/* 这一屏的容器同时带 .section-copy（为了拿字色字号），所以下面几条都要
   多一级特异性 —— 否则 .section-copy 的 max-width 和 margin:0 会把
   眉标和标题顶到左边去，只有正文那两栏还是居中的。 */
.section--center .section-inner .section-eyebrow {
  max-width: none;
  margin: 0 0 18px;
}

.section--center .section-inner h2 {
  margin: 0 auto;
  max-width: 18ch;
  font-size: clamp(28px, 3.4vw, 46px);
  line-height: 1.14;
  letter-spacing: -.028em;
}
html[lang="zh-Hans"] .section--center .section-inner h2 {
  max-width: 20em;
  font-size: clamp(25px, 2.9vw, 38px);
  line-height: 1.4;
  letter-spacing: 0;
}

/* 正文分两栏排在大标题下面。是排版，不是图表。 */
.section--center .section-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(26px, 3.6vw, 52px);
  margin-top: clamp(30px, 4.4vh, 50px);
  text-align: left;
}
/* balance：中文几乎每个字后面都能断，贪心填行会在栏子末尾劈出「其余｜部分」
   这种半个词；均分行长，断点就有机会落到逗号上。 */
.section--center .section-cols p { margin: 0; max-width: none; text-wrap: balance; }

/* 「还没成形 → 成形」：标题进场时是虚的，落定才清晰。
   只在 JS 确认可用时才敢糊 —— 爬虫和无 JS 第一帧就是清楚的。 */
.js .section--center .scroll-reveal h2 { filter: blur(8px); }
.js .section--center .scroll-reveal.in h2 {
  filter: none;
  transition: filter 1.1s var(--ease) .12s;
}
@media (prefers-reduced-motion: reduce) {
  .js .section--center .scroll-reveal h2 { filter: none; }
}

/* 中文标题比英文长一截。5fr 的文字栏放不下 17 个字，text-wrap: balance 会
   均分成 9/8，把「无论它在做什么，你 | 都随时可以开口。」断在「你」后面 ——
   中日韩几乎每字都能断，均分就一定断在词里。给中文的文字栏多分一点，一行走完。 */
html[lang="zh-Hans"] .section--text-left .section-inner {
  grid-template-columns: minmax(300px, 6fr) minmax(300px, 6fr);
}

/* 交替左右，给页面节奏。演示那一列尽量宽 —— Cowork 的工具栏有 8 组，挤不得。 */
.section--text-right .section-inner {
  grid-template-columns: minmax(360px, 8.5fr) minmax(230px, 3.5fr);
  gap: clamp(28px, 3.5vw, 52px);
  align-items: center;
}
.section--text-right .section-copy { order: 2; }
.section--text-right .section-copy p { max-width: 34ch; }

.section-eyebrow {
  margin: 0 0 14px;
  color: #7E9AC4;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .19em;
  text-transform: uppercase;
}
html[lang="zh-Hans"] .section-eyebrow {
  text-transform: none;
  font-size: 14px;
  letter-spacing: .22em;
}

.section-copy h2 {
  margin: 0 0 20px;
  color: var(--text);
  font-size: clamp(24px, 2.4vw, 32px);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -.02em;
  text-wrap: balance;
}
html[lang="zh-Hans"] .section-copy h2 {
  font-size: clamp(22px, 2.1vw, 28px);
  letter-spacing: 0;
  line-height: 1.42;
}

.section-copy p {
  margin: 0 0 .95em;
  max-width: 46ch;
  color: var(--text-body);
  font-size: clamp(16px, 1.35vw, 17.5px);
  line-height: 1.68;
}

.section-link {
  display: inline-block;
  margin-top: 10px;
  color: var(--azure, #78B5FF);
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
}
a.section-link:hover { text-decoration: underline; text-underline-offset: 4px; }
.section-link.is-pending { color: #4C5A6E; cursor: default; user-select: none; }

/* ---------- 媒体位 ---------- */

.media {
  display: block;
  width: 100%;
  border-radius: 16px;
  background: #060B14;
}

/* 视频还没录：虚线占位。跟顶栏/页脚的灰字同一套语言，同样被 --strict 拦。 */
.media.is-pending {
  display: grid;
  place-content: center;
  gap: 6px;
  border: 1px dashed rgba(255, 255, 255, .13);
  text-align: center;
}
.media-label {
  color: #5E708C;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .01em;
}
.media-note {
  color: #3E4A5C;
  font-size: 12.5px;
}

/* ---------- 滚动淡入 ----------
   基线仍然是「全可见」。只有 JS 确认可用后才允许藏。 */

.js .scroll-reveal { opacity: 0; transform: translateY(18px); }
.js .scroll-reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity .85s var(--ease), transform .85s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .js .scroll-reveal { opacity: 1; transform: none; transition: none; }
}

/* ---------- 页脚 ---------- */

.footer {
  border-top: 1px solid rgba(255, 255, 255, .07);
  background: #020509;
}

.footer-inner {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) auto;
  gap: 48px;
  align-items: start;
  width: min(1120px, 100% - clamp(40px, 10vw, 96px));
  margin: 0 auto;
  padding: clamp(48px, 7vh, 76px) 0 clamp(36px, 5vh, 52px);
}

.footer-brand img { width: 168px; opacity: .82; }

.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(120px, auto));
  gap: clamp(32px, 5vw, 72px);
}

.footer-col-title {
  margin: 0 0 14px;
  color: var(--text);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .01em;
}

.footer-col ul { margin: 0; padding: 0; list-style: none; }
.footer-col li + li { margin-top: 9px; }

.foot-link {
  color: var(--text-dim);
  font-size: 14px;
  text-decoration: none;
  transition: color .22s var(--ease);
}
a.foot-link:hover { color: var(--text); }

.foot-link.is-pending { color: #3E4A5C; cursor: default; user-select: none; }

.footer-base {
  border-top: 1px solid rgba(255, 255, 255, .05);
}
.footer-base span {
  display: block;
  width: min(1120px, 100% - clamp(40px, 10vw, 96px));
  margin: 0 auto;
  padding: 20px 0 6px;
  color: #55637A;
  font-size: 13px;
}

/* 占位版本的小声明。比版权行再低一档 —— 它是脚注，不是内容。
   宽度跟版权行取同一个容器，于是两行左边线对齐；
   居中的话会跟左对齐的「© 2026」错开，反而显眼。 */
.footer-notice {
  width: min(1120px, 100% - clamp(40px, 10vw, 96px));
  margin: 0 auto;
  padding: 0 0 26px;
  color: #465269;
  font-size: 12.5px;
  line-height: 1.55;
}

/* ---------- 404 ---------- */

.notfound {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100svh;
  padding: 60px clamp(20px, 5vw, 48px);
  text-align: center;
}

.notfound-inner { max-width: 480px; }

.notfound-brand { display: block; width: 240px; margin: 0 auto; }

.notfound-code {
  margin: clamp(36px, 6vh, 58px) 0 0;
  color: var(--cobalt);
  font-size: clamp(58px, 8.5vw, 92px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.035em;
}

.notfound h1 {
  margin: 20px 0 0;
  color: var(--text);
  font-size: clamp(24px, 2.4vw, 30px);
  font-weight: 600;
  line-height: 1.32;
  letter-spacing: -.021em;
}

.notfound-body {
  margin: 14px 0 30px;
  color: var(--text-muted);
  font-size: 16px;
}

/* 同页的中文那半：一条细线隔开，字号小半档 ——
   是「另一种语言的同一句话」，不是页面上的第二件事。 */
.notfound-alt {
  margin-top: clamp(34px, 5vh, 52px);
  padding-top: clamp(30px, 4.5vh, 46px);
  border-top: 1px solid var(--line);
}

.notfound-alt-head {
  margin: 0;
  color: var(--text);
  font-size: clamp(20px, 2vw, 25px);
  font-weight: 600;
  line-height: 1.4;
}

/* ---------- 单薄内容页（/download/ 这类只有几行字的） ----------
 *
 * 四行字撑不起一整套版式。与其把它排得像一篇文章，
 * 不如按一幕来处理：整屏居中，跟 404 同一种姿态。 */

.plain {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100svh;
  padding: calc(68px + var(--sp-6)) clamp(20px, 5vw, 48px) var(--sp-7);
  text-align: center;
}

/* 首屏那束从顶栏后面打下来的光，淡一档。
   没有它，这页在全站里像是另一个网站做的。 */
.plain::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(54rem 30rem at 50% -8%, rgba(47, 118, 255, .17), transparent 66%),
    radial-gradient(20rem 12rem at 50% -4%, rgba(146, 199, 255, .11), transparent 70%);
}

.plain-inner { max-width: 560px; }

/* 中文全角字比拉丁字宽，同样一句话要多占三成宽度，560px 的栏必然断行。
   而中日韩几乎每个字后面都能断，断点落在哪儿完全不受控 ——
   与其一个字一个字去凑，不如把栏放宽到每段各自一行走完（最长一段 43 字 ≈ 774px）。
   这几页本来就只有三两句，一行一句反而更干净。 */
html[lang="zh-Hans"] .plain-inner { max-width: 800px; }

.plain h1 {
  margin: var(--sp-2) 0 var(--sp-4);
  color: var(--text);
  font-size: clamp(32px, 4.4vw, 50px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -.03em;
  text-wrap: balance;
}

html[lang="zh-Hans"] .plain h1 {
  font-size: clamp(29px, 3.8vw, 44px);
  line-height: 1.28;
  letter-spacing: 0;
}

.plain-body {
  margin: 0 auto var(--sp-3);
  color: var(--text-body);
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.65;
  /* balance 不是 pretty ——
     中文几乎每个字后面都能断，贪心填行会把「就在这｜几天」拦腰劈开。
     均分两行，断点自然落到句号上。 */
  text-wrap: balance;
}

.plain-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2) var(--sp-6);
  margin-top: var(--sp-5);
}
.plain .section-link { display: inline-block; }

/* 头衔列。名字底下不写句子，只列身份和分工 —— 一行一条。
   第一条是身份，比后面几条大一档亮一档；后面几条是具体分工。 */
.plain-roles {
  list-style: none;
  margin: var(--sp-4) 0 0;
  padding: 0;
}
.plain-roles li {
  color: var(--text-body);
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.75;
}
.plain-roles li:first-child {
  margin-bottom: var(--sp-1);
  color: var(--text);
  font-size: clamp(18px, 1.7vw, 22px);
  font-weight: 600;
  letter-spacing: -.012em;
}

/* 正文之后那一句：比正文低一档，但还在正文的阵营里。 */
.plain-note {
  margin: var(--sp-4) auto 0;
  color: var(--text-dim);
  font-size: 15px;
  line-height: 1.6;
}

/* 致谢。上一版压得太低（13px + #4E5A70 + 空 92px），第一眼根本看不见 ——
   人家出了力，不该藏。给它一条分隔线和一个小标题，它就成了一个板块，
   而不是飘在页尾的一行小字；但仍然排在链接之后，不抢这一页的主语。 */
.plain-credits {
  max-width: 62ch;
  margin: clamp(40px, 6vh, 64px) auto 0;
  padding-top: clamp(26px, 3.6vh, 40px);
  border-top: 1px solid var(--line);
}
html[lang="zh-Hans"] .plain-credits { max-width: none; }

.plain-credits-title {
  margin: 0 0 var(--sp-2);
  color: #7E9AC4;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .19em;
  text-transform: uppercase;
}
html[lang="zh-Hans"] .plain-credits-title {
  text-transform: none;
  font-size: 13px;
  letter-spacing: .3em;
  margin-right: -.3em;
}

/* 字号、颜色、行距全部跟上面的正文一致 —— 致谢不是附注，是正文的一部分 */
.plain-credits p:not(.plain-credits-title) {
  margin: 0;
  color: var(--text-body);
  font-size: clamp(16px, 1.4vw, 18px);
  line-height: 1.65;
  text-wrap: balance;
}

/* 被点名的人：全页正文里最亮的一处 */
.credit-name {
  color: var(--text);
  font-weight: 600;
}

/* ---------- 响应式 ---------- */

/* 窄屏放不下「字标 + 五项导航」：英文那五项就要 283px，加字标 132px
   已经超过 375 屏减去内边距的 343px。页面链接暂时收起，只留语言切换 ——
   首屏本来就有大号下载按钮，页脚有完整导航。
   ⚠️ 上线前要做成真正的移动端菜单，见 OPEN-ITEMS。 */
@media (max-width: 700px) {
  .nav-link:not(.is-lang) { display: none; }
  .nav-link.is-lang { margin-left: 0; padding-left: 13px; border-left: 0; }
}

@media (max-width: 760px) {
  .topbar-inner { padding: 0 16px; }

  /* 手机上文字更多、更高，所以整体收紧，让五格文字全留在折线之上 */
  .hero { padding: calc(68px + var(--sp-4)) 20px 0; }

  .tagline { font-size: 12px; letter-spacing: .17em; }

  .hero h1 { margin-top: var(--sp-3); font-size: clamp(30px, 8.6vw, 40px); line-height: 1.14; }
  html[lang="zh-Hans"] .hero h1 { font-size: clamp(25px, 7.4vw, 33px); line-height: 1.34; }

  .hero-lede { margin-top: var(--sp-3); font-size: 16px; line-height: 1.6; }

  .hero-actions { flex-direction: column; align-items: stretch; gap: 12px; margin-top: var(--sp-4); }
  .btn { width: 100%; }

  .hero-meta { margin-top: var(--sp-2); }
  .scroll-cue { margin-top: var(--sp-2); width: 38px; height: 38px; }

  .hero-stage { margin-top: var(--sp-4); }
  .hud { height: 72px; gap: 12px; padding-left: 18px; border-radius: 26px 26px 0 0; }
  .hud-dot { width: 10px; height: 10px; }
  .hud-wave { height: 30px; }
  .hud-tail { width: 62px; }
  .hud-btn { width: 34px; }

  .overview { padding: 56px 20px; }

  /* 窄屏单列。无论左右版式，文字都排在媒体前面 —— 阅读顺序优先。 */
  .section { padding: 64px 0; }
  .section-inner,
  .section--text-right .section-inner { grid-template-columns: 1fr; gap: 28px; }
  .section--center .section-cols { grid-template-columns: 1fr; gap: 20px; }
  .section--text-right .section-copy { order: 0; }
  .section-copy p { max-width: 100%; }

  .footer-inner { grid-template-columns: 1fr; gap: 34px; }
  .footer-brand img { width: 148px; }
  .footer-cols { grid-template-columns: repeat(2, 1fr); gap: 28px 20px; }
}

/* ---------- 无障碍 ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* ---------- 「自由搭建」那一屏的轮子 ----------
 *
 * 一块面板，三个格子，两道细分隔 —— 是一台机器，不是三个孤立的框。
 *
 * 关键是**露出邻项**：窗口比一行高，上下各留半行。只显示一行的方框看着
 * 就是个输入框；能瞥见上下还有别的选项，才像一个能转的轮子。
 * 上下用渐隐压暗，中间压一道淡钴蓝的「落定线」，眼睛知道该看哪儿。
 *
 * 第一格锁住（语音进出只在本地）。**不能用虚线框** —— 这站上虚线是
 * 「未完成占位」的意思（视频位就是），拿来表示「锁住」会被读成还没做好。 */

.slots {
  --row: 46px;                 /* 一项的高度 */
  --win: 116px;                /* 窗口高度：中间一整行 + 上下各露半行 */
  --slot-face: #0B0E15;
  width: min(620px, 100%);
  margin-inline: auto;
}

.slots-face {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: 18px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, .012)),
    var(--slot-face);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .06) inset, 0 22px 60px rgba(0, 0, 0, .45);
  overflow: hidden;
}

.slot { padding: 16px 0 18px; }
.slot + .slot { border-left: 1px solid rgba(255, 255, 255, .075); }

.slot-label {
  margin: 0 0 10px;
  color: #7285A0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-align: center;
  text-transform: uppercase;
}
html[lang="zh-Hans"] .slot-label { text-transform: none; font-size: 12px; letter-spacing: .12em; }

.slot-win { position: relative; height: var(--win); overflow: hidden; }

/* 落定线：中间那一行的位置，一道极淡的钴蓝带 + 上下发丝线 */
.slot-line {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: var(--row);
  margin-top: calc(var(--row) / -2);
  border-top: 1px solid rgba(255, 255, 255, .055);
  border-bottom: 1px solid rgba(255, 255, 255, .055);
  background: rgba(47, 118, 255, .07);
  pointer-events: none;
}

/* 上下压暗，露出来的邻项只是个影子，不抢中间那行 */
.slot-win::before,
.slot-win::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 38px;
  z-index: 2;
  pointer-events: none;
}
.slot-win::before { top: 0; background: linear-gradient(var(--slot-face) 30%, transparent); }
.slot-win::after { bottom: 0; background: linear-gradient(transparent, var(--slot-face) 70%); }

.slot-reel {
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0;
  list-style: none;
  /* JS 只改 --n，位移由这里算 —— 不写死像素，字号变了也不会错位。
     前半截是「把第 n 项摆到窗口正中」的偏移量。 */
  transform: translateY(calc((var(--win) - var(--row)) / 2 - var(--n, 0) * var(--row)));
}
.js .slot-reel { transition: transform 1.5s cubic-bezier(.13, .86, .21, 1); }
.js .slot-reel.is-snap { transition: none; }

.slot-reel li {
  display: grid;
  place-items: center;
  height: var(--row);
  padding: 0 10px;
  color: var(--text);
  font-size: clamp(14px, 1.25vw, 16.5px);
  font-weight: 500;
  letter-spacing: -.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 锁住的那格：没有轮子可转，那一项直接占满窗口居中，也不加渐隐 */
.slot.is-locked .slot-win::before,
.slot.is-locked .slot-win::after { display: none; }
.slot.is-locked .slot-reel { transform: none; }
.slot.is-locked li { height: var(--win); color: var(--text-muted); font-weight: 400; }

.slots-foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
}

.slots-roll {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 18px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  cursor: pointer;
  transition: color .22s var(--ease), background-color .22s var(--ease), border-color .22s var(--ease);
}
.slots-roll:hover { color: var(--text); background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .22); }
.slots-roll:focus-visible { outline: 2px solid var(--cobalt-lift); outline-offset: 3px; }
.slots-roll-icon { width: 15px; height: 15px; flex: none; }

/* 转的时候图标跟着转一圈，按钮暂时不可点 */
.slots.is-rolling .slots-roll { pointer-events: none; color: var(--text-dim); }
.js .slots.is-rolling .slots-roll-icon { animation: slots-spin .9s cubic-bezier(.4, 0, .2, 1); }
@keyframes slots-spin { to { transform: rotate(360deg); } }

.slots-note { color: var(--text-dim); font-size: 13px; }

@media (max-width: 900px) {
  .slots { --row: 40px; --win: 100px; }
}
@media (max-width: 760px) {
  /* 三列挤在手机上每列只剩一百来像素，型号名放不下 —— 改成一行一格。
     一行一格就没有「轮子」可看了，索性把窗口收成一行高、去掉渐隐和落定线。 */
  .slots { --row: 52px; --win: 52px; width: 100%; }
  .slots-face { grid-template-columns: 1fr; }
  .slot { display: grid; grid-template-columns: 1fr 1.3fr; align-items: center; gap: 10px; padding: 6px 16px; }
  .slot + .slot { border-left: 0; border-top: 1px solid rgba(255, 255, 255, .075); }
  .slot-label { margin: 0; text-align: left; }
  .slot-win::before, .slot-win::after { display: none; }
  .slot-line { display: none; }
  .slot-reel li { justify-items: end; padding: 0; }
  .slot.is-locked li { height: var(--row); }
}

/* 这一屏的两栏对半分：默认的 8.5 : 3.5 会让面板空得发慌、文字挤成细长条 */
#stack .section-inner { grid-template-columns: minmax(320px, 6.2fr) minmax(300px, 5.8fr); }
#stack .section-copy p { max-width: 44ch; }
@media (max-width: 760px) {
  #stack .section-inner { grid-template-columns: 1fr; }
}

/* 满宽版式的「了解更多」现在在组件下面，居中 */
.section--full .section-tail { margin: clamp(26px, 3.4vh, 40px) 0 0; text-align: center; }

/* ---------- 区块里的下载按钮 ---------- */

.section-cta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  margin: var(--sp-4) 0 var(--sp-2);
}
.section-cta-note { color: var(--text-dim); font-size: 13.5px; }

/* ---------- 安装器：它自己把该拿的拿回来 ----------
 *
 * 这块演的就是那句话本身 ——「打开 dmg，其余它自己来」。
 * 终态 = 四条满格加勾。只有 JS 可用、而且这一屏真的进了视野，
 * 才倒回去从头播一次；播完停在终态，不循环。 */

.dl {
  border: 1px solid var(--line);
  border-radius: 16px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, .012)),
    #0B0E15;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .06) inset, 0 22px 60px rgba(0, 0, 0, .45);
  overflow: hidden;
}

.dl-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, .075);
  background: rgba(255, 255, 255, .022);
}
.dl-title { color: var(--text); font-size: 13.5px; font-weight: 600; }

/* 「就绪」只在全部装完之后出现 */
.dl-state {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #7FD69C;
  font-size: 12.5px;
  font-weight: 600;
}
.dl-state::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.dl-rows { margin: 0; padding: 10px 18px 16px; list-style: none; }

.dl-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(64px, 130px) 16px;
  align-items: center;
  gap: 14px;
  padding: 9px 0;
}
.dl-name {
  color: var(--text-body);
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dl-track {
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .08);
  overflow: hidden;
}
.dl-track i {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--cobalt), var(--cobalt-lift));
  transform-origin: left center;
  transform: scaleX(1);   /* 基线：装完了 */
}

.dl-tick { width: 16px; height: 16px; color: #7FD69C; }

/* 只有 JS 确认可用，才允许倒回去从头播 */
.js .dl.is-armed .dl-track i { transform: scaleX(0); }
.js .dl.is-armed .dl-tick { opacity: 0; }
.js .dl.is-armed .dl-state { opacity: 0; }

.js .dl.is-playing .dl-track i {
  animation: dl-fill .95s cubic-bezier(.35, .85, .3, 1) both;
  animation-delay: calc(var(--i) * .42s);
}
.js .dl.is-playing .dl-tick {
  animation: dl-pop .32s var(--ease) both;
  animation-delay: calc(var(--i) * .42s + .82s);
}
.js .dl.is-playing .dl-state {
  animation: dl-pop .4s var(--ease) both;
  animation-delay: 2.5s;
}

@keyframes dl-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes dl-pop { from { opacity: 0; transform: scale(.7); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  /* 全局那条会把动画掐到 0.001ms 停在末帧，正好就是终态 —— 这里只要保证
     armed 那层不生效，别让它停在「全空」上。 */
  .js .dl.is-armed .dl-track i { transform: scaleX(1); }
  .js .dl.is-armed .dl-tick,
  .js .dl.is-armed .dl-state { opacity: 1; }
}

@media (max-width: 760px) {
  .dl-row { grid-template-columns: minmax(0, 1fr) 72px 16px; gap: 10px; }
  .dl-name { font-size: 13.5px; }
}

/* ---------- Project CommonSwell：全站唯一换主题的一屏 ----------
 *
 * 越往下滑，海面越亮，五滴水聚拢成标记。
 * --swell 是滚动进度（0→1），由 hero.js 每次滚动实测算出来 ——
 * **不是滚到某个点一次性切换**，那种硬切一眼就廉价。
 *
 * 基线 --swell: 1、动画不按住：无 JS / 爬虫看到的是海面全亮、标记成形。 */

.swell {
  --swell: 1;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  border-top: 0;
  /* 满屏一整幕 —— 跟首屏那一幕对称 */
  display: grid;
  place-items: center;
  min-height: 100svh;
  padding: clamp(88px, 12vh, 140px) clamp(20px, 5vw, 48px);
  text-align: center;
}

/* 认可的氛围图。往上抬一点、亮起来 —— 像海面从下面浮上来。 */
.swell-sky {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-size: cover;
  background-repeat: no-repeat;
  /* ⚠️ 别改成 image-set() —— 实测那样一个像素都不画，
     而两张图单独用 <img> 探测都能正常解码。webp 56K，本来也不必再省。 */
  background-image: url('/assets/commonswell/horizon.webp');
  background-position: center center;
  opacity: var(--swell);
  transform: scale(calc(1.08 - var(--swell) * .08));
  /* 上沿化开，跟上一屏之间不留硬边 */
  mask-image: linear-gradient(transparent, #000 20%, #000);
  -webkit-mask-image: linear-gradient(transparent, #000 20%, #000);
}

/* 底部那层蓝，是「换了个世界」这件事真正被看见的地方 */
.swell-wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: var(--swell);
  background:
    /* 摊得很大很淡的一层：只把整片海压下去半档，不在文字后面留下一块看得见的黑。
       文字的可读性交给它自己的投影（.swell-copy 的 text-shadow）去解决。 */
    radial-gradient(120% 90% at 50% 62%, rgba(2, 6, 12, .42), transparent 78%),
    /* 底部那层蓝，是「换了个世界」真正被看见的地方 */
    radial-gradient(130% 60% at 50% 108%, rgba(62, 134, 255, .20), transparent 62%),
    linear-gradient(180deg,
      rgba(2, 6, 12, .92) 0%, rgba(2, 6, 12, .22) 26%,
      rgba(2, 6, 12, .30) 66%, rgba(2, 6, 12, .86) 100%);
}

.swell-inner { position: relative; width: 100%; }
.swell-copy {
  max-width: 640px;
  margin: 0 auto;
  /* 压黑底块会看着像贴了块黑板；改用文字自身的投影，海面就能一直亮着 */
  text-shadow: 0 1px 2px rgba(2, 6, 12, .85), 0 2px 22px rgba(2, 6, 12, .75);
}

/* 字标：两张图叠着。基线显示静态那张（无 JS / 爬虫看到的就是它），
   滚到位时 JS 才给动画那张填 src 并露出来，播完再换回静态。
   aspect-ratio 锁死，杜绝换图时的跳动。 */
.swell-mark {
  position: relative;
  width: min(880px, 84vw);   /* 跟开屏那张字标同尺寸 —— 一头一尾要一样大 */
  aspect-ratio: 937 / 224;
  margin: 0 auto clamp(34px, 5vh, 62px);
  filter: drop-shadow(0 16px 70px rgba(62, 134, 255, .38));
}
.cs-wm {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.cs-wm-intro { opacity: 0; }
.swell-mark.is-playing .cs-wm-intro { opacity: 1; }
.swell-mark.is-playing .cs-wm-static { opacity: 0; }

/* 「镜头」——外层的一次推拉，跟 SVG 自己的时钟对齐。
 *
 * 那张图里的水滴本来就在正中聚拢（@keyframes cs-symbol-dock 的 0% 是
 * translate(372px)，96 + 372 = 468 = 937/2），只是整幅图 937×224，
 * 水滴在里面才占 45×77 —— 按 880px 渲染，那滴水只有 42×72 像素，读不出来。
 *
 * 所以外层配一次推拉：
 *   0 → 0.95s   放大 --cs-zoom 倍锁在这一幕正中，五滴水在空屏上聚拢
 *               （字样 1.0s 才开始显影，此刻整幅只有水滴有内容，放多大都不露馅）
 *   0.95 → 2.45s 它内部把符号向左归位，外层同步缩回原大小
 * 于是水滴在屏幕中心成形，再一边缩一边滑进字标位 ——
 * 跟开屏那张大字标飞进顶栏是同一个动作，一头一尾对称。
 *
 * 放大中心 50% / 52% ＝ viewBox (468, 116.57)，正是五滴水绕着转的那个点；
 * --cs-dy 由 hero.js 实测填入，把那个点抬到这一幕的正中央。 */
.swell-mark {
  --cs-zoom: 3;
  --cs-dy: 0px;
}

@keyframes cs-camera {
  0%    { transform: translateY(var(--cs-dy)) scale(var(--cs-zoom)); }
  38.8% { transform: translateY(var(--cs-dy)) scale(var(--cs-zoom));
          animation-timing-function: cubic-bezier(.2, .76, .18, 1); }
  100%  { transform: translateY(0) scale(1); }
}

.swell-mark.is-playing {
  transform-origin: 50% 52%;
  animation: cs-camera 2.45s linear both;
}

.swell .section-eyebrow { color: #86C1FF; }

.swell h2 {
  margin: 0 0 20px;
  color: #F2F7FF;
  font-size: clamp(28px, 3.2vw, 44px);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -.028em;
  text-wrap: balance;
}
html[lang="zh-Hans"] .swell h2 {
  font-size: clamp(25px, 2.8vw, 37px);
  line-height: 1.4;
  letter-spacing: 0;
}

.swell p {
  margin: 0 auto .95em;
  max-width: 54ch;
  color: #B9CBE6;
  font-size: clamp(16px, 1.35vw, 17.5px);
  line-height: 1.68;
  /* 中文几乎每个字后面都能断，贪心填行会劈出「想动手的部｜分」这种；
     均分行长至少让断点有机会落到标点上 */
  text-wrap: balance;
}

/* 54ch 是按拉丁字宽算的，中文同样一句话要多占三成 —— 栏子偏窄，
   两行就挤，断点更没有余地。放宽一点。 */
html[lang="zh-Hans"] .swell p { max-width: 40em; }
.swell .section-link { color: #86C1FF; }
.swell .section-link.is-pending { color: #52698C; }


/* 文案等字标快落定了才浮上来。
   只有 JS 确认要播这一幕时才藏 —— 无 JS / 爬虫 / reduced-motion 第一帧就在。 */
.js .swell.is-untold .swell-copy { opacity: 0; transform: translateY(18px); }
.js .swell .swell-copy { transition: opacity .95s var(--ease), transform .95s var(--ease); }

@media (max-width: 760px) {
  .swell { padding: 84px 20px; }
  /* 窄屏下整幅图本来就小，同样 3 倍水滴还是太细，推得更近一点。
     放大后图宽超出视口没关系 —— 聚拢阶段只有正中那一小块有内容。 */
  .swell-mark { width: 84vw; margin-bottom: 32px; --cs-zoom: 4.4; }
}
