/* ===== Reset & Base ===== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg: #ffffff;
  --text: #1a1a1a;
  --border: #e5e7eb;
  --card-bg: #f3f4f6;
  color-scheme: light;
}

html, body {
  overflow: hidden; height: 100%; width: 100%;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg); color: var(--text);
  line-height: 1.5; font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }
::-webkit-scrollbar { display: none; }
body { scrollbar-width: none; }

/* ===== Scene ===== */
.scene {
  width: 100vw; height: 100vh;
  overflow: hidden; position: relative; background: #fff;
}

.grid-bg {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(0,0,0,0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0,0,0,0.03) 1px, transparent 1px);
  background-size: 60px 60px;
  will-change: transform; z-index: 0;
}

/* ===== Ambient top gradient (smooth color flow) ===== */
.ambient-blob {
  position: fixed; top: 0; left: -60px; right: -60px;
  height: 500px;
  pointer-events: none; z-index: 1;
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  background: linear-gradient(90deg,
    rgba(66,133,244,0.4),
    rgba(234,67,53,0.35),
    rgba(251,188,4,0.35),
    rgba(52,168,83,0.35),
    rgba(66,133,244,0.4)
  );
  background-size: 400% 100%;
  animation: breatheColors 80s linear infinite;
  filter: blur(40px);
  /* 桌面端：渐变铺满视口顶部，仅在底部 55%→100% 淡出（无顶部白段——桌面端无 iOS 状态栏白边问题）
     左右各外扩 60px，超过 blur(40px) 半径，避免视口左右边缘出现虚化透明带 */
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 55%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 55%, transparent 100%);
}
@keyframes breatheColors {
  from { background-position: 0% 0%; }
  to   { background-position: -100% 0%; }
}

.year-label {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  z-index: 2; pointer-events: none;
  font-size: clamp(120px, 20vw, 280px);
  font-weight: 800; color: rgba(0,0,0,0.04);
  letter-spacing: -4px; user-select: none; line-height: 1;
  will-change: transform, opacity;
}

/* ===== Navbar (matches reference — pill hover-expand + glass) ===== */
.navbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 2100;
  padding: 0 16px;
  display: flex; justify-content: center; pointer-events: none;
  /* iOS Safari：强制 GPU 合成层，减少地址栏收起/展开时 fixed 元素的抖动 */
  transform: translateZ(0);
  -webkit-backface-visibility: hidden;
  transition: opacity 0.3s ease;
}
.nav-glass {
  pointer-events: auto; margin-top: 12px; height: 68px; width: max-content;
  max-width: 1024px; gap: 10px; border-radius: 18px;
  border: 1px solid rgba(255,255,255,0.3); padding: 10px;
  display: flex; align-items: center;
  background: rgba(255,255,255,0.8);
  backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.10);
  transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.nav-glass:hover {
  padding: 10px 26px;
  gap: 14px;
}
/* Pill items — circle by default, expand on hover */
.nav-pill {
  display: flex; align-items: center; justify-content: center;
  height: 50px; min-width: 50px; padding: 16px;
  border-radius: 9999px;
  cursor: pointer; text-decoration: none;
  position: relative;
  transition: all 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.nav-pill:hover {
  padding: 16px 22px;
  min-width: auto;
  border-radius: 14px;
}
.logo-pill { padding: 8px; width: 60px; min-width: 60px; border-radius: 9999px; perspective: 200px; }
.logo-pill:hover { padding: 8px; width: 60px; border-radius: 9999px; }

/* 3D wrapper: animated element, no mirror on back side */
.logo-3d-wrap {
  width: 48px; height: 48px;
  transform-style: preserve-3d;
}
.logo-pill:hover .logo-3d-wrap,
.nav-glass:hover .logo-3d-wrap {
  animation: logoPopSpin 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.nav-logo-icon {
  width: 100%; height: 100%;
  object-fit: contain;          /* 任意比例 logo 等比塞进盒子，不拉伸变形 */
  object-position: center;
  border-radius: 4px; display: block;
  position: absolute; top: 0; left: 0;
  backface-visibility: hidden;
}
.logo-back { transform: rotateY(180deg); }

@keyframes logoPopSpin {
  0%   { transform: rotateZ(0deg) rotateY(0deg) scale(1); }
  15%  { transform: rotateZ(-12deg) rotateY(0deg) scale(1.5); }
  30%  { transform: rotateZ(-6deg) rotateY(180deg) scale(1.4); }
  55%  { transform: rotateZ(0deg) rotateY(540deg) scale(1.2); }
  75%  { transform: rotateZ(0deg) rotateY(680deg) scale(1.05); }
  100% { transform: rotateZ(0deg) rotateY(720deg) scale(1); }
}

/* Auto-play hover animations once on page load */
.navbar.page-loaded .nav-glass {
  padding: 10px 26px;
  gap: 14px;
}
.navbar.page-loaded .nav-pill:not(.logo-pill) {
  padding: 16px 22px;
  min-width: auto;
  border-radius: 14px;
}
.navbar.page-loaded .logo-3d-wrap {
  animation: logoPopSpin 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.navbar.page-loaded .nav-label {
  color: #111827;
}

.nav-label {
  font-size: 16px; font-weight: 500; color: #6b7280;
  white-space: nowrap;
  transition: color 0.2s;
}
.nav-pill:hover .nav-label,
.nav-pill.active .nav-label { color: #111827; }
.nav-pill.active .nav-label { font-weight: 700; }

/* Active dot indicator */
.nav-dot {
  position: absolute; bottom: 6px; left: 50%;
  transform: translateX(-50%);
  width: 4px; height: 4px; border-radius: 50%;
  background: #111827; display: none;
}
.nav-pill.active .nav-dot { display: block; }

/* ===== Filter Panel ===== */
.filter-panel {
  position: fixed; top: 33px; left: 24px; z-index: 50;
}
.filter-row {
  display: flex; flex-direction: row; align-items: center; gap: 8px;
  margin-bottom: 14px;
}
.filter-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 15px; border-radius: 9999px; font-size: 13px;
  backdrop-filter: blur(12px); background: #111827; color: #fff;
  border: 1px solid #111827; cursor: pointer; font-family: 'Inter', sans-serif;
  white-space: nowrap; box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.filter-btn:hover { background: #1f2937; }
.filter-btn.active { background: #111827; color: #fff; border-color: #111827; }
.filter-btn:not(.active) { background: rgba(255,255,255,0.9); color: #374151; border-color: #e5e7eb; }
.filter-btn:not(.active):hover { background: #f3f4f6; border-color: #d1d5db; }

.filter-toggle-btn {
  display: flex; align-items: center; justify-content: center;
  height: 36px; width: 36px; border-radius: 9999px;
  border: 1px solid #e5e7eb; background: rgba(255,255,255,0.9);
  backdrop-filter: blur(12px); box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  cursor: pointer; color: #6b7280; transition: background 0.15s;
}
.filter-toggle-btn:hover { background: #f3f4f6; }
.filter-toggle-btn svg { transition: transform 0.22s ease; }
.filter-toggle-btn.open svg { transform: rotate(180deg); }

.filter-tags {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.22s ease;
}
.filter-tags.open { grid-template-rows: 1fr; }
.filter-tags > .filter-tags-inner {
  overflow: hidden;
  display: flex; flex-wrap: wrap; gap: 8px; max-width: 380px;
  padding-top: 0;
}
.filter-tags.open > .filter-tags-inner { padding-top: 2px; }
.filter-tag {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 15px; border-radius: 9999px; font-size: 13px;
  background: rgba(255,255,255,0.9); backdrop-filter: blur(12px);
  border: 1px solid #e5e7eb; color: #374151; cursor: pointer;
  font-family: 'Inter', sans-serif; white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0,0,0,0.05);
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.filter-tag:hover { background: #f3f4f6; border-color: #d1d5db; }
.filter-tag.active { background: #111827; color: #fff; border-color: #111827; }

/* ===== Card Wrapper (scene position) ===== */
.card-wrapper {
  position: absolute; top: 50%; left: 50%;
  margin-left: -160px; margin-top: -145px;
  will-change: transform, opacity;
  pointer-events: auto;
  cursor: pointer;
  z-index: 3;
  transition: z-index 0s;
}
.card-wrapper:hover {
  z-index: 100 !important;
}
/* 详情页打开期间：所有卡片必须完全退出命中测试。
   ⚠️ 为什么必须写这条 —— flyCardToCenter() 会把被点的那张卡片提到
   z-index:5000（动画期间需要盖过其他卡片，合理），而 openDetail() 只给它
   设了 opacity:0 就留在原地。问题是 **opacity 不影响命中测试**：
   那张卡片于是变成一块盖在屏幕正中的隐形遮罩（实测 358×301，
   在 1440×900 下吃掉 16/104 个采样点），z-index 还高于 .detail-overlay 的 2000。
   症状 = 详情页打开后鼠标移到屏幕中间变手型，点什么都没反应
   —— 视频播放键点不中的真正原因就是这个，不是按钮太小。

   用 CSS 而不是 JS 来关：openDetail 里加 class 是同步的，但 CSS 守卫没有
   时序依赖，不会因为 openDetail 中途抛异常而让隐形遮罩复活。
   特异性 body.detail-open .card-wrapper (0,2,1) 压过 .card-wrapper (0,1,0)
   的 pointer-events:auto；卡片的 inline style 里没有 pointerEvents，不会反压。 */
body.detail-open .card-wrapper {
  pointer-events: none;
}

/* ===== Tilt Container ===== */
/* No perspective/preserve-3d here on purpose: applying `perspective` as a
   CSS *property* on this node while it also carries transform-style:preserve-3d
   makes browsers ignore the perspective, collapsing the child tilt into a flat
   orthographic squash. The 3D depth now comes from the element's OWN
   `perspective(800px)` in the JS transform (matching markview.work). */
.card-tilt-container {
  width: 320px;
  will-change: transform;
}

/* Inner layer that carries the visible card AND the JS-driven 3D tilt.
   It holds the full visual (background / border / radius) so the whole card
   tilts together. Kept separate from .project-card so the entrance scale
   animation never overrides the tilt transform. */
.card-tilt-inner {
  width: 320px;
  display: flex; flex-direction: column;
  background: #f3f4f6;
  border-radius: 12px; overflow: hidden;
  border: 1px solid #e5e7eb;
  transform-style: preserve-3d;
  transition: box-shadow 0.3s;
  will-change: transform;
  /* Faint shadow only for card/background separation (reference has no
     hover shadow — the "floating" drama comes purely from perspective+rotation). */
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}

/* ===== Project Card (layout shell + entrance scale animation) ===== */
.project-card {
  width: 320px;
  display: flex; flex-direction: column;
  cursor: pointer;
}

/* ===== Card Image Area ===== */
.card-image-container {
  width: 100%; height: 200px;
  position: relative; overflow: hidden;
  background: #e5e7eb; flex-shrink: 0;
}
.card-image {
  width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.card-video-overlay {
  position: absolute; inset: 0;
  transition: opacity 0.3s; opacity: 0;
  background: linear-gradient(135deg, rgba(0,0,0,0.2), rgba(0,0,0,0.05));
  pointer-events: none;
}
.card-tilt-container:hover .card-video-overlay {
  opacity: 1;
}

/* ===== 含视频作品的常驻播放角标 ===== */
/* 与 .card-video-overlay 职责分离：蒙层仍只在 hover 出现（保持既有观感不变），
   角标常驻显示，让用户一眼就能看出哪些作品带视频 */
.card-video-badge {
  position: absolute;
  right: 10px; bottom: 10px;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  transition: transform 0.25s ease;
}
.card-video-badge::after {
  content: '';
  width: 0; height: 0;
  margin-left: 2px;             /* 三角形重心偏左，右移一点做视觉居中 */
  border-left: 8px solid #111827;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
}
.card-tilt-container:hover .card-video-badge {
  transform: scale(1.12);
}

/* ===== Card Text Area (always visible, below image) ===== */
.card-text-area {
  width: 100%;
  padding: 12px 14px 14px 14px;
  display: flex; flex-direction: column; gap: 4px;
  flex-shrink: 0;
}

.card-title {
  font-weight: 700;
  font-size: 14px;
  line-height: 1.35;
  color: #111827;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.card-meta {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  color: #737373;
  gap: 10px;
}

.card-company-row {
  display: flex; align-items: center; gap: 5px;
  flex-shrink: 0;
}
.card-company-logo {
  width: 16px; height: 16px; border-radius: 50%;
  object-fit: cover; flex-shrink: 0;
}
.card-company-name {
  font-size: 12px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
  max-width: 90px;
}

.card-client-name {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 140px;
}

.card-date {
  font-size: 12px; margin-left: auto;
  white-space: nowrap;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ===== Bottom Timeline Bar ===== */
.timeline-bar {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 100;
  display: flex; justify-content: center; padding-bottom: 28px;
  background: linear-gradient(transparent, rgba(255,255,255,0.95) 50%);
  user-select: none; -webkit-user-select: none;
}
.timeline-inner { width: 100%; max-width: 768px; padding: 0 32px; }
.timeline-track-wrapper {
  position: relative; height: 44px;
  display: flex; align-items: center; cursor: pointer; width: 100%;
}
.timeline-track {
  position: absolute; left: 0; right: 0; top: 50%;
  height: 4px; margin-top: -2px;
  background: #e5e7eb; border-radius: 2px;
}
.timeline-progress {
  height: 100%; border-radius: 2px;
  background: linear-gradient(90deg, #404040, #737373, #525252);
  width: 0;
}
.timeline-dot {
  position: absolute; top: 50%;
  width: 10px; height: 10px; border-radius: 50%;
  background: #d1d5db; border: 2px solid #fff;
  transform: translate(-50%, -50%); z-index: 5;
  box-shadow: 0 0 0 4px rgba(255,255,255,0.9);
  transition: background 0.3s;
}
.timeline-label {
  position: absolute; top: 50%; transform: translateY(-50%);
  z-index: 10; border-radius: 14px; white-space: nowrap;
  pointer-events: auto; cursor: pointer;
  font-size: 14px; font-weight: 600; padding: 4px 14px;
  letter-spacing: 0.3px;
  transition: background-color 0.2s, border-color 0.2s, box-shadow 0.2s, color 0.2s;
  will-change: left;
}
.timeline-label.active {
  color: #fff; background-color: #171717;
  border: 1.5px solid #171717;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
}
.timeline-label.inactive {
  color: #9ca3af; background-color: #f3f4f6;
  border: 1.5px solid #e5e7eb;
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
.timeline-label:hover { background-color: #d1d5db; }
.timeline-label.active:hover { background-color: #374151; border-color: #374151; }

/* ===== Project Detail Overlay ===== */
.detail-overlay {
  position: fixed; inset: 0; z-index: 2000;
  height: 100vh; height: 100dvh; /* dvh：随地址栏伸缩自动贴合，避免白边 */
  background: rgba(255,255,255,0.6);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  display: flex; justify-content: center; align-items: flex-start;
  /* 顶部留出 ~88px，避开固定导航栏（底边约 80px），桌面端开详情页时标题不再被压 */
  padding: 88px 0 2rem 0;
  overflow-y: auto; overscroll-behavior: contain;
  opacity: 0; pointer-events: none;
  transition: opacity 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.detail-overlay.open { opacity: 1; pointer-events: auto; }

/* Side nav arrows: fixed at viewport center, outside card */
.detail-nav-btn {
  position: fixed; top: 50%; z-index: 2010;
  width: 52px; height: 52px; border-radius: 9999px;
  border: 1px solid #e5e7eb;
  background: rgba(255,255,255,0.9);
  box-shadow: 0 2px 12px rgba(0,0,0,0.1);
  backdrop-filter: blur(12px);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: #374151;
  opacity: 0; transform: translateY(-50%);
  transition: opacity 0.3s 0.2s, background 0.2s, color 0.2s;
}
.detail-overlay.open .detail-nav-btn,
.detail-nav-btn.visible { opacity: 1; }
.detail-nav-btn:hover { background: #e5e7eb; color: #111827; }
.detail-prev-btn { left: 20px; }
.detail-next-btn { right: 20px; }

/* Close button: fixed top-right, outside card */
.detail-close-btn {
  position: fixed; top: 16px; right: 20px; z-index: 9999;
  width: 40px; height: 40px; border-radius: 9999px;
  /* 半透明毛玻璃，与导航栏 nav-glass 同款材质 */
  border: 1px solid rgba(255,255,255,0.3);
  background: rgba(255,255,255,0.55);
  box-shadow: 0 4px 20px rgba(0,0,0,0.10);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: #374151;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s 0.2s, background 0.2s, color 0.2s;
}
.detail-overlay.open .detail-close-btn,
.detail-close-btn.visible { opacity: 1; pointer-events: auto; }
.detail-close-btn:hover { background: rgba(255,255,255,0.75); color: #111827; }

.detail-card {
  width: calc(100% - 2rem); max-width: 920px;
  background: #f3f4f6; border-radius: 10px; overflow: hidden;
  box-shadow: 0 4px 24px rgba(0,0,0,0.12);
  flex-shrink: 0;
}

.detail-scroll {
  overflow-y: visible;
}
.detail-scroll::-webkit-scrollbar { display: none; }

.detail-header {
  padding: 32px 32px 24px 32px;
  opacity: 1;
}
.detail-overlay.open .detail-header { opacity: 1; }

.detail-title { font-size: 20px; font-weight: 700; color: #111827; line-height: 1.3; margin-bottom: 12px; }
.detail-meta-row { display: flex; align-items: center; gap: 16px; }
.detail-company { display: flex; align-items: center; gap: 6px; }
.detail-company .card-company-logo { width: 18px; height: 18px; }
.detail-company .card-company-name { font-size: 14px; }
.detail-client { font-size: 14px; font-weight: 500; color: #374151; }
.detail-date { font-size: 14px; color: #9ca3af; margin-left: auto; }

.detail-images {
  padding: 0;
  display: flex; flex-direction: column; gap: 0;
}
.detail-image-wrapper {
  width: 100%; overflow: hidden;
  background: #e5e7eb;
  position: relative; min-height: 240px;
}
.detail-image-wrapper::before {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(90deg,
    #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%
  );
  background-size: 200% 100%;
  animation: skeletonShimmer 1.5s ease-in-out infinite;
  z-index: 1;
  transition: opacity 0.3s;
}
.detail-image-wrapper.loaded::before {
  opacity: 0; pointer-events: none;
}
@keyframes skeletonShimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.detail-image-wrapper img {
  width: 100%; height: auto; display: block;
  object-fit: cover; position: relative; z-index: 2;
  opacity: 0;
  transition: opacity 0.45s ease;
}
/* 图片加载完成后平滑淡入；骨架屏 (::before) 随 .loaded 同步淡出 */
.detail-image-wrapper.loaded img {
  opacity: 1;
}

/* ===== 详情页视频 ===== */
/* ⚠️ 容器比例只允许在没有封面时保持 16:9；有封面则由 JS 改成封面比例，
   并在用户按下播放的那一刻锁死（见 main.js 的 freezeRatio）。
   踩过的坑：
   ① 播放后按视频真实比例重算容器 → 实测封面 3:2、视频 16:9，容器 614px 骤缩到 518px，
      底部原生控件条向上位移 96px，直接从鼠标底下跑掉，表现就是「播放键很难点到」；
   ② 改用 preload="metadata" 想提前拿真实比例 → WebKit 会把整个 14.8MB 文件拉下来
      （即便服务器正常返回 206），3Mbps 下光打开详情就要 40 秒。
   现在的做法：容器比例取封面（已知、静止状态满幅好看），播放后锁死不再变；
   非 16:9 的视频内容靠 object-fit: contain 在固定容器里 letterbox。
   控件条位置绝对稳定，比画面填满更重要。 */
.detail-video-shell {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;     /* 无封面时的兜底；有封面会被 JS 覆盖 */
  background: #000;
}
.detail-video {
  display: block;
  width: 100%;
  height: 100%;             /* 撑满外壳，比例由外壳决定 */
  object-fit: contain;      /* 比例不符时居中留黑边，绝不裁切也绝不变形 */
  background: #000;
  position: relative;
  z-index: 2;
}

/* 大播放按钮：Safari 原生控件条只有约 28px 高、播放键约 20px 见方，
   热区小到经常点空。96px 圆形按钮把可点面积放大约 14 倍。
   定位用负 margin 而非 translate，避免与 hover 的 scale 打架。 */
.detail-video-bigplay {
  position: absolute;
  left: 50%; top: 50%;
  z-index: 4;
  width: 96px; height: 96px;
  margin: -48px 0 0 -48px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.32);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none;
  transform: scale(0.9);
  transition: opacity 0.22s ease, transform 0.22s ease, background 0.18s ease;
  -webkit-backdrop-filter: blur(2px);    /* Safari 需要 -webkit- 前缀 */
  backdrop-filter: blur(2px);
}
.detail-video-bigplay.is-visible {
  opacity: 1; pointer-events: auto;
  transform: scale(1);
}
.detail-video-bigplay:hover { background: #fff; transform: scale(1.07); }
.detail-video-bigplay:active { transform: scale(0.97); }
.detail-video-bigplay:focus-visible { outline: 3px solid #111827; outline-offset: 3px; }
/* 播放三角：重心偏左，右移一点做视觉居中 */
.detail-video-bigplay::after {
  content: '';
  width: 0; height: 0;
  margin-left: 7px;
  border-left: 27px solid #111827;
  border-top: 17px solid transparent;
  border-bottom: 17px solid transparent;
}

/* 缓冲指示：3Mbps 出向下点击到起播要 1~2 秒，
   期间毫无反馈会被当成「没点中」而反复去点 */
.detail-video-loading {
  position: absolute;
  left: 50%; top: 50%;
  z-index: 3;
  width: 40px; height: 40px;
  margin: -20px 0 0 -20px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.32);
  border-top-color: #fff;
  opacity: 0; pointer-events: none;
  animation: videoSpin 0.8s linear infinite;
  transition: opacity 0.2s ease;
}
.detail-video-loading.is-active { opacity: 1; }
@keyframes videoSpin { to { transform: rotate(360deg); } }

/* ===== Responsive ===== */
.mobile-projects { display: none; }

@media (max-width: 768px) {
  /* 移动端纵向列表需要原生纵向滚动，放开被锁定的 body */
  html, body { overflow-y: auto; overflow-x: hidden; height: auto; }
  .navbar-inner { margin-top: 12px; height: 44px; padding: 4px; gap: 4px; border-radius: 12px; }
  .nav-item { padding: 0 10px; min-width: 50px; }
  .nav-logo-area { padding: 0 10px; width: 50px; }
  .nav-link { font-size: 12px; }
  .nav-menu-btn { display: flex; }
  .filter-panel { position: relative; top: auto; left: auto; padding: 120px 16px 0; z-index: 2; }
  /* 备案号 + Design by 与筛选同一行（在 filter-row 内右侧竖排），随滚动（不再 fixed 冻结） */
  .site-footer {
    position: relative !important; top: auto !important; right: auto !important;
    flex-direction: column; align-items: flex-end; gap: 6px !important;
    line-height: 1.15;
    margin-left: auto;
    z-index: 2;
  }
  /* 移动端专属：白边修复 + 渐变跟随滚动（桌面端用 fixed 铺满顶部、无顶部白段） */
  .ambient-blob {
    position: absolute; top: -20px; left: 0; right: 0; height: 520px;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, transparent 10%, #000 20%, #000 55%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0%, transparent 10%, #000 20%, #000 55%, transparent 100%);
  }
  .nav-glass { background: rgba(255,255,255,0.55); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
  .filter-btn { font-size: 14px; padding: 8px 16px; }
  .filter-toggle-btn { height: 40px; width: 40px; }
  .filter-tag { font-size: 14px; padding: 8px 16px; }
  /* 移动端：隐藏横向场景 + 时间轴，改用参考站式纵向列表 */
  .scene { display: none; }
  .timeline-bar { display: none; }
  .mobile-projects {
    display: block;
    /* 让卡片在 ambient-blob 彩色渐变（z-index 1）之上，避免彩色盖住卡片 */
    position: relative; z-index: 2;
    padding: 10px 16px 10px;
    max-width: 640px;
    margin: 0 auto;
    /* iOS Safari：svh 是地址栏展开时的小视口高度（稳定值），不被地址栏收起/展开或 body overflow 切换影响——避免详情关闭后 dvh 视口状态残留导致底部白边 */
    min-height: 100vh;
    min-height: 100svh;
  }
  .mobile-year-section { margin-bottom: 44px; }
  .mobile-year-title {
    font-size: 36px;
    font-weight: 800;
    letter-spacing: -3px;
    line-height: 1;
    color: rgb(71, 71, 71);
    margin-bottom: 10px;
    user-select: none;
  }
  .mobile-card-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
  }
  .mobile-card {
    display: flex;
    flex-direction: column;
    background: #f3f4f6;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    overflow: hidden;
    cursor: pointer;
  }
  .mobile-card-media {
    width: 100%;
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: #e5e7eb;
  }
  .mobile-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .mobile-card-body {
    padding: 12px 14px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .mobile-card-title {
    font-size: 15px;
    font-weight: 700;
    color: #111827;
    line-height: 1.35;
  }
  .mobile-card-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 12px;
    color: #6b7280;
  }
  .mobile-card-company { font-weight: 600; color: #374151; }
  .mobile-card-date { margin-left: auto; }
  /* 导航栏在详情蒙版上方可见 */
  .navbar { z-index: 2100; }
  /* 移动端禁用导航栏交互动画（hover 展开 / logo 3D 翻转 / 过渡），减少触屏卡顿 */
  .nav-glass, .nav-pill, .nav-label { transition: none !important; }
  .nav-glass:hover { padding: 10px; gap: 10px; }
  .nav-pill:hover { padding: 16px; min-width: 50px; border-radius: 9999px; }
  .navbar.page-loaded .nav-glass { padding: 10px; gap: 10px; }
  .navbar.page-loaded .nav-pill:not(.logo-pill) { padding: 16px; min-width: 50px; border-radius: 9999px; }
  .logo-pill:hover .logo-3d-wrap,
  .nav-glass:hover .logo-3d-wrap,
  .navbar.page-loaded .logo-3d-wrap { animation: none !important; }
  .logo-3d-wrap { transform-style: flat; }
  .logo-pill { perspective: none; }
  .navbar.page-loaded .nav-label { color: #6b7280; }
  .navbar.page-loaded .nav-pill.active .nav-label { color: #111827; }
  /* 移动端详情：浮层回归 fixed 满视口（对齐基础 .detail-overlay），
     并用 100dvh 让浮层高度始终贴合可视区、随地址栏伸缩自动跟随 → 任何状态都无白边；
     body 走 position:fixed 锁滚（JS 里带 html:100vh 补丁）→ 地址栏不再展开。
     不再用流内 relative + scrollTo（那套正是地址栏从收缩态展开的诱因）。
     关闭态透明 + 不可见；开启态半透白 + 模糊，顶部 ambient-blob 渐变透出不会死白。 */
  /* 移动端：回归文档流方案（用户确认无白边的基线）。
     关闭态 absolute 脱离文档流不可见；开启态 relative 进入文档流、随 iOS 地址栏正常伸缩，
     从根消除 fixed+dvh 在 iOS 上产生的上下白边。开启态背景模糊实现遮罩。 */
  #detailOverlay {
    position: absolute; top: 0; left: 0; right: 0;
    min-height: 100vh;
    background: transparent;
    padding: 118px 0 80px 0;
    overflow: visible;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    visibility: hidden;
    pointer-events: none;
  }
  #detailOverlay.open {
    visibility: visible;
    pointer-events: auto;
    background: rgba(255, 255, 255, 0.6);
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  }
  /* 遮罩直接作为 #detailOverlay.open 自身背景（不做独立 ::before 层）：
     关闭详情时连容器一起消失，彻底消除 iOS 残留白层盖住顶部渐变的问题；
     半透白 + 模糊让打开详情时顶部 ambient-blob 渐变透出、不会变死白 */
  #detailCard { position: relative; z-index: 1; }
  .detail-nav-btn { display: none; }
  .detail-card { width: calc(100% - 1rem); }
  .detail-header { padding: 24px 20px 16px 20px; }
  .detail-title { font-size: 17px; }
  .detail-images { padding: 0; gap: 0; }
  /* 横屏图根因修复：全局 min-height:240px 在移动端宽屏图（img 高度 ~162px）场景下
     会让 wrapper 底部留出 ~78px 灰带，多张堆叠时视觉「断开」；
     改成 80px 后：img 高度 ≥80px 时 wrapper 完全由 img 撑开，零留白；
     骨架屏仍可见（仅在图片未加载完成期间，wrapper 高度 = min-height = 80px）。 */
  .detail-image-wrapper { min-height: 80px; }
  /* 手机屏宽 390–430px，96px 按钮占掉近 1/4，缩到 72px 更协调
     （仍远大于原生控件约 20px 的播放键） */
  .detail-video-bigplay { width: 72px; height: 72px; margin: -36px 0 0 -36px; }
  .detail-video-bigplay::after {
    margin-left: 5px;
    border-left: 20px solid #111827;
    border-top: 13px solid transparent;
    border-bottom: 13px solid transparent;
  }
  /* 关闭按钮最高层级（pointer-events 由 visible 控制） */
  .detail-close-btn { z-index: 9999; }
  /* 详情关闭按钮：移到下方水平居中 + 放大；材质改为与导航栏同款半透明毛玻璃 */
  #detailCloseBtn {
    top: auto; bottom: 36px;
    left: 50%; right: auto;
    transform: translateX(-50%);
    width: 52px; height: 52px;
    background: rgba(255,255,255,0.55);
    color: #374151;
    border: 1px solid rgba(255,255,255,0.3);
    box-shadow: 0 4px 20px rgba(0,0,0,0.10);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  }
  /* 关于我/联系方式关闭按钮：位置/材质/尺寸与详情页关闭按钮完全一致（底部居中） */
  #infoCloseBtn {
    top: auto; bottom: 36px;
    left: 50%; right: auto;
    transform: translateX(-50%);
    width: 52px; height: 52px;
    background: rgba(255,255,255,0.55);
    color: #374151;
    border: 1px solid rgba(255,255,255,0.3);
    box-shadow: 0 4px 20px rgba(0,0,0,0.10);
    backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  }
  /* 以下移动端覆盖均加 .info-card-clear 提权，压过更靠后源码顺序的基础规则
     （.info-contact 1028 行 / .contact-fold-head .info-name 1035 行 / .contact-fold-grid 1038 行），
     否则同特异性会被基础规则覆盖，移动端不生效 */
  /* 联系方式移动端：竖排、占满整行，并整体压缩高度，避免被顶部导航栏遮挡 */
  .info-card-clear .info-contact { padding: 16px 14px; gap: 12px; }
  .info-card-clear .contact-fold-head .info-name { font-size: 19px; }
  .info-card-clear .contact-fold-head .info-role { font-size: 12px; margin-top: 3px; }
  .info-card-clear .contact-fold-grid { grid-template-columns: 1fr; gap: 10px; }
  .info-card-clear .contact-fold-card { padding: 3px; }
  .info-card-clear .contact-fold-inner { gap: 8px; padding: 10px; }
  .info-card-clear .contact-fold-icon { width: 44px; height: 44px; font-size: 18px; border-radius: 9px; }
  .info-card-clear .contact-fold-name { font-size: 15px; }
  .info-card-clear .contact-fold-value { font-size: 12px; line-height: 1.4; }

  /* ===== 移动端「关于我」：上下结构（文字上 / 图片+水印下），背景纹理旋转90° ===== */
  /* 弹窗长内容可滚动；关于我才顶部对齐（联系方式保持居中） */
  .detail-overlay.info-overlay { overflow-y: auto; }
  .detail-overlay.info-overlay:has(.info-card-dark) {
    /* 垂直居中：safe 关键字保证卡片比视口高时回退到顶部对齐，
       避免 flex 居中把超长内容顶部裁掉且无法滚动；水平已由基础 justify-content:center 居中 */
    align-items: safe center;
    padding: 104px 1rem 104px;
  }
  /* 联系方式：垂直 safe center（卡片矮时居中、高时回退顶部对齐），
     顶部 padding 96px 给固定导航栏留白，避免被遮挡；
     用 #id:has 提权，压过 #infoOverlay 的 padding:0（移动端白边修复所设） */
  #infoOverlay:has(.info-card-clear) {
    align-items: safe center;
    padding: 136px 1rem 40px;
  }
  /* 移动端 info 弹窗：与详情页一致 —— 浮层 fixed 满视口（基础 .info-overlay 已是）+ 100dvh，
     关闭态透明不可见、开启态浅透白模糊，顶部渐变透出；body fixed 锁滚（JS 带 html:100vh 补丁）
     阻止地址栏展开、浮层满视口消除白边。不再用流内 relative（地址栏展开的温床）。 */
  #infoOverlay {
    position: absolute; top: 0; left: 0; right: 0;
    min-height: 100vh; min-height: 100svh;
    background: transparent;
    padding: 0;
    overflow: visible;
    visibility: hidden; pointer-events: none;
  }
  #infoOverlay.open {
    visibility: visible; pointer-events: auto;
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  }
  /* 卡片建立定位基准，承载旋转后的背景伪元素；关闭桌面横版直铺背景 */
  .detail-card.info-card-dark { position: relative; max-width: 460px; background-image: none; }
  .info-card-dark::before {
    content: "";
    position: absolute;
    inset: -35%;
    /* 同 .info-card-dark：等 .topo-ready 才真正下载（见该文件顶部注释） */
    background-image: var(--topo-bg, none);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    transform: rotate(90deg);
    opacity: 0.9;
    pointer-events: none;
    z-index: 0;
  }
  /* 画布改为纵向正常流，关闭 cqw 改用 px（否则竖屏字号塌缩） */
  .info-card-dark .info-resume {
    position: relative;
    z-index: 1;
    aspect-ratio: auto;
    container-type: normal;
    overflow: visible;
    display: flex;
    flex-direction: column;
    gap: 26px;
    padding: 20px 24px;
  }
  /* 文字信息容器：上方、全宽 */
  .info-card-dark .r-rows {
    position: static; left: auto; top: auto; transform: none;
    width: 100%;
    gap: 16px;
  }
  .info-card-dark .r-row { gap: 4px; }
  .info-card-dark .r-row-label { flex: 0 0 26%; font-size: 8px; line-height: 1.4; }
  .info-card-dark .r-row-value { font-size: 8px; line-height: 1.4; }
  .info-card-dark .r-line-split { gap: 12px; }
  .info-card-dark .r-line-right { font-size: 8px; line-height: 1.4; }
  /* 图片 + 水印：同层左右并排，整体水平居中 */
  .info-card-dark .info-side {
    /* 彻底清掉桌面端 absolute 定位残留，避免 relative 状态下 top/right/transform
       把图片+水印顶上去与技能模组重叠 */
    position: relative;
    top: auto; right: auto; bottom: auto; left: auto;
    transform: none;
    display: flex;
    flex-direction: row;
    align-items: flex-end;
    justify-content: center;
    gap: 12px;
    width: auto; max-width: 100%;
    height: auto;
    align-self: center;
    margin-top: 6px;
  }
  .info-card-dark .r-photo {
    position: relative; left: auto; top: auto;
    width: 92px; height: auto;
    aspect-ratio: 540 / 802;
    flex: 0 0 auto;
  }
  .info-card-dark .r-watermark {
    position: relative; right: auto; bottom: auto; top: auto;
    font-size: 28px; line-height: 1.05; letter-spacing: -0.02em;
    flex: 0 0 auto; text-align: right;
  }
  /* 技能模组：保持 50% 缩小尺寸，左对齐，且整行占满宽度（图标没填满也占满） */
  .info-card-dark .r-skill-modules { width: 100%; justify-content: flex-start; gap: 6px; }
  .info-card-dark .r-skill-module { width: 25px; gap: 3px; }
  .info-card-dark .r-skill-bars { height: 2.5px; gap: 1px; }
}

/* ===== Footer ===== */
.site-footer {
  position: fixed; top: 33px; right: 20px;
  display: flex; flex-direction: column; align-items: flex-end; gap: 2px;
  z-index: 1050;
}
.footer-icp { font-size: 13px; color: #6b7280; pointer-events: auto; cursor: pointer; text-decoration: none; }
.footer-icp:hover { color: #111827; }
.footer-icp-fallback { font-size: 13px; color: #6b7280; text-decoration: none; display: inline-block; padding: 0; }
.footer-icp-fallback:hover { color: #111827; }

/* Card entrance animation (uses @keyframes to avoid JS transform conflict) */
.project-card {
  opacity: 0;
}
.project-card.visible {
  animation: cardEnter 0.9s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

@keyframes cardEnter {
  0%   { opacity: 0; transform: scale(0.8); }
  100% { opacity: 1; transform: scale(1); }
}

/* Timeline entrance */
.timeline-bar {
  opacity: 0;
  transition: opacity 0.7s ease;
}
.timeline-bar.visible {
  opacity: 1;
}
.footer-designer { font-size: 13px; color: #6b7280; }

/* ===== About / Contact Info Modal（横向 1:1 还原 MasterGo 设计）===== */
.info-overlay { align-items: center; padding: 1.5rem 1rem; background: rgba(255, 255, 255, 0.85); height: 100vh; height: 100dvh; }
.info-card {
  max-width: 1120px;
  width: calc(100% - 2rem);
  border-radius: 10px;
  overflow: hidden;
  transform: scale(0.8);
  opacity: 0;
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease;
}
.info-overlay.open .info-card {
  transform: scale(1);
  opacity: 1;
}
/* 地形纹理（topographic.svg）的开关。
   为什么要做成变量：这张图 77.7 KB（gzip 37.8 KB），原本在首屏就被下载，
   但 .info-card-dark 首屏高度是 0（信息卡未展开）、移动端还是 visibility:hidden，
   等于访客看不见时白下 37.8 KB，占移动端首屏 40.5%。
   改成变量后，只有 <html> 拿到 .topo-ready 才会真正发起请求，
   该类由 index.html 底部的一段独立内联脚本在 load + requestIdleCallback 时加上。
   ⚠️ 变量未定义时回退 none（不是空字符串），否则会解析成无效值导致整条声明被丢弃。 */
html.topo-ready { --topo-bg: url("/assets/topographic.svg"); }
.info-card-dark {
  background-color: #292929;
  background-image: var(--topo-bg, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  color: #ffffff;
  font-family: "Noto Sans SC", "Inter", sans-serif;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
}
/* 关于我遮罩保持浅色（rgba(255,255,255,0.85)），与详情页同款；
   白边修复靠移动端 #infoOverlay 的 visibility + 关闭后 repaintAmbient（见下方 media），不改用深色遮罩 */
/* 联系方式弹窗：无深色底卡片、无阴影，浅色玻璃卡片直接浮在遮罩上 */
.info-card-clear {
  background: transparent;
  border-radius: 0;
  overflow: visible;
  box-shadow: none;
  margin-top: -80px;
}

/* 简历横向画布（2880×1840 等比例） */
.info-resume {
  position: relative;
  width: 100%;
  aspect-ratio: 2880 / 1840;
  container-type: inline-size;
  overflow: hidden;
}

/* 关于我卡片：左标签 + 右内容，逐行（top 对齐，单行） */
.r-rows {
  position: absolute;
  left: 4.76%;
  top: 50%;
  transform: translateY(-50%);
  width: 65%;
  display: flex;
  flex-direction: column;
  gap: 40px;
}
.r-row {
  display: flex;
  align-items: flex-start;
}
.r-row-label {
  flex: 0 0 18%;
  color: #ffffff;
  font-weight: 400;
  font-size: 1.25cqw;
  line-height: 2.4cqw;
  white-space: nowrap;
}
.r-row-value {
  flex: 1;
  min-width: 0;
  color: #ffffff;
  font-weight: 700;
  font-size: 1.25cqw;
  line-height: 2.4cqw;
  white-space: normal; /* 允许换行，避免长文本撑爆容器 */
}
.r-row-value .r-line-item { margin: 0; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }

/* 行内左右分布（如工作经历：公司名左、岗位信息右） */
.r-line-split {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 2cqw;
}
.r-line-left {
  flex: 1;
  min-width: 0;
  white-space: normal; /* 公司名较长时自动换行，不挤压右侧岗位 */
  overflow-wrap: anywhere; /* 超长无空格字符串也能折行 */
}
.r-line-right {
  flex: 0 0 auto;
  white-space: nowrap; /* 岗位信息不换行 */
  font-size: 1.25cqw;  /* 与公司名一致 */
  font-weight: 700;    /* 与公司名一致 */
  line-height: 2.4cqw; /* 与公司名一致，保证顶部对齐 */
  text-align: right;
}


/* 右侧水印（层级高于照片，右边缘与照片右边对齐） */
.info-side {
  position: absolute;
  right: 4.76%;
  top: 50%;
  transform: translateY(-50%);
  width: 18.75cqw;
  height: 43.41cqw;
  z-index: 2;
}

.r-watermark {
  position: absolute;
  right: 0;
  top: 0;
  text-align: right;
  font-size: 7cqw;
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.03em;
  color: rgba(255,255,255,0.2);
  pointer-events: none;
  z-index: 3;
}

/* 右侧照片（portrait 540×802，位置 left 2203/2880, top 773/1840） */
.r-photo {
  position: absolute;
  left: 0;
  top: 15.56cqw;
  width: 18.75cqw;
  aspect-ratio: 540 / 802;
  border-radius: 4px;
  overflow: hidden;
  background: #2e2e2e;
  z-index: 2;
}
.r-photo img { width: 100%; height: 100%; object-fit: contain; object-position: center; display: block; }

/* 技能模组：图标 + 下方四格熟练度条 */
.r-skill-modules {
  display: flex;
  flex-wrap: wrap;
  gap: 1.8cqw;
  align-self: flex-start;
  z-index: 4;
}
.r-skill-module {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85cqw;
  width: 4.2cqw;
}
.r-skill-icon {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 18%;
  overflow: hidden;
  background: #2a2a2a;
}
.r-skill-icon img { width: 100%; height: 100%; object-fit: contain; display: block; }
.r-skill-bars {
  display: flex;
  width: 100%;
  height: 0.65cqw;
  gap: 1.5px;
}
.r-skill-bar {
  flex: 1;
  background: rgba(255,255,255,var(--bar-opacity, 0.35));
  transition: background 0.2s;
}
.r-skill-bar:first-child { border-radius: 99px 0 0 99px; }
.r-skill-bar:last-child  { border-radius: 0 99px 99px 0; }
.r-skill-bar.active { background: rgba(255,255,255,1); }

.r-photo-placeholder {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: #4a4a4a; color: #888;
  font-size: 12px; letter-spacing: 0.1em;
}

/* ===== 联系方式「折页」卡片（完全对齐 markview.work/contact 浅色玻璃风格） ===== */
.info-contact {
  padding: 48px 56px;
  display: flex;
  flex-direction: column;
  gap: 28px;
}
/* 姓名/职位：去掉深色底卡片后，改用深色文字浮在浅色遮罩上 */
.contact-fold-head { text-align: center; }
.contact-fold-head .info-name { font-size: 30px; font-weight: 700; color: #111827; line-height: 1.2; }
.contact-fold-head .info-role { font-size: 15px; color: #6b7280; margin-top: 6px; }

.contact-fold-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  width: 100%;
}

/* 外层：浅灰毛玻璃容器（bg-gray-100/50 + rounded-4xl + backdrop-blur-md） */
.contact-fold-card {
  display: block;
  padding: 8px;
  border-radius: 32px;
  background: rgba(243, 244, 246, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  text-decoration: none;
  transition: transform 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}
.contact-fold-card:hover {
  transform: scale(1.05);
  background: rgba(243, 244, 246, 0.75);
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
}

/* 内层：白灰虚线边框卡片（border-gray-200 dashed + rounded-3xl） */
.contact-fold-inner {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
  border: none;
  border-radius: 24px;
  height: 100%;
  box-sizing: border-box;
}

.contact-fold-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

/* 图标区：64px 圆角浅灰底（w-16 h-16 rounded-xl） */
.contact-fold-icon {
  width: 64px;
  height: 64px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #e5e7eb;
  font-size: 26px;
  font-weight: 700;
  color: #4b5563;
  flex-shrink: 0;
  overflow: hidden;
}
.contact-fold-icon img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* 蓝色渐变胶囊按钮（from-blue-200 to-blue-500） */
.contact-fold-btn {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 9999px;
  background: linear-gradient(to top, #bfdbfe, #3b82f6);
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  transition: filter 0.2s ease, transform 0.2s ease;
}
.contact-fold-card:hover .contact-fold-btn { filter: brightness(1.05); transform: translateY(-1px); }

/* 文字：深色标题 + 灰值（text-xl / text-gray-500） */
.contact-fold-name {
  font-size: 20px;
  font-weight: 600;
  color: #111827;
}
.contact-fold-value {
  font-size: 14px;
  color: #6b7280;
  word-break: break-all;
}

/* 微信/复制卡片（div，非链接）：可点击 */
.contact-fold-wechat { cursor: pointer; }
.contact-fold-copy { cursor: pointer; }
.contact-fold-btn.copied { background: linear-gradient(to top, #22c55e, #4ade80); }

.info-empty { color: #777; font-size: 14px; }

/* Toast 提示 */
.toast {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) scale(0.96);
  z-index: 4000;
  background: #111827;
  color: #fff;
  padding: 12px 24px;
  border-radius: 14px;
  font-size: 15px;
  font-weight: 500;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease, transform 0.22s ease;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  will-change: transform, opacity;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.toast.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.toast.error { background: #dc2626; }

/* 微信二维码弹窗 */
.wechat-qr-overlay {
  position: fixed;
  inset: 0;
  /* 必须高于移动端 #infoCloseBtn 的 9999（.detail-close-btn），
     否则微信弹窗打开时底层联系方式关闭按钮会漏在最上层、
     点下方反而关掉联系方式页面 */
  z-index: 10000;
  background: rgba(17, 24, 39, 0.5);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.wechat-qr-overlay.hidden { display: none; }
.wechat-qr-card {
  background: #fff;
  border-radius: 20px;
  padding: 24px;
  width: min(360px, 100%);
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.wechat-qr-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.wechat-qr-header h3 {
  font-size: 18px;
  font-weight: 700;
  color: #111827;
}
.wechat-qr-close {
  width: 32px;
  height: 32px;
  border: none;
  background: #f3f4f6;
  border-radius: 50%;
  font-size: 20px;
  line-height: 1;
  color: #6b7280;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.wechat-qr-close:hover { background: #e5e7eb; }
.wechat-qr-body img {
  width: 100%;
  max-width: 280px;
  height: auto;
  display: block;
  margin: 0 auto;
  border-radius: 8px;
}
.wechat-qr-tip {
  margin-top: 16px;
  font-size: 13px;
  color: #6b7280;
}

/* ============================================================
   作品图片加载：骨架占位（微光）→ blur-up 虚化淡入
   容器底层铺骨架，图片未加载时 opacity:0 露出骨架；
   加载完成后虚化淡入并盖住骨架。移动端样式单独包在 media query 内，
   严格 mobile-only，不触碰桌面布局。
   ============================================================ */
@keyframes card-shimmer {
  0%   { background-position: 100% 0; }
  100% { background-position: 0 0; }
}

/* ---- 桌面端 ---- */
.card-image-container { isolation: isolate; }
.card-image-container::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(90deg, #e5e7eb 25%, #eef0f2 37%, #e5e7eb 63%);
  background-size: 400% 100%;
  animation: card-shimmer 1.8s ease-in-out infinite;
  pointer-events: none;
}
.card-image {
  position: relative;
  z-index: 1;
  opacity: 0;
  filter: blur(16px);
  transform: scale(1.05);   /* 轻微放大，裁掉模糊产生的羽化白边 */
  transition: opacity .6s ease, filter .6s ease, transform .6s ease;
}
.card-image.is-loaded {
  opacity: 1;
  filter: blur(0);
  transform: scale(1);
}
.card-image.is-error {
  opacity: 0;
  filter: none;
  transform: none;
}
/* 加载完成后停掉骨架动画，避免上百张卡片的微光动画空耗 GPU */
.card-image-container:has(.card-image.is-loaded)::before {
  animation: none;
  opacity: 0;
}
/* 加载失败：停动画但保留静态灰底，作为失败提示 */
.card-image-container:has(.card-image.is-error)::before {
  animation: none;
}

/* ---- 移动端（独立 media query，不影响桌面） ---- */
@media (max-width: 768px) {
  .mobile-card-media {
    position: relative;
    isolation: isolate;
  }
  .mobile-card-media::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: linear-gradient(90deg, #e5e7eb 25%, #eef0f2 37%, #e5e7eb 63%);
    background-size: 400% 100%;
    animation: card-shimmer 1.8s ease-in-out infinite;
    pointer-events: none;
  }
  .mobile-card-media img {
    position: relative;
    z-index: 1;
    opacity: 0;
    filter: blur(16px);
    transform: scale(1.05);
    transition: opacity .6s ease, filter .6s ease, transform .6s ease;
  }
  .mobile-card-media img.is-loaded {
    opacity: 1;
    filter: blur(0);
    transform: scale(1);
  }
  /* 含视频作品的常驻播放角标（与桌面端 .card-video-badge 同款，尺寸一致） */
  .mobile-card-video-badge {
    position: absolute;
    right: 10px; bottom: 10px;
    z-index: 2;                  /* 盖住骨架屏(0)与图片(1) */
    width: 26px; height: 26px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
    display: flex; align-items: center; justify-content: center;
  }
  .mobile-card-video-badge::after {
    content: '';
    width: 0; height: 0;
    margin-left: 2px;
    border-left: 8px solid #111827;
    border-top: 5px solid transparent;
    border-bottom: 5px solid transparent;
  }
  .mobile-card-media img.is-error {
    opacity: 0;
    filter: none;
    transform: none;
  }
  /* 同上：加载完成后停掉骨架动画 */
  .mobile-card-media:has(img.is-loaded)::before {
    animation: none;
    opacity: 0;
  }
  .mobile-card-media:has(img.is-error)::before {
    animation: none;
  }
}

/* 尊重系统「减弱动态效果」设置 */
@media (prefers-reduced-motion: reduce) {
  .card-image-container::before,
  .mobile-card-media::before { animation: none; }
  .card-image,
  .mobile-card-media img { transition-duration: .01ms; }
}
