/* ============================================================
   YUQING_C · Portfolio
   高级感 / 呼吸感 · 黑白分块 · 双语
   ============================================================ */

/* ---------- Fonts ---------- */
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/cabinet/CabinetGrotesk-Regular.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/cabinet/CabinetGrotesk-Medium.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/cabinet/CabinetGrotesk-Bold.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Cabinet Grotesk';
  src: url('../assets/fonts/cabinet/CabinetGrotesk-Black.woff2') format('woff2');
  font-weight: 900; font-style: normal; font-display: swap;
}

/* ---------- Tokens ----------
   配色：黑、白、灰三种底，页面按区域换底（tone），每种底配一个字色：
   - stage 纯黑：开场、自我介绍、三个词那一屏、结尾联系那一屏（带一层很淡的点阵）
   - paper 纯白：简历、视觉设计那一章、作品分类页和详情
   - deep  炭灰：视频剪辑那一章和视频分类页（放映厅）
   - tint  浅灰：AI 那一章
   页面上的彩色只来自作品本身（分类页里没选中的作品是灰阶的，选中才上色）。
   --mark / --pop / --stage-mark：强调色，只用在关键词和「现在在哪」的小标记上
   （自我介绍里加粗的词、章节序号、导航圆点、进度线的线头、选中文字），分别用于浅底、深底和 stage 底。
   2026-10-17 重新配色：底色不再是纯黑纯白纯灰，每一套都带一点温度；三套可以换（地址加 ?palette=b 预览，会记住）：
   - a「宣纸 · 赭石」（默认）：暖白的纸、带一点棕的墨黑、烧陶一样的赭石红做强调
   - b「青瓷」：带一点绿的白和墨绿的黑，强调色是青瓷绿（和青筠那套品牌接得上）
   - c「夜蓝」：带一点蓝的白和深夜蓝的黑，强调色是柔一点的蓝紫
   次一级的文字、细线、毛玻璃都由当前区域的 --ink / --bg 按比例混出来（见 :root, .tone 那一段），不单独配色 */
:root {
  --paper: #F7F8FA; --paper-ink: #0E1116;
  --stage: #07080B; --stage-ink: #EEF1F6;
  --deep: #121317;  --deep-ink: #EEF1F6; /* 2026-10-18 视频那一章的底：原来的深海蓝改成黑（比结尾的黑浅一点点，结尾升上来时看得出边） */
  --tint: #E8EDF6;  --tint-ink: #0E1116;
  --mark: #2B57FF; --pop: #8DA4FF; --stage-mark: #7D97FF; /* 配色 a「黑 · 白 · 蓝」（2026-10-18 默认）：黑、白、深海蓝三种底，一种亮蓝做强调 */

  --bg: var(--paper); --ink: var(--paper-ink); --seal: var(--mark);
  --gut: max(calc((100vw - 1320px) / 2), clamp(24px, 6.5vw, 128px)); /* 和 .wrap 同样的左右留白（2026-10-17 加宽，多留白） */
  --ease: cubic-bezier(.22, 1, .36, 1);
  --font-en: 'Author', 'Cabinet Grotesk', -apple-system, sans-serif; /* 英文：Author（2026-10-18 换） */
  --font-zh-serif: 'Noto Serif SC', 'Songti SC', 'STSong', 'SimSun', serif; /* 中文标题：思源宋体，字重 300 / 600 / 800 三档 */
  --font-num: 'Author', 'Noto Serif SC', serif; /* 大号数字、序号、英文大标题（2026-10-18 换成 Author） */
  --font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Mono', 'SF Mono', Menlo, Consolas, 'Microsoft YaHei', monospace; /* 等宽：读数、计数、方括号小标签、英文小标签 */
  --font-body: -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
[data-palette="b"] { /* 配色 b「青瓷」 */
  --paper: #F1F4EF; --paper-ink: #15211B; --stage: #0E1714; --stage-ink: #E5EEE7;
  --deep: #18251F; --deep-ink: #E5EEE7; --tint: #DEE7DF; --tint-ink: #15211B;
  --mark: #2E6C56; --pop: #8FD0B2; --stage-mark: #94D4B6;
}
[data-palette="c"] { /* 配色 c「夜蓝」 */
  --paper: #F3F4F8; --paper-ink: #161928; --stage: #0C0F1B; --stage-ink: #E8EBF5;
  --deep: #171C2F; --deep-ink: #E8EBF5; --tint: #E2E5EF; --tint-ink: #161928;
  --mark: #3D4EC0; --pop: #9DABFF; --stage-mark: #A3B0FF;
}
/* 四种区域：各取调色盘里的一对底色和字色 */
.tone-paper { --bg: var(--paper); --ink: var(--paper-ink); --seal: var(--mark); }
.tone-stage { --bg: var(--stage); --ink: var(--stage-ink); --seal: var(--stage-mark); }
.tone-deep  { --bg: var(--deep);  --ink: var(--deep-ink);  --seal: var(--pop); }
.tone-tint  { --bg: var(--tint);  --ink: var(--tint-ink);  --seal: var(--mark); }
/* 由当前区域的字色、底色混出来的次级颜色。必须在每个 .tone 上重新算一遍：
   自定义属性继承的是算好的值，只在 :root 上写的话，区域里换了 --ink 它们不会跟着变 */
:root, .tone, .resume-card {
  --ink-2: color-mix(in srgb, var(--ink) 70%, transparent);
  --ink-3: color-mix(in srgb, var(--ink) 48%, transparent);
  --line: color-mix(in srgb, var(--ink) 17%, transparent);
  --line-soft: color-mix(in srgb, var(--ink) 9%, transparent);
  --nav-rule: color-mix(in srgb, var(--ink) 36%, transparent); /* 导航线及其刻度、胶囊描边 */
  --accent: var(--ink);
  --accent-soft: color-mix(in srgb, var(--ink) 8%, transparent);
  --accent-glow: color-mix(in srgb, var(--ink) 26%, transparent);
  --card: var(--bg);
  --glass: color-mix(in srgb, var(--bg) 76%, transparent);
  --shadow: 0 24px 60px -24px rgba(0, 0, 0, .22);
}
.tone { color: var(--ink); } /* 文字色是继承来的算好的值，换了变量要在这里重新取一次 */


/* ---------- Reset / Base ---------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
html, body { height: 100%; }
body {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--ink);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  transition: background-color .8s var(--ease), color .8s var(--ease);
}
img, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }
::selection { background: var(--seal); color: #FFFFFF; }

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

.wrap { width: min(1320px, 100% - clamp(48px, 13vw, 256px)); margin-inline: auto; } /* 左右留白加宽 */

/* ---------- Navigation ----------
   导航线：左上角的签名 logo 沿笔顺画成一条矢量线（svg.nav-line，由 main.js initNavLine 排版），
   收笔的尾巴顺势放平，一路延长成横贯导航的细线；导航项坐在线上、各带一个刻度，
   当前板块用线上的圆点（.nav-dot）标出，右侧开关的胶囊接在线的尽头。
   --nav-line-y：线到导航顶边的距离；--nav-logo-h：logo 的高度 */
.nav {
  --nav-h: 62px; --nav-line-y: 47px; --nav-logo-h: 28px;
  position: fixed; top: 0; left: 0; right: 0; z-index: 900; padding-top: 14px;
  transition: background .6s var(--ease), backdrop-filter .6s var(--ease), transform .6s var(--ease);
}
.nav.nav-sync { transition: transform .6s var(--ease); } /* 跟章内换色同步时，底色不再自己慢慢过渡 */
/* 导航是一枚浮着的透明胶囊（照 weevolveit.com）：一圈细边，里面是很淡的半透明底色加毛玻璃，底下的内容隐约透上来。
   胶囊画在 .nav-inner::before 上、往两边各多出一截，里面的签名、导航项、开关的坐标都不用动 */
.nav-inner {
  position: relative; isolation: isolate;
  display: flex; align-items: flex-start; justify-content: space-between;
  height: var(--nav-h);
}
.nav-inner::before {
  content: ''; position: absolute; inset: 0 -26px; z-index: -1; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--ink) 14%, transparent);
  background: color-mix(in srgb, var(--bg) 46%, transparent);
  -webkit-backdrop-filter: blur(16px) saturate(1.3); backdrop-filter: blur(16px) saturate(1.3);
  box-shadow: 0 10px 30px -18px rgba(0, 0, 0, .35);
  transition: background-color .6s var(--ease), border-color .6s var(--ease);
}
.nav.nav-sync .nav-inner::before { transition: none; }
.nav-line { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.nav-line path { stroke-width: 1.25px; }
.brand { display: block; flex: none; } /* 可点范围 = logo 的范围，尺寸由 initNavLine 写入 */
.brand-sig {
  height: var(--nav-logo-h); width: auto; display: block;
  transition: filter .5s var(--ease), opacity .5s var(--ease);
}
.nav.has-sigline .brand-sig { display: none; } /* logo 已由导航线画出；没有笔顺数据时才显示这张位图 */
.tone-stage .brand-sig, .tone-deep .brand-sig { filter: invert(1); } /* 位图 logo 是墨色的：压在深色底上时反成白色 */
/* 签名开场期间整条导航隐藏（黑场只留签名）；落定后按「写出 logo → 线延长到头 → 导航项出现」进场 */
html.landing .nav { visibility: hidden; }
.nav-links {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: flex; gap: clamp(36px, 5.2vw, 76px);
}
.nav-links a {
  position: relative; padding: 4px 2px;
  font-size: 13px; letter-spacing: .22em; color: var(--ink-2);
  transition: color .4s var(--ease), opacity .5s var(--ease), transform .5s var(--ease);
}
/* 刻度：每个导航项正下方、压在线上 */
.nav-links a::after {
  display: none; /* 胶囊导航：不要刻度，当前项只用下面的小圆点标出 */
  content: ''; position: absolute; left: 50%; top: calc(100% + 5px);
  width: 1px; height: 6px; margin-left: -.5px; background: var(--nav-rule);
  transition: top .3s var(--ease), height .3s var(--ease), background-color .3s var(--ease), opacity .3s var(--ease);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after { top: calc(100% + 3px); height: 10px; background: var(--ink); }
.nav-links a.active { color: var(--ink); }
.nav-links a.active::after { opacity: 0; } /* 当前项的刻度让给圆点 */
/* 当前板块的圆点：沿线滑到对应导航项正下方（--x 由 initNavLine 写入） */
.nav-dot {
  position: absolute; left: 0; top: var(--nav-line-y);
  width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px; border-radius: 50%;
  background: var(--seal); pointer-events: none;
  opacity: 0; transform: translateX(var(--x, 0px)) scale(.2);
  transition: transform .7s var(--ease), opacity .4s var(--ease), background-color .8s var(--ease);
}
.nav-dot.on { opacity: 1; transform: translateX(var(--x, 0px)) scale(1); }
/* 进场前：导航项、圆点、右侧开关先藏着，等线画到头再出现（initNavLine 摘掉 nav-pre、挂上 nav-in） */
.nav.nav-pre .nav-links a { opacity: 0; transform: translateY(6px); }
.nav.nav-pre .nav-ctrl,
.nav.nav-pre .brand-sig { opacity: 0; }
.nav.nav-pre.nav-logo-in .brand-sig { opacity: 1; } /* 位图 logo：大签名飞到后先显出来，再延长线 */
.nav.nav-pre .nav-dot.on { opacity: 0; transform: translateX(var(--x, 0px)) scale(.2); }
.nav.nav-in .nav-links a:nth-child(2) { transition-delay: 70ms; }
.nav.nav-in .nav-links a:nth-child(3) { transition-delay: 140ms; }
.nav.nav-in .nav-ctrl { transition-delay: 220ms; }
.nav.nav-in .nav-dot { transition-delay: 320ms; }
.nav-ctrl {
  display: flex; align-items: center; gap: 14px;
  height: 34px; margin-top: calc((var(--nav-h) - 34px) / 2); /* 在导航胶囊里上下居中 */
  transition: opacity .5s var(--ease);
}
.nav-ctrl .ctrl-btn { height: 34px; padding-block: 0; border-color: var(--nav-rule); }
/* 两个胶囊之间补一小段线：签名 → 线 → 胶囊是连着的一笔 */
.ctrl-btn {
  font-size: 12.5px; letter-spacing: .1em;
  color: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 7px 14px;
  display: inline-flex; align-items: center; gap: 8px;
  position: relative; overflow: visible;
  transition: color .4s var(--ease), border-color .4s var(--ease), background .4s var(--ease);
}
.ctrl-btn:hover { color: var(--ink); border-color: var(--accent); }
.ctrl-btn .sep { opacity: .4; }
.ctrl-btn .opt { transition: color .3s var(--ease); }
.ctrl-btn .opt.active { color: var(--accent); font-weight: 600; }
/* 汉堡 */
.burger {
  display: none; width: 40px; height: 40px;
  position: relative; z-index: 1002;
}
.burger span {
  position: absolute; left: 9px; right: 9px; height: 1.5px;
  background: var(--ink); transition: transform .5s var(--ease), top .5s var(--ease), opacity .4s;
}
.burger span:nth-child(1) { top: 15px; }
.burger span:nth-child(2) { top: 24px; }
.burger.open span:nth-child(1) { top: 19.5px; transform: rotate(45deg); }
.burger.open span:nth-child(2) { top: 19.5px; transform: rotate(-45deg); }
.mobile-menu {
  position: fixed; inset: 0; z-index: 1001;
  background: var(--bg);
  display: flex; flex-direction: column; justify-content: center;
  padding: 0 clamp(32px, 10vw, 80px);
  opacity: 0; visibility: hidden;
  transition: opacity .5s var(--ease), visibility 0s linear .5s;
}
.mobile-menu.open { opacity: 1; visibility: visible; transition: opacity .5s var(--ease); }
.mobile-menu a {
  font-family: var(--font-zh-serif);
  font-size: clamp(34px, 9vw, 52px);
  padding: 18px 0; border-bottom: 1px solid var(--line-soft);
  display: flex; justify-content: space-between; align-items: baseline;
  transform: translateY(24px); opacity: 0;
  transition: transform .6s var(--ease), opacity .6s var(--ease);
}
.mobile-menu a small { font-family: var(--font-en); font-size: 13px; letter-spacing: .15em; color: var(--ink-3); }
.mobile-menu.open a { transform: none; opacity: 1; }
.mobile-menu.open a:nth-child(1) { transition-delay: .08s; }
.mobile-menu.open a:nth-child(2) { transition-delay: .16s; }
.mobile-menu.open a:nth-child(3) { transition-delay: .24s; }
.mobile-menu .menu-ctrl { display: flex; gap: 12px; margin-top: 40px; }

/* ---------- Hero · 签名首屏：整屏品牌蓝（.tone-stage，和自我介绍那一屏同色）+ 居中签名书写动画 ----------
   首屏内联脚本在首帧前定好：播开场加 html.landing（fixed 全屏遮罩）+ html.lock（锁滚），
   不播加 html.intro-off（hero 不占位）。写毕签名副本滑向左上角，快到位时这一层淡出、露出同色的自我介绍那一屏，
   副本落在导航 logo 上，结束后 hero 隐藏。深链 / snap / 同一次浏览里从别的页面回来：直接落定。 */
.hero {
  position: relative;
  height: 100vh; height: 100svh;
  min-height: 520px;
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
}
.hero[hidden], html.intro-off .hero { display: none; }
html.landing .hero {
  position: fixed; inset: 0;
  z-index: 800; /* 低于导航（900），高于页面内容 */
  will-change: opacity;
}
html.lock, html.lock body { overflow: hidden; }
html.lock { overscroll-behavior: none; }
.sig-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
}
/* 落地转场中的飞行签名（fixed，从屏幕中央滑到左上角、缩到与导航 logo 重合）。
   里面叠着两张同样的签名：白的在上，页面墨色的垫在下面；黑场叠化成页面时两张交叉淡化，
   签名跟着底色换色（落点和开场同色时只有一张）。只动位移和透明度 */
.sig-fly {
  position: fixed; z-index: 850; pointer-events: none;
  transform-origin: 0 0;
  will-change: transform;
}
.sig-fly img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* ---------- 惯性平滑滚动开着的时候（main.js initSmooth）：浏览器自己的平滑滚动要关掉，不然两个会打架 ---------- */
html.lenis { scroll-behavior: auto !important; }

/* ---------- 底色过渡：横着扫，没有竖着的渐变（.tone-wipe） ----------
   两块不同底色之间放一条：它盖在上一块的最后一屏上（margin-top: -100vh），里面一屏高的窗口贴住不动，
   下一块的颜色带着一段渐变的前沿从右往左扫过去，扫完整屏就是下一块的颜色，下一块直接接上。
   只用在章与章之间（三个词那一屏 → 第一章、最后一章 → 结尾，她说不要，两块直接相接）。
   照 landonorris.com 的「不知不觉就变了」：前沿的渐变拉得很长（--lead 比两屏还宽），一屏里只看得到一小段，
   整屏像是一起慢慢变色，而不是一道边扫过去；并且提前开始（--early：还在上一章最后那一段的时候就开始漫过来），
   走得慢（--dist：整段过渡要滚这么远）
   动画挂在滚动位置上（animation-timeline），不经过脚本；不支持的浏览器和减少动态效果下不出现，两块直接相接。
   渐变的几个停靠点按「慢—快—慢」取，前沿不会有一道看得出来的边 */
.tone-wipe.tone-paper { --wash: var(--paper); } .tone-wipe.tone-deep { --wash: var(--deep); }
.tone-wipe.tone-tint { --wash: var(--tint); } .tone-wipe.tone-stage { --wash: var(--stage); }
.tw-pin i {
  position: absolute; top: 0; bottom: 0; left: 0; will-change: transform;
  background: linear-gradient(to right,
    transparent 0,
    color-mix(in srgb, var(--wash) 3%, transparent) calc(var(--lead) * .1),
    color-mix(in srgb, var(--wash) 16%, transparent) calc(var(--lead) * .25),
    color-mix(in srgb, var(--wash) 35%, transparent) calc(var(--lead) * .4),
    color-mix(in srgb, var(--wash) 50%, transparent) calc(var(--lead) * .5),
    color-mix(in srgb, var(--wash) 65%, transparent) calc(var(--lead) * .6),
    color-mix(in srgb, var(--wash) 84%, transparent) calc(var(--lead) * .75),
    color-mix(in srgb, var(--wash) 97%, transparent) calc(var(--lead) * .9),
    var(--wash) var(--lead));
}
.tone-wipe { display: none; }
@keyframes wipeX { from { transform: translate3d(100vw, 0, 0); } to { transform: translate3d(calc(var(--lead) * -1), 0, 0); } }
@supports (animation-timeline: view()) {
  .tone-wipe { --early: 110vh; --dist: 230vh;
    display: block; position: relative; z-index: 3; height: calc(100vh + var(--dist)); margin-top: calc(-100vh - var(--early)); pointer-events: none; view-timeline-name: --wipe;
    background: linear-gradient(transparent calc(100vh + var(--early)), var(--from) 0); } /* 前面那段叠在上一章上面（透明）；多出来的那一段自己铺上一章的颜色，等着被漫过去 */
  .tone-wipe[data-from="paper"] { --from: var(--paper); } .tone-wipe[data-from="stage"] { --from: var(--stage); }
  .tone-wipe[data-from="deep"] { --from: var(--deep); } .tone-wipe[data-from="tint"] { --from: var(--tint); }
  .tw-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; }
  .tw-pin i { --lead: 240vw; width: calc(var(--lead) + 100vw); animation: wipeX linear both; animation-timeline: --wipe; animation-range: contain 0% contain 100%; }
}
body.deck-mode .tone-wipe, html.snap .tone-wipe, .chapters.pinned .tone-wipe { display: none !important; }
@media (max-width: 960px) { /* 窄屏章节不钉、只有一屏左右高：扫得短一点，别把整章的卡片都盖住 */
  .tone-wipe { --early: -70vh !important; --dist: 120vh !important; } /* 只叠在这一章最后三成屏高（卡片下面的空处）上，不盖住卡片 */
  .tw-pin i { --lead: 130vw !important; }
} /* ?snap=1 截图模式：动画都停了，这一条也不出现 */

/* ---------- 视差：不同的东西跟着滚动走得不一样快 ----------
   加了 --par 的元素，从屏幕底下进来到从顶上出去的这一路上，比页面多走（正数）或少走（负数）这么多像素。
   用的是挂在滚动位置上的动画（animation-timeline: view()），由浏览器在合成线程里算，不经过脚本，只动位移；
   动的是 translate 这个单独的属性，和元素自己原有的 transform（进场、悬停）互不干扰。
   不支持的浏览器 / 减少动态效果 / ?snap=1：都不动 */
@keyframes parY { from { translate: 0 calc(var(--par, 40) * 1px); } to { translate: 0 calc(var(--par, 40) * -1px); } }
@supports (animation-timeline: view()) {
  .cyq .pol,
  .chapter-kicker, .chapter-foot,
  .closing-title, .closing-clock, .closing-ways, .closing-qr, .closing-sig,
  .st-row .st-fig, .st-row .st-text, .qy-row > .qy-fig, .qy-row > .qy-stage, .qy-row > .qy-text, .qy-quote, .vd-shot {
    animation: parY linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; will-change: translate;
  }
  .cyq .pol { animation-range: entry 0% exit 100%; } /* 拍立得：--par 写在每张照片上（index.html），数越大飘得越快 */
  .chapter-kicker { --par: 22; } .chapter-foot { --par: -22; }
  .closing-title { --par: 46; } .closing-clock { --par: 30; } .closing-ways { --par: 14; } .closing-qr { --par: -16; } .closing-sig { --par: -34; }
  .st-row .st-fig { --par: 34; } .st-row .st-text { --par: -14; }
  .qy-row > .qy-fig, .qy-row > .qy-stage { --par: 30; } .qy-row > .qy-text { --par: -14; } .qy-quote { --par: 26; }
  .vd-shot.p0, .vd-shot.p2, .vd-shot.p4 { --par: 16; } .vd-shot.p1, .vd-shot.p3, .vd-shot.p5 { --par: 44; }
}
@media (prefers-reduced-motion: reduce) {
  .tone-wipe { display: none !important; }
  .cyq .pol, .chapter-kicker, .chapter-foot,
  .closing-title, .closing-clock, .closing-ways, .closing-qr, .closing-sig, .st-row .st-fig, .st-row .st-text,
  .qy-row > .qy-fig, .qy-row > .qy-stage, .qy-row > .qy-text, .qy-quote, .vd-shot, .hl-in, .hw { animation: none !important; }
}

/* 黑底的几屏铺一层很淡的点阵，不是一片死黑 */
/* 点阵底只铺在浅色和蓝色的作品区（照 weevolveit），鼠标走过亮起来的那一层在 js/dot-field.js。
   作品那几章的点画在 .chapter::before 上——整章都铺满，包括章尾那段空白，不会缺一块 */
/* 点进去的页面（分类页、全部作品、作品详情）都不铺点阵 */
.chapter::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle, color-mix(in srgb, var(--ink) 13%, transparent) 1px, transparent 1.5px);
  background-size: 30px 30px;
}
.chapter > * { position: relative; z-index: 1; }
.chapters.pinned .chapter-pin { position: sticky; }
/* 宽屏：点阵是一张钉在屏幕上的静止底板——往下滚、长卷往左走，点都不动；每一章用 clip-path 裁一下，只在自己这一块里露出来 */
.chapters.pinned .chapter { clip-path: inset(0); }
.chapters.pinned .chapter::before { position: fixed; inset: 0; }
/* 黑底的几屏（自我介绍、三个词、精选作品、结尾）不铺点阵，换成：顶上一团很淡的蓝光 + 一层细细的胶片颗粒，静的、不费电脑 */
.hello-screen, .cyq, .feat, .closing {
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 .05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(ellipse 70% 55% at 50% 0%, color-mix(in srgb, var(--mark) 16%, transparent), transparent 70%);
  background-size: 180px 180px, 100% 100%;
}
.hero { background: #000 !important; } /* 开场写 logo 的那一屏：纯黑 */

/* 滚动读数：右侧中间，页面滚到百分之几（三位数，等宽）。用差值混合，压在黑、白、灰哪种底上都看得清 */
.scroll-pct {
  position: fixed; right: clamp(10px, 1.3vw, 22px); top: 50%; z-index: 880;
  display: flex; flex-direction: column; align-items: flex-end; gap: 10px;
  transform: translateY(-50%);
  font-family: var(--font-mono); font-size: 13px; letter-spacing: .1em; line-height: 1;
  color: #FFFFFF; mix-blend-mode: difference; pointer-events: none;
  transition: opacity .5s var(--ease);
}
.scroll-pct i { width: 1px; height: 44px; background: currentColor; opacity: .5; transform-origin: 50% 0; transform: scaleY(var(--p, 0)); }
html.landing .scroll-pct, html.viewer-open .scroll-pct, body.deck-mode .scroll-pct { opacity: 0; }
@media (max-width: 960px) { .scroll-pct { display: none; } }

/* 方括号小标签：[ 视觉设计 ] 这种写法，等宽字 */
.chapter-cat::before, .cyq-hint::before { content: '[ '; }
.chapter-cat::after, .cyq-hint::after { content: ' ]'; }
.chapter-cat::before, .chapter-cat::after, .cyq-hint::before, .cyq-hint::after { font-family: var(--font-mono); font-weight: 400; letter-spacing: 0; color: var(--ink-3); }

/* ---------- Section base ---------- */
.section { padding: clamp(110px, 18vh, 220px) 0; position: relative; }
#about { padding-top: 0; padding-bottom: 0; } /* 首屏由 .hello-screen 撑满；最后是横扫的底色过渡，后面直接接作品 */
.sec-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 24px; flex-wrap: wrap;
  margin-bottom: clamp(48px, 7vh, 88px);
}
.sec-title { display: flex; align-items: baseline; gap: 20px; }
.sec-title .zh {
  font-family: var(--font-zh-serif);
  font-size: clamp(38px, 6vw, 72px);
  font-weight: 700; letter-spacing: .08em; line-height: 1.1;
}
.sec-title .en {
  font-family: var(--font-en); font-weight: 500;
  font-size: clamp(12px, 1.4vw, 15px);
  letter-spacing: .3em; text-transform: uppercase; color: var(--ink-3);
}
.sec-note { color: var(--ink-3); font-size: 13px; letter-spacing: .12em; }

/* 滚动进入 stagger */
.reveal { opacity: 0; transform: translateY(34px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: var(--d, 0ms);
}
/* 进场完成后撤掉过渡，视差才能逐帧写 transform */
.reveal.settled { transition: none; }

/* ---------- Works ---------- */
/* 点开文件夹/子类标签后才出现：默认隐藏，JS 加 .on 淡入上浮（REDUCED/?snap 瞬显）；.leaving 淡出下沉后隐藏 */
.works-deck { display: none; }
.works-deck.on { display: block; animation: deckIn .8s var(--ease); }
.works-deck.leaving {
  opacity: 0; transform: translateY(18px);
  transition: opacity .48s var(--ease), transform .48s var(--ease);
}
@keyframes deckIn {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}

/* deck 顶部：返回键（逐级退：L2→L1→首页）+ 当前层级标题（L1 后面跟着件数） */
.works-deck-bar {
  display: flex; align-items: baseline; gap: 26px;
  padding-bottom: 24px; border-bottom: 1px solid var(--line);
  margin-bottom: 34px;
}
.deck-back {
  font-size: 13px; letter-spacing: .14em; color: var(--ink-2);
  display: inline-flex; align-items: baseline; gap: 8px;
  transition: color .4s var(--ease), gap .4s var(--ease);
}
.deck-back:hover { color: var(--accent); gap: 13px; }
.deck-cat {
  font-family: var(--font-zh-serif);
  font-size: 17px; letter-spacing: .12em;
  display: inline-flex; align-items: baseline; gap: 12px;
}
.deck-cat small {
  font-family: var(--font-en); font-weight: 500;
  font-size: 10.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--ink-3);
}
.deck-n { font-family: var(--font-mono); font-style: normal; font-size: 12px; letter-spacing: .08em; color: var(--ink-2); }

/* deck 独立子页模式：只保留 .works-deck 本身（含返回键），上下滚动不会露出主页其他内容 */
body.deck-mode .nav,
body.deck-mode #about,
body.deck-mode .chapters,
body.deck-mode #featured, /* 精选作品只在首页它自己那一个位置出现，分类页、全部作品里都不出现 */
body.deck-mode #contact { display: none; }
body.deck-mode #works { padding: clamp(48px, 8vh, 88px) 0 72px; min-height: 100vh; background: var(--bg); } /* 视频分类是深色那一套（.tone-deep），底色要铺满整页 */

.works-stage { position: relative; min-height: 420px; scroll-margin-top: 92px; }
.works-view { transition: opacity .45s var(--ease), transform .45s var(--ease); }
.works-view.switching { opacity: 0; transform: translateY(14px); }

/* deck 两级视图互斥：L1 全部作品（data-view=dir）藏分类页；L2 分类页（data-view=grid）藏全部作品 */
.works-deck[data-view="dir"] .works-stage { display: none; }
.works-deck[data-view="grid"] .deck-dir { display: none; }
.works-deck[data-view="shop"] .works-stage, .works-deck[data-view="shop"] .deck-cat { display: none; } /* 分类页自己有大标题 */
.works-deck[data-view="shop"] .works-deck-bar { border-bottom: 0; margin-bottom: clamp(28px, 6vh, 64px); }

/* ---------- 分类页（照 pamidordesign.co/shop，main.js renderShop / shopCardHTML） ----------
   顶上左边：一个强调色小圆点和括号里的大类名，下面是分类名，特别大（另一种语言的名字小一号跟在下面）；右边一段说明。
   一条细线，下面一排方角小标签（同一章的各个分类，当前的是黑底），右边件数。
   卡片三列：浅底上放完整的作品图，左上角小标签；下面作品名和编号、再一行小字。鼠标移上去图慢慢放大一点。
   最下面「下一类」居中：括号小字、很大的分类名、一个黑底的小按钮 */
.shop-head { display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: 40px; align-items: end; }
.shop-kicker { display: flex; align-items: center; gap: 10px; font-family: var(--font-en); font-weight: 500; font-size: 12px; letter-spacing: .14em; color: var(--ink-2); }
.shop-kicker i { width: 7px; height: 7px; border-radius: 50%; background: var(--seal); }
.shop-title {
  margin-top: clamp(18px, 3vh, 32px);
  font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(44px, 5.6vw, 96px); line-height: 1.04; letter-spacing: .02em;
}
.shop-title small {
  display: block; margin-top: 14px;
  font-family: var(--font-en); font-weight: 700; font-size: clamp(18px, 2vw, 30px); letter-spacing: .02em; text-transform: uppercase; color: var(--ink-3);
}
:lang(en) .shop-title { font-family: var(--font-en); font-weight: 800; text-transform: uppercase; letter-spacing: -.01em; }
:lang(en) .shop-title small { font-family: var(--font-zh-serif); text-transform: none; }
.shop-lead { max-width: 30em; font-size: 15px; line-height: 1.8; color: var(--ink-2); padding-bottom: 10px; }
.shop-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  margin-top: clamp(44px, 8vh, 88px); padding-top: 24px; border-top: 1px solid var(--line);
}
.shop-chips { display: flex; flex-wrap: wrap; gap: 10px; }
.shop-chip {
  padding: 9px 15px; border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  font-size: 13px; letter-spacing: .06em; line-height: 1.2; color: var(--ink);
  transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.shop-chip:hover { border-color: var(--ink); }
.shop-chip.on { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.shop-count { flex: none; font-family: var(--font-mono); font-size: 12px; letter-spacing: .14em; color: var(--ink-2); }
.shop-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(36px, 5vh, 56px) clamp(16px, 1.8vw, 26px); margin-top: clamp(28px, 5vh, 44px); }
.shop-card { display: block; color: var(--ink); }
.shop-media {
  position: relative; display: block; overflow: hidden;
  aspect-ratio: 1 / 1; background: color-mix(in srgb, var(--ink) 5%, var(--bg)); /* 封面多是横的样机图：方的格子里上下不至于空太多 */
}
.shop-media img {
  display: block; width: 100%; height: 100%; object-fit: contain; padding: 9%;
  transition: transform 1s var(--ease);
}
.shop-media.is-wide { aspect-ratio: 16 / 10; }
.shop-media.is-wide img { object-fit: cover; padding: 0; }
.shop-prev { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .4s var(--ease); }
.shop-media.is-playing .shop-prev { opacity: 1; }
.shop-media.is-playing .shop-play { opacity: 0; }
.shop-play { transition: opacity .3s var(--ease); z-index: 1; }
.shop-tags { z-index: 1; }
.shop-card:hover .shop-media img { transform: scale(1.045); }
.shop-card:focus-visible { outline: none; }
.shop-card:focus-visible .shop-media { outline: 2px solid var(--seal); outline-offset: 3px; }
.shop-tags { position: absolute; left: 12px; top: 12px; display: flex; gap: 6px; }
.shop-tags span {
  padding: 5px 8px; background: var(--bg); color: var(--ink);
  font-size: 11px; font-weight: 600; letter-spacing: .12em; line-height: 1.2;
}
.shop-tags .is-dark { background: var(--ink); color: var(--bg); }
.shop-play {
  position: absolute; left: 14px; bottom: 14px; width: 34px; height: 34px; border-radius: 50%;
  background: rgba(255, 255, 255, .92);
}
.shop-play::after { content: ''; position: absolute; left: 13px; top: 11px; border-left: 10px solid #111; border-top: 6px solid transparent; border-bottom: 6px solid transparent; }
.shop-line { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-top: 16px; }
.shop-line b { font-family: var(--font-zh-serif); font-weight: 600; font-size: 18px; letter-spacing: .04em; line-height: 1.4; }
.shop-line i { flex: none; font-family: var(--font-mono); font-style: normal; font-size: 13px; color: var(--ink-2); }
.shop-meta { display: block; margin-top: 6px; font-size: 13px; letter-spacing: .04em; line-height: 1.5; color: var(--ink-2); }
.shop-next {
  display: flex; flex-direction: column; align-items: center; gap: 18px; width: 100%;
  margin-top: clamp(96px, 18vh, 200px); padding: 8px 0 clamp(24px, 6vh, 64px); text-align: center; color: var(--ink);
}
.shop-next-k { font-family: var(--font-en); font-weight: 500; font-size: 12px; letter-spacing: .16em; color: var(--ink-2); }
.shop-next b { font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(36px, 4.6vw, 72px); letter-spacing: .04em; line-height: 1.1; }
.shop-next-btn { display: inline-flex; align-items: center; gap: 10px; padding: 11px 18px; background: var(--ink); color: var(--bg); font-size: 14px; letter-spacing: .08em; }
.shop-next-btn i { font-style: normal; transition: transform .4s var(--ease); }
.shop-next:hover .shop-next-btn i { transform: translateX(4px); }
@media (max-width: 960px) {
  .shop-head { grid-template-columns: 1fr; gap: 20px; }
  .shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .shop-grid { grid-template-columns: 1fr; }
  .shop-bar { flex-direction: column; align-items: flex-start; }
}

/* ---------- 作品详情（照 pamidordesign.co 的单件作品页，main.js productHTML；查看层和 work.html 共用） ----------
   左边一列大图，每张放在一块浅底上，四周留白（竖图按屏高收住）；片子是播放器，下面三列剧照，点一张跳到那一秒。
   右边一栏钉着（initProduct 按它的高矮算钉在哪）：方框小标签、大标题、另一种语言的名字、说明第一段、
   细线隔开的表（左边小字的项目名，右边内容），再下面是说明的其余几段。最下面「同一类的其他作品」，三张卡片 */
.pd {
  display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); gap: clamp(32px, 5vw, 88px);
  max-width: 1360px; margin: 0 auto; align-items: start;
}
.pd-gallery { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.pd-fig { margin: 0; padding: clamp(18px, 3.4vw, 56px); background: color-mix(in srgb, var(--ink) 5%, var(--bg)); }
.pd-fig img { display: block; max-width: 100%; max-height: 84vh; width: auto; height: auto; margin: 0 auto; }
.pd-fig.is-combo { display: flex; align-items: flex-start; gap: 12px; }
.pd-fig.is-combo img { min-width: 0; max-height: none; }
.pd-player { position: relative; aspect-ratio: var(--r, 1.7778); background: #000; }
.pd-player video { position: absolute; inset: 0; width: 100%; height: 100%; display: block; background: #000; }
.pd-stills { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.pd-still { position: relative; display: block; overflow: hidden; }
.pd-still img { display: block; width: 100%; aspect-ratio: var(--r, 1.7778); object-fit: cover; transition: transform .8s var(--ease); }
.pd-still:hover img { transform: scale(1.05); }
.pd-still span { position: absolute; left: 8px; bottom: 8px; padding: 3px 6px; background: rgba(0, 0, 0, .6); color: #fff; font-family: var(--font-mono); font-size: 12px; }
.pd-info { position: sticky; top: 96px; min-width: 0; }
.pd-tag {
  display: inline-block; padding: 6px 10px; border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  font-size: 12px; font-weight: 600; letter-spacing: .14em; line-height: 1.2;
}
.pd-title { margin-top: 22px; font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(34px, 3.6vw, 58px); line-height: 1.14; letter-spacing: .03em; }
:lang(en) .pd-title { font-family: var(--font-en); letter-spacing: -.01em; }
.pd-alt { margin-top: 12px; font-family: var(--font-en); font-weight: 500; font-size: 17px; letter-spacing: .02em; color: var(--ink-2); }
:lang(en) .pd-alt { font-family: var(--font-zh-serif); }
.pd-lead { margin-top: 28px; font-size: 15px; line-height: 1.9; color: var(--ink-2); }
.pd-lead.is-pending { color: var(--ink-3); }
.pd-spec { margin-top: 32px; border-top: 1px solid var(--line); }
.pd-spec > div { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; padding: 15px 0; border-bottom: 1px solid var(--line); }
.pd-spec dt { font-size: 13px; letter-spacing: .16em; color: var(--ink-2); }
.pd-spec dd { margin: 0; font-size: 14px; letter-spacing: .04em; text-align: right; }
.pd-spec dd small { margin-left: 6px; font-family: var(--font-en); font-size: 13px; letter-spacing: .08em; color: var(--ink-2); }
.pd-more { margin-top: 28px; }
.pd-more p { font-size: 14px; line-height: 1.95; color: var(--ink-2); }
.pd-more p + p { margin-top: 1em; }
.pd-info .work-link-btn { margin-top: 28px; }
.pd-related { max-width: 1360px; margin: clamp(96px, 16vh, 180px) auto 0; padding-top: 26px; border-top: 1px solid var(--line); }
.pd-related h2 { font-family: var(--font-zh-serif); font-weight: 600; font-size: clamp(20px, 1.8vw, 26px); letter-spacing: .06em; }
.viewer .pd-info { top: 84px; }
@media (max-width: 900px) {
  .pd { grid-template-columns: 1fr; }
  .pd-info { position: static; order: -1; }
  .pd-stills { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* L1 全部作品：一面瀑布流（main.js renderAll / layAll，做法照 React Bits 的 Masonry）。
   每张图绝对定位，位置和宽高由脚本算好写进 transform / width / height；窗口变宽变窄时滑到新位置（.laid 之后才带过渡，
   免得第一次摆位也滑一下）。进场是脚本播的：从屏幕底下飞上来，由糊变清；.pending = 还在等第一屏的封面。
   鼠标移上去，那张图缩到 0.95。图下面一行小字：作品名在左，分类在右；列太窄时（.is-tight）只留作品名 */
.deck-dir { transition: opacity .45s var(--ease), transform .45s var(--ease); }
.deck-dir.switching { opacity: 0; transform: translateY(14px); }
.mgrid { --m-ease: cubic-bezier(.215, .61, .355, 1); position: relative; }
.mgrid.pending .mtile { opacity: 0; }
.mtile { position: absolute; left: 0; top: 0; display: block; color: var(--ink); }
.mgrid.laid .mtile { transition: transform .6s var(--m-ease), width .6s var(--m-ease); }
.mtile-in {
  position: relative; display: block; overflow: hidden;
  border-radius: 8px; background: var(--accent-soft);
  box-shadow: 0 14px 40px -20px rgba(0, 0, 0, .3);
  transition: transform .3s cubic-bezier(.25, .46, .45, .94);
}
.mgrid.laid .mtile-in { transition: transform .3s cubic-bezier(.25, .46, .45, .94), height .6s var(--m-ease); }
.mtile-in img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
@media (hover: hover) { .mtile:hover .mtile-in { transform: scale(.95); } }
.mtile:focus-visible { outline: none; }
.mtile:focus-visible .mtile-in { outline: 2px solid var(--seal); outline-offset: 3px; }
.mtile-cap {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  height: var(--mcap, 44px); padding: 12px 2px 0;
}
.mtile-cap b {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--font-zh-serif); font-weight: 600; font-size: 15px; letter-spacing: .05em; line-height: 1.4;
}
:lang(en) .mtile-cap b { font-family: var(--font-en); font-weight: 500; letter-spacing: .02em; }
.mtile-cap small { flex: none; font-size: 13px; letter-spacing: .08em; line-height: 1.4; color: var(--ink-2); }
.mgrid.is-tight .mtile-cap small { display: none; }
/* 视频封面左下角的小播放标记 */
.mtile-play {
  position: absolute; left: 12px; bottom: 12px;
  width: 34px; height: 34px; border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  display: flex; align-items: center; justify-content: center;
}
.mtile-play::after {
  content: ''; margin-left: 3px;
  border-left: 9px solid #fff; border-top: 6px solid transparent; border-bottom: 6px solid transparent;
}

/* ---------- Works · 三章 ----------
   视觉设计 / 视频剪辑 / AI 各一章（main.js initChapters 按 data.js 生成）。每章是一条横向的长卷：
   最左是一整屏的纯文字标题，右边接着这一类的子分类，一栏一个。
   宽屏（.chapters.pinned）：这一章钉在导航下面，往下滚、长卷就向左走——标题让开，分类一栏栏排进来；
   底边一道细线记着走到哪了，线头是一颗朱印色的点。
   窄屏和减少动态效果：不钉，标题在上，分类排成一条可以左右划的横条。
   一栏里从上到下：序号、分类名、一句说明和件数；鼠标移上去，这一类的封面从下往上铺满整栏、文字转白。
   点一栏进这个分类的作品页（.works-deck）；还没有作品的分类不能点，写着「整理中」。
   点标题或它下面那行「查看全部…」（.chapter-more）：进这一大类的全部作品，一面瀑布流。
   --gut：和 .wrap 同样的左右留白；--vw：钉住的那一屏的宽度（JS 写入，不含滚动条） */
#works { padding: 0; }
.chapters {
  --pin-top: 90px;
  --col-w: min(86vw, 620px);
  --gut: max(calc((var(--vw, 100vw) - 1320px) / 2), clamp(24px, 6.5vw, 128px));
}
.chapter { position: relative; background: var(--bg); } /* 每章一块底色：.tone-paper / .tone-deep / .tone-tint */
.chapter-pin { position: relative; }
.chapter-track { display: flex; flex-direction: column; }

/* 章标题：纯文字 */
.chapter-head { flex: none; min-height: 72vh; min-height: 72svh; }
.chapter-head-in {
  display: flex; flex-direction: column;
  height: 100%; min-height: inherit;
  padding: clamp(40px, 8.5vh, 100px) var(--gut) clamp(36px, 7.5vh, 84px);
}
.chapter-kicker { display: flex; align-items: baseline; gap: 18px; }
.chapter-no {
  font-family: var(--font-num); font-style: italic;
  font-size: clamp(30px, 2.5vw, 46px); line-height: 1; color: var(--seal);
}
.chapter-cat { font-family: var(--font-zh-serif); font-weight: 600; font-size: 17px; letter-spacing: .2em; }
.chapter-cat-en { font-family: var(--font-en); font-weight: 500; font-size: 13px; letter-spacing: .14em; color: var(--ink-2); }
:lang(en) .chapter-cat { font-family: var(--font-en); font-weight: 700; letter-spacing: .08em; }
/* 标题字号跟着字数走（--len：按全角字算的长度），长短标题都撑到差不多的行宽 */
.chapter-mid { margin: auto 0; display: flex; flex-direction: column; align-items: flex-start; }
.chapter-title {
  cursor: pointer;
  font-family: var(--font-zh-serif); font-weight: 800;
  font-size: clamp(34px, min(5.8vw, calc(42vw / var(--len, 5))), 108px);
  line-height: 1.1; letter-spacing: .02em;
}
:lang(en) .chapter-title { font-family: var(--font-num); font-weight: 400; letter-spacing: -.01em; }
/* 逐字（英文逐词）从下面升上来：进入视口时播一次 */
.chapter-title .ch { display: inline-block; overflow: hidden; vertical-align: top; padding: .08em 0; margin: -.08em 0; }
.chapter-title .ch > i {
  display: inline-block; font-style: normal;
  transform: translateY(108%);
  transition: transform 1.1s var(--ease);
  transition-delay: calc(var(--i, 0) * 60ms);
}
.chapter.in .chapter-title .ch > i { transform: none; }
.chapter-kicker, .chapter-foot, .chapter-more { opacity: 0; transition: opacity .9s var(--ease) .35s; }
.chapter.in .chapter-kicker, .chapter.in .chapter-foot, .chapter.in .chapter-more { opacity: 1; }
/* 标题下面的「查看全部…」：和「查看简历」同一种写法——一行字、一道下划线；悬停（标题或这行字）时下划线重画一遍、箭头往右送一点 */
.chapter-more {
  display: inline-flex; align-items: baseline; gap: 12px;
  margin-top: clamp(22px, 4.4vh, 48px); padding-bottom: 8px;
  font-family: var(--font-zh-serif); font-weight: 600;
  font-size: 18px; letter-spacing: .14em; line-height: 1.5; color: var(--ink);
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 1px;
}
:lang(en) .chapter-more { font-family: var(--font-en); font-weight: 500; letter-spacing: .08em; }
.chapter-more .arr { font-family: var(--font-en); font-weight: 400; transition: transform .5s var(--ease); }
.chapter-mid:hover .chapter-more .arr { transform: translateX(6px); }
.chapter-more:hover, .chapter-title:hover + .chapter-more { animation: wayLine .8s var(--ease); }
.chapter-more:active { opacity: .7; }
.chapter-foot {
  display: flex; justify-content: space-between; align-items: baseline; gap: 20px;
  font-size: 14px; letter-spacing: .1em; line-height: 1.6; color: var(--ink-2);
}
.chapter-hint { display: none; }
.chapter-hint::after { content: '→'; display: inline-block; margin-left: 12px; font-family: var(--font-en); animation: hintNudge 1.8s var(--ease) infinite; }
@keyframes hintNudge { 0%, 100% { transform: none; } 50% { transform: translateX(8px); } }

/* ---------- 分类：一类一屏（排版和动效照 weevolveit.com 的阶段页） ----------
   每个分类是一屏（.chapter-cols > li），只有文字：后面一个很大很淡的序号（.cp-ghost），
   再上面是内容（.ccol，整块可点）：很大的分类名带一个强调色的圆点、一道短线、一句说明、三件作品名、最后一行小字。
   钉住时一屏正好一个屏宽，往下滚一屏一屏横着换；屏幕底下一排节点（.chapter-steps）标着这一章有哪几类、现在在哪一类，可以点。
   视差（--px：这一屏的中线离屏幕中线几个屏宽，main.js 写入）：序号走得比这一屏慢，分类名、短线、说明、作品名、
   小字一层比一层走得快，并且离中线越远越淡——所以每一屏是从右边一层层赶上来、对正、再一层层散到左边去。
   点文字进这一类；鼠标移上去只有「看这一类」的箭头往右送一点。没钉住时（窄屏）是一条可以左右划的横条，没有视差 */
.chapter-cols {
  display: flex; flex: none;
  overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none;
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.chapter-cols::-webkit-scrollbar { display: none; }
.chapter-cols > li {
  position: relative; flex: none; width: var(--col-w); min-height: clamp(460px, 68svh, 680px);
  display: flex; align-items: center; overflow: hidden; scroll-snap-align: start;
}
.chapter-cols > li + li { border-left: 1px solid var(--line); }
.cp-ghost {
  position: absolute; right: -2%; top: 4%; z-index: 0; pointer-events: none;
  font-family: var(--font-num); font-size: clamp(200px, 46vw, 420px); line-height: .78; letter-spacing: -.04em;
  color: var(--ink); opacity: .06; transition: opacity .6s var(--ease), color .6s var(--ease);
}
.ccol {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: flex-start; text-align: left;
  width: 100%; padding: 44px clamp(22px, 6vw, 48px);
  color: var(--ink); transition: color .5s var(--ease);
}
.cp-title {
  display: inline-flex; align-items: baseline; white-space: nowrap;
  font-family: var(--font-zh-serif); font-weight: 800;
  font-size: clamp(36px, min(7vw, 13vh, calc(36vw / var(--len, 3))), 124px); line-height: 1.08; letter-spacing: .02em;
}
:lang(en) .cp-title { font-family: var(--font-num); font-weight: 400; letter-spacing: -.01em; }
.cp-dot { flex: none; width: .17em; height: .17em; margin-left: .1em; border-radius: 50%; background: var(--seal); transition: background-color .5s var(--ease); }
.cp-rule { width: clamp(90px, 9.6vw, 150px); height: 1px; margin-top: clamp(26px, 5vh, 54px); background: var(--ink-3); transition: background-color .5s var(--ease); }
.cp-lead { margin-top: clamp(20px, 3.8vh, 38px); font-size: clamp(16px, 1.3vw, 21px); line-height: 1.7; letter-spacing: .06em; }
.cp-list { display: grid; gap: clamp(10px, 1.7vh, 16px); margin-top: clamp(20px, 3.6vh, 36px); font-size: 15.5px; line-height: 1.6; letter-spacing: .05em; color: var(--ink-2); transition: color .5s var(--ease); }
.cp-list > span { display: flex; align-items: center; gap: 16px; }
.cp-list > span::before { content: ''; flex: none; width: 18px; height: 1px; background: currentColor; opacity: .6; }
.cp-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 22px; margin-top: clamp(24px, 4.4vh, 46px); font-size: 13.5px; line-height: 1.6; letter-spacing: .12em; color: var(--ink-2); transition: color .5s var(--ease); }
.cp-meta > span:first-child { font-family: var(--font-en); font-weight: 500; }
:lang(en) .cp-meta > span:first-child { font-family: var(--font-zh-serif); }
.cp-go { display: inline-flex; align-items: baseline; gap: 8px; padding-bottom: 3px; color: var(--ink); background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 1px; transition: color .5s var(--ease); }
.cp-go i { font-family: var(--font-en); font-style: normal; transition: transform .5s var(--ease); }
.ccol:hover .cp-go i { transform: translateX(6px); }
/* 悬停这一类：圆点胀大一点、短线伸长、作品名一行接一行往右让一步 */
.cp-dot { transition: background-color .5s var(--ease), transform .6s cubic-bezier(.34, 1.56, .64, 1); }
.ccol:hover .cp-dot { transform: scale(1.7); }
.cp-rule { transform-origin: 0 50%; transition: background-color .5s var(--ease), transform .7s var(--ease); }
.ccol:hover .cp-rule { transform: scaleX(1.6); background: var(--ink); }
.cp-list > span { transition: transform .5s var(--ease), color .4s var(--ease); }
.ccol:hover .cp-list > span { transform: translateX(10px); color: var(--ink); }
.ccol:hover .cp-list > span:nth-child(2) { transition-delay: 50ms; }
.ccol:hover .cp-list > span:nth-child(3) { transition-delay: 100ms; }
.ccol:focus-visible { outline-offset: 8px; }
/* 还没有作品的分类 */
.ccol.is-empty { cursor: default; }
.ccol.is-empty .cp-title { color: var(--ink-2); }
.ccol.is-empty .cp-dot { background: var(--ink-3); }

/* 节点：只在钉住时出现 */
.chapter-steps { display: none; }

/* 宽屏：钉住，往下滚带动长卷向左走 */
.chapters.pinned .chapter { height: calc(100vh - var(--pin-top) + var(--travel, 0px)); height: calc(100svh - var(--pin-top) + var(--travel, 0px)); }
.chapters.pinned .chapter-pin {
  position: sticky; top: var(--pin-top); z-index: 1;
  height: calc(100vh - var(--pin-top)); height: calc(100svh - var(--pin-top));
  overflow: hidden;
}
.chapters.pinned .chapter-track { flex-direction: row; width: max-content; height: 100%; will-change: transform; }
.chapters.pinned .chapter-head { width: var(--vw, 100vw); min-height: 0; height: 100%; }
.chapters.pinned .chapter-head-in { min-height: 0; will-change: transform, opacity; padding-top: clamp(70px, 13vh, 150px); }
/* 章与章之间多空一段：这一章横着走完、松开以后，还有一段同色的空白，下一章才上来 */
.chapters.pinned .chapter { box-sizing: content-box; padding-bottom: clamp(160px, 30vh, 320px); } /* 高度照旧是横走要的那一段，空白另外加在后面 */
.chapters.pinned .chapter-hint { display: block; }
.chapters.pinned .chapter-title { white-space: nowrap; } /* 一行排完；排不下时 JS 按可用宽度缩字号 */
.chapters.pinned .chapter-cols { position: relative; z-index: 1; overflow: visible; border-top: 0; border-bottom: 0; }
.chapters.pinned .chapter-cols > li { width: var(--vw, 100vw); height: 100%; min-height: 0; border-left: 0; padding-bottom: clamp(70px, 11vh, 120px); } /* 底下让出节点那一排 */
.chapters.pinned .cp-ghost {
  right: auto; left: 21%; top: 47%;
  font-size: min(50vh, 32vw);
  translate: calc(-6% + var(--px, 0) * -26vw + var(--mx, 0) * -26px) calc(-54% + var(--my, 0) * -18px); will-change: translate;
}
.chapters.pinned .ccol { width: auto; max-width: 64%; margin-left: 25.5%; padding: 0; }
.chapters.pinned .ccol > span { --fade: calc(1 - max(var(--px, 0), var(--px, 0) * -1) * 1.5); opacity: var(--fade); will-change: translate, opacity; }
.chapters.pinned .cp-title { translate: calc(var(--px, 0) * 9vw + var(--mx, 0) * 12px) calc(var(--my, 0) * 8px); }
.chapters.pinned .cp-rule  { translate: calc(var(--px, 0) * 16vw) 0; }
.chapters.pinned .cp-lead  { translate: calc(var(--px, 0) * 22vw + var(--mx, 0) * 6px) calc(var(--my, 0) * 4px); }
.chapters.pinned .cp-list  { translate: calc(var(--px, 0) * 30vw) 0; }
.chapters.pinned .cp-meta  { translate: calc(var(--px, 0) * 38vw) 0; }
.chapters.pinned .chapter-steps {
  position: absolute; left: 0; right: 0; bottom: clamp(20px, 4.4vh, 46px); z-index: 2;
  display: flex; justify-content: center; opacity: 0;
}
.chapter-steps button {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 9px;
  width: clamp(96px, 9.4vw, 156px); color: var(--ink-3); transition: color .5s var(--ease);
}
.chapter-steps button + button::before { content: ''; position: absolute; top: 13px; left: calc(-50% + 22px); right: calc(50% + 22px); height: 1px; background: var(--line); }
.chapter-steps b { font-family: var(--font-num); font-weight: 400; font-size: 27px; line-height: 1; }
.chapter-steps span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; letter-spacing: .12em; line-height: 1.4; }
.chapter-steps button.done, .chapter-steps button:hover { color: var(--ink); }
.chapter-steps button.on { color: var(--seal); }
.chapter-steps button:focus:not(:focus-visible), .ccol:focus:not(:focus-visible) { outline: none; }

@media (max-width: 760px) {
  .hello-screen .hello { font-size: min(6.4vw, 32px); letter-spacing: .06em; text-indent: .06em; } /* 最长那一行（爱拉着 AI 把点子变成作品）在手机上也排成一行 */
  .chapters { --col-w: 86vw; }
  .chapter-head { min-height: 58vh; min-height: 58svh; }
  .chapter-foot { font-size: 13px; }
}

/* 网格视图 */
.wgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  grid-auto-rows: 8px; /* 瀑布流：卡片按真实宽高比跨行，高度由 JS 量算 */
  gap: clamp(20px, 3vw, 40px);
}
.wcard { position: relative; display: block; }
.wcard .thumb {
  position: relative; overflow: hidden; border-radius: 8px;
  aspect-ratio: 4 / 5; /* 兜底比例；实际由内联 style 按封面真实宽高比覆盖，完整显示不裁切 */
  background: var(--accent-soft);
}
.wcard .thumb img, .wcard .thumb video {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease), opacity .5s var(--ease);
}
.wcard:hover .thumb img { transform: scale(1.02); }
.wcard .thumb video { position: absolute; inset: 0; opacity: 0; }
.wcard .thumb video.playing { opacity: 1; }
.wcard .play-badge {
  position: absolute; left: 50%; top: 50%; z-index: 3;
  transform: translate(-50%, -50%);
  width: 62px; height: 62px; border-radius: 50%;
  background: rgba(0, 0, 0, .4);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  transition: transform .5s var(--ease), background .5s var(--ease), opacity .4s;
}
.wcard .play-badge::after {
  content: ''; margin-left: 4px;
  border-left: 15px solid #fff;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
}
.wcard:hover .play-badge { transform: translate(-50%, -50%) scale(1.12); background: var(--accent-glow); }
.wcard .play-badge.hide { opacity: 0; }
.wcard .meta { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; padding: 18px 4px 0; }
.wcard .t { font-family: var(--font-zh-serif); font-size: 19px; letter-spacing: .05em; }
.wcard .t .en { display: block; font-family: var(--font-en); font-weight: 500; font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-3); margin-top: 5px; }
.wcard .c { font-size: 11.5px; letter-spacing: .12em; color: var(--ink-3); white-space: nowrap; }

.works-empty { padding: 90px 0; text-align: center; color: var(--ink-3); letter-spacing: .15em; }

/* ---------- 作品查看层（视觉设计的单件作品） ----------
   在分类页里点开一件作品：整屏白底盖上来，顶上一条——左边「第几件 / 共几件」，中间作品名，右边圆形关闭键；
   下面是这件作品的图和设计说明，图文穿插着排（见下面「图文排版」），最后是上一件 / 下一件（顶栏参考 perappelgren.de 的查看层）。
   ← → 换作品，Esc 关闭。打开时层淡入、内容从下面升上来；换作品时内容先淡出再换 */
.viewer {
  position: fixed; inset: 0; z-index: 1200;
  background: var(--bg); color: var(--ink);
  opacity: 0; visibility: hidden;
  transition: opacity .35s var(--ease), visibility 0s linear .35s;
}
.viewer.open { opacity: 1; visibility: visible; transition: opacity .45s var(--ease); }
html.viewer-open body { overflow: hidden; } /* 只锁 body：把 html 也设成 hidden 的话，关掉查看层后页面会跳回顶上 */
.viewer-bar {
  position: absolute; left: 0; right: 0; top: 0; z-index: 2; height: 68px;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 clamp(16px, 2.4vw, 32px);
  background: linear-gradient(var(--bg) 55%, transparent);
}
.viewer-count { font-family: var(--font-mono); font-size: 14px; letter-spacing: .1em; }
.viewer-title {
  position: absolute; left: 50%; transform: translateX(-50%); max-width: 60%;
  font-size: 16px; font-weight: 500; letter-spacing: .12em; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.viewer-close {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--ink); color: var(--bg);
  font-family: var(--font-body); font-weight: 400; font-size: 24px; line-height: 1;
  transition: transform .4s var(--ease);
}
.viewer-close:hover { transform: rotate(90deg); }
.viewer-body {
  position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 72px clamp(16px, 4vw, 56px) clamp(40px, 8vh, 88px);
  opacity: 0; transform: translateY(26px);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.viewer.open .viewer-body.in { opacity: 1; transform: none; transition: opacity .6s var(--ease) .08s, transform .7s var(--ease) .08s; }
.viewer-story { padding-top: clamp(8px, 3vh, 36px); }
.viewer-nav {
  max-width: min(1240px, 100%); margin: clamp(72px, 13vh, 150px) auto 0; padding-top: 22px;
  display: flex; justify-content: space-between; gap: 24px; border-top: 1px solid var(--line);
}
.viewer-nav button { text-align: left; font-size: 14px; letter-spacing: .1em; line-height: 1.6; color: var(--ink-2); transition: color .4s var(--ease); }
.viewer-nav button:last-child { text-align: right; }
.viewer-nav button b { display: block; margin-top: 4px; font-family: var(--font-zh-serif); font-weight: 600; font-size: clamp(18px, 1.7vw, 26px); letter-spacing: .05em; color: var(--ink); }
.viewer-nav button:hover { color: var(--ink); }
@media (max-width: 760px) {
  .viewer-title { position: static; transform: none; max-width: 56%; font-size: 15px; }
}

/* ---------- 图文排版（一件作品的详情：查看层和 work.html 共用，main.js storyHTML 生成） ----------
   一行两栏，文字 5 份、图 7 份，上下居中对齐；下一行左右对调（.is-flip）。图不铺满：横图最宽就是那 7 份，
   竖图再按屏高收窄（最高 70vh），放在自己那一栏的中间。开头一行（.st-open）差不多占一屏：分类、作品名、说明第一段。
   后面每段说明前有一个斜体序号（和首页章节序号同一种写法）。剩下没有配文字的图（.st-rest）排成小一号的两三列。
   窄屏改成一栏：开头先文字后图，往下每段先图后文字 */
.story { max-width: 1240px; margin: 0 auto; text-align: left; }
.st-row {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(32px, 6vw, 110px); align-items: center;
  margin-top: clamp(80px, 15vh, 170px);
}
.st-row.is-flip { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.st-row.is-flip .st-text { order: 2; }
.st-open { margin-top: 0; min-height: min(74vh, 720px); }
.st-text { max-width: 31em; }
.st-row.is-flip .st-text { justify-self: start; }
.st-kicker { display: flex; align-items: baseline; gap: 16px; }
.st-cat { font-family: var(--font-zh-serif); font-weight: 600; font-size: 16px; letter-spacing: .2em; }
.st-cat::before { content: '[ '; }
.st-cat::after { content: ' ]'; }
.st-cat::before, .st-cat::after { font-family: var(--font-mono); font-weight: 400; letter-spacing: 0; color: var(--ink-3); }
.st-cat-en { font-family: var(--font-en); font-weight: 500; font-size: 13px; letter-spacing: .14em; color: var(--ink-2); }
:lang(en) .st-cat { font-family: var(--font-en); font-weight: 700; letter-spacing: .08em; }
.st-title {
  margin-top: clamp(22px, 4vh, 40px);
  font-family: var(--font-zh-serif); font-weight: 800;
  font-size: clamp(28px, 3vw, 48px); line-height: 1.22; letter-spacing: .04em; text-wrap: balance;
}
:lang(en) .st-title { font-family: var(--font-num); font-weight: 400; letter-spacing: -.01em; }
.st-title small {
  display: block; margin-top: 14px;
  font-family: var(--font-en); font-weight: 500; font-size: 14px; letter-spacing: .14em; line-height: 1.5; color: var(--ink-2);
}
.st-text p { font-size: 16px; line-height: 2; letter-spacing: .03em; color: var(--ink-2); }
.st-text p + p { margin-top: 1.1em; }
.st-text .st-lead { margin-top: clamp(26px, 5vh, 48px); color: var(--ink); }
.st-text .st-lead + .st-lead { margin-top: 1.1em; }
.st-lead.is-pending { color: var(--ink-2); font-style: italic; }
.st-num {
  display: block; margin-bottom: 18px;
  font-family: var(--font-num); font-style: italic; font-size: clamp(28px, 2.3vw, 40px); line-height: 1; color: var(--seal);
}
.st-text .work-link-btn { margin-top: 34px; }
.st-fig { margin: 0; width: 100%; justify-self: center; }
.st-fig.is-tall { width: min(100%, calc(min(70vh, 660px) * var(--r))); }
.st-fig img, .st-fig video {
  display: block; width: 100%; height: auto; aspect-ratio: var(--r);
  border-radius: 6px; background: var(--accent-soft);
  box-shadow: 0 18px 46px -26px rgba(0, 0, 0, .34);
}
.st-fig video { background: #000; object-fit: contain; }
.st-fig video.st-clip { object-fit: cover; } /* 会动的剧照 */
/* 抠掉了底的图（透明 PNG）：直接落在页面上，不带卡片的底色、圆角和投影 */
.st-fig.is-cut img { border-radius: 0; background: none; box-shadow: none; filter: drop-shadow(0 26px 28px rgba(0, 0, 0, .16)); } /* 抠出来的东西落在页面上：只留一点它自己形状的影子 */
.st-fig .st-still { cursor: pointer; transition: opacity .3s var(--ease); } /* 片子的剧照：点一下跳到那一秒 */
.st-fig .st-still:hover { opacity: .86; }
/* 界面设计：两三张手机屏并排成一组，等高；每张的宽度和比例写在行内样式里 */
.st-fig.is-combo { display: flex; align-items: flex-start; gap: clamp(10px, 1.6vw, 24px); }
.st-fig.is-combo img { width: auto; min-width: 0; }
.st-rest {
  display: grid; grid-template-columns: repeat(var(--cols, 2), minmax(0, 1fr));
  gap: clamp(16px, 2.4vw, 36px); align-items: start;
  margin-top: clamp(80px, 15vh, 170px);
}
.st-rest .st-fig.is-tall { width: 100%; }
.st-rest.is-one { display: block; }
.st-rest.is-one .st-fig { width: min(100%, 760px); margin-inline: auto; }
.st-rest.is-one .st-fig.is-tall { width: min(100%, calc(min(70vh, 660px) * var(--r))); }
@media (max-width: 860px) {
  .st-row, .st-row.is-flip { grid-template-columns: minmax(0, 1fr); gap: 28px; margin-top: clamp(56px, 9vh, 88px); }
  .st-open { min-height: 0; margin-top: 0; }
  .st-text { max-width: none; }
  .st-row:not(.st-open) .st-fig { order: -1; }
  .st-row.is-flip .st-text { order: 0; }
  .st-rest { margin-top: clamp(56px, 9vh, 88px); }
  .st-rest:not(.is-one) { grid-template-columns: repeat(min(var(--cols, 2), var(--cols-m, 2)), minmax(0, 1fr)); }
}

/* ---------- 视觉设计的分类页：手风琴画廊 ----------
   这个分类的全部作品排成一排竖条，鼠标移到哪条、哪条就展开成大图（参考 React Bits 的 Accordion Gallery，
   用样式过渡改写）。没展开的是灰阶、压暗的，展开的那一张恢复原色——黑白的页面上，颜色只留给正在看的作品。
   图片按展开后的宽度定死尺寸、居中裁切，竖条变宽时图不跟着缩放，只是露出更多。
   画廊下面是当前这件的序号和名字；点展开的那一张进详情。窄屏不用这个版式，退回瀑布流网格 */
.agal { display: flex; gap: 10px; height: min(57vh, 600px); }
.apanel {
  position: relative; flex: 1 1 0; min-width: 0; overflow: hidden;
  border-radius: 6px; background: var(--accent-soft);
  transition: flex-grow .75s var(--ease);
}
.apanel.is-on { flex-grow: var(--grow, 6); }
.apanel img {
  position: absolute; left: 50%; top: 0; height: 100%;
  width: var(--media-w, 100%); max-width: none; object-fit: cover;
  transform: translateX(-50%);
  filter: grayscale(1) brightness(.72);
  transition: filter .75s var(--ease);
}
.apanel.is-on img { filter: none; }
.agal-cap { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; margin-top: clamp(26px, 4.6vh, 48px); }
.agal-title { font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(26px, 2.6vw, 46px); line-height: 1.2; letter-spacing: .04em; }
.agal-title small { display: block; margin-top: 8px; font-family: var(--font-en); font-weight: 500; font-size: 14px; letter-spacing: .12em; line-height: 1.5; color: var(--ink-2); }
.agal-no { flex: none; font-family: var(--font-num); font-size: clamp(44px, 4.4vw, 84px); line-height: .9; color: var(--seal); }
.agal-no small { margin-left: 10px; font-size: .34em; color: var(--ink-2); }

/* ---------- 视频分类页：监看窗 + 时间线 ----------
   排成剪辑软件的样子（深色那一套，.tone-deep）：上面一块监看窗放当前这条片子，旁边是它的序号、片名和所属分类；
   下面是一条时间线——全部片子按子分类分段排在同一条轨道上（封面按原比例），每段上方标着分类名，
   点哪段、监看窗就放哪段。监看窗和时间线正好占一屏，不用上下滚。
   横竖比例不同的片子都在同一块监看窗里按原比例完整显示，不用为每种比例各排一套版；
   以后加了新片子、新分类，时间线自己变长，一屏排不下时可以左右划 */
.vreel-top {
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(230px, 23vw, 380px);
  gap: clamp(24px, 3.4vw, 60px); align-items: end;
}
.vreel-monitor { position: relative; height: min(50vh, 46.5vw); background: #000; border-radius: 6px; overflow: hidden; }
.vreel-monitor video { display: block; width: 100%; height: 100%; object-fit: contain; background: #000; }
.vreel-no { font-family: var(--font-num); font-size: clamp(60px, 5.6vw, 108px); line-height: .9; color: var(--seal); }
.vreel-no small { margin-left: 12px; font-size: .3em; letter-spacing: .04em; color: var(--ink-2); }
.vreel-title {
  margin-top: 22px;
  font-family: var(--font-zh-serif); font-weight: 800;
  font-size: clamp(26px, 2.4vw, 44px); line-height: 1.2; letter-spacing: .04em;
}
.vreel-en { margin-top: 10px; font-family: var(--font-en); font-weight: 500; font-size: 14px; letter-spacing: .12em; line-height: 1.5; color: var(--ink-2); }
.vreel-cat { margin-top: 24px; font-size: 14px; letter-spacing: .1em; line-height: 1.6; color: var(--ink-2); }
.vreel-more {
  display: inline-block; margin-top: 20px; padding-bottom: 4px;
  font-size: 14px; letter-spacing: .12em; line-height: 1.5;
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 1px;
}
.vreel-more:hover { animation: wayLine .8s var(--ease); }
/* 时间线 */
.vline { margin-top: clamp(32px, 6vh, 64px); }
.vline-ruler { /* 刻度尺：每 12px 一小格，每 120px 一大格 */
  height: 16px;
  background:
    repeating-linear-gradient(90deg, var(--ink-3) 0 1px, transparent 1px 120px) 0 100% / 100% 100% no-repeat,
    repeating-linear-gradient(90deg, var(--line) 0 1px, transparent 1px 12px) 0 100% / 100% 45% no-repeat;
  border-bottom: 1px solid var(--line);
}
.vstrip { display: flex; gap: clamp(14px, 1.5vw, 26px); padding-top: 16px; overflow-x: auto; scrollbar-width: none; }
.vstrip::-webkit-scrollbar { display: none; }
.vgroup { flex: none; }
.vgroup-label {
  padding-bottom: 8px; white-space: nowrap;
  font-size: 14px; letter-spacing: .1em; line-height: 1.5; color: var(--ink-2);
  transition: color .4s var(--ease);
}
.vgroup-label small { margin-left: 8px; font-family: var(--font-en); font-weight: 500; font-size: 13px; letter-spacing: .06em; color: var(--ink-3); }
.vgroup.is-on .vgroup-label { color: var(--ink); }
.vgroup-clips { display: flex; gap: 5px; padding: 3px; margin: -3px; } /* 留出选中描边的位置 */
.vclip {
  position: relative; flex: none; overflow: hidden;
  height: clamp(56px, 7.8vh, 88px); aspect-ratio: var(--r, 1.7778);
  border-radius: 4px; opacity: .56;
  transition: opacity .4s var(--ease);
}
.vclip img { width: 100%; height: 100%; object-fit: cover; }
.vclip:hover, .vclip:focus-visible { opacity: 1; }
.vclip.is-on { opacity: 1; outline: 2px solid var(--seal); outline-offset: 1px; }
.vclip-t {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 16px 7px 5px;
  font-size: 13px; line-height: 1.4; letter-spacing: .02em; text-align: left; color: #FFFFFF;
  background: linear-gradient(transparent, rgba(0, 0, 0, .8));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 760px) {
  .vreel-top { grid-template-columns: 1fr; gap: 20px; }
  .vreel-monitor { height: 56.25vw; }
  .vreel-no { font-size: 52px; }
  .vclip { height: 72px; }
}

/* ---------- About · 自我介绍：墨黑底，六行字是一组，同一个字号、居中，只是出场的方式不一样 ----------
   字大、字重偏粗（600），每行的关键词（名字、ENFJ、设计、视频、做出来）用最粗的 900、强调色；字距放开，行与行之间留足空。
   每个字（英文按词）拆成一个小块（.hw，main.js initHelloText 拆）：
   - 第一行「你好」：模糊文字出场（照 React Bits 的 BlurText）——每个字从上面一点、糊着、透明落下来，
     先到半清半透、略低过头一点，再回到原位变清，一个字比一个字晚 0.2 秒。开场落定（或滚到它）时播一次。
   - 从「我是陈雨晴」开始：滚动揭示（照 React Bits 的 ScrollReveal）——这五行一开始就在那儿，只是很淡、糊着，
     整行略微歪一点；往下滚，字一个接一个变清、变亮，那一行同时转正。往回滚就原路退回去，完全跟着滚动走。
     这部分挂在滚动位置上（animation-timeline），由浏览器在合成线程里算，不经过脚本，只动透明度、模糊和旋转。
   不支持滚动动画的浏览器、减少动态效果、?snap=1：六行字就是全亮的、不动 */
.hello-screen {
  position: relative;
  padding: 38vh var(--gut) 30vh; /* 第一行落在第一屏中间偏上；最后一行后面留一段空，再接下一屏 */
  background: var(--bg);
}
.hello {
  margin: 0;
  font-family: var(--font-zh-serif); font-weight: 600;
  font-size: clamp(28px, min(3.8vw, 6.8vh), 72px); line-height: 1.45; letter-spacing: .12em; text-indent: .12em; /* 首行缩进补上最后一个字后面的字距，整行才真正居中 */
  word-break: keep-all;
  text-align: center;
  transition: opacity 1s var(--ease), transform 1s var(--ease);
}
.hello b { font-weight: 900; color: var(--seal); } /* 关键词：最粗、用强调色 */
:lang(en) .hello { font-family: var(--font-num); font-weight: 400; letter-spacing: .05em; text-indent: .05em; }
:lang(en) .hello b { font-weight: 400; font-style: italic; } /* 英文显示体只有一个字重：关键词改用斜体 */
html.landing .hello,
.hello.wait { opacity: 0; transform: translateY(18px); }
.hello-line { display: block; view-timeline-name: --hl; view-timeline-axis: block; }
.hello-line + .hello-line { margin-top: clamp(72px, 13vh, 160px); }
.hello-line:first-child + .hello-line { margin-top: clamp(110px, 22vh, 250px); } /* 「你好」单独一句，后面多空一点：第一屏只有它，后面几行滚下去才开始出现 */
.hl-in { display: inline-block; transform-origin: 0% 50%; }
.hw { display: inline-block; }
/* 第一行：等 BlurText 播之前先藏着（只有要播的时候脚本才加 .hl-wait） */
.hello-line.hl-wait .hw { opacity: 0; }
@supports (animation-timeline: view()) {
  .hello-line.is-sr .hl-in { animation: srTilt linear both, srBlur linear both; animation-timeline: --hl, --hl; animation-range: cover 20% cover 62%; }
  .hello-line.is-sr .hw {
    will-change: opacity, transform;
    animation: srWord linear both; animation-timeline: --hl;
    animation-range: cover var(--a, 6%) cover var(--b, 40%); /* 每个字各占一段，后一个字比前一个晚一点（--a / --b 由脚本按字数算） */
  }
}
@keyframes srTilt { from { rotate: 3deg; } to { rotate: 0deg; } }
@keyframes srWord { from { opacity: .12; transform: translateY(.22em); } to { opacity: 1; transform: none; } }
@keyframes srBlur { from { filter: blur(7px); } to { filter: blur(0); } }
/* ---------- About · 三个词（Creative / Young / Questioning） ----------
   自我介绍下面的一屏黑底，照 paragonproductions.co 的「Fuel for tomorrow's brands」：
   三个大词（首字母 C · Y · Q 用强调色的斜体，合起来是名字的缩写）、一行提示和简历入口，居中钉在屏幕中间（.cyq-pin，sticky）；
   十二张日常照做成拍立得，散在这一段很长的版面上（位置 --x / --y、角度 --r 写在每张照片上），
   往下滚的时候它们跟着页面往上走，再各自多走一点（视差 --par，见上面「视差」），快慢不一，像是从下面飘上来；
   .front 的从词的前面过，.back 的从后面过。最后一张出去以后，三个词单独停一会儿，下一章的白再从右边扫进来。
   移到（点一下）哪个词，只留这个词的照片亮着。
   不支持滚动动画 / 减少动态效果 / ?snap=1：照片不多走，只跟着页面滚过去，排法一样 */
.cyq {
  position: relative; isolation: isolate; /* 前面那层照片的层级只在这一屏里比，不会压到导航和下一章的扫入 */
  height: 460vh;
  background: var(--bg);
  overflow-x: clip; /* 贴边的照片露一半，不把页面撑宽 */
}
.cyq-pin {
  position: sticky; top: 0; z-index: 2;
  height: 100vh; height: 100svh;
  display: flex; align-items: center; justify-content: center;
  padding: 0 var(--gut);
  pointer-events: none; /* 空白处让给照片底下的东西；三个词和按钮自己接点击 */
}
.cyq-text { text-align: center; pointer-events: auto; }
.cyq-word {
  display: block; width: 100%; text-align: center;
  font-family: var(--font-num); font-size: clamp(40px, 4.6vw, 84px); line-height: 1.06; letter-spacing: .02em;
  transition: opacity .45s var(--ease);
}
.cyq-words li + li { margin-top: clamp(4px, 1vh, 12px); }
.cyq-word b { font-weight: 400; font-style: italic; color: var(--seal); padding-right: .04em; }
.cyq.has-on .cyq-word:not(.on) { opacity: .26; }
.cyq-hint { margin-top: clamp(36px, 6vh, 64px); font-size: 13px; letter-spacing: .12em; line-height: 1.6; color: var(--ink-3); }
/* 拍立得：暖白的相纸，上左右窄边、下面宽边写一行手写字；照片统一裁成 4:5 */
.cyq-pols { position: absolute; inset: 0; pointer-events: none; }
.pol {
  position: absolute; left: calc(var(--x) * 1%); top: calc(var(--y) * 1vh); z-index: 1;
  --pw: clamp(170px, 16.5vw, 270px); /* 相纸宽；边框按它算（百分比的内边距会按整屏宽算，不能用） */
  width: var(--pw); margin: 0;
  padding: calc(var(--pw) * .065) calc(var(--pw) * .065) 0;
  background: #F2EFE8;
  box-shadow: 0 2px 4px rgba(0, 0, 0, .35), 0 22px 44px -20px rgba(0, 0, 0, .9);
  rotate: calc(var(--r) * 1deg);
  transition: opacity .45s var(--ease);
}
.pol.front { z-index: 3; }
.pol img { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; background: #1c1c1c; }
.pol figcaption {
  padding: .5em 0 .78em;
  font-family: 'Long Cang', var(--font-body); font-size: clamp(18px, 1.5vw, 25px); line-height: 1.1;
  color: #34409A; /* 圆珠笔的蓝 */
  text-align: center; white-space: nowrap; overflow: hidden; text-overflow: clip;
}
:lang(en) .pol figcaption { font-family: 'Caveat', var(--font-body); font-weight: 500; font-size: clamp(19px, 1.6vw, 27px); }
.cyq.has-on .pol:not(.on) { opacity: .16; }
@media (max-width: 760px) {
  .cyq { height: 520vh; } /* 手机上词占满了一行宽，照片一定会从词上过：拉开上下间距，同一屏里只有两三张 */
  .cyq-word { font-size: clamp(44px, 14vw, 68px); }
  .pol { left: calc(var(--xm) * 1%); top: calc(var(--y) * 1.3vh); --pw: 40vw; }
  .pol figcaption { font-size: 17px; }
  :lang(en) .pol figcaption { font-size: 18px; }
}

/* 简历的入口：三个词下面的一行文字，带一道下划线和一个加号；悬停时下划线重画一遍，
   点开后简历作为一张卡片弹出来 */
.resume-btn {
  display: inline-flex; align-items: baseline; gap: 12px;
  margin-top: clamp(40px, 7vh, 76px); padding-bottom: 8px;
  font-family: var(--font-zh-serif); font-weight: 600;
  font-size: 18px; letter-spacing: .14em; line-height: 1.5;
  background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 1px;
}
:lang(en) .resume-btn { font-family: var(--font-en); font-weight: 500; letter-spacing: .08em; }
.resume-btn .plus { font-family: var(--font-en); font-weight: 400; font-size: 20px; line-height: 1; transition: transform .5s var(--ease); }
.resume-btn:hover { animation: wayLine .8s var(--ease); }
.resume-btn:active { opacity: .7; }

/* ---------- 简历：弹出来的一张卡片 ----------
   后面的页面压暗（.resume-pop），一张浅灰的圆角卡片（.resume-card）从下面升上来，一直顶到屏幕底边。
   卡片顶上不动：左边名字和方向，右边关闭键、下面几枚淡蓝的小标签；内容在 .resume-scroll 里自己滚。
   每一块的标题是一枚小标签（.r-block > h3）。卡片用浅灰那一套颜色，不跟着后面的页面变 */
.resume-pop {
  position: fixed; inset: 0; z-index: 1100;
  background: rgba(0, 0, 0, .56);
  opacity: 0; visibility: hidden;
  transition: opacity .35s var(--ease), visibility 0s linear .35s;
}
.resume-pop.open { opacity: 1; visibility: visible; transition: opacity .45s var(--ease); }
html.resume-open body { overflow: hidden; } /* 只锁 body：把 html 也设成 hidden 的话，页面会跳回顶上 */
html.resume-open .scroll-pct { opacity: 0; }
.resume-card {
  --bg: var(--tint); --ink: var(--tint-ink); --seal: var(--mark);
  position: absolute; left: 50%; top: clamp(20px, 6vh, 64px); bottom: 0;
  width: min(1040px, 100% - 32px);
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--ink);
  border-radius: 22px 22px 0 0;
  box-shadow: 0 -20px 80px -20px rgba(0, 0, 0, .5);
  transform: translate(-50%, 56px); opacity: 0;
  transition: transform .4s var(--ease), opacity .3s var(--ease);
}
.resume-pop.open .resume-card { transform: translate(-50%, 0); opacity: 1; transition: transform .7s var(--ease) .05s, opacity .5s var(--ease) .05s; }
.resume-head {
  flex: none; display: flex; justify-content: space-between; align-items: flex-start; gap: 24px;
  padding: clamp(28px, 4.6vh, 48px) clamp(22px, 4vw, 52px) 0;
}
.resume-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 14px; }
.resume-close {
  display: inline-flex; align-items: center; gap: 12px;
  font-size: 14px; letter-spacing: .12em; line-height: 1; color: var(--ink);
}
.resume-close i { position: relative; width: 16px; height: 16px; transition: transform .4s var(--ease); }
.resume-close i::before, .resume-close i::after {
  content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 1.5px; margin-top: -.75px; background: currentColor;
}
.resume-close i::before { transform: rotate(45deg); }
.resume-close i::after { transform: rotate(-45deg); }
.resume-close:hover i { transform: rotate(90deg); }
.r-pills { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; }
.r-pills span {
  padding: 6px 13px; border-radius: 999px;
  background: var(--stage-mark); color: var(--ink);
  font-size: 13px; letter-spacing: .06em; line-height: 1.3; white-space: nowrap;
}
.resume-scroll {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  margin-top: clamp(26px, 4.4vh, 44px);
  padding: 0 clamp(22px, 4vw, 52px) clamp(48px, 9vh, 96px);
  scrollbar-width: thin; scrollbar-color: var(--ink-3) transparent;
}
.resume-grid {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(36px, 5vw, 80px);
  padding-top: clamp(22px, 3.6vh, 36px); border-top: 1px solid var(--line);
}
.r-block { margin-bottom: clamp(40px, 6vh, 64px); }
.r-block > h3 {
  display: inline-block; margin-bottom: 18px; padding: 6px 11px; border-radius: 4px;
  background: var(--line-soft); color: var(--ink);
  font-size: 13px; font-weight: 500; letter-spacing: .1em; line-height: 1.3;
}
.r-name { font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(40px, 5.6vw, 78px); letter-spacing: .06em; line-height: 1.1; }
.r-name .en { display: block; font-family: var(--font-en); font-weight: 500; font-size: 14px; letter-spacing: .2em; color: var(--ink-2); margin-top: 14px; }
.r-role { margin-top: 10px; font-size: 14px; letter-spacing: .16em; color: var(--ink-2); }
.r-intro { font-size: 16px; color: var(--ink); line-height: 2; }
.skill { margin-bottom: 20px; }
.skill .s-head { display: flex; justify-content: space-between; font-size: 13.5px; margin-bottom: 8px; }
.skill .s-head .pct { font-family: var(--font-mono); color: var(--ink-2); font-size: 13px; }
.skill .s-track { height: 2px; background: var(--line-soft); border-radius: 2px; overflow: hidden; }
.skill .s-fill {
  height: 100%; width: 0;
  background: var(--ink);
  transition: width 1.2s var(--ease);
}
.resume-pop.open .s-fill { width: var(--pct); transition-delay: calc(.45s + var(--i) * 90ms); }
.r-item { position: relative; padding-left: 22px; margin-bottom: 26px; }
.r-item::before {
  content: ''; position: absolute; left: 0; top: 9px;
  width: 7px; height: 7px; border-radius: 0 50% 50% 50%;
  transform: rotate(45deg);
  background: var(--accent);
}
.r-item::after { content: ''; position: absolute; left: 3px; top: 22px; bottom: -18px; width: 1px; background: var(--line-soft); }
.r-item:last-child::after { display: none; }
.r-item .ri-head { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; flex-wrap: wrap; }
.r-item .ri-title { font-weight: 600; font-size: 15.5px; letter-spacing: .03em; }
.r-item .ri-time { font-family: var(--font-mono); font-size: 13px; letter-spacing: .04em; color: var(--ink-2); }
.r-item .ri-desc { font-size: 14px; color: var(--ink-2); margin-top: 6px; line-height: 1.9; }
.r-tags { display: flex; flex-wrap: wrap; gap: 9px; }
.r-tags span { font-size: 13px; line-height: 1.6; color: var(--ink-2); border: 1px solid var(--line); border-radius: 999px; padding: 5px 13px; }
.r-edu-major { font-size: 14px; color: var(--ink-2); margin-top: 8px; line-height: 1.9; }

/* ---------- Contact · 结尾一屏 ----------
   首页的最后一屏，黑底。所有内容沿中轴居中排成一列，像一封信的落款：
   一句邀请（大标题）→ 当地时间 → 一排四个联系方式 → 微信二维码 → 手写签名 → 版权行（左右各一句，对称）。
   四个联系方式都能点，都带一道下划线（main.js initContact）。内容比一屏高时往下延，不压缩 */
.closing {
  position: relative; display: flex; overflow: hidden;
  min-height: 100vh; min-height: 100svh;
  background: var(--bg); color: var(--ink);
}
.closing-inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding-top: clamp(130px, 19vh, 200px); padding-bottom: clamp(28px, 5vh, 56px);
}
.cl-k { font-family: var(--font-mono); font-size: 13px; letter-spacing: .32em; color: var(--ink-2); }
.closing-title {
  margin-top: clamp(22px, 4vh, 40px);
  font-family: var(--font-zh-serif); font-weight: 800;
  font-size: clamp(34px, 4.4vw, 76px);
  letter-spacing: .04em; line-height: 1.16; text-wrap: balance;
}
:lang(en) .closing-title { font-family: var(--font-en); font-weight: 900; letter-spacing: -.01em; }
.cl-sub { margin-top: clamp(22px, 4vh, 36px); font-size: 16px; line-height: 2; letter-spacing: .08em; color: color-mix(in srgb, var(--ink) 82%, transparent); }
/* 「在线 · 北京时间」小胶囊：绿点一呼一吸 */
.closing-clock {
  display: inline-flex; align-items: center; gap: 14px; margin-top: clamp(28px, 5vh, 44px);
  font-family: var(--font-mono); font-size: 13px; letter-spacing: .08em; color: var(--ink-2);
}
.cl-live { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; border: 1px solid var(--line); color: var(--ink); }
.cl-live i { width: 7px; height: 7px; border-radius: 50%; background: #3DDC84; box-shadow: 0 0 0 0 rgba(61, 220, 132, .6); animation: clPulse 2s ease-out infinite; }
@keyframes clPulse { 0% { box-shadow: 0 0 0 0 rgba(61, 220, 132, .55); } 70% { box-shadow: 0 0 0 8px rgba(61, 220, 132, 0); } 100% { box-shadow: 0 0 0 0 rgba(61, 220, 132, 0); } }
.clock-now { color: var(--ink); font-variant-numeric: tabular-nums; }
/* 留言框 */
.cl-form {
  display: flex; align-items: center; width: min(520px, 100%); margin-top: clamp(40px, 7vh, 64px);
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); border-radius: 12px;
  background: color-mix(in srgb, var(--ink) 4%, transparent);
  transition: border-color .4s var(--ease), background-color .4s var(--ease);
}
.cl-form:focus-within { border-color: color-mix(in srgb, var(--ink) 45%, transparent); background: color-mix(in srgb, var(--ink) 7%, transparent); }
.cl-form input {
  flex: 1; min-width: 0; height: 56px; padding: 0 20px; border: 0; outline: 0; background: none;
  font: inherit; font-family: var(--font-mono); font-size: 14px; letter-spacing: .04em; color: var(--ink);
}
.cl-form input::placeholder { color: var(--ink-3); }
.cl-form button { flex: none; width: 56px; height: 56px; font-size: 20px; color: var(--ink-2); transition: color .3s var(--ease); }
.cl-form button i { display: inline-block; font-style: normal; transition: transform .4s var(--ease); }
.cl-form button:hover { color: var(--ink); }
.cl-form button:hover i, .cl-form:focus-within button i { transform: translateX(4px); }
/* 散在四周的联系方式：像飘着的几句话，慢慢上下浮；悬停时变亮、箭头往右上送一点 */
.cl-floats { position: absolute; inset: 0; z-index: 2; pointer-events: none; } /* 写在 .closing-inner 里面（手机上按顺序排在签名前面），宽屏时铺满这一块 */
.cl-chip {
  position: absolute; left: var(--x); top: var(--y); pointer-events: auto;
  display: inline-flex; align-items: baseline; gap: 12px; padding: 8px 4px;
  font-family: var(--font-mono); font-size: 15px; letter-spacing: .04em; color: color-mix(in srgb, var(--ink) 78%, transparent);
  animation: clFloat var(--t, 8s) ease-in-out infinite alternate;
  transition: color .3s var(--ease);
}
.cl-chip.is-r { left: auto; right: var(--x); }
.cl-chip:nth-child(2) { animation-delay: -3s; } .cl-chip:nth-child(3) { animation-delay: -5s; } .cl-chip:nth-child(4) { animation-delay: -1.5s; }
.cl-chip span { font-family: var(--font-zh-serif); font-size: 13px; letter-spacing: .14em; color: var(--ink-3); }
.cl-chip b { font-weight: 500; }
.cl-chip i { font-style: normal; color: var(--ink-3); transition: transform .4s var(--ease), color .3s var(--ease); }
.cl-chip:hover { color: var(--ink); }
.cl-chip:hover i { transform: translate(3px, -3px); color: var(--ink); }
@keyframes clFloat { from { translate: 0 -8px; } to { translate: 0 10px; } }
/* 左下角的二维码小卡片（像 weevolveit 左下角那枚奖项卡片） */
.cl-badge {
  position: absolute; left: 0; bottom: calc(clamp(28px, 5vh, 56px) + 60px); z-index: 2; margin: 0;
  display: flex; align-items: center; gap: 14px; padding: 10px 18px 10px 10px;
  border: 1px solid var(--line); border-radius: 14px; background: color-mix(in srgb, var(--ink) 4%, transparent);
  transition: transform .4s cubic-bezier(.34, 1.56, .64, 1), border-color .3s var(--ease);
}
.cl-badge:hover { transform: translateY(-4px); border-color: color-mix(in srgb, var(--ink) 30%, transparent); }
.cl-badge img { width: 56px; height: 56px; border-radius: 8px; background: #fff; padding: 4px; }
.cl-badge figcaption { display: flex; flex-direction: column; gap: 4px; text-align: left; }
.cl-badge b { font-size: 13px; font-weight: 600; letter-spacing: .08em; }
.cl-badge small { font-family: var(--font-mono); font-size: 12px; letter-spacing: .14em; color: var(--ink-3); }
.closing-sig { width: min(100%, 380px); margin-top: clamp(40px, 7vh, 80px); }
.closing-sig .footer-sig-canvas { width: 100%; margin: 0; }
@media (max-width: 900px) {
  .cl-floats { position: static; display: flex; flex-direction: column; align-items: center; gap: 6px; margin-top: 40px; pointer-events: auto; }
  .cl-chip, .cl-chip.is-r { position: static; animation: none; font-size: 14px; }
  .cl-badge { position: static; margin-top: 24px; }
  .nav-inner::before { inset: 0 -12px; }
  .closing-inner { padding-top: 120px; }
}
.closing-foot { align-self: stretch; margin-top: auto; padding-top: clamp(48px, 9vh, 100px); }
.closing-foot .f-note { color: var(--ink-2); }

/* 轻提示：点了联系方式之后，在屏幕底部说一句发生了什么（号码已复制、名片已下载） */
.toast {
  position: fixed; left: 50%; bottom: clamp(24px, 6vh, 56px); z-index: 1300;
  max-width: calc(100vw - 32px); padding: 12px 20px; border-radius: 6px;
  background: #F2F1EC; color: #000000;
  font-size: 14px; letter-spacing: .06em; line-height: 1.6; text-align: center;
  opacity: 0; transform: translate(-50%, 12px); pointer-events: none;
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}
.toast.on { opacity: 1; transform: translate(-50%, 0); }

/* ---------- Footer（作品详情页；首页的版权行在结尾那一屏里，共用 .footer-inner / .f-brand / .f-note） ---------- */
.footer {
  border-top: 1px solid var(--line);
  padding: 44px 0 52px;
}
.footer-inner { display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; }
.f-brand { font-family: var(--font-en); font-weight: 900; letter-spacing: .08em; font-size: 15px; }
.f-note { font-size: 12.5px; color: var(--ink-3); letter-spacing: .1em; }
/* 结尾签名：大签名（canvas，滚到它时写出，见 main.js initFooterSig），只在首页结尾那一屏出现。
   宽高比 = 签名位图含留白的比例，画布没出图前先占好位 */
.footer-sig-canvas {
  width: min(100%, 1080px); height: auto;
  aspect-ratio: 1205 / 413;
  margin-inline: auto;
}

/* ---------- 视频详情（work.html 里有片子的作品，main.js videoHTML / initVideoPage）----------
   参考 bybang.co 的项目页。页面本身是放映厅那套深色（body.vd-page.tone-deep），一张圆角白纸（.vsheet）从下面升上来。
   纸上从上到下：一行很大的作品名一直横着走，上沿被纸边切掉一点（.vd-marq）；左边小表、右边说明（.vd-head）；
   播放器（.vd-player，按屏高限制大小，不铺满）；剧照错落着排（.vd-mosaic，12 栏，六种摆法 p0–p5 轮着用：
   大的配小的、靠右的大图、居中的宽幅，小的那张往下错开一截；都按片子原来的画幅，不裁），每张左下角是时间码，点一下跳到那一秒。
   纸的下面，深色的页面上是下一条片子的名字（.vd-next）。
   会动的只有 transform 和 opacity：白纸升起 / 落下、大字横移、剧照进场、悬停时放大一点 */
body.vd-page { background: var(--bg); }
body.vd-page .work-main { padding-top: clamp(96px, 13vh, 130px); }
.vsheet {
  position: relative; overflow: hidden;
  padding: 0 clamp(18px, 4vw, 64px) clamp(72px, 13vh, 150px);
  border-radius: clamp(18px, 2vw, 30px); background: var(--bg); color: var(--ink);
  text-align: left;
  opacity: 0; transform: translate3d(0, 46vh, 0);
}
.vsheet.in { opacity: 1; transform: none; transition: transform 1.1s var(--ease), opacity .5s var(--ease); }
.vsheet.out { opacity: 0; transform: translate3d(0, 60vh, 0); transition: transform .45s cubic-bezier(.5, 0, .9, .4), opacity .4s ease; }
.vd-close {
  position: absolute; right: clamp(18px, 2.4vw, 36px); top: clamp(16px, 2.6vh, 28px); z-index: 2;
  display: inline-flex; align-items: center; gap: 10px; padding: 8px 14px; border-radius: 999px;
  background: var(--bg); font-size: 14px; letter-spacing: .12em; line-height: 1; color: var(--ink);
}
.vd-close i { position: relative; width: 14px; height: 14px; transition: transform .4s var(--ease); }
.vd-close i::before, .vd-close i::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 1.5px; margin-top: -.75px; background: currentColor; }
.vd-close i::before { transform: rotate(45deg); } .vd-close i::after { transform: rotate(-45deg); }
.vd-close:hover i { transform: rotate(90deg); }
/* 大字：比纸还宽，上沿被切掉一点；一直往左走 */
.vd-marq { margin: 0 calc(-1 * clamp(18px, 4vw, 64px)); overflow: hidden; height: clamp(84px, 13.4vw, 216px); }
.vd-marq-track { display: inline-flex; white-space: nowrap; will-change: transform; translate: 0 -13%; } /* 往上提一点（translate），横着走用 transform，两个互不干扰 */
.vd-marq-track span {
  padding-right: .36em;
  font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(96px, 15.4vw, 250px); line-height: 1; letter-spacing: .01em;
}
:lang(en) .vd-marq-track span { font-family: var(--font-num); font-weight: 400; letter-spacing: -.02em; }
.vd-head { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 6fr) minmax(0, 3fr); gap: clamp(24px, 4vw, 72px); margin-top: clamp(28px, 5vh, 56px); }
.vd-meta div { display: flex; justify-content: space-between; gap: 16px; padding: 9px 0; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.6; letter-spacing: .06em; }
.vd-meta div:last-child { border-bottom: 1px solid var(--line); }
.vd-meta dt { color: var(--ink-2); }
.vd-meta dd { font-family: var(--font-mono); letter-spacing: .02em; text-align: right; }
.vd-desc p { max-width: 34em; font-size: 16px; line-height: 2; letter-spacing: .03em; color: var(--ink); }
.vd-desc p + p { margin-top: 1em; }
.vd-desc .vd-alt { margin-bottom: 14px; font-family: var(--font-en); font-weight: 500; font-size: 14px; letter-spacing: .14em; line-height: 1.5; color: var(--ink-2); }
.vd-desc .is-pending { color: var(--ink-2); font-style: italic; }
.vd-player { width: min(100%, calc(70vh * var(--r, 1.7778))); margin: clamp(48px, 9vh, 100px) auto 0; }
.vd-player video { display: block; width: 100%; aspect-ratio: var(--r, 1.7778); border-radius: 4px; background: #000; }
.vd-mosaic { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(12px, 1.7vw, 26px); align-items: start; width: min(100%, 1180px); margin: clamp(56px, 10vh, 110px) auto 0; }
.vd-shot { position: relative; display: block; text-align: left; }
.vd-shot-in { display: block; overflow: hidden; border-radius: 3px; background: var(--accent-soft); aspect-ratio: var(--r, 1.7778); } /* 剧照不裁：画面里常有字，裁了会缺半边 */
.vd-shot img, .vd-shot video { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 1.1s var(--ease); }
.vd-shot:hover img { transform: scale(1.05); }
.vd-tc { display: flex; align-items: center; gap: 8px; margin-top: 10px; font-family: var(--font-mono); font-size: 13px; letter-spacing: .04em; line-height: 1.4; color: var(--ink-2); transition: color .4s var(--ease); }
.vd-tc::before { content: ''; border-left: 8px solid currentColor; border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.vd-shot:hover .vd-tc { color: var(--ink); }
.vd-shot.p0 { grid-column: 1 / 8; }
.vd-shot.p1 { grid-column: 9 / 13; margin-top: 26%; }
.vd-shot.p2 { grid-column: 5 / 13; }
.vd-shot.p3 { grid-column: 1 / 5; margin-top: 12%; }
.vd-shot.p4 { grid-column: 6 / 13; }
.vd-shot.p5 { grid-column: 2 / 12; }
/* 纸下面：下一条 */
.vd-next { display: grid; grid-template-columns: 1fr auto; align-items: end; gap: 8px 24px; padding: clamp(64px, 12vh, 130px) clamp(18px, 4vw, 64px) clamp(40px, 8vh, 90px); text-align: left; color: var(--ink); }
.vd-next-k { grid-column: 1 / -1; font-family: var(--font-mono); font-size: 13px; letter-spacing: .1em; color: var(--ink-2); }
.vd-next-k::before { content: '[ '; } .vd-next-k::after { content: ' ]'; }
.vd-next b { font-family: var(--font-zh-serif); font-weight: 800; font-size: clamp(44px, 8.4vw, 136px); line-height: 1.1; letter-spacing: .02em; }
:lang(en) .vd-next b { font-family: var(--font-num); font-weight: 400; }
.vd-next i { font-family: var(--font-en); font-style: normal; font-size: clamp(36px, 5vw, 84px); line-height: 1.2; transition: transform .6s var(--ease); }
.vd-next:hover i { transform: translateX(16px); }
html.snap .vsheet { opacity: 1 !important; transform: none !important; }

/* 视频的分类页（首页点视频那一章的分类栏打开，main.js openVideoCat）：首页留在后面压暗，白纸在这一层里升上来、自己滚 */
.csheet { position: fixed; inset: 0; z-index: 1150; visibility: hidden; background: rgba(0, 0, 0, 0); transition: background .45s var(--ease), visibility 0s linear .45s; }
.csheet.open { visibility: visible; background: rgba(0, 0, 0, .72); transition: background .5s var(--ease); }
.csheet.leaving { background: rgba(0, 0, 0, 0); }
.csheet-scroll { position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain; padding: clamp(64px, 10vh, 112px) clamp(10px, 2.2vw, 44px) 0; }
.csheet .vsheet { max-width: 1480px; margin: 0 auto; }
html.csheet-open body { overflow: hidden; }
html.csheet-open .scroll-pct { opacity: 0; }
.vc-list { margin-top: clamp(48px, 9vh, 100px); }
.vc-tile { opacity: 0; transform: translate3d(0, 40px, 0); }
.vsheet.in .vc-tile { opacity: 1; transform: none; transition: opacity .8s var(--ease) calc(.35s + var(--d, 0ms)), transform 1s var(--ease) calc(.35s + var(--d, 0ms)); }
.vc-tile .vd-shot-in { position: relative; cursor: pointer; background: #000; }
.vc-tile.playing .vd-shot-in { cursor: default; }
.vc-tile:hover video { transform: none; }
.vc-play { position: absolute; left: 16px; bottom: 16px; display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 50%; background: rgba(0, 0, 0, .55); transition: opacity .3s var(--ease), transform .4s var(--ease); pointer-events: none; }
.vc-play::after { content: ''; margin-left: 3px; border-left: 12px solid #fff; border-top: 8px solid transparent; border-bottom: 8px solid transparent; }
.vc-tile:hover .vc-play { transform: scale(1.12); }
.vc-tile.playing .vc-play { opacity: 0; }
.vc-cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; margin-top: 12px; }
.vc-cap b { font-family: var(--font-zh-serif); font-weight: 700; font-size: 18px; letter-spacing: .06em; line-height: 1.5; }
:lang(en) .vc-cap b { font-family: var(--font-en); font-weight: 600; letter-spacing: .02em; }
.vc-cap small { font-family: var(--font-en); font-size: 13px; letter-spacing: .08em; line-height: 1.5; color: var(--ink-2); }
.vc-cap a { margin-left: auto; padding-bottom: 3px; font-size: 13px; letter-spacing: .1em; line-height: 1.5; color: var(--ink-2); background: linear-gradient(currentColor, currentColor) no-repeat 0 100% / 100% 1px; transition: color .4s var(--ease); }
.vc-cap a:hover { color: var(--ink); }
.vc-next { width: 100%; max-width: 1480px; margin: 0 auto; color: var(--ink); cursor: pointer; }
html.snap .vc-tile { opacity: 1 !important; transform: none !important; }
@media (max-width: 860px) {
  .vd-head { grid-template-columns: minmax(0, 1fr); }
  .vd-shot.p0, .vd-shot.p1, .vd-shot.p2, .vd-shot.p3, .vd-shot.p4, .vd-shot.p5 { grid-column: 1 / -1; margin-top: 0; }
  .vd-shot.p1, .vd-shot.p4 { grid-column: 3 / -1; } .vd-shot.p3 { grid-column: 1 / 11; }
}

/* ---------- Work detail page ---------- */
.work-main { padding-top: 140px; min-height: 100vh; }
/* 正文是图文排版（.story，见上面「图文排版」）：返回键跟着 1240px 的版心左对齐，下面接上一个 / 下一个 */
.work-back {
  display: flex; align-items: center; gap: 10px;
  width: fit-content; margin: 0 0 8px max(0px, calc((100% - 1240px) / 2));
  font-size: 13px; letter-spacing: .14em; color: var(--ink-2);
  transition: color .4s var(--ease), gap .4s var(--ease);
}
.work-back:hover { color: var(--accent); gap: 16px; }
.work-link-btn {
  display: inline-flex; align-items: center; gap: 14px;
  margin-top: 40px;
  font-family: var(--font-zh-serif); font-size: 16.5px; letter-spacing: .1em;
  color: var(--bg); background: var(--accent);
  padding: 17px 34px; border-radius: 999px;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}
.work-link-btn .en { font-family: var(--font-en); font-size: 11px; letter-spacing: .2em; text-transform: uppercase; opacity: .75; }
.work-link-btn:hover { transform: translateY(-3px); box-shadow: 0 18px 40px -14px var(--accent-glow); }
/* 品牌展板（君山银针详情页）：真网页排版复刻展板；浅色品牌画布固定 */
.brand-board {
  margin-top: clamp(80px, 15vh, 170px);
  background: #f3efe3; color: #2e580c;
  border-radius: 18px; padding: clamp(26px, 5vw, 72px);
}
.bb-hero {
  position: relative; overflow: hidden; border-radius: 12px;
  aspect-ratio: 2.3778; min-height: 280px;
  display: flex; align-items: center; justify-content: center;
}
.bb-hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.bb-hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(24, 48, 8, .38), rgba(24, 48, 8, .66)); }
.bb-hero-in {
  position: relative; z-index: 1; padding: 20px;
  display: flex; flex-direction: column; align-items: center; gap: clamp(10px, 1.6vw, 18px);
  color: #fff; text-align: center;
}
.bb-hero-mark {
  width: clamp(72px, 9vw, 118px); height: clamp(72px, 9vw, 118px);
  border: 2px solid rgba(255, 255, 255, .92); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: "Kaiti SC", "KaiTi", "STKaiti", serif;
  font-size: clamp(38px, 4.6vw, 62px); line-height: 1; padding-bottom: .08em;
}
.bb-hero-name { font-family: var(--font-en); font-size: clamp(15px, 1.9vw, 24px); letter-spacing: .42em; text-indent: .42em; font-weight: 500; }
.bb-hero-slogan { font-size: clamp(12.5px, 1.4vw, 16px); letter-spacing: .34em; text-indent: .34em; opacity: .92; }
.bb-hero-slogan.en { font-family: var(--font-en); letter-spacing: .18em; text-indent: .18em; text-transform: uppercase; font-size: clamp(10.5px, 1.1vw, 13px); }
.bb-h {
  display: flex; align-items: baseline; gap: 14px;
  margin: 0 0 18px; padding-left: 16px; border-left: 5px solid #afc279;
  font-size: clamp(17px, 2vw, 22px); font-weight: 600; letter-spacing: .3em;
}
.bb-h small { font-family: var(--font-en); font-size: 10.5px; letter-spacing: .24em; font-weight: 500; opacity: .55; }
.bb-cols { display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(28px, 5vw, 72px); margin-top: clamp(34px, 5vh, 56px); }
.bb-cols-2 { grid-template-columns: 1fr 1.2fr; }
.bb-text { margin: 0; font-size: 14.5px; line-height: 2.05; letter-spacing: .04em; text-align: justify; }
.bb-swatches { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.bb-swatches i { display: flex; align-items: center; justify-content: center; aspect-ratio: 1 / 1.15; border-radius: 10px; }
.bb-swatches i b { font-family: var(--font-en); font-size: 12px; font-weight: 500; letter-spacing: .14em; color: #fff; }
.bb-swatches i.light { border: 1px solid rgba(46, 88, 12, .22); }
.bb-swatches i.light b { color: #2e580c; }
.bb-swatches span { display: block; margin-top: 8px; font-size: 12px; letter-spacing: .12em; text-align: center; opacity: .8; }
.bb-logo { margin-top: clamp(34px, 5vh, 56px); }
.bb-sub { margin: -8px 0 22px; font-size: 13px; letter-spacing: .1em; opacity: .75; text-align: center; }
.bb-logo-row { display: flex; align-items: center; justify-content: center; gap: clamp(14px, 3.4vw, 44px); flex-wrap: wrap; }
.bb-logo-row img { display: block; }
.bb-bud { width: clamp(88px, 15vw, 168px); height: auto; border-radius: 50%; }
.bb-char { height: clamp(54px, 8vw, 96px); width: auto; }
.bb-final { height: clamp(104px, 14vw, 158px); width: auto; }
.bb-op { font-family: var(--font-en); font-weight: 300; font-size: clamp(30px, 4.4vw, 52px); color: #afc279; }
.bb-posters-grid, .bb-apps-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.bb-posters-grid img, .bb-apps-grid img { display: block; width: 100%; height: auto; border-radius: 8px; box-shadow: 0 14px 30px -18px rgba(24, 48, 8, .35); }
.bb-poster-wide { grid-column: 1 / -1; }
@media (max-width: 900px) {
  .bb-cols, .bb-cols-2 { grid-template-columns: 1fr; }
}
.work-nav {
  text-align: center;
  display: grid; grid-template-columns: 1fr 1fr;
  border-top: 1px solid var(--line);
  margin-top: clamp(70px, 10vh, 120px);
}
.work-nav a {
  padding: clamp(34px, 5vh, 54px) 8px;
  display: block;
  transition: background .5s var(--ease), padding .5s var(--ease);
}
.work-nav a + a { border-left: 1px solid var(--line); }
.work-nav a:hover { background: var(--accent-soft); }
.work-nav .wn-k { font-family: var(--font-en); font-size: 11px; letter-spacing: .3em; text-transform: uppercase; color: var(--ink-3); }
.work-nav .wn-t { font-family: var(--font-zh-serif); font-size: clamp(19px, 2.6vw, 28px); letter-spacing: .05em; margin-top: 10px; transition: color .4s var(--ease); }
.work-nav a:hover .wn-t { color: var(--accent); }
.work-empty { text-align: center; padding: 22vh 0 16vh; }
.work-empty .big { font-family: var(--font-zh-serif); font-size: clamp(30px, 5vw, 52px); letter-spacing: .1em; }
.work-empty p { color: var(--ink-3); margin-top: 16px; letter-spacing: .1em; }
.work-empty a {
  display: inline-block; margin-top: 36px;
  border: 1px solid var(--line); border-radius: 999px; padding: 13px 30px;
  font-size: 14px; letter-spacing: .12em;
  transition: all .4s var(--ease);
}
.work-empty a:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- Lightbox ---------- */
.lightbox {
  position: fixed; inset: 0; z-index: 1200;
  background: rgba(0, 0, 0, .9);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden;
  transition: opacity .5s var(--ease), visibility 0s linear .5s;
}
.lightbox.open { opacity: 1; visibility: visible; transition: opacity .5s var(--ease); }
.lightbox img {
  max-width: min(92vw, 1200px); max-height: 86vh;
  object-fit: contain; border-radius: 4px;
  transform: scale(.96);
  transition: transform .5s var(--ease);
}
.lightbox.open img { transform: scale(1); }
/* 长图（如简历 2480×3507）：按宽度完整显示，遮罩层内纵向滚动 */
.lightbox.tall {
  display: block; overflow-y: auto; -webkit-overflow-scrolling: touch;
  text-align: center;
}
.lightbox.tall img {
  max-width: min(92vw, 860px); max-height: none; width: auto;
  margin: 6vh auto 10vh; height: auto;
}
.lb-btn {
  position: absolute; z-index: 2;
  width: 54px; height: 54px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,.25);
  color: #fff; font-size: 20px; font-family: var(--font-en);
  display: flex; align-items: center; justify-content: center;
  transition: background .4s var(--ease), transform .4s var(--ease);
}
.lb-btn:hover { background: rgba(255,255,255,.14); transform: scale(1.06); }
.lb-close { top: 26px; right: 26px; }
.lb-prev { left: 26px; top: 50%; transform: translateY(-50%); }
.lb-next { right: 26px; top: 50%; transform: translateY(-50%); }
.lb-prev:hover { transform: translateY(-50%) scale(1.06); }
.lb-next:hover { transform: translateY(-50%) scale(1.06); }
.lb-count {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  color: rgba(255,255,255,.6); font-family: var(--font-en);
  font-size: 12px; letter-spacing: .3em;
}

/* ---------- 点击火花画布（JS 注入；全屏 fixed，层级在页面内容之上，不拦截事件） ---------- */
.spark-layer {
  position: fixed; inset: 0; z-index: 1500;
  pointer-events: none;
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .resume-grid { grid-template-columns: 1fr; gap: 0; }
  .resume-card { width: calc(100% - 16px); top: 4vh; border-radius: 18px 18px 0 0; }
  .resume-head { flex-direction: column; gap: 18px; }
  .resume-side { align-items: flex-start; }
  .resume-close { position: absolute; right: 20px; top: 22px; }
  .r-pills { justify-content: flex-start; }
  .closing-ways { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .nav-links, .nav-ctrl .ctrl-btn, .nav-dot { display: none; }
  .burger { display: block; }
  .nav { --nav-h: 64px; --nav-line-y: 30px; --nav-logo-h: 30px; } /* 窄屏：线从 logo 的尾巴延到菜单按钮前 */
  .nav-line path { stroke-width: 1.1px; }
  .closing-inner { padding-top: 84px; }
  .closing-ways { gap: 20px 16px; }
  .way dd { font-size: 17px; }
  .way:nth-child(n+3) { grid-column: 1 / -1; } /* 窄屏：微信和电话并排，邮箱、QQ 各占一行居中，左右保持对称 */
  .work-nav { grid-template-columns: 1fr; }
  .work-nav a + a { border-left: 0; border-top: 1px solid var(--line); }
  .hello-screen { padding: 34vh var(--gut) 24vh; }
  .hello-line + .hello-line { margin-top: clamp(48px, 9vh, 90px); }
  .wgrid { grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr)); }
  .lb-prev { left: 8px; } .lb-next { right: 8px; }
  .lb-btn { width: 44px; height: 44px; font-size: 16px; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001s !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* 截图/调试快照：?snap=1 时去掉过渡与动画，直接呈现终态 */
html.snap .reveal, html.snap .chapter-title .ch > i { opacity: 1 !important; transform: none !important; transition: none !important; }
html.snap * { transition-delay: 0s !important; animation: none !important; }
html.snap { scroll-behavior: auto !important; }


/* ============================================================
   2026-10-17 英文字体：三种角色，各管一摊
   - Instrument Serif（--font-num）：大号的英文字、数字、序号——带衬线、窄、斜体很好看，用在显眼处
   - Cabinet Grotesk（--font-en）：英文正文
   - JetBrains Mono（--font-mono）：中文旁边的英文小标签、计数、方括号——全大写、拉开字距，像版面上的注脚
   ============================================================ */
:lang(zh) .chapter-cat-en, :lang(zh) .st-cat-en, :lang(zh) .st-title small, :lang(zh) .deck-cat small,
:lang(zh) .shop-title small, :lang(zh) .cp-meta > span:first-child, :lang(zh) .shop-kicker, :lang(zh) .pd-alt,
:lang(zh) .mobile-menu a small, :lang(zh) .ft-hsub, :lang(zh) .ft-cat, :lang(zh) .shop-meta, :lang(zh) .shop-next-k,
:lang(zh) .cyq-hint, :lang(zh) .us-en {
  font-family: var(--font-mono) !important; font-weight: 400 !important; font-style: normal !important;
  text-transform: uppercase; letter-spacing: .16em !important; font-size: 11.5px !important;
}
:lang(zh) .shop-title small { font-size: 13px !important; margin-top: 18px; color: var(--ink-2); }
:lang(zh) .st-title small { margin-top: 16px; color: var(--ink-2); }
.f-brand, .closing-foot .f-brand { font-family: var(--font-mono); font-weight: 500; letter-spacing: .14em; font-size: 12px; }
:lang(en) .nav-links a { font-family: var(--font-mono); text-transform: uppercase; font-size: 12px; letter-spacing: .18em; }
:lang(en) .hello { font-family: var(--font-num); font-weight: 400; letter-spacing: .01em; text-indent: 0; }
:lang(en) .hello b { font-style: italic; font-weight: 400; }
.chapter-no, .cp-ghost, .st-num { font-feature-settings: 'lnum' 1; }

/* ============================================================
   2026-10-17 留白：每一段上下多空一点，正文行距放松
   ============================================================ */
.hello-screen { padding-top: 42vh; padding-bottom: 36vh; }
.st-row { margin-top: clamp(120px, 20vh, 220px); }
.st-text p { line-height: 2.1; }
.chapters.pinned .ccol { max-width: 56%; }
.cp-lead { max-width: 30em; }
.shop-grid { gap: clamp(48px, 7vh, 80px) clamp(24px, 2.6vw, 40px); }
.closing-inner { padding-top: clamp(150px, 22vh, 230px); }


/* ---------- 2026-10-17 鼠标拖尾（js/cursor-trail.js） ---------- */
.cursor-trail { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 2000; pointer-events: none; }

/* ---------- 2026-10-17 三个词换成 Cormorant Garamond：细的正体，首字母用斜体、强调色 ---------- */
.cyq-word { font-family: 'Author', var(--font-num); font-weight: 300; letter-spacing: -.01em; line-height: 1.04; font-size: clamp(44px, 5.2vw, 94px); } /* 2026-10-18 三个词也换成 Author */
.cyq-word b { font-family: 'Author', var(--font-num); font-weight: 500; font-style: italic; padding-right: .02em; }

/* ---------- 2026-10-17 联系页：漂着的几句换成一张一目了然的名片 ---------- */
.cl-floats, .cl-badge { display: none !important; }
.cl-card {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: clamp(28px, 4vw, 56px); align-items: center;
  width: min(720px, 100%); margin-top: clamp(44px, 7vh, 72px); padding: clamp(18px, 2.4vw, 28px);
  border: 1px solid var(--line); border-radius: 22px; text-align: left;
  background: color-mix(in srgb, var(--ink) 3%, transparent);
}
.cl-qr { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.cl-qr img { display: block; width: clamp(150px, 13vw, 184px); height: auto; aspect-ratio: 1; padding: 10px; border-radius: 14px; background: #fff; }
.cl-qr figcaption { font-size: 13px; letter-spacing: .14em; color: var(--ink-2); }
.cl-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.cl-list li { border-bottom: 1px solid var(--line); }
.cl-row {
  display: grid; grid-template-columns: 3.4em minmax(0, 1fr) auto 1em; align-items: baseline; gap: 14px;
  padding: 16px 4px; color: var(--ink);
  transition: padding .4s var(--ease), background-color .3s var(--ease);
}
.cl-row-k { font-family: var(--font-zh-serif); font-size: 13px; letter-spacing: .16em; color: var(--ink-2); }
.cl-row b { font-family: var(--font-mono); font-weight: 500; font-size: 15px; letter-spacing: .03em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cl-row em { font-style: normal; font-size: 12px; letter-spacing: .1em; color: var(--ink-3); transition: color .3s var(--ease); }
.cl-row i { font-style: normal; color: var(--ink-3); transition: transform .4s var(--ease), color .3s var(--ease); }
.cl-row:hover { padding-left: 10px; }
.cl-row:hover em, .cl-row:hover i { color: var(--seal); }
.cl-row:hover i { transform: translate(3px, -3px); }
.cl-form { margin-top: clamp(28px, 5vh, 44px); width: min(720px, 100%); }
@media (max-width: 760px) {
  .cl-card { grid-template-columns: 1fr; justify-items: center; }
  .cl-list { width: 100%; }
  .cl-row { grid-template-columns: 3em minmax(0, 1fr) 1em; }
  .cl-row em { display: none; }
}


/* ---------- 2026-10-18 联系页：对称排——二维码在正中，左右各两行联系方式；签名放大 ---------- */
.cl-card, .cl-form { display: none !important; }
.cl-sym {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center;
  gap: clamp(32px, 4.4vw, 72px); width: min(1080px, 100%); margin-top: clamp(64px, 10vh, 110px);
}
.cl-side { display: flex; flex-direction: column; gap: clamp(18px, 3vh, 28px); align-items: flex-end; }
.cl-side.is-r { align-items: flex-start; }
.cl-sym .cl-row {
  display: inline-flex; align-items: baseline; gap: 18px; width: min(100%, 340px);
  padding: 18px 22px; border: 1px solid var(--line); border-radius: 14px;
  background: color-mix(in srgb, var(--ink) 3%, transparent); color: var(--ink);
  transition: border-color .3s var(--ease), background-color .3s var(--ease), transform .4s var(--ease);
}
.cl-sym .cl-row:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--ink) 30%, transparent); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.cl-sym .cl-row b { flex: 1; font-size: 15.5px; }
.cl-sym .cl-row i { margin-left: auto; }
.cl-sym .cl-qr img { width: clamp(150px, 12vw, 180px); }
.closing-sig { width: min(100%, 640px) !important; margin-top: clamp(72px, 12vh, 130px) !important; }
@media (max-width: 860px) {
  .cl-sym { grid-template-columns: 1fr; justify-items: center; }
  .cl-sym .cl-qr { order: -1; }
  .cl-side, .cl-side.is-r { align-items: stretch; width: 100%; }
  .cl-sym .cl-row { width: 100%; }
}


/* ---------- 2026-10-18 英文统一用 Author：中文旁边的英文小标签也换成它（不再用等宽体），三个单词照旧用 Cormorant ---------- */
:lang(zh) .chapter-cat-en, :lang(zh) .st-cat-en, :lang(zh) .st-title small, :lang(zh) .deck-cat small,
:lang(zh) .shop-title small, :lang(zh) .cp-meta > span:first-child, :lang(zh) .shop-kicker, :lang(zh) .pd-alt,
:lang(zh) .mobile-menu a small, :lang(zh) .ft-hsub, :lang(zh) .ft-cat, :lang(zh) .shop-meta, :lang(zh) .shop-next-k,
:lang(zh) .cyq-hint, :lang(zh) .us-en, .f-brand, .closing-foot .f-brand {
  font-family: 'Author', var(--font-body) !important; font-weight: 500 !important; letter-spacing: .14em !important;
}
:lang(en) body, :lang(en) .nav-links a { font-family: 'Author', var(--font-body); }
:lang(en) .nav-links a { text-transform: uppercase; font-size: 12.5px; letter-spacing: .16em; font-weight: 500; }


/* ---------- 2026-10-18 点阵的鼠标光圈（js/dot-field.js）：差值混合的白点，深底亮、浅底暗 ---------- */
.dot-field { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 1990; pointer-events: none; mix-blend-mode: difference; }

/* ---------- 2026-10-18 精选作品 → 作品三章的转场 ----------
   作品那一块像一张浅色的纸从下面升上来：一开始两侧收进来一截、上沿是很大的圆角，
   往上滚的时候它慢慢撑满整屏、圆角收成直角；同时上面的精选作品往后退——缩小一点、变暗。
   全挂在滚动位置上（animation-timeline），由浏览器算，不走脚本 */
#works { background: var(--stage); }
body.deck-mode #works { background: var(--bg); }
@supports (animation-timeline: view()) {
  .chapters { animation: sheetUp linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; transform-origin: 50% 0; }
  @keyframes sheetUp {
    from { clip-path: inset(0 7% 0 7% round 56px 56px 0 0); }
    60%  { clip-path: inset(0 2% 0 2% round 36px 36px 0 0); }
    to   { clip-path: inset(0 0 0 0 round 0); }
  }
  .feat > * { animation: featBack linear both; animation-timeline: view(); animation-range: exit 0% exit 100%; transform-origin: 50% 100%; }
  @keyframes featBack { to { scale: .93; opacity: .25; filter: brightness(.6); } }
}
@media (prefers-reduced-motion: reduce) { .chapters, .feat > * { animation: none !important; } }
html.snap .chapters, html.snap .feat > * { animation: none !important; }


/* ---------- 2026-10-18 视频章 → 结尾：和「精选作品 → 作品三章」同一种转场（不定格、不叠上去）——
   结尾像一张纸从下面升上来：一开始两侧收进来一截、上沿是很大的圆角，往上滚的时候撑满整屏、圆角收成直角；
   纸两侧露出来的是视频那一章的底色（.cl-wrap 铺 --deep），上面视频那一章同时往后退（缩小一点、变暗） ---------- */
.cl-wrap { background: var(--deep); }
body:not(.deck-mode) { timeline-scope: --cl-rise; }
.closing { view-timeline: --cl-rise block; }
@supports (animation-timeline: view()) {
  .closing { animation: sheetUp linear both; animation-timeline: view(); animation-range: entry 0% entry 100%; }
  .chapters.pinned .chapter:last-child .chapter-pin { animation: featBack linear both; animation-timeline: --cl-rise; animation-range: entry 0% entry 100%; transform-origin: 50% 100%; }
}
@media (prefers-reduced-motion: reduce) { .closing, .chapters.pinned .chapter:last-child .chapter-pin { animation: none !important; } }
html.snap .closing, html.snap .chapters.pinned .chapter:last-child .chapter-pin { animation: none !important; }


/* ---------- 2026-10-18 自我介绍那一屏：纯黑底，不放背景动效 ---------- */
.hello-screen { background-image: none !important; }


/* ---------- 2026-10-18 结尾（联系）这一屏也铺点阵：和作品那几章同一种点、同样钉在屏幕上不动；
   结尾从定格的 MV 那一页上升上来的时候，两边的点正好对齐，连成一片 ---------- */
.closing { clip-path: inset(0); } /* 只让点在结尾这一块里露出来（宽屏时转场动画会接管 clip-path） */
.closing::before {
  content: ''; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle, color-mix(in srgb, var(--ink) 13%, transparent) 1px, transparent 1.5px);
  background-size: 30px 30px;
}


/* ---------- 2026-10-18 视频分类页打开（main.js renderShop 给 .shop 加 .v-open）：像放映机开机 ----------
   分类名从一条缝里升出来；标签那一排从左往右划开；
   每一张片子：先在中间亮出一条细线，线往两边拉满，再上下撑开成整个画面（画面同时从稍微放大落回原大），
   一张比一张晚一点；片名和小字最后浮上来。换分类、点「下一类」都重放一遍 */
.shop.v-open .shop-kicker, .shop.v-open .shop-lead { animation: vFade .8s var(--ease) both; }
.shop.v-open .shop-lead { animation-delay: .2s; }
.shop.v-open .shop-title { animation: vSlit 1s cubic-bezier(.7, 0, .2, 1) both; animation-delay: .05s; }
.shop.v-open .shop-bar { animation: vWipe .9s cubic-bezier(.7, 0, .2, 1) both; animation-delay: .2s; }
.shop.v-open .shop-media { animation: vOn 1.05s cubic-bezier(.7, 0, .2, 1) both; animation-delay: calc(.3s + var(--i, 0) * .1s); }
.shop.v-open .shop-media::after {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none; background: var(--ink);
  animation: vFlash 1.05s linear both; animation-delay: calc(.3s + var(--i, 0) * .1s);
}
.shop.v-open .shop-media img { animation: vZoom 1.4s var(--ease) both; animation-delay: calc(.55s + var(--i, 0) * .1s); }
.shop.v-open .shop-line, .shop.v-open .shop-meta { animation: vFade .7s var(--ease) both; animation-delay: calc(.85s + var(--i, 0) * .1s); }
@keyframes vFade { from { opacity: 0; translate: 0 14px; } to { opacity: 1; translate: 0 0; } }
@keyframes vSlit { from { clip-path: inset(0 0 100% 0); translate: 0 .4em; } to { clip-path: inset(0 0 0 0); translate: 0 0; } }
@keyframes vWipe { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes vOn {
  0%   { clip-path: inset(calc(50% - 1px) 50% calc(50% - 1px) 50%); }
  38%  { clip-path: inset(calc(50% - 1px) 0 calc(50% - 1px) 0); }
  100% { clip-path: inset(0 0 0 0); }
}
@keyframes vFlash { 0%, 38% { opacity: 1; } 75%, 100% { opacity: 0; } }
@keyframes vZoom { from { scale: 1.18; } to { scale: 1; } }
@media (prefers-reduced-motion: reduce) { .shop.v-open *, .shop.v-open .shop-media::after { animation: none !important; } }


/* ---------- 2026-10-18 导航胶囊改成全透明：不铺底色、不加毛玻璃和阴影，只留一圈细边，底下的点阵直接透上来 ---------- */
.nav-inner::before {
  background: transparent;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  box-shadow: none;
}
