/* 数字人播放端样式：设计稿 1080×1920 等比舞台 */
* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* 设计令牌（v3）：尺寸与颜色统一收口，替换原先散落的硬编码。
   舞台内一律用设计稿像素（1080×1920），由 JS 等比缩放，故无须媒体查询。 */
:root {
  --c-primary: #00e0e0;                      /* 主色：取自 logo 青色 */
  --c-primary-soft: rgba(0, 224, 224, 0.16);
  --c-me: #ffd84d;                           /* 用户消息 */
  --c-miss: #ffcf6b;                         /* 兜底/未命中 */
  --c-line: rgba(255, 255, 255, 0.18);       /* 描边 */
  --c-fill: rgba(255, 255, 255, 0.10);       /* 填充 */
  --c-fill-2: rgba(255, 255, 255, 0.16);
  --r-box: 12px;                             /* 统一圆角（输入框/按钮/消息条对齐） */
  --bar-h: 110px;
  --fs-msg: 30px;
  --fs-input: 40px;
  --band-h: 400px;                           /* 顶部字幕带高度（人物头 y≈420，不得加高） */
}

html, body {
  /* 手机端关键：钉死在布局视口，禁止浏览器为「露出聚焦的输入框」而上推整个文档
     （否则软键盘一弹，数字人画面会整体上移/抖动） */
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background: #000;
  font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
  user-select: none;
}

#app {
  width: 100%;
  height: 100%;
  position: relative;
  background: #000;
  /* 底部安全区（iPhone 手势条/全面屏）：舞台整体上移，手势区露出背景层 */
  padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* （已移除）背景虚化层 .bg-blur / 舞台内背景层 .stage-bg：
   现在由真实视频 object-fit: cover 铺满整个屏幕，不再需要用背景图补露边区。 */

/* 舞台：只承载 UI（消息区/输入栏/浮层）。背景透明，让下层媒体层的视频透出来；
   z-index 高于媒体层，UI 始终浮在视频之上 */
.stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1080px;
  height: 1920px;
  transform-origin: center center;
  overflow: hidden;
  background: transparent;
  z-index: 1;
}

/* 媒体层：直接铺满整个屏幕（不是铺舞台）。
   ★放在 #stage 之外，才不受舞台等比缩放与 overflow:hidden 裁剪；
   媒体一律 object-fit: cover —— 屏幕比例与素材(9:16)不一致时居中裁切，
   人物铺满全屏、无虚化背景、无露边。 */
.media-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #000;      /* 视频/图片就绪前的兜底底色 */
  pointer-events: none;
  z-index: 0;

  /* ★镜头微调（2026-09-22）：整体下移画面，让人物在屏内更靠下、头顶留白更顺眼。
     为什么在播放端调而不动素材：所有层（static/动作/对口型）一起移 → 待机↔回答
     依然完全同源，切换不跳；改一个数字即可，随时可回退。
       --cam-shift 下移幅度（%，正值 = 人物在画面中下移）
       --cam-zoom  数码变焦，必须 >1：给平移留出余量，否则顶部会露黑边
     约束：--cam-shift 必须小于 (--cam-zoom - 1) / 2 × 100
     现场试值可加 URL 参数覆盖：?camY=3&camZ=1.09 */
}

/* ★镜头微调默认值（2026-09-22）。在播放端整体下移画面，让人物在屏内更靠下、
   头顶留白更顺眼。为什么不动素材：所有层（static/动作/对口型）一起移 → 待机↔
   回答依然完全同源，切换不跳；改一个数字即可，随时可回退。
     --cam-shift 下移幅度（%，正值 = 人物在画面中下移）
     --cam-zoom  数码变焦，必须 >1：给平移留出余量，否则顶部会露黑边
   ★必须声明在 :root（不能放 .media-layer 里）：局部声明会盖住 URL 参数写在
   <html> 上的覆盖值，导致调参失效（已踩过）。
   几何约束：--cam-shift < (--cam-zoom - 1) / 2 × 100（取满值时头顶留白 ≈
   原留白 × --cam-zoom，人物同步放大约 --cam-zoom 倍）
   现场试值（不用改文件）：?camY=8.5&camZ=1.18 */
:root {
  --cam-shift: 8.5%;
  --cam-zoom: 1.18;
}

.media-video,
.media-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;     /* 铺满屏幕；比例不符时居中裁切，不拉伸不变形 */
  /* 镜头：先数码变焦（留出平移余量）再整体下移，所有层同一变换 → 层间零位移差 */
  transform-origin: center center;
  transform: translateY(var(--cam-shift, 0)) scale(var(--cam-zoom, 1));
}

/* ★待机底片常显（2026-09-29）：不能 display:none —— iOS/微信对隐藏的 video 不加载数据，
   canplay 永不触发（现象：只剩定妆照）。无画面时 video 透明，下方 .media-poster 兜底。 */
.media-video { display: block; z-index: 3; }
/* 回答对口型层：压在待机层之上，仍在 UI（5/6）之下 */
/* 回答对口型层 / 动作层：按需显示（不播时不挡底片） */
.media-video.answer { display: none; z-index: 4; }
.media-video.motion { display: none; z-index: 4; }
.media-poster { display: none; z-index: 2; }

/* ★底片动图（2026-09-29 动图方案）：手机/微信 H5 会拦 video 自动播放（需手势），
   但【图片不受该策略限制】→ 进页面立刻“动”。与 .media-poster 同层(z=2)，靠 DOM 顺序压其上；
   .media-video(z=3) 一出画面即自然盖住；JS 在 video 的 playing 事件里加 .hide 淡出，交接给更清晰的视频。 */
.media-anim {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform-origin: center center;
  transform: translateY(var(--cam-shift, 0)) scale(var(--cam-zoom, 1));
  z-index: 2;
  display: block;
  transition: opacity .45s ease;
}
.media-anim.hide { opacity: 0; pointer-events: none; }

/* 房间顶层装饰图（2026-09-29）：坐标系 = 房间设计稿像素（随 #stage 等比缩放）；
   整层不拦截交互（pointer-events:none）。
   ★层级：z-index:4 —— 盖在数字人画面之上、但【低于】舞台 UI（消息区 z=5 / 输入栏 z=6），
   保证装饰图不会遮住气泡与输入框（左右 2026-09-29 确认）。 */
.deco-layer {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  pointer-events: none;
  z-index: 4;
}
.deco-layer .deco-img {
  position: absolute;
  display: block;
  border: 0;
  max-width: none;
}

.media-fallback {
  display: none;
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  text-align: center;
  z-index: 1;
  color: rgba(255, 255, 255, 0.5);
  font-size: clamp(18px, 3.4vw, 40px);
  letter-spacing: 4px;
}

/* ============ 消息区（v3 改版） ============
   v2.2 的防遮视频约束保留：设计稿人物头 y≈420，此带高 400 不得加高。
   改动点：高度自适应（短消息贴合内容，不再留空带）、超出渐隐（替代硬切滚动条）、
   角色标识（不再只靠颜色区分）、思考占位、长答案点击看全文。 */
.chat-area {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: auto;
  max-height: var(--band-h);
  padding: 36px 24px 0;
  overflow: hidden;
  z-index: 5;
}

.msg-list {
  width: 100%;
  max-height: calc(var(--band-h) - 36px);
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.msg-list::-webkit-scrollbar { width: 0; height: 0; }
/* 仅在真正溢出时渐隐底边，提示「还有内容」 */
.msg-list.has-overflow {
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 40px), transparent 100%);
          mask-image: linear-gradient(to bottom, #000 calc(100% - 40px), transparent 100%);
}

/* 一条消息 = 角色标识 + 内容条 */
.msg {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  width: 100%;
  margin-bottom: 12px;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.msg.show { opacity: 1; transform: translateY(0); }

.msg-avatar {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  margin-top: 4px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  font-weight: 700;
  line-height: 1;
  background: var(--c-fill-2);
  color: rgba(255, 255, 255, 0.9);
}
.msg.dh .msg-avatar { background: var(--c-primary-soft); color: var(--c-primary); }
.msg.me .msg-avatar { background: rgba(255, 216, 77, 0.18); color: var(--c-me); }
.msg.miss .msg-avatar { background: rgba(255, 207, 107, 0.18); color: var(--c-miss); }

/* 内容条：沿用旧播放端字幕底（半透明黑），左侧加角色色条做区分 */
.msg-bubble {
  flex: 1;
  min-width: 0;
  padding: 12px 20px;
  border-radius: var(--r-box);
  border-left: 4px solid transparent;
  background: rgba(0, 0, 0, 0.46);
  font-size: var(--fs-msg);
  line-height: 1.45;
  word-break: break-word;
  color: #fff;
}
.msg.dh .msg-bubble { border-left-color: var(--c-primary); }
.msg.me .msg-bubble { color: var(--c-me); border-left-color: var(--c-me); }
.msg.miss .msg-bubble { color: var(--c-miss); border-left-color: var(--c-miss); }

/* 长答案：可点击展开全文，尾部给一个「展开全文」提示 */
.msg.is-long .msg-bubble { cursor: pointer; }
.msg.is-long .msg-bubble::after {
  content: "展开全文 ›";
  margin-left: 10px;
  font-size: 24px;
  color: rgba(255, 255, 255, 0.42);
}

/* 思考占位：三点脉动，替代回答前的静默 */
.msg.thinking .msg-bubble {
  display: flex;
  align-items: center;
  color: rgba(255, 255, 255, 0.6);
}
.dots { display: inline-flex; align-items: center; gap: 8px; margin-left: 10px; }
.dots i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.3;
  animation: dot-pulse 1.2s ease-in-out infinite;
}
.dots i:nth-child(2) { animation-delay: 0.2s; }
.dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes dot-pulse {
  0%, 100% { opacity: 0.25; transform: translateY(0); }
  40% { opacity: 1; transform: translateY(-4px); }
}

/* ============ 输入栏（v3 改版） ============ */
.input-bar {
  position: absolute;
  left: 60px;
  right: 60px;
  bottom: 40px;
  height: var(--bar-h);
  display: flex;
  gap: 20px;
  align-items: stretch;
  z-index: 6;
  /* 软键盘弹起时由 JS 用 transform 顶到键盘上沿（不动舞台、不动顶部字幕），
     v3.1 不再改 #app 高度，避开「整屏上移/舞台缩放」 */
  will-change: transform;
  /* 键盘弹起/收起时输入栏平滑到位（2026-09-29）；只动 transform，不触发重排 */
  transition: transform 0.18s ease-out;
}

/* 语音入口（D 方案：UI 占位，功能待接本地识别） */
.mic-btn {
  flex: 0 0 auto;
  width: var(--bar-h);
  border: 1px solid var(--c-line);
  border-radius: var(--r-box);
  background: var(--c-fill);
  color: rgba(255, 255, 255, 0.86);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.mic-btn:active { background: var(--c-fill-2); }
.mic-btn.ready { color: var(--c-primary); border-color: rgba(0, 224, 224, 0.5); }

.input-box { position: relative; flex: 1; min-width: 0; }

.chat-input {
  width: 100%;
  height: 100%;
  border: 1px solid var(--c-line);
  border-radius: var(--r-box);
  background: var(--c-fill);
  color: #fff;
  font-size: var(--fs-input);
  padding: 0 150px 0 32px;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
}
.chat-input::placeholder { color: rgba(255, 255, 255, 0.42); }
.chat-input:focus {
  border-color: var(--c-primary);
  box-shadow: 0 0 0 4px var(--c-primary-soft);
  background: rgba(255, 255, 255, 0.14);
}

.char-count {
  position: absolute;
  right: 26px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 24px;
  letter-spacing: 1px;
  color: rgba(255, 255, 255, 0.35);
  pointer-events: none;
  transition: color 0.2s;
}
.char-count.warn { color: var(--c-miss); }

.send-btn {
  position: relative;
  flex: 0 0 auto;
  width: 190px;
  border: none;
  border-radius: var(--r-box);
  background: var(--c-primary);
  color: #06272b;
  font-size: 40px;
  font-weight: 700;
  letter-spacing: 6px;
  cursor: pointer;
  transition: opacity 0.2s, transform 0.12s;
}
.send-btn:disabled { opacity: 0.3; cursor: default; }
.send-btn:not(:disabled):active { transform: scale(0.97); }
/* 发送中：文字隐去换成转圈，避免"点了没反应" */
.send-btn.busy { color: transparent; }
.send-btn.busy::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40px;
  height: 40px;
  margin: -20px 0 0 -20px;
  border: 4px solid rgba(6, 39, 43, 0.3);
  border-top-color: #06272b;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ============ 全文浮层（长答案展开） ============ */
.full-text {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.78);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 120px 80px;
  z-index: 50;
}
.full-text.show { display: flex; }
.full-text-card {
  width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  padding: 44px 40px 36px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 18px;
  background: #14171c;
}
.full-text-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  color: #fff;
  font-size: 32px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
  user-select: text;
}
.full-text-close {
  margin-top: 32px;
  flex: 0 0 auto;
  height: 88px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: var(--r-box);
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.85);
  font-size: 32px;
  letter-spacing: 4px;
  cursor: pointer;
}
.full-text-close:active { background: rgba(255, 255, 255, 0.14); }

/* ============ 轻提示 ============ */
.toast {
  position: absolute;
  left: 50%;
  bottom: 200px;
  padding: 20px 40px;
  border-radius: var(--r-box);
  background: rgba(0, 0, 0, 0.82);
  color: #fff;
  font-size: 30px;
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, 20px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 60;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* 加载遮罩 */
.loading {
  position: fixed;
  inset: 0;
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 99;
  transition: opacity 0.4s ease;
}
.loading.hide { opacity: 0; pointer-events: none; }
.loading-text {
  color: rgba(255, 255, 255, 0.8);
  font-size: 44px;
  letter-spacing: 6px;
  animation: pulse 1.2s ease-in-out infinite;
}
@keyframes pulse { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }

/* 横屏提示（默认隐藏，JS 检测到横屏显示） */
.landscape-hint {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.88);
  z-index: 200;
  align-items: center;
  justify-content: center;
}
.landscape-hint.show { display: flex; }
.landscape-hint-card { text-align: center; color: #fff; }
.landscape-hint-phone {
  width: 64px;
  height: 108px;
  margin: 0 auto 36px;
  border: 3px solid rgba(255, 255, 255, 0.9);
  border-radius: 12px;
  animation: hint-rotate 1.6s ease-in-out infinite;
}
@keyframes hint-rotate {
  0%, 20% { transform: rotate(0deg); }
  60%, 100% { transform: rotate(90deg); }
}
.landscape-hint-text {
  font-size: 28px;
  letter-spacing: 2px;
  color: rgba(255, 255, 255, 0.85);
}

/* ---------- 语音输入（v3.3：文字 ↔ 语音 模式切换） ---------- */
.mic-btn { position: relative; touch-action: none; -webkit-user-select: none; user-select: none; }
/* 左键图标：默认麦克风；语音模式下换成键盘（提示「点我回文字输入」） */
.mic-btn .ico-kb { display: none; }
.input-bar.voice-mode .mic-btn .ico-mic { display: none; }
.input-bar.voice-mode .mic-btn .ico-kb { display: block; }
.input-bar.voice-mode .mic-btn { color: var(--c-primary); border-color: rgba(0, 224, 224, 0.5); }

/* 「按住说话」：只在语音模式下显示，占位与输入框完全互换 */
.voice-btn {
  position: relative;
  display: none;
  flex: 1;
  min-width: 0;
  border: 1px solid var(--c-line);
  border-radius: var(--r-box);
  background: var(--c-fill);
  color: rgba(255, 255, 255, 0.9);
  font-size: var(--fs-input);
  letter-spacing: 4px;
  cursor: pointer;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, border-color 0.2s, color 0.2s;
}
.input-bar.voice-mode .voice-btn { display: flex; }
/* 语音模式下隐藏文字输入框与发送键（说即发，无需再点发送） */
.input-bar.voice-mode .input-box,
.input-bar.voice-mode .send-btn { display: none; }

.voice-btn.recording {
  color: #ff5252;
  border-color: rgba(255, 82, 82, 0.55);
  background: rgba(255, 82, 82, 0.12);
  animation: micPulse 1s ease-in-out infinite;
}
.voice-btn.recording::after {
  content: ""; position: absolute; inset: -2px; border-radius: var(--r-box);
  border: 2px solid rgba(255, 82, 82, .65); animation: micRipple 1.2s ease-out infinite;
}
.voice-btn.busy { opacity: .5; }
@keyframes micPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }
@keyframes micRipple { 0% { transform: scale(.9); opacity: .9; } 100% { transform: scale(1.45); opacity: 0; } }

/* ==================== 名片（2026-09-29） ====================
   ★ 本区块全部使用【房间设计稿坐标系】（如 1080×1920）像素值：
     弹层与按钮都挂在 #stage 内，随舞台等比缩放，手机上自动适配，无需媒体查询。
   数据：dh_room.contact → /api/room 的 room.contact = {name,title,phone,email,address} */

/* 装饰图下方的「名片」入口按钮（整层 pointer-events:none，此处单独放行） */
.namecard-btn {
  position: absolute;
  pointer-events: auto;              /* ★ 整层不拦截，只有它可点 */
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 72px;
  padding: 0 24px;
  box-sizing: border-box;
  border: 1.5px solid rgba(255, 255, 255, .38);
  border-radius: 14px;
  background: rgba(20, 26, 40, .55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  color: #eaf0ff;
  font-size: 30px;
  letter-spacing: 2px;
  cursor: pointer;
  transition: background .18s ease, transform .18s ease;
}
.namecard-btn:active { background: rgba(40, 90, 200, .75); transform: scale(.97); }
.namecard-btn svg { flex-shrink: 0; }

/* 弹层：铺满整个舞台 */
.card-modal {
  position: absolute;
  inset: 0;
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px;
  box-sizing: border-box;
  background: rgba(0, 0, 0, .72);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s ease, visibility .2s ease;
}
.card-modal.show { opacity: 1; visibility: visible; }

/* 名片本体：传统横式名片观感 */
.card-box { width: 100%; max-width: 800px; transform: translateY(12px); transition: transform .22s ease; }
.card-modal.show .card-box { transform: translateY(0); }

.nc-inner {
  position: relative;
  padding: 56px 52px 46px;
  border-radius: 26px;
  background: linear-gradient(160deg, #ffffff 0%, #f2f5fb 100%);
  box-shadow: 0 26px 70px rgba(0, 0, 0, .5);
  color: #16203a;
}
/* 顶部一细条品牌色，像名片的色带 */
.nc-inner::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 10px;
  border-radius: 26px 26px 0 0;
  background: linear-gradient(90deg, #1f6feb, #39a0ff 55%, #6fc3ff);
}

.nc-head { display: flex; align-items: center; gap: 30px; }
.nc-avatar {
  width: 140px; height: 140px;
  flex-shrink: 0;
  border-radius: 20px;
  overflow: hidden;
  background: #e6ebf5;
}
.nc-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.nc-id { flex: 1; min-width: 0; }

.nc-name {
  font-size: 54px;
  font-weight: 700;
  letter-spacing: 3px;
  line-height: 1.15;
}
.nc-title {
  margin-top: 14px;
  font-size: 28px;
  line-height: 1.45;
  color: #46536f;
}
.nc-company {
  margin-top: 8px;
  font-size: 26px;
  color: #7a869c;
}

.nc-sep {
  height: 2px;
  margin: 40px 0 32px;
  background: linear-gradient(90deg, #1f6feb 0%, #1f6feb 90px, rgba(31, 111, 235, .12) 90px, rgba(31, 111, 235, .12) 100%);
}

.nc-rows { display: flex; flex-direction: column; gap: 26px; }
.nc-row { display: flex; align-items: flex-start; gap: 18px; }
.nc-ico { flex-shrink: 0; margin-top: 3px; color: #1f6feb; }
.nc-k {
  flex-shrink: 0;
  width: 88px;
  font-size: 28px;
  color: #7a869c;
  letter-spacing: 2px;
}
.nc-v {
  flex: 1;
  font-size: 30px;
  line-height: 1.45;
  color: #16203a;
  word-break: break-all;
}

.nc-close {
  margin-top: 46px;
  width: 100%;
  height: 84px;
  border: none;
  border-radius: 16px;
  background: rgba(22, 32, 58, .08);
  color: #46536f;
  font-size: 30px;
  letter-spacing: 4px;
  cursor: pointer;
}
.nc-close:active { background: rgba(22, 32, 58, .16); }
