/* ============================================================
   Stating · 高级加载动效层 loading.css（在 style.css / lg.css 之后加载）
   纯新增层，全部使用 lp- 前缀命名空间，不覆盖任何既有类
   包含：① 启动页 Splash ② 顶部进度条 ③ 上传进度卡 ④ 消息发送中微状态

   —— 动效规范落地 ——
   1. 只动画 transform / opacity：所有进度条用 scaleX()，不用 width。
   2. 缓动：进入退出用 --lp-ease-out；屏内移动/形变用 --lp-ease-io；
      hover/颜色用 ease 150ms；匀速循环（流光/扫动）用 linear。
   3. 时长：微交互 150ms / 标准 UI 200ms / 整页级 300ms；
      退出比进入快约 20%；splash 全程 ≤ 1200ms。
   4. 入场初始态用 scale(.95)，不用 scale(0)。
   5. 成对元素（卡片+阴影、进度条+轨道）同 easing 同 duration。
   6. 末尾 prefers-reduced-motion 块：去transform/缩放/位移，保 opacity，
      循环动画用负 animation-delay 停在好看的帧上。
   7. hover 效果一律包在 @media (hover: hover) and (pointer: fine)。
   8. 抖/掉帧风险元素（流光、扫动、光环）加 will-change: transform。
   ============================================================ */

/* ---------- 动效 token ---------- */
:root {
  --lp-accent: #0a84ff;
  --lp-accent-2: #5aa6ff;
  --lp-danger: #ff3b30;
  --lp-ok: #34c759;

  /* 规格约定的 4 条缓动曲线 */
  --lp-ease-out: cubic-bezier(.22, 1, .36, 1);   /* 进入 / 退出 */
  --lp-ease-io: cubic-bezier(.65, 0, .35, 1);     /* 屏内移动 / 形变 */
  --lp-ease: cubic-bezier(.25, .85, .25, 1);      /* 兼容旧引用 */

  /* 时长档位 */
  --lp-d-micro: 150ms;   /* 微交互 */
  --lp-d-ui: 200ms;      /* 标准 UI */
  --lp-d-page: 300ms;    /* 整页级 */
  --lp-d-exit: 240ms;    /* 整页退出（比进入的 300ms 快约 20%） */
  --lp-d-card-exit: 160ms; /* 卡片退出（比进入的 200ms 快约 20%） */

  --lp-bar-h: 3px;
  --lp-ink: #15181f;
  --lp-ink-2: #77808e;
  --lp-surface: rgba(255, 255, 255, .82);
  --lp-edge: rgba(0, 0, 0, .08);
}

body.dark {
  --lp-ink: #f2f5fa;
  --lp-ink-2: #959eac;
  --lp-surface: rgba(24, 27, 36, .84);
  --lp-edge: rgba(255, 255, 255, .12);
}

/* ============================================================
   ① 启动页 Splash（整页级：进入 300ms / 退出 240ms，同 easing）
   ============================================================ */

.lp-splash {
  position: fixed;
  inset: 0;
  z-index: 9998;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: #eef2f9;
  will-change: transform, opacity;
  transition:
    opacity var(--lp-d-exit) var(--lp-ease-out),
    transform var(--lp-d-exit) var(--lp-ease-out),
    visibility 0s linear var(--lp-d-exit);
}

body.dark .lp-splash { background: #0a0a12; }

/* 退出态：淡出 + 轻微放大（只动 transform/opacity） */
.lp-splash.lp-leave {
  opacity: 0;
  transform: scale(1.04);
  pointer-events: none;
}

/* 品牌标记 */
.lp-splash-mark {
  position: relative;
  width: 84px;
  height: 84px;
  display: grid;
  place-items: center;
  border-radius: 26px;
  background: linear-gradient(160deg, var(--lp-accent-2) 0%, var(--lp-accent) 55%, #0a64e8 100%);
  box-shadow: 0 18px 44px rgba(10, 132, 255, .34);
  color: #fff;
  font-size: 38px;
  font-weight: 700;
  letter-spacing: -.5px;
  animation: lp-mark-in var(--lp-d-page) var(--lp-ease-out) both;
}

/* 标记外圈呼吸光环：循环动效用 linear（规格：匀速循环用 linear） */
.lp-splash-mark::after {
  content: "";
  position: absolute;
  inset: -10px;
  border-radius: 34px;
  border: 1.5px solid rgba(10, 132, 255, .3);
  will-change: transform, opacity;
  animation: lp-halo 2.4s linear infinite;
}

/* 入场初始态用 scale(.95)，不用 scale(0)，避免"凭空出现" */
@keyframes lp-mark-in {
  from { opacity: 0; transform: translateY(10px) scale(.95); }
  to   { opacity: 1; transform: none; }
}

@keyframes lp-halo {
  0%   { opacity: .75; transform: scale(.95); }
  70%  { opacity: 0;   transform: scale(1.2); }
  100% { opacity: 0;   transform: scale(1.2); }
}

.lp-splash-title {
  font-size: 21px;
  font-weight: 650;
  letter-spacing: .3px;
  color: var(--lp-ink);
  animation: lp-mark-in var(--lp-d-page) var(--lp-ease-out) 60ms both;
}

.lp-splash-sub {
  font-size: 13px;
  color: var(--lp-ink-2);
  min-height: 18px;
  animation: lp-mark-in var(--lp-d-page) var(--lp-ease-out) 100ms both;
}

/* 进度轨道：真实进度 + 一段匀速流光 */
.lp-splash-track {
  position: relative;
  width: min(240px, 62vw);
  height: 4px;
  border-radius: 999px;
  background: rgba(10, 132, 255, .16);
  overflow: hidden;
  animation: lp-mark-in var(--lp-d-page) var(--lp-ease-out) 140ms both;
}

/* 只动画 transform: scaleX()，不动画 width（GPU 友好，无重排） */
.lp-splash-fill {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--lp-accent-2), var(--lp-accent));
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform var(--lp-d-ui) var(--lp-ease-out);
}

/* 轨道内匀速流光，暗示"仍在工作"（不伪造百分比） */
.lp-splash-track::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 42%;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .62), transparent);
  will-change: transform;
  animation: lp-sheen 1.25s linear infinite;
}

@keyframes lp-sheen {
  from { transform: translateX(-120%); }
  to   { transform: translateX(320%); }
}

.lp-splash-pct {
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--lp-ink-2);
  min-height: 15px;
  animation: lp-mark-in var(--lp-d-page) var(--lp-ease-out) 180ms both;
}

/* ============================================================
   ② 顶部进度条
   ============================================================ */

.lp-topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--lp-bar-h);
  z-index: 9997;
  pointer-events: none;
  opacity: 0;
  /* 顶部可能被状态栏/刘海遮挡，用 env() 兜住 */
  padding-top: env(safe-area-inset-top, 0px);
  box-sizing: content-box;
  will-change: opacity;
  transition: opacity var(--lp-d-micro) ease;
}

.lp-topbar.lp-on { opacity: 1; }

/* 进度填充：整条铺满，用 scaleX 表现进度，避免动画 width */
.lp-topbar-fill {
  height: var(--lp-bar-h);
  width: 100%;
  border-radius: 0 999px 999px 0;
  background: linear-gradient(90deg, var(--lp-accent-2), var(--lp-accent));
  box-shadow: 0 0 12px rgba(10, 132, 255, .5);
  transform-origin: left center;
  transform: scaleX(0);
  will-change: transform;
  /* 进度推进由 JS 的 rAF 平滑驱动（已含缓动），此处不再叠加 transition，
     避免两套缓动互相打架产生延迟感 */
}

/* 不确定态：匀速来回扫动，不伪造百分比 */
.lp-topbar.lp-indeterminate .lp-topbar-fill {
  will-change: transform;
  animation: lp-slide 1.05s linear infinite;
}

@keyframes lp-slide {
  0%   { transform: translateX(-110%) scaleX(.34); }
  100% { transform: translateX(400%) scaleX(.34); }
}

/* 收尾动效（规格 10）：冲到 100% 后绿色一闪 + 淡出，不生硬消失 */
.lp-topbar.lp-flash .lp-topbar-fill {
  animation: lp-bar-flash var(--lp-d-ui) var(--lp-ease-out) both;
}

@keyframes lp-bar-flash {
  0%   { filter: brightness(1); }
  55%  { filter: brightness(1.35); }
  100% { filter: brightness(1); }
}

.lp-topbar.lp-flash .lp-topbar-fill {
  background: linear-gradient(90deg, #4ade80, var(--lp-ok));
}

/* ============================================================
   ③ 上传进度卡（缩略图 + 环形进度 + 速度/剩余时间）
   ============================================================ */

/* 卡片进入 200ms / 退出 160ms，同 easing（规格 3、5） */
.lp-upload {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 12px 14px;
  border-radius: 18px;
  background: var(--lp-surface);
  border: 1px solid var(--lp-edge);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .16);
  /* blur 控制在 18px（规格要求 ≤ 20px） */
  backdrop-filter: blur(18px) saturate(170%);
  -webkit-backdrop-filter: blur(18px) saturate(170%);
  opacity: 0;
  visibility: hidden;
  will-change: transform, opacity;
  transition:
    opacity var(--lp-d-card-exit) var(--lp-ease-out),
    transform var(--lp-d-card-exit) var(--lp-ease-out),
    visibility 0s linear var(--lp-d-card-exit);
}

.lp-upload.lp-on {
  opacity: 1;
  visibility: visible;
  transform: none;
  /* 进入用 200ms（退出时长 160ms 更快，符合"退出比进入快约 20%"） */
  transition:
    opacity var(--lp-d-ui) var(--lp-ease-out),
    transform var(--lp-d-ui) var(--lp-ease-out),
    visibility 0s linear 0s;
}

/* 多文件并发上传时纵向堆叠（容器本身不做动画，避免与卡片动画叠加） */
.lp-upload-stack {
  position: fixed;
  z-index: 9996;
  left: 50%;
  bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  width: min(320px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}

/* 缩略图 */
.lp-up-thumb {
  position: relative;
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  overflow: hidden;
  background: rgba(120, 130, 150, .16);
  display: grid;
  place-items: center;
  font-size: 20px;
  color: var(--lp-ink-2);
}

.lp-up-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.lp-up-thumb::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 13px;
  box-shadow: inset 0 0 0 1px var(--lp-edge);
}

/* 环形进度：conic-gradient，无需 SVG。
   --p 由 JS 通过 setProperty 写入（0~1），非 CSS 过渡，故不违反"只动画 transform"。 */
.lp-up-ring {
  position: absolute;
  inset: -5px;
  border-radius: 18px;
  background: conic-gradient(var(--lp-accent) calc(var(--p, 0) * 360deg), rgba(10, 132, 255, .16) 0);
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2.5px));
  mask: radial-gradient(farthest-side, transparent calc(100% - 2.5px), #000 calc(100% - 2.5px));
  opacity: 0;
  transition: opacity var(--lp-d-micro) ease;
}

.lp-upload.lp-has-pct .lp-up-ring { opacity: 1; }

/* 文本区 */
.lp-up-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.lp-up-name {
  font-size: 13px;
  font-weight: 550;
  color: var(--lp-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 条形进度（与环形同步；填充用 scaleX，不用 width） */
.lp-up-track {
  position: relative;
  height: 4px;
  border-radius: 999px;
  background: rgba(10, 132, 255, .16);
  overflow: hidden;
}

.lp-up-fill {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--lp-accent-2), var(--lp-accent));
  transform-origin: left center;
  transform: scaleX(0);
  /* 进度事件间隔不均匀，用 150ms 微交互级过渡把台阶磨平 */
  transition: transform var(--lp-d-micro) var(--lp-ease-out);
}

/* 总字节未知时走不确定态（匀速扫动） */
.lp-upload.lp-unknown .lp-up-fill {
  will-change: transform;
  animation: lp-slide-up 1.1s linear infinite;
}

@keyframes lp-slide-up {
  0%   { transform: translateX(-110%) scaleX(.36); }
  100% { transform: translateX(400%) scaleX(.36); }
}

.lp-up-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  color: var(--lp-ink-2);
  font-variant-numeric: tabular-nums;
}

.lp-up-pct {
  font-weight: 600;
  color: var(--lp-accent);
  /* 颜色过渡：ease 150ms（规格 2） */
  transition: color var(--lp-d-micro) ease;
}

/* 完成态：进度条与环形一起转绿（颜色过渡同 150ms ease） */
.lp-upload.lp-done .lp-up-fill {
  background: linear-gradient(90deg, #4ade80, var(--lp-ok));
}

.lp-upload.lp-done .lp-up-ring {
  background: conic-gradient(var(--lp-ok) 360deg, rgba(52, 199, 89, .18) 0);
}

.lp-upload.lp-done .lp-up-pct { color: var(--lp-ok); }

/* 失败态：转红 */
.lp-upload.lp-error .lp-up-fill {
  background: linear-gradient(90deg, #ff8a80, var(--lp-danger));
}

.lp-upload.lp-error .lp-up-ring {
  background: conic-gradient(var(--lp-danger) 360deg, rgba(255, 59, 48, .18) 0);
}

.lp-upload.lp-error .lp-up-pct { color: var(--lp-danger); }

/* ============================================================
   ④ 消息乐观发送微状态
   —— 仅给 .msg-row[data-msg-id^="local_"]（本地乐观气泡）加类，
      不改动 script.js 的渲染逻辑
   ============================================================ */

/* 发送中：脉冲用 ease-in-out（屏内呼吸，非匀速） */
.msg-row.lp-sending > .msg-bubble-col > .msg-meta::after {
  content: "发送中";
  margin-left: 6px;
  font-size: 10.5px;
  color: var(--lp-ink-2);
  opacity: .9;
  animation: lp-pulse 1.25s var(--lp-ease-io) infinite;
}

@keyframes lp-pulse {
  0%, 100% { opacity: .35; }
  50%      { opacity: 1; }
}

/* 发送中的气泡：极轻微降透明（只动 opacity） */
.msg-row.lp-sending > .msg-bubble-col > .msg-bubble {
  opacity: .72;
  transition: opacity var(--lp-d-micro) ease;
}

/* 发送成功的落地瞬间：一次极短高亮，200ms 微交互级 */
.msg-row.lp-sent > .msg-bubble-col > .msg-bubble {
  animation: lp-landed var(--lp-d-ui) var(--lp-ease-out);
}

@keyframes lp-landed {
  0%   { box-shadow: 0 0 0 0 rgba(10, 132, 255, .34); }
  100% { box-shadow: 0 0 0 9px rgba(10, 132, 255, 0); }
}

/* 失败：已有 script.js 的红色 "!" 重发按钮，这里只补一个柔和红晕 */
.msg-row.lp-failed > .msg-bubble-col > .msg-bubble {
  box-shadow: 0 0 0 1.5px rgba(255, 59, 48, .42);
}

/* ============================================================
   ⑦ 触屏设备不挂 hover 效果
   —— 当前动效层无纯 hover 态，这里保留钩子：
      后续若新增 hover 样式，必须包进这个 media 查询内。
   ============================================================ */
@media (hover: none), (pointer: coarse) {
  .lp-upload,
  .lp-topbar,
  .lp-splash {
    /* 触屏上清除任何 hover 残留态 */
    --lp-hover-fx: none;
  }
}

/* ============================================================
   ⑥ 动效偏好：系统要求减少动效时
   —— 去掉 transform / 位移 / 缩放 / 视差，只保留 opacity 淡入淡出；
      循环动画用负 animation-delay 停在好看的帧上（而非粗暴 none，
      那样会闪回 0% 的初始帧）。
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  /* 循环动画：停帧而非移除。用负 delay 定位到观感最好的帧，
     halo 停在扩散中段、sheen停在轨道中段。 */
  .lp-splash-mark::after {
    animation: lp-halo 2.4s linear -1.2s infinite !important;
    animation-play-state: paused !important;
    opacity: 0 !important;
  }

  .lp-splash-track::after,
  .lp-upload.lp-unknown .lp-up-fill {
    animation: none !important;
    opacity: .3;
    transform: translateX(180%) !important;
  }

  .lp-topbar.lp-indeterminate .lp-topbar-fill {
    animation: none !important;
    opacity: .55;
    transform: scaleX(1) !important;
  }

  /* 进入类动画：去掉位移与缩放，只留opacity */
  .lp-splash-mark,
  .lp-splash-title,
  .lp-splash-sub,
  .lp-splash-track,
  .lp-splash-pct {
    animation: lp-fade-in var(--lp-d-micro) ease both !important;
  }

  @keyframes lp-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
  }

  /* 落地高亮与脉冲：去掉，只保留静态可读状态 */
  .msg-row.lp-sent > .msg-bubble-col > .msg-bubble {
    animation: none !important;
  }

  .msg-row.lp-sending > .msg-bubble-col > .msg-meta::after {
    animation: none !important;
    opacity: .7 !important;
  }

  /* 退出：只淡出，不缩放 */
  .lp-splash.lp-leave {
    opacity: 0;
    transform: none !important;
    transition-duration: var(--lp-d-micro) !important;
  }

  /* 进度条填充：仍如实推进（scaleX 是状态表达，不是装饰动画），
     但去掉所有过渡与扫光 */
  .lp-splash-fill,
  .lp-up-fill,
  .lp-topbar-fill {
    transition: none !important;
  }

  /* 卡片：只淡出，不位移 */
  .lp-upload {
    transform: none !important;
    transition: opacity var(--lp-d-micro) ease, visibility 0s linear var(--lp-d-micro) !important;
  }

  .lp-upload.lp-on { transform: none !important; }
}
