/* 索引页专属版式。结构参照 augen.pro 实测：5 栏、发丝分隔行、整屏色带、胶囊。 */

/* 顶栏下滑等主视觉那段（模糊转清晰 1.5s）走完再起手，两件事不抢。
   内页没有那一段，用 base.css 里的默认值就行。 */
:root { --nav-drop-delay: 1.5s; }

/* ---- 幕一 · 入口：整屏铺满的主视觉，文字压在左下角 --------------------
   参照 augen 主页：图占满整个首屏（cover，不留边、不留横线），文案叠在左下。
   主体在图的中间七成，所以左右裁掉的只是纸底，看不出裁切。 */
.hero {
  position: relative;
  height: 100svh;
  overflow: clip;
  display: block;
}
.hero__key { position: absolute; inset: 0; margin: 0; }
.hero__key img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  will-change: transform, filter;
}
/* 入场的起始态必须写在 CSS 里，不能只由 heroIntro() 的 fromTo 去设。
   .js 是 nav-enter.js 同步加的（在 <nav> 之后、这张图被解析之前），所以这条
   规则在图第一次上屏之前就生效了。之前没有这条：图按原样一边下载一边从上往下
   画出来，等 index.js 跑到（本地 391ms，慢网络更晚）才被 GSAP 按回
   blur(26px)/opacity .35，看上去就是"图先加载出来、又消失、再模糊到清晰"。
   数值必须和 heroIntro() 的 from 完全一致，否则接手那一帧会跳。 */
.js .hero__key img { opacity: 0.35; filter: blur(26px); transform: scale(1.09); }
/* three 的粒子/路径层：铺在图上面、文字下面，不接指针事件 */
.hero__gl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  pointer-events: none;
}

.hero__copy {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(3rem, 8vh, 6rem);
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  /* 首屏这一组不跟版心走，直接贴左边缘——augen 实测是 68/2000 = 3.4%。
     版心收窄到 960 之后，如果还居中，这一组就飘到画面中间去了。 */
  max-width: none;
  padding-inline: clamp(1.25rem, 3.4vw, 3.5rem);
}
.hero__title { max-width: 24rem; }
.hero__jump {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-sm);
  margin-top: var(--space-xs);
}
.hero__jump .t-cap { margin-right: var(--space-2xs); }

.hero__cue {
  position: absolute;
  /* 文案贴到左边缘之后，这个箭头再放左下就顶到胶囊那一行了，挪到右下角，
     一左一右反而把首屏的底边撑开。 */
  right: clamp(1.25rem, 3.4vw, 3.5rem);
  bottom: clamp(3rem, 8vh, 6rem);
  z-index: 2;
  /* --cue-track 是胶囊的内高（去掉两条发丝），hover 滚动的行程和两份箭头的
     格高都用它，这样箭头正好从胶囊顶走到底，且不会被 1px 边框错开。 */
  --cue-track: calc(3rem - 2 * var(--rule));
  width: 1.375rem;
  /* 立起来的胶囊（augen 的做法）：箭头从上沿滚下来，所以要有一段高度当轨道，
     而且必须 clip，不然会看见箭头在胶囊外面飞。箭头本身在胶囊里居中——
     对着 augen 那张图量过，它的箭头是在竖胶囊的正中间，不是偏下。 */
  height: 3rem;
  overflow: clip;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  /* 这里必须用"比背景暗"的灰，不能用 --veil 那种浅色：箭头落点那块图亮度 232，
     而 --veil 的底色是 #ededea（237），差 5 级——0.3 也好 0.55 也好，实测亮度差
     只有 2.3 级，等于没有。改成极淡的墨灰，量出来差 12 级，和 augen 那张图上
     白底 255 配 #f0f0f0 的观感一档。发丝留一条浅白的，万一压到图里深色的部分
     还能靠边界立住。 */
  background: rgba(20, 22, 26, 0.07);
  border: var(--rule) solid rgba(255, 255, 255, 0.28);
  -webkit-backdrop-filter: var(--blur-veil-sm);
  backdrop-filter: var(--blur-veil-sm);
  /* 箭头比 --text-sm(13) 再小一档：胶囊收到 22×48 之后 13px 的字形在里面显得挤，
     11px 才是"一个小记号"的分量。这里不用令牌，--text-xs(12) 是正文的可读下限，
     而这个箭头不承载阅读。 */
  font-size: 0.6875rem;
}
/* 胶囊本体的入场交给 heroIntro() 那条 [data-hero="move"] 的 tween，和项目胶囊
   完全同参；起始态由 base.css 里 .js [data-hero='move'] 统一给。 */
/* 两条动画叠在一个元素上：cue-in 先跑（both 保留终态），到点之后列在后面的
   cue 接手 transform 和 opacity。排在胶囊本体落位（约 1.9s）之后起手。
   挂在 .cue__clip 上而不是里面的 span：里层的 transform 留给 hover 的滚动，
   两级各管一件事，不会互相覆盖。 */
.hero__cue .cue__clip {
  display: block;
  overflow: hidden;
  /* 撑满胶囊内高，hover 的行程才有整个胶囊那么长（原来只有一行字高 ≈14px） */
  align-self: stretch;
  justify-self: stretch;
  height: var(--cue-track);
  animation: cue-in 0.62s cubic-bezier(0.16, 1, 0.3, 1) 1.95s both,
    cue 2.6s var(--ease-in-out) 2.57s infinite;
}
@keyframes cue-in {
  from { transform: translateY(-1.4rem); opacity: 0; }
  to { transform: translateY(0); opacity: 0.5; }
}
@keyframes cue {
  0%, 100% { transform: translateY(0); opacity: 0.5; }
  50% { transform: translateY(3px); opacity: 1; }
}
/* hover 往下滚一整个胶囊高。两份箭头各占一格 --cue-track，静止时整条上移一格
   （露出下面那份、它在自己那格里居中），滚到 0 就是露出上面那份 —— 所以看到的是
   一个箭头从胶囊底部走出去、另一个从顶部走进来，行程正好是胶囊的高度。
   项目胶囊是 0 → -50% 往上，这里正好反过来。
   同样只滚一次不回滚：动画跑完由 js 摘掉 class，两份箭头一模一样，归零看不出来。 */
.hero__cue .cue__roll {
  display: flex;
  flex-direction: column;
  transform: translateY(calc(-1 * var(--cue-track)));
}
.hero__cue .cue__roll > span {
  display: grid;
  place-items: center;
  height: var(--cue-track);
  line-height: 1;
}
.hero__cue.is-rolling .cue__roll {
  animation: cue-roll 620ms cubic-bezier(0.4, 0, 0.25, 1) both;
}
@keyframes cue-roll {
  from { transform: translateY(calc(-1 * var(--cue-track))); }
  to { transform: translateY(0); }
}

/* 从入口胶囊跳过来时，让目标行亮一下，交代"你到了这里" */
.work__item:target .work__row::before { opacity: 1; }
.work__item:target .work__no { color: var(--accent); }

/* ---- 过场带 · 铰链线框 -------------------------------------------------
   两屏的滚动量换一屏的停留：钉住之后，滚动进度同时驱动三件事——上盖从闭合
   转到 105°、沿途逐档留下残影、右边三句话逐句浮出来。 */
.interlude { height: 260vh; overflow: clip; padding: 0; }
.interlude__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  align-content: center;
}
.interlude__inner {
  display: grid;
  /* 整组内容比视口中心再抬一点：钉住段里图下面留的空比上面多，
     居中反而显得整块坠着。translateY 不动布局，钉住的计算不受影响。 */
  transform: translateY(-4.5vh);
  /* 线框收小、往左靠（负的左边距让它探进页面留白里），
     省下来的宽度全给右边那三句话，行不至于被挤成三四行。 */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.24fr);
  column-gap: var(--space-xl);
  /* 两栏顶对齐只是起点：真正的对齐由 js 的 interludeAlign() 把文字栏整体下移，
     让末行的基线落在图纸最下面那条地线（y=682）的延长线上，两栏下沿齐平。
     纯居中／纯顶对齐都不行——线框的视觉重量全在下半部。 */
  align-items: start;
}
.interlude__fig {
  margin: 0 0 0 calc(var(--margin) * -0.62);
  justify-self: start;
  width: 100%;
}

/* 线框：所有线只描边不填色；non-scaling-stroke 保证缩放后仍是 1px 发丝。
   三档灰度就是这张图的层次——主结构、次结构、构造线。 */
.wf { display: block; width: 100%; height: auto; overflow: visible; }
.wf rect, .wf path, .wf line, .wf circle, .wf use {
  fill: none;
  vector-effect: non-scaling-stroke;
}
.wf__solid { stroke: rgba(242, 242, 244, 0.44); stroke-width: 1; }
.wf__thin { stroke: rgba(242, 242, 244, 0.24); stroke-width: 1; }
.wf__hair { stroke: rgba(242, 242, 244, 0.12); stroke-width: 1; }
.wf__accent { stroke: var(--accent); stroke-width: 1.2; }
.wf__dot { fill: var(--accent); stroke: none; }
/* 残影：默认不出现，进度滚过它那一档才浮出来 */
.wf-ghost { opacity: 0; }
.wf-arrow { opacity: 0; }

/* 三句话同字号、同颜色、同左边缘；层次只靠"逐句由淡到亮"来给 */
.interlude__lines { display: grid; gap: var(--space-xl); }
.interlude__line { opacity: 0; text-align: left; will-change: opacity, transform; }

@media (prefers-reduced-motion: reduce) {
  .interlude { height: auto; }
  .interlude__pin { position: static; height: auto; padding-block: var(--band-pad); }
  .interlude__inner { transform: none; }
  .interlude__line { opacity: 1; }
}

@media (max-width: 767px) {
  .interlude { height: auto; }
  .interlude__pin { position: static; height: auto; padding-block: var(--space-4xl); }
  .interlude__inner { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-2xl); transform: none; }
}

@media (max-width: 767px) {
  .hero { height: 100svh; }
  .hero__copy { bottom: 5.5rem; }
  /* 窄屏上 cover 会把主视觉裁到产品本体，文案正好压在最亮的旋钮上，读不清。
     底部加一层纸色渐隐（只在窄屏），桌面端的构图不受影响。 */
  .hero::after {
    content: '';
    position: absolute;
    inset: auto 0 0 0;
    height: 38%;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(to top, rgba(237, 237, 234, 0.94), rgba(237, 237, 234, 0));
  }
}

/* ---- 幕三 · 作品索引 -------------------------------------------------- */
.work { padding-block: var(--space-3xl) var(--space-4xl); }
.work__title { margin-bottom: var(--space-3xl); }

.work__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
  column-gap: var(--gutter);
  align-items: start;
  padding-block: clamp(1.75rem, 3vw, 2.75rem);
  position: relative;
  transition: color var(--dur-2) var(--ease-out);
}
/* 顶部发丝线做成 ::after，入场时靠 --rule-scale 从左画出来 */
.work__row::after {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: var(--rule);
  background: var(--hair);
  transform: scaleX(var(--rule-scale, 1));
  transform-origin: 0 50%;
}
.work__item:last-child .work__row { border-bottom: var(--rule) solid var(--hair); }

/* 悬停时整行左移一点，并铺一条极淡的底 —— 只用 transform 和背景色 */
.work__row::before {
  content: '';
  position: absolute;
  inset: 0 calc(var(--margin) * -0.5);
  background: rgba(14, 15, 17, 0.03);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
  pointer-events: none;
}
.work__row:hover::before, .work__row:focus-visible::before { opacity: 1; }
.work__row:hover .work__name, .work__row:focus-visible .work__name { color: var(--accent); }

.work__meta { display: flex; flex-direction: column; gap: 0.15rem; }
.work__no { color: var(--accent); }

.work__main { display: flex; flex-direction: column; gap: var(--space-sm); }
.work__name {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  transition: color var(--dur-2) var(--ease-out);
}
.work__desc { color: var(--ink-soft); }

.work__wip {
  font-size: var(--text-xs);
  font-style: normal;              /* 不用斜体 */
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--ink-soft);
  border: var(--rule) solid var(--hair);
  border-radius: var(--radius-pill);
  padding: 0.25em 0.7em;
}
.work__row.is-wip { cursor: default; }
.work__row.is-wip:hover .work__name { color: inherit; }

/* 焦点阶梯：悬停某一行时，其余行按距离递增地虚化和压暗。
   mandandan 用的就是这套渐进模糊（实测有 blur(0.61/0.87/1.02/1.25/1.48/1.69/2.21/2.39px) 的阶梯）。 */
.work__list { transition: none; }
.work__item {
  transition: opacity var(--dur-3) var(--ease-out), filter var(--dur-3) var(--ease-out);
}
.work__list.is-focusing .work__item { opacity: 0.55; }
.work__list.is-focusing .work__item[data-far='1'] { filter: blur(0.7px); opacity: 0.5; }
.work__list.is-focusing .work__item[data-far='2'] { filter: blur(1.3px); opacity: 0.42; }
.work__list.is-focusing .work__item[data-far='3'] { filter: blur(1.9px); opacity: 0.36; }
.work__list.is-focusing .work__item[data-far='4'] { filter: blur(2.4px); opacity: 0.32; }
.work__list.is-focusing .work__item[data-far='0'] { opacity: 1; filter: none; }

/* ---- 幕二 · 关于：深色带做分章 ---------------------------------------- */
.about { padding-block: var(--space-4xl) var(--space-3xl); position: relative; overflow: clip; }

/* 光点层：铺满这一带，压在文字下面，不接指针事件。深色底上光感比首屏强，
   所以点数和不透明度都在 js 里给了更小的一档。 */
.about__gl {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
.about > .page { position: relative; z-index: 1; }


/* 头像：方框（圆角只留 --radius-sm 那一档，和站里其它容器同规格），纸色底 +
   一圈发丝，线稿的黑才立得住；里面是角色全身像（图留了透明底，底色由这里给）。
   圆形那版只用在浏览器标签图标上。全身像比头部特写信息量大，尺寸相应放到
   5.25rem，再小衣领和手臂的线就并成一团了。 */
.about__avatar {
  margin: var(--space-lg) 0 var(--space-lg);
  width: 5.25rem;
  height: 5.25rem;
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--paper);
  box-shadow: 0 0 0 var(--rule) var(--hair-on-ink);
}
.about__avatar img { width: 100%; height: 100%; object-fit: cover; }

/* 这句是招呼语，和下面那句是一体的，颜色跟正文同档（原来压暗一档，太浅了） */
.about__hello { margin: 0 0 var(--space-2xs); color: inherit; }
.about__title { max-width: 34rem; margin: 0 0 var(--space-2xl); }

.about__bio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr));
  gap: var(--space-lg);
  max-width: 64rem;
}
.about__bio .t-body { color: var(--on-ink-soft); max-width: none; }

.about__quote {
  margin: var(--space-3xl) 0;
  padding-left: var(--space-lg);
  border-left: var(--rule) solid var(--accent);
  max-width: 44rem;
}

.about__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
  gap: var(--space-2xl);
}
.about__row { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }
.about__row > span:last-child { display: flex; flex-direction: column; gap: 0.35rem; }
.about__sub { color: var(--on-ink-soft); }

/* 公司 logo：和公司名共用一条基线。
   inline-block 的基线是它的下边缘，所以只有"图片底边正好是字标基线"时才对得齐。
   实测（tools 里量的）：百度的字标基线就在图片最底部（余量 0%），
   而 Lenovo 是带红底的 lockup，字标基线在 68/96 处，下面还有 28.1% 的红底——
   所以它会整体偏高。用 --logo-drop 把这段余量按比例补回去，两张就落在同一条线上。 */
/* 用 flex 而不是行内流：inline-block 的 logo 会把整个行框撑高 5px，
   于是左右两栏的行高差一档、两边的发丝线越往下越对不齐（用户指出的那处）。
   flex 容器的高度只取最高那一项，基线对齐照旧靠 align-items: baseline。 */
.about__org {
  display: flex;
  align-items: baseline;
  gap: var(--space-sm);
  /* 高度锁成一行正文的高度：logo 比这一行略矮，多出来的两像素让它溢出，
     不参与布局。这样有 logo 的那一栏和没有 logo 的那一栏行高完全一致。 */
  height: calc(1em * var(--leading-cn));
}
.about__logo {
  display: inline-block;
  vertical-align: baseline;
  position: relative;
  bottom: calc(var(--logo-h) * var(--logo-drop, 0) * -1);
  height: var(--logo-h);
  width: auto;
  flex: 0 0 auto;
  --logo-h: 1.35rem;
}
.about__logo[data-logo='lenovo'] { --logo-drop: 0.281; }
.about__logo[data-logo='baidu'] { --logo-drop: 0; }

.about__skills { margin-top: var(--space-3xl); }
.about__skills .about__row { grid-template-columns: minmax(0, 1fr) minmax(0, 4fr); }
.about__skillval { color: var(--on-ink-soft); max-width: none; }

/* ---- 幕四 · 联系 ------------------------------------------------------ */
.contact { padding-block: var(--space-4xl); }
.contact__inner { display: flex; flex-direction: column; gap: var(--space-lg); }
/* 四个联系方式一横排，谁都不许换行。用 flex + space-between 而不是等分网格：
   等分列会把 670156618@qq.com 挤到折行，按内容宽排就不会。 */
.contact__list {
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-between;
  gap: var(--space-lg);
  margin-top: var(--space-2xl);
}
.contact__item { flex: 0 0 auto; display: flex; flex-direction: column; gap: var(--space-2xs); }
.contact__val { letter-spacing: 0; white-space: nowrap; }

@media (max-width: 767px) {
  .work__row { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-md); }
  .work__meta { flex-direction: row; gap: var(--space-sm); }
  .about__row { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-2xs); }
  /* 窄屏一横排放不下四个，允许折成两排 */
  .contact__list { flex-wrap: wrap; gap: var(--space-lg) var(--space-xl); }
  .contact__item { flex: 1 1 40%; }
}

