/* ============================================================
   Verso · PC 启动序列（圆形遮罩揭示 + 书块依次上浮）
   ------------------------------------------------------------
   设计意图：启动不是「等待」，而是「开卷」。
   舞台取中性偏暖的深一档（#ECE9E4 一带），内容层是应用的纯白 #FFFFFF ——
   遮罩扩散时两级形成清晰的圆形边界，色相同族，所以「揭开」读起来是
   一次纸面展开，而不是一次转场。

   ── 为什么放在 HTML 层（而非 src/index.css）
   Vite 注入的 CSS 要等 JS 模块加载完才生效，首帧会闪一下应用原貌。
   本文件由 index.html 直接 <link>，是渲染阻塞资源，首帧即舞台底色 + 遮罩收拢，
   物理上不存在白屏窗口。

   ── 编舞（时间轴常量唯一来源在 src/lib/launch.ts）
   0        起手停顿（--pc-hold）
   140ms    呼吸式缩放 1 → 1.055 → 1（--pc-breathe，600ms）
   740ms↑   等首页内容就绪（上限 2400ms，避免揭开一片骨架）
   就绪     圆形遮罩以 Logo 圆心扩散铺满（--pc-mask，750ms，先慢后快）
            + Logo 放大溶解（--pc-logo-out，480ms）
   遮罩毕   书块按左→右 / 上→下依次上浮 + 淡入（间隔 60ms）

   ⚠️ 书块上浮已抽成全站统一能力（src/ui/rise.ts，样式在 src/index.css）——
   书库 / 私密书架、PC / 移动端、首载 / 返回，共用同一套「首次进入视口即上浮」。
   本文件的遮罩与 Logo 只负责把它「揭开」：launch.ts 起跑前挂起、遮罩起跑时放行。

   ⚠️ 判据一致性：下方媒体查询的 (pointer: fine) 是 src/lib/device.ts
   `(pointer: coarse)` 取反的等价形式，**仅为首帧上屏**而在此镜像一份；
   运行时复核仍走 detectTouch()。改动 device.ts 的判据时，这里必须同步。
   ============================================================ */

/* 启动层默认不存在，仅 PC（细指针）启用 */
#pc-launch {
  display: none;
}

/* 时间轴令牌：单位与缓动集中在 :root，数值由 launch.ts 覆写（单一来源） */
:root {
  --pc-hold: 140ms;
  --pc-breathe: 600ms;
  --pc-mask: 750ms;
  --pc-logo-out: 480ms;
  --pc-ease-mask: cubic-bezier(0.55, 0.02, 0.6, 0.55);
  --pc-ease-dissolve: cubic-bezier(0.66, 0.03, 0.72, 0.36);
  --pc-ease-breathe: cubic-bezier(0.37, 0, 0.63, 1);
}

@media (pointer: fine) {
  /* ── 启动层的三层结构（顺序至关重要，写反则整个遮罩完全不可见）──
       最下  .pc-stage  深一档中性舞台      z-index 0
       中间  #root      内容层，被圆形裁剪  z-index 1
       最上  .pc-logo   放大 Logo，独立溶解 z-index 9998
     ⚠️ 曾经把舞台和 Logo 装进同一个 position:fixed + z-index 的容器里，
        结果容器自成一个层叠上下文，舞台被整体抬到内容层**之上** ——
        无论内容层怎么裁剪，屏幕上永远只有舞台，圆形遮罩从头到尾看不见。
        所以这里 #pc-launch 只做显隐开关，**不定位、不设 z-index**，
        由两个子元素各自 fixed 到不同层级。 */
  #pc-launch {
    display: block;
  }
  /* PC 走新的启动序列，旧的轻量闪屏不再参与 */
  #boot-splash {
    display: none !important;
  }

  /* ── 最下：舞台 ──
     底色比内容层（纯白 #FFFFFF）深一档，且**刻意只在边缘加深、中央保持最亮**。
     ⚠️ 这里不能放「中央白色光晕」。放过的结果是圆心附近被洗成近白，
     与内容层几乎无差，遮罩在「先慢」那一段看不到边缘 —— 观感像卡住。
     现在中央与内容层保持约 10% 的明度台阶，圆边界从半径 0 起就清晰可读。 */
  #pc-launch .pc-stage {
    position: fixed;
    inset: 0;
    z-index: 0;
    /* 中央 #ece9e4 与内容层纯白 #ffffff 相差约 19/22/27（≈10% 明度台阶）——
       圆形边界从半径 0 起即可读；四角再深一档形成晕影，把注意力收在 Logo 上 */
    background: radial-gradient(82% 72% at 50% 45%, #ece9e4 0%, #e3dfd8 55%, #d3cdc3 100%);
  }

  /* ── 中间：内容层 = 圆形遮罩的载体 ──
     #root 恰好等于视口（index.css 里 html/body/#root 均为 height:100%），
     所以圆心 50% 50% 就是视口中心 = 放大 Logo 的圆心，无需任何换算。
     background 取应用画布色纯白 → 圆内揭开后与最终状态零色差。 */
  #root {
    position: relative;
    z-index: 1;
    background: #ffffff;
    clip-path: circle(0px at 50% 50%);
  }
  #root.pc-reveal {
    animation: pcCircleReveal var(--pc-mask) var(--pc-ease-mask) both;
    will-change: clip-path;
  }
  /* 终态把启动期加在内容层上的一切全部归还：裁剪、底色、定位与层叠上下文。
     ⚠️ position/z-index 必须一起还原 —— 留着它们会让 #root 长期处于层叠上下文里，
     可能改变内部浮层（抽屉/弹窗）的合成方式，污染运行中应用的渲染路径。
     还原不会造成跳变：#root 恒等于视口且位于 (0,0)，作为包含块与 static 时完全等价 */
  html.pc-launch-done #root {
    animation: none;
    clip-path: none;
    background: none;
    will-change: auto;
    position: static;
    z-index: auto;
  }
  html.pc-launch-done #pc-launch {
    display: none;
  }

  /* 启动期间内容层不可交互（舞台本身已挡住指针，此处再加一道保险） */
  html.pc-launch-live #root {
    pointer-events: none;
    user-select: none;
  }

  /* ── 最上：Logo 层（必须在内容层之上，Logo 溶解时才不会被遮罩裁掉）── */
  #pc-launch .pc-logo {
    position: fixed;
    inset: 0;
    z-index: 9998;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
  }
  #pc-launch .pc-logo-lockup {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 22px;
  }
  /* 尺寸按「与书架栅格同量级」定：1920 宽下约 138px（≈视口宽 7.2%），
     与一张书封（约 230px）同一量级 —— 更早的 208px 喧宾夺主，
     揭开的书封会被压在 Logo 底下，比例失衡 */
  /* 图记：几何、渐变、圆角全部来自 /logo.svg —— 这里只管尺寸与落位，
     不再重复定义底色（此前这里与侧栏、PWA 图标各写一套，是品牌不一致的来源） */
  #pc-launch .pc-logo-mark {
    display: block;
    width: clamp(100px, 7.2vw, 146px);
    height: clamp(100px, 7.2vw, 146px);
    /* ⚠️ 阴影必须用 drop-shadow：它跟随 <img> 的 alpha 轮廓；
       box-shadow 会按矩形盒投出一圈方角阴影，把圆角印面衬成方块 */
    filter: drop-shadow(0 13px 26px rgba(150, 44, 34, 0.36)) drop-shadow(0 44px 84px rgba(150, 44, 34, 0.28));
  }
  #pc-launch .pc-logo-word {
    font-family: 'Noto Serif SC', 'Songti SC', SimSun, serif;
    font-weight: 600;
    font-size: clamp(21px, 1.55vw, 30px);
    letter-spacing: 0.18em;
    text-indent: 0.18em;
    color: #1c1a14;
  }
  #pc-launch .pc-logo-sub {
    margin-top: -10px;
    font-family: 'Inter Tight', system-ui, sans-serif;
    font-size: clamp(10px, 0.7vw, 12px);
    letter-spacing: 0.44em;
    text-indent: 0.44em;
    color: #8a7c5e;
  }

  /* ── 动画 ── */
  #pc-launch .pc-logo-mark.pc-breathe {
    animation: pcBreathe var(--pc-breathe) var(--pc-ease-breathe) var(--pc-hold) both;
  }
  #pc-launch .pc-logo.pc-logo-out {
    animation: pcLogoOut var(--pc-logo-out) var(--pc-ease-dissolve) 30ms forwards;
  }
}

/* 74vmax 恰好越过「最坏比例（正方形窗口）下的半对角线 70.7vmax」——
   任何 PC 窗口比例都能铺满，又不至于半径远超屏幕导致后半段在画外空跑 */
@keyframes pcCircleReveal {
  from {
    clip-path: circle(0px at 50% 50%);
  }
  to {
    clip-path: circle(74vmax at 50% 50%);
  }
}
@keyframes pcBreathe {
  0% {
    transform: scale(1);
  }
  45% {
    transform: scale(1.055);
  }
  100% {
    transform: scale(1);
  }
}
@keyframes pcLogoOut {
  from {
    opacity: 1;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(1.12);
  }
}

/* ── 无障碍：偏好减弱动效时不做启动动画，直接呈现终态 ── */
@media (prefers-reduced-motion: reduce) {
  #pc-launch {
    display: none !important;
  }
  #boot-splash {
    display: none !important;
  }
  #root {
    clip-path: none !important;
    background: none !important;
  }
}

/* ── 兜底：老旧浏览器不支持圆形裁剪时，内容立即可见，绝不永久锁死 ── */
@supports not (clip-path: circle(0px at 50% 50%)) {
  #root {
    clip-path: none !important;
    background: none !important;
  }
}

/* ── 界面主题：暗色 ──────────────────────────────────────────────────
   data-ui-theme 由 index.html 的首帧引导脚本在样式表之前落好，
   暗色用户刷新时不会先闪一帧亮色启动页。
   ⚠️ 保持亮色那套不变式：**内容层（#root）比舞台亮一档**，圆边界从半径 0 起可读。
   亮色是「白内容 + 灰舞台」，暗色就取「深灰内容 + 近黑舞台」，
   而不是简单把明度反过来（反过来会让内容层比舞台更暗，遮罩边界消失）。 */
@media (pointer: fine) {
  /* :not(.pc-launch-done) 是必须的：本块在文件末尾，与上面的
     `html.pc-launch-done #root { background: none }` 特异度相同，
     不排除终态就会靠源序把它顶掉，让启动期加在内容层上的背景一直留着。 */
  html[data-ui-theme='dark']:not(.pc-launch-done) #root {
    background: #131316;
  }
  html[data-ui-theme='dark'] #pc-launch .pc-stage {
    background: radial-gradient(82% 72% at 50% 45%, #0f0f12 0%, #0a0a0c 55%, #060607 100%);
  }
  html[data-ui-theme='dark'] #pc-launch .pc-logo-word {
    color: #f2f1ef;
  }
  html[data-ui-theme='dark'] #pc-launch .pc-logo-sub {
    color: #85848d;
  }
}
