/* =============================================================
   XmLoader 就地卡片 / 分阶段步骤条 / 特效背景 样式（独立文件，不污染 design-system.css）
   ============================================================= */

.xm-loader {
  position: relative;
  overflow: hidden;
  border-radius: 14px;
  border: 1px solid var(--bd-1, rgba(255,255,255,.08));
  background: var(--bg-2, #0e0e12);
  min-height: 200px;
  display: block;
  transition: opacity .4s ease;
}

/* 整卡大幅特效背景（醒目，不再缩进小圆盘） */
.xm-loader-fx { position: absolute; inset: 0; opacity: 0; transition: opacity .8s ease; pointer-events: none; }
.xm-loader-fx canvas { display: block; width: 100% !important; height: 100% !important; }
.xm-loader.xm-fx-ready .xm-loader-fx { opacity: 1; }

/* 右侧可读性遮罩：左边露出特效、右边压暗放文字，两者不再互相遮挡 */
/* 磨砂遮罩层：模糊 + 暗底，用 mask 从左往右柔和淡入，消除硬边界；文字层浮在其上 */
.xm-loader-scrim {
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  background: linear-gradient(90deg,
    rgba(12,12,18,0) 0%,
    rgba(12,12,18,.42) 46%,
    rgba(12,12,18,.74) 70%,
    rgba(12,12,18,.9) 100%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,.35) 30%, #000 58%);
  mask-image: linear-gradient(90deg, transparent 0%, rgba(0,0,0,.35) 30%, #000 58%);
}

/* 文字层（透明，浮在磨砂层之上，靠文字阴影保证可读） */
.xm-loader-body {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(54%, 430px);
  padding: 22px 30px;
  display: flex; flex-direction: column; justify-content: center;
  z-index: 2; text-align: left;
}

/* 底部进度条（动画本身代表进度） */
.xm-progress { position: absolute; left: 0; right: 0; bottom: 0; height: 4px; background: rgba(255,255,255,.07); z-index: 2; }
.xm-progress-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, #7c3aed, #a78bfa);
  box-shadow: 0 0 10px rgba(167,139,250,.7);
  transition: width .7s cubic-bezier(.4,0,.2,1);
}
.xm-loader-title {
  font-size: 15px;
  font-weight: 700;
  color: #fff;
  margin-bottom: 16px;
  letter-spacing: .01em;
  text-shadow: 0 1px 12px rgba(0,0,0,.7);
}
.xm-loader-title:empty { display: none; }

/* 步骤条 */
.xm-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.xm-step { display: flex; align-items: center; gap: 10px; font-size: 13px; transition: color .3s ease; text-shadow: 0 1px 6px rgba(0,0,0,.55); }
.xm-dot {
  flex-shrink: 0;
  width: 16px; height: 16px;
  border-radius: 50%;
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1.5px solid var(--bd-1, rgba(255,255,255,.14));
  transition: border-color .3s ease, background .3s ease;
}
.xm-step-label { transition: color .3s ease; }

/* pending：暗点 */
.xm-step.is-pending { color: var(--tx-3, #6b6b76); }
.xm-step.is-pending .xm-dot { border-color: rgba(255,255,255,.14); }

/* active：品牌紫转圈 + 文字点亮 */
.xm-step.is-active { color: var(--tx-1, #f4f4f5); }
.xm-step.is-active .xm-dot { border-color: transparent; }
.xm-step.is-active .xm-dot::before {
  content: "";
  position: absolute; inset: -1.5px;
  border-radius: 50%;
  border: 1.5px solid rgba(139,92,246,.28);
  border-top-color: var(--brand, #a78bfa);
  animation: xm-spin .7s linear infinite;
}

/* done：紫底 ✓ */
.xm-step.is-done { color: var(--tx-2, #b8b8c0); }
.xm-step.is-done .xm-dot {
  border-color: #8b5cf6;
  background: #8b5cf6;
}
.xm-step.is-done .xm-dot::after {
  content: "";
  width: 4px; height: 8px;
  border: solid #fff; border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg) translateY(-1px);
}

/* fail：红点 ✕（字色走 --err，亮色为深红可读） */
.xm-step.is-fail { color: var(--err, #f87171); }
.xm-step.is-fail .xm-dot { border-color: #ef4444; background: rgba(239,68,68,.16); }
.xm-step.is-fail .xm-dot::after {
  content: "✕"; font-size: 9px; line-height: 1; color: var(--err, #f87171);
}

/* 当前步单行(仅框选模式显示;整列步骤见 .xm-steps) */
.xm-current { display: none; }

/* =============================================================
   框选模式:生成类把加载卡约束到目标图/视频的比例与宽度,
   特效满铺整卡、文字压底,不再撑满整行的横条。
   舞台居中 + 自适应加大,避免「大结果区 + 左下角小卡 + 大片空白」。
   ============================================================= */
.xm-loader-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  width: 100%;
  min-height: min(58vh, 560px);
  padding: 12px 8px 28px;
  box-sizing: border-box;
}
.xm-loader-caption {
  font-size: 12px;
  color: var(--tx-3, #6b6b76);
  text-align: center;
  line-height: 1.5;
}
.xm-loader-slots {
  display: grid;
  width: 100%;
  max-width: 960px;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  align-items: stretch;
}
/* 2–4 屏时更匀称的列 */
.xm-loader-slots[data-n="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 560px; }
.xm-loader-slots[data-n="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 720px; }
.xm-loader-slots[data-n="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); max-width: 880px; }
.xm-loader-slots[data-n="5"],
.xm-loader-slots[data-n="6"] { grid-template-columns: repeat(3, minmax(0, 1fr)); max-width: 780px; }
.xm-loader-slots[data-n="7"],
.xm-loader-slots[data-n="8"] { grid-template-columns: repeat(4, minmax(0, 1fr)); max-width: 920px; }
@media (max-width: 720px) {
  .xm-loader-slots[data-n="3"],
  .xm-loader-slots[data-n="4"],
  .xm-loader-slots[data-n="5"],
  .xm-loader-slots[data-n="6"],
  .xm-loader-slots[data-n="7"],
  .xm-loader-slots[data-n="8"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.xm-loader-slot {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  min-width: 0;
}
.xm-loader-slot.is-live {
  /* 主加载卡吃满格子 */
}
.xm-loader-slot.is-live .xm-loader.xm-framed {
  display: block;
  width: 100% !important;
  max-width: none;
  height: auto;
  --xm-w: 100%;
}
.xm-loader-slot.is-ghost {
  aspect-ratio: var(--xm-ar, 3 / 4);
  border: 1px dashed var(--bd-2, rgba(255,255,255,.12));
  background:
    linear-gradient(135deg, rgba(139,92,246,.08), rgba(255,255,255,.02) 55%),
    var(--bg-2, #121218);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  color: var(--tx-3, #6b6b76);
}
.xm-ghost-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--tx-2, #b8b8c0);
}
.xm-ghost-wait {
  font-size: 11px;
  opacity: .75;
}
/* 幽灵格呼吸,表示「后续还会出图」 */
.xm-loader-slot.is-ghost::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(110deg, transparent 30%, rgba(167,139,250,.08) 48%, transparent 66%);
  background-size: 200% 100%;
  animation: xm-ghost-shimmer 2.4s ease-in-out infinite;
  pointer-events: none;
}
@keyframes xm-ghost-shimmer {
  0% { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

.xm-loader.xm-framed {
  display: block;
  width: var(--xm-w, clamp(300px, 36vw, 400px));
  max-width: min(100%, 480px);
  aspect-ratio: var(--xm-ar, 3 / 4);
  min-height: 0;
  margin: 0 auto;
  box-shadow: 0 16px 48px rgba(0,0,0,.28), 0 0 0 1px rgba(139,92,246,.08);
}
/* 遮罩改为自下而上淡入(小卡里文字压底) */
.xm-loader.xm-framed .xm-loader-scrim {
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  background: linear-gradient(0deg,
    rgba(10,10,16,.92) 0%,
    rgba(10,10,16,.72) 24%,
    rgba(10,10,16,.32) 48%,
    rgba(10,10,16,0) 72%);
  -webkit-mask-image: linear-gradient(0deg, #000 0%, rgba(0,0,0,.4) 42%, transparent 74%);
  mask-image: linear-gradient(0deg, #000 0%, rgba(0,0,0,.4) 42%, transparent 74%);
}
.xm-loader.xm-framed .xm-loader-body {
  top: auto; left: 0; right: 0; bottom: 0;
  width: 100%;
  padding: 16px 18px 18px;
  justify-content: flex-end;
}
.xm-loader.xm-framed .xm-steps { display: none; }
.xm-loader.xm-framed .xm-loader-title { font-size: 14px; margin-bottom: 6px; }
.xm-loader.xm-framed .xm-current {
  display: block;
  font-size: 12px;
  color: #e7e2f7;
  text-shadow: 0 1px 6px rgba(0,0,0,.6);
  min-height: 1em;
}
.xm-loader.xm-framed .xm-loader-foot { margin-top: 10px; }

@media (max-width: 560px) {
  .xm-loader-stage { min-height: min(48vh, 420px); padding: 8px 4px 20px; }
  .xm-loader.xm-framed {
    width: var(--xm-w, min(92vw, 340px));
    max-width: 100%;
  }
}
/* 嵌在对话气泡等窄容器:不要强撑 58vh,只保留卡片本身 */
.xm-mount .xm-loader-stage,
.chat-msg .xm-loader-stage,
.msg-body .xm-loader-stage {
  min-height: 0;
  padding: 2px 0 6px;
  align-items: flex-start;
}
.xm-mount .xm-loader.xm-framed {
  margin: 0;
}

/* 底部：计时 + 提示 */
.xm-loader-foot {
  margin-top: 18px;
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; color: var(--tx-3, #6b6b76);
  font-variant-numeric: tabular-nums;
}
.xm-elapsed { font-weight: 600; color: var(--tx-2, #b8b8c0); }
.xm-hint { color: var(--tx-3, #6b6b76); }
.xm-hint:not(:empty)::before { content: "·"; margin-right: 8px; color: var(--bd-1, rgba(255,255,255,.2)); }
.xm-pct { margin-left: auto; font-weight: 700; color: var(--brand, #a78bfa); font-variant-numeric: tabular-nums; }

/* 终态 */
.xm-loader.xm-fail { border-color: rgba(239,68,68,.32); }
.xm-loader.xm-done .xm-loader-title { color: var(--brand, #a78bfa); }

/* 降级：无 WebGL / prefers-reduced-motion → 静态渐变呼吸 */
.xm-loader.xm-reduced .xm-loader-fx { display: none; }
.xm-loader.xm-reduced {
  background:
    radial-gradient(130% 100% at 50% -10%, rgba(139,92,246,.14), transparent 62%),
    var(--bg-2, #0e0e12);
}

@media (max-width: 560px){
  .xm-loader-body { width: 100%; padding: 20px 22px; }
  .xm-loader-scrim { background: linear-gradient(90deg, rgba(11,11,17,.5) 0%, rgba(11,11,17,.9) 55%); }
}

@keyframes xm-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .xm-step.is-active .xm-dot::before { animation: none; border-top-color: var(--brand, #a78bfa); }
  .xm-loader-fx { display: none; }
}

/* =============================================================
   浅色主题:整卡此前写死暗底/暗遮罩/白字,在浅色下呈现"左白右黑"割裂。
   这里把卡底、可读性遮罩、文字与进度轨改成浅色调,让紫色特效柔和淡入浅底、深色文字压其上。
   ============================================================= */
:root[data-theme="light"] .xm-loader {
  background: rgba(255,255,255,.82);
  border-color: rgba(0,0,0,.06);
}
:root[data-theme="light"] .xm-loader.xm-framed {
  box-shadow: 0 12px 36px rgba(15,23,42,.1), 0 0 0 1px rgba(124,58,237,.08);
}
:root[data-theme="light"] .xm-loader-slot.is-ghost {
  background:
    linear-gradient(135deg, rgba(139,92,246,.06), rgba(255,255,255,.7) 55%),
    #f4f4f8;
  border-color: rgba(0,0,0,.08);
}
:root[data-theme="light"] .xm-ghost-label { color: var(--tx-1, #1d1d1f); }
:root[data-theme="light"] .xm-loader-caption { color: var(--tx-3, #a1a1a6); }
/* 遮罩改为白色淡入(替换 rgba(12,12,18) 暗底),消除右侧黑块 */
:root[data-theme="light"] .xm-loader-scrim {
  background: linear-gradient(90deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,.5) 46%,
    rgba(255,255,255,.82) 70%,
    rgba(255,255,255,.94) 100%);
}
:root[data-theme="light"] .xm-loader.xm-framed .xm-loader-scrim {
  background: linear-gradient(0deg,
    rgba(255,255,255,.94) 0%,
    rgba(255,255,255,.8) 24%,
    rgba(255,255,255,.4) 48%,
    rgba(255,255,255,0) 72%);
}
@media (max-width: 560px){
  :root[data-theme="light"] .xm-loader-scrim {
    background: linear-gradient(90deg, rgba(255,255,255,.55) 0%, rgba(255,255,255,.94) 55%);
  }
}
/* 文字/步骤:浅底改深字,阴影减弱 */
:root[data-theme="light"] .xm-loader-title { color: var(--tx-1, #1c1c1e); text-shadow: 0 1px 8px rgba(255,255,255,.7); }
:root[data-theme="light"] .xm-step { text-shadow: none; }
:root[data-theme="light"] .xm-loader.xm-framed .xm-current { color: var(--tx-2, #3a3a3c); text-shadow: 0 1px 6px rgba(255,255,255,.7); }
:root[data-theme="light"] .xm-loader.xm-done .xm-loader-title { color: #7c3aed; }
:root[data-theme="light"] .xm-pct { color: #7c3aed; }
:root[data-theme="light"] .xm-elapsed { color: var(--tx-2, #636366); }
/* 进度轨与降级静态底改浅色 */
:root[data-theme="light"] .xm-progress { background: rgba(0,0,0,.07); }
:root[data-theme="light"] .xm-loader.xm-reduced {
  background:
    radial-gradient(130% 100% at 50% -10%, rgba(124,58,237,.12), transparent 62%),
    rgba(255,255,255,.82);
}
