/* 来处 / Pardine · ui-settings.css（owner D）
 *
 * 欢迎页三页（#welcome 里的 .onb）、装机页、设置表单（.set）、语言列表、搬家小浮层、
 * 住过的地方（列表行首的印 + 一段的小表单）。
 * 外框归 styles.css：.welcome（全屏、纸底、自己滚）、.rows / .row、.seg、.chips / .chip、.btn、
 * .field、.toggle、.sub-en、.brand。这里只加修饰，不重定义它们的基础样式。
 *
 * ⚠ 只用令牌（CONTRACT §6.3），这里不写任何颜色值：深浅色靠令牌自己切。
 * ⚠ 只用逻辑属性（margin-inline-start、padding-block…）：ar / fa / he / ur 真从右往左。
 *   安全区是物理的（左右刘海），所以欢迎页的左右内边距取「页边距与两侧安全区里最大的那个」，两边对称，
 *   不必分方向。
 * ⚠ 动作（DESIGN §10.6；ADDENDUM-3 E8「所有进出都要过渡，都用优雅的非线性方式」）：
 *   · 欢迎页换页：旧的一页 130ms 淡出（--ease-exit，加速离开）→ 新的一页 260ms 以 scale(.988) 淡入（--ease），
 *     Parote swapBox 的节奏（E14.2「快出、慢进」），「同一张纸，下一页」；
 *   · 高度随内容变的盒子（搜索结果、语言列表、搬家的月历）：height 过渡 --t-grow（growBox，E14.2）；收起加速离开；
 *   · 宽屏欢迎页的世界（1b）：底图晚到 900ms 淡入、上过的色换页时退场、手机那一条放不下时淡出；
 *   · 欢迎页整页出现（从设置打开装机页）--t-in 淡入、离开 --t-out 淡出；首启的第一帧不淡入；
 *   · 选好的那一处（.onb__chosen）从无到有：淡入 + 上移 .25rem；
 *   · 设置重画时各组的高度过渡（--t-grow）：变高变矮、新出现（内容再 180ms 淡入）、消失（影子收起）。
 *   时长一律读 styles.css :root 的时间表（--t-in / --t-out / --t-grow），括号里是令牌缺席时的家族默认值；
 *   ui-settings.js 的定时器读同一组令牌（msVar）。基础样式 = 终态；退场是过渡（从不 animation forwards）；
 *   全局的减少动态效果规则会把它们都压成瞬间（JS 那边也直接跳过）。
 * ⚠ 欢迎页「是一页，不是海报」：左对齐、衬线、手机上按钮贴在拇指那一头；平板竖放整页居中成一栏；
 *   宽屏（≥ 60rem、横放、高 ≥ 36rem）是一张扉页：字在阅读起点那一栏，身后是一张发丝线的世界（1b，E12）。
 */

/* ==========================================================================
   1. 欢迎页
   ========================================================================== */

.welcome { transition: opacity var(--t-in, 240ms) var(--ease); }
.welcome.is-entering { opacity: 0; transition: none; }
.welcome.is-leaving { opacity: 0; pointer-events: none; transition: opacity var(--t-out, 170ms) var(--ease-exit); }

.onb {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  max-width: 34rem;
  margin-inline: auto;
  padding-block: calc(var(--safe-top) + .625rem) calc(var(--safe-bottom) + 1.5rem);
  padding-inline: max(var(--gutter), var(--safe-left), var(--safe-right));
  color: var(--text);
}
/* 换页（E14.2 快出、慢进）：旧的 130 ms 淡出（= ui-settings.js 的 SWAP_FADE），新的 260 ms 以 scale(.988) 淡入 */
.onb.is-out { opacity: 0; transform: scale(.988); transition: opacity 130ms var(--ease-exit), transform 130ms var(--ease-exit); }
.onb--in { animation: onbIn 260ms var(--ease) backwards; }
@keyframes onbIn { from { opacity: 0; transform: scale(.988); } }
/* 换页时焦点落在标题上（给读屏），不是给眼睛的：不画焦点环 */
.onb [data-focus]:focus,
.onb [data-focus]:focus-visible { outline: none; }

.onb__top {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-height: 2.75rem;
}
.onb__top--start { justify-content: flex-start; }
.onb__back { margin-inline-start: -.5rem; color: var(--text-dim); }

/* 右上角的语言：一枚安静的描边胶囊，写的是当前语言的自称 */
.onb__lang {
  display: inline-flex;
  align-items: center;
  height: 1.875rem;
  padding: 0 .8125rem;
  border: 1px solid var(--border);
  border-radius: 99px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-ui);
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: color 140ms var(--ease), border-color 140ms var(--ease);
}
.onb__lang:hover { color: var(--text); border-color: var(--text-faint); }
html[data-touch="on"] .onb__lang { height: 2.375rem; padding-inline: 1rem; }
@media (hover: none) { .onb__lang:hover { color: var(--text-dim); border-color: var(--border); } }

.onb__main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  padding-top: clamp(1rem, 12vh, 7rem);
}

/* 第 1 页：品牌小印 + 名字（副名）是一个落款式的组合，真正的主角是下面那句标语 */
.onb__lockup { display: flex; align-items: center; gap: 1rem; }
.onb__lockup .brand { flex: none; }
.onb__names { display: flex; flex-direction: column; gap: .1875rem; min-width: 0; }
.onb__name {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -.02em;
}
.onb__name-alt { font-size: 1rem; line-height: 1.3; }
/* 非中文界面里的中文副行：衬线（简繁切片总是链接着）、不斜体、淡 */
.onb__zh {
  font-family: var(--font-serif);
  font-style: normal;
  font-weight: 400;
  color: var(--text-faint);
  letter-spacing: .02em;
}

.onb__tagline {
  margin: clamp(2rem, 7.5vh, 3.75rem) 0 0;
  font-family: var(--font-serif);
  font-size: clamp(1.625rem, 6.4vw, 2.25rem);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.onb__tagline-alt { margin: .5rem 0 0; font-size: .9375rem; line-height: 1.5; }
.onb__body {
  margin: 1.75rem 0 0;
  max-width: 26em;
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  line-height: 1.8;
  color: var(--text-dim);
}
.onb__private {
  margin: 1rem 0 0;
  font-family: var(--font-ui);
  font-size: .8125rem;
  line-height: 1.6;
  color: var(--text-faint);
}

.onb__acts {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  margin-top: 2rem;
}
.onb__acts .btn {
  width: 100%;
  min-height: 3rem;
  font-family: var(--font-ui);
  font-size: 1rem;
}

/* 第 2、3 页 */
.onb__h {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -.015em;
  text-wrap: balance;
}
.onb__lead {
  margin: .875rem 0 0;
  max-width: 28em;
  font-family: var(--font-serif);
  font-size: 1rem;
  line-height: 1.75;
  color: var(--text-dim);
}
.onb__cap {
  margin: 1.875rem 0 .625rem;
  font-family: var(--font-ui);
  font-size: .75rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text-faint);
}
/* 时区猜的家：几枚就全摆出来（折行），不横向滚 —— 建议就这几个，藏一半没有意义 */
.onb__chips {
  flex-wrap: wrap;
  overflow: visible;
  padding-block: 0;
  -webkit-mask-image: none;
  mask-image: none;
}

/* 「没有固定住处，走到哪吃到哪」：一颗安静的文字按钮，读作一句旁白，不是第二个选项。
   ⚠ padding-block 写死对称：它是 <button>，WebKit 的 UA 给按钮上 2 下 3 的内边距，中文会偏高（E7）。
   下划线用发丝色，点得到但不抢〔就是这里〕。 */
.onb__roam {
  align-self: flex-start;
  margin: .875rem 0 0;
  padding: .5rem 0;
  min-height: 2.25rem;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-ui);
  font-size: .875rem;
  line-height: 1.4;
  text-align: start;
  text-decoration: underline;
  text-decoration-color: var(--border);
  text-decoration-thickness: 1px;
  text-underline-offset: .3em;
  cursor: pointer;
  transition: color 140ms var(--ease), text-decoration-color 140ms var(--ease);
}
.onb__roam:hover { color: var(--text); text-decoration-color: var(--text-faint); }
html[data-touch="on"] .onb__roam { min-height: 2.75rem; }
@media (hover: none) { .onb__roam:hover { color: var(--text-dim); text-decoration-color: var(--border); } }
/* E9.6：搜一处就在这一页里 —— 真的输入框 + 下面一张结果表（行与选择器同一套 .prow），任何宽度都是 */
.onb__find { margin: 1rem 0 0; }
.onb__roam + .onb__find { margin-top: .75rem; }
.onb__lead + .onb__find { margin-top: 1.875rem; }
.onb__search {
  width: 100%;
  min-height: 3rem;
  gap: .625rem;
  font-family: var(--font-ui);
}
.onb__search:hover { border-color: var(--text-faint); }
.onb__search:focus-within { border-color: var(--accent-line); }
/* 自带的清除钮与放大镜交给我们自己的样子（Safari / Chromium 的 search 输入框各画一套） */
.onb__input { -webkit-appearance: none; appearance: none; }
.onb__input::-webkit-search-decoration,
.onb__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* 结果表：贴在输入框下面的一张纸（发丝线、圆角），最多约七行高，自己滚；
   行的内边距与选择器桌面面板一致，高亮 = 墨色竖条 +「↵」（styles.css 的 .prow[aria-selected]） */
.onb__results {
  margin-top: .375rem;
  max-block-size: min(22rem, 46vh);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-block: .25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--bg-elev);
}
.onb__results .prow { padding-inline: .875rem; cursor: pointer; }
.onb__results .pnote { padding-inline: .875rem; }
.onb__results .pnarrow { padding-inline: 3rem .875rem; padding-bottom: .625rem; }
.onb__more { margin-inline-end: -.25rem; color: var(--text-faint); display: inline-flex; }
.prow[aria-expanded="true"] .onb__more .ico { transform: rotate(-90deg); }
/* E14.2：结果表、语言列表、搬家的月历，高度随内容变：DLUI.growBox / growIn / growOut（app.js 唯一的一份），
   它们带 data-grow，过渡与裁边是 styles.css 的 [data-grow].is-swapping；从无到有长出来并淡入，收起加速离开 */

/* ---- 语言（欢迎页里的一页，E9.6）：一张列表就在卡片里，行与选择器同一套 .prow ---- */
.onb__find--lang { margin-top: 1.5rem; }
.onb__results--lang { max-block-size: min(30rem, 62vh); }
.onb__results--lang:focus { outline: none; }
.onb__langrow .prow__label { font-family: var(--font-serif); font-size: 1rem; }
.onb__langrow[aria-current="true"] .prow__label { font-weight: 600; }
.onb__langrow[aria-disabled="true"] { pointer-events: none; opacity: .6; transition: opacity 140ms var(--ease); }
.onb__langcheck { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 1.125rem; color: var(--accent); }
/* 没有过滤框时：「回车会选的那一行」的墨色竖条只在用键盘走这张表时出现（鼠标、手指看到的只是勾） */
.onb__results--lang[tabindex]:not(:focus-visible) .prow[aria-selected="true"] { background: transparent; }
.onb__results--lang[tabindex]:not(:focus-visible) .prow[aria-selected="true"]::before { display: none; }
.onb__results--lang[tabindex]:not(:focus-visible) .prow[aria-selected="true"] .prow__enter { display: none; }
@media (hover: hover) {
  .onb__results--lang[tabindex]:not(:focus-visible) .prow[aria-selected="true"]:hover { background: var(--bg-elev2); }
}

.onb__chosen {
  display: flex;
  align-items: center;
  gap: .9375rem;
  margin-top: 1.25rem;
  padding: .875rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--bg-elev);
}
.onb__chosen .seal { flex: none; }
.onb__chosen-text { display: flex; flex-direction: column; gap: .1875rem; min-width: 0; }
.onb__chosen-name {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.onb__chosen-sub { font-family: var(--font-ui); font-size: .8125rem; line-height: 1.45; color: var(--text-dim); }
.onb__chosen-sub .sub-en { font-size: .875rem; }

/* 第 3 页：主屏幕上的那一格（真图标 + 真名字）+ 怎么装 */
.onb__steps {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  margin-top: 1.75rem;
  padding: 1.125rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-card);
  background: var(--bg-elev);
}
.onb__tile {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .375rem;
  width: 4.5rem;
}
.onb__tile-name {
  font-family: var(--font-ui);
  font-size: .6875rem;
  line-height: 1.2;
  color: var(--text-dim);
}
.onb__how {
  margin: 0;
  min-width: 0;
  font-family: var(--font-ui);
  font-size: .9375rem;
  line-height: 1.6;
  color: var(--text);
}
/* 「已经在这里记了一些？」：挂在卡片后面的一句补充，左边一道发丝线，读作注脚而不是第二个选项 */
.onb__move {
  margin-top: 1.5rem;
  padding-inline-start: .875rem;
  border-inline-start: 2px solid var(--border);
}
.onb__move-text {
  margin: 0;
  font-family: var(--font-ui);
  font-size: .8125rem;
  line-height: 1.6;
  color: var(--text-dim);
}
.onb__move-btn { margin-top: .625rem; gap: .4375rem; font-family: var(--font-ui); }

/* 宽屏：整页居中成一栏，按钮并排、跟在正文后面（不再贴到窗口底边） */
@media (min-width: 720px) {
  .onb { justify-content: center; padding-block: calc(var(--safe-top) + 1.5rem) calc(var(--safe-bottom) + 2.5rem); }
  .onb__top { position: absolute; inset-block-start: calc(var(--safe-top) + .75rem); inset-inline: 0; max-width: 34rem; margin-inline: auto; padding-inline: max(var(--gutter), var(--safe-left), var(--safe-right)); }
  .onb__main { flex: 0 0 auto; padding-top: 3.5rem; }
  .onb__acts { flex-direction: row; flex-wrap: wrap; margin-top: 2.5rem; }
  .onb__acts .btn { width: auto; min-width: 10.5rem; padding-inline: 1.5rem; }
}
@media (max-height: 640px) and (max-width: 719px) {
  .onb__main { padding-top: .5rem; }
  .onb__tagline { margin-top: 1.5rem; }
}

/* ==========================================================================
   1b. 欢迎页的底：一张发丝线的世界（ADDENDUM-4 E12「细线世界」；实验室 hairline 手工并入，图注取自 spread）
   --------------------------------------------------------------------------
   .wbg 是 #welcome 的第一个孩子，换页不换（「同一张纸，下一页」）；画布由 ui-settings.js 第 2b 节画。
   ⚠ 画布的 left / top 是物理坐标（地图不随 RTL 镜像），由 JS 按屏幕像素给，这里只给 position。
   ⚠ 动作：底图有缓存时第一帧就在；晚到时 900 ms 淡进来（大面积的变化从不「啪」地出现）；换到别的页
     上过的色 --t-out 退场、回到第 1 页 --t-in 淡回；手机上那一条世界放不下时 --t-out 淡出。
   ========================================================================== */
.wbg {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  transition: opacity var(--t-scrim-in, 260ms) var(--ease);
}
.wbg.is-empty { opacity: 0; transition: opacity var(--t-out, 170ms) var(--ease-exit); }
.wbg__base, .wbg__bloom, .wbg__wash, .wbg__more, .wbg__home { position: absolute; top: 0; left: 0; display: block; }   /* 物理坐标：见上 */
.wbg.is-pending .wbg__base { opacity: 0; transition: none; }
.wbg.is-slow .wbg__base { transition: opacity 900ms var(--ease); }
.wbg__bloom, .wbg__more { transition: opacity var(--t-in, 220ms) var(--ease); }
.wbg__bloom.is-off, .wbg__more.is-off { opacity: 0; transition: opacity var(--t-out, 170ms) var(--ease-exit); }
/* 字底下的地方（放着不动、世界接着亮的那一段）：形状碰到字的一行（+18 px）的那一处不上阶色、不画斜线，整处只铺一层
   很淡的晕 = 第 1 阶的颜色 × --wb-wash（它自己一块画布 .wbg__wash 的 opacity，再乘字栏那道 40 % 的遮罩；
   每一处在那块画布上都是不透明的，重叠处不会越叠越深）。地图不挪。
   几档由 .wbg[data-wash] 切（ui-settings.js 的 WB_WASH 给默认）；blank = 不画（之前的样子：美洲在字底下几乎不亮）。 */
.wbg, .wbg[data-wash="blank"] { --wb-wash: 0; }
.wbg[data-wash="1"] { --wb-wash: .2; }
.wbg[data-wash="2"] { --wb-wash: .35; }
.wbg[data-wash="3"] { --wb-wash: .5; }
.wbg__wash { opacity: var(--wb-wash); transition: opacity var(--t-in, 220ms) var(--ease); }
.wbg__wash.is-off { opacity: 0; transition: opacity var(--t-out, 170ms) var(--ease-exit); }
/* 选好的家（E14.9）：一处最浅的阶色 + 家圈。换一处 = 新的 260 ms 淡入、旧的离开的缓动淡出（交叉）；
   在字那一栏底下时 JS 给 --wb-a（四成起），与底图的遮罩同一个意思 */
.wbg__home { opacity: 0; transition: opacity var(--t-out, 170ms) var(--ease-exit); }
.wbg__home.is-on { opacity: var(--wb-a, 1); transition: opacity var(--t-scrim-in, 260ms) var(--ease); }
/* 宣纸纹压在墨线之上：线是印进纸里的，不是浮在纸上的（与 body::before 同一张噪声、同一个 --paper-noise） */
.wbg::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: var(--paper-noise);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.6' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 260px 260px;
}
@supports (-webkit-touch-callout: none) {
  @media (pointer: coarse) { .wbg::after { display: none; } }
}
.welcome > .onb { position: relative; z-index: 1; }

/* 对句的两半：手机上是行内的（照旧一行），宽屏上各占一行 */
.onb__line { display: inline; }
/* 刊头与落款的发丝线、末端角的图注：只在宽屏的第 1 页（与从设置打开的装机页）出现 */
.onb__rule, .onb__figcap { display: none; }

/* ---------- 宽屏：整页是一张扉页 ----------
   字落在阅读起点那一栏（--wcol ≈ 视口的 36 %），世界铺满整页；上下两条发丝线把它框成一张版面：
   刊头（品牌 ··· 语言）下面一条，落款（「只存在这台设备上」··· 图注）上面一条。
   矮的宽屏（< 36rem）字会滚而世界是固定的，避让框就不准了：退回单栏。 */
@media (min-width: 60rem) and (min-aspect-ratio: 1/1) and (min-height: 36rem) {
  .welcome {
    --wm: clamp(2.5rem, 6vw, 7rem);
    --wcol: clamp(26rem, 36vw, 40rem);
  }
  .onb {
    max-width: none;
    margin-inline: 0;
    padding-block: calc(var(--safe-top) + clamp(1.25rem, 3.6vh, 2.5rem)) calc(var(--safe-bottom) + clamp(1.25rem, 4.2vh, 2.75rem));
    padding-inline: max(var(--wm), var(--safe-left), var(--safe-right));
  }
  /* 第 2、3 页与语言页也落在同一栏：世界留着，上过的色退场 */
  .onb > :not(.onb__top) { max-width: var(--wcol); }
  .onb__top { max-width: none; margin-inline: 0; padding-inline: max(var(--wm), var(--safe-left), var(--safe-right)); }
  /* 字底下那一栏的世界退到四成：线从字里穿过去读起来像印坏了；到字栏的边 + 10rem 回到全浓。
     遮罩只用透明度（#fff / transparent 是 test/csp.mjs 放行的两个字面量），RTL 反过来。 */
  .wbg__base,
  .wbg__wash,
  .wbg__more {
    -webkit-mask-image: linear-gradient(90deg, color-mix(in srgb, #fff 40%, transparent) calc(var(--wm) + var(--wcol) * .8), #fff calc(var(--wm) + var(--wcol) + 10rem));
    mask-image: linear-gradient(90deg, color-mix(in srgb, #fff 40%, transparent) calc(var(--wm) + var(--wcol) * .8), #fff calc(var(--wm) + var(--wcol) + 10rem));
  }
  [dir="rtl"] .wbg__base,
  [dir="rtl"] .wbg__wash,
  [dir="rtl"] .wbg__more {
    -webkit-mask-image: linear-gradient(270deg, color-mix(in srgb, #fff 40%, transparent) calc(var(--wm) + var(--wcol) * .8), #fff calc(var(--wm) + var(--wcol) + 10rem));
    mask-image: linear-gradient(270deg, color-mix(in srgb, #fff 40%, transparent) calc(var(--wm) + var(--wcol) * .8), #fff calc(var(--wm) + var(--wcol) + 10rem));
  }
  /* 上色画布只盖着那几处的外接框：遮罩按它自己的盒子算会错位，所以它不遮（上色的地方本来就避开了字 + 18 px） */

  .onb--hello {
    display: grid;
    grid-template-columns: minmax(0, var(--wcol)) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(2rem, 1fr) auto auto auto auto minmax(2rem, 1.3fr) auto auto;
    grid-template-areas:
      "brand lang"
      "hrule hrule"
      ".     ."
      "tag   ."
      "alt   ."
      "body  ."
      "acts  ."
      ".     ."
      "frule frule"
      "priv  cap";
    column-gap: 2rem;
  }
  .onb--hello > * { max-width: none; }
  .onb--hello .onb__top,
  .onb--hello .onb__main { display: contents; }
  .onb--hello .onb__lang { grid-area: lang; justify-self: end; align-self: center; }
  .onb--hello .onb__lockup { grid-area: brand; align-self: center; gap: .875rem; }
  .onb--hello .onb__lockup .brand { width: 2.75rem !important; height: 2.75rem !important; }   /* brandMark 给的是 CSSOM 尺寸 */
  .onb--hello .onb__names { flex-direction: row; align-items: baseline; gap: .625rem; }
  .onb--hello .onb__name { font-size: 1.5rem; letter-spacing: -.01em; }
  .onb--hello .onb__name-alt { font-size: 1.0625rem; }
  .onb--hello .onb__rule { display: block; height: 0; border-block-start: 1px solid var(--border); }
  .onb--hello .onb__rule--head { grid-area: hrule; margin-block-start: .875rem; }
  .onb--hello .onb__rule--foot { grid-area: frule; margin-block-end: .875rem; }

  .onb--hello .onb__tagline {
    grid-area: tag;
    margin: 0;
    font-size: clamp(2.75rem, min(4.4vw, 7.5vh), 4.75rem);
    font-weight: 500;
    line-height: 1.08;
    letter-spacing: -.022em;
  }
  html:is(:lang(zh), :lang(ja), :lang(ko)) .onb--hello .onb__tagline {
    font-size: clamp(3rem, min(5.4vw, 9.5vh), 5.75rem);
    line-height: 1.24;
    letter-spacing: .03em;
  }
  .onb--hello .onb__line { display: block; }
  .onb--hello .onb__tagline-alt { grid-area: alt; margin: .875rem 0 0; font-size: 1.25rem; line-height: 1.45; }
  .onb--hello .onb__body {
    grid-area: body;
    margin: clamp(1.75rem, 4.5vh, 2.75rem) 0 0;
    max-width: 29em;
    font-size: clamp(1.125rem, .55vw + .75rem, 1.3125rem);
    line-height: 1.8;
  }
  html:lang(zh) .onb--hello .onb__body { max-width: 25em; }
  .onb--hello .onb__acts {
    grid-area: acts;
    flex-direction: row;
    align-items: center;
    gap: .75rem;
    margin-top: clamp(1.75rem, 4.5vh, 2.5rem);
  }
  .onb--hello .onb__acts .btn { width: auto; min-width: 9.5rem; padding-inline: 1.5rem; }
  .onb--hello .onb__private { grid-area: priv; align-self: start; margin: 0; }

  .onb__figcap { display: flex; }
  .onb--hello .onb__figcap { grid-area: cap; justify-self: end; align-self: start; }
  .onb--install .onb__figcap {
    position: fixed;
    inset-block-end: calc(var(--safe-bottom) + clamp(1.25rem, 4.2vh, 2.75rem));
    inset-inline-end: max(var(--wm), var(--safe-left), var(--safe-right));
    max-width: none;
  }
}
/* 末端角的图注：一方印（云南上色时落下，刻「滇」）+ 两行（「初尝 · 云南」/「示例 · 那个人」）。两行字第一帧就在；
   印先占位（visibility），落印时才出现，版面不跳。字的样子写在媒体查询外面（只有宽屏 display:flex）：
   docs/optics 的测量台在 390 宽下也要量得到它（E7）。 */
.onb__figcap { align-items: center; gap: .75rem; margin: 0; }
.onb__figcap-seal { display: flex; flex: none; }
.onb__figcap-text { display: flex; flex-direction: column; gap: .125rem; min-width: 0; }
/* 行高 1.4 = 21 px：半行距正好 3 px。1.35（20.25 px）时 Blink 把半行距向下取整，中文在行盒里高 0.8 px（-5.4 %，docs/optics） */
.onb__figcap-first { margin: 0; font-family: var(--font-serif); font-size: .9375rem; line-height: 1.4; color: var(--text-dim); }
.onb__figcap-what { margin: 0; font-family: var(--font-ui); font-size: .75rem; line-height: 1.45; color: var(--text-faint); }
.onb__figcap.is-pending .onb__figcap-seal { visibility: hidden; }

/* ==========================================================================
   2. 设置表单
   ========================================================================== */

.set { padding-bottom: .5rem; }
.set__group { margin-top: 1.5rem; }
.set__group:first-child { margin-top: .375rem; }
.set__h {
  margin: 0 0 .5rem;
  padding-inline: .125rem;
  font-family: var(--font-ui);
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: .04em;
  color: var(--text-faint);
}
.set-row .row__label { overflow-wrap: anywhere; }
.set-row__value { display: inline-flex; align-items: center; gap: .4375rem; }
.set-row__value .seal { flex: none; }
.set-row__text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-row > .ico:first-child { flex: none; }
.row--danger > .ico { color: currentColor; }
/* 行首带印的行（住过的地方）：印与名字之间比图标行宽一点，印不许被挤扁 */
.set-row--seal { gap: .8125rem; }
.set-row--seal > .seal { flex: none; }
.set-row--seal .row__label { font-family: var(--font-serif); font-size: 1rem; font-weight: 500; }
.set-row--seal .row__sub { font-family: var(--font-ui); font-weight: 400; font-variant-numeric: tabular-nums; }
/* 分段放在行尾；放不下就整段折到下一行，从行首开始 */
.set-row--seg { flex-wrap: wrap; row-gap: .5rem; }
.set-row--seg .seg { margin-inline-start: auto; }

.set__note {
  margin: .5rem .125rem 0;
  font-family: var(--font-ui);
  font-size: .75rem;
  line-height: 1.55;
  color: var(--text-faint);
}
.set__status { margin: 0 .125rem .75rem; }
.set__line {
  margin: 0;
  font-family: var(--font-ui);
  font-size: .8125rem;
  line-height: 1.6;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.set__line + .set__line { margin-top: .1875rem; }
/* 真的 disabled（不是 pointer-events:none）：淡下去、不响应悬停 */
.set-row:disabled { opacity: .42; cursor: default; }
.set-row:disabled:hover { background: transparent; }

.set__para {
  margin: .875rem .125rem 0;
  font-family: var(--font-ui);
  font-size: .8125rem;
  line-height: 1.7;
  color: var(--text-dim);
}
.set__para--credits { font-size: .75rem; color: var(--text-faint); }

/* 落款：小印 + 名字（13px、500、−.015em）+ 家族描述。一枚签名，不是一条横幅。 */
.set__colophon {
  display: flex;
  align-items: center;
  gap: .625rem;
  margin: 1.75rem .125rem .25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--border-soft);
}
.set__colophon .brand { flex: none; }
.set__colophon-text { display: flex; flex-direction: column; gap: .125rem; min-width: 0; }
.set__colophon-name {
  font-family: var(--font-serif);
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: -.015em;
  color: var(--text);
}
.set__colophon-alt { font-size: .8125rem; }
.set__colophon-desc { font-family: var(--font-ui); font-size: .75rem; line-height: 1.45; color: var(--text-faint); }
/* 第 3 行：名字的来历（about_name，ADDENDUM-5 E18.3）。同字号，颜色深一档（--text-dim），不斜体（斜体只给英文副名） */
.set__colophon-note { color: var(--text-dim); }

/* ---- 语言列表 ---- */
.set-lang__name { font-size: 1rem; }
.set-lang__row[aria-pressed="true"] .set-lang__name { font-weight: 600; }
.set-lang__check {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.125rem;
  height: 1.125rem;
  color: var(--accent);
}

/* ---- 搬家：从哪天开始住在这里？ ---- */
.set-move__place { display: flex; align-items: center; gap: .75rem; margin: .25rem 0 1rem; }
.set-move__place .seal { flex: none; }
.set-move__name {
  font-family: var(--font-serif);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.set-move__acts { display: flex; justify-content: flex-end; margin-top: 1rem; }

/* ---- 住过的地方 · 一段的小表单 ---- */
.set-base { padding-top: .25rem; }
.set-base__head { display: flex; align-items: center; gap: .9375rem; }
.set-base__head .seal { flex: none; }
.set-base__text { display: flex; flex-direction: column; gap: .1875rem; min-width: 0; }
.set-base__name {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}
.set-base__sub { font-family: var(--font-ui); font-size: .8125rem; line-height: 1.45; color: var(--text-dim); }
.set-base__facts {
  margin: 1rem 0 0;
  padding-top: .875rem;
  border-top: 1px solid var(--border-soft);
  font-family: var(--font-ui);
  font-size: .9375rem;
  line-height: 1.5;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
/* 两颗按钮：〔在地图上看〕是正事，〔删掉这一段〕是安静的红字（危险但不喊） */
.set-base__acts { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.25rem; }
.set-base__btn { gap: .4375rem; font-family: var(--font-ui); }

/* 城市表还没到时住处印的空位：与印同尺寸（.seal 按 --s 定宽高），不画任何东西，到了整块重画（不跳版） */
.set-seal-ph { visibility: hidden; }

/* ---- E8：出现与消失 ---- */
/* 选好的那一处从无到有 */
.onb__chosen.is-in { animation: onbChosenIn var(--t-in, 240ms) var(--ease) backwards; }
@keyframes onbChosenIn { from { opacity: 0; transform: translateY(.25rem); } }
/* 设置重画：组的高度过渡（ui-settings.js growGroups 写起止高度，这里只给过渡与裁切） */
.set__group.is-growing { overflow: clip; transition: height var(--t-grow, 300ms) var(--ease); }
.set__group.is-new > * { animation: setGroupIn 180ms var(--ease) backwards; }
@keyframes setGroupIn { from { opacity: 0; } }
/* 消失的组（影子）：高度、上外边距、不透明度一起收到 0，加速离开 */
.set__group.is-leaving-g {
  overflow: clip;
  pointer-events: none;
  transition: height var(--t-grow, 300ms) var(--ease-exit), margin-top var(--t-grow, 300ms) var(--ease-exit), opacity 180ms var(--ease-exit);
}
.set__group.is-leaving-g.is-gone { margin-top: 0; opacity: 0; }
