/* ==========================================================================
   v3-wall.css — 方案三：媒体墙与沉浸舞台
   --------------------------------------------------------------------------
   结构：
     · 文档正常滚动：hero → 吸顶工具条（控件行 + 类别轨道）→ 瀑布流 → 加载更多
     · 主表面是 CSS columns 瀑布流，卡片高度随素材真实比例变化
     · 标题块与素材重叠 18px，并按 3n 节奏交错偏移，形成对角流动
     · 详情是全屏沉浸式浮层（#/e/<id>，返回键关闭），带缩略导航带
   视觉：暖白纸 + 墨蓝强调 + 大字号 + 柔和投影 + 充足留白
   动效：滚动逐张入场（stagger）、浮层分层淡入、悬停上浮 + 素材放大
   ========================================================================== */

html[data-view="v3"] {
  --paper:      oklch(0.968 0.008 85);
  --surface:    oklch(0.995 0.003 85);
  --surface-2:  oklch(0.945 0.010 85);
  --surface-3:  oklch(0.912 0.012 85);
  --ink:        oklch(0.215 0.014 60);
  --ink-2:      oklch(0.405 0.012 62);
  --ink-3:      oklch(0.540 0.010 64);
  --ink-invert: oklch(0.990 0.003 85);
  --line:        oklch(0.890 0.010 82);
  --line-strong: oklch(0.808 0.012 80);
  --accent:       oklch(0.485 0.150 285);
  --accent-hover: oklch(0.415 0.148 285);
  --accent-soft:  oklch(0.935 0.030 285);
  --accent-line:  oklch(0.760 0.090 285);
  --accent-ink:   oklch(0.990 0.003 85);
  --band-bg:    oklch(0.185 0.010 60);
  --band-ink:   oklch(0.980 0.004 85);
  --band-ink-2: oklch(0.790 0.010 80);
  --ok: oklch(0.520 0.120 155);
  --warn: oklch(0.600 0.130 75);
  --danger: oklch(0.520 0.180 25);
  --r-xs: 3px; --r-sm: 7px; --r-md: 12px; --r-lg: 20px;
  --cat-l: 0.510; --cat-c: 0.130; --cat-mix: 12%;
  --cat-fallback: oklch(0.510 0.070 60);
  --shadow-1: 0 2px 10px oklch(0.40 0.03 70 / 0.07);
  --shadow-2: 0 14px 38px oklch(0.40 0.03 70 / 0.13);
  --shadow-3: 0 32px 80px oklch(0.30 0.03 70 / 0.24);
  --dur-fast: 180ms; --dur-base: 380ms; --dur-slow: 780ms;
  --ease-out: cubic-bezier(0.2, 1, 0.28, 1);
  --enter-y: 26px;
  --lift: 4px;
  --hover-scale: 1.05;
  --stagger: 60ms;
}

.v3 { padding-bottom: var(--sp-9); }

/* ============================================================ 超大 hero */
.v3-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: var(--sp-7);
  align-items: end;
  padding: var(--sp-8) var(--sp-7) var(--sp-7);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
.v3-hero__left { min-width: 0; }
/* 刊头顶行：横跨两列。左侧眉题，右侧作者与抖音号 —— 像杂志的 masthead，
   正好填住右上角的空白；空间不够时整组换行，不会挤压。 */
.v3-hero__top {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-2) var(--sp-5); flex-wrap: wrap;
}
.v3-hero__top .v3-kicker { margin: 0; }
.v3-hero__author {
  margin: 0;
  display: inline-flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap;
  font-family: var(--ff-mono); font-size: var(--fs-2xs);
  letter-spacing: 0.08em; color: var(--ink-3);
}
.v3-hero__author a {
  font-weight: 500; color: var(--ink); letter-spacing: 0.01em;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease-out);
}
.v3-hero__author a:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
.v3-hero__author a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-xs);
}
.v3-douyin { font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.v3-kicker {
  font-family: var(--ff-mono); font-size: var(--fs-2xs);
  letter-spacing: 0.28em; text-transform: uppercase; color: var(--ink-3);
}
.v3-hero__title {
  margin-top: var(--sp-4);
  font-size: clamp(40px, 6.4vw, 96px);
  font-weight: 600;
  line-height: 0.98;
  letter-spacing: -0.045em;
}
.v3-hero__title em { font-style: normal; color: var(--accent); }
.v3-hero__lede {
  margin-top: var(--sp-5);
  max-width: 44ch;
  font-size: var(--fs-lg);
  line-height: 1.75;
  color: var(--ink-2);
}
.v3-search {
  display: flex; align-items: center; gap: 10px;
  margin-top: var(--sp-6);
  max-width: 520px; height: 50px;
  padding: 0 16px;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-full);
  box-shadow: var(--shadow-1);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.v3-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.v3-search svg { flex: none; color: var(--ink-3); }
.v3-search input { flex: 1 1 auto; min-width: 0; border: 0; background: none; outline: none; font-size: var(--fs-md); }
.v3-search input::-webkit-search-cancel-button { display: none; }
.v3-search__clear {
  flex: none; width: 22px; height: 22px; display: grid; place-items: center;
  border-radius: 50%; background: var(--surface-2); color: var(--ink-2); font-size: 12px;
}
.v3-search__clear:hover { background: var(--ink); color: var(--ink-invert); }

.v3-hero__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-5);
  padding-bottom: 6px;
}
.v3-stat { border-top: 1px solid var(--line-strong); padding-top: 12px; }
.v3-stat b {
  display: block;
  font-family: var(--ff-display);
  font-size: clamp(28px, 3.4vw, 52px);
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
.v3-stat span { display: block; margin-top: 6px; font-family: var(--ff-mono); font-size: var(--fs-3xs); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); }

/* 破格元素：一个压住 hero 边缘的装饰字，纯装饰 */
.v3-hero__mark {
  position: absolute;
  right: -0.06em; bottom: -0.3em;
  font-family: var(--ff-display);
  font-size: clamp(120px, 22vw, 300px);
  line-height: 0.72;
  letter-spacing: -0.06em;
  color: var(--ink);
  opacity: 0.045;
  pointer-events: none;
  user-select: none;
}

.v3-hero__actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-5); }
/* 登录/退出/管理按钮在 hero 里的点按反馈，比通用 btn 更醒目一点 */
.v3-hero__actions .btn { min-height: 44px; padding: 0 20px; font-weight: 600; }
.v3-hero__account {
  margin-top: var(--sp-3);
  font-family: var(--ff-mono); font-size: var(--fs-2xs); color: var(--ink-2);
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.v3-hero__account b { font-weight: 500; color: var(--accent); }
/* 详情页「下载地址」链接：浮层深底上用亮朱红保证对比度 */
.v3-download {
  color: var(--accent); font-weight: 500; text-decoration: none;
  border-bottom: 1px solid color-mix(in oklab, var(--accent) 45%, transparent);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.v3-download:hover { color: var(--accent-hover); border-color: var(--accent); }
.v3-overlay .v3-download { color: oklch(0.80 0.13 30); }
.v3-overlay .v3-download:hover { color: oklch(0.88 0.10 30); border-color: oklch(0.80 0.13 30); }
.v3-hero__coverage {
  margin-top: var(--sp-4);
  font-family: var(--ff-mono); font-size: var(--fs-2xs); color: var(--ink-3);
  display: flex; gap: 14px; flex-wrap: wrap;
}
.v3-hero__coverage b { color: var(--ink-2); font-weight: 500; }

/* ==========================================================================
   吸顶工具条：控件行 + 类别轨道
   滚到任何位置都够得着筛选与数量，不用回到顶部
   ========================================================================== */
.v3-sticky {
  position: sticky; top: 0; z-index: var(--z-sticky);
  background: color-mix(in oklab, var(--paper) 88%, transparent);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid var(--line);
}
.v3-bar {
  display: flex; align-items: center; gap: 8px var(--sp-4); flex-wrap: wrap;
  padding: 10px var(--sp-7) 8px;
}
.v3-status {
  font-family: var(--ff-mono); font-size: var(--fs-2xs); color: var(--ink-3);
  white-space: nowrap;
}
.v3-status b { color: var(--ink); font-weight: 500; font-size: var(--fs-sm); }
.v3-chips { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.v3-bulkbar {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
  padding: 8px var(--sp-7);
  border-top: 1px solid var(--line);
  background: color-mix(in oklab, var(--surface-2) 70%, transparent);
}
.v3-bulkbar__count {
  margin-right: auto;
  font-family: var(--ff-mono); font-size: var(--fs-2xs); color: var(--ink-3);
}
.v3-bulkbar__count b { color: var(--ink); font-weight: 500; }

/* 右侧控件组：min-width:0 + 自身可换行，保证永远不会溢出被裁掉 */
.v3-bar__right {
  display: flex; align-items: center; gap: 8px var(--sp-3); flex-wrap: wrap;
  justify-content: flex-end;
  flex: 1 1 auto; min-width: 0;
}

/* 控件都带一个极小的说明字，避免一排下拉看不出各是干什么的。
   flex: 0 0 auto —— 不参与压缩，空间不够时整组换行，而不是把下拉挤到文字溢出重叠。 */
.v3-f { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.v3-f__label {
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
  white-space: nowrap;   /* 被挤扁时宁可换行，也不要竖排成"来/源" */
}
.v3-f .select {
  height: 30px; min-height: 30px; font-size: var(--fs-2xs);
  background-color: var(--surface);
  width: auto; min-width: 132px; max-width: 200px;
}
.v3-tgl {
  min-height: 30px; padding: 0 10px;
  font-size: var(--fs-2xs);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.v3-tgl:hover { border-color: var(--ink-3); color: var(--ink); }
.v3-tgl[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.v3-tgl--star[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

/* 类别轨道：单选 + 自动换行。
   超过单行可容纳宽度时折到第二行，而不是继续向右延伸；
   水平间距靠每个按钮自带的内边距（16px）保持一致，行间用 2px 呼吸。 */
.v3-chapters {
  display: flex; align-items: stretch;
  flex-wrap: wrap;
  gap: 2px 0;
  padding: 0 var(--sp-7);
}
.v3-chapter {
  position: relative;
  flex: none;
  padding: 11px 16px 10px;
  font-size: var(--fs-sm);
  color: var(--ink-2);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}
.v3-chapter::after {
  content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.v3-chapter:hover { color: var(--ink); }
.v3-chapter[aria-pressed="true"] { color: var(--ink); font-weight: 500; }
.v3-chapter[aria-pressed="true"]::after { transform: scaleX(1); }
.v3-chapter__dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--cat, var(--cat-fallback)); margin-right: 7px; vertical-align: middle; }
.v3-chapter em { font-style: normal; margin-left: 7px; font-family: var(--ff-mono); font-size: var(--fs-3xs); color: var(--ink-3); }

/* ==========================================================================
   效果墙：行优先的四列网格
   --------------------------------------------------------------------------
   之前用 CSS `columns`（多列布局），它是**列优先**的 —— 内容先填满第一列再填第二列，
   所以第一行看起来是 001 / 007 / 013 / 019。改成 CSS Grid 后就是**行优先**：
   第一行 001 002 003 004，从左到右读。列数固定 4（窄屏按断点降到 3 / 2 / 1）。
   ========================================================================== */
.v3-wall {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-6) var(--sp-5);
  align-items: start;
  padding: var(--sp-6) var(--sp-7) 0;
}
/* 空状态要占满整行 */
.v3-wall > .empty { grid-column: 1 / -1; }

.v3-card {
  position: relative;
  min-width: 0;
  /* 逐张入场：默认隐藏，进入视口后由 JS 加上 .in */
  opacity: 0;
  transform: translateY(var(--enter-y));
}
.v3-card.in {
  opacity: 1; transform: none;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--d, 0ms);
}
/* 键盘遍历时的"当前卡片"：用强调色描边，和鼠标悬停区分开 */
.v3-card.is-cursor::after {
  content: ""; position: absolute; inset: -6px -6px -10px;
  border: 2px solid var(--accent); border-radius: calc(var(--r-md) + 6px);
  pointer-events: none;
}

.v3-card__mediawrap { position: relative; }
.v3-card__select {
  position: absolute; right: 48px; bottom: 10px; z-index: 4;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 7px;
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: color-mix(in oklab, var(--surface) 90%, transparent);
  color: var(--ink-2);
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  backdrop-filter: blur(8px);
  cursor: pointer;
}
.v3-card__select input { margin: 0; accent-color: var(--accent); }
.v3-card__select:hover,
.v3-card__select:focus-within {
  border-color: var(--accent-line);
  background: var(--surface);
}
.v3-card.is-selected .v3-card__media {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.v3-card__hit { display: block; width: 100%; text-align: left; position: relative; }
/* 外层展示用固定外框（16:9），素材按 contain 完整适配 ——
   上传什么尺寸都不会把卡片撑变形、拉伸或裁切。 */
.v3-card__media {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--dur-base) var(--ease-out);
}
.v3-card__media .media { position: absolute; inset: 0; aspect-ratio: auto !important; height: 100%; }
.v3-card__media .media__el { width: 100%; height: 100%; object-fit: contain; }
.v3-card:hover .v3-card__media { box-shadow: var(--shadow-2); }
.v3-card:hover .media__el.is-loaded { transform: none; }
.v3-card.is-drag .v3-card__media { outline: 2px solid var(--accent); outline-offset: -2px; }

/* 类别角标：压在素材左上 */
.v3-card__cat {
  position: absolute; left: 10px; top: 10px;
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  padding: 3px 8px; border-radius: var(--r-full);
  background: color-mix(in oklab, var(--surface) 84%, transparent);
  color: var(--ink-2);
  backdrop-filter: blur(8px);
  border: 1px solid var(--line);
}
/* 宿主兼容标识：卡片右上角。深底浅字，在浅色占位底和真实素材上都读得出；
   AE / PR 各带一点 Adobe 品牌色相，一眼区分双支持还是仅其一。
   pointer-events:none —— 徽标不挡点击，点卡片仍是打开详情。 */
.v3-card__host {
  position: absolute; right: 10px; top: 8px; z-index: 2;
  display: inline-flex; gap: 4px;
  pointer-events: none;
}
.v3-card__host i {
  font-style: normal;
  font-family: var(--ff-mono); font-size: var(--fs-3xs); font-weight: 500;
  line-height: 1; padding: 3px 5px; border-radius: var(--r-xs);
  background: oklch(0.16 0.01 60 / 0.66);
  letter-spacing: 0.06em;
  backdrop-filter: blur(4px);
}
.v3-host-ae { color: oklch(0.84 0.09 285); }   /* After Effects 紫 */
.v3-host-pr { color: oklch(0.82 0.12 330); }   /* Premiere Pro 紫粉 */
/* 素材状态角标：405 条里哪些已经配好素材、有几条，一眼能看出来。
   注意要抬到标题块的压盖线（18px）之上，否则会被标题块遮住。 */
.v3-card__state {
  position: absolute; left: 10px; bottom: 26px;
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  padding: 3px 7px; border-radius: var(--r-xs);
  background: color-mix(in oklab, var(--surface) 90%, transparent);
  color: var(--ink-2); backdrop-filter: blur(8px);
  border: 1px solid var(--line);
  letter-spacing: 0.04em;
}
.v3-card__state::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex: none;
}
.v3-card__state[data-state="none"] { color: var(--ink-3); border-style: dashed; }
.v3-card__state[data-state="anim"] { color: var(--accent); }
.v3-card__state[data-state="video"] { color: var(--accent); }
.v3-card__state[data-state="image"] { color: var(--ok); }

/* 悬停快捷收藏：已收藏的常亮，不用悬停也能看出来。同样抬到压盖线之上。 */
.v3-qbtn {
  position: absolute; right: 10px; bottom: 26px;
  width: 30px; height: 30px; display: grid; place-items: center;
  border-radius: var(--r-full);
  background: color-mix(in oklab, var(--surface) 90%, transparent);
  border: 1px solid var(--line);
  color: var(--ink-3);
  backdrop-filter: blur(8px);
  opacity: 0; transform: translateY(4px);
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.v3-card__mediawrap > .v3-card__select {
  bottom: 26px;
}
.v3-card:hover .v3-qbtn,
.v3-card.is-cursor .v3-qbtn,
.v3-qbtn:focus-visible { opacity: 1; transform: none; }
.v3-qbtn[aria-pressed="true"] { opacity: 1; transform: none; color: var(--accent); border-color: var(--accent-line); }
.v3-qbtn:hover { background: var(--surface); color: var(--accent); }
.v3-qbtn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.v3-qbtn[aria-pressed="true"] svg { fill: currentColor; }

/* 标题块与素材重叠（上移 18px），左右留对称边距、统一左对齐。
   曾经按卡片序号做交错缩进，是三列时代的错位设计残留；
   四列网格下会让每行第 2/3 张卡的名字块缩进不一致（12/34/6/12px），
   短名字显得忽左忽右 —— 已移除，统一为对称 12px。 */
.v3-card__title {
  position: relative;
  display: block; width: auto;
  margin: -18px 12px 0 12px;
  padding: 10px 14px 11px;
  text-align: left;
  background: var(--band-bg);
  color: var(--band-ink);
  border-radius: var(--r-sm);
  box-shadow: var(--shadow-1);
  transition: transform var(--dur-base) var(--ease-out);
}
.v3-card:hover .v3-card__title { transform: translateY(-3px); }
/* 中英文名混排：统一字重与行高，减少「英文粗、中文细」的割裂。
   英文名 600 / 中文名 500，颜色同系（中文名用 color-mix 提亮到接近英文名）；
   换行用 break-word（优先词边界断，超长技术名才在词内断），
   英文名最多 2 行、中文名 1 行，超出省略号，避免长名撑破卡片。 */
.v3-card__en {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  font-family: var(--ff-sans);
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  overflow-wrap: break-word;
  overflow: hidden;
}
.v3-card__cn {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 1;
  margin-top: 4px;
  font-family: var(--ff-sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: color-mix(in oklab, var(--band-ink) 82%, var(--band-ink-2));
  overflow-wrap: break-word;
  overflow: hidden;
}
.v3-card__cn--missing { font-family: var(--ff-mono); font-size: var(--fs-3xs); color: color-mix(in oklab, var(--band-ink) 40%, var(--band-bg)); }
.v3-translation-source { display: inline-block; margin-left: 6px; font-size: 9px; font-weight: 500; line-height: 1.4; vertical-align: 2px; color: var(--ink-3); }
.v3-translation-source--machine { color: #9a5712; }
.v3-intro-source { display: inline-block; margin-top: 8px; color: var(--ink-3); font-size: var(--fs-xs); text-decoration: underline; text-underline-offset: 2px; }
.v3-card__note {
  margin: 12px 12px 0;
  font-size: var(--fs-xs); line-height: 1.7; color: var(--ink-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  /* 固定两行高度：四列网格里卡片高度一致，行与行对齐才干净 */
  min-height: 42px;
}
.v3-card__meta {
  display: flex; gap: 8px; align-items: center;
  margin: 8px 12px 0;
  font-family: var(--ff-mono); font-size: var(--fs-3xs); color: var(--ink-3);
}
.v3-card__acts { display: none; gap: 6px; margin: 10px 12px 0; flex-wrap: wrap; }
body[data-manage="true"] .v3-card__acts { display: flex; }

.v3-more { display: grid; place-items: center; gap: var(--sp-3); padding: var(--sp-7) var(--sp-7) var(--sp-8); }
.v3-more__info { font-family: var(--ff-mono); font-size: var(--fs-2xs); color: var(--ink-3); }
.v3-more__bar {
  width: min(240px, 60vw); height: 3px; border-radius: var(--r-full);
  background: var(--surface-3); overflow: hidden;
}
.v3-more__bar i { display: block; height: 100%; background: var(--accent); }

/* ==========================================================================
   页脚：品牌收尾（作者与抖音号已上移到 hero 刊头顶行）
   ========================================================================== */
.v3-footer {
  border-top: 1px solid var(--line);
  margin-top: var(--sp-6);
  padding: var(--sp-5) var(--sp-7) var(--sp-6);
  background: color-mix(in oklab, var(--surface-2) 50%, transparent);
}
.v3-footer__brand {
  font-family: var(--ff-display);
  font-size: var(--fs-md);
  letter-spacing: -0.02em;
  color: var(--ink);
}

/* ==========================================================================
   右下角：滚动进度环 + 回到顶部
   ========================================================================== */
.v3-fab {
  position: fixed; right: var(--sp-5); bottom: var(--sp-5); z-index: var(--z-panel);
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-2);
  color: var(--ink-2);
  opacity: 0; transform: translateY(12px) scale(0.9);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out), color var(--dur-fast) var(--ease-out);
  pointer-events: none;
}
.v3-fab[data-show="true"] { opacity: 1; transform: none; pointer-events: auto; }
.v3-fab:hover { color: var(--accent); border-color: var(--accent-line); }
.v3-fab__ring { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.v3-fab__ring circle { fill: none; stroke-width: 2; }
.v3-fab__track { stroke: var(--line); }
.v3-fab__bar { stroke: var(--accent); stroke-linecap: round; transition: stroke-dashoffset 120ms linear; }
.v3-fab__arrow { font-size: 15px; line-height: 1; }

/* ==========================================================================
   沉浸式详情浮层
   ========================================================================== */
.v3-overlay {
  position: fixed; inset: 0; z-index: var(--z-overlay);
  display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
  background: oklch(0.16 0.012 60 / 0.93);
  backdrop-filter: blur(18px);
  color: oklch(0.965 0.004 85);
  animation: v3-overlay-in var(--dur-base) var(--ease-out);
}
@keyframes v3-overlay-in { from { opacity: 0; } }
.v3-overlay__bar {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid oklch(1 0 0 / 0.12);
}
.v3-overlay__pos { font-family: var(--ff-mono); font-size: var(--fs-2xs); color: oklch(0.78 0.006 85); }
.v3-overlay__body {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(300px, 0.65fr);
  gap: var(--sp-7);
  padding: var(--sp-5) var(--sp-7) var(--sp-5);
  min-height: 0;
  overflow: hidden;
}
/* 详情舞台固定为 1920×1080 的 16:9 画布，实际像素随容器缩放。 */
.v3-overlay__body > :first-child {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.v3-stage {
  display: grid; place-items: stretch;
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: calc(100% - 28px);
  margin: auto 0 0;
  min-height: 0; min-width: 0;
  overflow: hidden;
}
.v3-stage .media {
  width: 100%; height: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-md);
  background: oklch(0.19 0.010 60 / 0.55);
  overflow: hidden;
  cursor: default;
}
.v3-stage .media__el { object-fit: contain; background: transparent; }
/* 素材切换时只动舞台内容，外框尺寸保持稳定，避免整块画面闪烁。 */
.v3-stage.is-switching .media {
  animation: v3-stage-box-in 320ms var(--ease-out) both;
}
.v3-stage.is-switching .media__el.is-loaded {
  animation: v3-stage-media-in 360ms var(--ease-out) both;
}
@keyframes v3-stage-box-in {
  from { opacity: 0.35; transform: scale(0.985); }
  to { opacity: 1; transform: none; }
}
@keyframes v3-stage-media-in {
  from { opacity: 0; transform: scale(1.012); }
  to { opacity: 1; transform: none; }
}
.v3-zoombar {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-top: 10px;
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  color: oklch(0.72 0.006 85);
}
.v3-overlay__side { overflow-y: auto; min-height: 0; padding-right: 4px; }
.v3-overlay__names { margin-bottom: var(--sp-5); }
.v3-overlay__en {
  font-size: clamp(26px, 3vw, 46px);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  overflow-wrap: break-word;
}
.v3-overlay__cn {
  margin-top: 8px;
  font-size: var(--fs-xl);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: oklch(0.86 0.008 85);
  overflow-wrap: break-word;
}
.v3-overlay__cn--missing { font-family: var(--ff-mono); font-size: var(--fs-sm); color: oklch(0.62 0.008 85); }
.v3-overlay__cn .v3-translation-source { color: oklch(0.68 0.01 85); }
.v3-overlay__cn .v3-translation-source--machine { color: #f0b35f; }
.v3-overlay__cn .v3-intro-source { color: oklch(0.72 0.02 200); }
.v3-overlay__block { padding: var(--sp-4) 0; border-top: 1px solid oklch(1 0 0 / 0.12); }
.v3-overlay__block .u-label { color: oklch(0.70 0.008 85); }
.v3-overlay__text { margin-top: 8px; font-size: var(--fs-sm); line-height: 1.85; white-space: pre-line; color: oklch(0.90 0.006 85); }
.v3-overlay__acts { display: flex; gap: 8px; flex-wrap: wrap; margin-top: var(--sp-5); }
/* 同类快捷跳转 */
.v3-same {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 10px;
  font-size: var(--fs-xs);
  color: oklch(0.86 0.006 85);
  border-bottom: 1px solid oklch(1 0 0 / 0.28);
  padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.v3-same:hover { color: oklch(1 0 0); border-color: oklch(1 0 0 / 0.6); }
.v3-overlay .kv { border-top-color: oklch(1 0 0 / 0.12); }
.v3-overlay .kv > div { border-bottom-color: oklch(1 0 0 / 0.10); }
.v3-overlay .kv dt { color: oklch(0.70 0.008 85); }
.v3-overlay .kv dd { color: oklch(0.94 0.005 85); }
.v3-asset-note__text { white-space: pre-line; }
.v3-asset-note__edit-btn {
  margin-left: 8px;
  color: oklch(0.76 0.01 70);
  font-size: var(--fs-2xs);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.v3-asset-note__edit-btn:hover { color: oklch(0.98 0.004 85); }
.v3-asset-note__edit { display: grid; gap: 8px; }
.v3-asset-note__edit .textarea { min-height: 72px; font-family: var(--ff-sans); font-size: var(--fs-sm); }
.v3-asset-note__actions { display: flex; justify-content: flex-end; gap: 6px; }
.v3-overlay .tag { background: oklch(1 0 0 / 0.10); border-color: oklch(1 0 0 / 0.16); color: oklch(0.90 0.006 85); }
.v3-overlay .btn--outline { border-color: oklch(1 0 0 / 0.26); color: oklch(0.96 0.004 85); background: oklch(1 0 0 / 0.06); }
.v3-overlay .btn--outline:hover { background: oklch(1 0 0 / 0.14); }
.v3-navbtn {
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 1px solid oklch(1 0 0 / 0.22); border-radius: var(--r-full);
  color: oklch(0.96 0.004 85);
  transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.v3-navbtn:hover:not([disabled]) { background: oklch(1 0 0 / 0.14); transform: scale(1.06); }
.v3-navbtn[disabled] { opacity: 0.28; cursor: not-allowed; }

/* 底部素材条：当前效果自己的主素材 + 追加素材，不再跳到别的效果。
   标签固定在左侧不随缩略图滚动。 */
.v3-aside {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 10px var(--sp-5) calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid oklch(1 0 0 / 0.12);
  min-height: 78px;
}
.v3-aside__label {
  flex: none;
  display: grid; gap: 3px;
  font-family: var(--ff-mono); font-size: var(--fs-3xs);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: oklch(0.70 0.008 85);
  white-space: nowrap;
}
.v3-aside__label b { color: oklch(0.95 0.004 85); font-size: var(--fs-2xs); letter-spacing: 0.04em; }
.v3-aside__hint { font-size: 9.5px; letter-spacing: 0.02em; color: oklch(0.60 0.008 85); text-transform: none; }

.v3-strip {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 auto; min-width: 0;
  padding: 6px 2px 8px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: thin;
  scroll-behavior: smooth;
}
.v3-strip__item {
  position: relative;
  flex: none; width: 74px;
  border-radius: var(--r-xs);
  overflow: hidden;
  border: 1px solid oklch(1 0 0 / 0.16);
  opacity: 0.6;
  transition: opacity var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.v3-strip__item:hover { opacity: 0.95; transform: translateY(-2px); }
.v3-strip__item[aria-current="true"] { opacity: 1; border-color: oklch(0.99 0 0 / 0.9); }
.v3-strip__item .media { border-radius: 0; aspect-ratio: 16 / 9; }
.v3-strip__item .media__el { object-fit: contain; }
.v3-strip__item[aria-current="true"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
  background: oklch(0.99 0 0 / 0.9);
}
.v3-strip__tag {
  position: absolute; left: 3px; top: 3px;
  font-family: var(--ff-mono); font-size: 9px;
  padding: 1px 4px; border-radius: var(--r-xs);
  background: oklch(0.12 0.01 60 / 0.78); color: oklch(0.96 0.004 85);
  letter-spacing: 0.04em;
}
.v3-strip__ph {
  display: grid; place-items: center;
  aspect-ratio: 16 / 9;
  background: oklch(1 0 0 / 0.08);
  font-family: var(--ff-mono); font-size: 9px; color: oklch(0.72 0.006 85);
}
.v3-strip__add {
  flex: none; width: 74px;
  display: grid; place-items: center; gap: 3px;
  aspect-ratio: 16 / 9;
  border: 1px dashed oklch(1 0 0 / 0.3);
  border-radius: var(--r-xs);
  color: oklch(0.86 0.006 85);
  font-size: var(--fs-lg); line-height: 1;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.v3-strip__add:hover { background: oklch(1 0 0 / 0.1); border-color: oklch(1 0 0 / 0.55); }
.v3-strip__empty {
  font-size: var(--fs-xs); color: oklch(0.68 0.008 85);
  font-family: var(--ff-mono);
}

/* ------------------------------------------------------------ 响应式 */
@media (max-width: 1280px) {
  .v3-wall { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .v3-overlay__body { grid-template-columns: minmax(0, 1fr) minmax(280px, 0.7fr); gap: var(--sp-5); padding: var(--sp-5); }
}
@media (max-width: 1080px) {
  .v3-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .v3-hero { grid-template-columns: minmax(0, 1fr); gap: var(--sp-6); padding: var(--sp-7) var(--sp-5) var(--sp-6); }
  .v3-hero__stats { grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); }
  .v3-hero__mark { opacity: 0.03; }
  .v3-bar, .v3-bulkbar, .v3-chapters, .v3-wall, .v3-more, .v3-footer { padding-left: var(--sp-5); padding-right: var(--sp-5); }
  .v3-bar { gap: var(--sp-2); padding-top: 8px; }
  .v3-bar__right { margin-left: 0; width: 100%; }
  .v3-overlay__body { display: flex; flex-direction: column; overflow-y: auto; padding: var(--sp-4); gap: var(--sp-4); }
  .v3-overlay__body > :first-child { flex: none; }
  .v3-stage { max-height: none; flex: 0 0 auto; }
  .v3-overlay__side { overflow: visible; flex: none; }
  .v3-aside { padding-left: var(--sp-4); padding-right: var(--sp-4); }
  .v3-aside__label { display: none; }
}
@media (max-width: 680px) {
  .v3-wall { grid-template-columns: minmax(0, 1fr); }
  .v3-hero__title { font-size: clamp(34px, 11vw, 52px); }
  .v3-card__title { margin-left: 10px; margin-right: 10px; }
  .v3-fab { right: var(--sp-4); bottom: var(--sp-4); }
  .v3-hero__top { align-items: flex-start; flex-direction: column; gap: var(--sp-2); }
  .v3-footer { padding-top: var(--sp-4); padding-bottom: var(--sp-4); }
}

@media (prefers-reduced-motion: reduce) {
  .v3-stage.is-switching .media,
  .v3-stage.is-switching .media__el.is-loaded { animation: none; }
}
