/* ═══════════════════════════════════════════════════════════════
 * Filmstrip Hero — 样式
 *
 * 设计基准见 design/hero-carousel-filmstrip.md
 *
 * 原则：这里**不出现任何写死的尺寸**。所有几何都走 CSS 变量，
 * 变量由 hero-filmstrip.js 按舞台比例写入 —— 这样同一个组件在
 * 320px 手机和 4K 屏上比例完全一致。
 * ═══════════════════════════════════════════════════════════════ */

/* ── 浮在 hero 之上的导航层 ── */
.hero-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  /*
   * 要比 hero 高。hero 内部的 `.hf-bg-hue` 用了 mix-blend-mode，
   * 那会创建自己的 stacking context —— 父层如果只给一个不痛不痒的 z-index，
   * 很可能被它盖住，表现就是“页头文字凭空消失”（而不是变淡）。
   * 所以这里直接给一个大值，不跟它比谁优雅。
   */
  z-index: 200;
  padding: clamp(14px, 3vw, 32px) clamp(16px, 4vw, 48px);
  /* 不挡拖拽：hero 的卡片带要能直接抓到 */
  pointer-events: none;
}

/* hero 自己回到下层，不跟浮层抢 */
#spotlight { position: relative; z-index: 0; }
.hero-layer a,
.hero-layer button {
  pointer-events: auto;
}

/* 原本的 .topbar 是 fixed（页面无 hero 时的做法）；
   现在它属于 hero 浮层，改为常规流，否则会飘到视野之外 */
/* 语言开关：与登录按钮同一排，做成胶囊而不只是文字，
   让它看起来是一个“控件”而不是一处链接 */
.lang-toggle {
  padding: .34em 1em;
  border: 1px solid rgba(255, 255, 255, .28);
  border-radius: 999px;
  background: rgba(255, 255, 255, .06);
  color: rgba(255, 255, 255, .88);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background .2s, border-color .2s;
}
.lang-toggle:hover {
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .45);
}

.hero-layer .topbar {
  position: static;
  top: auto;
  padding: 0;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  margin-bottom: clamp(10px, 2vw, 22px);
}

/*
 * 页头已移除。
 *
 * 之前这里还有 `.hero-layer header` / `h1` / `.brand` / `.sub` 几条规则
 * （文字压在图上需要 text-shadow 垫底）。
 * 现在那三行不在了，规则也跟着删——留着就是死代码，
 * 而且下次有人看到“为什么 h1 有阴影”会找不到那个 h1。
 */

body { position: relative; }

/* 作品太少时 hero 不渲染（#spotlight 带 hidden）——
   此时浮层不能继续绝对定位，否则控件会掉在一片空白上。 */
body:has(#spotlight.hidden) .hero-layer {
  position: relative;
}

/* hero 之后的内容需要呼吸：100dvh 的带子下面直接接 tabs 会贴得很死 */
.wrap { padding-top: clamp(20px, 4vw, 40px); }

/* ── 舞台在页面里的尺寸 ──
 *
 * 全屏。这里用 100dvh（dynamic viewport height）而不是 100vh：
 * 移动端地址栏收起/展开时 vh 是个固定值，会让底部留出一条白，
 * 或者把内容顶出去。dvh 跟踪真实的可用高度，地址栏不管怎么动都贴合。
 *
 * fallback：不支持 dvh 的浏览器退回 100vh，至少不会碎。
 */
#spotlight { position: relative; }
#spotlight .hf-stage {
  height: 100vh;
  height: 100dvh;
  min-height: 30rem;
}

/*
 * 页头与筛选栏浮在 hero 之上。
 *
 * 既然 hero 接管了整屏，就不该在它上面再堆一块黑底把“会变的背景”遮住——
 * 那等于把刚做出来的效果又盖回去。所以这两层改成绝对定位的浮层，
 * 让作品图从第一像素就开始铺。
 */
.hero-overlay-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  padding: clamp(18px, 4vw, 44px) clamp(16px, 4vw, 48px) 0;
  pointer-events: none;
}
.hero-overlay-top a,
.hero-overlay-top button { pointer-events: auto; }

.hf-stage {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 24rem;
  overflow: hidden;
  background: #000;
  color: #fff;
  user-select: none;
  -webkit-user-select: none;
  outline: none;
}
.hf-stage:focus-visible { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .4); }

/* ── 背景：图片层 + 两层调色 ── */

.hf-bg { position: absolute; inset: 0; }

.hf-bg-img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  transform: scale(1.28);
  transition: opacity .7s ease-out;
}

/* 保住照片明度、只取 accent 的色相 —— 整块幕布随每次切换摆动 */
.hf-bg-hue {
  position: absolute;
  inset: 0;
  mix-blend-mode: color;
  transition: background-color .7s ease-out;
}
.hf-bg-mul {
  position: absolute;
  inset: 0;
  opacity: .55;
  mix-blend-mode: multiply;
  transition: background-color .7s ease-out;
}

/* 可读性压暗 + 颗粒（在调色层之上，所以换图时不会跟着闪） */
.hf-wash {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, .4) 0%,
    transparent 50%,
    rgba(0, 0, 0, .45) 100%
  );
}
.hf-grain {
  position: absolute;
  inset: 0;
  opacity: .22;
  mix-blend-mode: overlay;
  background-size: 180px 180px;
  pointer-events: none;
}

/* ── 顶部 cluster（居中，不铺满） ── */

.hf-top {
  position: absolute;
  left: 0;
  right: 0;
  top: max(16px, 2.9%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: max(20px, 6%);
}
.hf-brand {
  font-weight: 600;
  letter-spacing: .06em;
  font-size: calc(var(--hf-label, 12px) * 1.35);
}

/* ── 居中三段式：badge → 大标题 → 副标题 → CTA ──
 *
 * 之前是左对齐一行（标题 + 署名 + 元信息），读起来像文档标题：
 * 视线从左往右扫，然后在右侧散掉。居中堆叠把视线钉在画面中轴——
 * 不是审美偏好，它是让“一眼看完一句话”成立的最短路径。
 */

.hf-center {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: var(--hf-strip-top, 50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  text-align: center;
  padding-left: var(--hf-pad, 20px);
  padding-right: var(--hf-pad, 20px);
  padding-bottom: clamp(16px, 3.5%, 40px);
  gap: clamp(6px, 1.2vh, 14px);
  pointer-events: none;
  /* 内容不应溢出到 CTA 上：设 0 允许它被压缩 */
  min-height: 0;
  overflow: hidden;
}

.hf-center > * { flex-shrink: 0; }

/* 胶囊：先给一个上下文 */
.hf-badge {
  display: inline-flex;
  align-items: center;
  padding: .42em 1.05em;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 999px;
  font-size: var(--hf-badge, 13px);
  font-weight: 500;
  color: rgba(255, 255, 255, .84);
  background: rgba(255, 255, 255, .06);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* 大标题：超粗、紧行距、负字距 —— 参考图那种“块状”标题 */
.hf-title {
  margin: 0;
  font-weight: 800;
  line-height: .94;
  letter-spacing: -.035em;
  font-size: var(--hf-title, 56px);
  max-width: min(92%, 13ch);
  text-shadow: 0 4px 30px rgba(0, 0, 0, .45);
}

/* 每行独立揭示：外层裁切，内层上推 */
.hf-line { display: block; overflow: hidden; }
.hf-line > span {
  display: block;
  transform: translateY(110%);
  transition: transform .62s cubic-bezier(.22, 1, .36, 1);
}

.hf-sub {
  margin: 0;
  max-width: min(92%, 34ch);
  font-size: var(--hf-sub, 15px);
  line-height: 1.5;
  color: rgba(255, 255, 255, .64);
  text-shadow: 0 2px 14px rgba(0, 0, 0, .4);
  /* 副标题最多两行，多了就不是副标题而是正文 */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* CTA：颜色跟随当前作品的 accent ——
   它是画面里唯一一个“可点的色块”，用作品自己的色才不会跳出来。 */
.hf-cta {
  margin-top: clamp(4px, 1vh, 12px);
  padding: .8em 1.7em;
  border: 0;
  border-radius: 999px;
  font-size: var(--hf-sub, 15px);
  font-weight: 600;
  font-family: inherit;
  color: #fff;
  background: var(--hf-accent, #e8442c);
  cursor: pointer;
  pointer-events: auto;
  transition: transform .2s var(--ease-expo-out, ease-out), filter .2s;
  box-shadow: 0 10px 30px -8px rgba(0, 0, 0, .6);
}
.hf-cta:hover { transform: translateY(-1px); filter: brightness(1.1); }
.hf-cta:active { transform: translateY(0); filter: brightness(.96); }

/* ── 卡片 strip ── */

.hf-strip {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--hf-strip-top, 50%);
  height: var(--hf-full-h, 200px);
}
.hf-track {
  display: flex;
  align-items: flex-start;
  gap: var(--hf-gap, 8px);
  cursor: grab;
  /* spring 近似：轻微 overshoot，让「展开」有弹性而不是生硬 */
  transition: transform .55s cubic-bezier(.34, 1.24, .64, 1);
  will-change: transform;
}
.hf-track.is-grabbing { cursor: grabbing; transition: none; }

.hf-card {
  position: relative;
  flex: 0 0 auto;
  width: var(--hf-card-w, 150px);
  height: var(--hf-half-h, 100px);
  padding: 0;
  border: 0;
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
  transition: height .55s cubic-bezier(.34, 1.24, .64, 1);
  cursor: pointer;
}

/* 26% 是经验值：人像的视觉重心在 1/4 偏上。
   这个值决定裁切是「取景」还是「切头」。 */
.hf-card img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 26%;
}

/* 未聚焦的卡退后一点，但**不灰度** —— 保持彩色，只是暗下去 */
.hf-card-veil {
  position: absolute;
  inset: 0;
  background: #000;
  transition: opacity .55s;
  pointer-events: none;
}

/* ── 位置轨 ── */

.hf-rail {
  position: absolute;
  left: var(--hf-pad, 20px);
  bottom: max(14px, 2.2%);
  width: 20%;
}
.hf-rail-nums {
  display: flex;
  justify-content: space-between;
  font-family: ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
  opacity: .8;
  font-size: var(--hf-label, 12px);
}
.hf-rail-bar {
  position: relative;
  margin-top: .5rem;
  height: 1px;
  width: 100%;
  background: rgba(255, 255, 255, .25);
}
.hf-rail-fill {
  position: absolute;
  top: 0;
  bottom: 0;
  background: #fff;
  transition: left .55s cubic-bezier(.34, 1.24, .64, 1), width .55s;
}

/* ── 减少动效：所有过渡归零 ── */

.hf-reduced *,
.hf-reduced *::before,
.hf-reduced *::after {
  transition-duration: 0s !important;
  animation-duration: 0s !important;
}
