/* naisho.space —— 全站唯一一份样式。没有脚本，没有第三方资源，没有网络字体。
   为什么不引网络字体（画布《官网规格》）：能用这个产品的人全在 Apple 设备上，
   那里的系统字栈就是 SF Pro ＋ 苹方 / ヒラギノ，和 app 里一模一样；
   中文没有能引的那一款（一两 MB，子集化也拖首屏），而只引拉丁正好制造
   「一句中英混排的话当场看出两副字」——app 那条规矩要避开的正是这个。 */

:root {
  color-scheme: light dark;
  --bg: #F7F6F2;
  --surface: #FEFDFB;
  --text: #1B1A18;
  --prose: #35322D;
  --muted: #77736C;
  --faint: #ABA69D;
  --rule: #DDDAD4;
  --accent: #1A1917;
  --ink-invert: #F7F6F2;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0D0D0B;
    --surface: #1C1A16;
    --text: #F3F0EA;
    --prose: #DCD8D0;
    --muted: #A8A49B;
    --faint: #7A756C;
    --rule: rgba(255, 255, 255, 0.10);
    --accent: #F3F0EA;
    --ink-invert: #0D0D0B;
  }
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  /* 中日文那几款必须显式列出：网页上没有 iOS 那条「系统自己的回落链是对的」的保证，
     -apple-system 在 Windows / Android 会落到 Segoe UI / Roboto，两副都没有汉字。 */
  font: 17px/1.72 -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
        "PingFang SC", "PingFang TC", "Hiragino Sans", "Microsoft YaHei",
        "Noto Sans SC", "Helvetica Neue", Helvetica, Arial, sans-serif;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 46rem; margin: 0 auto; padding: 0 1.5rem; }

/* ── 页眉 ─────────────────────────────────────────── */
.masthead {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .75rem 1rem;
  padding: 1.75rem 0 1.5rem; border-bottom: 1px solid var(--rule);
}
.wordmark {
  font: 700 1.35rem/1 "Helvetica Neue", Helvetica, Arial, sans-serif;
  letter-spacing: -0.015em; margin: 0;
}
/* **这一行是普通的行内排版，不是 flex**（09-07，Changming：「logo 和右侧的高度、
   间距之类的也不一致」）。原来 `.wordmark a` 是 `inline-flex`，而 **flex 容器的基线取自
   它第一个 flex 项**——也就是那张 28 px 的图，图片的基线是它的**盒底**。于是页眉那条
   `align-items: baseline` 拿去对齐的是*图片的底边*（y=56.0），而不是「Naisho」的文字基线
   （54.2），导航整体因此比字标低 4.8 px。
   行内排版没有这个问题：行盒的基线本来就是文字基线，图片靠 `vertical-align` 挂上去、
   不参与基线计算。于是「Naisho」和「Privacy」真的坐在同一条线上。 */
.wordmark a { color: inherit; border: none; }
/* `<picture>` 只负责按深浅挑图源，不该在排版里多一层盒子——`display: contents`
   让它自己那层消失，`img` 直接落进字标那一行。 */
.wordmark picture { display: contents; }
/* 名字在五种语言里都只有一个：Naisho。字标里不挂译名。 */
/* -.32em：字标 1.35rem = 21.6 px，这个位移把 28 px 的图**视觉上**居中在文字的中线上
   （图心 baseline−7.1，字心 baseline−7.8），同时它整个待在基线之外，不动基线本身。 */
.logo {
  display: inline-block; width: 28px; height: 28px; border-radius: 6px;
  vertical-align: -.32em; margin-right: .5rem;
}
/* 深色版是**另一张图**，不是把亮色那张反相（`<picture>` + `prefers-color-scheme` 换源，零脚本）。
   09-07 一度用的是 `filter: invert(1)`，当时的理由写着「墨 + 透明，反相只把墨翻成浅色，
   形状一模一样」——**那句话是错的，而且我验的是 alpha 通道，不是它长什么样**。
   这张线稿不是纯墨稿：头发是一大片深色、脸是一大片浅色，反相把人翻成了照片负片
   （白头发、黑脸），看着像换了个人。Changming 一眼看出来了。
   现在用的就是 app 自己那张 `AppIcon-Dark.png`——头发照旧深、脸照旧浅，只有底翻黑。

   **它是不透明的，这是有意的**：那张图的底色正是 #0D0D0B，和深色下的 `--bg` 一模一样
   （图标本来就是照同一个令牌画的），贴上去看不出边。抠成透明反而会在头发边缘留一圈锯齿。
   代价是这两个值绑在了一起：`--bg` 哪天改了，这张图要跟着重出。 */

/* 语言：一个纯 CSS 的下拉（<details>，没有脚本）。 */
.lang { position: relative; }
.lang > summary {
  list-style: none; cursor: pointer; color: var(--muted);
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary::after { content: " ⌄"; letter-spacing: 0; }
.lang[open] > summary { color: var(--text); }
.lang > ul {
  position: absolute; right: 0; top: calc(100% + .5rem); z-index: 5;
  margin: 0; padding: .35rem 0; list-style: none; min-width: 7.5rem;
  background: var(--surface); border: 1px solid var(--rule); border-radius: 10px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .07);
}
.lang li { padding: 0; }
.lang li a, .lang li b {
  display: block; padding: .35rem .85rem; font-size: .9rem; font-weight: 400;
  color: var(--muted); border: none; white-space: nowrap;
}
.lang li b { color: var(--text); }
.lang li a:hover { color: var(--text); background: var(--bg); }
/* 页眉那一行三样东西（隐私 · 支持 · 语言）。**这里是 flex，不是一串 inline**
   ——Changming 09-07：「字号、间距、高度都统一吗？」不统一，三处：

   ① 下划线。全站那条 `a { border-bottom }` 在**正文**里是对的（正文中的链接不能只靠颜色
      认出来），可页眉里只有三样东西、位置本身就说明了它们是导航；三道下划线再加页眉自己
      那道分隔线，一条窄带里横着四条平行线。页眉这一处撤掉，正文那条一个字不动。
   ② 语言那一颗的线比另外两颗**低 1px、长一截**：它有自己的 `border-bottom` 外加
      `padding-bottom: 1px`，而且那道线连 `⌄` 和它前面那个空格一起划了进去。
   ③ 语言前面那道缝比「隐私 · 支持」之间的宽：`.sep` 两边各 .5rem 是一样的，
      但 HTML 里 `</span>` 和 `<details>` 之间有个换行，浏览器把它当成一个空格
      ——于是那一处多出小半个字。**改成 flex + gap，空白符从此不参与排版**，
      这类缝再也不会因为谁换了行就变宽。

   字号本来就是统一的（.9rem，下拉里的条目也是），高度现在靠 `align-items: baseline`
   对齐基线——三样东西坐在同一条基线上，而不是各自的盒底。 */
.masthead nav {
  margin-left: auto; font-size: .9rem; color: var(--muted);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .1rem .4rem;
}
/* 页眉在 iPhone 12–16 那一档（390）上曾经差 1.6 px 就折成两行：字标 106 + 导航 202
   + 列间距 20 = 328.6，而可用只有 327。两行不是不能看，但左上一个小 logo、右下
   一行导航是散的。所以这一处的两个间距（页眉 1rem、导航 .4rem）是**按宽度算出来的**，
   不是随手调的——改它们之前先量一遍 375 / 390 会不会折。 */
.masthead nav a { color: inherit; border-bottom: none; }
.masthead nav a:hover { color: var(--text); }
.masthead nav .sep { opacity: .45; margin: 0; }

a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--rule); }
a:hover { border-color: var(--muted); }
a:focus-visible { outline: 2px solid var(--muted); outline-offset: 3px; border-radius: 2px; }

/* ── 开场 ─────────────────────────────────────────── */
.hero { padding: 3.5rem 0 3rem; }
.hero h1 {
  font-size: clamp(1.85rem, 5.2vw, 2.6rem); line-height: 1.28; font-weight: 600;
  letter-spacing: -0.02em; margin: 0 0 1.25rem; text-wrap: balance; max-width: 20ch;
}
.hero .sub { font-size: 1.075rem; color: var(--prose); margin: 0 0 1rem; max-width: 40ch; }
.hero .fine { font-size: .925rem; color: var(--muted); margin: 0; max-width: 42ch; }

.actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 2rem; }
.btn {
  display: inline-block; padding: .7rem 1.35rem; border-radius: 999px;
  font-size: .95rem; border: 1px solid var(--rule); background: var(--surface);
  color: var(--text);
}
/* 主动作：实心墨块。app 里那颗「连接」也是这个道理——一屏上只有一个这么重的东西。 */
.btn.primary {
  background: var(--accent); color: var(--ink-invert); border-color: var(--accent);
  font-weight: 500;
}
.btn.primary:hover { opacity: .88; }
.btn.ghost { border-color: transparent; background: transparent; color: var(--muted); padding-left: .35rem; }
.btn.ghost:hover { color: var(--text); }

/* ── 开场右边：那块场 ──────────────────────────────────────────────
   Changming 09-07：「感觉官网第一部分的右侧有点空」。那块空不拿图形填——
   站进去的是这个产品唯一的画面：**两个人、之间那段距离、场在呼吸**。

   和下面《怎么用》那三块屏刻意不是同一句话：那三块讲「app 长什么样」（有手机、有
   状态栏、有按钮、有计时器），这一块讲「那件事本身长什么样」——没有手机、没有连线、
   没有边界圈，直接躺在站点自己的纸上（#F7F6F2 / #0D0D0B 本来就是 app 那张纸）。
   材料是同一批数，所以两处摆在同一页上认得出是同一只手。

   为什么另起一份 --fld-*，不复用 .shot 那套 --sh-*：那一套是「屏里」的一套，挂在 .shot 上、
   跟着那三块屏走；这块场不在屏里。这里的分工是**材料照 app，字照站点**——头像那张纸、
   光晕、投影用 app 的值，名字用 --muted，因为名字是页面上的字，不是屏里的字。 */
.hero .fld {
  /* 浅色三个值就是 app 里那三个（Theme.avatar / 声场核那团光 / 投影的黑）。
     深色的头像纸 #35312A 必须比页面 #0D0D0B 亮一档，不然 emoji 是浮在虚空里的；
     投影在深色里归零，和 .shot 一样——那边靠纸本身分层，不靠影子。 */
  --fld-face: #FEFDFB;
  --fld-glow: 254, 253, 251;
  --fld-sh: 27, 26, 24;
  --fld-ink: 26, 25, 23;
  /* 一个尺寸源：整块场的宽。头像、光晕、位置全从它算，换一档只改这一行。
     62vw 是保险丝——系统字号调大时 rem 会跟着涨，那时按视口收，别顶出纸边。 */
  --u: min(13.5rem, 62vw);
  /* 头像 64：场上只有两个人时 app 给的就是 64（FieldPlacement.avatarDiameter，≥5 人才收到 56）。
     这块场不在屏里，不用按 .shot 那个 0.525 缩——它和真机上一样大。 */
  --d: calc(var(--u) * .32);
  position: relative;
  width: var(--u);
  height: calc(var(--u) * .98);
  margin: 2.75rem auto 0;
  user-select: none; -webkit-user-select: none;
  /* 有人在场那一档呼吸：5.6 s、1 → 1.006（Tunables.fieldSettlePeriod / fieldSettleScale）。
     1.006 在 200 px 上是 1.2 px——它本来就不该被看见，只该被觉得。
     搜索那一档（4.4 s / 1.022）是「一个人在找人」，这块场里有两个人，用不上。
     呼吸挂在整块上而不是各自头像上：胀缩的是**他们之间那段距离**。 */
  animation: fld-breathe 5.6s ease-in-out infinite;
}
@media (prefers-color-scheme: dark) {
  .hero .fld {
    --fld-face: #35312A; --fld-glow: 46, 42, 34; --fld-sh: 0, 0, 0; --fld-ink: 243, 240, 234;
  }
}

/* 那一小块光：场的全部范围就是它，**不画边界圈**。
   app 0.6.6 把 ⌀216 那条外环整条退役了，理由是「闭合、均匀、静止的圆线只有一种读法：
   到此为止」。这块场要说的恰好反过来：亮到这儿为止、再往外什么都没有，可它自己没有围墙。
   116% / 126% 是让它溢出盒子——溢出的那一圈已经淡到接近 0，只为了让这个物体在
   右栏里显得比 200 px 大一圈，而不占版面。 */
.hero .fld .pool {
  position: absolute; left: 51%; top: 47.5%;
  width: 116%; height: 126%;
  transform: translate(-50%, -50%);
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(var(--fld-glow), .9) 0%, rgba(var(--fld-glow), .42) 56%, rgba(var(--fld-glow), 0) 100%);
}

/* 品牌那三点。点是「存在 / 声音 / 声场」，永远不是网络拓扑（ProximityField 开头那段）。
   它们散在光的边上、越外越淡——作用是让这块光**有一个看得出来的边，而不是画一条边**。
   落在 .pool 前面是照 app 的图层序：里圈的被光洗掉，只剩外圈的还站着。 */
.hero .fld .dot {
  position: absolute; width: 3px; height: 3px; border-radius: 50%;
  background: rgb(var(--fld-ink));
}

/* 两个人：**一样大、不一样高**。
   一样大是因为对这一页的访客来说他们是对等的两个人（场心那颗「我」不在这儿，
   所以这块场没有 orb，也就不会和第一块屏撞脸）。
   不一样高是因为对称本身就是「这是摆出来的」这个信号（FieldPlacement 那一条）——
   差那一档高度，一对图标才变回两个站着的人。
   中心距 101 px，两张纸之间还剩 37 px 空白：圆可以相切、绝不相交（0.6.6 的不变量）。
   **那段空白就是这一整块的主语**，所以中间什么都不画——一条连线会把「一段距离」
   变成「一条链路」，而链路是拓扑。
   格子只有头像那么大、名字挂在版面外：和 app 里一样（FieldAvatar「圆心就是落位点」）。 */
.hero .fld .who { position: absolute; width: var(--d); height: var(--d); }
.hero .fld .one { left: 13%; top: 18.4%; }
.hero .fld .two { left: 57%; top: 43.9%; }

.hero .fld .face {
  position: relative; display: flex; align-items: center; justify-content: center;
  width: var(--d); height: var(--d); border-radius: 50%;
  background: var(--fld-face);
  font-size: calc(var(--d) * .48); line-height: 1;
  /* FieldAvatar 那两层，一点没缩：.09 / 11 / y8 把这张纸托起来，
     .05 / 1 / y1 再把它压回纸面——少任何一层它都会飘。 */
  box-shadow: 0 8px 11px rgba(var(--fld-sh), .09), 0 1px 1px rgba(var(--fld-sh), .05);
  transform: scale(1.028);
  animation: fld-say 9.6s ease-in-out infinite;
}

/* 名字：这是页面上的字，不是屏里的字，所以走站点的 --muted。
   绝对定位挂在头像下面，名字再长也推不动头像（app 那条「名字不进版面」）。 */
.hero .fld b {
  position: absolute; left: 50%; top: calc(100% + .55rem);
  transform: translateX(-50%);
  font-size: .8rem; font-weight: 400; line-height: 1;
  color: var(--muted); white-space: nowrap;
}

/* 说话的那一个脚下那团光（app InCall 里 .sp .glow 那一层）。
   **只加不减**：说话的人被托起来，听的那个一点不暗——ProximityField 里那条硬规矩，
   亮度一开口就会被读成「信号弱 / 离得远」，用一个轴说另一个轴的事正是那次事故本身。 */
.hero .fld .lift {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--d) * 1.85); height: calc(var(--d) * 1.85);
  margin: calc(var(--d) * -.925) 0 0 calc(var(--d) * -.925);
  border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(var(--fld-glow), 1) 0%, rgba(var(--fld-glow), .55) 56%, rgba(var(--fld-glow), 0) 100%);
  opacity: .92;
  animation: fld-lift 9.6s ease-in-out infinite;
}
/* 静止那一帧——也就是减弱动态之后剩下的那一帧、和页面加载的第一帧：
   一个人正说着，另一个听着。两个人的基础样式就是那一帧的两半，
   动画只是把这两半来回换（-4.8s 是把 .two 拨到半圈之后），不另写一条静止规则。 */
.hero .fld .two .lift { opacity: 0; }
.hero .fld .two .face { transform: scale(1); }
.hero .fld .two .lift, .hero .fld .two .face { animation-delay: -4.8s; }

/* 9.6 s 一轮：一个人说 4 s，交接 0.8 s，换另一个。
   **这一句只有这块场说得出来**：没有「按住说话」这回事，两个人都能说（六件事 03），
   而下面三块屏里没有一块讲得了「轮到谁」。
   交接慢到 0.8 s 是故意的：快了是切换，慢了才是接话。 */
@keyframes fld-lift { 0%, 41.6% { opacity: .92; } 50%, 91.6% { opacity: 0; } 100% { opacity: .92; } }
@keyframes fld-say  { 0%, 41.6% { transform: scale(1.028); } 50%, 91.6% { transform: scale(1); } 100% { transform: scale(1.028); } }
@keyframes fld-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.006); } }

/* 48rem = 768：正是 .wrap（46rem）连自己的内边距一起吃满的那一刻——从这里起正文列
   永远是 688 px，再宽也不变。所以分栏只存在于这一侧，中间**没有一段「越来越挤」的宽度带**：
   要么两列，要么叠下去。
   688 − 200 − 32 = 456 给字：够 h1 的 20ch、够 .sub 的 40ch，也够那两颗按钮并排一行。 */
@media (min-width: 48rem) {
  .hero { display: grid; grid-template-columns: minmax(0, 1fr) 12.5rem; column-gap: 2rem; align-items: center; }
  .hero .copy { min-width: 0; }
  /* 竖着居中，于是它落在 .sub 那几行旁边、而不是和 h1 抢：一屏上只让一件事最响。 */
  .hero .fld { --u: 12.5rem; margin: 0; }
}

/* ── 分节 ─────────────────────────────────────────── */
section { padding: 3.25rem 0; border-top: 1px solid var(--rule); }
.eyebrow {
  font-size: .7rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 .75rem;
}
h2 {
  font-size: clamp(1.3rem, 3.4vw, 1.6rem); font-weight: 600; letter-spacing: -0.015em;
  margin: 0 0 1.75rem; text-wrap: balance;
}
h3 { font-size: 1.0rem; font-weight: 600; margin: 0 0 .4rem; }
p { margin: 0 0 1rem; color: var(--prose); }
p:last-child { margin-bottom: 0; }
.fine { font-size: .9rem; color: var(--muted); }

/* 场景：一条一条，不是卡片墙——它们是同一件事的四个样子 */
.scenes { list-style: none; margin: 0 0 1.75rem; padding: 0; }
.scenes li { padding: .9rem 0; border-top: 1px solid var(--rule); color: var(--prose); }
.scenes li:first-child { border-top: none; padding-top: 0; }
.scenes b { color: var(--text); font-weight: 600; }
.closing { font-size: 1.02rem; color: var(--text); }

/* 六件事 */
.facts { display: grid; gap: 1.75rem; }
@media (min-width: 40rem) { .facts { grid-template-columns: 1fr 1fr; gap: 2rem 2.5rem; } }
.fact .n {
  display: inline-block; font-size: .72rem; color: var(--faint);
  font-variant-numeric: tabular-nums; margin-bottom: .35rem;
}
.fact p { margin-bottom: .5rem; }

/* ── 怎么用：三块真屏 ──────────────────────────────────────────────
   纯 HTML + CSS，零脚本、零外链、零位图。屏跟着访客的主题翻（prefers-color-scheme）——
   app 的纸 #F7F6F2 / #0D0D0B 和站点的 --bg 本来就是同一块材料，屏里那一套是 app 自己的
   令牌（画布《材料与字阶》），用 --sh-* 单独挂在 .shot 上，不和站点的 --text / --prose 混。
   减弱动态：沿用本文件底部那条全局 animation:none —— 每个会动的东西，静止态都写在
   基础样式里（有人在场 / 说话中），动画一关剩下的就是那一帧，不另写一条。 */
.howto { display: grid; gap: 2.1rem; }
@media (min-width: 40rem) { .howto { grid-template-columns: repeat(3, 1fr); gap: 2rem 1.75rem; } }
.step .n {
  display: block; font-size: .72rem; color: var(--faint);
  font-variant-numeric: tabular-nums; margin-bottom: .6rem;
}
.step .n em { font-style: normal; margin-left: .5em; }
.step p { font-size: .9rem; line-height: 1.7; color: var(--prose); margin: .75rem 0 0; }
.step .shot { margin: 0 auto; }

/* 屏：402 × 874 的真机按 211 宽重排（不是缩图——16 号正文缩到 8.4 号没人读得了）。
   几何等比 0.525，字号设下限：主文字 11–12.5，次要 10，三级 9.5。 */
.shot {
  --sh-bg: #F7F6F2; --sh-ink: #1A1917; --sh-i: 26, 25, 23;
  --sh-t2: #77736C; --sh-t3: #ABA69D;
  --sh-card: #FEFDFB; --sh-face: #FEFDFB; --sh-chip: #EEECE6; --sh-cap: #ECEAE5;
  --sh-orb1: #FEFDFB; --sh-orb2: #FCFCFA; --sh-orb3: #F3F1EC; --sh-rim: rgba(254, 253, 251, .9);
  --sh-track: #DDDAD4; --sh-thumb: #FEFDFB; --sh-inv: #F7F6F2;
  --sh-sh: 27, 26, 24; --sh-glow: 254, 253, 251;
  position: relative; width: 211px; height: 458px; overflow: hidden; border-radius: 26px;
  background: var(--sh-bg); color: var(--sh-ink);
  box-shadow: 0 0 0 1px var(--rule), 0 2px 6px rgba(var(--sh-sh), .05), 0 18px 44px rgba(var(--sh-sh), .08);
  display: flex; flex-direction: column; align-items: stretch;
  font-size: 10px; line-height: 1.3; font-weight: 400; letter-spacing: 0; text-align: left;
  -webkit-font-smoothing: antialiased; user-select: none; -webkit-user-select: none;
}
@media (prefers-color-scheme: dark) {
  .shot {
    --sh-bg: #0D0D0B; --sh-ink: #F3F0EA; --sh-i: 243, 240, 234;
    --sh-t2: #A8A49B; --sh-t3: #7A756C;
    --sh-card: #1C1A16; --sh-face: #35312A; --sh-chip: #2E2B25; --sh-cap: #2E2B25;
    --sh-orb1: #2E2A22; --sh-orb2: #26231D; --sh-orb3: #191713; --sh-rim: rgba(243, 240, 234, .14);
    --sh-track: #3A362F; --sh-thumb: #EDE9E1; --sh-inv: #0D0D0B;
    --sh-sh: 0, 0, 0; --sh-glow: 46, 42, 34;
  }
}
/* 三列时格子只有 178–211 宽（视口 40–46rem），窄屏叠起来时放大一档。zoom 是重排不是栅格缩放，字仍然清楚。 */
@media (min-width: 40rem) and (max-width: 45.99rem) { .shot { zoom: .84; } }
@media (max-width: 39.99rem) { .shot { zoom: 1.24; } }

.shot * { box-sizing: border-box; margin: 0; padding: 0; }
.shot svg { display: block; width: auto; height: auto; }
.shot .grow { flex: 1 1 auto; }
.shot .num { font-variant-numeric: tabular-nums; }
.shot .x { display: grid; } .shot .x > * { grid-area: 1 / 1; }
.shot .face {
  display: flex; align-items: center; justify-content: center; flex: none;
  border-radius: 50%; background: var(--sh-face); line-height: 1; font-style: normal;
}
.shot .wm { font: 700 15px/1 "Helvetica Neue", Helvetica, Arial, sans-serif; letter-spacing: .2px; color: var(--sh-ink); }
.shot .fd { display: flex; align-items: center; gap: 7px; }
.shot .fd i { display: block; width: 3px; height: 3px; border-radius: 50%; background: var(--sh-ink); }

/* ── 01 首页：搜索中 → 有人进来了 → 又走了（18 秒一圈，画布《搜索页 · 动效说明》分镜 ①②⑤⑥） ── */
.s1 .top { height: 30px; flex: none; }
.s1 .hdr { height: 24px; flex: none; display: flex; align-items: center; justify-content: space-between; padding: 0 13px; }
.s1 .cap {
  display: flex; align-items: center; gap: 4px; height: 20px; padding: 0 8px 0 5px;
  border-radius: 10px; background: var(--sh-cap); font-size: 9.5px; color: var(--sh-ink); white-space: nowrap;
}
.s1 .cap i { font-style: normal; font-size: 11px; line-height: 1; }
.s1 .field { position: relative; height: 183px; flex: none; margin-top: 8px; }
.s1 .dot { position: absolute; width: 3px; height: 3px; border-radius: 50%; background: var(--sh-ink); }
.s1 .mist {
  position: absolute; left: 50%; top: 50%; width: 160px; height: 160px; margin: -80px 0 0 -80px; border-radius: 50%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(var(--sh-glow), .55) 0%, rgba(var(--sh-glow), .22) 58%, rgba(var(--sh-glow), 0) 86%);
}
/* 三道等势线：越往外越淡、越往外越断（代码 FieldRipples.bands：[40,.8] → [6,4] → [2,7]），没有一圈是闭合的 */
.s1 .ripples { position: absolute; left: 50%; top: 50%; width: 167px; height: 167px; margin: -83.5px 0 0 -83.5px; overflow: visible; opacity: 0; animation: s1-ripples 18s linear infinite; }
.s1 .rp { fill: none; stroke: rgb(var(--sh-i)); stroke-width: 1.6; r: 124px; opacity: 0; stroke-dasharray: 40 .8; animation: s1-rp 4.4s cubic-bezier(.22, .61, .36, 1) infinite; }
.s1 .rp2 { animation-delay: -1.45s; } .s1 .rp3 { animation-delay: -2.9s; }
@keyframes s1-rp {
  0%   { r: 124px; opacity: .18; stroke-dasharray: 40 .8; }
  35%  { r: 164px; opacity: .085; stroke-dasharray: 14 2.8; }
  70%  { r: 204px; opacity: .03; stroke-dasharray: 4 5.2; }
  100% { r: 238px; opacity: 0;   stroke-dasharray: 2 7; }
}
.s1 .orb {
  position: absolute; left: 50%; top: 50%; width: 88px; height: 88px; margin: -44px 0 0 -44px; border-radius: 50%;
  background: radial-gradient(118% 118% at 32% 24%, var(--sh-orb1) 0%, var(--sh-orb2) 48%, var(--sh-orb3) 100%);
  box-shadow: 0 6px 16px rgba(var(--sh-sh), .055), 0 1px 3px rgba(var(--sh-sh), .04), inset 0 1px 0 var(--sh-rim);
  display: flex; align-items: center; justify-content: center; animation: s1-orb 18s ease-in-out infinite;
}
.s1 .orb .face { width: 38px; height: 38px; font-size: 18px; box-shadow: 0 3px 8px rgba(var(--sh-sh), .055), 0 1px 1px rgba(var(--sh-sh), .035); }
/* 进来的人：只有距离没有方向 → 放正上方（《只有距离》定稿），半径 = 正常对话距离那一档（112 × .525） */
.s1 .arc { position: absolute; left: 50%; top: 50%; width: 130px; height: 130px; margin: -65px 0 0 -65px; overflow: visible; filter: blur(.45px); animation: s1-arc 18s linear infinite; }
.s1 .arc path { fill: none; stroke-width: 1.6; stroke-linecap: butt; }
.s1 .peer {
  position: absolute; left: 50%; top: 50%; width: 70px; margin: -76px 0 0 -35px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  transform-origin: 35px 17px; animation: s1-peer 18s ease-out infinite;
}
.s1 .peer .fw { position: relative; width: 34px; height: 34px; }
.s1 .peer .face { width: 34px; height: 34px; font-size: 16px; box-shadow: 0 4px 11px rgba(var(--sh-sh), .09), 0 1px 1px rgba(var(--sh-sh), .05); }
.s1 .peer .halo { position: absolute; left: 0; top: 0; width: 34px; height: 34px; border-radius: 50%; border: 1px solid rgba(var(--sh-i), .22); opacity: 0; animation: s1-halo 18s ease-out infinite; }
.s1 .peer b { font-size: 9.5px; font-weight: 400; color: var(--sh-ink); white-space: nowrap; }
.s1 .peer .dust { position: absolute; left: 17px; top: 17px; width: 2px; height: 2px; border-radius: 50%; background: var(--sh-ink); opacity: 0; animation: s1-dust 18s ease-out infinite; }
.s1 .status { flex: none; margin-top: 10px; padding: 0 14px; text-align: center; font-size: 11px; font-weight: 500; color: var(--sh-ink); line-height: 1.35; }
.s1 .status .a { opacity: 0; animation: s1-a 18s linear infinite; }
.s1 .status .b { opacity: 1; animation: s1-b 18s linear infinite; }
.s1 .last { flex: none; padding: 0 13px; display: flex; flex-direction: column; gap: 6px; }
.s1 .lh { display: flex; align-items: baseline; justify-content: space-between; font-size: 10px; }
.s1 .lh b { font-weight: 500; color: var(--sh-t2); }
.s1 .lh .see { display: flex; align-items: center; gap: 3px; color: var(--sh-t3); }
.s1 .card {
  display: flex; align-items: center; gap: 7px; height: 44px; padding: 0 9px; border-radius: 12px;
  background: var(--sh-card); box-shadow: 0 1px 2px rgba(var(--sh-sh), .035), 0 4px 10px rgba(var(--sh-sh), .035);
}
.s1 .card .face { width: 24px; height: 24px; font-size: 13px; background: var(--sh-chip); }
.s1 .card .txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.s1 .card .txt b { font-size: 11.5px; font-weight: 600; color: var(--sh-ink); }
.s1 .card .sub { font-size: 9.5px; color: var(--sh-t3); white-space: nowrap; }
.s1 .card .sub em, .s1 .status span { font-style: normal; }
.s1 .card .sub .a { opacity: 0; animation: s1-a 18s linear infinite -17.6s; }
.s1 .card .sub .b { color: var(--sh-t2); opacity: 1; animation: s1-b 18s linear infinite -17.6s; }
.s1 .card .btn { flex: none; font-size: 10px; }
.s1 .card .btn > span { display: flex; align-items: center; justify-content: center; height: 22px; padding: 0 11px; border-radius: 11px; white-space: nowrap; }
.s1 .card .btn .a { background: var(--sh-chip); color: var(--sh-t2); opacity: 0; animation: s1-a 18s linear infinite -17.6s; }
.s1 .card .btn .b { background: var(--sh-ink); color: var(--sh-inv); font-weight: 500; opacity: 1; animation: s1-b 18s linear infinite -17.6s; }
.s1 .how { flex: none; margin-top: 10px; padding: 0 13px; height: 24px; display: flex; align-items: center; gap: 5px; font-size: 9.5px; color: var(--sh-t3); }
.s1 .bot { height: 14px; flex: none; }
/* 18 秒的主时间线：0–5 s 搜索 · 5 s 进入 · 5–14.5 s 在场 · 14.5–15.5 s 化尘离开 · 回到搜索 */
@keyframes s1-ripples { 0%, 27.5% { opacity: 1; } 29%, 86% { opacity: 0; } 89%, 100% { opacity: 1; } }
@keyframes s1-orb {
  0% { transform: scale(1); } 12.2% { transform: scale(1.022); } 24.4% { transform: scale(1); }
  40% { transform: scale(1.006); } 55% { transform: scale(1); } 71% { transform: scale(1.006); } 86% { transform: scale(1); }
  93% { transform: scale(1.02); } 100% { transform: scale(1); }
}
@keyframes s1-peer {
  0%, 27.8% { opacity: 0; transform: scale(.78); }
  29.6% { opacity: 1; transform: scale(1.05); }
  31%, 80.5% { opacity: 1; transform: scale(1); }
  83.5%, 100% { opacity: 0; transform: scale(.94) translateX(3px); }
}
@keyframes s1-halo {
  0%, 29.8% { opacity: 0; transform: scale(1); } 29.9% { opacity: .4; } 38% { opacity: 0; transform: scale(1.9); }
  47.9% { opacity: 0; transform: scale(1); } 48% { opacity: .32; } 56.5% { opacity: 0; transform: scale(1.9); }
  66.2% { opacity: 0; transform: scale(1); } 66.3% { opacity: .32; } 75%, 100% { opacity: 0; transform: scale(1.9); }
}
@keyframes s1-arc { 0%, 28.8% { opacity: 0; } 31%, 81% { opacity: 1; } 84%, 100% { opacity: 0; } }
@keyframes s1-a { 0%, 28% { opacity: 1; } 29.2%, 84.4% { opacity: 0; } 86%, 100% { opacity: 1; } }
@keyframes s1-b { 0%, 29.4% { opacity: 0; } 30.6%, 83% { opacity: 1; } 84.4%, 100% { opacity: 0; } }
@keyframes s1-dust {
  0%, 80.6% { opacity: 0; transform: translate(0, 0); } 81.4% { opacity: .55; }
  84.6%, 100% { opacity: 0; transform: translate(var(--dx), var(--dy)); }
}

/* ── 02 第一次见面 · TA 那一侧：ConfirmFriendScreen.joinFrame（幕布 97% 之上、居中、无字标） ── */
.s2 .c2 { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); padding: 0 17px; display: flex; flex-direction: column; align-items: center; text-align: center; }
.s2 .duo { position: relative; display: flex; align-items: center; height: 100px; }
.s2 .duo .glow { position: absolute; left: 50%; top: 50%; width: 173px; height: 100px; margin: -50px 0 0 -86px; border-radius: 50%; background: radial-gradient(60% 60% at 50% 50%, rgba(var(--sh-glow), .9) 0%, rgba(var(--sh-glow), .4) 55%, rgba(var(--sh-glow), 0) 100%); }
.s2 .duo .face { position: relative; width: 44px; height: 44px; font-size: 21px; box-shadow: 0 6px 16px rgba(var(--sh-sh), .07), 0 1px 1px rgba(var(--sh-sh), .04); }
.s2 .link { position: relative; width: 58px; height: 44px; }
.s2 .link i { position: absolute; top: 21px; width: 1.6px; height: 1.6px; border-radius: 50%; background: var(--sh-ink); opacity: .34; }
.s2 .nm { margin-top: 12px; font-size: 11.5px; font-weight: 600; color: var(--sh-ink); }
.s2 .ask { margin-top: 5px; font-size: 12.5px; font-weight: 500; color: var(--sh-ink); }
.s2 .once { margin-top: 5px; font-size: 10px; line-height: 1.5; color: var(--sh-t2); }
.s2 .fill { margin-top: 16px; width: 100%; height: 28px; border-radius: 14px; background: var(--sh-ink); color: var(--sh-inv); font-size: 11px; font-weight: 500; display: flex; align-items: center; justify-content: center; }
.s2 .pill { margin-top: 7px; height: 25px; padding: 0 23px; border-radius: 13px; background: var(--sh-chip); color: var(--sh-t2); font-size: 10.5px; display: flex; align-items: center; }
.s2 .fn { margin-top: 4px; font-size: 9px; color: var(--sh-t3); }

/* ── 03 对话中 · 说话中：InCallSpeaking（顶部三点是静息态：网络好就该看不见） ── */
.s3 .top { height: 37px; flex: none; }
.s3 .q { height: 17px; flex: none; display: flex; align-items: center; gap: 2px; padding: 0 9px; }
.s3 .q i { display: block; width: 3px; height: 3px; border-radius: 50%; background: var(--sh-ink); opacity: .2; }
.s3 .pf { position: relative; flex: none; width: 186px; height: 174px; margin: 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; }
.s3 .mist { position: absolute; left: 0; top: 8px; width: 186px; height: 158px; border-radius: 50%; background: radial-gradient(58% 58% at 50% 50%, rgba(var(--sh-glow), .9) 0%, rgba(var(--sh-glow), .45) 56%, rgba(var(--sh-glow), 0) 100%); }
.s3 .fd { position: relative; }
.s3 .pair { position: relative; display: flex; align-items: flex-start; gap: 24px; }
.s3 .me { display: flex; flex-direction: column; align-items: center; gap: 6px; transform: translateY(5px); }
.s3 .me .face { width: 44px; height: 44px; font-size: 21px; box-shadow: 0 3px 8px rgba(var(--sh-sh), .04); opacity: .82; }
.s3 .me span { font-size: 9.5px; color: var(--sh-t3); }
.s3 .sp { position: relative; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.s3 .sp .glow { position: absolute; left: -17px; top: -17px; width: 84px; height: 84px; border-radius: 50%; background: radial-gradient(50% 50% at 50% 50%, rgba(255, 255, 254, 1) 0%, rgba(var(--sh-glow), .6) 58%, rgba(var(--sh-glow), 0) 100%); opacity: .85; transform: scale(1.03); animation: s3-glow 1.7s ease-in-out infinite; }
.s3 .sp .df { position: absolute; left: 25px; top: 25px; width: 80px; height: 80px; margin: -40px 0 0 -40px; border-radius: 50%; border: 1.5px dotted rgba(var(--sh-i), .26); opacity: .2; animation: s3-df 3.2s ease-out infinite; }
.s3 .sp .d2 { animation-delay: -1.06s; } .s3 .sp .d3 { animation-delay: -2.12s; }
.s3 .sp .face { position: relative; width: 49px; height: 49px; font-size: 24px; box-shadow: 0 7px 18px rgba(var(--sh-sh), .09), 0 1px 1px rgba(var(--sh-sh), .04); animation: s3-voice 1.7s ease-in-out infinite; }
.s3 .sp b { position: relative; font-size: 11.5px; font-weight: 600; color: var(--sh-ink); }
.s3 .timer { flex: none; margin-top: 5px; text-align: center; font-size: 9.5px; letter-spacing: .3px; color: var(--sh-t3); }
.s3 .vol { flex: none; width: 186px; margin: 0 auto; display: flex; flex-direction: column; gap: 6px; }
.s3 .vol span { font-size: 10px; color: var(--sh-t2); }
.s3 .track { position: relative; height: 11px; }
.s3 .track i { position: absolute; top: 4.5px; left: 0; right: 0; height: 2px; border-radius: 1px; background: var(--sh-track); }
.s3 .track i.on { right: auto; width: 61.6%; background: var(--sh-ink); }
.s3 .track i.th { top: 0; left: calc(61.6% - 5.5px); right: auto; width: 11px; height: 11px; border-radius: 50%; background: var(--sh-thumb); box-shadow: 0 1px 2px rgba(var(--sh-sh), .22), 0 2px 5px rgba(var(--sh-sh), .10); }
.s3 .mic { flex: none; width: 186px; margin: 12px auto 0; height: 20px; display: flex; align-items: center; font-size: 10px; }
.s3 .mic span { flex: 1 1 auto; color: var(--sh-t2); }
.s3 .mic em { font-style: normal; color: var(--sh-t3); }
.s3 .dock {
  flex: none; width: 186px; height: 61px; margin: 10px auto 0; padding: 0 14px; border-radius: 15px;
  background: var(--sh-card); box-shadow: 0 1px 2px rgba(var(--sh-sh), .035), 0 5px 14px rgba(var(--sh-sh), .045);
  display: flex; align-items: center; justify-content: space-between;
}
.s3 .dock .g { display: flex; gap: 14px; }
.s3 .k { display: flex; flex-direction: column; align-items: center; gap: 5px; font-size: 9px; color: var(--sh-t2); }
.s3 .ctl { width: 32px; height: 32px; border-radius: 50%; background: var(--sh-chip); display: flex; align-items: center; justify-content: center; }
.s3 .ctl svg { stroke: var(--sh-ink); }
.s3 .end .ctl { width: 29px; height: 29px; background: var(--sh-ink); box-shadow: 0 2px 5px rgba(var(--sh-i), .13); }
.s3 .end .ctl svg { fill: var(--sh-inv); stroke: none; }
.s3 .bot { height: 18px; flex: none; }
@keyframes s3-voice { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.052); } }
@keyframes s3-glow { 0%, 100% { opacity: .70; transform: scale(.96); } 50% { opacity: 1; transform: scale(1.10); } }
@keyframes s3-df { 0% { width: 50px; height: 50px; margin: -25px 0 0 -25px; opacity: .55; } 100% { width: 110px; height: 110px; margin: -55px 0 0 -55px; opacity: 0; } }

/* 加密那一段：两条并排，形状本身就在说「这是两件事」 */
.split { display: grid; gap: 1.25rem; }
@media (min-width: 40rem) { .split { grid-template-columns: 1fr 1fr; gap: 2rem; } }
.split .col {
  background: var(--surface); border: 1px solid var(--rule);
  border-radius: 14px; padding: 1.25rem 1.35rem;
}
.split .label {
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint); margin: 0 0 .5rem;
}

/* 诚实那一段 */
.honest { padding: 3.5rem 0; }
.honest .big {
  font-size: clamp(1.2rem, 3.2vw, 1.45rem); font-weight: 600; line-height: 1.45;
  letter-spacing: -0.01em; margin: 0 0 1rem; text-wrap: balance;
}

/* 页脚上方的收尾（母本 §11.11）：一句收尾话 + 主行动第二次、也是最后一次出现。
   整页只有一颗主行动，只出现两次——开场一次、这里一次，中间不插第三颗、不做浮动条。 */
.closing-cta { padding: 3.25rem 0 1rem; border-top: 1px solid var(--rule); }
.closing-cta .big {
  font-size: clamp(1.2rem, 3.2vw, 1.45rem); font-weight: 600; line-height: 1.45;
  letter-spacing: -0.01em; margin: 0; text-wrap: balance;
}
.closing-cta .actions { margin-top: 1.25rem; }

/* 联系 */
.mail {
  display: inline-block; margin-top: .35rem; font-size: 1.1rem;
  border-bottom: 1px solid var(--muted); padding-bottom: 1px;
}

/* 规格条 */
.spec {
  display: flex; flex-wrap: wrap; gap: .5rem 1.25rem;
  font-size: .875rem; color: var(--muted);
  padding: 1.5rem 0; border-top: 1px solid var(--rule);
}
.spec span { white-space: nowrap; }

footer {
  padding: 1.5rem 0 4rem; font-size: .875rem; color: var(--muted);
  display: flex; flex-wrap: wrap; gap: .5rem 1.25rem; align-items: baseline;
}
footer a { color: inherit; border-bottom-color: transparent; }
footer a:hover { color: var(--text); border-bottom-color: var(--rule); }
footer .copy { margin-left: auto; color: var(--faint); }

/* 长文（隐私政策、支持页） */
.doc h2 {
  font-size: 1.22rem; margin: 3rem 0 1.1rem;
  padding-top: 1.85rem; border-top: 1px solid var(--rule);
}
.doc h2:first-of-type { border-top: none; padding-top: 0; margin-top: 0; }
.doc h3 { margin: 2rem 0 .5rem; }
.doc ul, .doc ol { margin: 0 0 1rem; padding-left: 1.35rem; color: var(--prose); }
.doc li { margin-bottom: .4rem; }
.lede {
  background: var(--surface); border: 1px solid var(--rule); border-radius: 14px;
  padding: 1.125rem 1.25rem; margin: 0 0 1.75rem;
}
.updated { color: var(--faint); font-size: .875rem; margin: .35rem 0 0; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
