/* ====================
   极简摄影作品集 — 简洁主页版
   ====================
   本文件是站点样式的唯一来源。index.html 内联样式仅保留「首帧防白闪」两行，
   不再重复定义组件样式 —— 此前内联与外链两处都定义了 .about 的
   animation-delay（0.3s / 0.8s），实际以外链为准，属易误判的维护陷阱。
   ==================== */

/* ====================
   Self-hosted Pacifico font
   优先 WOFF2（体积约为 TTF 的 1/8），保留 TTF 作为老浏览器回退
   ==================== */
@font-face {
  font-family: 'Pacifico';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/metro/fonts/Pacifico-v23.woff2') format('woff2'),
       url('/metro/fonts/Pacifico-v23.ttf') format('truetype');
}

:root {
  --color-bg: #1c1c1c;
  --color-text: #ffffff;
  --color-text-light: #cccccc;
  --color-text-muted: #888888;
  --font-display: 'Pacifico', cursive;
  --font-body: 'Pacifico', cursive;
  --transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  /* ⚠️ 翻转动画依赖此变量。历史上漏定义导致 var(--ease) 整条 transition
     失效（未定义变量 = invalid at computed-value time），transform 退化为
     0s 瞬间跳变 —— 表现为「文字变了但没有翻转效果」。任何新增 var() 都要先
     在这里落地，否则 transition/transform 会被静默吞掉。 */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* ====================
   光标策略
   纯文字区域使用默认箭头，不显示 I 型文本光标。
   注意：能否划选文字由 user-select 决定，与 cursor 完全无关 ——
   这里只改光标外观，按住拖动依然可以正常选中文字。
   ==================== */
body {
  cursor: default;
}

/* 链接与可点击元素仍显示手型 */
a,
button,
[role="button"],
summary {
  cursor: pointer;
}

/* 输入类控件保留文本光标 */
input,
textarea,
select {
  cursor: auto;
}

/* 移动端视口高度：dvh 随浏览器地址栏伸缩，避免 100vh 大于可视区域
   导致底部磁贴被裁切或布局抖动；不支持 dvh 时回退到 100%。 */
html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

@supports (height: 100dvh) {
  html, body {
    height: 100dvh;
  }
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

/* ====================
   Metro Background - grid properties set by JS
   ==================== */
.metro-background {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  gap: 0;
  z-index: 0;
  overflow: hidden;
  /* 渐变透明度：左下角 70% → 右上角 100%，使文字区域更通透。
     这是站点唯一的屏级暗化层；左下文字区另用 80% 不透明度的矩形底色。 */
  -webkit-mask-image: linear-gradient(to top right, rgba(0,0,0,0.7), rgba(0,0,0,1));
  mask-image: linear-gradient(to top right, rgba(0,0,0,0.7), rgba(0,0,0,1));
}

/* 加载期间的呼吸提示，磁贴出现后自然被覆盖 */
.metro-background::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: radial-gradient(circle at 50% 50%, #2a2a2a, #1c1c1c);
  animation: loadBreathe 2s ease-in-out infinite;
  z-index: -1;
}

@keyframes loadBreathe {
  0%, 100% { opacity: 0.6; }
  50% { opacity: 1; }
}

.metro-tile {
  position: relative;
  overflow: hidden;
  background: #000000;
  perspective: 800px;
}

.metro-tile-inner {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transform: rotateY(0deg);
}

.metro-tile-inner.is-flipping {
  will-change: transform;
}

.metro-background.has-photos::before {
  animation: none;
  opacity: 0;
}

.metro-tile-front,
.metro-tile-back {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}

.metro-tile-back {
  transform: rotateY(180deg);
}

.metro-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.metro-tile img.loaded {
  opacity: 1;
}

/* 照片清单加载失败时的提示 */
.metro-error {
  position: fixed;
  left: 50%;
  /* 放到顶部而非底部：.home 固定在 bottom:4rem，同位会与卡片重叠。
     顶部是照片马赛克最不敏感的区域（内容本就密），遮住无碍。 */
  top: 1.5rem;
  bottom: auto;
  transform: translateX(-50%);
  z-index: 3;
  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, Georgia, serif;
  font-size: 0.875rem;
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
  pointer-events: none;
  text-align: center;
  padding: 0 1rem;
}

/* ====================
   Home Page
   ==================== */
.home {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  z-index: 2;
  /* 底部留白 + 刘海屏/圆角安全区 */
  padding: 0 0 calc(4rem + env(safe-area-inset-bottom, 0px)) 0;
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}

@keyframes fadeIn {
  to { opacity: 1; }
}

/* ====================
   About Section
   ------------------
   左下角卡片：悬停沿 Y 轴 180° 翻转。
   实现要点（改动前务必知道）：
   1. 正反两面必须用 grid-area:1/1 叠在同一格 —— 若用 position:absolute，
      两面尺寸各自计算，翻转瞬间会出现跳变；用 absolute 时还要让两面
      由同一元素撑开（.about-card 是 grid 容器），否则宽度不一致。
   2. .about 需要 perspective（或 preserve-3d + translateZ）才能产生透视效果，
      否则 rotateY 会被「压扁」成单纯的横向缩放。
   3. .about-bg 在 .about-card 内部（grid 底层，与两面同格叠放），
      随卡片一起翻转 —— 整个矩形框像照片磁贴那样整体翻。
   4. 背面必须显式 rotateY(180deg)，否则两面同向，看到的是镜像文字。
   ==================== */
.about {
  margin-top: 0;
  margin-left: max(1.5rem, 8vw);
  opacity: 0;
  animation: fadeIn 1s ease forwards;
  animation-delay: 0.8s;
  position: relative;
  /* padding 已移入 .about-face：黑底矩形（about-bg）现在是 about-card 的
     grid 底层，随卡片一起翻转，about 自身不再撑 padding。 */
  padding: 0;
  border-radius: 0;
  /* perspective 放在这里给 .about-card 透视。 */
  perspective: 1000px;
}

/* 黑底矩形：about-card 的 grid 底层（DOM 第一个 = 绘制最底），
   与两面同格叠放、随卡片一起翻转 —— 翻转的是整个矩形框，
   和照片磁贴的翻转观感一致。纯色无方向性，镜像无影响。
   透明度 80%（2026-10-11）：opacity 写在矩形自身上，
   正常态 / hover 态 / is-flipped 态自动统一为 80%，无需在各状态里重复换算色值；
   矩形无子元素，不会连带影响文字的不透明度。 */
.about-bg {
  grid-area: 1 / 1;
  background: #1c1c1c;
  opacity: 0.85;
  border-radius: 0;
  pointer-events: none;
  transition: background 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 翻转容器：grid 让两面共享同一格尺寸，避免各自撑开导致宽度跳变 */
.about-card {
  display: grid;
  transform-style: preserve-3d;
  /* 缓动写实值而非 var(--ease)：翻转是本卡片唯一的动画主干，
     不该因为某个变量缺失就整条静默失效（这正是之前没有翻转效果的根因）。 */
  transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
  transform-origin: 50% 50%;
}

/* 翻转触发：桌面用 :hover，触屏用 JS 加的 .is-flipped。
   ⚠️ 触屏必须**排除** :hover 分支。移动浏览器在点按后会把 :hover 粘住
   （实测 matches(':hover') 一直为 true 不消失），于是翻回正面时
   `.about:hover .about-card` 仍在命中，卡片被钉死在 180°，看起来就是
   「文字变了但瞬间跳变、没有翻转动画」。
   做法：把「触屏模式」标记到 <html> 上（JS 用 matchMedia('(hover: hover)')
   判定），CSS 侧用 html.has-touch 把 :hover 规则整体关掉，
   触屏下只剩 .is-flipped 一条路径，翻正翻反都由 JS 显式驱动。 */
html.has-touch .about:hover .about-card {
  transform: none;
}

.about:hover .about-card,
.about.is-flipped .about-card {
  transform: rotateY(180deg);
}

/* 触屏：仅由 .is-flipped 驱动。
   放在 .about:hover 规则**之后**，靠同特异度（0,3,1）+ 后写优先，
   确保触屏下 is-flipped 的两种状态都能盖过上面的 :hover 复位。 */
html.has-touch .about.is-flipped .about-card {
  transform: rotateY(180deg);
}

/* 悬停时底色略透并起内描边，避免纯黑矩形显得死板。
   ⚠️ 触屏 :hover 会粘住（见上方 has-touch 注释），翻回后底色会被钉在
   悬停态，所以触屏下显式排除 hover 分支，只随 .is-flipped 变化。 */
/* 纯色框：任何状态下都只有底色，无描边（用户要求去掉 inset 描边）。
   悬停/翻转态仅底色略深作反馈；触屏 :hover 会粘住（见上方 has-touch 注释），
   仍需排除 hover 分支，避免翻回后底色被钉在悬停态。 */
.about:hover .about-bg,
.about.is-flipped .about-bg {
  background: #161616;
}

html.has-touch .about:hover .about-bg {
  background: #1c1c1c;
}

html.has-touch .about.is-flipped .about-bg {
  background: #161616;
}

/* 两面共用的定位与翻转基础样式 */
.about-face {
  grid-area: 1 / 1;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* 原 .about 的 padding（1.25rem）已并入这里，保持文字与矩形边的间距不变；
     极窄屏下允许换行，避免 contact 文本溢出矩形 */
  padding: 1.25rem 1.5rem;
  min-width: 0;
}

/* 背面默认不接收点击。
   ⚠️ 注意：backface-visibility:hidden 只隐藏渲染，元素依然参与命中测试。
   更关键的是在 3D 变换下，正反两面几何完全重叠，浏览器的命中测试会落到
   背面 <a> 上（实测 pointerdown 命中正面 H1，click 的 target 却变成背面 A）。
   因此这里用 pointer-events 明确关闭背面命中，翻转到位后再放开。 */
.about-back {
  transform: rotateY(180deg);
  pointer-events: none;
}

/* 翻转完成后背面才可点：此时它正处于视觉正面，链接可安全命中。
   .about-flipping 期间（0.82s，与 JS 的 820ms 对齐）继续禁用，防止翻转途中
   落指直接唤起邮件客户端。类名带 about- 前缀，避免与 metro.js 里磁贴翻转
   使用的 .is-flipping 撞名（同名会被磁贴动画结束时一并清掉）。 */
.about:hover .about-back,
.about.is-flipped .about-back {
  pointer-events: auto;
}

.about.is-flipped.about-flipping .about-back,
.about:hover.about-flipping .about-back {
  pointer-events: none;
}

.about-front {
  transform: rotateY(0deg);
}

.about-name {
  font-family: var(--font-display);
  /* Pacifico 仅提供 400 字重，声明 500 会触发浏览器合成加粗（伪粗体） */
  font-weight: 400;
  font-size: 1.75rem;
  margin: 0;
  letter-spacing: -0.02em;
  position: relative;
  z-index: 1;
}

/* 反面：文字行。热区分两块 ——
   「contact」一词与卡片空白 = 翻回区域（无交互样式、无手型）；
   em.about-mail（邮箱地址）= 发信热区，由 JS 判定后主动跳 mailto。
   刻意不用 <a>：3D 变换下命中测试会穿透（pointerdown 命中正面 H1、
   click 的 target 却是背面元素），链接必须由 JS 守门，见 metro.js。 */
.about-contact {
  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, Georgia, 'Times New Roman', serif;
  font-size: 0.9375rem;
  color: var(--color-text);
  text-decoration: none;
  line-height: 1.6;
  /* 邮件地址较长，给一点字间距提升可读性 */
  letter-spacing: 0.01em;
  word-break: break-word;
  cursor: default;
}

/* 邮箱地址 = 发信热区。样式上与 "contact" 一词无差别（同一行、同色），
   交互反馈靠 hover 不透明度与手型光标。 */
.about-mail {
  font-style: normal;
  transition: opacity 0.25s ease;
}

/* 桌面：悬停卡片即处于反面，地址可点 */
html:not(.has-touch) .about:hover .about-mail {
  cursor: pointer;
}

html:not(.has-touch) .about:hover .about-mail:hover {
  opacity: 0.7;
}

/* 触屏：仅当卡片翻到反面且动画结束（about-flipping 已移除）才是可点态 */
html.has-touch .about.is-flipped:not(.about-flipping) .about-mail {
  cursor: pointer;
}

/* 键盘聚焦时给出可见焦点圈（em 不会自动获得链接的默认轮廓） */
.about-mail:focus-visible {
  outline: 1px solid rgba(255, 255, 255, 0.55);
  outline-offset: 4px;
}

/* ====================
   Responsive
   ==================== */
@media (max-width: 1024px) {
  .metro-background { gap: 0; }
}

@media (max-width: 768px) {
  .about-name { font-size: 1.5rem; }
  .metro-background { gap: 0; }
}

@media (max-width: 480px) {
  .about-contact { font-size: 0.875rem; }
  .metro-background { gap: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .metro-background::before,
  .about { animation: none; }
  .about { opacity: 1; }
  .metro-tile img,
  .about-card,
  .about-bg,
  .about-contact { transition: none; }
}
