/* 雇主开户 V3（分屏 + 右侧信任面板）。
 *
 * 命名空间 `.v3-`。这份文件是从 public/onboarding-v3-prototype.html 的 <style> 整段搬过来的
 * —— 原型本来就 <link> 了线上真实 CSS，所以这里**只有**原型里那些 `.v3-` 私有规则，
 * 以及少量对 `.me-*` 既有控件的作用域内覆盖。没有任何重新实现的设计系统组件。
 *
 * ⚠️ 原型 <style> 开头那段「基础」（body 字体栈 / reset）**刻意没有搬**：那是原型自己
 * 没有 globals.css 才需要的，生产由 app/layout.tsx 与既有 CSS 负责，照搬会污染全站。
 *
 * 改这里之前先读 .claude/skills/bonjour-ui/SKILL.md。原型仍然是这套版式的可交互参照，
 * 两边不一致时以本文件为准（原型不参与构建）。
 */

/* 分屏各步靠 hidden 属性切换显隐，这条兜底是**必需**的，不是防御性写法：
   `.v3-split-left { display: flex }` 是作者样式，而 UA 的 `[hidden] { display: none }`
   永远输给作者样式（与特异性无关，是层叠来源的优先级）。不写这条，hidden 完全不生效 ——
   表现是四个步骤同时铺在页面上（实测过，就是这个症状）。
   同理站内引进来的 CSS 也会给 .me-field-err / .me-onboarding-weixin-state 这类元素写死
   display，把它们的 hidden 压掉。
   ⚠️ 作用域必须收在 .v3-split 内。原型里这条是全局 `[hidden]{display:none!important}`，
   那在原型里没问题（单页），搬进生产会波及站内所有刻意覆盖 hidden 的组件。 */
.v3-split[hidden],
.v3-split [hidden] { display: none !important; }

/* ⚠️ box-sizing 收进 V3 作用域。原型的「基础」段里有全局 `* { box-sizing: border-box }`，
   我搬 CSS 时当成 reset 丢掉了 —— 但这份版式里到处是「同时写 height/min-height 和 padding」
   的写法，全都默认 border-box。实测代价：`.v3-ready` 的 `min-height:100vh` + `padding:56px`
   在 content-box 下相加成 1012px（视口 900），交接屏于是既不垂直居中、又能滚。
   不照搬全局 reset（那会波及全站），只在 V3 这两个容器里生效。
   这是丢掉那一段的第二个坑，第一个是 [hidden]（见下）。 */
.v3-split,
.v3-split *,
.v3-root,
.v3-root * { box-sizing: border-box; }

/* ══════════════════════════════════════════════════════════════════
   ① 开户页版式 —— 照抄 OnboardingJobComposer.module.css（另一份来源 OnboardingFlowV2Preview.module.css 已随 V2 下线）
      （CSS Module 编译进 Next chunk，link 不进来，只能复制。比例、断点、gap 全部保持原值）
   ══════════════════════════════════════════════════════════════════ */

/* ⚠️ 必须带 :has() 作用域。原型是单页，这两条写成了裸选择器；照搬进生产就是把
   **全站每一个 me-shell 页面**的 880px 上限顶成 1280、内距也一起改掉（本文件在
   me-shell.css 之后加载，同特异性下后来者赢）。实测后台所有页都受影响。
   1280 而不是 1140 —— 两栏 + 大 gap 需要这个总宽，仍在 §3 的 1312 断点内。 */
.me-shell-main-inner:has(.v3-root) { max-width: 1280px; }
.me-shell-main:has(.v3-root) { padding: 28px 36px 120px; }

/* 满屏分屏（四步 + 交接屏）：解除 shell 的内距与宽度上限，让右列铺到屏幕边缘。
   ⚠️ 用 :has() 而不是原型那套 `body.is-split` —— 原型靠 JS 给 body 加类，生产照搬
   就得在 client effect 里改全局 class：SSR 首帧没有这个类，会先按 880 窄栏渲染再跳成
   满屏（首屏闪一下），还要负责卸载时清理。:has() 是纯 CSS，两个问题都没有。
   （me-shell.css 曾有同样写法的先例 `.create-team-page--onboarding-edit`，随 V1/V2 下线已删） */
/* ⚠️ 交接屏（data-step="done"）也要算进来：它自己是 min-height:100vh 的居中屏，
   外面再套一层 shell 的 28/120 内距，100vh 就顶不下 —— 内容被推到中线以下、整页还多出
   一截可滚（实测就是「看起来没居中」）。原型里这两类共用同一个 is-split 开关，
   搬过来时只搬了分屏那一半。
   特异性 (0,3,0) 压过上面那条给 .v3-root 的 (0,2,0)。 */
.me-shell-main:has(.v3-split),
.me-shell-main:has(.v3-root[data-step="done"]) { padding: 0; }
.me-shell-main-inner:has(.v3-split),
.me-shell-main-inner:has(.v3-root[data-step="done"]) { max-width: none; }
/* 整页不滚，滚动只发生在两列各自内部（交接屏本来就只有一屏）。
   ⚠️ 职位步（data-step="job"）是常规文档流，绝不能锁，锁了就滚不动。 */
body:has(.v3-split),
body:has(.v3-root[data-step="done"]) { overflow: hidden; }

.v3-root {
  display: flex;
  flex-direction: column;
  width: 100%;
  gap: 20px;
  padding-inline: 36px;
  min-height: calc(100vh - 210px);
}
.v3-root[hidden] { display: none; }

/* 62:38 ≈ 760:460。原版注释：写死像素会静默退化成按比例压缩，不如把比例本身写明。 */
.v3-stage {
  display: grid;
  grid-template-columns: minmax(0, 62fr) minmax(0, 38fr);
  gap: 56px;
  align-items: start;
  width: 100%;
  flex: 1 1 auto;
  min-height: 0;
}

.v3-form-col {
  align-self: start;
  display: flex;
  flex-direction: column;
  gap: 32px;
  min-width: 0;
}

.v3-intro { display: flex; flex-direction: column; gap: 4px; }
.v3-title-row { display: flex; align-items: center; gap: 14px; }
.v3-title-copy { display: flex; min-width: 0; flex-direction: column; gap: 4px; }
.v3-title {
  margin: 0;
  color: #1d1d1f;
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.012em;
  line-height: 1.3;
}
.v3-desc {
  margin: 0;
  color: #86868b;
  font-size: 13px;
  font-weight: 400;
  line-height: 18.2px;
  max-width: 65ch;
}

/* 建团表单卡：几何取自 home.css 的 .create-team-page__card（§2 全站统一一档容器边界），
   但那条 class 绑在整页布局上，这里只取参数。 */
.v3-form-card {
  width: 100%;
  padding: 40px 32px 32px;
  border-radius: 24px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 8px 24px -12px rgba(0, 0, 0, 0.06);
}

/* 编辑器外框去描边：JD 面板本身已经是一张卡，里面再套一圈框就是「框中框」，
   §2 只允许一层容器边界。⚠️ 保留 1px transparent 而不是 border:0 —— 报错态
   （.is-err）还要靠 border-color 变红，写成 0 高度会跳。
   overflow 也要放开：工具栏气泡的阴影会溢出 me-tip，overflow:hidden 会削掉一半。 */
/* border-width 归零而不是只把颜色调透明：留着 1px 透明边，正文就比左边的职位名和
   chip 往里缩 1px，内距归零之后这 1px 就是唯一还没对齐的东西。
   overflow 也要放开：工具栏气泡的阴影会溢出 me-tip，overflow:hidden 会削掉一半。 */
[data-step="job"] .me-tip {
  border-width: 0;
  overflow: visible;
}

/* 编辑器工具栏改成浮起的气泡（同 macOS 备忘录那种），并落到正文下面 ——
   备忘录的格式条也在底部：写字时视线在文末，工具就该在手边，放顶上等于每次
   要抬一次视线。DOM 顺序已同步调整，Tab 焦点不会和视觉次序打架。
   阴影比 §2 的容器档略强：它是浮在正文之上的控件，不是并排的内容块。 */
[data-step="job"] .me-tip-toolbar {
  align-self: center;
  flex: none;
  margin: 8px 0 0;
  padding: 4px 6px;
  border: 0;
  border-radius: 999px;
  background: #ffffff;
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.04),
    0 6px 20px -8px rgba(0, 0, 0, 0.18);
  gap: 2px;
}
[data-step="job"] .v3-tip-btn {
  width: 34px;
  height: 30px;
  border-radius: 999px;
  color: #1d1d1f;
  font-size: 13.5px;
  cursor: pointer;
  transition: background 150ms ease;
}
/* design-ok: §1 允许的 hover 临时态 */
[data-step="job"] .v3-tip-btn:hover { background: #f5f5f5; }

/* ⚠️ JD 面板要有确定高度，正文才可能在框内滚动而不是把面板撑长。
   这条链每一层都要 min-height:0 —— 缺任一层，flex 子项就退回「按内容撑高」，
   编辑器一打字整页就变长（生产的 me-editors.css 同注）。
   .v3-form-col 默认是 align-self:start（分屏几步要它贴顶），这一步必须改回 stretch。 */
[data-step="job"] .v3-form-col {
  align-self: stretch;
  min-height: 0;
}
[data-step="job"] .v3-jd-panel {
  height: 100%;
  min-height: 0;
}

/* JD 步的 JD 面板：照抄 .jdPanel */
.v3-jd-panel {
  display: flex;
  flex-direction: column;
  padding: 34px 36px 28px;
  border-radius: 32px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 8px 24px -12px rgba(0, 0, 0, 0.06);
}
.v3-team-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
  color: #6e6e73;
  font-size: 14px;
}
.v3-team-logo-ph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px; height: 24px;
  flex: none;
  border-radius: 8px;
  background: #ffffff;
  color: #86868b;
  font-weight: 500;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
/* 职位名输入：静态态不画横线（§1），下边框透明 —— focus / 报错换色，高度不跳（§4） */
.v3-role-input.me-input {
  padding: 7px 0 9px;
  border-width: 0 0 1px;
  border-color: transparent;
  border-radius: 0;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
}
.v3-role-input.me-input:focus { border-color: #2e84fa; }
.v3-role-input.me-input--err { border-color: #e5484d; }

/* meta chip 行：照抄 OnboardingJobMetaChips.module.css */
.v3-chip-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 12px; }
.v3-chip {
  position: relative;
  appearance: none;
  font: inherit;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0; max-width: 100%;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  background: #f5f5f7; /* design-ok: 照抄 JD hero 事实 chip 的灰底，非 §1 的分区填充 */
  border: 0;
  color: #1d1d1f;
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}
/* 30px 的 pill 视觉刚好，但点击区太小 —— 伪元素撑到 44px，视觉不变（§5.3） */
.v3-chip::before { content: ""; position: absolute; inset: -7px 0; }
.v3-chip svg { flex: none; color: #6b7280; }
.v3-chip:hover { background: #ececef; }
.v3-chip:active { transform: scale(0.97); }
.v3-chip.is-empty, .v3-chip.is-empty svg { color: #6e6e73; }
/* 填完就撤掉加号，chip 从「动作」变回「事实」 */
.v3-chip:not(.is-empty) .v3-chip-plus { display: none; }
.v3-chip.is-err, .v3-chip.is-err:hover { box-shadow: inset 0 0 0 1px #b91c1c; color: #b91c1c; }
.v3-chip.is-err svg { color: #b91c1c; }

.v3-jd-editor { margin-top: 34px; display: flex; flex-direction: column; flex: 1; min-height: 0; }
.v3-jd-editor .me-tip { display: flex; flex-direction: column; flex: 1; min-height: 0; }
/* padding 不在这里写：上面 [data-step="job"] 那条同为 (0,2,0)，谁在后面谁赢，
   两处都写就是在靠行号定胜负。气泡的尺寸只由那一条负责。 */
.v3-jd-editor .me-tip-toolbar { flex: none; }
/* 外框去掉之后，正文那圈 14/16 的内距就没有参照物了 —— 它原本是「离框边多远」，
   现在框不在了，只剩下正文相对左边职位名 / chip 那条内容线往里缩一截。左右上归零，
   正文直接落到内容线上。底部留 8：正文和下面那颗工具栏气泡之间要有间隙。
   ⚠️ 归零走变量，不是直接写 .me-tip-body 的 padding —— 提示层 .me-tip-ghost 读同一组
   变量，写死只改正文会让提示往右下各偏一截（这条就是 2026-08-18 修的那个错位）。 */
.v3-jd-editor .me-tip {
  --me-tip-pad-y: 0px;
  --me-tip-pad-x: 0px;
}
.v3-jd-editor .me-tip-body {
  flex: 1;
  height: auto;
  min-height: 220px;
  padding-bottom: 8px;
  overflow-y: auto;
  scrollbar-width: none;
}
.v3-jd-editor .me-tip-body::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* 边框没了，报错态改用 outline —— outline 不参与布局，画出来正文不会位移 1px；
   offset 8 让红框离正文有口气，不至于贴着字。 */
.v3-jd-editor.is-err .me-tip { outline: 1px solid #e5484d; outline-offset: 8px; }
.v3-tip-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border: 0; border-radius: 8px;
  background: none; color: #5d5d5d;
  font-size: 13px;
  cursor: default;
}

/* savebar：几何继承 me-editors.css 的 .me-savebar 基类，这里只定位 */
.v3-savebar.me-savebar { align-self: center; margin-top: auto; }
.v3-err {
  margin: 0;
  overflow: hidden;
  color: #b91c1c;
  font-size: 13px; line-height: 1.4;
  text-overflow: ellipsis; white-space: nowrap;
}
.v3-hint { margin: 0; color: #86868b; font-size: 13px; line-height: 1.4; }

/* 「跳过」是次要出口，不跟主按钮抢视觉重量（照抄 .skipBtn） */
.v3-skip.me-btn {
  background: transparent; border-color: transparent;
  color: #86868b; font-weight: 400;
}
.v3-skip.me-btn:hover:not(:disabled):not(.me-btn--primary) {
  background: transparent; border-color: transparent; color: #1d1d1f;
}

/* 下一步按钮：宽度锁在最长状态文案上，切换时不跳（照抄 .nextButton 的撑宽件手法，§4）。
   两个 class 都要命中 —— JD 步是 .me-savebar-btn，微信 / 通知步是 .me-btn--primary。 */
.v3-next.v3-next {
  display: grid; grid-template-areas: "label"; place-items: center;
  min-width: 88px; height: 42px; padding: 0 19px;
  font-size: 15px; font-weight: 500;
}
.v3-next > span { grid-area: label; }
.v3-next .v3-sizer { visibility: hidden; }

/* ══════════════════════════════════════════════════════════════════
   ② 步骤条（分屏三步挂在左列左上角；职位步自己带一份 .v3-plain-head）
   ══════════════════════════════════════════════════════════════════ */

/* 非分屏那一步的头部：返回键 + 进度点分列两端，跟着正常文档流 */
.v3-plain-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex: none;
}

/* 品牌位：占左上角，与右上角的进度点分列两端（同 Chatbase 的头部结构）。
   110px 同 landing 头部的 .hire-brand__logo，高度由 svg 比例（110×21.6）决定。 */
/* ⚠️ 高度必须写死：这个 svg 内部是 width/height="100%" + preserveAspectRatio="none"，
   没有固有尺寸，height:auto 会让它撑满容器并被拉变形（实测直接盖住了下面的标题）。
   22 = 110 × (21.6276 / 110)，按 viewBox 比例算出来的。 */
.v3-brand {
  width: 110px;
  height: 22px;
  flex: none;
  display: block;
}
/* 视觉隐藏但读屏可读 */
.v3-sr {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════════
   ③ 右栏价值面板（本次方案的核心新增）
   ══════════════════════════════════════════════════════════════════ */
.v3-visual { align-self: start; min-width: 0; }

/* 面板整体不是一张大卡：分组靠留白（§1），只有需要边界的子块才画容器 */
.v3-panel { display: flex; flex-direction: column; gap: 32px; min-width: 0; }
.v3-panel-eyebrow {
  margin: 0;
  color: #86868b;
  font-size: 13px;
  line-height: 1.5;
}
.v3-panel-title {
  margin: 0 0 12px;
  color: #1d1d1f;
  font-size: 15px; font-weight: 500;
  letter-spacing: -0.01em;
}

/* display 档标题：大字号 + 收紧字距（Apple 那种标题观感）。
   26 而不是更大 —— 右列的主角是 36px 的数字，标题不该跟它抢。 */
.v3-panel-title--display {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.3;
}
/* 50% 黑 ≈ #8e8e90，正好落在墨色阶的副文本档位上 */
.v3-title-dim { color: rgba(29, 29, 31, 0.5); }

/* 数据数字：2×2 网格，等宽数字防止抖动（§3） */
/* 行距 32 而不是 24：数字放到 36px 之后，24 的行距让上下两行黏在一起。
   列距保持 20 —— 同一行的两个数字是并列关系，不需要拉开。 */
.v3-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 32px 20px; }
/* 高光扫过。landing 那版是 WebGPU HDR 逐字形渲染（ThreeAnimatedWord + webgpu-hdr-word），
   纯 HTML 复刻不了，这里用 background-clip: text 做视觉近似：一条比主墨色浅的高光带
   横穿数字，扫完停一拍再来。
   design-ok: 自动播放的氛围动效（skill §5.2 例外档）。⚠️ 动的是 background-position
   不是 transform —— §5.3 的首选之外，但文字扫光只有这一种做法；作用对象是 4 个小文本，
   重绘成本可忽略，且不触 §5.4 的大容器红线。 */
.v3-stat-num {
  display: block;
  color: #1d1d1f;
  /* 26 → 36（type ramp 往上两档）：这一列的主角是数字，之前和评价卡的引言差不多重，
     没拉开层级。36 时最长的「300,000+」约 200px，两列各 315px 放得下。 */
  font-size: 36px; font-weight: 500;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}

/* ── 右列的入场编排（照 Apple 官网 WordAnim 的 slide 档：下移 10px 淡入，easeOutQuad）──
   逐块错开，打开页面时一块块落位。
   ⚠️ logo 墙不在序列里：它有 1200px+ 高，给「全内容高度的大容器」加 transform/opacity
   会在 iOS 上打穿内存（§5.4 红线，优先级高于一切动效需求）。它在页面下方，
   滚到时进场本来也早结束了。
   动画时长 420ms 超出 §5.2 的 300ms 上限，走的是「自动播放、无人等待」那档例外。 */
@keyframes v3-enter {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
/* 走 §5.2 那档「自动播放、无人等待」的例外：页面加载即播，只动 transform/opacity，
   reduced-motion 下整组关掉，且刻意不加在 logo 墙那种全内容高度容器上（§5.4）。 */
/* design-ok: 自动播放的入场氛围动效 */
.v3-anim { animation: v3-enter 420ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }

/* logo 墙的入场：⚠️ 动画加在**每一张卡片**上，不是加在墙容器上。
   墙有 1200px+ 高，给它整体上 transform/opacity 会把整块提升成合成层 —— 正是 §5.4
   那条 iOS 内存红线。单张卡片只有 ~200×52，60 张错峰播完就释放，没有大层。
   只动 opacity 不动 transform：60 个元素同时位移的开销没必要，淡入已经够。 */
@keyframes v3-fade-in { from { opacity: 0; } to { opacity: 1; } }
.v3-split-logo { animation: v3-fade-in 280ms ease-out both; }
/* 既要入场又要扫光的（两个标题）：两条动画并列声明，delay 各给各的 */
.v3-anim.v3-shine {
  animation:
    /* design-ok: 自动播放的入场氛围动效，同 .v3-anim */
    v3-enter 420ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both,
    /* ⚠️ 已知偏离：它动的是 background-position 而不是 transform/opacity ——
       文字扫光靠 background-clip:text 实现，没有等价的 transform 写法。
       reduced-motion 下整条关掉并回落纯墨色。 */
    /* design-ok: 自动播放的装饰性扫光 */
    v3-stat-shine 4200ms cubic-bezier(0.5, 0, 1, 1) infinite;
}

/* 扫光单独成 class：数字和标题共用同一道光，参数只有一份。
   加在谁身上谁就会被光扫过（.v3-stat-num / .v3-panel-title--display）。 */
.v3-shine {
  /* 色板 1:1 取自 webgpu-hdr-word.ts 的 thermalPalette()，把那几个 HDR vec3 收进 sRGB：
       coolBlue (0.025,0.16,1.0)   → #0629ff
       violet   (0.34,0.055,1.0)   → #570eff
       magenta  (0.96,0.045,0.52)  → #f50b85
       amber    (1.0,0.30,0.035)   → #ff4d09
       hotWhite (1.08,1.0,0.88)    → #fff4e0
     landing 上光带前缘偏蓝、核心品红转琥珀、尾部收到热白，这里按同一顺序排。
     ⚠️ 这些不是品牌色（§3 那支蓝仍然只有 #2e84fa），是复刻既有效果的光谱色，只出现在扫光带里。 */
  /* 光带占渐变的 34%~66%：background-size 是 260%，换算到元素上约 0.83 倍宽度，
     一次能把整组数字罩住。再窄就只有尾巴几个字符吃到光，看不出是一道光扫过。 */
  background-image: linear-gradient(
    100deg,
    #1d1d1f 0%, #1d1d1f 34%,
    #0629ff 40%,
    #570eff 45%,
    #f50b85 50%,
    #ff4d09 55%,
    #fff4e0 60%,
    #1d1d1f 66%, #1d1d1f 100%
  );
  background-size: 260% 100%;
  background-position: 130% 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  /* background-position 是 background-clip:text 文字扫光的唯一实现方式；
     reduced-motion 下关闭并回落纯墨色。 */
  /* design-ok: 自动播放的装饰性扫光 */
  animation: v3-stat-shine 4200ms cubic-bezier(0.5, 0, 1, 1) infinite;
}
/* 逐个错开，同 landing 的 stagger；四个一起扫会像整块闪，反而看不出是数字。
   起点排在入场序列之后（~800ms），不然数字还在往上滑就开始扫光，两件事糊在一起。 */
.v3-stats > div:nth-child(1) .v3-stat-num { animation-delay: 800ms; }
.v3-stats > div:nth-child(2) .v3-stat-num { animation-delay: 930ms; }
.v3-stats > div:nth-child(3) .v3-stat-num { animation-delay: 1060ms; }
.v3-stats > div:nth-child(4) .v3-stat-num { animation-delay: 1190ms; }

@keyframes v3-stat-shine {
  0%   { background-position: 130% 0; }
  /* 扫过约 1.9s，剩下 2.3s 停在原位当间歇 —— 不停歇地扫会一直抢注意力 */
  45%  { background-position: -30% 0; }
  100% { background-position: -30% 0; }
}
/* 6 而不是 4：数字变大后，标签贴得太近会像数字的下标而不是它的说明 */
.v3-stat-label { display: block; margin-top: 6px; color: #86868b; font-size: 13px; line-height: 1.4; }
.v3-footnote { margin: 0; color: #a1a1a6; font-size: 12px; line-height: 1.5; }

/* logo 墙 */
.v3-logos { display: flex; flex-wrap: wrap; gap: 8px; }
.v3-logo {
  display: inline-flex; align-items: center; gap: 6px;
  height: 30px; padding: 0 10px 0 6px;
  border-radius: 999px;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #1d1d1f; font-size: 12.5px; line-height: 1;
  white-space: nowrap;
}
.v3-logo img { width: 20px; height: 20px; border-radius: 6px; object-fit: cover; flex: none; }

/* 客户评价轮播：视口锁死高度 —— 每条长短不一，不锁高度整块面板会随换条上下跳（§4）。
   140 = 最长那条在最窄使用宽度下的正文行数 + 署名行 + 内距。 */
.v3-quote-viewport {
  overflow: hidden;
  /* 卡片 216（= 内距 56 + 品牌行 24 + 间距 40 + 正文三行 72 + 署名 24），
     再加上下各 20 的阴影余量 —— 全局 box-sizing 是 border-box，余量必须算进这个高度里，
     否则 padding 会从卡片身上扣，正文第三行就被压没了。 */
  height: 256px;
  /* 卡片阴影往外扩，overflow:hidden 会切掉它 —— 垂直方向先留余量再用等量负边距还原
     （底部那层阴影是主要的视觉）。⚠️ 水平方向不能这么做：负边距会把视口撑出右列的
     内距、卡片右缘被窗口切掉；而横向滑动本来就要求水平 hidden。 */
  /* 上下各留 20 再用等量负边距还原：hover 时阴影是 0 16px 36px -12px，向下扩散约 22，
     只留 8 的话放大那一下底部阴影会被这个 overflow:hidden 切掉半截。 */
  padding: 20px 0;
  /* 右边突破整个内距、顶到屏幕边缘；左边只突破 40 —— 右列内距是 56，
     突破满会让卡片正好压在分栏竖线上，把线和它的阴影一起吃掉。
     留 16 的余量，线才透得出来。 */
  margin: -20px -56px -20px -40px;
}
/* 横向切换（左右滑）。⚠️ 只动 transform，且轨道高度固定 140、不是「全内容高度的
   大容器」—— 不触 §5.4 的 iOS 内存红线。 */
.v3-quote-track {
  display: flex;
  height: 100%;
  /* 卡间距：相邻卡露出的那一截靠它和下面的 88% 一起决定 */
  gap: 12px;
  /* design-ok: 自动播放的氛围动效，skill §5.2 例外档（600–800ms） */
  transition: transform 620ms cubic-bezier(.2, 0, 0, 1);
}
/* 82% 而不是 100%：当前卡不占满视口，左右各露出相邻卡的一角 ——
   「前后还有」这件事由露出的边缘本身表达，不需要再写一句话或加计数器。
   82 是按「两边各露约 9%」反推的；再宽就只剩一条缝，看不出是卡片。 */
/* 86% 是按「视口已经比内容区宽了 56」反推的：卡片实宽仍接近内容宽，
   右边露出的那一截正好落在屏幕边缘外。 */
.v3-quote-track > .v3-quote { flex: 0 0 86%; }

/* 容器边界走 §2 统一那一档。内部三段：品牌名 → 引言 → 署名，靠留白分组（§1）。 */
.v3-quote {
  box-sizing: border-box;
  height: 100%;
  padding: 28px 32px;
  border-radius: 20px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 8px 24px -12px rgba(0, 0, 0, 0.06);
  /* 顺排 + 固定间距，不用 space-between —— 定高卡片里内容长短不一，
     space-between 会让短引言的署名被推到很远、长引言的又贴死在正文下面。 */
  display: flex; flex-direction: column; gap: 20px;
  cursor: pointer;
  /* hover 抬起的过渡，参数同主站团队卡 */
  transition:
    box-shadow .2s cubic-bezier(.2, 0, 0, 1),
    transform .3s cubic-bezier(0, 0, .5, 1);
}

/* 品牌名：退一档墨色，让引言本身是这张卡里最重的东西（§3 层级靠颜色） */
.v3-quote-brand {
  display: flex; align-items: center; gap: 8px;
  color: #86868b;
  font-size: 16px;
  line-height: 1.2;
}
.v3-quote-brand img {
  width: 20px; height: 20px; border-radius: 6px; object-fit: cover; flex: none;
}

/* 引言：卡内主体。字重 500 封顶（§3 不超 600），靠字号和墨色拿到重量 */
.v3-quote-text {
  margin: 0;
  flex: 1;
  min-height: 0;
  color: #1d1d1f;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.65;
  letter-spacing: -0.01em;
}

/* 署名：人名主墨色，职位与团队退到副墨色 —— 同一行里的两级信息不靠字重区分 */
/* center 而不是 baseline：这一行加了头像之后，baseline 会拿 22px 的图去跟 13px 的
   文字对基线，图整个被顶高 6px。名字和职位同字号，改 center 不影响它俩的对齐。 */
.v3-quote-who { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.v3-quote-name { color: #1d1d1f; font-size: 13px; }
.v3-quote-meta { color: #86868b; font-size: 13px; line-height: 1.4; }

/* hover 抬起：参数 1:1 取自主站团队卡 .ft-card（home.css:547）——
   scale3d(1.01) + 阴影第二层加深，box-shadow .2s / transform .3s cubic-bezier(0,0,.5,1)。
   ⚠️ 只在真有指针的设备上生效（@media hover），触屏上 :hover 会粘住不放。 */
@media (hover: hover) and (pointer: fine) {
  .v3-quote:hover,
  .v3-split-logo:hover {
    box-shadow:
      0 0 0 1px rgba(0, 0, 0, 0.08),
      0 16px 36px -12px rgba(0, 0, 0, 0.12);
    transform: scale3d(1.01, 1.01, 1.01);
  }
}

/* 说话人的头像：放在名字前面，让引言有张脸 */
.v3-quote-face {
  width: 22px; height: 22px;
  flex: none;
  border-radius: 999px;
  object-fit: cover;
  background: #f5f5f7; /* design-ok: 头像加载前的占位底，非分区填充 */
}

/* 样例候选人卡 */
.v3-cand-list { display: flex; flex-direction: column; gap: 12px; }
.v3-cand {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 16px;
  border-radius: 16px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 8px 24px -12px rgba(0, 0, 0, 0.06);
}
.v3-cand-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; flex: none;
  border-radius: 999px;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #86868b; font-size: 14px;
}
.v3-cand-main { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.v3-cand-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.v3-cand-name { color: #1d1d1f; font-size: 14px; }
.v3-cand-tier { color: #86868b; font-size: 12.5px; }
.v3-cand-summary { margin: 0; color: #86868b; font-size: 13px; line-height: 1.5; }
/* 联系方式锁定态：让「解锁」这件事在 onboarding 里第一次被看见 */
.v3-cand-locked {
  display: inline-flex; align-items: center; gap: 6px;
  color: #a1a1a6; font-size: 12.5px;
}
.v3-cand-locked svg { flex: none; }

/* 「这是样例」的标注 —— 做成 chip 而不是一句说明：这句话被略过的代价是用户以为
   我们已经为他找到了人，是本页最不能出错的一处。品牌蓝描边属 §3 的非文本用途。 */
.v3-sample-note {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0;
  height: 26px; padding: 0 10px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(46, 132, 250, 0.35);
  color: #2e84fa; font-size: 12.5px; line-height: 1;
  white-space: nowrap;
}

/* 进行时状态（微信步右栏） */
.v3-working { display: flex; align-items: center; gap: 10px; }
.v3-working-dot {
  position: relative; flex: none;
  width: 8px; height: 8px; border-radius: 999px; background: #2e84fa;
}
.v3-working-dot::after {
  content: ""; position: absolute; inset: 0;
  border-radius: 999px; background: #2e84fa;
  /* 只动 transform/opacity，reduced-motion 下关闭。 */
  /* design-ok: 自动播放的等待指示，同 spinner */
  animation: v3-pulse 1.8s ease-out infinite;
}
@keyframes v3-pulse {
  0% { opacity: .5; transform: scale(1); }
  100% { opacity: 0; transform: scale(2.6); }
}
.v3-working-text { color: #1d1d1f; font-size: 14px; line-height: 1.5; min-width: 0; }

/* 额度说明 */
.v3-quota { margin: 0; color: #86868b; font-size: 13px; line-height: 1.6; }
.v3-quota b { color: #1d1d1f; font-weight: 500; }

/* JD 步右栏的 tab（申请问题 / 会看到谁） */
.v3-tabs { display: flex; gap: 8px; margin-bottom: 20px; }
.v3-tab {
  appearance: none; font: inherit;
  height: 30px; padding: 0 12px;
  border: 0; border-radius: 999px;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #86868b; font-size: 13px; line-height: 1;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, box-shadow 150ms ease;
}
.v3-tab:hover { color: #1d1d1f; }
.v3-tab.is-on { background: #1d1d1f; box-shadow: none; color: #ffffff; }

/* 标题 + 那句副标题是一对，不能被 .v3-panel 的 32 gap 拆开，所以单独包一层。 */
.v3-panel-head { display: flex; flex-direction: column; gap: 6px; }
.v3-panel-head .v3-panel-title { margin-bottom: 0; }

/* 申请问题（静态展示，形态照 me-form-primitives 的既有控件） */
.v3-q { display: flex; flex-direction: column; gap: 12px; }
/* 「添加」跟着列表走同一条 12 的节奏，不另起一块 —— 它是这张清单的最后一行，
   不是一个独立分区（§1）。不画卡片边界：有框就成了「第四道题」，而它是动作。 */
.v3-q-add {
  appearance: none;
  font: inherit;
  display: inline-flex;
  align-items: center;
  align-self: start;
  gap: 6px;
  height: 32px;
  /* 负左边距把自己的内距抵掉：加号要落在标题和卡片边界那条内容线上（886），
     不然它夹在内容线和卡内文字线中间，跟谁都不对齐。hover 底色往左溢 10px 没关系。 */
  margin-left: -10px;
  padding: 0 12px 0 10px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: #6e6e73;
  font-size: 13px;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}
/* design-ok: §1 允许的 hover 临时态 */
.v3-q-add:hover { background: #f5f5f7; color: #1d1d1f; }
.v3-q-add:active { transform: scale(0.97); }
.v3-q-add svg { flex: none; }
.v3-q-item {
  padding: 14px 16px;
  border-radius: 14px;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #1d1d1f; font-size: 13.5px; line-height: 1.5;
}
.v3-q-item span { display: block; margin-top: 4px; color: #86868b; font-size: 12.5px; }

/* 微信上传区（照抄 me-editors.css 的 .me-onboarding-weixin 结构，只补原型专属状态） */
.v3-weixin-preview {
  display: block;
  width: 216px; height: 236px;
  object-fit: cover;
  border-radius: 12px;
}

/* ── 完成页：照 Chatbase analyzing 页的结构与动效 ── */
.v3-ready {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 32px;
  min-height: 100vh;
  padding: 56px 24px;
  text-align: center;
}

/* 标志方块：进场落位后持续轻微呼吸。
   原版是旋转，但那里转的是抽象标记；挥手图标转起来会很怪，改成 scale 呼吸。
   持续动画不受 §5.2 的 300ms 约束（那条管的是「用户点完在等」）。 */
.v3-ready-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: 16px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  overflow: hidden;
  background: #ffffff;
  border: 1px solid rgba(0, 0, 0, 0.04);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 8px 24px -12px rgba(0, 0, 0, 0.06);
  animation:
    v3-ready-in 300ms cubic-bezier(0.2, 0, 0, 1) both,
    /* design-ok: 持续的加载指示，同 spinner 那一类 */
    v3-ready-breathe 2400ms ease-in-out 300ms infinite;
}
.v3-ready-mark img { width: 100%; height: 100%; object-fit: cover; }
.v3-ready-initial { color: #86868b; font-size: 24px; font-weight: 500; }

@keyframes v3-ready-in {
  from { opacity: 0; transform: translateY(8px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes v3-ready-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.05); }
}

/* 进场动效（带 blur）现在挂在状态行上，见 .v3-ready-status */
@keyframes v3-ready-title-in {
  from { opacity: 0; transform: translateY(10px); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

/* 团队 logo 内联在句子里（原版把客户站点的 favicon 嵌在标题中间） */
.v3-ready-brand {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin: 0 4px;
  vertical-align: middle;
  border-radius: 8px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  overflow: hidden;
  background: #f5f5f7; /* design-ok: 头像占位底，非分区填充 */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #86868b;
  font-size: 14px;
  font-weight: 500;
}
.v3-ready-brand img { width: 100%; height: 100%; object-fit: cover; }

/* 进行时状态：文字扫光（原版同款 background-clip:text + 光带横移）。
   原版是深色底用浅色光带，这里白底反过来 —— 底色是副墨色，光带压到近黑。 */
/* 这一行现在是这一屏唯一的文字，字号接过原来大标题那一档（28/600/-0.03em）。
   扫光落在大字上比落在 15px 的说明文字上明显得多。 */
.v3-ready-status {
  margin: 0;
  font-size: 28px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.03em;
  white-space: nowrap;
  /* 进场跟原标题一致（含 blur），只是现在挂在状态行上 */
  animation-delay: 80ms;
  background-image: linear-gradient(
    90deg,
    rgba(29, 29, 31, 0) 0%,
    rgba(29, 29, 31, 0.04) 18%,
    rgba(29, 29, 31, 0.18) 32%,
    rgba(29, 29, 31, 0.55) 42%,
    rgba(29, 29, 31, 1) 50%,
    rgba(29, 29, 31, 0.55) 58%,
    rgba(29, 29, 31, 0.18) 68%,
    rgba(29, 29, 31, 0.04) 82%,
    rgba(29, 29, 31, 0) 100%
  ), linear-gradient(90deg, #c7c7cc, #c7c7cc);
  background-size: 60% 100%, 100% 100%;
  background-repeat: no-repeat;
  background-position: -60% 0, 0 0;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  /* 两条动画并列：进场播一次（带 blur，同原标题），扫光持续跑。
     design-ok: 扫光是持续的加载指示，linear（§5.1：持续运动不加缓动，否则会周期性顿一下） */
  animation:
    v3-ready-title-in 300ms cubic-bezier(0.2, 0, 0, 1) 80ms both,
    v3-ready-shimmer 1800ms linear infinite;
}
@keyframes v3-ready-shimmer {
  from { background-position: -60% 0, 0 0; }
  to   { background-position: 160% 0, 0 0; }
}

.v3-done-actions { margin-top: 8px; }

@media (prefers-reduced-motion: reduce) {
  .v3-ready-mark { animation: none; opacity: 1; transform: none; }
  /* 扫光停掉后要给回实色，否则文字停在 transparent 上看不见 */
  .v3-ready-status {
    animation: none;
    background-image: none;
    -webkit-text-fill-color: #86868b;
  }
}

/* ══════════════════════════════════════════════════════════════════
   ③b 满屏两列（左表单裸放，右信任面板）—— 建团 / 微信 / 通知三步共用
   试过品牌蓝铺满右半屏（Chatbase 那种 splash），已按 §1「页面一律纯白、禁整块
   底色填充」退回白底：左右分界靠列间距和右列自己的卡片边界，不靠底色。
   顺带解决了蓝底白色小字对比度不达 AA 的问题，不必再记一笔欠账。
   ══════════════════════════════════════════════════════════════════ */

/* 分屏时解除 shell 的内距与宽度上限，让右列能铺到屏幕边缘 */
/* （满屏解锁已上移到文件开头的 :has() 段，这里不再用 body.is-split） */
/* 分屏几步：整页不滚，滚动只发生在两列各自内部。
   ⚠️ 只在分屏时锁 —— 职位步是常规文档流，锁了它就滚不动了；
   ≤900px 塌成单列后也要解锁（见下方媒体查询）。 */
/* 锁整页滚动同上，见文件开头 body:has(.v3-split) */
/* 全局顶栏让位：分屏模式下它改在左列内部渲染，否则会横跨蓝区 */

.v3-split {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  width: 100%;
  /* height 而不是 min-height：行高钉死在一屏，右列内容再多也只在自己那一列里滚，
     不会把 grid 行撑高、连带把左列也拉长（左列的重心必须稳定在一屏正中）。 */
  height: 100vh;
  /* ⚠️ column-gap 必须是 0：竖线画在正中（50%），而 gap 会**平分**在竖线两侧，
     叠上两列各自的 padding 后就不对称了 ——
     曾经是「左列 padding-right 56 + gap 一半 36 = 92」对「右列 padding-left 0 + 36 = 36」。
     间距全部交给两列自己的 padding，左右各 56，竖线两侧才等宽。 */
  column-gap: 0;
}

/* ⚠️ 分栏竖线：Vincent 在原型评审时明确要求加。
   这一条**违反 bonjour-ui §1**（分割线做分组是禁用手段，唯一例外是表达层级的吸顶线），
   规范解法是加大列间距而不是画线。保留在原型里是为了看实际效果；进生产前需要复核，
   要么撤掉、要么在 SKILL.md 里为「满屏分栏」补一条例外。
   颜色取 §1 例外档的 #ececef，位置压在两列正中（1fr 1fr 等宽，交界即 50%）。 */
/* design-ok: 用户明确要求的分栏竖线，破例理由见上方注释 */
.v3-split::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: #ececef;
  /* 只向右投一层很浅的阴影：读起来是「左列这块板浮在上面，右列在它后面」。
     0.04 的黑 + 16px 扩散 —— 再重就变成两块拼接的界面，不是层次。 */
  box-shadow: 3px 0 16px -2px rgba(0, 0, 0, 0.04);
  pointer-events: none;
}
.v3-split[hidden] { display: none; }

/* 左列：内容块（表单 + 按钮）在这一列里水平垂直都居中，两列各自成一个干净的容器。
   表单直接躺在白底上，不套卡片（少一层容器边界，§2 的容器只留给右列的卡）。 */
.v3-split-left {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* ⚠️ 不做垂直居中：各步内容高矮差很多（建团一整张表 vs 规模四个按钮），
     居中会让标题在每一步落在不同高度，翻页时标题上下跳。改成从固定顶距起排，
     所有步的标题落在同一条水平线上。 */
  justify-content: flex-start;
  gap: 36px;
  min-width: 0;
  /* 底部 200 而不是 56：① 底下钉着 .v3-split-foot（absolute），要给它留出位置，
     否则内容多的步骤会滚到按钮底下去；② 居中算的是这个内距区间，底部留得比顶部多，
     表单块的重心就往上提（200 比按钮实际占的 160 再多 40，是刻意的上提量）。 */
  padding: 56px 56px 200px;
  /* 矮屏兜底：内容顶不下时这一列自己滚，不影响右列。滚动条同样藏掉。 */
  overflow-y: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.v3-split-left::-webkit-scrollbar { width: 0; height: 0; display: none; }
/* 步骤条 / 返回键是导航，不参与居中 —— 脱离文档流钉在这一列的左上角，
   否则它会把居中的重心往下压。 */
.v3-split-head {
  position: absolute;
  top: 40px;
  left: 56px;
  right: 56px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
/* 团队切换器紧贴返回键成一组（都是「离开这一步」的出口），步骤条留在最右。
   ⚠️ auto 边距而不是改 justify-content：space-between 下三个子项会把切换器甩到正中间，
   看起来像它自己是一档内容。auto 吃掉全部余量 → 前两个成组、第三个贴右缘。 */
.v3-split-head > .me-shell-team {
  margin-right: auto;
  /* 侧栏那套的外边距在这一排是多余的：这里靠 flex gap 定间距。 */
  padding: 0;
  margin-bottom: 0;
  margin-left: -8px; /* 抵掉 gap:20 的一半，让它读起来是返回键的「隔壁」而不是另一组 */
}
.v3-split-head .me-shell-team-avatarrow {
  margin-bottom: 0;
}
/* 与 .ov-back.me-page-flow-back 同为 36 的圆形命中区，两颗并排才是一排。 */
.v3-split-head .me-shell-team-avatar {
  width: 36px;
  height: 36px;
  border-radius: 999px;
}
.v3-split-body {
  flex: none;
  display: flex;
  flex-direction: column;
  /* 36：标题组到表单第一个控件的距离。32 时副标题和输入框贴得太近，
     读起来像 label 挂在框上，而不是「一段说明 + 一个独立控件」。 */
  gap: 36px;
  width: 100%;
  max-width: 520px;
  /* 每一步的标题都从这条线开始（左列 padding-top 56 + 这里 72 = 128）。
     head 是 absolute 不占位，所以 body 就是流里的第一个元素。 */
  margin-top: 72px;
}
/* 主操作钉在这一列的底部，和顶部的进度点对称 —— 每一步的主按钮都落在同一个位置，
   用户的视线和鼠标不用跟着内容长短上下找。
   ⚠️ 脱离文档流后必须给 .v3-split-left 留出底部内距，否则内容多的步骤会压到按钮上。 */
/* 翻页动效：新的一步淡入 + 轻微上移。280ms 落在 §5.2 的「弹窗 / 抽屉 / 视图切换」档，
   曲线走进场的 ease-out（§5.1 决策树）。
   ⚠️ 只在 ≥901px 播：窄屏塌成单列后这一列的高度由内容决定（建团那步能到 900+），
   给这么高的容器加 transform 就逼近 §5.4 那条 iOS 内存红线；窄屏翻页不带动效没有损失。 */
@keyframes v3-pane-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
/* design-ok: 900 断点的 min-width 配对，非新增断点 */
@media (min-width: 901px) {
  .v3-split-left.is-entering {
    /* 300 = §5.2「弹窗 / 抽屉 / 视图切换」这一档的上限，也是全局硬上限。
       整列切换属于「元素越大越慢」那条调整规则里最大的一档，所以取满。
       再慢就越线了 —— 那条线的成因是「用户点完在等」，不是审美偏好。 */
    animation: v3-pane-in 300ms cubic-bezier(0.2, 0, 0, 1) both;
  }
}

/* ⚠️ 主按钮在每一步都必须落在同一条线上。
   如果整个 foot 按 bottom 对齐，带副按钮的那步（融资有「先跳过」）会把主按钮顶高，
   翻页时按钮上下跳。所以：主按钮自己按 bottom 定位，副内容（跳过 / 协议）绝对定位
   浮在它下方，不参与高度计算。 */
.v3-split-foot {
  position: absolute;
  bottom: 96px;
  left: 56px;
  right: 56px;
  max-width: 520px;
  margin-inline: auto;
}
/* .ct-submit 是 inline 的 span —— 不转成块级，foot 量不到按钮的真实高度，
   下面那条 top:100% 就会落错位置。 */
.v3-split-foot > .ct-submit { display: block; }
/* 融资步骤没有报道时仍允许直接继续，但主动作先降一档；添加至少一条后恢复品牌主按钮。 */
.v3-funding-next.is-empty {
  background: #f5f5f7;
  color: #2e84fa;
}
/* 主按钮之后的一切（协议说明、跳过）挂到按钮下方的固定位置，不参与 foot 的高度，
   这样带副内容的步骤不会把主按钮顶高。
   ⚠️ 用 .v3-foot-note 而不是 :not(.ct-submit)：后者写起来省事，但一旦 foot 里多出
   任何辅助节点就会被一起绝对定位，出问题时很难看出是这条在作怪。 */
.v3-foot-note {
  position: absolute;
  top: calc(100% + 16px);
  left: 0;
  right: 0;
  margin: 0;
  text-align: center;
}

/* 右列：内容整体垂直居中，与左列的重心对齐。
   ⚠️ 内容比左列多，笔记本屏（900 高）放不下 —— 必须能滚，否则底部直接被切掉。
   滚动条藏起来：它会在两列之间多画一条纵向硬线（同 .jdPanel / .tib-*-scroll 的处理）。 */
.v3-split-right {
  display: flex;
  flex-direction: column;
  /* ⚠️ safe 不能省：内容一超高，纯 center 会把顶部（数字组、评价卡）推到滚动起点之外，
     打开就直接看到 logo 墙中段，上面那截根本滚不回去。
     safe center = 放得下就居中，放不下就退回顶端对齐。 */
  justify-content: safe center;
  /* 组间距：这是右列两个大区（数字 / 说好）之间，必须明显大于区内的任何间距，
     否则两区会读成一整块（§1）。96 是区内最大值（块间 36）的 2.7 倍，分组关系一眼可辨。
     ⚠️ 代价同顶边距 —— logo 墙吃的是剩余空间，这里每加一档，墙就少半行。 */
  gap: 96px;
  min-width: 0;
  /* 上 120（间距阶梯最大那档）：这一列从顶部铺下来，留出大片顶边让数字组"落"在屏中上部，
     不贴屏幕边。下边留 56，上重下轻。
     左 56 与左列的 padding-right 对齐 —— 竖线两侧等宽（见 .v3-split 的 column-gap 注释）。
     ⚠️ 顶边距和 logo 墙此消彼长 —— 墙吃的是这一列的剩余空间，120 之后大约只剩 3 行半。 */
  padding: 120px 56px 56px 56px;
  overflow-y: auto;
  /* ⚠️ x 轴必须显式收掉：CSS 规定一轴设成 auto 时，另一轴的 visible 会被强制算成 auto ——
     只写 overflow-y 会连带让 x 轴可滚。而这一列里有两个**故意**向右出血到视口边缘的
     东西（评价轮播露出的下一张卡、Newsroom 的灰底块），于是整列能左右拖，拖出来是
     一条 16px 的空白。
     写 clip 是因为它语义更准（不产生滚动盒），但按 CSS Overflow 3，clip 与另一轴的
     auto 同时出现时**计算值会退化成 hidden** —— 实测 getComputedStyle 拿到的就是
     hidden。这没关系：hidden 一样禁止用户滚动，只是脚本仍能改 scrollLeft。
     两者在这里等价，留 clip 是为了表达意图。 */
  overflow-x: clip;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.v3-split-right::-webkit-scrollbar { width: 0; height: 0; display: none; }
.v3-split-right .v3-quote-text { font-size: 15px; }

/* ⚠️ logo 墙自己滚，是为了让**右列整体能居中**：60 家铺开有 1200+ px，
   直接堆在右列里会把整列撑到比屏幕高，那时「垂直居中」和「顶部内容能滚到」
   就成了互斥的两件事（safe center 只能退回顶端对齐）。
   把墙收成一个定高滚动区之后，右列总高回到一屏内，居中才成立。 */
/* ⚠️ 这一块里的四段（标题 / 评价卡 / logo 墙 / 脚注）分属三个层级，
   不能用一个 gap 统一 —— 那会把「块之间」压成和「标题到正文」一样紧，
   读起来就是一堆挤在一起的东西（§1 分组靠留白，前提是留白得分档）。
     标题 → 正文    24
     评价区 → logo 墙 36（两种不同内容，块间）
     logo 墙 → 脚注  12（脚注是附属说明，贴紧它解释的东西） */
/* ⚠️ flex:none 是必须的，原来那行 min-height:0 才是「滚到底没有底边距」的真凶：
   这一块是右列（滚动容器）的最后一个 flex 子项，默认 flex-shrink:1；min-height:0
   恰好解除了「flex 列子项不小于内容高」的保护，于是它被压扁（实测真实高 1628 被压成
   407），内容整个溢出到 item 外面。溢出的部分虽然还能滚到，但脚注的 margin-bottom
   和容器的 padding-bottom 都是按 item 的盒子算的 —— 全部不计入滚动区，滚到底就正好
   停在脚注底边上。改成不压缩之后这 96+56 才真的存在（scrollHeight 1969 → 2121）。 */
.v3-wall-block {
  display: flex;
  flex-direction: column;
  flex: none;
  gap: 0;
}
.v3-wall-block .v3-panel-title { margin-bottom: 24px; }
.v3-wall-block .v3-footnote { margin: 12px 0 0; }
/* 收尾留白挂在「本列最后一块」上，而不是写死给某个元素 —— 它表达的是「滚到底了」，
   Newsroom 加进来之后就该跟着走。原来写在脚注的 margin-bottom 上，脚注一旦不再是
   最后一个，就变成了块间的双倍间距（96 margin + 96 列 gap）。
   64 + 容器自己的 padding-bottom 56 = 120，和这一列的顶边距 120 对称。 */
.v3-split-right > :last-child { padding-bottom: 64px; }
/* Newsroom：横向卡（封面 + 标题 + 日期）。列宽只有 350 出头，封面做成顶部大图
   三张叠起来会把整列拉得很长，横向排列既能露出封面又保持清单的密度。
   ⚠️ 同 .v3-wall-block：这也是滚动容器的 flex 子项，必须 flex:none，
   否则又会被压扁、内容溢出到 item 外面（那正是「滚到底没有底边距」的成因）。 */
/* 灰底分区（同 Apple Newsroom 的 #f5f5f7，实测取自它 .in-the-loop-gallery 的
   computed background）：上面是白的「你们」，这里换底色说明「换了个话题」。
   这是本文件里唯一一处用底色分区 —— §1 的「不用底色分组」管的是同一块内容里的
   小分区，跨版块换底是另一回事，Apple / Linear 的落地页都这么切。
   ⚠️ 三个方向都要负边距顶掉容器内距：灰必须一直铺到视口右缘和滚动终点，
   边上留一条白边就穿帮了。左边不铺到 0 是因为那儿是两列之间的分割线。
   ⚠️ padding-bottom 要自己写满 120（见下面那条）：它的 margin-bottom 已经把容器的
   padding-bottom 56 顶掉了，不能再套用通用的「最后一块 64 + 容器 56」那套算法。 */
.v3-news-block {
  display: flex;
  flex-direction: column;
  flex: none;
  /* 交界线上下必须等距，否则那条线看着是歪的。-48 吃掉列 gap 96 的一半 →
     线上留 48 白，线下再给 48 灰，线正好落在中间。
     总量仍是 96，和这一列其它块间距一致 —— 换底色不该顺带把间距也翻倍。 */
  margin: -48px -56px -56px;
  padding-top: 48px;
  padding-inline: 56px;
  background: #f5f5f7;
}
/* 双写类名把特异性抬到 (0,3,0)，压过通用的 `.v3-split-right > :last-child`(0,2,0)。
   两条同为 (0,2,0) 时只能靠行号定胜负 —— 那种写法一挪位置就静默失效
   （仓库里 .saveBar.saveBar 用的是同一个手法）。
   120 = 这一列的顶边距，滚到底和滚到顶留白一样多。 */
.v3-split-right > .v3-news-block.v3-news-block { padding-bottom: 120px; }
/* Newsroom 卡片走 Apple Newsroom 的形态：图和文各占一块，文字落在白底上而不是
   压在图上。⚠️ 这不是审美偏好 —— 蒙版压字要成立，前提是封面下半部足够暗且可控；
   我们的封面是各家团队自己传的（厨房大白光、手机屏反光都有），压字随时会糊。
   白底把可读性从「这张图碰巧够暗」变成结构保证。
   头条横排（图左文右）+ 下面两张竖排（图上文下），层级靠版式而不是字号堆叠。 */
/* 头条和下面那排之间 20（12 拉开约 50%，取阶梯上最近的一档）；
   ⚠️ 只拉纵向。并排两张之间仍是 12 —— 那两张要读成「一排」，横向一旦跟纵向等宽，
   四张卡就散成一片没有行的网格了。 */
.v3-news-list { display: flex; flex-direction: column; gap: 20px; }
.v3-news-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }

/* 不画描边：这一块换成灰底之后，白色卡面本身就是边界了，再描一圈是把同一条界线
   画两遍（§2 一档就够）。这也是 Apple 的做法 —— 它的 tile 在灰底上同样没有描边。
   ⚠️ 这条只在灰底里成立。同一列上面那些卡（logo 墙、申请问题）站在白底上，
   没有描边就没有边界，那边的 inset 1px 不能跟着删。 */
.v3-news {
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  border-radius: 18px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  text-decoration: none;
  transition:
    box-shadow .2s cubic-bezier(.2, 0, 0, 1),
    transform .3s cubic-bezier(0, 0, .5, 1);
}
/* design-ok: §2 可点击卡片的标准 hover，与 .v3-split-logo / .v3-quote 同参数 */
.v3-news:hover {
  transform: translateY(-1px);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.03),
    0 8px 24px -12px rgba(0, 0, 0, 0.06);
}

.v3-news-media { position: relative; overflow: hidden; }
.v3-news-cover {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #ececec; /* design-ok: 图未加载时的占位底，不是 §1 的分区填充 */
}

.v3-news-desc {
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: space-between;
  gap: 14px;
  min-width: 0;
  padding: 16px;
}
.v3-news-head { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* Apple 那行是分类（PRESS RELEASE / UPDATE）。我们没有对应的分类字段，就用文章
   实际的作者/来源 —— 宁可少一层信息，也不为了版式好看编一个分类出来。
   uppercase 对中文是空操作，将来来源是中文也不会变形。 */
.v3-news-eyebrow {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: #6e6e73;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.v3-news-title {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  overflow-wrap: anywhere;
  color: #1d1d1f;
  font-weight: 600;
  letter-spacing: -0.015em;
}
.v3-news-time {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  color: #6e6e73;
  font-size: 12.5px;
}
.v3-news-time svg { flex: none; }

/* 头条：图左文右。55% 给图 —— 再窄图就只剩一条，再宽标题会被挤成四行。 */
.v3-news--hero { flex-direction: row; }
.v3-news--hero .v3-news-media { flex: 0 0 55%; align-self: stretch; }
.v3-news--hero .v3-news-desc { padding: 20px; }
.v3-news--hero .v3-news-title { font-size: 19px; line-height: 1.35; }

/* 下面两张：图上文下，16:10 —— 生产封面多是横构图，16:9 会把人物切头 */
.v3-news-row .v3-news-media { aspect-ratio: 16 / 10; }
.v3-news-row .v3-news-title { font-size: 14.5px; line-height: 1.45; }

/* 评价卡和它的进度点是一组，内部间距自己管 */
.v3-quote-group { flex: none; margin-bottom: 36px; }

/* logo 墙：三列，每格是「图标 + 团队名」的一块。
   白底上用 inset 描边表达边界，不用底色（§1）。 */
/* ⚠️ 这里一度把墙收成「定高 + 内部滚动」，为的是让右列还能垂直居中。已回退：
   页面里嵌一个小滚动窗很难用，也看不出下面还有多少家。
   现在 60 家全平铺，滚动交给右列本身 —— 代价是内容超过一屏后右列不再垂直居中
   （safe center 退回顶端对齐），内容比容器高时这两件事本来就互斥。 */
.v3-split-logos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
/* ⚠️ 行数上限**不在这里**：改成由组件切数组（[[OnboardingV3TrustPanel]] 的
   WALL_MAX_ROWS），CSS 不再裁。之前用 max-height + overflow:hidden 裁切，既要拿
   padding/负 margin 把被切掉的卡片阴影救回来，又和组件里算「还有 N 家」的行数常量
   对不上（CSS 裁 6 行、常量写 3 行）。行数只能有一个真相源。 */
/* 展开/收起做成一颗真按钮，而不是「点整面墙」—— 墙上每一格看着都像能点进团队主页，
   把整面墙变成开关，等于给 60 个看起来是链接的东西挂了一个完全不相干的动作。 */
.v3-split-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  height: 52px;
  padding: 0 12px;
  border-radius: 14px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #1d1d1f;
  font-size: 13px;
  line-height: 1.2;
  transition:
    box-shadow .2s cubic-bezier(.2, 0, 0, 1),
    transform .3s cubic-bezier(0, 0, .5, 1);
}
.v3-split-logo img {
  width: 22px; height: 22px;
  flex: none;
  border-radius: 6px;
  object-fit: cover;
}
/* 团队名长短差很多，一律单行截断；完整名在 title 里 */
.v3-split-logo span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 分屏下的表单：输入框铺满左列可用宽度 */
.v3-split .self-serve-team-form { gap: 32px; }
/* 「或手动填入」这道分隔上下的呼吸位：36 → 44（按评审要求 +25%）。
   ⚠️ 44 不在 §3 的间距阶梯上（36 的下一档是 56，那是 +55%、过头了）——
   这是一处按指定比例取的值，不是阶梯内的标准档。 */
.v3-split .self-serve-team-form-body { gap: 44px; }

/* ── 官网链接输入（结构照搬 Chatbase：前缀段 + 输入 + 帮助区包在一个沉底容器里）──
   ⚠️ 这里的浅灰底**违反 bonjour-ui §1**（灰底填充禁用，§1 只放行 hover 临时态和
   markdown code 块）。Vincent 在原型评审时明确要求照搬该组件。同分栏竖线、OR 分隔线，
   进生产前需要一起复核：要么改成纯白 + 描边，要么在 SKILL.md 里补一条控件内部的例外。 */
/* design-ok: 用户明确要求照搬的输入组件，破例理由见上方注释 */
.v3-url-field { display: flex; flex-direction: column; gap: 8px; }
.v3-url-label { color: #1d1d1f; font-size: 14px; font-weight: 500; line-height: 1.4; }
.v3-url-box {
  border-radius: 12px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #f7f7f8;
  overflow: hidden;
}
.v3-url-row { display: flex; align-items: stretch; }
.v3-url-prefix {
  display: inline-flex;
  align-items: center;
  flex: none;
  padding: 0 12px;
  border: 1px solid #e6e6e8;
  border-right: 0;
  border-radius: 10px 0 0 10px;
  background: #f0f0f2;
  color: #86868b;
  font-size: 14px;
}
.v3-url-input {
  flex: 1;
  min-width: 0;
  height: 42px;
  padding: 0 12px;
  border: 1px solid #e6e6e8;
  border-radius: 0 10px 10px 0;
  background: #ffffff;
  color: #1d1d1f;
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.v3-url-input::placeholder { color: #a1a1a6; }
.v3-url-input:focus {
  border-color: #2e84fa;
  box-shadow: 0 0 0 3px rgba(46, 132, 250, 0.12);
}
.v3-url-input.is-err { border-color: #e5484d; }
/* 没有前缀件作伴时补回左侧那两个圆角 —— 基类的 `0 10px 10px 0` 是按「左边贴着
   前缀件」算的，独用时左上左下会是直角。 */
.v3-url-input--solo { border-radius: 10px; }
.v3-url-hint {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 0;
  padding: 6px 12px 8px;
  color: #86868b;
  font-size: 12px;
  line-height: 1.45;
}
.v3-url-hint svg { flex: none; margin-top: 1px; }

/* 「或手动填入」的居中分隔线。
   ⚠️ SKILL.md §1 把 divider 作为分组手段禁用了，这里是**明确破例**：
   Vincent 2026-08-17 在两种形态之间选定了这一种。破例只落在开户 V3 的团队步 ——
   V1 / V2 的建团页仍是纯文字标题（见 SelfServeTeamCreateForm 的 framedLink 分叉）。
   不要把这条当先例推广到别处，别处照旧用留白分组。
   用伪元素画线而不是 border-top/bottom：文字要压在线中间，两侧各一段。 */
/* design-ok: 开户 V3 团队步的「或手动填入」分隔线，用户明确拍板破 §1，范围限本处 */
.v3-manual-sep {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
}
/* design-ok: 同上 —— 这两段就是那条线本身 */
.v3-manual-sep::before,
.v3-manual-sep::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #ececef;
}
.v3-manual-sep-text {
  flex: none;
  color: #86868b;
  font-size: 13px;
  line-height: 1.4;
}

/* 微信这一步的标题跟着内容居中：这一屏的主体（上传框、路径指引）本来就是居中的，
   标题再左对齐会和下面整块错开。其余几步的主体是左对齐的表单，保持左对齐。 */
.v3-split-left[data-step="weixin"] .v3-lead { text-align: center; }
.v3-split-left[data-step="weixin"] .v3-lead-sub { margin-inline: auto; }

/* 路径指引：生产里它包在 .me-onboarding-weixin-state--card 内（那层负责居中）。
   这里把它移到了两态之外好让空态也能看见，居中就得自己补 ——
   它本身是 inline-flex，套一层块级居中即可。 */
.me-onboarding-weixin-where {
  display: flex;
  justify-content: center;
  margin-top: 16px;
}

/* 空态的微信图标：40 → 32（小两号），灰改墨色。
   ⚠️ 生产用 currentColor 从 .me-onboarding-weixin-placeholder 继承 #a1a1a6，
   这里显式覆盖，不动那个共享类。 */
.v3-split .me-onboarding-weixin-empty-icon {
  width: 32px;
  height: 32px;
  /* 50% 墨色：空态图标是「这里放什么」的示意，不该跟下面那行操作文案抢重量 */
  color: rgba(29, 29, 31, 0.5);
}
/* 生产是 400；这里提到 500 —— 它是这块空态里唯一的操作指令，
   §3 允许用字重表达「角色」（这是动作，不是说明）。 */
.v3-split .me-onboarding-weixin-empty-action {
  font-weight: 500;
}

/* ── 融资报告：贴进来的链接清单 ── */
.v3-link-list { display: flex; flex-direction: column; gap: 8px; margin: 0; padding: 0; list-style: none; }
.v3-link-item {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  padding: 12px 12px 12px 14px;
  border-radius: 12px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
}
.v3-link-host { flex: none; color: #1d1d1f; font-size: 13.5px; }
/* 完整 URL 退到副墨色：域名已经说明是哪家报道了，路径只是佐证 */
.v3-link-url {
  flex: 1;
  min-width: 0;
  color: #a1a1a6;
  font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.v3-link-del {
  appearance: none; border: 0; background: none;
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 24px; height: 24px;
  border-radius: 999px;
  color: #a1a1a6;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease;
}
.v3-link-del:hover { background: #f5f5f5; color: #1d1d1f; } /* design-ok: §1 允许的 hover 临时态 */

/* ── 融资报告：上传区 ── */
.v3-upload { display: flex; flex-direction: column; gap: 12px; }
.v3-upload-trigger {
  appearance: none;
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  padding: 32px 20px;
  border: 0;
  border-radius: 16px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  /* 虚线描边表达「这里还是空的、等你放东西进来」，同 me-chip-toggle--rec 的用法 */
  box-shadow: inset 0 0 0 1px #e6e6e8;
  color: #86868b;
  cursor: pointer;
  transition: box-shadow 150ms ease, color 150ms ease;
}
.v3-upload-trigger:hover { box-shadow: inset 0 0 0 1px #d2d2d7; color: #1d1d1f; }
.v3-upload-title { color: #1d1d1f; font-size: 14px; font-weight: 500; }
.v3-upload-hint { font-size: 12.5px; }
.v3-upload-picked {
  margin: 0;
  color: #1d1d1f;
  font-size: 13px;
  line-height: 1.5;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ── 团队规模：单选 ── */
.v3-size-group { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.v3-size-opt {
  appearance: none;
  font: inherit;
  height: 56px;
  padding: 0 16px;
  border: 0;
  border-radius: 14px;
  -webkit-corner-shape: squircle;
  corner-shape: squircle;
  background: #ffffff;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);
  color: #1d1d1f;
  font-size: 14px;
  cursor: pointer;
  transition: box-shadow 150ms ease, color 150ms ease;
}
.v3-size-opt:hover { box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.16); }
/* 选中用品牌蓝描边 + 蓝字，不用实底 —— 实底会让这一屏出现四个色块在互相竞争 */
.v3-size-opt.is-on {
  box-shadow: inset 0 0 0 1.5px #2e84fa;
  color: #2e84fa;
}
.v3-field-err { margin: 0; color: #b91c1c; font-size: 13px; line-height: 1.4; }

/* 次要出口：不跟主按钮抢重量（同 JD 步的「跳过」） */
.v3-skip-link {
  appearance: none; border: 0; background: none;
  padding: 0;
  color: #86868b;
  font: inherit; font-size: 13px;
  cursor: pointer;
  transition: color 150ms ease;
}
.v3-skip-link:hover { color: #1d1d1f; }

/* 页面主标题（照 Chatbase 的比重：大标题 + 一句副文案） */
.v3-lead { display: flex; flex-direction: column; gap: 4px; }
.v3-lead-title {
  margin: 0;
  color: #1d1d1f;
  /* 28 不在间距阶梯里，但那是间距的阶梯；字号按 type ramp 走，28/600 是这一档的显示标题 */
  font-size: 28px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.03em;
}
.v3-lead-sub {
  margin: 0;
  max-width: 65ch;
  /* 与大标题里被压暗的那半句同一个值（50% 墨色），标题和副标题读成一组 */
  color: rgba(29, 29, 31, 0.5);
  font-size: 15px;
  line-height: 1.5;
}

/* ⚠️ 「或手动填入」两侧的横线：Vincent 在原型评审时明确要求（照 Chatbase 的 OR 分隔）。
   这**违反 bonjour-ui §1**（分割线做分组是禁用手段）。同分栏竖线，进生产前需要复核。
   颜色取 §1 例外档的 #ececef。 */
/* design-ok: 用户明确要求的 OR 分隔线，破例理由见上方注释 */
.v3-or { display: flex; align-items: center; gap: 12px; }
.v3-or-line { height: 1px; flex: 1; background: #ececef; }
.v3-or-text {
  margin: 0;
  flex: none;
  color: #86868b;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
}

@media (max-width: 1312px) {
  .v3-split-left { padding: 40px; }
  .v3-split-head { top: 40px; left: 40px; right: 40px; }
  /* 窄一档的屏通常也更矮，顶边跟着收到 72，别把内容区挤没了。
     左内距同样与左列 padding 对齐，保持竖线两侧等宽。 */
  .v3-split-right { padding: 72px 40px 40px 40px; gap: 64px; }
  /* 跟着上面的 padding-right 收到 40 */
  .v3-quote-viewport { margin: -20px -40px -20px -24px; }
}

/* 900 以下右列整体让位（同其余步骤：窄屏空间留给表单） */
@media (max-width: 900px) {
  /* 单列下高度交还给内容，滚动交还给页面本身 —— 桌面那套「各列自己滚」
     在单列里会变成「一屏之内的小滚动窗」，很难用。 */
  .v3-split { grid-template-columns: minmax(0, 1fr); height: auto; }
  .v3-split-left { overflow: visible; }
  /* 单列下滚动交还给页面，桌面那把锁必须解开 */
  body:has(.v3-split) { overflow: visible; }
  /* 右列都没了，那条竖线会变成一道悬在内容右边的孤线 */
  .v3-split::before { display: none; }
  .v3-split-right { display: none; }
  /* 单列下不再垂直居中：内容比屏幕高时居中会把顶部顶出视口。
     步骤条也回到正常文档流。 */
  .v3-split-left {
    justify-content: flex-start;
    gap: 28px;
    padding: 20px 20px 40px;
  }
  /* 回到文档流后要显式贴左：外层的 align-items:center 会把它一起居中，
     而进度指示属于导航，居中会读成标题 */
  .v3-split-head { position: static; align-self: flex-start; }
  /* ⚠️ foot 也必须跟着回到文档流：桌面版它是 absolute + bottom:56（钉在一屏底部），
     单列下这一列的高度由内容决定，那个定位就落到内容区里、直接压在表单上。
     漏改这一条就是「主按钮盖住输入框」那个移动端 bug。
     width:100% 同样不能省 —— 左列是 align-items:center 的 flex 列，交叉轴就是水平方向，
     回到文档流的 foot 会被收缩成按钮内容那么宽（实测缩成一个小胶囊）。 */
  .v3-split-foot { position: static; width: 100%; }
  /* 副文案跟着回流：它的 absolute 基准是左列（唯一 positioned 的祖先），
     单列下 top:100% 会算到整列底部之外，协议那行被甩出去老远。 */
  .v3-foot-note { position: static; margin-top: 16px; }
  .v3-split-body, .v3-split-foot { max-width: none; }
}

/* ══════════════════════════════════════════════════════════════════
   ④ 响应式：≤900px 右栏整体让位（与生产开户页一致 —— 窄屏空间留给表单）
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  /* 只给 V3 自己收掉 shell 的横向 padding。这里曾经写成裸 `.me-shell-main`，
     因为本文件在 me-shell.css 之后加载，结果把普通 /team-manage 页原有的 16px
     移动端左右留白也覆盖成 0，卡片和列表直接贴到视口边缘。 */
  .me-shell-main:has(.v3-root),
  .me-shell-main:has(.v3-split) { padding: 20px 0 120px; }
  .v3-root { gap: 28px; padding-bottom: calc(108px + env(safe-area-inset-bottom)); }
  .v3-stage { display: flex; flex-direction: column; gap: 32px; }
  .v3-form-col { width: 100%; }
  .v3-visual { display: none; }
  .v3-step-label { display: none; }
  .v3-savebar.me-savebar {
    position: fixed; right: 16px; left: 16px;
    width: auto; max-width: none; margin: 0;
  }

  /* ── 方案 B：JD 步在窄屏铺成两屏（jd / questions）──────────────────
     上面那条 `.v3-visual { display:none }` 是给开户四步用的：右栏是纯装饰面板，
     窄屏让位没有损失。但 JD 步的右栏是**申请问题**，是这版 onboarding「让人看懂
     这套东西值什么」的载体 —— 直接藏掉等于这块白做，堆到 JD 面板下面也不行：
     savebar 是钉底的，用户可以从头到尾没滚到问题区就点了发布。所以拆页。
     (0,3,0) 压过上面的 (0,1,0)。 */
  [data-step="job"][data-subpage="questions"] .v3-form-col { display: none; }
  /* ⚠️ width:100% 不能省 —— 单列下 .v3-stage 是 flex 列，交叉轴是水平方向，
     而 .v3-visual 带 align-self:start，回到文档流会被收缩成内容宽（实测题卡只有
     160px 宽）。跟 .v3-split-foot 那条注释是同一个坑。 */
  [data-step="job"][data-subpage="questions"] .v3-visual {
    display: block;
    align-self: stretch;
    width: 100%;
  }
  /* 「候选人投递前必答」这时已经升格成页标题（见 JOB_HEAD），面板里不再念第二遍 */
  [data-step="job"][data-subpage="questions"] .v3-panel-head { display: none; }

  /* 窄屏放弃「面板固定高 + 正文内滚」：触屏上嵌套滚动很难用（手指往上划，到底
     谁在滚说不清）。拆页之后编辑器可以独占整页高、跟着整页滚，反而更顺。 */
  [data-step="job"] .v3-form-col { align-self: auto; }
  [data-step="job"] .v3-jd-panel { height: auto; }
  .v3-jd-editor .me-tip-body { min-height: 260px; overflow-y: visible; }
}

@media (max-width: 720px) {
  .v3-root { padding-inline: 20px; }
  .me-stepdots { gap: 12px; }
  .v3-form-card { padding: 32px 20px 24px; }
  .v3-jd-panel { padding: 24px 20px 36px; border-radius: 24px; }
  .v3-role-input.me-input { font-size: 23px; }
  .v3-hint { display: none; }
  .v3-err { white-space: normal; }
  .v3-savebar.me-savebar { min-height: 58px; padding: 8px 9px 8px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  /* 扫光是纯装饰，关掉后回落成纯墨色 —— 别让文字停在透明填充上变成看不见 */
  .v3-shine,
  .v3-anim.v3-shine {
    animation: none;
    background-image: none;
    -webkit-text-fill-color: #1d1d1f;
  }
  /* 入场动画同样关掉，但必须让元素停在最终态（both 会把它冻在起始的 opacity:0） */
  .v3-anim { animation: none; opacity: 1; transform: none; }
  .v3-split-left.is-entering { animation: none; }
  .v3-split-logo { animation: none; }
  .v3-quote-track { transition: none; }
  .v3-working-dot::after { animation: none; }
  .v3-chip:active { transform: none; }
}

/* ══════════════════════════════════════════════════════════════════
   ⑤ 生产接线：把原型里几个自绘控件的形态，套到复用的生产组件上
      （原型是静态 HTML 自己画的；生产用现成组件，只能从外面给形态）
   ══════════════════════════════════════════════════════════════════ */

/* 融资步：输入框 + 提示装进 .v3-url-box 灰底控件；已解析卡片是它下方的独立控件。
   两部分仍在同一个 PressLinkEditor 内，只在开户 V3 作用域改皮，团队资料页保持原样。 */
.v3-split-left[data-step="funding"] .me-press {
  gap: 16px;
  padding: 0;
  background: none;
}
.v3-split-left[data-step="funding"] .v3-url-box {
  border-radius: 12px 12px 16px 16px;
}
.v3-split-left[data-step="funding"] .v3-url-box .bm-up-input {
  display: block;
  width: 100%;
  height: 42px;
  padding: 0 12px;
  border: 1px solid #e6e6e8;
  border-radius: 10px;
  background: #ffffff;
  color: #1d1d1f;
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.v3-split-left[data-step="funding"] .v3-url-box .bm-up-input:focus {
  border-color: #2e84fa;
  box-shadow: 0 0 0 3px rgba(46, 132, 250, 0.12);
}
/* 卡片组已在灰底输入控件之外；组内每张卡的样式继续走 bm-link-card 基类。 */
.v3-split-left[data-step="funding"] .me-press > .bm-up-cards { margin: 0; }

/* 桌面融资步只让报道卡片滚动：标题和输入框留在原位，列表视口的底边停在主按钮
   上方 16px。把 foot 放回 flex 流里后，16px 由左列 gap 直接表达，不依赖按钮高度；
   96px 底内距继续容纳按钮下方的「先跳过」。这条只收 funding；其它内容可能更长的步骤
   仍沿用左列自己的矮屏滚动兜底。 */
/* design-ok: 901 与现有 900px 单列断点配对，不是新增断点 */
@media (min-width: 901px) {
  .v3-split-left[data-step="funding"] {
    gap: 16px;
    padding-bottom: 96px;
    overflow: hidden;
  }
  .v3-split-left[data-step="funding"] .v3-split-body {
    flex: 1 1 0;
    min-height: 0;
    overflow: hidden;
  }
  .v3-split-left[data-step="funding"] .v3-split-foot {
    position: relative;
    inset: auto;
    flex: none;
    width: 100%;
  }
  .v3-split-left[data-step="funding"] .me-press {
    flex: 1 1 0;
    min-height: 0;
    overflow: hidden;
  }
  .v3-split-left[data-step="funding"] .v3-url-box {
    flex: none;
  }
  .v3-split-left[data-step="funding"] .me-press > .bm-up-cards {
    flex: 1 1 0;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior-y: contain;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .v3-split-left[data-step="funding"] .me-press > .bm-up-cards::-webkit-scrollbar {
    width: 0;
    height: 0;
    display: none;
  }
  .v3-split-left[data-step="funding"] .me-press > .bm-up-cards > .bm-link-card {
    flex: none;
  }
}

/* 团队步：SelfServeTeamCreateForm 自带 `.self-serve-team-footer`（提交按钮 + 那句
   「创建代表你同意…」），内容与其余几步的 `.v3-split-foot` 逐字相同。所以**不重写一份**，
   直接把它钉到同一个位置 —— 四步的主按钮必须落在同一条水平线上，否则翻页时按钮会跳。
   ⚠️ 只在 [data-step="team"] 作用域内生效：这个表单在 /create-team 之外还有别的用法
   （V1/V2 的建团页、团队资料编辑），那些地方它就该跟着内容走。 */
.v3-split-left[data-step="team"] .self-serve-team-footer {
  position: absolute;
  bottom: 96px;
  left: 56px;
  right: 56px;
  max-width: 520px;
  margin-inline: auto;
}
/* 表单主体不再需要为自己的 footer 留位（footer 已脱离文档流） */
.v3-split-left[data-step="team"] .self-serve-team-form { display: contents; }

@media (max-width: 900px) {
  /* 单列下同 .v3-split-foot：回到文档流，否则会绝对定位压在表单上（先例见 §4 那段注释）。
     width:100% 不能省 —— 左列是 align-items:center 的 flex 列，交叉轴是水平方向，
     回流后的 footer 会被收缩成按钮内容那么宽。 */
  .v3-split-left[data-step="team"] .self-serve-team-footer {
    position: static;
    left: auto;
    right: auto;
    width: 100%;
    max-width: none;
  }
}
/* 表单自带的「从链接快速创建 / 修改」分组标题：V3 已经把它上移成页面副标题
   （见 OnboardingV3TeamStep），留着就是同一句话在同屏说两遍（SKILL.md §7 删除审查）。
   ⚠️ 只收视觉不删节点：它是 aria 结构的一部分，用 v3-sr 那套「视觉隐藏但读屏可读」
   的写法，读屏用户仍然拿得到分组名。 */
.v3-split-left[data-step="team"] .self-serve-team-link-title {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* 品牌标做成链接：只加指针和一点点 hover 反馈，不加底色/边框 —— 它在页头是个标识，
   不是按钮，画出按钮的样子会让人以为点了会在流程里前进。
   .v3-brand 自己带 width/height（那个 svg 没有固有尺寸），这里只管交互态。 */
.v3-brand-home {
  display: inline-flex;
  flex: none;
  border-radius: 8px;
  /* design-ok: §1 允许的 hover 临时态 */
  transition: opacity 150ms ease;
}
.v3-brand-home:hover { opacity: 0.7; }
