/* ============================================
   PersonalWeb - Minimal B&W Design System
   Inspira UI inspired, B&W color palette
   ============================================ */

/* ---------- CSS Variables ---------- */
:root {
  color-scheme: dark;
  --bg-primary: #0a0a0a;
  --bg-secondary: #111111;
  --bg-card: #1a1a1a;
  --bg-card-hover: #222222;
  --text-primary: #faf9f5;
  --text-secondary: #b5b5b5;
  --text-muted: #7c7c7c;
  --accent: #ffffff;
  --accent-subtle: rgba(255,255,255,0.08);
  --ember: #d0624e;
  --ember-rgb: 208, 98, 78;
  --ember-soft: rgba(var(--ember-rgb), 0.12);
  --border: rgba(255,255,255,0.08);
  --border-hover: rgba(255,255,255,0.18);
  --font-sans: 'Inter Variable', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'JetBrains Mono Variable', 'JetBrains Mono', 'Fira Code', monospace;
  /* 中文衬线正文使用系统字体，避免 Google Fonts 在弱网或国内网络下
     晚加载后改变换行和页面高度。 */
  --font-serif-cn: 'Songti SC', 'STSong', 'Source Han Serif SC', 'Noto Serif CJK SC', 'SimSun', serif;
  --motion-ease: cubic-bezier(0.16, 1, 0.3, 1);
  --motion-fast: 180ms;
  --motion-base: 360ms;
  --motion-slow: 600ms;
  --transition: var(--motion-base) var(--motion-ease);
  --transition-fast: var(--motion-fast) var(--motion-ease);
}

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

html {
  -webkit-font-smoothing: antialiased;
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-sans);
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  overflow-x: hidden;
}

.site-main {
  width: 100%;
  flex: 1 0 auto;
}

a { color: var(--text-primary); text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--accent); }
img { max-width: 100%; display: block; }
button { font-family: inherit; }

/* ---------- Keyboard skip link ---------- */
.skip-link {
  position: fixed;
  top: 12px;
  left: 16px;
  z-index: 100001;
  padding: 10px 14px;
  border: 1px solid rgba(var(--ember-rgb), 0.62);
  border-radius: 6px;
  background: #111;
  color: var(--text-primary);
  font-size: 0.8rem;
  transform: translateY(-160%);
  transition: transform var(--motion-fast) var(--motion-ease);
}

.skip-link:focus {
  transform: translateY(0);
}

.site-main:focus {
  outline: none;
}

/* ---------- Navigation ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  /* 左侧继续与首页正文对齐，右侧稍收紧，让导航在宽屏上更利落。 */
  padding: 20px clamp(24px, 3vw, 56px) 20px clamp(32px, 5vw, 80px);
  transition: background var(--transition), padding var(--transition), opacity var(--transition), transform var(--transition);
}
.nav.scrolled {
  background: rgba(10,10,10,0.92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  padding: 14px clamp(24px, 3vw, 56px) 14px clamp(32px, 5vw, 80px);
  border-bottom: 1px solid var(--border);
}
.nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.nav-logo {
  --logo-columns: 0fr;
  --logo-opacity: 0;
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  display: inline-flex;
  align-items: baseline;
  flex-shrink: 0;
  white-space: nowrap;
}
/* 按文字真实宽度展开，位移与显隐共用一条时间线；快速移出时可直接反向，避免空等和跳帧。 */
.nav-logo-c,
.nav-logo-r {
  display: inline-block;
}
.nav-logo-expand,
.nav-logo-expand2 {
  display: inline-grid;
  grid-template-columns: var(--logo-columns);
  white-space: nowrap;
  opacity: var(--logo-opacity);
  transition: grid-template-columns var(--transition), opacity var(--transition);
}
.nav-logo-expand > span,
.nav-logo-expand2 > span {
  min-width: 0;
  overflow: hidden;
}
.nav-logo:focus-visible {
  --logo-columns: 1fr;
  --logo-opacity: 1;
}
/* 触屏点击只负责回首页，不留下黏住的悬停展开态。 */
@media (hover: hover) and (pointer: fine) {
  .nav-logo:hover {
    --logo-columns: 1fr;
    --logo-opacity: 1;
  }
}

.nav-links { display: flex; gap: 32px; }
.nav-link {
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-secondary);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  position: relative;
}
.nav-link::after {
  content: '';
  position: absolute;
  bottom: -4px; left: 0;
  width: 0; height: 1px;
  background: var(--ember);
  transition: width var(--transition);
}
.nav-link:hover { color: var(--text-primary); }
.nav-link:hover::after { width: 100%; }
.nav-link-active { color: var(--text-primary); }
.nav-link-active::after { width: 100%; }

.nav-mobile-btn {
  display: none;
  background: none;
  border: none;
  width: 28px; height: 20px;
  position: relative;
}
.nav-mobile-btn span {
  display: block;
  width: 100%; height: 1.5px;
  background: var(--text-primary);
  position: absolute;
  left: 0;
  transition: transform var(--transition), background var(--transition);
}
.nav-mobile-btn span:first-child { top: 0; }
.nav-mobile-btn span:last-child { bottom: 0; }
.nav-mobile-btn.active span:first-child { top: 50%; transform: translateY(-50%) rotate(45deg); }
.nav-mobile-btn.active span:last-child { bottom: 50%; transform: translateY(50%) rotate(-45deg); }

/* Search entry — pill button aligned with nav links; ⌘K hint on desktop */
.nav-right { display: flex; align-items: center; gap: 20px; }
@media (max-width: 768px) {
  .nav-links {
    display: flex;
    position: absolute;
    top: 100%; left: 0; right: 0;
    background: rgba(10,10,10,0.97);
    backdrop-filter: blur(12px);
    padding: 24px 40px;
    /* 横屏时菜单必须在视口内独立滚动，最后一项不能落在屏幕外。 */
    max-height: calc(100vh - 64px);
    max-height: calc(100dvh - 64px);
    overflow-y: auto;
    overscroll-behavior-y: contain;
    padding-bottom: max(24px, env(safe-area-inset-bottom));
    gap: 20px;
    border-bottom: 1px solid var(--border);
    flex-direction: column;
    align-items: flex-start;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                visibility 0s linear 0.25s;
  }
  .nav-link {
    width: fit-content;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .nav-links.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                visibility 0s linear 0s;
    z-index: 60;
  }
  .nav-mobile-btn {
    display: block;
    width: 44px;
    height: 44px;
  }
  .nav-mobile-btn span {
    left: 8px;
    width: 28px;
  }
  .nav-mobile-btn span:first-child { top: 12px; }
  .nav-mobile-btn span:last-child { bottom: 12px; }
  .nav { padding: 8px 20px; }
  .nav.scrolled { padding: 6px 20px; }
  .nav-right { gap: 4px; }
  /* 无 JavaScript 或导航脚本失败时，保留一个可横向滚动的静态导航条；
     同时隐藏无法工作的菜单和搜索按钮。 */
  html:not(.js) .nav-links {
    flex-direction: row;
    align-items: center;
    gap: 20px;
    padding: 0 20px;
    min-height: 44px;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    white-space: nowrap;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
    z-index: 60;
    scrollbar-width: none;
  }
  html:not(.js) .nav-links::-webkit-scrollbar { display: none; }
  html:not(.js) .nav-mobile-btn,
  html:not(.js) .quick-search-trigger { display: none; }
}

/* ---------- Hero ---------- */
.hero {
  min-height: 100vh;
  display: flex;
  align-items: center;
  position: relative;
  z-index: 1;
  overflow: hidden;
}

/* 满屏背景图 */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-bg-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 95% center;
}

/* 移动端：背景图居中显示 */
@media (max-width: 768px) {
  .hero-bg-img {
    object-position: 50% center;
  }
}

/* 左侧深色渐变遮罩 — 从左到右逐渐透明 */
.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to right,
    rgba(10, 10, 10, 0.97) 0%,
    rgba(10, 10, 10, 0.94) 25%,
    rgba(10, 10, 10, 0.82) 45%,
    rgba(10, 10, 10, 0.55) 62%,
    rgba(10, 10, 10, 0.25) 78%,
    transparent 100%
  );
}

/* 底部淡化过渡 — Hero 图片自然溶解到下一模块的深色背景 */
.hero::after {
  content: '';
  position: absolute;
  bottom: 0; left: 0; right: 0;
  height: 35%;
  z-index: 1;
  background: linear-gradient(
    to bottom,
    transparent 0%,
    rgba(10, 10, 10, 0.25) 30%,
    rgba(10, 10, 10, 0.65) 60%,
    rgba(10, 10, 10, 0.9) 80%,
    var(--bg-primary) 100%
  );
  pointer-events: none;
}

/* 内容容器 */
.hero-content {
  position: relative;
  z-index: 2;
  width: 100%;
  /* Left-align with nav logo — same horizontal padding */
  padding: 120px clamp(32px, 5vw, 80px) 80px clamp(32px, 5vw, 80px);
}
.hero-text { max-width: 520px; }
.hero-name {
  margin-bottom: 28px;
  white-space: nowrap;
  /* NO animation on container — avoid double opacity compositing */
}
.hero-name-line {
  display: inline-block;
  font-size: clamp(3.5rem, 8vw, 6.5rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: #f5f5f5;
  opacity: 1;
  transform: none;
  transition:
    opacity   1.1s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.1s cubic-bezier(0.22, 1, 0.36, 1);
  /* Force own compositing layer — prevent repaint on every frame */
  z-index: 1;
  position: relative;
}
.js .hero-name-line {
  opacity: 0;
  /* Use translate3d to force GPU compositing only for the animated path. */
  transform: translate3d(0, 18px, 0);
  will-change: transform, opacity;
}
.hero-name-accent { color: var(--text-muted); }
.hero-name-line + .hero-name-line { margin-left: 0.12em; }

.hero-tagline {
  font-size: 1.2rem;
  color: var(--text-secondary);
  margin-bottom: 40px;
  line-height: 1.7;
  max-width: 400px;
}

/* 打字机光标：跟随当前正在输入的行 */
.hero-tagline-line.typing::after {
  content: '|';
  display: inline-block;
  margin-left: 2px;
  animation: cursor-blink 0.85s step-end infinite;
  font-weight: 300;
  color: var(--text-secondary);
}
.hero-tagline-line {
  display: inline;
}
@keyframes cursor-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

/* ---------- Hero Entrance Animation ---------- */
/* Only .hero-name-line animates (opacity + translate3d).
   NO animation on .hero-name container — avoids double compositing. */
.js .hero-text > .hero-tagline,
.js .hero-text > .hero-cta {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition:
    opacity   1.0s cubic-bezier(0.22, 1, 0.36, 1),
    transform 1.0s cubic-bezier(0.22, 1, 0.36, 1);
}
/* .hero-name: static container, no animation at all */
.js .hero-text > .hero-name {
  opacity: 0;
}
/* Fade in container immediately (no transform), then name lines stagger */
.hero-text.hero-loaded > .hero-name    { opacity: 1; }
.hero-text.hero-loaded > .hero-tagline { opacity: 1; transform: translate3d(0, 0, 0); transition-delay: 1.50s; }
.hero-text.hero-loaded > .hero-cta     { opacity: 1; transform: translate3d(0, 0, 0); transition-delay: 2.00s; }
/* 首页 HTML 预置等待标记，确保打字机脚本本身在慢网下也不会先闪出全文；
   开始输入后用活动标记取消通用的 1.5 秒延迟，让首批字符立即淡入。
   禁用 JavaScript 时选择器不生效，完整静态文案仍然可见。 */
.js .hero-text.hero-loaded > .hero-tagline.typewriter-pending {
  opacity: 0;
  transform: translate3d(0, 18px, 0);
  transition-delay: 0s;
}
.js .hero-text.hero-loaded > .hero-tagline.typewriter-active {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition-delay: 0s;
}
/* Name lines: each word fades in on its own compositing layer */
.hero-text.hero-loaded .hero-name-line:nth-child(1) { opacity: 1; transform: translate3d(0, 0, 0); transition-delay: 0.50s; }
.hero-text.hero-loaded .hero-name-line:nth-child(2) { opacity: 1; transform: translate3d(0, 0, 0); transition-delay: 0.90s; }

/* ============================================
   Buttons — Subtle Hint
   ============================================ */

.btn-magnetic {
  display: inline-block;
  transform: translate(var(--mx, 0px), var(--my, 0px));
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform;
}
.btn-magnetic.is-magnetic {
  transition: transform 0.12s cubic-bezier(0.4, 0, 0.2, 1);
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 4px;
  font-size: 0.72rem;
  font-weight: 300;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text-muted);
  background: transparent;
  border: none;
  transition: color 0.4s ease;
  position: relative;
}

/* 底部细线 —— hover 时从中心展开 */
.btn-primary::after {
  content: '';
  position: absolute;
  bottom: 2px; left: 50%;
  width: 0; height: 1px;
  background: var(--text-secondary);
  transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  transform: translateX(-50%);
}
.btn-primary:hover {
  color: var(--text-secondary);
}
.btn-primary:hover::after {
  width: 100%;
}

/* 箭头轻微呼吸弹跳 */
.btn-arrow {
  display: inline-block;
  animation: arrow-breathe 2.4s ease-in-out infinite;
  font-size: 0.95em;
}
@keyframes arrow-breathe {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50%      { transform: translateY(4px); opacity: 1; }
}

@media (max-width: 768px) {
  .hero { padding: 100px 5vw 60px; }
  .hero-content { padding: 80px clamp(16px,3vw,28px) 40px; }
  .hero-text { max-width: 100%; margin: 0 auto; text-align: center; }
  .hero-tagline { margin: 0 auto 32px; }
  /* 移动端：渐变更深，覆盖更多背景图 */
  .hero-overlay {
    background: linear-gradient(
      to right,
      rgba(10, 10, 10, 0.97) 0%,
      rgba(10, 10, 10, 0.92) 50%,
      rgba(10, 10, 10, 0.75) 80%,
      rgba(10, 10, 10, 0.4) 100%
    );
  }
}

/* ---------- Sections ---------- */
.section {
  padding: 120px 40px;
  position: relative;
  z-index: 1;
}
.section-dark { background: var(--bg-secondary); }

/* About Me — soft aurora glow so the near-black section gains depth (Option A).
   Base stays --bg-primary; two faint radial blooms (indigo + violet) lift it
   without breaking the dark, premium tone. No layout/HTML change. */
#about {
  background:
    radial-gradient(64% 54% at 32% 38%, rgba(99, 102, 241, 0.11), transparent 72%),
    radial-gradient(50% 48% at 80% 46%, rgba(139, 92, 246, 0.07), transparent 72%),
    var(--bg-primary);
}

.container { max-width: 1200px; margin: 0 auto; }

.section-header { margin-bottom: 64px; }
.section-number {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-muted);
  letter-spacing: 0.12em;
  display: block;
  margin-bottom: 12px;
}
.section-title {
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #f5f5f5;
}
.section-line {
  width: 40px; height: 1px;
  background: var(--text-muted);
  margin-top: 20px;
}

/* ---------- About ---------- */
.about-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: start;
}
.about-text { max-width: none; }
.about-bio {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--text-primary);
  margin-bottom: 18px;
  letter-spacing: 0.04em;
  font-family: var(--font-mono);
}
.about-tags { display: flex; flex-wrap: wrap; gap: 10px; }
.tag {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  padding: 6px 16px;
  letter-spacing: 0.04em;
  transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.tag:hover {
  border-color: var(--border-hover);
  color: var(--text-primary);
  background: var(--accent-subtle);
}

/* 方案B：About 区职业标签去边框，融入纯文本信息流 */
.about-tags .tag {
  font-size: 0.85rem;
  border: none;
  padding: 0;
  background: none;
}
.about-tags .tag:hover {
  border: none;
  background: none;
  color: var(--text-primary);
}

/* 左侧当前关注 — 方案B：纯文本信息流，无边框无横线 */
.about-focus {
  margin-top: 22px;
  padding-top: 0;
  border-top: none;
  font-size: 0;
}
.about-focus-label {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  text-transform: none;
  display: inline;
}
.about-focus-label::after {
  content: ": ";
}
.about-focus-text {
  display: inline;
  font-size: 0.85rem;
  color: var(--text-secondary);
  line-height: 1.7;
}

/* 右侧经历时间线 — 整体往上移，与左侧 bio 顶部对齐 */
.about-experience { position: relative; margin-top: -18px; }
.timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
  padding-left: 24px;
}
.timeline::before {
  content: '';
  position: absolute;
  left: 3px;
  top: 0;
  bottom: 6px;
  width: 1px;
  background: var(--border);
}
.timeline-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 0 20px 20px;
  position: relative;
  border-bottom: 1px solid var(--border);
}
.timeline-item:last-child { border-bottom: none; }
.timeline-item::before {
  content: '';
  position: absolute;
  left: -24px;
  top: 18px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--text-muted);
  border: 1.5px solid var(--bg-primary);
  z-index: 1;
}
.timeline-item--current::before {
  background: #fff;
  box-shadow: 0 0 0 3px rgba(255,255,255,0.15);
}
.timeline-year {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-muted);
  letter-spacing: 0.10em;
  text-transform: uppercase;
}
.timeline-logo {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: 0.02em;
}
.timeline-role {
  font-size: 0.82rem;
  color: var(--text-secondary);
}

@media (max-width: 768px) {
  .section { padding: 80px 24px; }
  .about-layout {
    grid-template-columns: 1fr;
    gap: 48px;
  }
}

/* ---------- Contact ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-bottom: 48px;
}
.contact-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 28px 24px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  transition: border-color var(--transition), background var(--transition), transform var(--transition);
  cursor: pointer;
  overflow: hidden;
}
.contact-card:hover {
  border-color: var(--border-hover);
  background: var(--bg-card-hover);
  transform: translateY(-2px);
}

/* Subtle "copy" hint — driven by JS (.show reveals, .success turns green)
   so the success confirmation never flips back to the hover hint. */
.copy-hint {
  position: absolute;
  top: 14px;
  right: 14px;
  font-family: var(--font-mono);
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  color: rgba(255,255,255,0.58);
  padding: 3px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.25s ease, transform 0.25s ease, color 0.25s ease, border-color 0.25s ease;
  pointer-events: none;
}
.copy-hint.show {
  opacity: 1;
  transform: translateY(0);
  color: rgba(255,255,255,0.72);
  border-color: var(--border-hover);
}
.copy-hint.success {
  color: rgba(140, 200, 160, 0.85);
  border-color: rgba(140, 200, 160, 0.4);
}

.contact-icon {
  flex-shrink: 0;
  width: 44px; height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.contact-icon svg {
  width: 24px; height: 24px;
  fill: none;
  stroke: var(--text-muted);
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke 0.3s ease, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.contact-card:hover .contact-icon svg { stroke: var(--text-secondary); }
.contact-card:hover .contact-icon--mail svg  { transform: translateY(-2px) rotate(-4deg); }
.contact-card:hover .contact-icon--phone svg { transform: rotate(-12deg); }
.contact-card:hover .contact-icon--pin svg   { transform: translateY(2px); }
.contact-card h3 {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 4px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.contact-card p {
  font-size: 0.9rem;
  color: var(--text-primary);
}

/* contact-card 铅笔手绘背景变体（花 / 叶子 / 藤蔓）。
   800px WebP 足以覆盖卡片的最大显示尺寸，同时避免首页加载三张 1920px JPEG。 */
.contact-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: grayscale(1) contrast(1.05);
  opacity: 0.12;
  pointer-events: none;
  z-index: 0;
  transition: filter 0.45s ease, opacity 0.45s ease;
  /* 右下角水印区域渐隐（135deg 末端落在右下） */
  -webkit-mask-image: linear-gradient(135deg, #000 66%, transparent 100%);
          mask-image: linear-gradient(135deg, #000 66%, transparent 100%);
}
.contact-card > * { position: relative; z-index: 1; }
.contact-card > .copy-hint { position: absolute; }

.contact-card--flower::before { background-image: url("/assets/contact/flower-800.webp"); }
.contact-card--leaf::before   { background-image: url("/assets/contact/leaf-800.webp"); background-position: center 55%; }
.contact-card--vine::before   { background-image: url("/assets/contact/vine-800.webp"); opacity: 0.16; }

/* Hover lights up the pencil sketch without washing out the strokes.
   The sketch is light-gray lines on near-white paper, so a raw brightness()
   boost lifts the lines toward the paper and kills the texture. Instead we
   raise opacity (lines read brighter over the dark card) and contrast (keeps
   the strokes crisp), with only a faint brightness lift for a "wake" feel. */
.contact-card:hover::before {
  filter: grayscale(1) contrast(1.32) brightness(1.05);
  opacity: 0.3;
}

.social-links { display: flex; gap: 16px; flex-wrap: wrap; }
.social-link {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  padding: 10px 24px;
  letter-spacing: 0.04em;
  transition: border-color var(--transition), color var(--transition), background var(--transition);
}
.social-link:hover {
  border-color: var(--border-hover);
  color: var(--text-primary);
  background: var(--accent-subtle);
}

@media (max-width: 768px) {
  .contact-grid { grid-template-columns: 1fr; }
}

/* ---------- Footer ---------- */
.footer {
  padding: 52px 40px;
  border-top: 1px solid var(--border);
  /* Keep the global footer visually identical on pages that use the fixed
     ambient background and on the plain home page. */
  background: var(--bg-primary);
  position: relative;
  z-index: 1;
}
.footer .container {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
}
/* Letter-style signature: an elegant italic serif sign-off above a quiet
   mono caption — reads like the closing line of a personal letter. */
.footer-sign {
  font-family: 'Georgia', 'Times New Roman', 'Songti SC', serif;
  font-style: italic;
  font-size: 1.05rem;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
  transition: color var(--transition);
}
.footer-sign:hover {
  color: var(--text-primary);
}
.footer-sign-sub {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-muted);
  letter-spacing: 0.06em;
}
.footer-sign-sub a {
  color: var(--text-secondary);
  text-decoration: underline;
  text-decoration-color: rgba(181,181,181,0.55);
  text-underline-offset: 3px;
  transition: color var(--transition), text-decoration-color var(--transition);
}
.footer-sign-sub a:hover {
  color: var(--text-primary);
  text-decoration-color: currentColor;
}

@media (max-width: 768px) {
  .footer { padding: 40px 24px; }
}

/* ---------- Scroll Animations ---------- */
/* Premium easing: fast start, slow end — intentional, not bouncy */
.js .animate-on-scroll {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity var(--motion-slow) var(--motion-ease),
    transform var(--motion-slow) var(--motion-ease);
}
.animate-on-scroll.visible {
  opacity: 1;
  transform: translateY(0);
}

/* Stagger children inside .section-header */
.section-header.animate-on-scroll .section-number { transition-delay: 0s; }
.section-header.animate-on-scroll .section-title  { transition-delay: 0.1s; }
.section-header.animate-on-scroll .section-line    { transition-delay: 0.2s; }

/* Children start hidden, reveal when parent gets .visible */
.js .section-header.animate-on-scroll .section-number,
.js .section-header.animate-on-scroll .section-title,
.js .section-header.animate-on-scroll .section-line {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity var(--motion-slow) var(--motion-ease),
    transform var(--motion-slow) var(--motion-ease);
}
.section-header.animate-on-scroll.visible .section-number,
.section-header.animate-on-scroll.visible .section-title,
.section-header.animate-on-scroll.visible .section-line {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- Selection ---------- */
::selection {
  background: rgba(var(--ember-rgb), 0.42);
  color: #fff;
}

/* ---------- Focus Visible (keyboard navigation) ---------- */
:focus-visible {
  outline: 2px solid rgba(var(--ember-rgb), 0.7);
  outline-offset: 2px;
  border-radius: 2px;
}
/* Remove outline for mouse clicks on elements that already have visual feedback */
:focus:not(:focus-visible) { outline: none; }

/* ---------- Reduced Motion (accessibility) ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  body { cursor: auto !important; }
  button, a { cursor: pointer !important; }
  .animate-on-scroll {
    opacity: 1 !important;
    transform: none !important;
  }
  .hero-text > * {
    opacity: 1 !important;
    transform: none !important;
  }
  .hero-name-line {
    opacity: 1 !important;
    transform: none !important;
  }
  .hero-name { white-space: normal; }
}

/* ---------- Back to Top Button (icon only, no container) ---------- */
.back-to-top {
  position: fixed;
  bottom: 26px;
  right: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: transparent;
  border: none;
  color: rgba(255, 255, 255, 0.45);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: color 0.3s ease, opacity 0.35s cubic-bezier(0.16, 1, 0.3, 1), transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: 90;
  pointer-events: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.back-to-top.visible {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
}

.back-to-top:hover,
.back-to-top:focus-visible {
  color: rgba(255, 255, 255, 1);
}

.back-to-top svg {
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

.back-to-top:hover svg {
  transform: translateY(-2px);
}

@media (max-width: 768px) {
  .back-to-top {
    bottom: 18px;
    right: 18px;
  }
}

/* ============================================
   Page Transition Overlay
   ============================================ */
.page-transition-overlay {
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: #0a0a0a;
  pointer-events: none;
  opacity: 0;
}

/* JS adds this class before the first paint. The animation is a safety net:
   even if the main runtime fails, the overlay releases the page by itself. */
.page-transition-overlay--entering {
  opacity: 1;
  pointer-events: auto;
  animation: page-transition-failsafe 0.5s 0.1s forwards;
}

@keyframes page-transition-failsafe {
  0%, 80% { opacity: 1; pointer-events: auto; }
  100% { opacity: 0; pointer-events: none; }
}

@media (prefers-reduced-motion: reduce) {
  .page-transition-overlay--entering {
    animation-duration: 0.01ms;
    animation-delay: 0s;
  }
}

/* ============================================
   Toast — click-to-copy feedback (Contact cards)
   ============================================ */
.ray-toast {
  position: fixed;
  top: 24px;
  left: 50%;
  transform: translate(-50%, -16px);
  padding: 12px 22px;
  font-family: var(--font-sans);
  font-size: 0.85rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.9);
  background: rgba(22, 22, 24, 0.82);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(14px) saturate(180%);
  -webkit-backdrop-filter: blur(14px) saturate(180%);
  z-index: 100000;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.ray-toast::before {
  content: '✓';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  background: rgba(255, 255, 255, 0.14);
  color: #fafafa;
  border-radius: 50%;
  font-size: 0.7rem;
}
.ray-toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}
@media (max-width: 768px) {
  .ray-toast {
    top: 16px;
    padding: 10px 18px;
    font-size: 0.8rem;
  }
}

/* ============================================
   Shared Hero Background Effect (essays & photos reuse this)
   mask 椭圆尺寸由各自页面覆盖（photos 用更宽椭圆）
   ============================================ */
.hero-bg-effect {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  mask-image: radial-gradient(ellipse 2800px 1600px at 50% 50%, white 0%, transparent 99%);
  -webkit-mask-image: radial-gradient(ellipse 2800px 1600px at 50% 50%, white 0%, transparent 99%);
  transition: opacity var(--transition);
}
.hero-bg-effect::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 50% 60% at 50% 50%, rgba(255,255,255,0.03), transparent 70%);
  pointer-events: none;
}
.hero-glow-line {
  position: absolute;
  top: 0;
  height: 1px;
  border-radius: 1px;
  animation: glow-pulse 4s ease-in-out infinite alternate;
}
.hero-glow-line--indigo { left: 20%; width: 55%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.5), transparent); }
.hero-glow-line--indigo-blur { left: 20%; width: 55%; height: 3px; filter: blur(8px); background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); }
.hero-glow-line--sky { left: 55%; width: 30%; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent); }
.hero-glow-line--sky-blur { left: 55%; width: 30%; height: 4px; filter: blur(10px); background: linear-gradient(90deg, transparent, rgba(255,255,255,0.25), transparent); }
.hero-glow-line--indigo-blur, .hero-glow-line--sky-blur { animation-delay: 0.8s; }
@keyframes glow-pulse { 0% { opacity: 0.5; } 100% { opacity: 1; } }
#hero-sparkle-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
