/* ==========================================================================
   廖博文 · 个人网站
   浅色、克制。唯一的强调色只用在“这条线”上：流动的光、当前位置和“现在”。
   ========================================================================== */

/* 中文里的引号、破折号、省略号、间隔号交给系统中文字体，不让它们落到西文字体里显得又窄又短 */
@font-face {
  font-family: "CJK Punct";
  src: url("data:font/woff2;base64,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") format("woff2");
  font-weight: 400;
  unicode-range: U+00B7, U+2014, U+2018-201D, U+2026;
}

@font-face {
  font-family: "CJK Punct";
  src: url("data:font/woff2;base64,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") format("woff2");
  font-weight: 600;
  unicode-range: U+00B7, U+2014, U+2018-201D, U+2026;
}

/* 标题用思源黑体 SemiBold，只裁出标题里用到的字（tools/font-work）。
   直接内嵌成 data URL：双击 index.html（file://）打开时，浏览器会拦截单独的字体文件请求。
   原文件在 assets/fonts/title-sc-600.woff2；换字后用 tools/inline-font.py 重新内嵌 */
@font-face {
  font-family: "BW Title SC";
  src: url("data:font/woff2;base64,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") format("woff2");
  font-weight: 600;
  font-display: swap;
}

:root {
  --animation-time: 1; /* 全局动作保持原始 1 倍；内容作用域单独派生 */
  --bg: #fbfbfd;
  --bg-2: #f3f3f6;
  --ink: #1d1d1f;
  --ink-2: #3d3d42;
  --mute: #6e6e73;
  --mute-2: #8e8e93;
  --line: #d2d2d7;
  --hair: rgba(0, 0, 0, 0.08);
  --accent: #e8571f;
  --accent-ink: #b5410f;
  --accent-soft: rgba(232, 87, 31, 0.13);

  --out: cubic-bezier(0.16, 1, 0.3, 1);
  --inout: cubic-bezier(0.65, 0, 0.35, 1);

  --font: "CJK Punct", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei UI", "Microsoft YaHei", system-ui, sans-serif;
  --font-display: "CJK Punct", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Display", "Segoe UI", "PingFang SC",
    "BW Title SC", "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei UI", "Microsoft YaHei", system-ui, sans-serif;

  --tb-h: 3.5rem;
  --gutter: clamp(1.25rem, 4.2vw, 4rem);
  --maxw: 78rem;
}

/* 大屏按档位放大：每一档都有上限，内容收在中间，不随屏幕无限变大。
   同时看宽和高，矮而宽的窗口不会被放大到首屏放不下。 */
@media (min-width: 1680px) and (min-height: 880px) {
  html { font-size: 106.25%; }
}
@media (min-width: 2200px) and (min-height: 1080px) {
  html { font-size: 118.75%; }
}
@media (min-width: 2800px) and (min-height: 1350px) {
  html { font-size: 137.5%; }
}
@media (min-width: 3400px) and (min-height: 1650px) {
  html { font-size: 150%; }
}

/* 非手机画面共用居中的内容框。正文、Logo、作品图和间距都随 rem
   一起适配宽高，至少保留两侧各 12% 的空白；大屏沿用 78rem 上限。
   自然滚动的窄/矮窗口仍保留阅读字号，手机继续使用原有布局。 */
html.m-wide {
  font-size: clamp(13px, min(0.8vw, 1.5svh), 24px);
  --maxw: min(78rem, 76vw);
  --gutter: max(12vw, calc((100vw - var(--maxw)) / 2));
}

.m-wide .chapters {
  width: min(30rem, calc(var(--maxw) * 0.38));
}

@media (min-width: 768px) {
  html.m-tall { --gutter: 12vw; }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--bg);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

img {
  display: block;
  max-width: none;
  -webkit-user-drag: none;
  user-select: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, p, ul, ol, dl, dd, figure {
  margin: 0;
}

ul, ol {
  padding: 0;
  list-style: none;
}

::selection {
  background: var(--accent-soft);
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 8px;
}

.nw {
  white-space: nowrap;
}

.wx-thumb {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

.skip {
  position: fixed;
  z-index: 100;
  left: 1rem;
  top: 0.5rem;
  padding: 0.6rem 1rem;
  border-radius: 0.5rem;
  background: var(--ink);
  color: #fff;
  font-size: 0.875rem;
  transform: translateY(-200%);
}

.skip:focus {
  transform: none;
}

/* ---------------------------------------------------------------- 顶栏：邮箱一直在 */

.topbar {
  position: fixed;
  z-index: 30;
  top: 0;
  left: 0;
  right: 0;
  height: var(--tb-h);
  background: rgba(251, 251, 253, 0.84);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  backdrop-filter: saturate(1.6) blur(14px);
  transition: box-shadow calc(0.3s * var(--animation-time));
}

.topbar.is-scrolled {
  box-shadow: 0 1px 0 var(--hair);
}

.tb-inner {
  width: min(calc(100% - var(--gutter) * 2), var(--maxw));
  height: 100%;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.tb-name {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-weight: 600;
  font-size: 0.9375rem;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  transition: opacity calc(0.3s * var(--animation-time)), transform calc(0.4s * var(--animation-time)) var(--out);
}

.topbar.is-scrolled .tb-name {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.tb-en {
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--mute);
}

.tb-mail {
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

.tb-addr {
  font-size: 0.9375rem;
  color: var(--ink-2);
  padding: 0.4rem 0.5rem;
  border-radius: 0.5rem;
  font-variant-numeric: tabular-nums;
  transition: color calc(0.2s * var(--animation-time));
}

.tb-copy {
  position: relative;
  height: 2rem;
  padding: 0 0.75rem 0 1.8rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  color: var(--ink-2);
  background: var(--bg-2);
  transition: background calc(0.2s * var(--animation-time)), color calc(0.2s * var(--animation-time));
}

/* 复制图标：两张叠着的纸 */
.tb-copy::before,
.tb-copy::after {
  content: "";
  position: absolute;
  width: 0.5rem;
  height: 0.6rem;
  border: 1.4px solid currentColor;
  border-radius: 2px;
}

.tb-copy::before {
  left: 0.72rem;
  top: calc(50% - 0.42rem);
}

.tb-copy::after {
  left: 0.92rem;
  top: calc(50% - 0.22rem);
  background: var(--bg-2);
}

.tb-copy.is-done span {
  font-size: 0;
}

.tb-copy.is-done span::after {
  content: "已复制";
  font-size: 0.8125rem;
}

@media (hover: hover) {
  .tb-addr:hover { color: var(--accent-ink); }
  .tb-copy:hover { background: #e8e8ed; }
}

/* ---------------------------------------------------------------- 舞台 */

.journey {
  position: relative;
  height: 700vh;
}

.stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.js .stage {
  opacity: 0;
}

.js.is-ready .stage {
  opacity: 1;
  transition: opacity calc(0.5s * var(--animation-time)) ease;
}

.viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.world {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  transform-origin: 0 0;
  --tk: 1;
}

/* ---------------------------------------------------------------- 线 */

.w-svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 1px;
  height: 1px;
  overflow: visible;
  pointer-events: none;
}

.w-svg path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.l-main {
  stroke: var(--ink);
  stroke-width: 3.6;
  transition: stroke calc(0.5s * var(--animation-time)) var(--out);
}

/* 凯度的四条项目线：比主线细，颜色同主线，读起来是“从凯度长出来的” */
.l-strand {
  stroke: var(--ink);
  stroke-width: 2.2;
  transition: stroke calc(0.4s * var(--animation-time)) var(--out), stroke-width calc(0.4s * var(--animation-time)) var(--out), opacity calc(0.4s * var(--animation-time)) var(--out);
}

.l-enroll {
  stroke: #b9b9bf;
  stroke-width: 3;
  stroke-dasharray: 0.1 11;
  opacity: 0;
  transition: opacity calc(0.8s * var(--animation-time)) calc(0.4s * var(--animation-time));
}

.l-future {
  stroke: url(#gFuture);
  stroke-width: 3.6;
  stroke-dasharray: 0.1 13;
  opacity: 0;
  transition: opacity calc(0.8s * var(--animation-time)) calc(0.6s * var(--animation-time));
}

.world.is-in .l-enroll,
.world.is-in .l-future {
  opacity: 1;
}

/* 悬停或讲到某一站时，节点附近的线亮起来：线下面铺一层暖色的光 */
.l-hi {
  stroke: var(--accent);
  stroke-width: 12;
  opacity: 0;
  transition: opacity calc(0.3s * var(--animation-time)) var(--out);
}

.l-hi--strand {
  stroke-width: 8;
}

.l-hi.is-on {
  opacity: 0.2;
}

/* 流光：柔光、光身、亮头三层，头部对齐 */
.fx {
  pointer-events: none;
}

.fx-glow {
  stroke: var(--accent);
  stroke-width: 13;
  opacity: 0.09;
}

.fx-body {
  stroke: var(--accent);
  stroke-width: 3.8;
  opacity: 0.42;
}

.fx-head {
  stroke: #ff7c3f;
  stroke-width: 4.4;
  opacity: 0.95;
}

/* 项目线上的光细一点，和线的粗细相配 */
.fx-strand.fx-body { stroke-width: 2.4; }
.fx-strand.fx-head { stroke-width: 2.8; }

.fx-speck {
  fill: var(--accent);
  opacity: 0.45;
}

/* 选中项目时顺着线落下去的光：讲凯度时也是亮的，不跟着环境的流光一起变淡；
   这条线本身随后变成强调色，所以光头用近白色，在橙色的线上也看得出来 */
.world .fx-shot.fx-glow { stroke: var(--accent); stroke-width: 12; opacity: 0.28; }
.world .fx-shot.fx-body { stroke: #ff9a66; stroke-width: 3.2; opacity: 0.95; }
.world .fx-shot.fx-head { stroke: #fff4ec; stroke-width: 3; opacity: 1; }

/* 整条线连成的路径：只用来量长度、取点，不画出来 */
.w-svg .l-route {
  stroke: none;
}

/* 全景里指针靠近线：线在指针附近亮起来一小段 */
.l-near {
  stroke: var(--accent);
  stroke-width: 3.8;
  opacity: 0;
}

.l-near--head {
  stroke: #ff7c3f;
  stroke-width: 4.4;
}

.l-near--glow {
  stroke-width: 16;
}

/* 阅读光标：跟着滚动沿线走到正在讲的那一站 */
.g-cur {
  opacity: 0;
}

.cur-dot {
  fill: #ff7c3f;
}

.cur-halo {
  fill: var(--accent);
  opacity: 0.16;
}

.cur-t {
  visibility: hidden;
}

.cur-t--glow {
  stroke: var(--accent);
  stroke-width: 14;
  opacity: 0.12;
}

.cur-t--body {
  stroke: var(--accent);
  stroke-width: 4;
  opacity: 0.85;
}

.cur-t--head {
  stroke: #ff7c3f;
  stroke-width: 5;
  opacity: 0.95;
}

/* 行标题：读书 / 工作 */
.rowhead {
  position: absolute;
  transform: translate(-100%, -50%);
  font-size: calc(19px * var(--tk));
  font-weight: 500;
  letter-spacing: 0.32em;
  color: var(--mute-2);
  white-space: nowrap;
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time));
}

/* ---------------------------------------------------------------- 站点 */

.st {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  transition: opacity calc(0.5s * var(--animation-time)) var(--out), filter calc(0.45s * var(--animation-time)) var(--out);
}

.st.is-in {
  opacity: 1;
}

.st-dot {
  position: absolute;
  left: -12px;
  top: -12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--bg);
  border: 4px solid var(--ink);
  transition: transform calc(0.5s * var(--animation-time)) var(--out), box-shadow calc(0.4s * var(--animation-time));
}

/* 节点轻微的明暗起伏 */
.st-dot::before {
  content: "";
  position: absolute;
  inset: -12px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  animation: breathe calc(7s * var(--animation-time)) ease-in-out infinite;
  animation-delay: calc((var(--i, 0) * -1.15s) * var(--animation-time));
}

@keyframes breathe {
  0%, 100% { opacity: 0; transform: scale(0.7); }
  50% { opacity: 0.09; transform: scale(1); }
}

.st--edu .st-dot {
  border-color: #8e8e93;
}

.st--now .st-dot {
  background: var(--accent);
  border-color: var(--accent);
}

.st--now .st-dot::after {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  animation: pulse calc(2.8s * var(--animation-time)) var(--out) infinite;
}

@keyframes pulse {
  0% { transform: scale(1); opacity: 0.55; }
  70%, 100% { transform: scale(2.8); opacity: 0; }
}

/* 光标落到这一站、或点一下节点：泛起一圈 */
.ping {
  position: absolute;
  left: -12px;
  top: -12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  opacity: 0;
  pointer-events: none;
}

.is-ping > .ping {
  animation: ping calc(1.2s * var(--animation-time)) var(--out);
}

@keyframes ping {
  0% { transform: scale(1); opacity: 0.75; }
  100% { transform: scale(3.6); opacity: 0; }
}

.st.is-hi .st-dot,
.st.is-focus .st-dot {
  transform: scale(1.2);
  box-shadow: 0 0 0 8px var(--accent-soft);
}

.st-body {
  position: absolute;
  left: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 6px 12px;
  white-space: nowrap;
  text-align: center;
  border-radius: 14px;
}

.st--work .st-body {
  top: 24px;
}

.st--edu .st-body {
  bottom: 24px;
  flex-direction: column-reverse;
}

.st-logo {
  height: 70px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.st-logo img,
.pr-logo img {
  transition: filter calc(0.6s * var(--animation-time)) var(--out), opacity calc(0.6s * var(--animation-time)) var(--out), transform calc(0.6s * var(--animation-time)) var(--out);
}

.st-lbl {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.st-name {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: calc(30px * var(--tk));
  line-height: 1.25;
  transition: color calc(0.3s * var(--animation-time));
}

.st-ind {
  font-family: var(--font);
  font-weight: 500;
  font-size: calc(21px * var(--tk));
  color: var(--mute);
  padding-left: 10px;
  border-left: 2px solid var(--line);
  line-height: 1.1;
}

.st-now {
  font-family: var(--font);
  font-style: normal;
  font-weight: 600;
  font-size: calc(17px * var(--tk));
  line-height: 1.5;
  color: var(--accent-ink);
  background: var(--accent-soft);
  padding: 1px 8px;
  border-radius: 6px;
}

.st-time {
  font-size: calc(22px * var(--tk));
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

/* ESCP 的排名放在 logo 右边 */
.st-side {
  position: absolute;
  top: -65px;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding-left: 16px;
  border-left: 2px solid var(--line);
  white-space: nowrap;
  /* 两行的总高不超过 logo 那一档（70），不会碰到上面的时间 */
  font-size: calc(17px * var(--tk));
  color: var(--mute);
  line-height: 1.25;
}

/* “FT 欧洲商学院 第 4 · 2025” */
.st-side b {
  font-weight: 600;
  color: var(--ink);
  margin-left: 7px;
}

.st-side i {
  font-style: normal;
  color: var(--mute-2);
}

.st-side i::before {
  content: "·";
  margin: 0 6px;
}

/* 凯度：站名靠在项目线束的左边，右对齐，和右边四行项目夹着线束排成一组 */
.st--kantar .st-body {
  left: auto;
  right: 24px;
  transform: none;
  align-items: flex-end;
  text-align: right;
}

.st--kantar .st-lbl {
  align-items: flex-end;
}

@media (hover: hover) {
  .st-body:hover .st-name { color: var(--accent-ink); }
}

/* ---------------------------------------------------------------- 凯度：线束末端的四行项目 */

.pr {
  position: absolute;
  white-space: nowrap;
  /* 这一块的外框比看得见的内容大（藏着的正文也占位）：只让看得见的部分接住鼠标，不挡 IDC 等站 */
  pointer-events: none;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity calc(0.6s * var(--animation-time)) var(--out), transform calc(0.7s * var(--animation-time)) var(--out), filter calc(0.45s * var(--animation-time)) var(--out);
}

.pr.is-in {
  opacity: 1;
  transform: none;
}

.pr-head {
  position: relative;
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: calc(12px * var(--tk));
  padding: calc(4px * var(--tk)) calc(10px * var(--tk)) calc(4px * var(--tk)) 0;
  border-radius: calc(10px * var(--tk));
  font-size: calc(24px * var(--tk));
  line-height: 1.3;
  text-align: left;
}

.pr-logo {
  flex: none;
  width: calc(58px * var(--tk));
  display: flex;
  align-items: center;
  justify-content: center;
}

.pr-name {
  font-weight: 500;
  color: var(--ink-2);
  transition: color calc(0.3s * var(--animation-time));
}

.world[data-focus="kantar"] .pr-name {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
}

/* 项目题目和时间：全景里不出现，讲凯度时才显出来。
   全景里把它们移出排版（不撑大这一行），悬停时题目接在名字后面出现 */
.pr-title {
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time)) var(--out);
}

.world:not([data-focus="kantar"]):not(.is-measure) .pr-title {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  visibility: hidden;
}

.world.has-pj .pr.is-hi .pr-title {
  visibility: visible;
}

.pr-title {
  font-size: calc(20px * var(--tk));
  font-weight: 500;
  color: var(--ink-2);
}

.world[data-focus="kantar"] .pr-title {
  opacity: 1;
}

/* 紧凑窗口讲凯度：线旁边的“KANTAR”让出位置（左边章节标题已经写明这是凯度），
   节点和线束留着；全景里（看整条线）照旧显示 */
.world.is-cramped[data-focus="kantar"] .st--kantar .st-body {
  opacity: 0;
  visibility: hidden;
}

/* 讲凯度时：选中的那一行和它的线是强调色，其余三行退半步 */
.world[data-focus="kantar"].has-project .pr:not(.is-sel) .pr-name {
  color: var(--ink-2);
}

.world[data-focus="kantar"].has-project .pr:not(.is-sel) .pr-title {
  color: var(--mute);
}

/* 四个客户入口持续可读；焦点或悬停只加强对应名称和线。 */
.world[data-focus="kantar"].has-hi .pr.is-in:not(.is-hi) { opacity: 1; }

.world[data-focus="kantar"] .l-strand.is-sel {
  stroke: var(--accent);
  stroke-width: 2.6;
  /* 等落下去的那束光先走一段，线再跟着变色 */
  transition: stroke calc(0.6s * var(--animation-time)) var(--out) calc(0.25s * var(--animation-time)), stroke-width calc(0.4s * var(--animation-time)) var(--out) calc(0.25s * var(--animation-time));
}

.world[data-focus="kantar"] .pr.is-sel .pr-name {
  color: var(--accent-ink);
}

.pr.is-hi .pr-name {
  color: var(--accent-ink);
}

/* 凯度到站：四束光落到四行时，四个项目名一起亮一下（四个项目同期并行） */
.world[data-focus="kantar"] .pr.is-flash .pr-name {
  color: var(--accent-ink);
  transition: color calc(0.12s * var(--animation-time));
}

/* 全景里悬停一行项目：这一行显出题目，凯度以外的站退后，让出位置 */
.world.has-pj .pr.is-hi .pr-title {
  opacity: 1;
}

/* 悬停任何一站或一个项目：没亮的退后一点，焦点更清楚 */
.world.has-hi .st.is-in:not(.is-hi) {
  opacity: 0.3;
}

.world.has-hi .pr.is-in:not(.is-hi) {
  opacity: 0.45;
}

/* 全景里悬停（站点、项目、首屏标签）：没亮的站轻微虚化，亮着的那一站 logo 微微浮起，像镜头对焦。
   只是轻微：退后的站名仍然认得出来 */
.world.has-hi:not(.is-chapter) .st.is-in:not(.is-hi) {
  opacity: 0.45;
  filter: blur(1.2px);
}

.world.has-hi:not(.is-chapter) .pr.is-in:not(.is-hi) {
  opacity: 0.5;
  filter: blur(1px);
}

.world.has-hi:not(.is-chapter) .st.is-hi .st-logo img {
  transform: translateY(-5px) scale(1.05);
}

@media (hover: hover) {
  .pr-head:hover .pr-name { color: var(--accent-ink); }
}

/* ---------------------------------------------------------------- 下一站：只在结尾出现 */

.nx {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
  /* 只是装饰：讲晶澳时它隐身停在三幕的标签上面，不能挡住点击 */
  pointer-events: none;
  transition: opacity calc(0.6s * var(--animation-time)) var(--out);
}

.world.is-outro .nx {
  opacity: 1;
}

.nx-ring {
  position: absolute;
  left: -12px;
  top: -12px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 3px dashed var(--accent);
  background: var(--bg);
}

.nx-ring::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
  transform: scale(0);
  transition: transform calc(0.6s * var(--animation-time)) var(--out);
}

.nx.is-lit .nx-ring::after {
  transform: scale(1);
}

.nx-lbl {
  position: absolute;
  top: 30px;
  left: 0;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  white-space: nowrap;
  gap: 2px;
}

.nx-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: calc(30px * var(--tk));
  color: var(--accent-ink);
}

.nx-line {
  font-size: calc(21px * var(--tk));
  color: var(--ink-2);
}

/* ---------------------------------------------------------------- 讲到某一站时才出现的说明图 */

.vx {
  position: absolute;
  margin: 0;
  pointer-events: none;
}

/* 多幕作品图（晶澳、拜耳）：三件事各演一幕。尺寸都用 em：宽屏 1em = 讲这一站时世界坐标里的 1rem（--wr），
   和左边正文一样大；手机按栏宽缩放。每一幕分三段演（p1 → p2 → p3），done 是演完。
   讲到哪一章，哪一章的图出现、可以点；没讲到的退隐 */
.vx-works {
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time));
}

.world[data-focus="jasolar"] .vx-works--jasolar,
.world[data-focus="bayer"] .vx-works--bayer {
  opacity: 1;
}

.vx-fig .jw {
  /* --jwf 由 fitFig 按这一章的镜头算好：在屏幕上是正文的 1.05–1.4 倍，图里的小字也能看清 */
  font-size: var(--jwf, 16px);
}

.world[data-focus="jasolar"] .vx-works--jasolar .jw-tab,
.world[data-focus="jasolar"] .vx-works--jasolar [data-k],
.world[data-focus="bayer"] .vx-works--bayer .jw-tab,
.world[data-focus="bayer"] .vx-works--bayer [data-k] {
  pointer-events: auto;
}

/* 晶澳镜头只显示 logo：透明站名和按钮空白区不能挡住下方三站时间线。 */
.world[data-focus="jasolar"] .st--jasolar .st-body {
  pointer-events: none;
}

.world[data-focus="jasolar"] .st--jasolar .st-logo {
  pointer-events: auto;
}

/* 拜耳镜头：拜耳的三幕压在凯度站名和 logo 上面（它们退成淡淡的背景），
   退后的站不再截获点击，点不到的三站时间线才是事 */
.world[data-focus="bayer"] .st--kantar .st-body {
  pointer-events: none;
}

.jw-fig,
.mv-works {
  margin: 0;
}

.jw {
  --animation-time: var(--content-time, 1);
  position: relative;
  width: 24em;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

.jw {
  display: grid;
}

/* 三幕的切换：一排可以切的标签。字下面一道细线；正在演的那一站是实心的强调色圆点，底下一段强调色实线
   （原来三站串在一根线上，看起来像进度条） */
.jw-tabs {
  position: relative;
  display: flex;
  gap: 1.9em;
  margin-bottom: 1.1em;
}

.jw-tabs::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.45em;
  height: 1px;
  background: linear-gradient(90deg, var(--line), var(--line) 70%, transparent);
}

.jw-tab {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin: 0;
  padding: 0 0.35em 0 0;
  border: 0;
  background: var(--bg);
  font: inherit;
  font-size: 0.8125em;
  font-weight: 600;
  line-height: 1.5;
  color: var(--mute);
  cursor: pointer;
  transition: color calc(0.25s * var(--animation-time));
}

.jw-tab i {
  width: 0.62em;
  height: 0.62em;
  box-sizing: border-box;
  border-radius: 50%;
  border: 1.5px solid #b4b4ba;
  background: var(--bg);
  transition: background calc(0.3s * var(--animation-time)), border-color calc(0.3s * var(--animation-time)), transform calc(0.3s * var(--animation-time)) var(--out);
}

.jw-tab:hover {
  color: var(--ink-2);
}

.jw-tab:hover i {
  border-color: var(--ink-2);
}

.jw-tab[aria-selected="true"] {
  color: var(--ink);
}

.jw-tab[aria-selected="true"] i {
  border-color: var(--accent);
  background: var(--accent);
  transform: scale(1.15);
}

.jw-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

/* 三幕叠在同一格里：整块的高度按最高的一幕算，切换时下面的内容不会跳；旧的一幕先退，新的一幕再进 */
.jw-sc {
  grid-area: 2 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity calc(0.12s * var(--animation-time)), visibility calc(0s * var(--animation-time)) calc(0.12s * var(--animation-time));
}

.jw-sc.is-cur {
  opacity: 1;
  visibility: visible;
  transition: opacity calc(0.3s * var(--animation-time)) calc(0.1s * var(--animation-time));
}

.jw-sc.is-reset,
.jw-sc.is-reset * {
  transition: none !important;
  animation: none !important;
}

.jw-stage {
  position: relative;
  height: 10em;
}

.jw-sc.is-fading .jw-stage { opacity: 0.2; transition: opacity calc(0.45s * var(--animation-time)) linear; }

.jw-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.jw-svg * {
  vector-effect: non-scaling-stroke;
}

.jw-lab {
  position: absolute;
  white-space: nowrap;
  font-size: 0.75em;
  line-height: 1.2;
  color: var(--mute);
  transform: translateY(-50%);
  transition: opacity calc(0.4s * var(--animation-time)) var(--out), color calc(0.25s * var(--animation-time));
}

.jw-lab--mid {
  transform: translate(-50%, -50%);
  text-align: center;
}

.jw-lab--end {
  transform: translate(-100%, -50%);
}

.jw-lab--two {
  transform: translate(-50%, 0);
}

.jw-lab--two b,
.jw-lab--two i {
  display: block;
  font-style: normal;
}

.jw-lab b {
  font-weight: 600;
  color: var(--ink);
}

/* 底下一行：这一幕的三段。演到哪一段，那一段是强调色；上面一道细线跟着走。
   固定三栏：放不下时每段在自己那栏里折行，不会把第三段单独挤到下一行 */
.jw-steps {
  position: relative;
  display: grid;
  grid-template-columns: auto 1.1em auto 1.1em auto;
  justify-content: start;
  align-items: center;
  gap: 0 0.7em;
  margin: 0.9em 0 0;
  padding-top: 0.6em;
  border-top: 1px solid var(--hair);
  font-size: 0.8125em;
  line-height: 1.4;
  color: var(--mute-2);
}

.jw-st {
  transition: color calc(0.3s * var(--animation-time));
}

.jw-arr {
  width: 1.1em;
  height: 1px;
  background: var(--line);
}

.jw-prog {
  position: absolute;
  left: 0;
  right: 0;
  top: -1px;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

.jw-sc.p1 .jw-prog { transform: scaleX(0.3); transition: transform calc(var(--pd) * var(--animation-time)) linear; }
.jw-sc.p2 .jw-prog { transform: scaleX(0.65); transition: transform calc(var(--pd) * var(--animation-time)) linear; }
.jw-sc.p3 .jw-prog { transform: scaleX(1); transition: transform calc(var(--pd) * var(--animation-time)) linear; }
.jw-sc.done .jw-prog { opacity: 0.35; transition: opacity calc(0.6s * var(--animation-time)); }

.jw-sc.p1 .s0,
.jw-sc.p2 .s1,
.jw-sc.p3 .s2 { color: var(--accent-ink); }
.jw-sc.p2 .s0,
.jw-sc.p3 .s1,
.jw-sc.done .s0,
.jw-sc.done .s1 { color: var(--ink-2); }

/* 流程图标签由逐帧绘制控制，不叠加通用过渡。 */
.jw-flow .jw-lab { transition: none; }

/* ---- 第一幕 网站 */
.js-win { fill: none; stroke: #a1a1a6; stroke-width: 1.2; }
.js-line { fill: none; stroke: var(--line); stroke-width: 1; }
.js-tl { fill: #d2d2d7; }
.js-url { fill: var(--bg-2); }

.js-win,
.js-line,
.js-tl,
.js-url,
.js-mail,
.jw-site .jw-lab--mute,
.jw-site .jw-lab--url {
  opacity: 0;
  transition: opacity calc(0.35s * var(--animation-time));
}

.jw-site.p1 .js-win,
.jw-site.p1 .js-line,
.jw-site.p1 .js-tl,
.jw-site.p1 .js-url,
.jw-site.p1 .js-mail,
.jw-site.p1 .jw-lab--mute,
.jw-site.p1 .jw-lab--url { opacity: 1; }

.jw-lab--url { font-size: 0.625em; transform: translate(-50%, -50%); color: var(--mute); }

/* 蓝图：每一块先是虚线框；AI 走到哪块，哪块做实 */
.js-bp {
  fill: none;
  stroke: #b4b4ba;
  stroke-width: 0.055;
  stroke-dasharray: 0.12 0.09;
  vector-effect: none;
  opacity: 0;
  transition: opacity calc(0.3s * var(--animation-time));
}

.js-el:nth-child(odd) .js-bp { transition-delay: calc(0.08s * var(--animation-time)); }
.jw-site.p1 .js-bp { opacity: 1; }
.jw-site.p2 .js-bp { opacity: 0; transition: opacity calc(0.2s * var(--animation-time)) calc(var(--d) * var(--animation-time)); }

.js-so {
  opacity: 0;
  transition: opacity calc(0.25s * var(--animation-time)) calc(var(--d) * var(--animation-time));
}

.jw-site.p2 .js-so { opacity: 1; }

.js-bar { fill: #c9c9ce; }
.js-el:first-child .js-bar { fill: var(--ink-2); }
.js-box { fill: #fff; stroke: var(--line); stroke-width: 1; }
.js-btn { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 1.2; }
.js-head { fill: var(--bg-2); }
.js-rowline { fill: var(--line); }
.js-cell { fill: #c9c9ce; }

.jw-lab--btn {
  font-size: 0.6875em;
  font-weight: 600;
  color: var(--accent-ink);
  transform: translate(-50%, -50%);
  opacity: 0;
}

.jw-site.p2 .jw-lab--btn { opacity: 1; transition-delay: calc(0.85s * var(--animation-time)); }

.js-agent {
  opacity: 0;
}

.js-agent circle {
  fill: var(--accent);
  stroke: rgba(232, 87, 31, 0.22);
  stroke-width: 6;
}

.js-agent text {
  font-size: 0.42px;
  font-weight: 700;
  fill: var(--accent-ink);
  letter-spacing: 0.02px;
}

/* 互查：两个 AI 交换到对方那一半时出现，之后留着 */
.js-x {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.1;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.js-x,
.jw-lab--x {
  opacity: 0;
  transition: opacity calc(0.35s * var(--animation-time));
}

.jw-site.p2 .js-x,
.jw-site.p2 .jw-lab--x { opacity: 1; transition-delay: calc(0.95s * var(--animation-time)); }
.jw-lab--x { font-size: 0.6875em; color: var(--accent-ink); }

.js-app {
  fill: var(--accent);
  stroke: rgba(232, 87, 31, 0.25);
  stroke-width: 7;
  opacity: 0;
}

.js-trail {
  fill: none;
  stroke: var(--accent);
  stroke-width: 0.07;
  stroke-dasharray: 0.01 0.2;
  vector-effect: none;
  stroke-linecap: round;
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time));
}

.jw-site.p3 .js-trail { opacity: 0.55; }

/* 新的一份投递：后台已有的几行往下让一格，新的一行落在最上面 */
.js-el--row { transition: transform calc(0.4s * var(--animation-time)) var(--out) calc(0.38s * var(--animation-time)); }
.jw-site.p3 .js-el--row { transform: translateY(0.75px); }

.js-new { opacity: 0; transition: opacity calc(0.35s * var(--animation-time)) calc(0.45s * var(--animation-time)); }
.jw-site.p3 .js-new { opacity: 1; }
.js-nb { fill: var(--accent-soft); }
.js-nf { fill: var(--accent); opacity: 0.75; }

.js-mail rect,
.js-mail path {
  fill: none;
  stroke: #a1a1a6;
  stroke-width: 1.2;
  stroke-linejoin: round;
  transition: stroke calc(0.3s * var(--animation-time)) calc(0.85s * var(--animation-time));
}

.js-mail { transform-box: fill-box; transform-origin: center; }
.jw-site.p3 .js-mail rect,
.jw-site.p3 .js-mail path { stroke: var(--accent); }
.jw-site.p3 .js-mail { animation: jsMail calc(0.5s * var(--animation-time)) var(--out) calc(0.85s * var(--animation-time)); }

@keyframes jsMail {
  0% { transform: scale(1); }
  40% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

.js-pane.is-lk .js-box,
.js-pane.is-lk .js-head { stroke: var(--accent); }

/* ---- 第二幕 数据清洗 */
.jc-sf { fill: #fff; stroke: #b8b8be; stroke-width: 1; }
.jc-sh { fill: #f1f1f4; }
.jc-shc { fill: #b8b8be; }
.jc-sg { fill: none; stroke: rgba(0, 0, 0, 0.08); stroke-width: 1; }
.jc-miss { fill: rgba(232, 87, 31, 0.06); stroke: var(--accent); stroke-width: 0.035; stroke-dasharray: 0.1 0.07; vector-effect: none; }

.jc-src { opacity: 0; transition: opacity calc(0.4s * var(--animation-time)); }
.jw-clean.p1 .jc-src { opacity: 1; }
.jw-clean.p2 .jc-src { opacity: 0.3; transition-delay: calc(0.2s * var(--animation-time)); }

/* 一格一格：从源表里的位置（歪着、宽窄不一）飞到总表那一行（摆正、同一种宽度）；
   口径那一列在总表里统一成深色，只有一张表才有的第 4 列并进口径那一列 */
.jc-c {
  fill: #c9c9ce;
  opacity: 0;
  transform: translate(var(--sx), var(--sy)) rotate(var(--sr)) scale(var(--sw), 1);
  transition: opacity calc(0.3s * var(--animation-time)), transform calc(0.55s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time)), fill calc(0.3s * var(--animation-time)) calc(var(--d) * var(--animation-time));
}

.jw-clean.p1 .jc-c:not(.jc-c--raw) { opacity: 1; }
.jw-clean.p2 .jc-c { opacity: 1; transform: translate(var(--ax), var(--ay)) rotate(0deg) scale(var(--aw), 1); }
.jw-clean.p2 .jc-c--key { fill: var(--ink-2); }
.jw-clean.p2 .jc-c--drop { opacity: 0; transition: opacity calc(0.2s * var(--animation-time)) calc((var(--d) + 0.42s) * var(--animation-time)), transform calc(0.55s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time)), fill calc(0.3s * var(--animation-time)) calc(var(--d) * var(--animation-time)); }

/* 源表里的原始写法：P4+、51—53、3=、M3……开头摆出来，行飞走时淡掉 */
.jc-raw {
  opacity: 0;
  font-size: 0.625em;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink-2);
}

.jw-clean.p1 .jc-raw { opacity: 1; transition-delay: calc(0.25s * var(--animation-time)); }
.jw-clean.p2 .jc-raw { opacity: 0; transition-delay: calc(0s * var(--animation-time)); transition-duration: calc(0.2s * var(--animation-time)); }

/* 总表：先只有表头和空着的底格（统一口径），p2 一行行填满 */
.jc-mf { fill: #fff; stroke: #a1a1a6; stroke-width: 1.2; }
.jc-mt { fill: var(--ink); }
.jc-mg { fill: none; stroke: var(--line); stroke-width: 1; }
.jc-mh { fill: #b8b8be; }
.jc-mh--rule { fill: var(--accent); }
.jc-m { opacity: 0; transition: opacity calc(0.4s * var(--animation-time)) calc(0.3s * var(--animation-time)); }
.jw-clean.p1 .jc-m { opacity: 1; }
.jc-mh { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)) calc((0.55s + var(--c) * 0.12s) * var(--animation-time)); }
.jw-clean.p1 .jc-mh { opacity: 1; }
.jw-clean.p1 .jc-mh--rule { animation: jcRule calc(0.9s * var(--animation-time)) var(--out) calc(0.95s * var(--animation-time)); }
@keyframes jcRule {
  0%, 100% { opacity: 1; }
  30% { opacity: 0.25; }
  60% { opacity: 1; }
}
.jc-slot { fill: #efeff2; opacity: 0; transition: opacity calc(0.35s * var(--animation-time)) calc(0.6s * var(--animation-time)); }
.jw-clean.p1 .jc-slot { opacity: 1; }

/* 缺的那一格：总表里由匹配补上（先是强调色），核对过后变回普通的一格 */
.jc-fill {
  fill: var(--accent);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: left;
  transform: scaleX(0);
  transition: opacity calc(0.2s * var(--animation-time)), transform calc(0.4s * var(--animation-time)) var(--out), fill calc(0.3s * var(--animation-time));
}

.jw-clean.p2 .jc-fill { opacity: 1; transform: none; transition-delay: calc((var(--d) + 0.55s) * var(--animation-time)); }
.jw-clean.done .jc-fill { fill: var(--ink-2); transition-delay: calc(0s * var(--animation-time)); }

.jc-arrow { fill: none; stroke: #b8b8be; stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round; opacity: 0; transition: opacity calc(0.35s * var(--animation-time)); }
.jw-clean.p1 .jc-arrow { opacity: 1; transition-delay: calc(0.7s * var(--animation-time)); }

.jc-ai { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jc-ai circle { fill: var(--accent); stroke: rgba(232, 87, 31, 0.22); stroke-width: 6; transform-box: fill-box; transform-origin: center; }
.jc-ai text { font-size: 0.42px; font-weight: 700; fill: var(--accent-ink); letter-spacing: 0.02px; }
.jw-clean.p2 .jc-ai { opacity: 1; }
.jw-clean.p2:not(.p3) .jc-ai circle { animation: jcPulse calc(0.5s * var(--animation-time)) var(--out) 2; }

@keyframes jcPulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.3); }
}

/* 核对：一道线从上扫到下，扫过的行后面亮起一个点 */
.jc-scan { fill: var(--accent); opacity: 0; }
.jw-clean.p3 .jc-scan { animation: jcScan calc(0.7s * var(--animation-time)) linear both; }

@keyframes jcScan {
  0% { opacity: 1; transform: translateY(0); }
  90% { opacity: 1; transform: translateY(6.3px); }
  100% { opacity: 0; transform: translateY(6.3px); }
}

.jc-ok {
  fill: var(--ink-2);
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0);
  transition: opacity calc(0.2s * var(--animation-time)) calc(var(--q) * var(--animation-time)), transform calc(0.3s * var(--animation-time)) var(--out) calc(var(--q) * var(--animation-time));
}

.jw-clean.p3 .jc-ok { opacity: 1; transform: none; }

/* 用时：约一周对一天 */
.jc-tb { transform-box: fill-box; transform-origin: left; transform: scaleX(0); transition: transform calc(0.7s * var(--animation-time)) var(--out); }
.jc-tb--slow { fill: #d2d2d7; }
.jc-tb--fast { fill: var(--accent); }
.jw-clean.p3 .jc-tb--slow { transform: none; transition-delay: calc(0.4s * var(--animation-time)); }
.jw-clean.p3 .jc-tb--fast { transform: none; transition-delay: calc(0.85s * var(--animation-time)); transition-duration: calc(0.35s * var(--animation-time)); }

.jc-l0,
.jc-l2,
.jc-t { font-size: 0.6875em; opacity: 0; }
.jc-l1 { font-size: 0.625em; color: var(--accent-ink); opacity: 0; }
.jc-t1 { color: var(--accent-ink); font-weight: 600; }
.jc-l3 { opacity: 0; }
.jc-l3 b { color: var(--accent-ink); }
.jw-clean.p1 .jc-l0,
.jw-clean.p1 .jc-l2 { opacity: 1; }
.jw-clean.p2 .jc-l1 { opacity: 1; }
.jw-clean.p3 .jc-t0 { opacity: 1; transition-delay: calc(0.4s * var(--animation-time)); }
.jw-clean.p3 .jc-t1 { opacity: 1; transition-delay: calc(0.85s * var(--animation-time)); }
.jw-clean.p3 .jc-l3 { opacity: 1; transition-delay: calc(0.55s * var(--animation-time)); }

.jc-l3 b.is-lk { text-decoration: underline; text-underline-offset: 0.2em; }
.world[data-lk="jc"] .jc-mf { stroke: var(--accent); }

/* 左边几条经历跟着右边的演示走（晶澳、拜耳三条对三幕；IDC 两条对一幅图的前后两段）。
   每条左边一道浅槽；右边演到哪一条，那一条的槽里就和右图底下的进度线同一个节奏，长出一道强调色细线，
   小标题变强调色，其余几条退成灰。演完细线往下流走，下一条从顶上接着长。
   换条的那一刻，新的一条的槽和右边那一站的圆点同时亮一下；指到哪一条，槽先变深一点 */
.ch-points.is-linked > div {
  position: relative;
}

.m-wide .ch-points.is-linked > div {
  cursor: pointer;
}

.ch-points.is-linked > div::before,
.ch-points.is-linked > div::after {
  content: "";
  position: absolute;
  left: -0.9rem;
  top: 0.95rem;
  bottom: 0;
  width: 2px;
}

.ch-points.is-linked > div::after {
  background: var(--line);
  transition: background-color calc(0.25s * var(--animation-time));
}

/* 细线：平时收在槽底（往下流走的样子）；is-on 时从顶上长到 --lp，用时 --lt，和右图同一个时钟 */
.ch-points.is-linked > div::before {
  z-index: 1;
  background: var(--accent);
  transform-origin: top;
  transform: translateY(100%) scaleY(0);
  transition: transform calc(0.5s * var(--animation-time)) var(--inout);
}

.ch-points.is-linked > div.is-on::before {
  transform: scaleY(var(--lp, 0));
  transition: transform var(--lt, 0.4s) linear;
}

.ch-points.is-linked > div.is-arm::before {
  transform: scaleY(0);
  transition: none;
}

.ch-points.is-linked > div dt {
  transition: color calc(0.25s * var(--animation-time));
}

.ch-points.is-linked.has-cur > div:not(.is-cur) dt {
  color: var(--mute-2);
}

.m-wide .ch-points.is-linked.has-cur > div:not(.is-cur):hover dt {
  color: var(--ink-2);
}

.m-wide .ch-points.is-linked > div:hover::after {
  background-color: #b4b4ba;
}

@keyframes linkEcho {
  0% { background-color: rgba(232, 87, 31, 0.6); }
  100% { background-color: var(--line); }
}

@keyframes tabPing {
  0% { box-shadow: 0 0 0 0 rgba(232, 87, 31, 0.45); }
  100% { box-shadow: 0 0 0 0.6em rgba(232, 87, 31, 0); }
}

@media (prefers-reduced-motion: no-preference) {
  .ch-points.is-linked > div.is-echo::after {
    animation: linkEcho calc(1s * var(--animation-time)) var(--out);
  }
  .jw-tab.is-ping i {
    animation: tabPing calc(1s * var(--animation-time)) var(--out);
  }
}


/* 引导：在几条经历上方写明白怎么操作、会发生什么，一直在，不消失；开头一个指针图标，到站时轻点两下。
   手机放在作品图的三站上方，说轻触 */
.work-hint {
  display: none;
  align-items: center;
  gap: 0.5em;
  font-size: max(0.9375rem, 14px);
  line-height: 1.5;
  color: var(--ink-2);
}

.work-hint b {
  font-weight: 600;
  color: var(--accent-ink);
}

.work-hint svg {
  flex: none;
  width: 0.85em;
  height: 1.12em;
  overflow: visible;
  fill: var(--bg);
  stroke: var(--accent);
  stroke-width: 1.4;
  stroke-linejoin: round;
}

.work-hint--touch svg {
  width: 1.05em;
  height: 1.05em;
  fill: none;
  stroke-width: 1.2;
}

.work-hint--touch .wh-dot {
  fill: var(--accent);
  stroke: none;
}

.m-wide .work-hint--wide {
  display: flex;
  margin-top: 1.25rem;
}

.m-wide .ch .work-hint--wide + .ch-points {
  margin-top: 0.55rem;
}

.m-tall .work-hint--touch {
  display: flex;
  margin-bottom: 0.85rem;
}

@keyframes whTap {
  0%, 100% { transform: none; }
  25% { transform: translate(1.5px, 2.5px); }
  50% { transform: none; }
  75% { transform: translate(1px, 1.5px); }
}

@media (prefers-reduced-motion: no-preference) {
  .m-wide .ch.is-on .work-hint--wide svg {
    animation: whTap calc(1.2s * var(--animation-time)) var(--inout) calc(0.8s * var(--animation-time)) both;
  }
}

/* 可以指的标题：左边几条的小标题和正文里的关键词同一套记号，平时下面一道淡点线；右边三站是底线上的一段。
   鼠标停上去，强调色实线从左往右长满（0.18 秒，和 app.js 的 AIM_MS 一致），长满的那一刻右边切过去；
   正在演的那一对，左右都是强调色实线 */
.m-wide .ch-points.is-linked dt span {
  background-image: linear-gradient(var(--accent), var(--accent)), repeating-linear-gradient(90deg, rgba(29, 29, 31, 0.3) 0 2px, transparent 2px 5px);
  background-repeat: no-repeat;
  background-position: 0 100%, 0 100%;
  background-size: 0% 2px, 100% 1px;
  transition: background-size 0.3s var(--out);
}

.m-wide .ch-points.is-linked > div.is-cur dt span {
  background-size: 100% 2px, 0% 1px;
}

.jw-tab::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0.35em;
  bottom: calc(-0.45em - 0.5px);
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--out);
}

.jw-tab[aria-selected="true"]::before {
  transform: none;
}

@media (hover: hover) {
  .m-wide:not(.is-quiet) .ch-points.is-linked > div:not(.is-cur):hover dt span {
    background-size: 100% 2px, 100% 1px;
    transition: background-size 0.18s linear;
  }
  :root:not(.is-quiet) .jw-tab[aria-selected="false"]:hover::before {
    transform: none;
    transition: transform 0.18s linear;
  }
}

/* 手机：三站的字小，点按范围往四周放大一圈（不占位置） */
.m-tall .jw-tab::after {
  content: "";
  position: absolute;
  inset: -0.75em -0.45em;
}


/* ---- IDC 研究框架：一棵往右展开的树，收进价格表，再分成 3 套底表 */
.jw-drill {
  --animation-time: calc(var(--content-time, 1) / var(--scene-speed, 1));
}

.vx-drill {
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time));
}

.world[data-focus="idc"] .vx-drill {
  opacity: 1;
}

.world[data-focus="idc"] .vx-drill [data-k] {
  pointer-events: auto;
}

.dr-gl { fill: none; stroke: #b8b8be; stroke-width: 1; stroke-dasharray: 2 3; opacity: 0; transition: opacity calc(0.4s * var(--animation-time)); }
.jw-drill.p1 .dr-gl { opacity: 0.6; }
.jw-drill.p3 .dr-gl { opacity: 0.25; }

.dr-h {
  transform: translateX(-50%);
  text-align: center;
  line-height: 1.25;
  opacity: 0.35;
  transition: opacity calc(0.4s * var(--animation-time)) var(--out), color calc(0.25s * var(--animation-time));
}

.dr-h b,
.dr-h i {
  display: block;
  font-style: normal;
  white-space: nowrap;
}

.dr-h b { font-size: 0.875em; transition: color calc(0.25s * var(--animation-time)); }
.dr-h i { margin-top: 0.15em; font-size: 0.8125em; color: var(--mute); opacity: 0; transition: opacity calc(0.35s * var(--animation-time)), color calc(0.25s * var(--animation-time)); }
.dr-h0 { transform: translateX(-20%); text-align: left; }

/* p1：三层框架（场景、区域、企业）的表头先立起来；价格和产出两列到 p3 才亮 */
.jw-drill.p1 .dr-h0,
.jw-drill.p1 .dr-h1,
.jw-drill.p1 .dr-h2 { opacity: 1; }
.jw-drill.p1 .dr-h0 i { opacity: 1; }
.jw-drill.p2 .dr-h1 i { opacity: 1; transition-delay: calc(0.5s * var(--animation-time)); }
.jw-drill.p2 .dr-h2 i { opacity: 1; transition-delay: calc(1s * var(--animation-time)); }
.jw-drill.p3 .dr-h3,
.jw-drill.p3 .dr-h3 i { opacity: 1; transition-delay: calc(0.25s * var(--animation-time)); }
.jw-drill.done .dr-h4,
.jw-drill.done .dr-h4 i { opacity: 1; transition-delay: calc(0.45s * var(--animation-time)); }
.dr-h4 i { color: var(--accent-ink); font-weight: 600; }

/* 根：一开始是虚线圈（数据缺口），演完填实 */
.dr-root { fill: var(--bg); stroke: var(--ink); stroke-width: 0.06; stroke-dasharray: 0.12 0.09; vector-effect: none; transition: fill calc(0.4s * var(--animation-time)), stroke calc(0.4s * var(--animation-time)); }
.jw-drill.done .dr-root { fill: var(--accent); stroke: var(--accent); stroke-dasharray: none; }
.dr-gap { font-size: 0.625em; color: var(--accent-ink); opacity: 0; transition: opacity calc(0.35s * var(--animation-time)); }
.jw-drill.p1 .dr-gap { opacity: 1; transition-delay: calc(0.2s * var(--animation-time)); }
.jw-drill.done .dr-gap { opacity: 0; }

/* 线和点：一层层长出来（--d 是这一条在这一段里的起点） */
/* 画线动画用 pathLength = 1 的虚线：线宽、虚线都按图里的单位算（不跟屏幕像素），否则虚线会碎成点 */
.dr-e { fill: none; stroke: #c3c3c9; stroke-width: 0.045; stroke-dasharray: 1; stroke-dashoffset: 1; vector-effect: none; }
.dr-e1 { stroke: #8e8e93; stroke-width: 0.075; }
.dr-e2 { stroke: #a1a1a6; stroke-width: 0.055; }
.jw-drill.p2 .dr-e1,
.jw-drill.p2 .dr-e2,
.jw-drill.p2 .dr-e3 { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.32s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)); }
.jw-drill.p3 .dr-e4 { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.35s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)); }
.jw-drill.done .dr-e5 { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.3s * var(--animation-time)) var(--out) calc((0.3s + var(--d)) * var(--animation-time)); }
.dr-e4 { stroke: #d6d6db; stroke-width: 0.04; }
.dr-e5 { stroke: var(--accent); stroke-width: 0.06; }

.dr-n { transform-box: fill-box; transform-origin: center; transform: scale(0); }
.dr-n1 { fill: var(--ink); }
.dr-n2 { fill: var(--ink-2); }
.dr-n3 { fill: #6e6e73; }
.jw-drill.p2 .dr-n { transform: none; transition: transform calc(0.3s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)), fill calc(0.25s * var(--animation-time)); }

/* 价格表：142 个点，开头散在各处、深浅不一（各家来源、写法、口径不一），统一口径后排齐、变成同一种灰；
   演完时一道线从上扫到下，扫过的点变深（核对过） */
.dr-p {
  opacity: 0;
  transform: translate(var(--jx), var(--jy));
  transition: opacity calc(0.25s * var(--animation-time)), transform calc(0.5s * var(--animation-time)) var(--inout), fill calc(0.3s * var(--animation-time));
}

.dr-p0 { fill: #b4b4ba; }
.dr-p1 { fill: #d6d6db; }
.dr-p2 { fill: #96969c; }
.jw-drill.p3 .dr-p { opacity: 1; transform: none; fill: #c3c3c9; transition: opacity calc(0.25s * var(--animation-time)) calc(0.15s * var(--animation-time)), transform calc(0.5s * var(--animation-time)) var(--inout) calc(0.5s * var(--animation-time)), fill calc(0.3s * var(--animation-time)) calc(0.6s * var(--animation-time)); }
.jw-drill.done .dr-p { fill: var(--ink-2); transition: opacity calc(0.25s * var(--animation-time)), transform calc(0.5s * var(--animation-time)) var(--inout), fill calc(0.15s * var(--animation-time)) calc((var(--r) * 20ms) * var(--animation-time)); }

.dr-scan { fill: var(--accent); opacity: 0; }
.jw-drill.done .dr-scan { animation: drScan calc(0.5s * var(--animation-time)) linear both; }

@keyframes drScan {
  0% { opacity: 1; transform: translateY(0); }
  90% { opacity: 1; transform: translateY(8.2px); }
  100% { opacity: 0; transform: translateY(8.2px); }
}

/* 3 套底表 */
.dr-tf { fill: #fff; stroke: #a1a1a6; stroke-width: 1.1; }
.dr-th { fill: var(--accent-soft); }
.dr-tc { fill: #c9c9ce; }
.dr-t { opacity: 0; transform: translateX(-0.3px); transition: opacity calc(0.35s * var(--animation-time)), transform calc(0.45s * var(--animation-time)) var(--out); }
.jw-drill.done .dr-t { opacity: 1; transform: none; transition-delay: calc((0.45s + var(--d)) * var(--animation-time)); }


/* 指着正文里对应的那句话（或者指着图里的表头）：那一层亮起来 */
.dr-h.is-lk b { color: var(--accent-ink); }
.dr-h.is-lk i { color: var(--ink); }
.dr-g1.is-lk .dr-n1,
.dr-g1.is-lk .dr-n2,
.dr-g2.is-lk .dr-n3 { fill: var(--accent); }
.dr-g1.is-lk .dr-e1,
.dr-g1.is-lk .dr-e2,
.dr-g2.is-lk .dr-e3 { stroke: var(--accent); stroke-opacity: 0.55; }
.dr-g2.is-lk .dr-pts .dr-p { fill: var(--accent); }
.dr-g3.is-lk .dr-tf { stroke: var(--accent); }
.dr-g0.is-lk .dr-root { stroke: var(--accent); }

/* 凯度固定图位：五块面板共享一格，尺寸不随选择变化。 */
.pr-list { position: absolute; inset: 0; pointer-events: none; }
.kx {
  position: absolute;
  display: grid;
  width: 31.2em;
  border-top: 1px solid var(--hair);
  padding-top: 0.8em;
  font-size: calc(19px * var(--tk));
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity calc(0.35s * var(--animation-time)) var(--out), visibility calc(0s * var(--animation-time)) calc(0.35s * var(--animation-time));
}
.world[data-focus="kantar"] .kx { opacity: 1; visibility: visible; pointer-events: auto; transition-delay: calc(0s * var(--animation-time)); }
.kx-panel, .kp-panel, .pj-panels > .pj-panel {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(6px);
  transition: opacity calc(0.15s * var(--animation-time)), transform calc(0.3s * var(--animation-time)) var(--out), visibility calc(0s * var(--animation-time)) calc(0.15s * var(--animation-time));
}
.kx-panel.is-cur, .kp-panel.is-cur, .pj-panels > .pj-panel.is-cur {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition: opacity calc(0.3s * var(--animation-time)) calc(0.1s * var(--animation-time)), transform calc(0.3s * var(--animation-time)) var(--out) calc(0.1s * var(--animation-time)), visibility calc(0s * var(--animation-time));
}
.kx-label { font-size: 0.9em; color: var(--mute); line-height: 1.65; margin-bottom: 0.8em; }
.kx-fig { margin: 0; }
.kx-fig .jw { font-size: 1.5em; }
.kx-stats { display: flex; gap: 2.1em; padding: 1.1em 0; }
.kx-stat p { display: flex; align-items: baseline; gap: 0.4em; white-space: nowrap; }
.kx-stat b { font-family: var(--font-display); font-size: 2.32em; font-weight: 600; line-height: 1.15; }
.kx-stat span { font-size: 1.05em; color: var(--ink-2); }
.kx-stat small { display: block; margin-top: 0.4em; color: var(--mute); font-size: 0.9em; }
.kx.is-arrived .kx-stat { animation: swapIn calc(0.45s * var(--animation-time)) var(--out) calc((0.55s + var(--i) * 0.12s) * var(--animation-time)) both; }
.kx-stat.is-lk b { color: var(--accent-ink); }

.pj-panel {
  container-type: inline-size;
}

.pj-fig {
  margin: 0.8rem 0 0.2rem;
}

.pj-fig .jw {
  font-size: min(17px, 100cqw / 21.2);
}

.m-tall .pj-fig .mf-l { font-size: max(0.75em, 11px); }
.m-tall .pj-fig .mf-s,
.m-tall .pj-fig .mf-row { font-size: max(0.6875em, 10px); }

.mf-s { font-size: 0.6875em; }
.mf-key { color: var(--accent-ink); font-weight: 600; }
.mf-row { font-size: 0.6875em; font-weight: 600; color: var(--ink-2); }
.mf-base { fill: none; stroke: var(--line); stroke-width: 1; }

.mf-sw {
  display: inline-block;
  width: 0.62em;
  height: 0.62em;
  margin-right: 0.35em;
  border-radius: 0.12em;
  background: var(--accent);
  vertical-align: -0.04em;
}

.mf-out { opacity: 0; }
.jw-sc.p3 .mf-out { opacity: 1; transition-delay: calc(0.55s * var(--animation-time)); }

/* 环球影城：得分格一列列铺开；环球那一行框出来，明显落后的几项变成强调色；右边的柱子按样本量校准到一样高 */
.ub-c { opacity: 0; transition: opacity calc(0.25s * var(--animation-time)) calc(var(--d) * var(--animation-time)), fill calc(0.3s * var(--animation-time)); }
.jw-ubr.p1 .ub-c { opacity: 1; }
.jw-ubr.p2 .ub-c--lag { fill: var(--accent) !important; transition: opacity calc(0.25s * var(--animation-time)), fill calc(0.3s * var(--animation-time)) calc((0.2s + var(--q)) * var(--animation-time)); }

.ub-us { fill: none; stroke: var(--ink-2); stroke-width: 1.2; opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-ubr.p2 .ub-us { opacity: 1; }
.mf-row { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)) calc(0.3s * var(--animation-time)); }
.jw-ubr.p1 .mf-row { opacity: 1; }
.ub-lag { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-ubr.p2 .ub-lag { opacity: 1; transition-delay: calc(0.55s * var(--animation-time)); }

.ub-b {
  fill: #c7c7cc;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: bottom;
  transition: opacity calc(0.3s * var(--animation-time)) calc((0.45s + var(--d)) * var(--animation-time)), transform calc(0.6s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time));
}

.ub-b--us { fill: var(--ink-2); }
.jw-ubr.p1 .ub-b { opacity: 1; }
.jw-ubr.p3 .ub-b { transform: scaleY(var(--k)); }

.ub-cal { fill: none; stroke: var(--accent); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-ubr.p3 .ub-cal { opacity: 1; transition-delay: calc(0.5s * var(--animation-time)); }

.ub-l1,
.ub-l2 { opacity: 0; }
.jw-ubr.p1 .ub-l1 { opacity: 1; transition-delay: calc(0.45s * var(--animation-time)); }
.jw-ubr.p3 .ub-l1 { opacity: 0; transition-delay: calc(0s * var(--animation-time)); transition-duration: calc(0.2s * var(--animation-time)); }
.jw-ubr.p3 .ub-l2 { opacity: 1; transition-delay: calc(0.3s * var(--animation-time)); }

/* 泰康：逐波的柱子立起来；一个窗口从左滑到右，后面画出滚动算出来的线；开放题的回答飞进三类编码 */
.tk-b { fill: #c7c7cc; transform-box: fill-box; transform-origin: bottom; transform: scaleY(0); transition: transform calc(0.4s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)); }
.jw-tk.p1 .tk-b { transform: none; }
.tk-win { fill: rgba(232, 87, 31, 0.07); stroke: var(--accent); stroke-width: 1; opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-tk.p2 .tk-win { opacity: 1; transform: translateX(7px); transition: opacity calc(0.25s * var(--animation-time)), transform calc(1s * var(--animation-time)) linear calc(0.1s * var(--animation-time)); }
.jw-tk.p3 .tk-win { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)) calc(0.15s * var(--animation-time)), transform calc(1s * var(--animation-time)) linear calc(0.1s * var(--animation-time)); }
.tk-avg { fill: none; stroke: var(--accent); stroke-width: 0.085; vector-effect: none; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 1; stroke-dashoffset: 1; }
.jw-tk.p2 .tk-avg { stroke-dashoffset: 0; transition: stroke-dashoffset calc(1s * var(--animation-time)) linear calc(0.1s * var(--animation-time)); }
.tk-k { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-tk.p3 .tk-k { opacity: 1; }
.tk-h { fill: #b8b8be; opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.tk-q,
.tk-k2 { opacity: 0; transition: opacity calc(0.3s * var(--animation-time)); }
.jw-tk.p1 .tk-q { opacity: 1; }
.jw-tk.p3 .tk-h,
.jw-tk.p3 .tk-k2 { opacity: 1; transition-delay: calc(0.3s * var(--animation-time)); }
.jw-tk.p3 .tk-q { opacity: 0; transition-delay: calc(0s * var(--animation-time)); }

.tk-c {
  fill: #c9c9ce;
  opacity: 0;
  transform: translate(var(--sx), var(--sy)) scale(var(--sw), 1);
  transition: opacity calc(0.3s * var(--animation-time)), transform calc(0.55s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time)), fill calc(0.3s * var(--animation-time)) calc(var(--d) * var(--animation-time));
}

.jw-tk.p1 .tk-c { opacity: 1; }
.jw-tk.p3 .tk-c { transform: translate(var(--ax), var(--ay)) scale(var(--aw), 1); fill: var(--ink-2); }

/* 凯度第二轮起保留图形骨架。阶段仍改变高亮、柱高和编码位置，
   但重播时不再把得分格、趋势线、柱子、报告和说明一起清空。 */
.jw-ubr.is-looping :is(.ub-c, .ub-b, .ub-us, .mf-row, .ub-lag, .ub-cal, .mf-out),
.jw-tk.is-looping :is(.tk-win, .tk-h, .tk-c, .tk-k, .mf-out) {
  opacity: 1;
}

.jw-ubr.is-looping .ub-l1 { opacity: 1; transition: none; }
.jw-ubr.is-looping .ub-l2 { opacity: 0; transition: none; }
.jw-ubr.is-looping.p3 .ub-l1 { opacity: 0; }
.jw-ubr.is-looping.p3 .ub-l2 { opacity: 1; }
.jw-tk.is-looping .tk-avg { stroke-dashoffset: 0; }
.jw-tk.is-looping .tk-b { transform: none; }
.jw-tk.is-looping .tk-q,
.jw-tk.is-looping .tk-k2 { transition: none; }
.jw-tk.is-looping:not(.p3) .tk-q { opacity: 1; }
.jw-tk.is-looping:not(.p3) .tk-k2 { opacity: 0; }


/* “现在”之后的虚线：讲晶澳时慢慢往前流，线还在往下走 */
.world[data-focus="jasolar"] .l-future {
  animation: futureFlow calc(1.6s * var(--animation-time)) linear infinite;
}

@keyframes futureFlow {
  to { stroke-dashoffset: -13.1; }
}

/* ---------------------------------------------------------------- 拜耳三幕 */

/* 第一幕 集团简报：三类材料的卡片先落位，再连到各业务的拆解，最后一页页排出 48 页 */
.bf-card { fill: var(--bg); stroke: var(--line); stroke-width: 1; }
.bf-ln { fill: #c9c9ce; }
.bf-bar { fill: #b8b8be; }
.bf-spark { fill: none; stroke: #8e8e93; stroke-width: 0.06; stroke-linecap: round; }

.bf-src {
  opacity: 0;
  transform: translateY(0.18px);
  transition: opacity calc(0.4s * var(--animation-time)) calc(var(--d) * var(--animation-time)), transform calc(0.45s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time));
}
.jw-brief.p1 .bf-src { opacity: 1; transform: none; }

.jw-brief .bf-t { opacity: 0; }
.jw-brief.p1 .bf-t { opacity: 1; transition-delay: calc(0.15s * var(--animation-time)); }
.bf-t { color: var(--ink-2); }

.bf-fl {
  fill: none;
  stroke: #b8b8be;
  stroke-width: 0.045;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  vector-effect: none;
  transition: stroke calc(0.45s * var(--animation-time));
}
.jw-brief.p2 .bf-fl { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.55s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)), stroke calc(0.45s * var(--animation-time)); }
.jw-brief.p3 .bf-fl { stroke: #dcdce0; }

.bf-nb { fill: #6e6e73; }
.bf-bub {
  fill: #c9c9ce;
  transform: scaleX(0);
  transform-box: fill-box;
  transform-origin: 0 50%;
}
.bf-arr { fill: #8e8e93; }
.bf-tag { fill: #e2e2e6; stroke: #d2d2d7; stroke-width: 1; }
.bf-bu { opacity: 0; transition: opacity calc(0.35s * var(--animation-time)) calc(var(--d) * var(--animation-time)); }
.jw-brief.p2 .bf-bu { opacity: 1; }
.jw-brief.p2 .bf-bub { transform: none; transition: transform calc(0.6s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)); }

.jw-brief .bf-k1,
.jw-brief .bf-k2 { opacity: 0; }
.jw-brief.p2 .bf-k1 { opacity: 1; transition-delay: calc(0.35s * var(--animation-time)); }
.jw-brief.p2 .bf-k2 { opacity: 1; transition-delay: calc(0.45s * var(--animation-time)); }
.bf-k1, .bf-k2 { font-size: 0.6875em; }

.bf-page {
  opacity: 0;
  transform: translateY(0.14px);
  transition: opacity calc(0.3s * var(--animation-time)) calc(var(--d) * var(--animation-time)), transform calc(0.4s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time));
}
.jw-brief.p3 .bf-page { opacity: 1; transform: none; }
.bf-pg { fill: var(--bg); stroke: #d2d2d7; stroke-width: 1; }
.bf-pg--sec { fill: var(--accent-soft); stroke: rgba(232, 87, 31, 0.35); }
.bf-pt { fill: #b8b8be; }
.bf-pt--sec { fill: var(--accent); }

.jw-brief .bf-n { opacity: 0; }
.jw-brief.p3 .bf-n { opacity: 1; transition-delay: calc(0.15s * var(--animation-time)); }

.bf-ul {
  fill: none;
  stroke: var(--accent);
  stroke-width: 0.07;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  vector-effect: none;
}
.jw-brief.done .bf-ul { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.6s * var(--animation-time)) var(--out); }

.jw-brief .bf-rep { opacity: 0; }
.jw-brief.done .bf-rep { opacity: 1; transition-delay: calc(0.2s * var(--animation-time)); }

/* 三栏题注：p1 就出现 */
.jw-brief .bf-h0,
.jw-brief .bf-h1,
.jw-brief .bf-h2 { opacity: 0; }
.jw-brief.p1 .bf-h0,
.jw-brief.p1 .bf-h1,
.jw-brief.p1 .bf-h2 { opacity: 1; }

.bb-f { fill: none; stroke: #d2d2d7; stroke-width: 1; transition: stroke calc(0.5s * var(--animation-time)); }
.bb-g { stroke: rgba(0, 0, 0, 0.07); stroke-width: 1; fill: none; }
.jw-bench .bb-f,
.jw-bench .bb-g { opacity: 0; transition: opacity calc(0.4s * var(--animation-time)); }
.jw-bench.p1 .bb-f,
.jw-bench.p1 .bb-g { opacity: 1; }
.jw-bench.p3 .bb-f { stroke: var(--accent); }

.bb-rh { fill: #b8b8be; }
.bb-c { transform: translate(var(--jx), var(--jy)); opacity: 0; }
.bb-cv0 { fill: #c9c9ce; }
.bb-cv1 { fill: #b4b4ba; }
.bb-cv2 { fill: #dcdce0; }
.jw-bench.p1 .bb-c { opacity: 1; transition: opacity calc(0.35s * var(--animation-time)) calc(var(--d) * var(--animation-time)); }
/* 排齐：位置、颜色、长短都统一成同一比较口径（长短过渡同时走） */
.jw-bench.p2 .bb-c { fill: #c4c4ca; transform: none; width: 1.85px; transition: transform calc(0.55s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time)), fill calc(0.5s * var(--animation-time)) calc(var(--d) * var(--animation-time)), width calc(0.55s * var(--animation-time)) var(--inout) calc(var(--d) * var(--animation-time)); }

/* 统一前混在表里的原始写法（地区叫法、币种）：p1 看得见，排齐时淡掉 */
.bb-chip { font-style: italic; color: var(--mute-2); opacity: 0; }
.jw-bench.p1 .bb-chip { opacity: 1; transition: opacity calc(0.4s * var(--animation-time)) calc(0.55s * var(--animation-time)); }
.jw-bench.p2 .bb-chip { opacity: 0; transition: opacity calc(0.4s * var(--animation-time)) calc(0.1s * var(--animation-time)); }

/* 左上角题注：“口径不一”淡出，“统一比较口径”接上；此后一直留住 */
.jw-bench .bb-l0 { opacity: 0; }
.jw-bench.p1 .bb-l0 { opacity: 1; transition: opacity calc(0.4s * var(--animation-time)); }
.jw-bench.p2 .bb-l0 { opacity: 0; transition: opacity calc(0.5s * var(--animation-time)) calc(0.55s * var(--animation-time)); }
.jw-bench .bb-l0b { opacity: 0; }
.jw-bench.p2 .bb-l0b { opacity: 1; transition: opacity calc(0.5s * var(--animation-time)) calc(0.8s * var(--animation-time)); }

.jw-bench .bb-h,
.jw-bench .bb-h2 { opacity: 0; }
.jw-bench.p1 .bb-h,
.jw-bench.p1 .bb-h2 { opacity: 1; transition-delay: calc(0.3s * var(--animation-time)); }

.bb-tr {
  fill: none;
  stroke: #9d9da3;
  stroke-width: 0.06;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  vector-effect: none;
}
.jw-bench.p2 .bb-tr { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.6s * var(--animation-time)) var(--out) calc(var(--d) * var(--animation-time)); }
.bb-td { fill: #9d9da3; transform: scale(0); transform-box: fill-box; transform-origin: center; }
.jw-bench.p2 .bb-td { transform: none; transition: transform calc(0.3s * var(--animation-time)) var(--out) calc((var(--d) + 0.45s) * var(--animation-time)); }

.bb-hu {
  fill: none;
  stroke: var(--accent);
  stroke-width: 0.06;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  vector-effect: none;
}
.jw-bench.p3 .bb-hu { stroke-dashoffset: 0; transition: stroke-dashoffset calc(0.55s * var(--animation-time)) var(--out); }

.jw-bench .bb-l1 { opacity: 0; }
.jw-bench.p3 .bb-l1 { opacity: 1; transition-delay: calc(0.3s * var(--animation-time)); }

/* 第二幕 客户筛查：整表扫一遍，四层过滤淡掉 73 家，挑出的 30 余家点亮后飞进高/中/低三档，原格留下空心痕 */
.bs-d,
.bs-g { fill: none; stroke: #c3c3c9; stroke-width: 1.2; }

@keyframes bsScan {
  0%, 100% { stroke: #c3c3c9; }
  35% { stroke: #6e6e73; }
}
.jw-screen.p1:not(.done) .bs-d,
.jw-screen.p1:not(.done) .bs-g { animation: bsScan calc(0.4s * var(--animation-time)) ease-out calc(var(--s) * var(--animation-time)); }

.jw-screen.p2 .bs-d:not(.bs-d--on) { opacity: 0.24; transition: opacity calc(0.4s * var(--animation-time)) calc((var(--f) * 0.32s + 0.15s) * var(--animation-time)); }

.jw-screen.p2 .bs-d--on { fill: var(--accent); stroke: var(--accent); transition: fill calc(0.3s * var(--animation-time)) calc(var(--p) * var(--animation-time)), stroke calc(0.3s * var(--animation-time)) calc(var(--p) * var(--animation-time)); }

.jw-screen.p3 .bs-d--on {
  transform: translate(var(--tx), var(--ty));
  transition: transform calc(0.65s * var(--animation-time)) var(--inout) calc(var(--o) * var(--animation-time)), fill calc(0.4s * var(--animation-time)) calc(var(--o) * var(--animation-time)), stroke calc(0.4s * var(--animation-time)) calc(var(--o) * var(--animation-time));
}
.jw-screen.p3 .bs-t1 { fill: #8e8e93; stroke: #8e8e93; }
.jw-screen.p3 .bs-t2 { fill: #b9b9bf; stroke: #b9b9bf; }

.bs-tl { stroke: rgba(0, 0, 0, 0.08); stroke-width: 1; stroke-dasharray: 2 3; fill: none; opacity: 0; transition: opacity calc(0.4s * var(--animation-time)); }
.jw-screen.p3 .bs-tl { opacity: 1; }

.jw-screen .bs-tier,
.jw-screen .bs-pri { opacity: 0; }
.jw-screen.p3 .bs-tier { opacity: 1; transition-delay: calc(0.35s * var(--animation-time)); }
.jw-screen.p3 .bs-pri { opacity: 1; transition-delay: calc(0.15s * var(--animation-time)); }

.jw-screen .bs-n0 { opacity: 0; }
.jw-screen.p1 .bs-n0 { opacity: 1; }
.jw-screen .bs-n1 { opacity: 0; color: var(--accent-ink); }
.jw-screen.p2 .bs-n1 { opacity: 1; transition-delay: calc(0.3s * var(--animation-time)); }

.jw-screen .bs-chn { opacity: 0; }
.jw-screen.p2 .bs-chn { opacity: 1; transition: opacity calc(0.4s * var(--animation-time)); }
.bs-f { font-style: normal; color: var(--mute-2); transition: color calc(0.3s * var(--animation-time)); }
.jw-screen.p2 .bs-f { color: var(--accent-ink); transition: color calc(0.3s * var(--animation-time)) calc((var(--f) * 0.32s + 0.2s) * var(--animation-time)); }
.jw-screen.p3 .bs-f,
.jw-screen.done .bs-f { color: var(--ink-2); transition: color calc(0.5s * var(--animation-time)); }

/* 每一幕的进度细线，节奏跟着这一幕的时间表走 */

/* 正文和图互相点亮：指着词，图里对应的部分亮；指着图里的部分，词加下划线 */
.bf-n b.is-lk,
.bb-l1 b.is-lk,
.bs-n0 b.is-lk,
.bs-n1 b.is-lk { text-decoration: underline; text-underline-offset: 0.2em; }
.world[data-lk="ba"] .bf-pg,
.world[data-lk="ba"] .bf-pg--sec { stroke: var(--accent); }
.world[data-lk="bb"] .bb-f { stroke: var(--accent); }
.world[data-lk="bc"] .bs-all circle { stroke: #8e8e93; }
.world[data-lk="bd"] .bs-d--on { stroke: var(--accent-ink); }

/* ---------------------------------------------------------------- 讲某一站时，其它站退到背景里 */

/* 凯度的四条项目线只在全景和讲凯度时出现；讲别的站时整组隐去，不在镜头里留一个没头没尾的分叉 */
.g-strands .l-strand,
.g-hi .l-hi--strand,
.g-ink .l-ink--strand,
.fx-strand {
  transition: opacity calc(0.4s * var(--animation-time)) var(--out);
}

/* Keep the rightmost selector specific: `path` makes a focus change invalidate
   SVG paths in every hidden work scene, although only these four strands match. */
.world.is-chapter:not([data-focus="kantar"]) .g-strands .l-strand,
.world.is-chapter:not([data-focus="kantar"]) .fx-strand,
.world.is-chapter:not([data-focus="kantar"]) .pr {
  opacity: 0 !important;
}

.world.is-chapter:not([data-focus="kantar"]) .pr-head {
  pointer-events: none;
}

/* 讲某一站时，别的站只留节点，logo、站名、时间都隐去，不在镜头边上留半截字半个标 */
.world.is-chapter .st:not(.is-focus) .st-logo,
.world.is-chapter:not([data-focus="kantar"]) .pr.is-in .pr-logo {
  opacity: 0;
  transition: opacity calc(0.4s * var(--animation-time)) var(--out);
}

.world.is-chapter .st:not(.is-focus) .st-lbl,
.world.is-chapter .st:not(.is-focus) .st-side,
.world.is-chapter:not([data-focus="kantar"]) .pr .pr-name {
  opacity: 0;
}

.world.is-chapter .st:not(.is-focus) .st-dot {
  opacity: 0.35;
}


.world.is-chapter .l-main,
.world.is-chapter .l-strand {
  stroke: #c9c9ce;
}

/* 讲某一站时，环境的流光退到很淡、不要柔光那一层（镜头放大以后它是一条粗橙带，会和阅读的光点抢“我在这”）；
   凯度的四条项目线上不走环境流光。顺线落下的光（.fx-shot）不受影响 */
.world.is-chapter .fx-glow:not(.fx-shot) {
  opacity: 0;
}

.world.is-chapter .fx-body:not(.fx-shot) {
  opacity: 0.14;
}

.world.is-chapter .fx-head:not(.fx-shot) {
  opacity: 0.32;
}

.world.is-chapter .fx-strand:not(.fx-shot) {
  opacity: 0 !important;
}

.world.is-chapter .fx-speck {
  opacity: 0.2;
}

/* 站名和时间左边的正文里已经有了，镜头里只留 logo */
.st-lbl {
  transition: opacity calc(0.4s * var(--animation-time)) var(--out);
}

.world.is-chapter .st.is-focus .st-lbl,
.world.is-chapter .st.is-focus .st-side {
  opacity: 0;
}

/* 讲到的那一段线重新变深 */
.l-ink {
  stroke: var(--ink);
  stroke-width: 3.6;
  opacity: 0;
  transition: opacity calc(0.35s * var(--animation-time)) var(--out);
}

.l-ink--strand {
  stroke-width: 2.4;
}

.world.is-chapter .l-ink.is-on {
  opacity: 1;
}

/* 教育页：镜头把两校连同中间那段线一起装下（倍数很小），所以学校这几样单独放大：
   线和节点按 --ek 放大到和别的章里看到的一样粗，logo 按 --eb 放大；logo 只留图形，站名、时间左边正文里有。
   logo 底边离节点 14·ek + 12·eb（app.js 的 fitSchool 按同样的数排上面的榜单图） */
.world[data-focus="school"]:not(.is-layout) .st--edu .st-body {
  bottom: calc(14px * var(--ek) + 12px * var(--eb));
  padding: 0;
  transform: translateX(-50%) scale(var(--eb));
  transform-origin: bottom center;
  transition: transform calc(0.5s * var(--animation-time)) var(--out), bottom calc(0.5s * var(--animation-time)) var(--out);
}
.world[data-focus="school"]:not(.is-layout) .st--edu .st-lbl { display: none; }
/* logo 格子两校一样高（logo 在里面居中），两个 logo 因此齐平 */
.world[data-focus="school"]:not(.is-layout) .st--edu .st-logo { height: var(--edu-box, 110px); }
/* 只在教育图位覆盖 layoutWorld 的标准内联尺寸，首屏仍用标准比例。 */
.world[data-focus="school"]:not(.is-layout) .st--edu .st-logo img { width: var(--edu-logo-w) !important; height: var(--edu-logo-h) !important; }
.world.is-chapter[data-focus="school"] .st.st--edu .st-logo { opacity: 1; }
.world[data-focus="school"] .st-side { visibility: hidden; }
.world[data-focus="school"].has-hi .st--edu.is-in:not(.is-hi) { opacity: 1; }
/* 两所学校的节点：平时不带“正在讲”的那一圈，正在演的那一所另有一圈（见下面 data-edv），换到哪一所，哪一站泛一圈 */
.world[data-focus="school"] .st--edu .st-dot { transform: scale(var(--ek)); opacity: 1; }
.world[data-focus="school"] .st--edu:not(.is-hi) .st-dot { box-shadow: none; }
.world[data-focus="school"] .st--work .st-dot { transform: scale(calc(0.6 * var(--ek))); opacity: 0.35; }
.world[data-focus="school"] .st--work .st-dot::before,
.world[data-focus="school"] .st--work .st-dot::after { display: none; }
.world[data-focus="school"] .is-ping > .ping { animation-name: schoolPing; }
@keyframes schoolPing { from { opacity: 0.75; transform: scale(var(--ek)); } to { opacity: 0; transform: scale(calc(3.6 * var(--ek))); } }
.world[data-focus="school"] .l-main,
.world[data-focus="school"] .l-ink { stroke-width: calc(2.88 * var(--ek)); }
.world[data-focus="school"] .l-enroll { stroke-width: calc(2.4 * var(--ek)); stroke-dasharray: 0.1 calc(11px * var(--ek)); }

/* 线上哪所学校在演：它的 logo 是实的，节点外面一圈浅强调色；另一所退淡一点（app.js 的 eduShow 设 data-edv） */
.world[data-focus="school"]:not(.is-layout) .st--edu .st-logo {
  transition: opacity calc(0.45s * var(--animation-time)) var(--out);
}
.world.is-chapter[data-focus="school"][data-edv="escp"] .st.st--sussex .st-logo,
.world.is-chapter[data-focus="school"][data-edv="sussex"] .st.st--escp .st-logo {
  opacity: 0.35;
}
.world.is-chapter[data-focus="school"] .st.st--edu .st-dot {
  opacity: 0.55;
  transition: transform calc(0.5s * var(--animation-time)) var(--out), box-shadow calc(0.4s * var(--animation-time)), opacity calc(0.4s * var(--animation-time));
}
.world.is-chapter[data-focus="school"][data-edv="escp"] .st.st--escp .st-dot,
.world.is-chapter[data-focus="school"][data-edv="sussex"] .st.st--sussex .st-dot {
  opacity: 1;
  box-shadow: 0 0 0 6px var(--accent-soft);
}

/* 榜单图：两所学校中间那段线的上方。上面两站标签（和晶澳、拜耳的三站同一套样子），下面两幕叠在同一格里，
   一幕是一所学校的两份榜单。尺寸都用 em，1em 由 fitSchool 按镜头算好（--edf），在屏幕上是正文的 1.4 倍左右。
   每份榜单：左边一列名次，一根细竖线，每一名一道短刻度、后面是校名；本校那一行铺一层浅强调色、刻度伸长，
   竖线上一个强调色的点落在这一行；中间省掉的几名合成一段虚线。
   is-reset 是开头（全藏、没有过渡），is-play 按 --li（第几份）、--r（第几格）、--hit（本校在第几格）排好先后往终态走；
   不带这两个类就是终态（减少动态效果、停下来时） */
.ed-fig {
  --animation-time: var(--content-time, 1);
  --ed-rh: 1.6em;
  width: max-content;
  font-size: var(--edf, 16px);
  line-height: 1.3;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  transform: translate(-50%, -100%);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.35s var(--out), visibility 0s 0.35s;
}

.world[data-focus="school"]:not(.is-layout) .ed-fig {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  cursor: default;
  /* 讲教育时自成一个合成层：图里一行行淡入、光点落下、换校，只重画这一小块，不连带整条线和各站重新栅格化 */
  will-change: opacity;
  transition: opacity 0.35s var(--out);
}

.ed-tabs {
  margin-bottom: 1.6em;
}

.ed-acts {
  display: grid;
}

/* 两幕叠在同一格里（整块按大的那一幕算，换幕时下面不跳）；换的时候旧的一幕先退 */
.ed-act {
  grid-area: 1 / 1;
  display: flex;
  gap: 2.6em;
  opacity: 0;
  visibility: hidden;
  transition: opacity calc(0.3s * var(--animation-time)) var(--out), visibility 0s calc(0.3s * var(--animation-time));
}

.ed-act.is-cur {
  opacity: 1;
  visibility: visible;
  transition: opacity calc(0.3s * var(--animation-time)) var(--out);
}

.ed-lad {
  position: relative;
  min-width: 7em;
}

.ed-lh {
  margin: 0 0 0.55em;
}

.ed-lh span {
  display: block;
  font-size: 0.8em;
  font-weight: 600;
  color: var(--ink-2);
  transition: color 0.25s;
}

.ed-lh i {
  display: block;
  margin-top: 0.1em;
  font-size: 0.72em;
  font-style: normal;
  color: var(--mute-2);
}

.ed-lb {
  position: relative;
  padding-left: 1.7em;
}

.ed-lb ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ed-lb li {
  position: relative;
  display: flex;
  align-items: center;
  height: var(--ed-rh);
}

/* 名次：竖线左边，右对齐 */
.ed-lb li b {
  position: absolute;
  right: 100%;
  margin-right: 0.7em;
  font-size: 0.72em;
  font-weight: 500;
  line-height: 1;
  color: var(--mute-2);
}

/* 刻度：每一行一样长，校名因此排成一列 */
.ed-lb li s {
  position: relative;
  display: block;
  flex: none;
  width: 0.75em;
  height: 1.5px;
  background: #c2c2c8;
}

/* 校名 */
.ed-lb li > span {
  margin-left: 0.5em;
  font-size: 0.78em;
  color: var(--mute);
}

/* 中间省掉的几名：占满剩下的格数，竖线在这一段换成虚线 */
.ed-lb li.ed-gap {
  height: calc(var(--span, 1) * var(--ed-rh));
}

.ed-gap b {
  font-weight: 700;
}

.ed-gap::before {
  content: "";
  position: absolute;
  left: -2px;
  width: 4px;
  top: calc(var(--ed-rh) * 0.35);
  bottom: calc(var(--ed-rh) * 0.35);
  background: repeating-linear-gradient(to bottom, #c2c2c8 0 2px, transparent 2px 6px) center / 1.5px 100% no-repeat, var(--bg);
}

/* 竖线：从第一格的刻度到最后一格 */
.ed-sp {
  position: absolute;
  left: 1.7em;
  top: calc(var(--ed-rh) / 2);
  bottom: calc(var(--ed-rh) / 2);
  width: 1.5px;
  margin-left: -0.75px;
  background: #c2c2c8;
  transform-origin: top;
}

/* 本校那一行：一层浅强调色的底，从名次铺到这份榜单的右边；刻度上叠一道强调色，名次、校名加深。
   字重一直是粗的，光点落下时只变颜色（不改字重、不改刻度长短，免得落下那一刻重新排版） */
.ed-lb li.is-hit::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: -1.95em;
  right: -0.7em;
  top: 0.14em;
  bottom: 0.14em;
  border-radius: 0.3em;
  background: var(--accent-soft);
  transform-origin: left center;
}

.ed-lb li.is-hit b {
  font-weight: 700;
  color: var(--accent-ink);
}

.ed-lb li.is-hit s::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2.5px;
  margin-top: -1.25px;
  background: var(--accent);
  transform-origin: left center;
}

.ed-lb li.is-hit > span {
  font-weight: 700;
  color: var(--ink);
}

/* 竖线上的光点：落在本校那一行 */
.ed-dot {
  position: absolute;
  z-index: 1;
  left: 1.7em;
  top: calc(var(--ed-rh) / 2);
  width: 0.56em;
  height: 0.56em;
  margin: -0.28em 0 0 -0.28em;
  border-radius: 50%;
  background: var(--accent);
  transform: translateY(calc(var(--hit) * var(--ed-rh)));
}

.ed-dot::after {
  content: "";
  position: absolute;
  inset: -0.2em;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  opacity: 0;
}

/* 指着左边的那条排名（或这份榜单）：榜单名和本校那一行的校名变强调色 */
.ed-lad.is-lk .ed-lh span,
.ed-lad.is-lk li.is-hit > span {
  color: var(--accent-ink);
}

/* 开头 */
.ed-act.is-reset,
.ed-act.is-reset * {
  transition: none !important;
  animation: none !important;
}

.ed-act.is-reset .ed-lh,
.ed-act.is-reset .ed-lb li {
  opacity: 0;
}

.ed-act.is-reset .ed-sp {
  transform: scaleY(0);
}

/* 光点还没走（开头，或者几行已经摆出来、光点还在等镜头停稳）：光点藏在第一行，本校那一行和别的行一样 */
.ed-act.is-reset .ed-dot,
.ed-act.is-play:not(.is-land) .ed-dot {
  opacity: 0;
  transform: none;
}

.ed-act.is-reset .ed-lb li.is-hit::before,
.ed-act.is-reset .ed-lb li.is-hit s::after,
.ed-act.is-play:not(.is-land) .ed-lb li.is-hit::before,
.ed-act.is-play:not(.is-land) .ed-lb li.is-hit s::after {
  transform: scaleX(0);
}

.ed-act.is-reset .ed-lb li.is-hit b,
.ed-act.is-play:not(.is-land) .ed-lb li.is-hit b {
  color: var(--mute-2);
}

.ed-act.is-reset .ed-lb li.is-hit > span,
.ed-act.is-play:not(.is-land) .ed-lb li.is-hit > span {
  color: var(--mute);
}

/* 摆（is-play）：第二份榜单晚 --li × 0.45s；竖线 0.1s 起往下画，一行行跟着淡入。只动透明度和变换，交给合成器 */
.ed-act.is-play .ed-lad {
  --t0: calc(var(--li) * 0.45s);
}

.ed-act.is-play .ed-lh {
  transition: opacity calc(0.3s * var(--animation-time)) var(--out) calc(var(--t0) * var(--animation-time));
}

.ed-act.is-play .ed-sp {
  transition: transform calc(0.5s * var(--animation-time)) cubic-bezier(0.3, 0, 0.4, 1) calc((var(--t0) + 0.1s) * var(--animation-time));
}

.ed-act.is-play .ed-lb li {
  transition: opacity calc(0.25s * var(--animation-time)) var(--out) calc((var(--t0) + 0.12s + var(--r) * 0.06s) * var(--animation-time));
}

/* 落（is-land）：--d0 后第一个光点出现（app.js 的 eduLand 给：和几行一起开演时 0.55s，到站等镜头停稳以后 0），
   第二份再晚 --li × 0.45s；出现 0.05s 后沿竖线往下走，每格 0.11s，落到本校那一行（--land，和 app.js 的 edLand 一致）。
   落下的那一刻泛一圈，那一行铺上浅强调色，刻度叠上强调色，名次和校名变色 */
.ed-act.is-land .ed-lad {
  --go: calc(var(--d0, 0s) + var(--li) * 0.45s);
  --land: calc(var(--go) + 0.05s + var(--hit) * 0.11s);
}

.ed-act.is-land .ed-dot {
  transition: opacity calc(0.15s * var(--animation-time)) linear calc(var(--go) * var(--animation-time)),
    transform calc((0.001s + var(--hit) * 0.11s) * var(--animation-time)) cubic-bezier(0.45, 0, 0.55, 1) calc((var(--go) + 0.05s) * var(--animation-time));
}

.ed-act.is-land .ed-dot::after {
  animation: edPing calc(0.9s * var(--animation-time)) var(--out) calc(var(--land) * var(--animation-time)) forwards;
}

.ed-act.is-land .ed-lb li.is-hit::before {
  transition: transform calc(0.45s * var(--animation-time)) var(--out) calc(var(--land) * var(--animation-time));
}

.ed-act.is-land .ed-lb li.is-hit s::after {
  transition: transform calc(0.3s * var(--animation-time)) var(--out) calc(var(--land) * var(--animation-time));
}

.ed-act.is-land .ed-lb li.is-hit b,
.ed-act.is-land .ed-lb li.is-hit > span {
  transition: color calc(0.25s * var(--animation-time)) calc(var(--land) * var(--animation-time));
}

@keyframes edPing {
  0% { opacity: 0.75; transform: scale(1); }
  100% { opacity: 0; transform: scale(3); }
}

/* 两幕之间沿线从一所学校走到另一所的光点：单独一张 svg（坐标和主线那张一样，盖住两校之间那段线），
   讲教育时自成一个合成层：每一帧改路径只重画这一层，淡入淡出改这一层的透明度，交给合成器 */
.ed-svg {
  position: absolute;
  left: -120px;
  top: -120px;
  overflow: visible;
  opacity: 0;
  pointer-events: none;
}

.world[data-focus="school"] .ed-svg {
  will-change: opacity;
}

.ed-trail {
  fill: none;
  stroke: var(--accent);
  stroke-width: calc(3.6px * var(--ek, 1));
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.9;
}

.ed-trail--glow {
  stroke-width: calc(13px * var(--ek, 1));
  opacity: 0.16;
}

.ed-head {
  fill: #ff7c3f;
}

/* 讲某一站时，左边的文字下面垫一层底色，线从文字后面穿出来 */
.veil {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  --vx: calc(max(var(--gutter), (100% - var(--maxw)) / 2) + min(30rem, 40%));
  background: linear-gradient(
    to right,
    var(--bg) 0,
    var(--bg) calc(var(--vx) + 0.5rem),
    rgba(251, 251, 253, 0) calc(var(--vx) + 7rem)
  );
}

.m-tall .veil {
  display: none;
}

/* 讲凯度时四条项目线都保持深色，选中的项目那一条变成强调色 */
.world[data-focus="kantar"] .l-strand {
  stroke: var(--ink);
}

.world[data-focus="kantar"] .l-ink--strand {
  opacity: 0 !important;
}

/* ---------------------------------------------------------------- 首屏：人、方向、完整的线 */

.hero {
  position: absolute;
  z-index: 2;
  top: calc(var(--tb-h) + clamp(1rem, 4.5vh, 3.25rem));
  left: 0;
  right: 0;
  width: min(calc(100% - var(--gutter) * 2), var(--maxw));
  margin: 0 auto;
}

.id {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 2.4vw, 2.5rem);
}

.id-photo {
  flex: none;
}

.id-photo img {
  width: 9.75rem;
  height: 12.1875rem;
  object-fit: cover;
  border-radius: 1rem;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 10px 30px -18px rgba(0, 0, 0, 0.35);
}

.id-name {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.25rem 1.1rem;
  font-weight: 600;
}

.id-zh {
  font-family: var(--font-display);
  font-size: 3.5rem;
  line-height: 1.15;
  letter-spacing: 0.04em;
}

.id-en {
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--mute);
}

/* 名字下面一行：ESCP 的 logo、在读的学位、这个专业的排名。整行可以点（去“教育”那一章） */
.id-edu {
  margin-top: 0.45rem;
}

.id-edu a {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.25rem 0.7rem;
  font-size: 1.0625rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--ink);
}

.id-edu img {
  flex: none;
  margin-right: -0.1rem;
}

.id-school,
.id-deg {
  white-space: nowrap;
}

.id-edu i {
  width: 1px;
  height: 0.95em;
  background: var(--line);
}

.id-rk {
  color: var(--ink-2);
}

.id-rk b {
  font-weight: 600;
  color: var(--accent-ink);
}

.id-deg,
.id-rk {
  transition: color calc(0.25s * var(--animation-time));
}

@media (hover: hover) {
  .id-edu a:hover .id-deg { color: var(--accent-ink); }
}

.m-wide .id-edu a.is-tag .id-deg {
  color: var(--accent-ink);
}

/* 名字下面的邮箱：和英文名同一档字重，比标签醒目一点，数字等宽；复制按钮是顶栏那颗的同款 */
.id-mail {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.35rem 0.6rem;
  margin-top: 0.55rem;
}

.id-addr {
  position: relative;
  font-size: 1.1875rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  padding-bottom: 0.1rem;
  background: linear-gradient(var(--line), var(--line)) 0 100% / 100% 1.5px no-repeat;
  transition: color calc(0.2s * var(--animation-time)), background-size calc(0.3s * var(--animation-time)) var(--out);
}

.id-copy {
  position: relative;
  height: 1.875rem;
  padding: 0 0.7rem 0 1.75rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  color: var(--ink-2);
  background: var(--bg-2);
  transition: background calc(0.2s * var(--animation-time)), color calc(0.2s * var(--animation-time));
}

.id-copy::before,
.id-copy::after {
  content: "";
  position: absolute;
  width: 0.5rem;
  height: 0.6rem;
  border: 1.4px solid currentColor;
  border-radius: 2px;
}

.id-copy::before {
  left: 0.7rem;
  top: calc(50% - 0.42rem);
}

.id-copy::after {
  left: 0.9rem;
  top: calc(50% - 0.22rem);
  background: var(--bg-2);
}

.id-copy.is-done span {
  font-size: 0;
}

.id-copy.is-done span::after {
  content: "已复制";
  font-size: 0.8125rem;
}

@media (hover: hover) {
  .id-addr:hover {
    color: var(--accent-ink);
    background-image: linear-gradient(var(--accent), var(--accent));
  }

  .id-copy:hover { background: #e8e8ed; }
}

/* 标签行用自然换行流（li 之间留空格、分隔符挂在上一项的 ::after），
   换行时分隔符永远跟在上一项末尾，不会漂到行首——设计审计 #3 */
.id-main {
  display: block;
  margin-top: 0.85rem;
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.9;
}

.id-main li {
  display: inline;
  white-space: nowrap;
}

.id-main li:not(:last-child)::after {
  content: "";
  display: inline-block;
  width: 1px;
  height: 0.95em;
  margin: 0 0.95rem;
  background: var(--line);
  vertical-align: -0.12em;
}

.id-main li:first-child::before {
  content: "";
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  margin-right: 0.7rem;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.12em;
}

.id-more {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.9375rem;
  color: var(--mute);
  line-height: 1.9;
}

.id-more li {
  display: inline;
  white-space: nowrap;
}

.id-more li:not(:last-child)::after {
  content: "·";
  margin: 0 0.5rem;
  color: #b4b4b9;
}

/* 入场：照片和名字先出来，标签跟着 */
.js .hero .id-photo,
.js .hero .id-name,
.js .hero .id-edu,
.js .hero .id-mail,
.js .hero .id-main,
.js .hero .id-more {
  opacity: 0;
  transform: translateY(10px);
}

.js.is-ready .hero .id-photo,
.js.is-ready .hero .id-name,
.js.is-ready .hero .id-edu,
.js.is-ready .hero .id-mail,
.js.is-ready .hero .id-main,
.js.is-ready .hero .id-more {
  opacity: 1;
  transform: none;
  transition: opacity calc(0.7s * var(--animation-time)) var(--out), transform calc(0.9s * var(--animation-time)) var(--out);
}

.js.is-ready .hero .id-name { transition-delay: calc(0.08s * var(--animation-time)); }
.js.is-ready .hero .id-edu { transition-delay: calc(0.1s * var(--animation-time)); }
.js.is-ready .hero .id-mail { transition-delay: calc(0.12s * var(--animation-time)); }
.js.is-ready .hero .id-main { transition-delay: calc(0.18s * var(--animation-time)); }
.js.is-ready .hero .id-more { transition-delay: calc(0.26s * var(--animation-time)); }

/* ---------------------------------------------------------------- 章节文字（宽屏在左边，跟着镜头换） */

.overview {
  display: none;
}

.chapters {
  position: absolute;
  z-index: 2;
  top: var(--tb-h);
  bottom: 4.25rem;
  left: max(var(--gutter), calc((100% - var(--maxw)) / 2));
  width: min(30rem, 40%);
  /* 容器只排版不挡内容：只有正在展示的那一章（.ch.is-on）吃指针事件，
     否则全景里被盖住的节点（如凯度下发的项目）点不到 */
  pointer-events: none;
}

.ch {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  visibility: hidden;
  pointer-events: none;
  transition: visibility calc(0s * var(--animation-time)) calc(0.35s * var(--animation-time));
}

.ch.is-on {
  visibility: visible;
  pointer-events: auto;
  transition-delay: calc(0s * var(--animation-time));
}

/* 正文进出：干脆利落，不做由虚到实（读的人要的是马上能读） */
.ch > * {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity calc(0.25s * var(--animation-time)) var(--out), transform calc(0.4s * var(--animation-time)) var(--out);
}

.ch.is-on > * {
  opacity: 1;
  transform: none;
  transition: opacity calc(0.4s * var(--animation-time)) var(--out), transform calc(0.55s * var(--animation-time)) var(--out);
}

.ch.is-on > :nth-child(2) { transition-delay: calc(0.03s * var(--animation-time)); }
.ch.is-on > :nth-child(3) { transition-delay: calc(0.06s * var(--animation-time)); }
.ch.is-on > :nth-child(4) { transition-delay: calc(0.09s * var(--animation-time)); }
.ch.is-on > :nth-child(5) { transition-delay: calc(0.12s * var(--animation-time)); }
.ch.is-on > :nth-child(6) { transition-delay: calc(0.15s * var(--animation-time)); }

.ch-kicker {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.55rem;
  font-size: 0.875rem;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

.ch-kicker i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #b4b4b9;
}

.now-dot {
  position: relative;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--accent);
}

.now-dot::after {
  content: "";
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
  animation: pulse calc(2.8s * var(--animation-time)) var(--out) infinite;
}

.ch-now {
  color: var(--accent-ink);
  font-weight: 600;
}

.ch-title {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.2rem 0.85rem;
  margin-top: 0.45rem;
}

.ch-zh {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 2.75rem;
  line-height: 1.15;
}

.ch-en {
  font-size: 1rem;
  font-weight: 500;
  color: var(--mute);
}

.ch-role {
  margin-top: 0.55rem;
  font-size: 1.0625rem;
  font-weight: 500;
  color: var(--ink-2);
}

.ch-lede {
  margin-top: 1.1rem;
  font-size: 1.0625rem;
  line-height: 1.75;
  color: var(--ink-2);
}

.ch-points {
  display: grid;
  gap: 0.95rem;
  margin-top: 1.4rem;
}

.ch-points > div {
  display: grid;
  grid-template-columns: 4.25rem 1fr;
  gap: 0.75rem;
  padding-top: 0.95rem;
  border-top: 1px solid var(--hair);
}

.ch-points dt {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent-ink);
  padding-top: 0.12rem;
}

.ch-lede,
.ch-points dd,
.pj-points li,
.kp-panel li {
  text-wrap: pretty;
}

.ch-points dd {
  font-size: 0.96875rem;
  line-height: 1.75;
  color: var(--ink-2);
}

/* 左侧常驻任职信息；详情面板共用最大高度。 */
.kp { display: grid; margin-top: 1.4rem; }
.kp-panel { align-self: start; }
.kp-overview .ch-points { margin-top: 0; }
.kp-panel:not(.kp-overview) { border-top: 1px solid var(--hair); padding-top: 0.8rem; }
.kp-back { font-size: 0.8125rem; color: var(--mute); padding: 0.15rem 0; margin-bottom: 0.7rem; }
.kp-back:hover { color: var(--ink); }
.kp-ctx { color: var(--mute); font-size: 0.8125rem; margin-bottom: 0.55rem; }
.kp-panel .pj-time { margin-top: 0.25rem; }
.pj-heading { font-size: 0.9375rem; font-weight: 600; margin: 1.6rem 0 0.65rem; color: var(--ink-2); }
.pj-panels { display: grid; }
.m-tall .kp-panel:not(.kp-overview) { display: none; }
.m-tall .kp-overview { opacity: 1; visibility: visible; transform: none; pointer-events: auto; }
@media (min-width: 1000px) and (max-height: 820px) {
  .m-wide .kp { margin-top: 1rem; }
  .m-wide .kp-back { margin-bottom: 0.5rem; }
}

/* 凯度：四个并行项目 */
.pj {
  margin-top: 1.35rem;
}

.pj-tabs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-bottom: 1px solid var(--line);
}

.pj-tab {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  padding: 0.55rem 0.2rem 0.6rem;
  font-size: 0.8125rem;
  color: var(--mute);
  border-radius: 0.5rem 0.5rem 0 0;
  transition: color calc(0.2s * var(--animation-time)), background calc(0.2s * var(--animation-time));
}

.pj-tab::after {
  content: "";
  position: absolute;
  left: 18%;
  right: 18%;
  bottom: -1px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform calc(0.35s * var(--animation-time)) var(--out);
}

.pj-tab[aria-selected="true"] {
  color: var(--ink);
  font-weight: 600;
}

.pj-tab[aria-selected="true"]::after {
  transform: scaleX(1);
}

.pj-logo {
  height: 1.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* logo 一律保持品牌原色；选中靠字重、颜色和下划线区分 */
@media (hover: hover) {
  .pj-tab:hover { color: var(--ink); background: rgba(0, 0, 0, 0.025); }
}

.pj-panel {
  padding-top: 0.95rem;
  min-height: 8.75rem;
}

@keyframes swapIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}

.pj-title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.6rem;
  font-size: 1.0625rem;
  font-weight: 600;
}

.pj-sub {
  font-weight: 500;
  color: var(--ink-2);
}

.pj-time {
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

.pj-points li {
  position: relative;
  margin-top: 0.45rem;
  padding-left: 1.05rem;
  font-size: 0.9375rem;
  line-height: 1.7;
  color: var(--ink-2);
}

.pj-points li::before {
  content: "";
  position: absolute;
  left: 0.1rem;
  top: 0.68em;
  width: 0.34rem;
  height: 0.34rem;
  border-radius: 50%;
  border: 1.5px solid var(--accent);
}

/* 教育：和别的章同一套写法。标题“教育”，下面两条，一所学校一条：校名、学位、时间地点、两行排名。
   宽屏每条左边一道槽，右边演到哪所学校的榜单，哪一条的槽里长出细线（和晶澳、IDC、拜耳同一套记号）；
   手机 logo 放在校名右边 */
.ch-label {
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--accent-ink);
  margin-bottom: 1.1rem;
}

.ed-list {
  gap: 1.15rem;
}

.ed-list > .sc {
  position: relative;
  display: block;
  padding-top: 1.15rem;
}

.ch-points.ed-list.is-linked > .sc::before,
.ch-points.ed-list.is-linked > .sc::after {
  top: 1.4rem;
}

.ed-list dt.sc-name {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.1rem 0.6rem;
  padding: 0;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
}

.ed-list .sc-en {
  font-family: var(--font);
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--mute);
}

.m-wide .ch-points.ed-list.is-linked dt .sc-en {
  background: none;
}

.ed-list dd {
  margin: 0;
  font-size: 1rem;
  line-height: 1.6;
}

.sc-degree {
  margin-top: 0.4rem;
  font-weight: 500;
  color: var(--ink-2);
}

.sc-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.1rem;
  font-size: 0.875rem;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

.sc-meta i {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #b4b4b9;
}

.sc-now {
  font-weight: 600;
  color: var(--accent-ink);
}

/* 两行排名：榜单名、名次、榜单年份三列对齐 */
.sc-ranks {
  margin: 0.65rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
  line-height: 1.65;
}

.sc-ranks li {
  display: grid;
  grid-template-columns: 8.75rem 4.75rem auto;
  align-items: baseline;
  column-gap: 0.6rem;
}

.rk-label {
  color: var(--ink-2);
}

.sc-ranks b {
  justify-self: start;
  font-weight: 600;
  color: var(--ink);
}

.rk-y {
  font-size: 0.8125rem;
  color: var(--mute-2);
  font-variant-numeric: tabular-nums;
}

.m-wide .sc-logo { display: none; }
.m-tall .ch-points.ed-list.is-linked > .sc::before,
.m-tall .ch-points.ed-list.is-linked > .sc::after { display: none; }
.m-tall .ed-list dt.sc-name,
.m-tall .sc-degree,
.m-tall .sc-meta { padding-right: 5.5rem; }
.m-tall .ed-list dt.sc-name { font-size: 1.3rem; }
.m-tall .sc-logo { position: absolute; right: 0; top: 1.15rem; display: flex; align-items: center; justify-content: flex-end; width: 5rem; height: 3.25rem; }
.m-tall .sc-logo img { max-width: 100%; height: auto; }

/* 手机版正文里的说明图和项目切换，宽屏用的是线上那一份 */
.m-wide .mv-fig,
.m-wide .mv-works,
.m-wide .ch--kantar .pj {
  display: none;
}

/* ---------------------------------------------------------------- 结尾：联系 */

.outro {
  position: absolute;
  z-index: 2;
  top: calc(var(--tb-h) + clamp(1.5rem, 6vh, 4rem));
  left: max(var(--gutter), calc((100% - var(--maxw)) / 2));
  opacity: 0;
  visibility: hidden;
}

.ct-mail {
  display: inline-block;
  margin-top: 0.35rem;
  padding-bottom: 0.2rem;
  font-size: 2.25rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  border-bottom: 1.5px solid var(--ink);
  font-variant-numeric: tabular-nums;
  transition: color calc(0.2s * var(--animation-time)), border-color calc(0.2s * var(--animation-time));
}

.ct-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.1rem;
}

.ct-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: 2.375rem;
  padding: 0 1.05rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: #fff;
  font-size: 0.9375rem;
  transition: border-color calc(0.2s * var(--animation-time)), color calc(0.2s * var(--animation-time));
}

.ct-btn.is-done {
  border-color: var(--accent);
  color: var(--accent-ink);
}

.ext {
  font-size: 0.8em;
  color: var(--mute);
}

@media (hover: hover) {
  .ct-mail:hover { color: var(--accent-ink); border-color: var(--accent); }
  .ct-btn:hover { border-color: var(--ink); }
}

/* ---------------------------------------------------------------- 悬停提示 */

.tip {
  position: absolute;
  z-index: 5;
  left: 0;
  top: 0;
  max-width: 19rem;
  padding: 0.55rem 0.8rem 0.6rem;
  border-radius: 0.7rem;
  background: rgba(29, 29, 31, 0.94);
  color: #fff;
  font-size: 0.8125rem;
  line-height: 1.5;
  opacity: 0;
  pointer-events: none;
  transition: opacity calc(0.18s * var(--animation-time));
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.4);
}

.tip.is-on {
  opacity: 1;
}

.tip-t {
  font-weight: 600;
  white-space: nowrap;
}

.tip-t span {
  margin-left: 0.5rem;
  font-weight: 400;
  color: rgba(255, 255, 255, 0.6);
}

.tip-x {
  margin-top: 0.15rem;
  color: rgba(255, 255, 255, 0.86);
}

/* ---------------------------------------------------------------- 底部导航 */

.dock {
  position: fixed;
  z-index: 40;
  left: 50%;
  bottom: max(1rem, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  opacity: 0;
  transition: opacity calc(0.5s * var(--animation-time)) calc(0.6s * var(--animation-time));
}

.is-ready .dock {
  opacity: 1;
}

.dk-track {
  position: relative;
  display: flex;
  padding: 0.25rem;
  border-radius: 999px;
  background: rgba(29, 29, 31, 0.9);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 8px 24px -10px rgba(0, 0, 0, 0.35);
}

.dk-track button {
  position: relative;
  z-index: 1;
  height: 1.875rem;
  padding: 0 0.72rem;
  border-radius: 999px;
  font-size: 0.78125rem;
  color: rgba(255, 255, 255, 0.6);
  white-space: nowrap;
  transition: color calc(0.25s * var(--animation-time));
}

.dk-track button.is-on {
  color: #fff;
}

.dk-pos {
  position: absolute;
  top: 0.25rem;
  left: 0;
  height: 1.875rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.15);
  transition: transform calc(0.45s * var(--animation-time)) var(--out), width calc(0.45s * var(--animation-time)) var(--out);
}

@media (hover: hover) {
  .dk-track button:hover { color: #fff; }
}

/* ---------------------------------------------------------------- 提示条、页脚 */

.toast {
  position: fixed;
  z-index: 60;
  left: 50%;
  top: calc(var(--tb-h) + 0.6rem);
  transform: translate(-50%, -8px);
  padding: 0.6rem 1rem;
  border-radius: 0.75rem;
  background: var(--ink);
  color: #fff;
  font-size: 0.875rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity calc(0.25s * var(--animation-time)), transform calc(0.4s * var(--animation-time)) var(--out);
}

.toast.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

.foot {
  width: min(calc(100% - var(--gutter) * 2), var(--maxw));
  margin: 0 auto;
  padding: 1.5rem 0 5.5rem;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 1.5rem;
  border-top: 1px solid var(--hair);
  font-size: 0.8125rem;
  color: var(--mute);
}

.nojs {
  max-width: 44rem;
  margin: 0 auto;
  padding: 5rem 1.5rem;
  line-height: 1.8;
}

/* ---------------------------------------------------------------- 矮一点的桌面窗口 */

@media (min-width: 820px) and (max-height: 820px) {
  .id-photo img { width: 8.5rem; height: 10.625rem; }
  .id-zh { font-size: 3rem; }
  .id-main { margin-top: 0.85rem; }
  .ch-zh { font-size: 2.375rem; }
  .ch-lede { margin-top: 0.85rem; font-size: 1rem; line-height: 1.7; }
  .ch-points { margin-top: 1rem; gap: 0.7rem; }
  .ch-points > div { padding-top: 0.7rem; }
  .ch-points.is-linked > div::before,
  .ch-points.is-linked > div::after { top: 0.7rem; }
  .m-wide .work-hint--wide { margin-top: 0.95rem; }
  .ch-points dd { font-size: 0.9375rem; line-height: 1.65; }
  .pj { margin-top: 1rem; }
  .pj-panel { min-height: 8rem; padding-top: 0.75rem; }
  .pj-points li { line-height: 1.6; }
}

/* 矮屏收紧段间留白，窄桌面把小标题并入首行，给正文留足宽度。 */
@media (max-height: 720px) {
  .m-wide .ch--jasolar .ch-points { margin-top: 0.8rem; gap: 0.45rem; }
  .m-wide .ch--jasolar .ch-points > div { padding-top: 0.45rem; }
  .m-wide .ch--jasolar .ch-points.is-linked > div::before,
  .m-wide .ch--jasolar .ch-points.is-linked > div::after { top: 0.45rem; }
}

/* 再矮一点（1366×768 笔记本去掉浏览器栏约 650 高）：晶澳三条经历行距再收一点，保证仍是整页 */
@media (max-height: 680px) {
  .m-wide .ch--jasolar .ch-lede { line-height: 1.6; }
  .m-wide .ch--jasolar .ch-points dd { line-height: 1.55; }
}

@media (max-width: 1200px) {
  .m-wide .ch--jasolar .ch-points > div { display: block; }
  .m-wide .ch--jasolar .ch-points dt { display: inline; margin-right: 0.65rem; }
  .m-wide .ch--jasolar .ch-points dd { display: inline; }
}

/* ---------------------------------------------------------------- 手机与竖屏：自然往下读 */

.m-tall .journey {
  height: auto !important;
}

.m-tall .stage {
  position: static;
  height: auto;
  overflow: visible;
}

.m-tall .viewport,
.m-tall .tip {
  display: none;
}

.m-tall .hero {
  position: static;
  transform: none !important;
  width: auto;
  padding: calc(var(--tb-h) + 1.5rem) var(--gutter) 0;
  opacity: 1 !important;
  visibility: visible !important;
}

.m-tall .id {
  gap: 1.1rem;
  align-items: flex-end;
}

.m-tall .id-photo img {
  width: 7rem;
  height: 8.75rem;
  border-radius: 0.875rem;
}

.m-tall .id-name {
  flex-direction: column;
  gap: 0.1rem;
}

.m-tall .id-zh {
  font-size: 2.375rem;
}

.m-tall .id-en {
  font-size: 1rem;
}

.m-tall .id-edu {
  margin-top: 0.35rem;
}

.m-tall .id-edu a {
  gap: 0.15rem 0.5rem;
  font-size: 0.875rem;
}

.m-tall .id-edu img {
  height: 1.05rem;
  width: auto;
}

/* 手机上排名单独一行，不在行尾留一根竖线 */
.m-tall .id-edu i {
  display: none;
}

.m-tall .id-rk {
  flex-basis: 100%;
}

.m-tall .id-mail {
  margin-top: 0.45rem;
  gap: 0.3rem 0.5rem;
}

.m-tall .id-addr {
  font-size: 0.9375rem;
}

/* 手机上顶栏紧挨着就有复制，名字下面只留可以点的邮箱，免得复制按钮折到下一行 */
.m-tall .id-copy {
  display: none;
}

.m-tall .id-main {
  margin-top: 0.7rem;
  font-size: 1rem;
}

.m-tall .id-main li:not(:last-child)::after {
  margin: 0 0.6rem;
}

.m-tall .id-main li:first-child::before {
  margin-right: 0.5rem;
}

.m-tall .id-more {
  display: flex;
  flex-wrap: wrap;
  gap: 0 0.85rem;
  margin-top: 0.35rem;
  font-size: 0.8125rem;
}

.m-tall .id-more li:not(:last-child)::after {
  content: none;
}

.m-tall .id-text {
  padding-bottom: 0.15rem;
}

/* 手机概览：一条竖线，从现在往回 */
.m-tall .overview {
  display: block;
  padding: 2rem var(--gutter) 0;
}

.ov {
  position: relative;
}

.ov::before,
.ov::after {
  content: "";
  position: absolute;
  left: 0.6875rem;
  top: 1.6rem;
  bottom: 1.6rem;
  width: 2px;
  margin-left: -1px;
  background: var(--ink);
}

/* 竖线上流动的光（从过去流向现在，所以是自下往上） */
.ov::after {
  background: linear-gradient(to top, transparent 0%, var(--accent) 6%, transparent 13%) 0 0 / 100% 300% repeat-y;
  animation: ovFlow calc(9s * var(--animation-time)) linear infinite;
  opacity: 0.9;
}

@keyframes ovFlow {
  from { background-position: 0 0; }
  to { background-position: 0 -300%; }
}

.ov-it {
  position: relative;
}

.ov-a {
  display: grid;
  grid-template-columns: 1.375rem 4.75rem 1fr;
  align-items: center;
  gap: 0.85rem;
  padding: 0.7rem 0;
}

.ov-dot {
  position: relative;
  z-index: 1;
  width: 1.125rem;
  height: 1.125rem;
  margin-left: 0.125rem;
  border-radius: 50%;
  border: 3px solid var(--ink);
  background: var(--bg);
}

.ov--edu .ov-dot {
  border-color: #8e8e93;
}

.ov--now .ov-dot {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 5px var(--accent-soft);
}

.ov-logo {
  display: flex;
  align-items: center;
  height: 2rem;
}

.ov-lbl {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ov-name {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem 0.5rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
}

.ov-name em {
  font-family: var(--font);
  font-style: normal;
  font-weight: 500;
  font-size: 0.8125rem;
  color: var(--mute);
  padding-left: 0.5rem;
  border-left: 1.5px solid var(--line);
}

.ov--edu .ov-name em {
  flex-basis: 100%;
  padding-left: 0;
  border-left: 0;
}

.ov-name b {
  font-family: var(--font);
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--accent-ink);
  background: var(--accent-soft);
  padding: 0 0.35rem;
  border-radius: 0.3rem;
}

.ov-time {
  font-size: 0.8125rem;
  color: var(--mute);
  font-variant-numeric: tabular-nums;
}

/* 凯度：同期并行的四个项目。和宽屏同一个结构：四条细线从凯度下面并排垂下，逐条转进一行 */
/* 凯度的 logo 往右让一点，给从节点出来的线束留出位置 */
.ov--fork > .ov-a .ov-logo {
  padding-left: 0.6rem;
}

.ov-fork {
  position: relative;
  margin: -0.35rem 0 0.35rem 2.45rem;
  padding-left: 2.25rem;
}

.ov-bundle {
  position: absolute;
  pointer-events: none;
  left: 0;
  top: 0;
  width: 2rem;
  height: 100%;
  overflow: visible;
}

.ov-bundle path {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.4;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.ov-pj {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  height: 2.25rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-2);
}

.ov-pj-logo {
  width: 2.5rem;
  display: flex;
  justify-content: center;
}

/* 手机正文 */
.m-tall .chapters {
  position: static;
  width: auto;
  padding: 1rem var(--gutter) 0;
}

.m-tall .ch {
  position: static;
  display: block;
  visibility: visible;
  pointer-events: auto;
  padding: 2.75rem 0 0.25rem;
  scroll-margin-top: calc(var(--tb-h) + 0.75rem);
}

.m-tall .ch + .ch {
  margin-top: 1rem;
  border-top: 1px solid var(--hair);
}

.m-tall .ch > * {
  opacity: 1;
  transform: none;
  filter: none;
}

.m-tall .ch-zh {
  font-size: 2.125rem;
}

.m-tall .ch-points > div {
  grid-template-columns: 1fr;
  gap: 0.2rem;
}

.m-tall .pj-tabs {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.m-tall .pj-tab {
  font-size: 0.75rem;
}

/* 晶澳、拜耳、IDC（手机）：同一块图放在正文里，按栏宽缩放；字有下限 */
.mv-works,
.mv-fig {
  margin-top: 1.6rem;
  container-type: inline-size;
}

.mv-works .jw,
.mv-fig .jw {
  font-size: min(16px, 100cqw / 24.2);
}

.m-tall .mv-fig .jw-steps { font-size: max(0.8125em, 12px); }
.m-tall .mv-fig .dr-h b { font-size: max(0.875em, 11.5px); }
.m-tall .mv-fig .dr-h i { font-size: max(0.8125em, 10.5px); }

.m-tall .mv-works .jw-tab { font-size: max(0.8125em, 13px); }
.m-tall .mv-works .jw-steps { font-size: max(0.8125em, 12px); }
.m-tall .mv-works .jw-lab { font-size: max(0.75em, 11px); }
.m-tall .mv-works .jc-raw { font-size: max(0.625em, 9.5px); }
.m-tall .mv-works .jc-l0,
.m-tall .mv-works .jc-l1,
.m-tall .mv-works .jc-l2,
.m-tall .mv-works .jc-t { font-size: max(0.6875em, 10.5px); }
.m-tall .mv-works .jw-lab--url,
.m-tall .mv-works .jw-lab--btn { font-size: max(0.625em, 10px); }

.m-tall .outro {
  position: static;
  opacity: 1 !important;
  visibility: visible !important;
  transform: none !important;
  padding: 3.5rem var(--gutter) 2.5rem;
}

.m-tall .ct-mail {
  font-size: 1.5rem;
}

.m-tall .foot {
  padding-bottom: 6rem;
}

.m-tall .dock {
  max-width: calc(100% - 1rem);
}

.m-tall .dk-track {
  overflow-x: auto;
  scrollbar-width: none;
}

.m-tall .dk-track::-webkit-scrollbar {
  display: none;
}

.m-tall .dk-track button {
  height: 2.125rem;
  padding: 0 0.62rem;
  font-size: 0.75rem;
}

.m-tall .dk-pos {
  height: 2.125rem;
}

@media (min-width: 700px) {
  html.m-tall {
    font-size: 106.25%;
  }

  .m-tall .hero,
  .m-tall .overview,
  .m-tall .chapters,
  .m-tall .outro,
  .m-tall .foot {
    max-width: calc(40rem + var(--gutter) * 2);
    margin-left: auto;
    margin-right: auto;
  }

  .m-tall .foot {
    max-width: 40rem;
  }
}

@media (max-width: 600px) {
  :root {
    --tb-h: 3.25rem;
  }

  .tb-name .tb-en {
    display: none;
  }

  .tb-addr {
    font-size: 0.8125rem;
    padding: 0.3rem 0.25rem;
  }

  .tb-copy {
    padding: 0 0.6rem 0 1.6rem;
    font-size: 0.75rem;
  }

  .tb-copy::before { left: 0.6rem; }
  .tb-copy::after { left: 0.8rem; }
}

@media (max-width: 380px) {
  .m-tall .id-photo img { width: 6rem; height: 7.5rem; }
  .m-tall .id-main { font-size: 0.9375rem; }
  .m-tall .id-zh { font-size: 2.125rem; }
  .tb-name { display: none; }
}

/* ---------------------------------------------------------------- 减少动态效果 */

/* ---------------------------------------------------------------- R5：整页翻、图文联动、到站动作 */

/* 宽屏没有可以往下滚的页脚：同样的两句放在“联系”这一页的底部，分在导航两边 */
.sfoot {
  display: none;
}

.m-wide .foot {
  display: none;
}

.m-wide .sfoot {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: calc(max(1rem, env(safe-area-inset-bottom)) + 0.55rem);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1rem;
  width: min(calc(100% - var(--gutter) * 2), var(--maxw));
  transform: translateX(-50%);
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--mute-2);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

.m-wide .sfoot > span {
  max-width: calc(50% - 12rem);
}

.m-wide .sfoot > span:last-child {
  text-align: right;
}

.foot .cl,
.sfoot .cl {
  display: inline-block;
}

/* 宽屏上手指划动由页面自己接（整页翻），只保留双指缩放 */
.m-wide .stage {
  touch-action: pinch-zoom;
}

/* 光点上的小日期：翻页途中，数字一列列滚到这一站的时间 */
.tchip {
  position: absolute;
  z-index: 3;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  height: 1.5rem;
  padding: 0 0.6rem;
  border-radius: 999px;
  background: rgba(29, 29, 31, 0.9);
  box-shadow: 0 6px 16px -8px rgba(0, 0, 0, 0.4);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity calc(0.25s * var(--animation-time)) var(--out);
}

.tchip.is-on {
  opacity: 1;
  transition-delay: calc(0.16s * var(--animation-time));
}

/* 每一列上下边缘渐隐：滚动途中露出的半个数字淡掉，不会读成别的字 */
.tc-col {
  display: inline-block;
  height: 1.15em;
  line-height: 1.15em;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(transparent, #000 16%, #000 84%, transparent);
  mask-image: linear-gradient(transparent, #000 16%, #000 84%, transparent);
}

.tc-strip {
  display: block;
  transition: transform calc(0.5s * var(--animation-time)) cubic-bezier(0.2, 0.8, 0.2, 1);
}

.tc-strip i {
  display: block;
  height: 1.15em;
  font-style: normal;
}

.tc-dot {
  padding: 0 0.04em;
}

.m-tall .tchip {
  display: none;
}

/* 正文里和说明图对应的几句：平时下面只有一道很淡的点线（像注脚，不像链接）；
   可见正文按独立阅读节奏轮流扫强调色细线，扫完就收；主动指上去，这句话和图里那部分一起亮 */
.lk {
  background-image: linear-gradient(var(--accent), var(--accent)), repeating-linear-gradient(90deg, rgba(29, 29, 31, 0.3) 0 2px, transparent 2px 5px);
  background-repeat: no-repeat;
  background-position: 0 100%, 0 100%;
  background-size: 0% 2px, 100% 1px;
  transition: color calc(0.25s * var(--animation-time)), background-size calc(0.25s * var(--animation-time)) var(--out);
}

.lk.is-sweep {
  animation: lkOnce calc(1.4s * var(--sweep-time, 1)) var(--out) calc((var(--lko, 0) * 0.3s) * var(--sweep-time, 1)) both;
}

.m-wide .ch.is-on .lk.is-lk {
  animation: none;
  color: var(--accent-ink);
  background-size: 100% 2px, 0% 1px;
}

@keyframes lkOnce {
  0% { background-size: 0% 2px, 100% 1px; background-position: 0 100%, 0 100%; }
  40% { background-size: 100% 2px, 100% 1px; background-position: 0 100%, 0 100%; }
  55% { background-size: 100% 2px, 100% 1px; background-position: 100% 100%, 0 100%; }
  100% { background-size: 0% 2px, 100% 1px; background-position: 100% 100%, 0 100%; }
}

/* 标签隐藏时暂停正文强调；作品图生命周期由脚本管理。 */
.is-paused .lk {
  animation-play-state: paused !important;
}

/* 首屏标签：鼠标移上去，这个词变成强调色，时间线上对应的几站亮起来 */
.m-wide .id-main li[data-tag],
.m-wide .id-more li[data-tag] {
  cursor: default;
  transition: color calc(0.25s * var(--animation-time));
}

.m-wide .id-main li.is-tag,
.m-wide .id-more li.is-tag {
  color: var(--accent-ink);
}

/* 说明图里的数字：数的时候宽度不变 */
.cnt {
  display: inline-block;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    /* 禁止过渡本身，避免默认 all 让同步字号测量拿到过渡前的宽度。 */
    transition: none !important;
  }

  .ov::after {
    display: none;
  }
}
