/* =========================================================================
   个人主页模板 · 三种玻璃质感
   -------------------------------------------------------------------------
   .glass--blur     纯毛玻璃     backdrop-filter: blur() + 半透明底
   .glass--liquid   液态玻璃     边缘位移折射 + 四边 inset 高光 + 色散
   .glass--fusion   融合版       模糊 + 折射 + 双层镜面高光
   -------------------------------------------------------------------------
   用法：任意元素加 class="glass glass--liquid"，用 JS 换掉 glass--* 即可换材质。
   目录：1 变量  2 重置  3 背景  4 布局  5 顶栏  6 玻璃系统  7 组件  8 响应式
   ========================================================================= */

/* ------------------------------------------------------------------ 1 变量 */
/* 本地字体：方正粗圆简体（MINIFONT.ttf，中文圆体，标题/正文中文都吃它） */
@font-face {
  font-family: "FZCuYuan";
  src: url("../fonts/MINIFONT.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}

:root {
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 26px;
  --r-xl: 34px;
  --r-pill: 999px;

  --maxw: 1120px;
  --gap: clamp(16px, 2.2vw, 28px);
  --pad: clamp(20px, 3vw, 34px);

  --t-fast: .18s cubic-bezier(.3, .7, .3, 1);
  --t-mid: .38s cubic-bezier(.22, .8, .28, 1);

  --font: "Space Grotesk", "FZCuYuan", "Inter", "PingFang SC", "Microsoft YaHei", "Noto Sans SC", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "JetBrains Mono", "Cascadia Code", "SF Mono", Consolas, monospace;
}

/* 暗色（默认） */
html[data-theme="dark"] {
  color-scheme: dark;
  --bg: #06070f;
  --bg-2: #0b0e1d;
  --ink: #f4f6ff;
  --ink-dim: rgba(244, 246, 255, .74);
  --ink-mute: rgba(244, 246, 255, .52);

  --glass-border: rgba(255, 255, 255, .34);
  --glass-tint: rgba(255, 255, 255, .08);
  --glass-shadow: 0 18px 40px rgba(0, 0, 0, .42);
  --glass-hi: rgba(255, 255, 255, .55);
  --sheen: rgba(255, 255, 255, .20);

  --accent: #7cc7ff;
  --accent-2: #ff7ac0;
  --blob-a: #3d5bff;
  --blob-b: #ff2d78;
  --blob-c: #00d4c8;
  --blob-d: #ffb03a;
  --blob-blur: 64px;
  /* 网格/点阵是玻璃唯一能“扭”的高频细节，太淡就等于没有 */
  --grid-line: rgba(255, 255, 255, .11);
  --grid-dot: rgba(255, 255, 255, .17);
  --noise-o: .07;
}

/* 亮色 */
html[data-theme="light"] {
  color-scheme: light;
  --bg: #eef1fa;
  --bg-2: #ffffff;
  --ink: #10131f;
  --ink-dim: rgba(16, 19, 31, .76);
  --ink-mute: rgba(16, 19, 31, .55);

  --glass-border: rgba(255, 255, 255, .85);
  --glass-tint: rgba(255, 255, 255, .42);
  --glass-shadow: 0 18px 40px rgba(24, 32, 64, .16);
  --glass-hi: rgba(255, 255, 255, .95);
  --sheen: rgba(255, 255, 255, .55);

  --accent: #1f6feb;
  --accent-2: #d6337f;
  --blob-a: #8fb4ff;
  --blob-b: #ff9ecb;
  --blob-c: #8ff0e6;
  --blob-d: #ffd79a;
  --blob-blur: 56px;
  --grid-line: rgba(16, 19, 31, .10);
  --grid-dot: rgba(16, 19, 31, .16);
  --noise-o: .05;
}

/* ------------------------------------------------------------------ 2 重置 */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { margin: 0; line-height: 1.25; letter-spacing: -.01em; }
p { margin: 0 0 .9em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
ul { margin: 0; padding: 0; list-style: none; }
button { font: inherit; color: inherit; border: 0; background: none; cursor: pointer; }

code, kbd, pre { font-family: var(--mono); font-size: .86em; }

kbd {
  padding: .1em .45em;
  border: 1px solid var(--glass-border);
  border-radius: 6px;
  background: var(--glass-tint);
  font-size: .95em;
}

::selection { background: var(--accent); color: #04060f; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip-link {
  position: fixed;
  top: -100px;
  left: 16px;
  z-index: 999;
  padding: 10px 16px;
  border-radius: var(--r-sm);
  background: var(--accent);
  color: #04060f;
  font-weight: 700;
  transition: top var(--t-fast);
}
.skip-link:focus { top: 14px; }

.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ------------------------------------------------------------------ 3 背景 */
.bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 50% -10%, var(--bg-2), var(--bg) 60%),
    var(--bg);
}

.bg__blob {
  position: absolute;
  width: 46vmax;
  height: 46vmax;
  border-radius: 50%;
  filter: blur(var(--blob-blur));
  opacity: .55;
  will-change: transform;
}
.bg__blob--1 { top: -14vmax; left: -8vmax;  background: var(--blob-a); animation: drift1 24s ease-in-out infinite; }
.bg__blob--2 { top: -6vmax;  right: -12vmax; background: var(--blob-b); animation: drift2 29s ease-in-out infinite; }
.bg__blob--3 { bottom: -18vmax; left: 12vmax; background: var(--blob-c); animation: drift3 33s ease-in-out infinite; }
.bg__blob--4 { bottom: -12vmax; right: 4vmax; background: var(--blob-d); animation: drift1 27s ease-in-out infinite reverse; }

@keyframes drift1 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6vmax, 4vmax, 0) scale(1.12); }
}
@keyframes drift2 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50%      { transform: translate3d(-7vmax, 5vmax, 0) scale(.94); }
}
@keyframes drift3 {
  0%, 100% { transform: translate3d(0, 0, 0) scale(.98); }
  50%      { transform: translate3d(5vmax, -5vmax, 0) scale(1.1); }
}

.bg__noise {
  position: absolute;
  inset: 0;
  opacity: var(--noise-o);
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ------------------------------------------------------------------ 4 布局 */
main { display: block; }

.hero,
.section,
.footer {
  width: min(100% - 2 * var(--gap), var(--maxw));
  margin-inline: auto;
}

.hero { padding: clamp(96px, 13vh, 150px) 0 clamp(30px, 5vh, 56px); }
.section { padding: clamp(34px, 6vh, 64px) 0; }

.section__head { max-width: 62ch; margin-bottom: clamp(20px, 3vh, 32px); }

.kicker {
  margin: 0 0 .35em;
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--accent);
}

.section__title { font-size: clamp(1.5rem, 3.4vw, 2.1rem); font-weight: 700; }

.section__desc { margin-top: .7em; color: var(--ink-dim); }

.cards { display: grid; gap: var(--gap); }
.cards--2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.cards--3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

/* ------------------------------------------------------------------ 5 顶栏 */
.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  padding: 14px var(--gap) 0;
}

.topbar__inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  width: min(100%, var(--maxw));
  margin-inline: auto;
  padding: 9px 12px 9px 18px;
  border-radius: var(--r-pill);
  isolation: isolate;
}

/* ── 顶栏装饰层（全在内容之下，不挡交互）───────────────────────────
   ① topbar__deco：缓慢流动的极光，三色径向渐变在药丸内部漂移
   ② topbar__sheen：顶部 1px 发丝高光 + 上半部柔和渐隐，做出「抛光玻璃」的厚度感 */
.topbar__deco,
.topbar__sheen {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;   /* 必须压过 .glass > * 的 z-index:1 —— 见下方 !important 覆盖 */
  overflow: hidden;
}
/* .glass > * 会把所有子元素提到 z-index:1；装饰层必须压在文字之下、shader canvas 之上
   （canvas 由引擎注入并设 z-index:-1，这里再给它降一层，保证装饰层不会挡住折射） */
.topbar__inner > canvas.glass-out { z-index: -2 !important; }
.topbar__inner > .topbar__deco,
.topbar__inner > .topbar__sheen { z-index: -1 !important; }
.topbar__deco {
  opacity: .55;
  background:
    radial-gradient(30% 110% at 10% 50%, rgba(124, 199, 255, .16), transparent 72%),
    radial-gradient(26% 120% at 44% 40%, rgba(186, 150, 255, .11), transparent 74%),
    radial-gradient(24% 110% at 80% 62%, rgba(120, 230, 255, .09), transparent 72%);
  background-size: 190% 100%, 170% 100%, 180% 100%;
  animation: topAurora 18s ease-in-out infinite alternate;
  filter: saturate(115%);
}
@keyframes topAurora {
  0%   { background-position: 0% 50%, 100% 50%, 50% 50%; }
  50%  { background-position: 70% 50%, 30% 50%, 10% 50%; }
  100% { background-position: 100% 50%, 0% 50%, 80% 50%; }
}
/* 上沿发丝高光 + 极淡顶部渐隐。发丝线并入本层（而不是独立 ::after 直条），
   这样它被 border-radius + overflow:hidden 一起裁掉，不会在药丸圆角外露出直线头。 */
.topbar__sheen {
  background:
    linear-gradient(180deg, rgba(255,255,255,.13) 0%, rgba(255,255,255,.04) 26%, transparent 52%),
    linear-gradient(90deg,
      transparent, rgba(255,255,255,.50) 16%, rgba(255,255,255,.80) 50%,
      rgba(255,255,255,.50) 84%, transparent) top / 100% 1px no-repeat;
  -webkit-mask: linear-gradient(180deg, #000 0%, #000 46%, transparent 76%);
  mask: linear-gradient(180deg, #000 0%, #000 46%, transparent 76%);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: .015em;
  white-space: nowrap;
  transition: opacity var(--t-fast);
}
.brand:hover { opacity: .85; }
.brand__dot {
  position: relative;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: linear-gradient(135deg, #a8e2ff, #7cc7ff 45%, #c9a6ff);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.35),
    0 0 12px rgba(124,199,255,.85),
    0 0 24px rgba(160,140,255,.45);
}
/* 呼吸光晕：让品牌点像一颗活的指示灯 */
.brand__dot::after {
  content: "";
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(124,199,255,.55), transparent 68%);
  animation: dotPulse 3.4s ease-in-out infinite;
}
@keyframes dotPulse {
  0%, 100% { transform: scale(.85); opacity: .55; }
  50%      { transform: scale(1.25); opacity: .95; }
}
.brand__text {
  background: linear-gradient(180deg, #ffffff, #d8e8ff 60%, #b9d2f0);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 1px 8px rgba(140, 190, 255, .28);
}

/* 导航：文字 + 底部滑出的小光条 */
.nav { display: flex; gap: 2px; margin-left: auto; }
.nav a {
  position: relative;
  padding: 8px 13px;
  border-radius: var(--r-pill);
  font-size: .92rem;
  font-weight: 500;
  color: var(--ink-dim);
  transition: color var(--t-fast), background var(--t-fast);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 50%; bottom: 3px;
  width: 0; height: 1.5px;
  border-radius: 2px;
  transform: translateX(-50%);
  background: linear-gradient(90deg, transparent, rgba(160,215,255,.95), transparent);
  box-shadow: 0 0 8px rgba(124,199,255,.85);
  transition: width .32s cubic-bezier(.22,.8,.28,1);
}
.nav a:hover { color: var(--ink); background: rgba(255,255,255,.07); }
.nav a:hover::after { width: 58%; }

/* 语言 / 材质切换器：外层是一个淡淡的槽，选中项直接用「主题玻璃」渲染
   （选中按钮挂 .is-sel + 由引擎接管，材质和页面上的卡片/按钮完全一致，
    不再自绘白色高光 —— 那样和主题割裂）。 */
/* 语言 / 材质切换器：外层槽子要做成「凹下去」的沟（inset），
   里面的滑动玻璃胶囊才是「浮起来」的那一颗 —— 有凹有凸才有层次。
   做法：槽底压暗 + 内侧高光在下沿 / 阴影在上沿（用 inset box-shadow 模拟
   被挖空的侧壁），外沿用一圈极淡的亮线勾出开口。 */
.lang {
  position: relative;
  display: flex;
  gap: 2px;
  margin-left: 10px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: rgba(4, 8, 20, .42);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, .55),
    inset 0 -1px 0 rgba(255, 255, 255, .10),
    0 1px 0 rgba(255, 255, 255, .06);
}
.lang__btn {
  position: relative;
  z-index: 1;
  border: 0;
  background: transparent;
  color: rgba(226,238,255,.58);
  font: 600 .78rem/1 var(--font);
  letter-spacing: .04em;
  padding: 6px 11px;
  border-radius: var(--r-pill);
  cursor: pointer;
  overflow: hidden;
  transition: color .3s var(--ease-spring), transform .12s ease;
}
.lang__btn:hover { color: #eaf3ff; }
.lang__btn:active { transform: scale(.9); }
.lang__btn.is-active { color: #ffffff; }
/* 重复点击同一项：轻轻弹一下（配合引擎重播流体成型） */
.is-bump { animation: bump .42s cubic-bezier(.3, 1.6, .4, 1); }
@keyframes bump {
  0%   { transform: scale(1); }
  35%  { transform: scale(.90); }
  70%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}

/* 选中项的玻璃底 = 一块会滑动的胶囊（.glass-pill）。
   它自带 glass/js-glass，由 WebGL 引擎按当前主题材质渲染 —— 所以选中态和页面上的
   卡片/按钮完全同一套 shader，不是另画的白高光。
   位置/尺寸由 app.js 量出选中按钮的矩形后写进 transform + width，
   CSS 过渡负责「滑过去」；引擎每帧按新矩形重画玻璃 → 像一滴液体在槽里滑动。 */
.glass.glass-pill {
  position: absolute;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  z-index: 0;
  opacity: 0;
  border-radius: var(--r-pill);
  pointer-events: none;
  transform: translate(0, 0);
  transition:
    transform .44s cubic-bezier(.34, 1.28, .42, 1),
    width .44s cubic-bezier(.34, 1.28, .42, 1),
    height .22s ease,
    opacity .22s ease;
  will-change: transform, width;
}
/* 引擎不接管 transform 的元素（见 webgl-glass.js 的 noTransform），
   否则内联的 perspective/scale 会把这里的 translate 覆盖掉 → 胶囊永远停在左端。 */
.lang__btn.is-active::before,
.switcher__btn.is-active::before { display: none; }

.switcher {
  position: relative;
  display: flex;
  gap: 3px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: rgba(4, 8, 20, .42);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, .55),
    inset 0 -1px 0 rgba(255, 255, 255, .10),
    0 1px 0 rgba(255, 255, 255, .06);
}

.switcher__btn {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  font-size: .84rem;
  font-weight: 600;
  color: var(--ink-mute);
  border: 1px solid transparent;
  background: none;
  overflow: hidden;
  transition: color .3s var(--ease-spring), transform .12s ease;
}
.switcher__btn:active { transform: scale(.93); }
.switcher__btn:hover { color: var(--ink); }
.switcher__ico { font-size: .9em; opacity: .8; }
.switcher__btn.is-active { color: var(--ink); }

.iconbtn {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: var(--glass-tint);
  font-size: 1rem;
  transition: background var(--t-fast), transform var(--t-fast);
}
.iconbtn:hover { background: var(--sheen); transform: rotate(-12deg); }

/* ------------------------------------------------------------------ 6 玻璃系统 */
.glass {
  position: relative;
  isolation: isolate;
  border-radius: var(--r-lg);
  border: 1px solid var(--glass-border);
  background: var(--glass-tint);
  box-shadow: var(--glass-shadow);
  overflow: hidden;
  /* 切换材质时平滑过渡（Chromium 支持 backdrop-filter 插值） */
  transition:
    backdrop-filter .55s var(--ease-spring),
    -webkit-backdrop-filter .55s var(--ease-spring),
    background .55s var(--ease-spring),
    box-shadow .55s var(--ease-spring),
    border-color .55s var(--ease-spring);
}

/* 内容层压在折射层之上 */
.glass > * { position: relative; z-index: 1; }

/* ---- WebGL 液体玻璃引擎激活 ----
   引擎接管的元素带 .is-gpu（卡片、按钮、胶囊都算），并注入 <canvas class="glass-out">
   （z-index:-1，四周留 26px 投影余量）。此时关掉 CSS 的 backdrop-filter / 底色 / 边框 /
   投影 —— 折射、内边框高光、投影全部由 shader 负责，避免「一半 CSS 一半 shader」的割裂感。
   ⚠ 选择器要压过 .tag / .btn 里带 !important 的规则，所以带上 html[data-webgl-glass]。 */
html[data-webgl-glass] .is-gpu {
  background: transparent !important;
  border-color: transparent !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  box-shadow: none !important;
}
html[data-webgl-glass] .glass.is-gpu { overflow: visible; }
/* 伪元素折射环（带 backdrop-filter，走 CPU）在 GPU 模式下必须关掉 */
html[data-webgl-glass] .is-gpu::before { display: none !important; }
html[data-webgl-glass] .is-gpu > canvas.glass-out {
  position: absolute;
  pointer-events: none;
  z-index: -1;
  border-radius: inherit;
  /* hover 收缩时：元素整体缩（内容跟着走），canvas 反向缩回原尺寸，
     于是玻璃里折射到的背景钉死在屏幕上、不跟着卡片跑。
     --isc 由引擎每帧与元素内联 transform 同步写入（同一个 s）。 */
  transform: scale(var(--isc, 1));
  transform-origin: center center;
}
/* ⚠ 卡片 transform 完全由引擎写内联样式（见 webgl-glass.js renderItem），
   这里不要再声明 [data-tilt]{transform:...} —— 会和内联值打架，
   出现「卡片不缩放」+「canvas 反缩过头溢出边缘」+「背景跟着卡片动」。 */

/* 快速滚动保护：滚动是合成器线程完成的，玻璃画布里的内容是「上一帧该屏幕位置的
   背景裁剪」，主线程跟不上时会被搬到新位置 → 卡片后面断层/撕裂。
   此时隐藏 shader 输出，让真实壁纸直接透出来（正确优先于好看），
   滚完 110ms 后由 JS 移除这个 class 并强制补画。
   同时把过渡关掉：滚动中做 opacity 过渡只会多一层重绘。 */
html.is-scrolling .is-gpu > canvas.glass-out {
  opacity: 0 !important;
  transition: none !important;
}
/* 隐藏期间把元素自己的 CSS 玻璃底露出来兜底，避免卡片变成完全透明的空洞。
   blur 模式本来就是毛玻璃；liquid/fusion 在滚动瞬间用一层很淡的底色即可。 */
html.is-scrolling .is-gpu {
  background: rgba(10, 16, 32, .20) !important;
  border-color: rgba(255, 255, 255, .10) !important;
}

/* ---- 6.1 Blur：纯毛玻璃 ----
   特征：重霜。三种材质里唯一强调「模糊」的，用来和 liquid 的「清澈」形成对比。 */
.glass--blur {
  background: rgba(255, 255, 255, .05);
  border-color: rgba(255, 255, 255, .20);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .14),
    0 12px 32px rgba(2, 4, 14, .38);
  -webkit-backdrop-filter: blur(16px) saturate(112%);
  backdrop-filter: blur(16px) saturate(112%);
}
html[data-theme="light"] .glass--blur {
  background: rgba(255, 255, 255, .34);
  border-color: rgba(255, 255, 255, .9);
  box-shadow: 0 12px 32px rgba(24, 32, 64, .14);
}

.glass--blur::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, .07), rgba(255, 255, 255, 0) 45%);
}

/* ---- 6.2 Liquid Glass：清澈玻璃 + GPU 边缘折射 ----
   原理：中心用 blur(1px) 几乎不糊（清澈），
   但 ::before 覆盖整个卡片却用 mask 只显示边缘一圈，那一圈用 blur(10px)+saturate(170%)
   → 视觉上中心清楚、边缘模糊增艳，就是厚玻璃把边缘光"吸走"的折射感。
   ⚠ 不用 backdrop-filter: url() —— 那玩意在 Chromium 走 CPU 光栅化，视频背景下一帧就卡死。
   这里全用 GPU blur()，合成器加速，视频背景下丝滑。 */
.glass--liquid {
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .08) 0%,
      rgba(255, 255, 255, .02) 42%,
      rgba(255, 255, 255, .05) 100%);
  border-color: rgba(255, 255, 255, .30);
  box-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, .55),
    inset 0 -2px 3px rgba(255, 255, 255, .12),
    inset 0 0 26px rgba(255, 255, 255, .05),
    0 22px 48px rgba(2, 4, 14, .36);
  -webkit-backdrop-filter: blur(1px) saturate(150%) brightness(1.08);
  backdrop-filter: blur(1px) saturate(150%) brightness(1.08);
}
html[data-theme="light"] .glass--liquid {
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .22) 0%,
      rgba(255, 255, 255, .06) 42%,
      rgba(255, 255, 255, .14) 100%);
  border-color: rgba(255, 255, 255, .8);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    inset 0 -1px 1px rgba(255, 255, 255, .3),
    inset 0 0 24px rgba(255, 255, 255, .16),
    0 20px 44px rgba(24, 32, 64, .12);
}

/* Liquid 边缘折射环：GPU blur() 伪厚玻璃折射。
   mask 中心透明、边缘一圈不透明 → 只有边缘显示 blur(10px)+saturate(175%) 的背景。
   ⚠ 只在 .glass--liquid 下生效，避免 blur/fusion 也背着 backdrop-filter 白耗 GPU。 */
.glass--liquid::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  border-radius: inherit;
  -webkit-mask:
    radial-gradient(118% 118% at 50% 50%,
      transparent 74%, rgba(0, 0, 0, .85) 88%, #000 96%, #000 100%);
  mask:
    radial-gradient(118% 118% at 50% 50%,
      transparent 74%, rgba(0, 0, 0, .85) 88%, #000 96%, #000 100%);
  -webkit-backdrop-filter: blur(10px) saturate(175%) brightness(1.04);
  backdrop-filter: blur(10px) saturate(175%) brightness(1.04);
}

/* ---- 6.3 Fusion：融合玻璃 ----
   特征：中等霜 + 双镜面。模糊介于 blur(16) 与 liquid(1) 之间，
   顶部亮边更厚、底部也有内阴影，是「毛玻璃 + 液态高光」的折中。 */
.glass--fusion {
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .12) 0%,
      rgba(255, 255, 255, .05) 38%,
      rgba(255, 255, 255, .09) 100%);
  border-color: rgba(255, 255, 255, .26);
  box-shadow:
    inset 0 1.5px 0 rgba(255, 255, 255, .45),
    inset 0 -1.5px 2px rgba(255, 255, 255, .12),
    inset 0 0 30px rgba(255, 255, 255, .06),
    0 26px 56px rgba(2, 4, 14, .40);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
  backdrop-filter: blur(8px) saturate(120%);
}
html[data-theme="light"] .glass--fusion {
  background:
    linear-gradient(158deg,
      rgba(255, 255, 255, .45) 0%,
      rgba(255, 255, 255, .18) 38%,
      rgba(255, 255, 255, .34) 100%);
  border-color: rgba(255, 255, 255, .85);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    inset 0 -1px 1px rgba(255, 255, 255, .35),
    inset 0 0 30px rgba(255, 255, 255, .2),
    0 26px 56px rgba(24, 32, 64, .14);
}

.glass--liquid::after,
.glass--fusion::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  border-radius: inherit;
  background:
    radial-gradient(240px circle at var(--mx, 24%) var(--my, 4%),
      rgba(255, 255, 255, .18), rgba(255, 255, 255, 0) 62%),
    linear-gradient(160deg,
      rgba(255, 255, 255, .22) 0%,
      rgba(255, 255, 255, .04) 24%,
      rgba(255, 255, 255, 0) 42%),
    linear-gradient(0deg,
      rgba(255, 255, 255, .10) 0%,
      rgba(255, 255, 255, 0) 20%);
  mix-blend-mode: screen;
  opacity: .72;
  transition: opacity var(--t-mid);
}

/* 降级：不支持 backdrop-filter 时改为不透明底 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass--blur,
  .glass--liquid,
  .glass--fusion {
    background: color-mix(in srgb, var(--bg) 88%, #8aa0ff 12%);
    border-color: rgba(255, 255, 255, .3);
  }
  .glass--fusion { box-shadow: 0 18px 40px rgba(2, 4, 14, .4); }
}

/* ------------------------------------------------------------------ 7 组件 */
/* Hero */
.hero__card {
  padding: clamp(28px, 4.4vw, 56px);
  border-radius: var(--r-xl);
  text-align: left;
}

.avatar {
  position: relative;
  width: 92px;
  height: 92px;
  margin-bottom: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: linear-gradient(140deg, var(--accent), var(--accent-2));
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, .55),
    0 12px 30px rgba(0, 0, 0, .3);
}
.avatar__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 22%;   /* 构图偏上，把脸留在圆心里 */
}
.avatar__initial { font-size: 2rem; font-weight: 700; color: #04060f; }
/* 图片加载成功 → 隐藏兜底首字母 */
.avatar:has(.avatar__img) .avatar__initial { display: none; }

.eyebrow {
  margin: 0 0 .2em;
  font-size: .82rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.hero__name { font-size: clamp(2rem, 6.2vw, 3.4rem); font-weight: 800; letter-spacing: -.03em; }
.hero__name-en {
  display: block;
  margin-top: .18em;
  font-size: clamp(.9rem, 2.2vw, 1.15rem);
  font-weight: 500;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

.hero__role {
  margin: 1.1em 0 .6em;
  font-size: clamp(1rem, 2.3vw, 1.16rem);
  font-weight: 600;
  color: var(--accent);
}

.hero__lede { max-width: 52ch; color: var(--ink-dim); }

.cta { display: flex; flex-wrap: wrap; gap: 10px; margin: 24px 0 20px; }

/* 按钮 */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 11px 20px;
  border-radius: var(--r-pill);
  font-size: .94rem;
  font-weight: 600;
  border: 1px solid transparent;
  transition: transform var(--t-fast), background var(--t-fast), box-shadow var(--t-fast), border-color var(--t-fast);
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: linear-gradient(160deg, var(--accent), var(--accent-2));
  color: #04060f;
  box-shadow: 0 10px 26px rgba(0, 0, 0, .28), inset 0 1px 0 rgba(255, 255, 255, .6);
}

.btn--ghost {
  border-color: var(--glass-border);
  background: var(--glass-tint);
  box-shadow: inset 0 1px 0 var(--glass-hi);
}
.btn--ghost:hover { background: var(--sheen); }

.btn--quiet { color: var(--ink-mute); }
.btn--quiet:hover { color: var(--ink); }
.btn--block { width: 100%; margin-top: auto; }

/* 标签 */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  padding: 5px 13px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-border);
  background: var(--glass-tint);
  font-size: .82rem;
  color: var(--ink-dim);
}

/* 对比区 */
.compare {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
}

.compare__item {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: var(--pad);
}

/* 演示舞台：左半被玻璃盖住，右半裸露，方便对比 */
.stage {
  position: relative;
  height: 190px;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--glass-border);
}
.stage__art {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background:
    radial-gradient(58% 88% at 18% 18%, #ff4d8d, transparent 62%),
    radial-gradient(58% 88% at 84% 26%, #4dd0ff, transparent 62%),
    radial-gradient(70% 92% at 52% 108%, #ffd166, transparent 62%),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .16) 0 2px, transparent 2px 15px),
    #0a0c18;
}
.stage__art b {
  font-size: clamp(26px, 5vw, 44px);
  font-weight: 800;
  letter-spacing: .1em;
  color: rgba(255, 255, 255, .92);
  text-shadow: 0 4px 18px rgba(0, 0, 0, .5);
}

.stage__glass {
  position: absolute;
  inset: 16px 44% 16px 16px;
  border-radius: var(--r-md);
  display: grid;
  place-items: center;
}
.stage__tag {
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: #fff;
  text-shadow: 0 2px 10px rgba(0, 0, 0, .55);
}

.compare__title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 1.12rem;
  font-weight: 700;
}
.compare__title .num {
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--accent);
}
.compare__text { color: var(--ink-dim); font-size: .95rem; }
.compare__text code { color: var(--accent); }

.spec { display: grid; gap: 6px; margin-top: auto; }
.spec li {
  position: relative;
  padding-left: 20px;
  font-size: .87rem;
  color: var(--ink-mute);
}
.spec li::before {
  content: "";
  position: absolute;
  left: 3px;
  top: .62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent);
}

/* 通用卡片 */
.card { padding: var(--pad); }
.card__title { margin-bottom: .6em; font-size: 1.08rem; font-weight: 700; }

.code {
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--r-sm);
  border: 1px solid var(--glass-border);
  background: rgba(4, 6, 15, .45);
  color: var(--ink-dim);
  font-size: .8rem;
  line-height: 1.65;
  overflow-x: auto;
  white-space: pre;
}
html[data-theme="light"] .code { background: rgba(10, 14, 32, .06); }

/* 技能条 */
.bars { display: grid; gap: 14px; }
.bar { display: grid; gap: 7px; }
.bar__label { font-size: .88rem; color: var(--ink-dim); }
.bar__track {
  display: block;
  height: 7px;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--glass-tint);
  border: 1px solid var(--glass-border);
}
.bar__track i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width 1.1s cubic-bezier(.22, .8, .28, 1);
}
.is-in .bar__track i { width: var(--v, 60%); }

/* 项目卡 */
.work { display: flex; flex-direction: column; gap: 10px; transition: transform var(--t-mid), box-shadow var(--t-mid); }
.work:hover { transform: translateY(-5px); }
.work__badge {
  align-self: flex-start;
  padding: 3px 11px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-border);
  background: var(--glass-tint);
  font-size: .78rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.work__desc { margin: 0; font-size: .94rem; color: var(--ink-dim); }
.work__meta { margin: 0; font-family: var(--mono); font-size: .78rem; color: var(--ink-mute); }

/* ---- 广告位招租：页面最底部的一条（footer 之下）---- */
.ad {
  padding: 14px clamp(14px, 3vw, 40px) 22px;
  text-align: center;
}
.ad__txt {
  margin: 0;
  font-family: var(--mono);
  font-size: .8rem;
  font-weight: 500;
  letter-spacing: .22em;
  color: var(--ink-mute);
  opacity: .78;
}
.ad__sub {
  margin: .35em 0 0;
  font-size: .76rem;
  color: var(--ink-mute);
  opacity: .5;
}

/* 页脚 */
.footer {
  padding: 44px 0 60px;
  text-align: center;
  font-size: .86rem;
  color: var(--ink-mute);
}
.footer__hint { margin-top: .4em; font-size: .8rem; }

/* 入场动效 */
/* 滚动入场：放缓 + 位移收小，避免「啪」地弹出来。
   liquid 材质另有 shader 里的「流体成型」，两者叠加成一整段顺滑的出现。
   ⚠ [data-tilt] 卡片的 transform 归引擎收缩/tilt 专用（见 16 块），
   入场只淡入不位移，否则 .is-in{transform:none} 会把收缩整个吃掉。 */
.reveal {
  opacity: 0;
  transform: translateY(14px) scale(.985);
  transition:
    opacity 1.1s cubic-bezier(.22, .61, .28, 1),
    transform 1.1s cubic-bezier(.22, .8, .28, 1);
}
.reveal.is-in { opacity: 1; transform: none; }
/* tilt 卡：transform 归引擎内联/16 块规则专用，reveal 只淡入不位移 */
.reveal[data-tilt] { transition-property: opacity; }

/* 复制成功反馈 */
.is-copied { color: var(--accent) !important; }

/* ------------------------------------------------------------------ 8 新增：Apple 风组件 + 动效
   字体切换为 Space Grotesk（标题）+ JetBrains Mono（等宽） */
:root {
  --font-display: "Space Grotesk", "Inter", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
  --ease-back: cubic-bezier(.34, 1.56, .64, 1);
  --ease-spring: cubic-bezier(.34, 1.2, .4, 1);
}

/* ---- 8.1 滚动进度条 ---- */
.progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px;
  z-index: 200; pointer-events: none;
}
.progress__bar {
  display: block; height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2), var(--blob-c));
  box-shadow: 0 0 12px rgba(124, 199, 255, .6);
  transition: width .12s linear;
}

/* ---- 8.2 顶栏滚动后毛玻璃 ---- */
.topbar { position: sticky; top: 0; z-index: 100; padding: 14px clamp(14px, 3vw, 40px) 0; }
.topbar.is-scrolled .topbar__inner {
  background: linear-gradient(158deg, rgba(255,255,255,.10), rgba(255,255,255,.04) 45%, rgba(255,255,255,.08));
  border-color: rgba(255,255,255,.28);
  box-shadow: 0 12px 32px rgba(2, 4, 14, .35);
}

/* ---- 8.3 动态壁纸背景（视频） ----
   视频替代原先 4 个大 blur 光斑 + 光点 + 星星：视频解码由 GPU 硬件处理，
   不会像多个 blur(80px) + 逐帧动画那样每帧重绘整块合成层。 */
.bg__video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center;
  filter: saturate(1.12) brightness(1.02) contrast(1.02);
  transform: translateZ(0);
}
.bg__veil {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(6,7,15,.14), rgba(6,7,15,.34) 68%),
    linear-gradient(180deg, rgba(6,7,15,.20), rgba(6,7,15,.44));
}

/* ---- 8.4 Apple Liquid Glass 按钮 ---- */
.btn {
  font-family: var(--font-display); font-weight: 600; letter-spacing: .01em;
  position: relative; overflow: hidden;
  transition:
    transform .45s var(--ease-spring),
    box-shadow .45s var(--ease-spring),
    background .35s ease,
    border-color .35s ease,
    color .35s ease;
}
.btn::after { /* 扫光：更细、更克制，只在 hover 时短暂出现 */
  content: ""; position: absolute; top: -20%; left: -140%;
  width: 50%; height: 140%;
  background: linear-gradient(100deg, transparent, rgba(255,255,255,.35), transparent);
  transform: skewX(-20deg); opacity: 0;
  transition: left .9s var(--ease-spring), opacity .4s ease;
}
.btn:hover::after { left: 160%; opacity: 1; }
.btn:hover { box-shadow: 0 10px 28px rgba(124,199,255,.14), 0 4px 10px rgba(0,0,0,.22); }
/* 点击反馈加强：按得更深、回弹更快，配 JS 落点涟漪（.ripple 层） */
.btn:active { transform: scale(.93) !important; transition: transform .09s ease; }
.ripple {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,.5), rgba(255,255,255,0) 70%);
  transform: scale(0);
  pointer-events: none;
  animation: rippleOut .5s ease-out forwards;
  z-index: 2;
}
@keyframes rippleOut {
  to { transform: scale(1); opacity: 0; }
}

.btn--primary {
  /* 单色偏冷的玻璃蓝，去掉三色彩虹 → 高级不廉价 */
  background: linear-gradient(180deg, rgba(124,199,255,.28) 0%, rgba(124,199,255,.14) 100%);
  border: 1px solid rgba(255,255,255,.32);
  color: #eaf3ff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.50),
    inset 0 -1px 1px rgba(0,0,0,.10),
    0 14px 30px rgba(0,0,0,.20);
  -webkit-backdrop-filter: blur(16px) saturate(130%);
  backdrop-filter: blur(16px) saturate(130%);
}
.btn--primary:hover {
  background: linear-gradient(180deg, rgba(124,199,255,.36) 0%, rgba(124,199,255,.20) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.60),
    inset 0 -1px 1px rgba(0,0,0,.08),
    0 18px 40px rgba(0,0,0,.26),
    0 0 0 1px rgba(255,255,255,.06);
}
.btn--ghost {
  background: rgba(255,255,255,.04);
  border: 1px solid rgba(255,255,255,.22);
  color: var(--ink);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.30);
  -webkit-backdrop-filter: blur(12px) saturate(120%);
  backdrop-filter: blur(12px) saturate(120%);
}
.btn--ghost:hover {
  background: rgba(255,255,255,.08);
  border-color: rgba(255,255,255,.34);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.42);
}
.btn--quiet { background: transparent; border: 1px solid rgba(255,255,255,.12); color: var(--ink-mute); }
.btn--quiet:hover { color: var(--ink); border-color: rgba(255,255,255,.28); }
.btn--sm { padding: 8px 16px; font-size: .82rem; }

/* 磁性按钮位移（JS 设置 --tx/--ty） */
.btn.magnetic { transform: translate(var(--tx, 0), var(--ty, 0)); }

/* ---- 8.5 打字机光标 ---- */
.caret { display: inline-block; width: 2px; height: 1em; margin-left: 2px; background: var(--accent); vertical-align: -.15em; animation: blink 1s steps(2) infinite; }
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* ---- 8.6 项目 / 视频 / 标签 / 技能条 ---- */
/* 玻璃卡必须留出内边距，否则文字贴边会被圆角裁掉 */
.about__card { padding: clamp(24px, 3.6vw, 44px); }
.project__card { padding: clamp(24px, 3.6vw, 44px); }
.project__lede { font-size: 1.02rem; line-height: 1.7; color: var(--ink-dim); }
.project__lede strong { color: var(--ink); }
/* ⚠ overflow 必须 !important：引擎 registerItem 会把所有 .glass 元素写成
   【内联】overflow:visible（为了让投影溢出），普通 CSS 规则压不过内联样式。
   扁条不需要投影溢出，反而需要把内容裁住 —— 否则 nowrap 的文字从两端溢出，
   被自己的玻璃透镜拽出来，就是用户看到的「奇怪的影子」。 */
.feature { list-style: none; display: grid; grid-template-columns: 1fr 1fr; gap: 30px 22px; margin: 18px 0 22px; }
.feature li { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 11px 16px; border-radius: var(--r-md); overflow: hidden !important; }
.feature__k { font-size: .88rem; color: var(--ink-dim); min-width: 0; }
.feature__v { font-family: var(--mono); font-size: .82rem; color: var(--accent); flex: none; }

.videos { display: grid; gap: 30px; }
/* .video 已加 glass/js-glass，材质跟随全局切换器；这里只保留布局和悬停位移 */
.video {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 18px;
  padding: 18px 22px; border-radius: var(--r-lg); text-decoration: none; color: inherit;
  transition: transform .5s var(--ease-spring), box-shadow .4s ease;
}
.video:hover { transform: translateX(6px) translateY(-2px); }
.video__num { font-family: var(--mono); font-size: .78rem; color: var(--accent); opacity: .8; }
.video__title { margin: 0; font-size: 1.05rem; font-weight: 600; }
.video__desc { margin: 4px 0 0; font-size: .88rem; color: var(--ink-mute); }
.video__arrow { font-size: 1.2rem; color: var(--accent); transition: transform .3s ease; }
.video:hover .video__arrow { transform: translate(2px, -2px); }

.tags { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 20px 0 0; padding: 0; }
/* .tag：细腻玻璃碎屑。
   小尺寸上不能用全局材质 —— saturate(150%) 会把背后颜色放大成蓝色塑料气泡。
   这里固定用「极轻 tint + 细边框 + 顶部一道高光」，克制才有高级感。 */
.tag {
  font-family: var(--mono); font-size: .9rem;
  padding: 8px 15px;
  border-radius: var(--r-pill);
  /* 覆盖 .glass 的材质，不再跟随全局切换器 */
  background: rgba(255, 255, 255, .06) !important;
  border: 1px solid rgba(255, 255, 255, .16) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .18),
    0 2px 6px rgba(0, 0, 0, .10) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  transition:
    background .3s ease,
    border-color .3s ease,
    box-shadow .3s ease,
    transform .3s var(--ease-spring);
}
.tag:hover {
  background: rgba(255, 255, 255, .10) !important;
  border-color: rgba(255, 255, 255, .24) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .24),
    0 4px 12px rgba(0, 0, 0, .14) !important;
  transform: translateY(-1px);
}
.tag__mono { color: var(--accent); margin-right: 4px; }

.stack { padding: 24px 28px; }
.stack__row { display: grid; grid-template-columns: 160px 1fr 56px; align-items: center; gap: 16px; margin: 14px 0; }
.stack__label { font-size: .92rem; color: var(--ink-dim); }
.stack__bar { height: 8px; border-radius: 6px; background: rgba(255,255,255,.10); overflow: hidden; }
.stack__fill { display: block; height: 100%; border-radius: 6px; background: linear-gradient(90deg, var(--accent), var(--accent-2)); width: 0; transition: width 1.1s var(--ease-back); }
.stack__val { font-family: var(--mono); font-size: .82rem; color: var(--accent); text-align: right; }

.about { display: grid; gap: 22px; }
.about__bio { font-size: clamp(1.4rem, 2.6vw, 2rem); font-weight: 600; margin: 0 0 10px; }
.about__lede { font-size: 1.02rem; line-height: 1.7; color: var(--ink-dim); margin: 0; }
.about__lede strong { color: var(--ink); }

/* 平滑锚点滚动时留出顶栏高度 */
html { scroll-padding-top: 90px; }

/* ------------------------------------------------------------------ 8 响应式 */
@media (max-width: 900px) {
  .nav { display: none; }
  .feature { grid-template-columns: 1fr; }
  .stack__row { grid-template-columns: 1fr auto; gap: 10px; }
  .stack__bar { grid-column: 1 / -1; }
}

@media (max-width: 640px) {
  .video { grid-template-columns: auto 1fr; }
  .video__arrow { display: none; }
}

@media (max-width: 720px) {
  .topbar__inner { flex-wrap: wrap; justify-content: center; border-radius: var(--r-lg); row-gap: 8px; padding: 10px 12px; }
  .nav { display: none; }
  .brand { margin-right: auto; }
  .lang { margin-left: 0; }
  /* 材质切换器独占一行，均分宽度，不再溢出 */
  .switcher { order: 3; width: 100%; justify-content: center; }
  .switcher__btn { flex: 1; justify-content: center; padding-inline: 8px; min-width: 0; }
  .hero__card { text-align: center; }
  .avatar { margin-inline: auto; }
  .cta { justify-content: center; }
  .chips { justify-content: center; }
  .stage__glass { inset: 14px 34% 14px 14px; }
}

/* 小屏（手机）：修掉横向溢出。
   原因：hero 卡片里的 .cta 带 min-width:196px（桌面两栏布局用），
   窄屏下再加上卡片内边距就把内容顶出屏幕；typewriter 长句也没有断行约束。 */
@media (max-width: 560px) {
  .hero { padding-top: 92px; }
  .hero__card { padding: 22px 18px; }
  .hero__card .cta { min-width: 0; width: 100%; }
  .cta { gap: 8px; margin: 18px 0 0; }
  .cta .btn { flex: 1 1 auto; justify-content: center; padding-inline: 14px; }

  /* 打字机长句：允许断词换行，绝不撑破卡片 */
  .hero__role { max-width: 100%; }
  .role__mono {
    display: inline;
    overflow-wrap: anywhere;
    word-break: break-word;
  }
  .hero__name { font-size: clamp(1.9rem, 9vw, 2.6rem); overflow-wrap: anywhere; }

  /* 卡片内边距收紧，避免内容贴边被圆角裁掉 */
  .about__card, .project__card, .repos, .social__card {
    padding: 20px 18px;
  }
  .section__title { font-size: clamp(1.35rem, 7vw, 1.9rem); }
  .section__head { margin-bottom: 18px; }

  /* 视频卡：小屏单列，缩略图整宽 */
  .video { grid-template-columns: minmax(0, 1fr); gap: 12px; padding: 16px; }
  .video__thumb { width: 100%; }
  .video--feature { grid-template-columns: minmax(0, 1fr); }

  /* 账号卡：头像和文字在极窄屏上改为上下堆叠 */
  .social__card { grid-template-columns: minmax(0, 1fr); justify-items: start; gap: 14px; }
  .social__stats { gap: 18px; }

  /* 仓库行：元信息换行，不挤压名字 */
  .repo { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .repo__meta { flex-wrap: wrap; gap: 10px; }
}

/* 兜底：任何情况下都不出现横向滚动 */
html, body { max-width: 100%; overflow-x: hidden; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .bg__blob { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
}

@media print {
  .bg, .topbar, .footer__hint { display: none; }
  .glass { box-shadow: none; border-color: #999; background: #fff; }
}

/* ==========================================================================
   12 排版 v2 —— 统一节奏 + 空间重分配
   问题：卡片都是 1120 宽满铺，hero 右半空着、长文横跨整屏（超过舒适测量宽度）。
   做法：容器/间距统一成一套；hero 收窄居中并把「行动按钮」拎到右栏；
        about / project 拆两栏；video 变三栏卡片；contact 居中 + 两栏 chips。
   （本节覆盖上面的旧布局规则，方便整块回退。）
   ========================================================================== */

/* --- 12.1 容器与节奏 --- */
.hero { padding: clamp(84px, 11vh, 128px) 0 clamp(24px, 4vh, 42px); }
.section { padding: clamp(30px, 5vh, 56px) 0; }
.section__head { max-width: 60ch; margin-bottom: clamp(18px, 2.6vh, 30px); }
.section__title { font-size: clamp(1.55rem, 3.2vw, 2.15rem); letter-spacing: -.01em; }
.section__desc { max-width: 56ch; }
.about__lede, .project__lede { max-width: 62ch; }

/* --- 12.2 Hero：收窄居中，≥820px 两栏（身份 | 行动） --- */
.hero__card {
  padding: var(--card-pad);
  border-radius: var(--r-xl);
}
@media (min-width: 820px) {
  .hero__card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "avatar cta"
      "eyebrow cta"
      "name    cta"
      "role    cta";
    align-content: center;
    align-items: center;
    column-gap: clamp(24px, 4vw, 58px);
    row-gap: 6px;
  }
  .hero__card .avatar { grid-area: avatar; margin: 0 0 10px; }
  .hero__card .eyebrow { grid-area: eyebrow; margin: 0; }
  .hero__card .hero__name { grid-area: name; }
  .hero__card .hero__role { grid-area: role; margin-top: 2px; }
  .hero__card .cta {
    grid-area: cta;
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    margin: 0;
    min-width: 196px;
  }
  .hero__card .cta .btn { justify-content: center; }
}

/* --- 12.3 About：两栏（大标语 | 正文） --- */
.about { gap: 20px; }
@media (min-width: 860px) {
  .about__card {
    display: grid;
    grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
    gap: clamp(20px, 3.4vw, 52px);
    align-items: start;
  }
  .about__bio { font-size: clamp(1.55rem, 2.8vw, 2.15rem); margin: 0; }
  .about__lede { margin: 0; }
}

/* --- 12.4 Project：两栏（介绍+按钮 | 特性表） --- */
@media (min-width: 900px) {
  .project__card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.06fr);
    gap: clamp(22px, 3.6vw, 54px);
    align-items: start;
  }
  .project__lede { margin: 0; }
  .project__card .cta { margin: 22px 0 0; }
  .project__card .feature { margin: 0; }
}

/* --- 12.5 Videos：三栏卡片（编号/箭头在上，标题描述在下） --- */
.videos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: var(--gap);
}
.video {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "num   arrow"
    "body  body";
  grid-template-rows: auto 1fr;
  align-content: start;
  gap: 14px;
  min-height: 170px;
  padding: clamp(20px, 2.4vw, 28px);
  border-radius: var(--r-lg);
}
.video__num { grid-area: num; font-size: .8rem; }
.video__arrow { grid-area: arrow; align-self: start; }
.video__body { grid-area: body; align-self: end; }
.video__title { font-size: 1.08rem; line-height: 1.35; }
.video__desc { margin-top: 6px; }
.video:hover { transform: translateY(-4px); }

/* --- 12.7 页脚节奏 --- */
.footer { padding: 40px 0 56px; }

/* --- 12.8 玻璃上的文字：细投影保证可读性 --- */
.btn { text-shadow: 0 1px 2px rgba(3, 6, 18, .45); }
.btn--primary { text-shadow: 0 1px 2px rgba(0, 12, 28, .55); }

/* --- 12.9 按钮/胶囊：留极淡的一层底 ---
   引擎把 .is-gpu 的底色清成透明，按钮就成了「随背景变脸」的浮动块，看着发飘。
   补一层很淡的白渐变（在 shader 输出之上、文字之下），任何背景上都读得出这是个「面」。 */
html[data-webgl-glass] .btn.is-gpu,
html[data-webgl-glass] .iconbtn.is-gpu,
html[data-webgl-glass] .tag.is-gpu,
html[data-webgl-glass] .chip.is-gpu {
  background: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, .05)) !important;
}

/* --- 12.10 统一尺度（本轮重点）---
   之前 hero(940 居中) / 其它(满容器 1120) / contact(920 居中) 三种左沿，看着散。
   现在：所有 section 共用同一容器宽度与同一左沿；大卡统一 --r-xl + --card-pad。 */
:root {
  --card-pad: clamp(26px, 3.4vw, 46px);
}
.hero__card,
.about__card,
.project__card {
  border-radius: var(--r-xl);
  padding: var(--card-pad);
}
.section__head,
.cards,
.videos,
.about,
.project,
.hero__card {
  width: 100%;
}
/* 顶栏、内容、页脚共用同一条左右边线 */
.topbar__inner { width: min(100%, var(--maxw)); }
.hero__card { max-width: none; margin-inline: 0; }

/* ==========================================================================
   13 排版 v3 —— 同一套网格，但每个区块构图不同（解决「太单调」）
   共同：容器 1120、同一左沿、同一套间距。
   不同：标题带编号+细线；about 卡在左、文字在右；project 反过来；videos 首卡放大；
        contact 标题与卡片并排。
   ========================================================================== */

/* --- 13.1 区块标题：编号 + 通栏细线 + 更大的字号 --- */
main { counter-reset: sec; }
.section { counter-increment: sec; }
.section__head {
  position: relative;
  max-width: none;
  padding-top: 20px;
  margin-bottom: clamp(20px, 3vh, 34px);
}
.section__head::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, .34) 0%,
    rgba(255, 255, 255, .10) 42%,
    rgba(255, 255, 255, 0) 100%);
}
.kicker {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .22em;
}
.kicker::before {
  content: "0" counter(sec) " / ";
  opacity: .55;
}
.section__title {
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.08;
}
.section__desc { margin-top: .8em; max-width: 48ch; }

/* --- 13.2 About：左侧玻璃卡（大标语） + 右侧无卡正文 --- */
.about {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(20px, 3.6vw, 56px);
  align-items: center;
}
.about__card {
  display: grid;
  align-content: center;
  min-height: 230px;
  border-radius: var(--r-xl);
  padding: var(--card-pad);
}
.about__bio {
  font-size: clamp(1.7rem, 3.1vw, 2.5rem);
  font-weight: 700;
  line-height: 1.22;
  letter-spacing: -.02em;
  margin: 0;
}
.about__side { display: grid; gap: 14px; align-content: center; }
.about__lede { font-size: 1.05rem; line-height: 1.75; color: var(--ink-dim); margin: 0; max-width: 46ch; }
.about__lede strong { color: var(--ink); }
.about__note {
  margin: 0;
  padding-left: 14px;
  border-left: 2px solid var(--accent);
  font-family: var(--mono);
  font-size: .84rem;
  color: var(--ink-mute);
}

/* --- 13.3 Project：左侧无卡介绍 + 按钮，右侧玻璃卡（特性表）--- */
.project {
  display: grid;
  grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr);
  gap: clamp(20px, 3.6vw, 56px);
  align-items: center;
}
.project__side { display: grid; gap: 20px; align-content: center; }
.project__lede { font-size: 1.02rem; line-height: 1.75; color: var(--ink-dim); margin: 0; max-width: 44ch; }
.project__lede strong { color: var(--ink); }
.project__side .cta { margin: 0; }
.project__card { border-radius: var(--r-xl); padding: var(--card-pad); }
.feature { margin: 0; }

/* --- 13.4 Videos：首卡放大（通栏两列 + 更高），后两张并排 --- */
.videos {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}
.video:first-child {
  grid-column: 1 / -1;
  min-height: 208px;
  padding: clamp(26px, 3vw, 38px);
}
.video:first-child .video__title { font-size: clamp(1.25rem, 2.2vw, 1.6rem); }
.video:first-child .video__desc { max-width: 52ch; }

/* --- 13.6 窄屏回落：全部单栏 --- */
@media (max-width: 900px) {
  .about, .project { grid-template-columns: 1fr; }
  .videos { grid-template-columns: 1fr; }
  .video:first-child { grid-column: auto; min-height: 0; }
}

/* --- 13.7 窄卡内的特性表：单列，左标签右状态 --- */
.project__card .feature {
  grid-template-columns: 1fr;
  gap: 30px;   /* ≥28：canvas 四周有 26px 投影留白，间距更小会互相叠 */
}
.project__card .feature li {
  padding: 11px 16px;
  border-radius: 12px;
}
.feature__k { white-space: nowrap; }
.feature__v { white-space: nowrap; }
/* --- 13.8 About 大标语：自然换行 + 更舒展 --- */
.about__card { min-height: 260px; }
.about__bio { max-width: 20ch; }

/* --- 13.10 About 大标语：字号收一点、不限宽，避免出现单字成行 --- */
.about__bio {
  font-size: clamp(1.6rem, 2.7vw, 2.2rem);
  max-width: none;
  line-height: 1.25;
  text-wrap: balance;
}

/* ==========================================================================
   14 排版 v4（定稿方向 A）—— 满宽卡片 + 卡内两栏
   规则：每个区块的内容块都用同一条 1120 边线；两栏一律放在「卡片内部」；
        变化只来自字号层级、编号标题、细线与留白节奏，不再有半宽错位卡。
   ========================================================================== */

/* --- 14.1 About：满宽卡，卡内「大标语 | 正文+注」 --- */
.about { display: block; }
.about__card {
  display: grid;
  grid-template-columns: minmax(0, .92fr) minmax(0, 1.08fr);
  gap: clamp(24px, 4vw, 68px);
  align-items: center;
  min-height: 0;
  padding: clamp(30px, 3.8vw, 54px);
  border-radius: var(--r-xl);
}
.about__bio {
  font-size: clamp(1.7rem, 2.9vw, 2.4rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  margin: 0;
  max-width: none;
  text-wrap: balance;
}
.about__body { display: grid; gap: 16px; align-content: center; }
.about__lede { font-size: 1.05rem; line-height: 1.78; color: var(--ink-dim); margin: 0; max-width: 52ch; }
.about__lede strong { color: var(--ink); }
.about__note {
  margin: 0;
  padding-left: 14px;
  border-left: 2px solid var(--accent);
  font-family: var(--mono);
  font-size: .84rem;
  color: var(--ink-mute);
}

/* --- 14.2 Project：满宽卡，卡内「介绍+按钮 | 特性表」 --- */
.project { display: block; }
.project__card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: clamp(24px, 4vw, 68px);
  align-items: center;
  padding: clamp(30px, 3.8vw, 54px);
  border-radius: var(--r-xl);
}
.project__side { display: grid; gap: 22px; align-content: center; }
.project__lede { font-size: 1.05rem; line-height: 1.78; color: var(--ink-dim); margin: 0; max-width: 46ch; }
.project__lede strong { color: var(--ink); }
.project__side .cta { margin: 0; }
/* 同样要 ≥28px：单列时行距太小会让玻璃 canvas 的投影互相叠 */
.project__card .feature { grid-template-columns: 1fr; gap: 30px; margin: 0; }
.project__card .feature li { padding: 12px 16px; border-radius: 12px; overflow: hidden; }
.project__card .feature li .feature__k,
.project__card .feature li .feature__v { white-space: normal; }

/* --- 14.3 Videos：首卡通栏（仍是 1120 边线），后两张并排 --- */
.videos { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.video:first-child {
  grid-column: 1 / -1;
  min-height: 196px;
  padding: clamp(26px, 3vw, 38px);
}
.video:first-child .video__title { font-size: clamp(1.3rem, 2.3vw, 1.7rem); }
.video:first-child .video__desc { max-width: 56ch; }

/* --- 14.4 Contact：标题回到上方，卡片满宽 + 两栏行 --- */
#contact { display: block; }
#contact .section__head { margin-bottom: clamp(20px, 3vh, 34px); }
.contact {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  padding: clamp(30px, 3.8vw, 54px);
  border-radius: var(--r-xl);
}
.contact__row:last-child:nth-child(odd) { grid-column: 1 / -1; }

/* --- 14.5 窄屏：两栏全部收成一栏 --- */
@media (max-width: 900px) {
  .about__card, .project__card { grid-template-columns: 1fr; }
  .videos { grid-template-columns: 1fr; }
  .video:first-child { grid-column: auto; min-height: 0; }
  .contact { grid-template-columns: 1fr; }
  .contact__row:last-child:nth-child(odd) { grid-column: auto; }
}

/* ==========================================================================
   15 新内容区块：视频封面 / Devlog / 公开仓库 / 账号详情
   ========================================================================== */

/* --- 15.1 视频卡：封面在上，文字在下；首卡通栏（封面在左） --- */
.video {
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "thumb thumb"
    "main  arrow";
  grid-template-rows: auto 1fr;
  gap: 16px;
  min-height: 0;
  padding: clamp(14px, 1.6vw, 18px);
}
.video__thumb {
  grid-area: thumb;
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
}
.video__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.video__thumb--ph {
  display: grid;
  place-items: center;
  background:
    radial-gradient(120% 120% at 18% 8%, rgba(124, 199, 255, .30), transparent 62%),
    linear-gradient(158deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, .02));
}
.video__thumb--ph span {
  font-family: var(--mono);
  font-size: 1.7rem;
  letter-spacing: .12em;
  color: var(--ink);
  opacity: .55;
}
.video__main { grid-area: main; display: grid; gap: 8px; align-content: start; padding: 2px 4px 4px; }
.video__arrow { grid-area: arrow; align-self: end; }
.video__num { font-size: .76rem; }

@media (min-width: 900px) {
  .video--feature {
    grid-template-columns: 360px minmax(0, 1fr) auto;
    grid-template-areas: "thumb main arrow";
    align-items: center;
    gap: clamp(20px, 3vw, 44px);
    padding: clamp(18px, 2vw, 24px);
  }
  .video--feature .video__title { font-size: clamp(1.3rem, 2.2vw, 1.7rem); }
  .video--feature .video__main { padding: 0; }
  .video--feature .video__desc { max-width: 52ch; }
}

/* --- 15.3 公开仓库 --- */
.repos {
  display: grid;
  gap: 18px;
  padding: var(--card-pad);
  border-radius: var(--r-xl);
}
.repos__list { display: grid; gap: 30px; }
.repo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 4px 16px;
  padding: 15px 18px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, .10);
  background: rgba(255, 255, 255, .04);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  transition: background .25s ease, transform .25s ease;
}
.repo:hover { background: rgba(255, 255, 255, .09); transform: translateX(3px); }
.repo:active { transform: scale(.985); transition: transform .09s ease; }
.repo__name { font-family: var(--mono); font-size: .95rem; font-weight: 700; }
.repo__meta { display: flex; gap: 14px; font-family: var(--mono); font-size: .76rem; color: var(--ink-mute); }
.repo__desc { grid-column: 1 / -1; margin: 2px 0 0; font-size: .86rem; color: var(--ink-mute); }
.repos__hint { margin: 0; font-size: .9rem; color: var(--ink-mute); }
.repos__more { font-family: var(--mono); font-size: .84rem; color: var(--accent); text-decoration: none; }
.repos__more:hover { text-decoration: underline; }

/* --- 15.4 账号详情：两张卡并排 --- */
.social {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
  align-items: stretch;   /* 两卡等高，视觉基线一致 */
}
.social__card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  align-content: start;
  gap: 18px;
  padding: var(--card-pad);
  border-radius: var(--r-xl);
}
.social__body { display: grid; align-content: start; gap: 0; min-width: 0; }
.social__avatar {
  width: 72px; height: 72px; border-radius: 50%; object-fit: cover;
  align-self: start;
}
.social__avatar--qq { border-radius: 22px; }
.social__name { margin: 0; font-size: 1.22rem; font-weight: 700; }
.social__meta { margin: 5px 0 0; font-family: var(--mono); font-size: .76rem; color: var(--ink-mute); }
.social__stats { list-style: none; display: flex; flex-wrap: wrap; gap: 24px; margin: 16px 0 0; padding: 0; }
.social__stats li { display: grid; gap: 2px; }
.social__stats b { font-size: 1.12rem; font-weight: 700; }
.social__stats span { font-size: .78rem; letter-spacing: .1em; color: var(--ink-mute); }
.social__link { display: inline-block; margin-top: 16px; font-family: var(--mono); font-size: .84rem; color: var(--accent); text-decoration: none; }
.social__link:hover { text-decoration: underline; }
.social__actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }

@media (max-width: 900px) {
  .social { grid-template-columns: 1fr; }
  .video--feature { grid-template-columns: minmax(0, 1fr); grid-template-areas: "thumb" "main" "arrow"; }
}

/* --- 16 卡片动效：hover 边角收紧 -----------------------------------------
   GPU 模式：webgl-glass.js 里监听 data-tilt 卡片 hover，逐帧收紧 shader 圆角。
   CSS 回退（引擎未激活时）用同样的参数做 border-radius 过渡，行为一致。 */
.glass[data-tilt] {
  transition:
    border-radius .32s cubic-bezier(.22, .8, .28, 1),
    backdrop-filter .55s var(--ease-spring),
    background .55s var(--ease-spring),
    box-shadow .55s var(--ease-spring);
}
.glass[data-tilt]:hover { border-radius: calc(var(--r-xl) - 14px); }

/* =========================================================================
   17 联系区新版排版 + 赞赏码浮标 + QQ 在线状态
   -------------------------------------------------------------------------
   联系区：左侧「最快找到我」主渠道大卡（QQ / Email 强调），
           右侧三个次要渠道小方块（GitHub / Bilibili / 官网）。
   赞赏码：固定在屏幕右侧中部，hover 出提示语，点击展开二维码。
   ========================================================================= */

/* --- 17.1 联系区：主次分明 --- */
/* 联系区标题在左、卡片在右会显得空；改成整行标题 + 满宽卡片，
   内部两栏（主渠道 | 次要渠道），和页面其它区块同一条 1120 边线。 */
#contact { grid-template-columns: minmax(0, 1fr); align-items: start; }
#contact .section__head { margin-bottom: clamp(16px, 2.2vw, 26px); }
.contact {
  display: grid;
  /* 左主渠道 | 右次要渠道，底部再单独一条通栏的「常用 ID」。
     两大块保持原尺寸原比例，ID 条只负责填掉底部空行，不挤占左右。 */
  grid-template-columns: minmax(0, .86fr) minmax(0, 1.14fr);
  grid-template-rows: auto auto;
  gap: clamp(12px, 1.6vw, 20px);
  align-items: stretch;
  padding: var(--card-pad);
  border-radius: var(--r-xl);
}
/* 底部通栏：横跨两列 */
.contact__ids {
  grid-column: 1 / -1;
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 58px;
  padding: 14px 20px;
  border-radius: var(--r-md);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
}
.contact__primary {
  display: grid;
  grid-template-rows: auto 1fr 1fr;
  gap: 10px;
  align-content: stretch;
}
.contact__eyebrow {
  margin: 0 0 2px;
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: .9;
}

/* 主渠道：大号数字 + 复制提示。卡片本身带 .glass（引擎渲染主题材质），
   这里只留布局与文字，不自绘底色/边框。
   ⚠ 不写 transition: transform —— 内层卡的 transform 由引擎每帧内联写入
   （hover 收缩 + tilt），CSS 过渡会和它打架，表现为「卡片不缩小 / 抽搐」。 */
.contact__main {
  position: relative;
  display: grid;
  align-content: center;
  gap: 2px;
  width: 100%;
  padding: 16px 18px;
  border-radius: var(--r-md);
  text-align: left;
}
/* ⚠ 不加 :hover / :active 的 transform：引擎每帧写内联 transform（hover 收缩 +
   tilt），CSS 的 hover 规则虽然优先级低，但在引擎没接管 transform 的元素上仍会生效，
   和收缩叠加成「位移 + 缩小」的复合效果，看着发飘。内层卡的反馈由引擎负责
   （边角收紧 + 玻璃收缩）。 */
.contact__main-k {
  font-size: .74rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-mute);
}
.contact__main-v {
  font-family: var(--mono);
  font-size: 1.24rem;
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--ink);
}
.contact__main-v--sm { font-size: .98rem; }
.contact__main-hint {
  position: absolute; right: 16px; bottom: 14px;
  font-size: .76rem; color: var(--ink-mute);
  opacity: 0; transform: translateY(3px);
  transition: opacity .22s ease, transform .22s ease, color .22s ease;
}
.contact__main:hover .contact__main-hint { opacity: 1; transform: none; color: var(--accent); }
.contact__main.is-copied .contact__main-hint { opacity: 1; transform: none; color: var(--accent); }
.contact__main--sub { padding: 13px 18px; }
.contact__main--sub .contact__main-k { font-size: .72rem; }

/* 次要渠道：三块方卡，和左侧主渠道等高铺满。
   注意：方块本身带 .glass + .js-glass（由引擎渲染主题材质）+ data-tilt
   （hover 收缩交给引擎），这里只负责布局与内边距，
   不再自绘底色/边框、也不写 transform 过渡 —— 否则会和 shader 打架，
   表现为「中间那块没有主题效果」或「小卡片不跟着缩小」。 */
/* 第三块已移到底部通栏 .contact__ids，网格里只留两块 */
.contact__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: 1fr;
  gap: 10px;
  align-content: stretch;
}
.contact__tile {
  position: relative;
  display: grid;
  align-content: center;
  gap: 4px;
  padding: 16px 18px;
  border-radius: var(--r-md);
  color: inherit;
  text-decoration: none;
  overflow: hidden;
}
.contact__tile-k {
  font-size: .74rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-mute);
}
.contact__tile-v { font-size: .92rem; font-weight: 600; overflow-wrap: anywhere; }
.contact__tile-arrow {
  position: absolute; top: 12px; right: 14px;
  font-size: .9rem; color: var(--accent);
  opacity: .55; transition: transform .25s ease, opacity .25s ease;
}
.contact__tile:hover .contact__tile-arrow { opacity: 1; transform: translate(2px, -2px); }

/* --- 底部通栏「常用 ID」：一条扁玻璃，左标签右值 --- */
.contact__ids-k {
  flex: none;
  font-size: .74rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-mute);
}
.contact__ids-v {
  font-family: var(--mono);
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.contact__ids-v i {
  font-style: normal;
  color: var(--ink-mute);
  padding: 0 2px;
}
.contact__ids-arrow {
  margin-left: auto;
  flex: none;
  font-size: .9rem; color: var(--accent);
  opacity: .55; transition: transform .25s ease, opacity .25s ease;
}
.contact__ids:hover .contact__ids-arrow { opacity: 1; transform: translate(2px, -2px); }

/* --- 17.2 QQ 在线状态 --- */
.social__status {
  display: flex; align-items: center; gap: 7px;
  margin: 5px 0 0;
  font-family: var(--mono);
  font-size: .8rem;
  color: var(--ink-dim);
}
.status-dot {
  position: relative;
  width: 7px; height: 7px; border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 8px rgba(74,222,128,.85);
  flex: none;
}
/* 在线呼吸圈 */
.status-dot::after {
  content: "";
  position: absolute; inset: -4px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(74,222,128,.55), transparent 70%);
  animation: onlinePulse 2.4s ease-in-out infinite;
}
@keyframes onlinePulse {
  0%, 100% { transform: scale(.8); opacity: .5; }
  50%      { transform: scale(1.3); opacity: 1; }
}
.status-sep { color: var(--ink-mute); opacity: .55; }
.status-device { color: var(--ink-mute); }

/* --- 17.3 赞赏码浮标（贴屏幕右缘，默认只露一颗爱心）---
   质感与主题三种玻璃一致：按钮带 .glass + .js-glass，由 WebGL 引擎按当前材质渲染，
   所以切 blur / liquid / fusion 时它也跟着变。
   默认大半藏在屏幕外，只留爱心；hover 时整块滑出 + 提示语。 */
.tip {
  position: fixed;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  z-index: 60;
  /* 半隐藏时按钮在屏幕外，靠 .tip 这块命中区接住鼠标，否则永远触发不了滑出 */
  min-width: 52px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.tip__btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 7px;
  padding: 12px 16px;
  /* 贴边：左侧圆角、右侧切平，像从屏幕边缘探出来的玻璃片 */
  border-radius: var(--r-pill) 0 0 var(--r-pill);
  color: var(--ink);
  font: 600 .82rem/1 var(--font);
  cursor: pointer;
  overflow: hidden;
  /* 半隐藏时露出的宽度 = 爱心那一块；用固定的 34px，不随文字长度变化 */
  transform: translateX(calc(100% - 34px));
  transition:
    transform .46s cubic-bezier(.22,.8,.28,1),
    border-radius .46s cubic-bezier(.22,.8,.28,1);
  /* 贴边一侧不加投影，和浏览器边缘「融」在一起；只在左侧留一点柔和外溢 */
  box-shadow: -10px 0 26px -12px rgba(0, 0, 0, .55);
}
/* 未 hover 时给爱心一点微光脉动，暗示这里有东西 */
.tip__btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(60% 100% at 22% 50%, rgba(255, 178, 120, .28), transparent 70%);
  opacity: .5;
  transition: opacity .3s ease;
  pointer-events: none;
}
.tip:hover .tip__btn::after,
.tip.is-open .tip__btn::after { opacity: 1; }

/* 滑出：整块进入视口，圆角恢复成完整药丸 */
.tip:hover .tip__btn,
.tip.is-open .tip__btn {
  transform: translateX(0);
  border-radius: var(--r-pill);
}
.tip__btn:active { transform: translateX(0) scale(.95); }
/* 引擎接管后：canvas 要向外溢出 26px 画投影，overflow 必须放开 */
.tip__btn.is-gpu { overflow: visible; }
.tip__btn.is-gpu > canvas.glass-out { border-radius: inherit; }
.tip__ico {
  position: relative;
  z-index: 1;
  color: #ffb37a;
  font-size: 1rem;
  line-height: 1;
  filter: drop-shadow(0 0 6px rgba(255, 150, 90, .55));
  animation: tipHeart 3.2s ease-in-out infinite;
}
@keyframes tipHeart {
  0%, 100% { transform: scale(1); }
  45%      { transform: scale(1.16); }
  60%      { transform: scale(.98); }
}
.tip__label { position: relative; z-index: 1; white-space: nowrap; }

/* 提示语：悬在按钮左侧 */
.tip__hint {
  position: absolute;
  right: calc(100% + 10px);
  top: 50%;
  padding: 8px 14px;
  border-radius: var(--r-pill);
  /* 材质由玻璃引擎渲染（.glass .js-glass）→ 跟当前主题三种样式统一。
     这里只留文字与定位；不写死深色底，否则和 liquid/fusion 割裂。 */
  color: var(--ink);
  font-size: .8rem;
  white-space: nowrap;
  opacity: 0;
  transform: translate(10px, -50%) scale(.94);
  pointer-events: none;
  transition: opacity .22s ease, transform .3s cubic-bezier(.22,.8,.28,1);
}
.tip:hover .tip__hint { opacity: 1; transform: translate(0, -50%) scale(1); }
/* 面板展开时隐藏提示语（两者都在按钮左侧，会互相压住）。
   ⚠ 必须写成 :not(:hover)：.tip 常驻 .is-open（展开二维码后不会自己消失），
     如果无条件压 opacity，悬停时提示语永远出不来；而语言切换时 morphText
     会用 WAAPI 短暂接管 opacity，反而让提示语闪一下露出来。
     加上 :not(:hover) 后，只有「面板开着且鼠标没碰到」才藏起来。 */
.tip.is-open:not(:hover) .tip__hint { opacity: 0; transform: translate(10px, -50%) scale(.94); }

/* 二维码面板：默认隐藏，点击后在按钮左侧展开。
   用与主题一致的浅色玻璃（不是黑色卡片）—— 深黑底和整站玻璃语言割裂。 */
.tip__panel {
  position: absolute;
  right: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%) scale(.94);
  transform-origin: right center;
  width: 264px;
  padding: 14px;
  border-radius: var(--r-lg);
  /* 材质同样交给引擎（.glass .js-glass）→ 选 Liquid 就是液态玻璃折射，
     选 Blur 才是毛玻璃；不再写死 backdrop-filter: blur()，那样三种模式看起来都一样。 */
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .26s ease, transform .34s cubic-bezier(.22,.8,.28,1), visibility .26s;
}
.tip.is-open .tip__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(-50%) scale(1);
  pointer-events: auto;
}
.tip__panel img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 10px;
  background: #fff;
}
.tip__cap {
  display: table;                /* 收缩到内容宽度，好让底色只包住文字 */
  margin: 10px auto 0;
  padding: 5px 12px;
  border-radius: var(--r-pill);
  /* 玻璃面板可能折射出很亮的背景，说明文字加一层暗底保证可读 */
  background: rgba(8, 12, 26, .55);
  font-size: .8rem;
  color: #eaf2ff;
}

/* 窄屏：浮标收成图标，二维码改为居中弹出 */
@media (max-width: 900px) {
  .tip { right: 12px; }
  .tip__label { display: none; }
  .tip__btn { padding: 10px; }
  .tip__hint { display: none; }
  .tip__panel {
    position: fixed;
    right: 12px; left: 12px; top: 50%;
    width: auto; max-width: 320px;
    margin-inline: auto;
    transform: translateY(-50%) scale(.94);
    transform-origin: center;
  }
  .tip.is-open .tip__panel { transform: translateY(-50%) scale(1); }
}

/* 联系区窄屏：主次堆叠 */
@media (max-width: 900px) {
  #contact { grid-template-columns: 1fr; }
  .contact { grid-template-columns: minmax(0, 1fr); }
  .contact__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .contact__grid { grid-template-columns: minmax(0, 1fr); }
}
