/* ============================================================
   英特费斯 INTERFACE · 交互细节层 fx.css
   排在 aw.css / vibe.css 之后，只新增类名与状态，不覆写既有版式。
   原则：动效要小、要快、要有物理感——位移不超过 8px，时长 .18–.55s，
   缓动统一走 --ease；任何一条在 prefers-reduced-motion 下都必须能整条关掉。
   ============================================================ */

:root {
  --fx-ease: cubic-bezier(0.22, 0.65, 0.25, 1);
  --fx-spring: cubic-bezier(0.34, 1.42, 0.44, 1);
}

/* ============================================================
   01 · 选中色 / 滚动条 / 焦点环——三处「浏览器默认」的品牌化
   ============================================================ */

::selection { background: var(--accent); color: var(--ink); text-shadow: none; }
::-moz-selection { background: var(--accent); color: var(--ink); }
/* 深色区块里青柠底墨字仍然读得出来，不另做反相 */

/* 细滚动条：轨道透明、滑块半墨，hover 转实。Firefox 走 scrollbar-* */
/* 不加 scrollbar-gutter：全站版式是按「容器宽 = 100% − 2×padding」实测定的，
   常驻留白会把内容宽整体削掉 11px，栅格测量对不上 */
@supports selector(::-webkit-scrollbar) {
  ::-webkit-scrollbar { width: 11px; height: 11px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: rgba(34, 34, 34, 0.22);
    border: 3px solid transparent;
    border-radius: 99px;
    background-clip: content-box;
  }
  ::-webkit-scrollbar-thumb:hover { background: rgba(34, 34, 34, 0.42); background-clip: content-box; }
  ::-webkit-scrollbar-corner { background: transparent; }
}
html { scrollbar-color: rgba(34, 34, 34, 0.28) transparent; scrollbar-width: thin; }

/* 统一焦点环：紫罗兰实线 + 一圈淡晕，键盘用户看得见落点，鼠标点击不出现 */
:where(a, button, [tabindex], input, select, textarea):focus-visible {
  outline: 2px solid var(--violet);
  outline-offset: 3px;
  border-radius: var(--r-sm);
  box-shadow: 0 0 0 6px rgba(94, 106, 210, 0.16);
  transition: box-shadow 0.18s var(--fx-ease);
}

/* ============================================================
   02 · 页面转场帘：加载时揭开，站内跳转时落下
   一层地色的薄幕，从下沿收起（.is-up）/ 从上沿落下（.is-down）。
   幕布本身不拦事件（pointer-events:none），落幕那 320ms 里页面还能滚。
   ============================================================ */

.fx-veil {
  position: fixed;
  inset: 0;
  z-index: 999;
  pointer-events: none;
  background: var(--ground);
  transform-origin: 50% 100%;
  transition: transform 0.52s cubic-bezier(0.76, 0, 0.24, 1), opacity 0.36s linear;
}
.fx-veil.is-up { transform: scaleY(0); opacity: 0; }
.fx-veil.is-down {
  transform-origin: 50% 0;
  transform: scaleY(1);
  opacity: 1;
  transition: transform 0.26s cubic-bezier(0.65, 0, 0.35, 1), opacity 0.16s linear;
}
/* 幕布中央的一粒品牌点：落幕时才追上来，收幕时先走 */
.fx-veil::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  transform: scale(0.2);
  transition: opacity 0.2s linear, transform 0.4s var(--fx-spring);
}
.fx-veil.is-down::after { opacity: 1; transform: scale(1); transition-delay: 0.1s; }

/* 03 · 光标伴随环——已撤（2026-09-06）。指针一律用系统原生箭头，不做替换、不做跟随件。 */

/* ============================================================
   04 · 按压涟漪：从指针落点扩散的一圈墨晕
   ============================================================ */

.fx-ripple {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0);
  background: currentColor;
  opacity: 0.16;
  animation: fx-ripple 0.62s var(--fx-ease) forwards;
}
@keyframes fx-ripple {
  to { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}

/* ============================================================
   05 · 卡片高光：指针在卡上时，一层白色径向光晕跟着指针走
   2026-09-06 用户不要倾斜——原来这里整张卡还会朝指针侧转 ±4.8deg，已删。
   位置由 JS 写 --mx / --my；**这里不许再出现 rotate / skew / 3D 透视**。
   ============================================================ */

.fx-sheen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.35s var(--fx-ease);
  background: radial-gradient(
    260px circle at var(--mx, 50%) var(--my, 50%),
    rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 62%);
  mix-blend-mode: overlay;
}
.fx-sheen:hover::after { opacity: 1; }

/* ============================================================
   06 · 图片揭幕：进场时自下而上抹开，同时从 1.06 收到 1
   包一层 .fx-mask（JS 自动加），裁切在外层，缩放在图片自身。
   ============================================================ */

.fx-mask {
  display: block;
  overflow: hidden;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 0.85s cubic-bezier(0.62, 0.05, 0.2, 1);
}
.fx-mask.is-shown { clip-path: inset(0 0 0 0); }
.fx-mask > img,
.fx-mask > picture > img {
  transform: scale(1.07);
  transition: transform 1.1s cubic-bezier(0.62, 0.05, 0.2, 1);
}
.fx-mask.is-shown > img,
.fx-mask.is-shown > picture > img { transform: scale(1); }

/* 图片没解码完时的呼吸底：避免灰块硬切 */
.fx-mask::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, var(--grey-2) 30%, #f4f4f4 50%, var(--grey-2) 70%) 0 0 / 240% 100%;
  animation: fx-shimmer 1.5s linear infinite;
  opacity: 0;
  transition: opacity 0.4s linear;
  pointer-events: none;
}
.fx-mask.is-loading { position: relative; }
.fx-mask.is-loading::before { opacity: 1; }
@keyframes fx-shimmer { to { background-position: -240% 0; } }

/* ============================================================
   07 · 行内文字链接：下划线自左扫入、离开自右收回
   只给正文里的裸链接（.fx-ul 由 JS 挑出来，避开卡片 / 导航 / 按钮）
   ============================================================ */

.fx-ul {
  background-image: linear-gradient(var(--violet), var(--violet));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 1px;
  transition: background-size 0.34s var(--fx-ease), color 0.25s var(--fx-ease);
}
.fx-ul:hover,
.fx-ul:focus-visible { background-size: 100% 1px; color: var(--violet); }
.fx-ul.is-out { background-position: 100% 100%; }

/* ============================================================
   08 · 动态行：缩略图跟着光标浮出 + 行内容右挪 + 尾部箭头
   ============================================================ */

.fx-peek {
  position: fixed;
  left: 0;                       /* 不写就落在流内的静态位置上——fixed 元素的 auto 偏移取的是
                                    「它本该在文档里的地方」，会跑到 body 末尾去 */
  top: 0;
  z-index: 60;
  width: 232px;
  aspect-ratio: 16 / 10;
  border-radius: 10px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
  /* 位移写在 transform，缩放走同名的独立属性——两者叠加而不是互相覆盖，
     所以 transform 里不能再出现 scale()。缩略图曾经是歪着浮出来的（rotate: -3deg），
     2026-09-06 用户不要倾斜，改成正着弹出。 */
  transform: translate3d(var(--x, 0px), var(--y, 0px), 0) translate(-50%, -50%);
  scale: 0.86;
  transition: opacity 0.26s var(--fx-ease), scale 0.36s var(--fx-spring);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.18);
  background: var(--grey-2);
  will-change: transform;
}
.fx-peek img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fx-peek.is-on { opacity: 1; scale: 1; }

/* 行本体：hover 时日期与标题一起右挪一格，尾部推出一个箭头 */
.news-row { position: relative; }
.news-row::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--violet);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 0.34s var(--fx-ease);
}
.news-row:hover::before,
.news-row:focus-visible::before { transform: scaleY(1); transform-origin: 50% 0; }
.news-row .news-row__date,
.news-row .news-row__title { transition: transform 0.38s var(--fx-ease), color 0.28s var(--fx-ease); }
.news-row:hover .news-row__date { transform: translateX(10px); }
.news-row:hover .news-row__title { transform: translateX(14px); }
/* 0×0 的行内锚点：不进入行盒高度，标题基线不动，分类标签就不会被挤下一行 */
.fx-row-go {
  position: relative;
  display: inline-block;
  width: 0;
  height: 0;
  overflow: visible;
  vertical-align: baseline;
}
.fx-row-go__k {
  position: absolute;
  left: 9px;
  top: -0.72em;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--ink);
  opacity: 0;
  transform: translateX(-8px) scale(0.6);
  transition: opacity 0.28s var(--fx-ease), transform 0.34s var(--fx-spring);
}
.fx-row-go__k svg { width: 11px; height: 11px; }
.news-row:hover .fx-row-go__k,
.news-row:focus-visible .fx-row-go__k { opacity: 1; transform: translateX(0) scale(1); }

/* ============================================================
   09 · 回到顶部：一圈跟着阅读进度长的环
   ============================================================ */

/* 靠左下角：右下角已经被 AI 客服的浮标（chat.css，z-index 984）和机器人占着，
   再堆一颗按钮既会被压在下面点不着，也把那个角挤成一团。 */
.fx-top {
  position: fixed;
  left: 26px;
  bottom: 26px;
  z-index: 70;
  width: 48px;
  height: 48px;
  border: 0;
  padding: 0;
  border-radius: 50%;
  background: var(--card);
  color: var(--ink);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.13);
  cursor: pointer;
  display: grid;
  place-items: center;
  opacity: 0;
  transform: translateY(14px) scale(0.86);
  pointer-events: none;
  transition: opacity 0.3s var(--fx-ease), transform 0.42s var(--fx-spring), background-color 0.25s;
}
.fx-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.fx-top:hover { background: var(--ink); color: #fff; }
.fx-top svg.fx-top__ico { width: 15px; height: 15px; position: relative; z-index: 1; transition: transform 0.3s var(--fx-ease); }
.fx-top:hover svg.fx-top__ico { transform: translateY(-2px); }
.fx-top__ring { position: absolute; inset: 0; width: 48px; height: 48px; transform: rotate(-90deg); }
.fx-top__ring circle {
  fill: none;
  stroke-width: 1.6;
  cx: 24; cy: 24; r: 22.4;
}
.fx-top__ring .t { stroke: rgba(34, 34, 34, 0.1); }
.fx-top__ring .p {
  stroke: var(--violet);
  stroke-linecap: round;
  stroke-dasharray: 140.8;
  stroke-dashoffset: calc(140.8 - 140.8 * var(--p, 0));
  transition: stroke-dashoffset 0.12s linear;
}
@media (max-width: 760px) { .fx-top { left: 14px; bottom: 14px; width: 42px; height: 42px; }
  .fx-top__ring, .fx-top__ring circle { width: 42px; height: 42px; }
}

/* ============================================================
   10 · 右缘章节轨：每个 <section> 一颗点，当前节拉成短杠
   ============================================================ */

.fx-rail {
  position: fixed;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 55;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-end;
  opacity: 0;
  transition: opacity 0.35s var(--fx-ease);
  pointer-events: none;
}
.fx-rail.is-on { opacity: 1; pointer-events: auto; }
.fx-rail__d {
  position: relative;
  width: 22px;
  height: 16px;
  border: 0;
  background: none;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.fx-rail__d::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 99px;
  background: rgba(34, 34, 34, 0.24);
  transition: width 0.4s var(--fx-spring), background-color 0.3s var(--fx-ease);
}
.fx-rail__d:hover::after { background: rgba(34, 34, 34, 0.5); width: 12px; }
.fx-rail__d.is-cur::after { width: 20px; background: var(--ink); }
/* 悬停冒出的节名，从右侧滑出 */
.fx-rail__t {
  position: absolute;
  right: 30px;
  top: 50%;
  transform: translateY(-50%) translateX(6px);
  white-space: nowrap;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  background: var(--ink);
  padding: 4px 9px;
  border-radius: 5px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.24s var(--fx-ease), transform 0.3s var(--fx-ease);
}
.fx-rail__d:hover .fx-rail__t { opacity: 1; transform: translateY(-50%) translateX(0); }
@media (max-width: 1280px) { .fx-rail { display: none; } }

/* ============================================================
   11 · 空位（原「滚动速度斜切」）
   2026-09-06 用户不要页面倾斜，整章删除（对应 fx.js 模块 10）。
   ============================================================ */

/* ============================================================
   12 · 首屏滚动提示：呼吸 + 可点
   ============================================================ */

.fx-cue { cursor: pointer; }
.fx-cue .fx-cue__b { animation: fx-cue 2.1s var(--fx-ease) infinite; }
@keyframes fx-cue {
  0%, 100% { transform: translateY(0); opacity: 1; }
  46% { transform: translateY(6px); opacity: 0.45; }
  70% { transform: translateY(0); opacity: 1; }
}

/* ============================================================
   13 · 复制提示条
   ============================================================ */

.fx-toast {
  position: fixed;
  left: 50%;
  bottom: 34px;
  z-index: 200;
  transform: translateX(-50%) translateY(16px);
  background: var(--ink);
  color: #fff;
  font-size: 13px;
  line-height: 1;
  padding: 12px 18px;
  border-radius: 99px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.26s var(--fx-ease), transform 0.4s var(--fx-spring);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.fx-toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.fx-toast::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent);
}
/* 可复制的邮箱 / 电话：虚线底，hover 转实并冒出「复制」 */
.fx-copy {
  cursor: copy;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  opacity: 1;
  transition: color 0.24s var(--fx-ease), background-size 0.3s var(--fx-ease);
}
.fx-copy:hover { color: var(--violet); }

/* ============================================================
   14 · 小件的物理感：按钮 / 药丸 / 标签
   ============================================================ */

/* 按钮按下时压一下（位移交给磁吸的 transform，缩放走 scale 属性，两者不打架） */
.button, .cta, .fx-press { transition: scale 0.16s var(--fx-ease), background-color 0.28s var(--fx-ease), color 0.28s var(--fx-ease), border-color 0.28s var(--fx-ease); }
.button:active, .cta:active, .fx-press:active { scale: 0.965; }

/* 标签 / chip：hover 上抬 + 转成品牌底 */
.card-dir__tags span,
.pill, .tag, .chip {
  transition: transform 0.3s var(--fx-spring), background-color 0.26s var(--fx-ease),
              color 0.26s var(--fx-ease), border-color 0.26s var(--fx-ease);
}
.card-dir__tags span:hover,
.pill:hover, .tag:hover, .chip:hover { transform: translateY(-2px); }

/* 卡片里的箭头钮：整卡 hover 时转紫罗兰并走一步斜上 */
.card-sp__go { transition: transform 0.42s var(--fx-spring), background-color 0.3s var(--fx-ease), color 0.3s var(--fx-ease); }
.card-sp:hover .card-sp__go { transform: translate(3px, -3px); }

/* ============================================================
   15 · 表格行 / 索引行：hover 时左侧色条抹入 + 行整体右移
   ============================================================ */

.box-table__row, .fx-row {
  position: relative;
  transition: transform 0.34s var(--fx-ease), background-color 0.3s var(--fx-ease);
}
.box-table__row::after, .fx-row::after {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 3px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 0.32s var(--fx-ease);
}
.box-table__row:hover::after, .fx-row:hover::after { transform: scaleY(1); transform-origin: 50% 0; }
.box-table__row:hover, .fx-row:hover { transform: translateX(6px); }

/* ============================================================
   16 · 巨号字标：指针经过时逐字上抬（页脚 INTERFACE / SAVEHMI）
   ============================================================ */

.fx-lift { display: inline-block; transition: transform 0.5s var(--fx-spring), color 0.4s var(--fx-ease); }
.fx-lift.is-near { transform: translateY(-0.06em); }

/* ============================================================
   17 · 数字跑表结束后单位跳一下
   ============================================================ */

.fx-pop { animation: fx-pop 0.5s var(--fx-spring); }
@keyframes fx-pop {
  0% { transform: translateY(0) scale(1); }
  36% { transform: translateY(-4px) scale(1.09); }
  100% { transform: translateY(0) scale(1); }
}

/* ============================================================
   18 · 图片默认略降饱和，hover 回满并慢推
   只给作品 / 案例封面，人物照与实拍插图不动（.fx-nofilter 可退出）
   ============================================================ */

.card-dir__cover img,
.card-sp__cover img,
.figure-rollover img {
  filter: saturate(0.88) contrast(1.01);
  transition: filter 0.55s var(--fx-ease), transform 0.85s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.card-dir:hover .card-dir__cover img,
.card-sp:hover .card-sp__cover img,
.card-slide:hover .figure-rollover img { filter: none; transform: scale(1.045); }
.fx-nofilter img { filter: none !important; }

/* ============================================================
   19 · 顶栏下拉插画：跟着指针做一点视差
   ============================================================ */

.mega__art, .mega__card img { transition: transform 0.5s var(--fx-ease); }
.fx-para { transform: translate3d(var(--px, 0px), var(--py, 0px), 0); }

/* ============================================================
   20 · 跑马灯：hover 暂停（读得清里面写了谁）
   ============================================================ */

[data-mq]:hover .mq__t { animation-play-state: paused; }
[data-mq] .mq__t { transition: filter 0.3s var(--fx-ease); }

/* ============================================================
   21 · 区块眉题：进场时前缀画一条短线
   ============================================================ */

/* 不改 .sec__label 的 display——它是块级 <p>，换成 inline-flex 会改动全站的区块间距。
   线用 inline-block 的伪元素，只吃掉行内的一小段宽度。 */
.sec__label::before {
  content: "";
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 1px;
  margin-right: 0;
  background: var(--ink);
  transition: width 0.7s 0.15s var(--fx-ease), margin-right 0.7s 0.15s var(--fx-ease);
}
.sec__label.is-line::before { width: 26px; margin-right: 10px; }

/* ============================================================
   22 · 无 JS / 减少动效的兜底
   ============================================================ */

.no-js .fx-mask { clip-path: none; }
.no-js .fx-veil { display: none; }

@media (prefers-reduced-motion: reduce) {
  .fx-veil, .fx-peek, .fx-rail { display: none !important; }
  .fx-mask { clip-path: none !important; transition: none !important; }
  .fx-mask > img, .fx-mask > picture > img { transform: none !important; transition: none !important; }
  .fx-sheen::after { display: none; }
  .fx-cue .fx-cue__b { animation: none; }
  .fx-pop { animation: none; }
  .sec__label::before { width: 26px; margin-right: 10px; transition: none; }
  .fx-top { transition: opacity 0.2s linear; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.06s !important; }
}

/* ============================================================
   23 · 首屏随滚动淡出上移
   文案往上走 + 淡出，压暗层同时加深——滚出首屏时像镜头继续推。
   幅度由 JS 写 --hp（0→1）。
   ============================================================ */

.hero__inner { will-change: transform, opacity; }
.fx-hero .hero__inner {
  transform: translateY(calc(var(--hp, 0) * -64px));
  opacity: calc(1 - var(--hp, 0) * 1.35);
}
.fx-hero .hero__scrim { opacity: calc(1 + var(--hp, 0) * 0.5); }

/* ============================================================
   24 · 区块巨标随滚动横向漂移
   Works / Belief 这类满宽巨标，进出视口时横向走一小段（≤34px），
   停在中段时正好归零——版面因此有「读到这里」的呼吸。
   ============================================================ */

/* 走独立的 translate 属性，不能写进 transform——巨标身上还挂着 [data-reveal]
   的 transform: translateY(14px) 做进场，同属性覆写会把进场位移吃掉。 */
.fx-drift { translate: var(--dx, 0px) 0; will-change: translate; }

/* 25 · 深色区块上的光标环反色——随光标伴随环一起撤掉。 */

/* ============================================================
   26 · 页脚站点索引：行名后的定位横线 + 链接逐个错峰
   ============================================================ */

.footer__row { position: relative; }
.footer__key { position: relative; display: inline-block; }
.footer__key::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -4px;
  height: 1px;
  width: 0;
  background: var(--accent);
  transition: width 0.42s var(--fx-ease);
}
.footer__row:hover .footer__key::after { width: 100%; }
.footer__links a { transition: color 0.24s var(--fx-ease), transform 0.34s var(--fx-spring); }
.footer__links a:hover { transform: translateY(-1px); }

/* ============================================================
   27 · 表单控件：聚焦时描边由中间向两侧展开
   ============================================================ */

.fx-field { position: relative; }
.fx-field::after {
  content: "";
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: -1px;
  height: 2px;
  background: var(--violet);
  border-radius: 2px;
  opacity: 0;
  transition: left 0.34s var(--fx-ease), right 0.34s var(--fx-ease), opacity 0.2s linear;
}
.fx-field.is-focus::after { left: 0; right: 0; opacity: 1; }
.fx-field input,
.fx-field textarea,
.fx-field select { transition: border-color 0.28s var(--fx-ease), background-color 0.28s var(--fx-ease); }
/* 填过字的框留一个淡淡的已填记号，扫一眼就知道还差哪几项 */
.fx-field.is-filled::before {
  content: "";
  position: absolute;
  right: 10px;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2.5px;
  border-radius: 50%;
  background: var(--accent);
  pointer-events: none;
}
.fx-field:has(textarea).is-filled::before { top: 14px; margin-top: 0; }

/* ============================================================
   28 · 按钮里的箭头：hover 时飞出右侧、从左侧补回来
   ============================================================ */

/* 不包裹节点：外面套一层 inline-block 会改按钮的行盒高度，
   整页跟着长几十像素。直接给箭头本体做「飞出右侧、从左侧补回」，
   出画的两帧透明度归零，不需要任何裁切容器。 */
.button svg,
.link-arrow svg,
[data-arrow] svg { transition: transform 0.32s var(--fx-ease); }
.button:hover svg,
.button:focus-visible svg,
.link-arrow:hover svg,
[data-arrow]:hover svg { animation: fx-arrow 0.54s var(--fx-ease); }
@keyframes fx-arrow {
  0% { transform: translateX(0); opacity: 1; }
  44% { transform: translateX(150%); opacity: 0; }
  46% { transform: translateX(-150%); opacity: 0; }
  100% { transform: translateX(0); opacity: 1; }
}

/* ============================================================
   29 · 触屏：没有 hover，就把反馈给按下的那一刻
   ============================================================ */

@media (hover: none) {
  .card-sp:active, .card-dir:active, .card-slide:active,
  .news-row:active, .vb-card:active { scale: 0.985; transition: scale 0.14s var(--fx-ease); }
  .news-row:active .fx-row-go__k { opacity: 1; transform: none; }
  .fx-rail, .fx-peek { display: none !important; }
}

/* ============================================================
   30 · 跳到正文（键盘第一个可达元素）
   ============================================================ */

.fx-skip {
  position: fixed;
  left: 14px;
  top: 14px;
  z-index: 1000;
  background: var(--ink);
  color: #fff;
  font-size: 13px;
  padding: 10px 16px;
  border-radius: var(--r-ui);
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform 0.28s var(--fx-ease);
}
.fx-skip:focus-visible { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .fx-hero .hero__inner { transform: none; opacity: 1; }
  .fx-drift { translate: none !important; }
  .button svg, .link-arrow svg, [data-arrow] svg { animation: none !important; }
}
