/* ============================================================
   QKIE — 进场 Logo 动画:一笔一划写出,再收进导航栏
   ------------------------------------------------------------
   三件事按顺序发生:
     1. 拿一组 SVG 笔画当遮罩,沿 logo 中轴线一根根画出 logo(被扫过处才露出
        底下的 logo.svg,所以中间是手写过程、收笔是完整图形);
     2. 底图是矢量 —— 描摹自 logo.png 的 assets/logo.svg,与原图只差 5 个像素。
        所以放到任何尺寸、任何 DPI 下都清晰,不存在位图被拉伸的问题;
     3. 大 logo 一边缩小一边飞到左上角,落在导航栏 logo 的位置上,同时深色底
        淡出露出页面 —— 换手那一刻两者位置尺寸完全重合,看不出来。

   落点是运行时量的:导航 logo 的位置和大小随视口变,写不进 CSS。js/intro.js
   量完把位移与缩放假写进 --qk-fly-x / --qk-fly-y / --qk-fly-scale,动画照读。
   下面给了这三个变量的默认值,量不到时退化成"原地淡出"而不是不动。

   笔画长度不一(圆环 vs 短点),用 pathLength="1" 把每条笔画都归一化成
   单位长度,于是所有笔画共用同一套 stroke-dasharray/dashoffset 动画,
   只靠 animation-delay 排队。

   时间轴:14 笔 × 间隔 140ms + 每笔 320ms → 落笔完毕 2140ms,
   高亮在收笔前后点亮托住定格 → 2290ms 起开始飞,
   飞行 2140ms 到 4430ms 落位(此刻换成导航栏 logo),
   底色用线性淡出 2540ms(比飞行长),到 4830ms 才完全亮完 → 撤遮罩。整条 4.83s。
   飞行刻意做成和"书写那一段"等长(都是 2140ms),两段节奏一致;曲线也换成
   更均匀的 S 形 —— 之前两头太缓,长时间里前半段几乎不动,看着像卡住。
   飞行的最后 16% 位移已经走完、只缩尺寸,让"落位"这一步本身也有动画可看。

   结构、样式、脚本文档三处改动互相咬合,改一处请一起看:
   · 各 .html 里的 .qk-intro 片段(带坐标系数字)与 head 里的跳过判定
   · 本文件
   · js/intro.js(量落点、换手、收尾)
   ============================================================ */

.qk-intro {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  overflow: hidden;
  /* 盖住整屏且可点击(点一下跳过),别让手指滑动时把下面页面滚了 */
  touch-action: none;
  cursor: default;
  /* 落点由 js/intro.js 写入;默认值让"量不到"时退化成原地淡出 */
  --qk-fly-x: 0px;
  --qk-fly-y: 0px;
  --qk-fly-scale: 1;
  animation: qkIntroDone 1ms linear 4830ms forwards;
}

/* head 里的内联脚本判定本次会话已播过 / 用户要求减少动态效果时挂上 */
html.intro-skip .qk-intro {
  display: none;
}

/* 进场期间先把导航栏那个 logo 藏起来,等大 logo 收进去的一刻再露出来。
   顺带把它的橙色投影也摘掉:飞行的 logo 没有投影,不摘的话换手那一瞬
   会凭空多出一圈光晕。摘掉后 .logo-img 自带的 filter 过渡会在换手后
   用 300ms 把它淡回来,等于一次自然的呼吸。
   下面这条 animation 是保险:万一 js/intro.js 没跑起来,4430ms(落位时刻)后
   它也会自己出现,不至于让导航栏空着 */
html.intro-play .site-header .logo-img {
  opacity: 0;
  filter: none;
  animation: qkHeaderIn 1ms linear 4430ms forwards;
}

/* 点击跳过:不重排时间线,直接把整块淡掉,JS 随后摘除 */
.qk-intro.is-skipped {
  animation: none;
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease-out;
}

/* ---------- 遮罩底色 ----------
   单独一层,好让它和 logo 分开退场。淡出故意比飞行长(2290→4830,飞行 4430
   就落位了),而且用线性 —— 用缓动曲线的话到落位时只剩几个百分点没亮完,
   "落位之后再亮完"这一下就看不出来了;线性能保证落位那一刻还剩约一成半,
   最后这一成半是落位后收的。
   底色必须亮完才撤遮罩(qkIntroDone 也是 4830),否则最后那点亮度会"跳"一下 */
.qk-intro__backdrop {
  position: absolute;
  inset: 0;
  background: var(--bg, #07070f);
  animation: qkFadeOut 2540ms linear 2290ms forwards;
}

/* ---------- 背后的一点呼吸:橙蓝双色辉光 ---------- */
.qk-intro__glow {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(120vw, 900px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    rgba(255, 138, 31, 0.18) 0%,
    rgba(43, 166, 255, 0.08) 40%,
    transparent 66%
  );
  opacity: 0;
  animation: qkGlow 1000ms cubic-bezier(0.22, 0.61, 0.2, 1) 40ms forwards,
    qkFadeOut 2540ms linear 2290ms forwards;
}

/* ---------- logo 舞台 ----------
   三条动画各管各的属性,互不打架:
     qkMarkIn  出场淡入(opacity)
     qkBloom   高亮(橙+蓝双层辉光 + 轻微提亮,filter)
     qkFly     落位(transform) */
.qk-intro__mark {
  position: relative;
  width: min(74vw, 430px);
  /* 与 assets/logo.png 同比例,和 SVG 的 viewBox 一致 ——
     也正因为同比例,飞过去只需要一个等比 scale */
  aspect-ratio: 843 / 438;
  animation: qkMarkIn 220ms ease-out 60ms forwards,
    qkBloom 3230ms ease-in-out 1200ms forwards,
    qkFly 2140ms cubic-bezier(0.4, 0.2, 0.3, 1) 2290ms forwards;
}

.qk-intro__logo {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------- 笔尖 ----------
   每条笔画先整条藏起来(dashoffset 从 1 退回 0 = 从起点画到终点)。
   圆头笔尖让推进的那一端是个圆点,像笔尖而不是刀口。 */
.qk-intro__nib > * {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: qkDraw 320ms linear forwards;
}

/* 遮罩按亮度取可见度:白=露出,黑=遮住。这个属性必须显式写死 ——
   万一被当成 alpha 遮罩,底下那块黑 rect 反而会整片露出 logo */
#qkDraw {
  mask-type: luminance;
}

/* 顺序即落笔顺序:先 Q 再 k、i、e,最后补上三道信号弧 */
.qk-intro__nib > *:nth-child(1)  { animation-delay: 0ms; }
.qk-intro__nib > *:nth-child(2)  { animation-delay: 140ms; }
.qk-intro__nib > *:nth-child(3)  { animation-delay: 280ms; }
.qk-intro__nib > *:nth-child(4)  { animation-delay: 420ms; }
.qk-intro__nib > *:nth-child(5)  { animation-delay: 560ms; }
.qk-intro__nib > *:nth-child(6)  { animation-delay: 700ms; }
.qk-intro__nib > *:nth-child(7)  { animation-delay: 840ms; }
.qk-intro__nib > *:nth-child(8)  { animation-delay: 980ms; }
.qk-intro__nib > *:nth-child(9)  { animation-delay: 1120ms; }
.qk-intro__nib > *:nth-child(10) { animation-delay: 1260ms; }
.qk-intro__nib > *:nth-child(11) { animation-delay: 1400ms; }
.qk-intro__nib > *:nth-child(12) { animation-delay: 1540ms; }
.qk-intro__nib > *:nth-child(13) { animation-delay: 1680ms; }
.qk-intro__nib > *:nth-child(14) { animation-delay: 1820ms; }

/* ---------- 时间线 ---------- */

@keyframes qkDraw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes qkGlow {
  from {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.7);
  }
  to {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
}

@keyframes qkMarkIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 高亮:落笔快收尾时点亮,托住那个定格,起飞后收掉 ——
   落位那一刻它是 0,才不会和导航 logo 那层淡投影撞在一起。
   辉光用橙(近)加蓝(远)两层,呼应 logo 上的蓝弧;再轻微提亮让橙色更跳 */
@keyframes qkBloom {
  0% {
    filter: none;
  }
  29% {
    filter: drop-shadow(0 0 14px rgba(255, 138, 31, 0.5))
      drop-shadow(0 0 38px rgba(43, 166, 255, 0.28)) brightness(1.06);
  }
  40% {
    filter: drop-shadow(0 0 14px rgba(255, 138, 31, 0.5))
      drop-shadow(0 0 38px rgba(43, 166, 255, 0.28)) brightness(1.06);
  }
  100% {
    filter: none;
  }
}

/* 落位:先整体平移到导航 logo 的中心,再等比缩到它的大小。
   transform-origin 默认在中心,所以"移到中心 + 原地缩放"就够,不用拆算两角。

   中间那个 84% 是关键帧里的关键帧:位移到 84% 处就完全走完,但此刻尺寸
   还比目标大一半 —— 最后 16%(约 340ms)是**停在导航 logo 的位置上把尺寸
   慢慢收干净**。不这么拆的话位移和缩小同时结束,等走拢了尺寸也早到位了,
   落位这一下就没有"逐渐缩小"可看。
   84% 上另配了缓动:关键帧里的 animation-timing-function 管的是它到下一个
   关键帧那一段,也就是这段收尾用哪条曲线。 */
@keyframes qkFly {
  0% {
    transform: translate(0, 0) scale(1);
  }
  84% {
    transform: translate(var(--qk-fly-x), var(--qk-fly-y))
      scale(calc(var(--qk-fly-scale) * 1.5));
    animation-timing-function: cubic-bezier(0.33, 0, 0.3, 1);
  }
  100% {
    transform: translate(var(--qk-fly-x), var(--qk-fly-y)) scale(var(--qk-fly-scale));
  }
}

@keyframes qkFadeOut {
  to {
    opacity: 0;
  }
}

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

/* 收尾只挂一个瞬时动画:它到点触发 animationend,js 接过手去换手 + 摘遮罩 */
@keyframes qkIntroDone {
  to {
    pointer-events: none;
  }
}

/* ---------- 窄屏:整体缩小一点,别顶到边 ---------- */
@media (max-width: 600px) {
  .qk-intro__mark {
    width: min(78vw, 340px);
  }
}
