<!-- =============================================================================
// 企微IT智能服务台 — H5用户端输入栏组件（v1.3 视觉重塑）
// =============================================================================
// 说明：底部输入栏，固定在消息列表下方。
// v1.3 视觉重塑：
//   - 工具栏从 InputBar 内下方 → 移到 InputBar 顶部（resize-handle 之后）
//   - 工具栏 class: .input-bar__toolbar → .glass-toolbar（玻璃拟态胶囊）
//   - 按钮 class: .input-bar__btn → .glass-btn（40px 圆形玻璃）
//   - 坐席按钮 class: .input-bar__agent → .agent-btn（44px 图片头像 + 紫粉渐变边框）
//   - emoji/file/voice 按钮内容：emoji 字符 → 高端 SVG 图标
//   - 坐席按钮：删除 .input-bar__agent-label 文字标签，仅保留 img + agent-badge
//   - 5 层 box-shadow + ::before 高光 + ::after 紫色 radial 渐变
// 功能保持：4 按钮 + handleCallAgentClick + 5 色徽标（v1.2 契约不变）
// ============================================================================= -->

<template>
  <!-- ===========================================================
       SVG defs：渐变定义（emoji / 文件 / 话筒）
       这些 defs 必须在 button SVG 之前渲染，供 url(#g-*) 引用
       =========================================================== -->
  <svg width="0" height="0" style="position: absolute;" aria-hidden="true">
    <defs>
      <!-- 表情渐变 -->
      <linearGradient id="g-emoji" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" stop-color="#fde68a" />
        <stop offset="60%" stop-color="#fbbf24" />
        <stop offset="100%" stop-color="#d97706" />
      </linearGradient>
      <radialGradient id="g-emoji-blush" cx="50%" cy="50%" r="50%">
        <stop offset="0%" stop-color="rgba(244, 63, 94, 0.4)" />
        <stop offset="100%" stop-color="rgba(244, 63, 94, 0)" />
      </radialGradient>
      <linearGradient id="g-highlight" x1="50%" y1="0%" x2="50%" y2="100%">
        <stop offset="0%" stop-color="white" stop-opacity="0.7" />
        <stop offset="100%" stop-color="white" stop-opacity="0" />
      </linearGradient>
      <!-- 文件渐变 -->
      <linearGradient id="g-doc-body" x1="50%" y1="0%" x2="50%" y2="100%">
        <stop offset="0%" stop-color="#ffffff" />
        <stop offset="100%" stop-color="#dbeafe" />
      </linearGradient>
      <linearGradient id="g-doc-fold" x1="50%" y1="0%" x2="50%" y2="100%">
        <stop offset="0%" stop-color="#c7d2fe" />
        <stop offset="100%" stop-color="#6366f1" />
      </linearGradient>
      <linearGradient id="g-doc-text" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" stop-color="#6366f1" />
        <stop offset="100%" stop-color="#a855f7" />
      </linearGradient>
      <!-- 语音渐变 -->
      <linearGradient id="g-mic-body" x1="50%" y1="0%" x2="50%" y2="100%">
        <stop offset="0%" stop-color="#c4b5fd" />
        <stop offset="50%" stop-color="#8b5cf6" />
        <stop offset="100%" stop-color="#6d28d9" />
      </linearGradient>
      <linearGradient id="g-mic-shine" x1="50%" y1="0%" x2="50%" y2="100%">
        <stop offset="0%" stop-color="white" stop-opacity="0.65" />
        <stop offset="100%" stop-color="white" stop-opacity="0" />
      </linearGradient>
      <!-- 群聊渐变（v1.9 新增） -->
      <linearGradient id="g-group" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#a5b4fc" />
        <stop offset="100%" stop-color="#c4b5fd" />
      </linearGradient>
      <linearGradient id="g-group-strong" x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stop-color="#6366f1" />
        <stop offset="50%" stop-color="#a855f7" />
        <stop offset="100%" stop-color="#ec4899" />
      </linearGradient>
      <!-- 圆角长方形轨道渐变（v1.9 新增） -->
      <linearGradient id="g-rail" x1="0%" y1="0%" x2="100%" y2="0%">
        <stop offset="0%" stop-color="#818cf8" stop-opacity="0.5" />
        <stop offset="50%" stop-color="#c4b5fd" stop-opacity="0.9" />
        <stop offset="100%" stop-color="#818cf8" stop-opacity="0.5" />
      </linearGradient>
    </defs>
  </svg>

  <div class="input-bar">
    <!-- 拖拽手柄：可手动调节输入栏高度 -->
    <div
      class="input-bar__resize-handle"
      @mousedown="handleInputResizeStart"
    >
      <div class="input-bar__resize-track"></div>
    </div>

    <!-- ===========================================================
         v1.9 圆润拱形工具栏 — InputBar 内顶部居中（resize-handle 之后）
         5 按钮顺序：emoji / 文件 / 人工坐席(居中 60px) / 语音 / 群聊
         拱形轨道 SVG 严格按交付清单 §三 固化（viewBox 0 0 312 84）
         =========================================================== -->
    <div class="gem-toolbar">
      <!-- 拱形轨道背景（装饰性 SVG，对辅助阅读隐藏） -->
      <svg
        class="gem-toolbar-bg"
        viewBox="0 0 312 84"
        preserveAspectRatio="xMidYMid meet"
        aria-hidden="true"
        role="presentation"
      >
        <path
          d="M 18 18
             L 84 18
             C 116 18, 126 6, 156 4
             C 186 6, 196 18, 216 18
             L 294 18
             C 302 18, 312 26, 312 34
             L 312 50
             C 312 58, 302 66, 294 66
             L 216 66
             C 196 66, 186 78, 156 80
             C 126 78, 116 66, 84 66
             L 18 66
             C 0 66, 0 58, 0 50
             L 0 34
             C 0 26, 10 18, 18 18 Z"
          fill="url(#g-rail)"
          stroke="rgba(255,255,255,0.85)"
          stroke-width="1.2"
        />
      </svg>
      <div class="gem-row">
        <!-- 1. 表情按钮：高端 SVG emoji 图标 -->
        <button
          class="glass-btn"
          :class="{ 'is-active-emoji': showEmojiPanel }"
          title="表情"
          aria-label="表情"
          @click="handleEmoji"
        >
          <svg viewBox="0 0 24 24" fill="none">
            <circle cx="12" cy="12" r="9" fill="url(#g-emoji)" />
            <ellipse cx="12" cy="6" rx="6" ry="2.5" fill="url(#g-highlight)" />
            <ellipse cx="6.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)" />
            <ellipse cx="17.5" cy="14" rx="1.5" ry="1" fill="url(#g-emoji-blush)" />
            <ellipse cx="8.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b" />
            <ellipse cx="15.5" cy="11" rx="1.4" ry="1.6" fill="#1e1b4b" />
            <circle cx="8.9" cy="10.4" r="0.5" fill="white" />
            <circle cx="15.9" cy="10.4" r="0.5" fill="white" />
            <path
              d="M8 15 Q12 18 16 15"
              fill="none"
              stroke="#1e1b4b"
              stroke-width="1.6"
              stroke-linecap="round"
            />
          </svg>
        </button>

        <!-- 2. 文件按钮：高端 SVG 文件图标 -->
        <button
          class="glass-btn"
          title="文件"
          aria-label="文件"
          @click="handleFile"
        >
          <svg viewBox="0 0 24 24" fill="none">
            <path
              d="M4 2 L14 2 L20 8 L20 20 L4 20 Z"
              fill="url(#g-doc-body)"
              stroke="#818cf8"
              stroke-width="0.8"
              stroke-linejoin="round"
            />
            <path
              d="M14 2 L14 8 L20 8"
              fill="url(#g-doc-fold)"
              stroke="#818cf8"
              stroke-width="0.8"
              stroke-linejoin="round"
            />
            <ellipse cx="10" cy="4" rx="5" ry="0.8" fill="url(#g-highlight)" />
            <rect x="7" y="11.5" width="10" height="0.8" rx="0.4" fill="url(#g-doc-text)" />
            <rect
              x="7"
              y="14"
              width="8"
              height="0.8"
              rx="0.4"
              fill="url(#g-doc-text)"
              opacity="0.7"
            />
            <rect
              x="7"
              y="16.5"
              width="6"
              height="0.8"
              rx="0.4"
              fill="url(#g-doc-text)"
              opacity="0.5"
            />
          </svg>
        </button>

        <!-- 3. 人工坐席按钮（居中，60px，v1.9 增大 50%）：图片头像 + 5 色徽标 -->
        <button
          class="agent-btn gem"
          :class="[agentBtnClass, callAgentBtnClass]"
          :title="callAgentBtnTitle"
          :aria-label="callAgentBtnTitle"
          :disabled="callAgentState === 'disabled'"
          @click="handleCallAgentClick"
        >
          <img
            :src="agentAvatar"
            class="agent-btn__avatar"
            alt="人工坐席"
          />
          <span class="agent-badge" :class="agentBadgeClass" aria-hidden="true"></span>
        </button>

        <!-- 4. 语音按钮（三态：默认 / 录音 / 已识别）— 高端 SVG 话筒图标 -->
        <button
          v-if="showVoiceButton"
          class="glass-btn"
          :class="voiceBtnClass"
          :title="isTranscribing ? '正在识别...' : (isVoiceActive ? '点击停止' : '语音输入 (Ctrl+D)')"
          :disabled="isTranscribing"
          @mousedown.prevent="handleVoiceToggle"
          @click.prevent="handleVoiceToggle"
          @touchstart.prevent="handleVoiceToggle"
        >
          <svg viewBox="0 0 24 24" fill="none">
            <rect x="8" y="2" width="8" height="13" rx="4" fill="url(#g-mic-body)" />
            <rect x="9" y="3" width="2" height="11" rx="1" fill="url(#g-mic-shine)" />
            <line
              x1="10.5"
              y1="6"
              x2="10.5"
              y2="11"
              stroke="white"
              stroke-width="0.3"
              opacity="0.4"
            />
            <line
              x1="12"
              y1="5"
              x2="12"
              y2="12"
              stroke="white"
              stroke-width="0.3"
              opacity="0.4"
            />
            <line
              x1="13.5"
              y1="6"
              x2="13.5"
              y2="11"
              stroke="white"
              stroke-width="0.3"
              opacity="0.4"
            />
            <path
              d="M3 12 Q3 18 12 18 Q21 18 21 12"
              fill="none"
              stroke="url(#g-mic-body)"
              stroke-width="2"
              stroke-linecap="round"
            />
            <line
              x1="12"
              y1="18"
              x2="12"
              y2="22"
              stroke="url(#g-mic-body)"
              stroke-width="2"
              stroke-linecap="round"
            />
            <line
              x1="8"
              y1="22"
              x2="16"
              y2="22"
              stroke="url(#g-mic-body)"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
        </button>

        <!-- 5. 群聊按钮（v1.9 新增）：3 人小组 + 1 人前景 SVG 图标 -->
        <button
          class="glass-btn"
          title="群聊"
          aria-label="群聊"
          @click="handleGroupChat"
        >
          <svg viewBox="0 0 24 24" fill="none">
            <circle cx="8" cy="9" r="2.2" fill="url(#g-group)" />
            <path d="M5 16 Q5 13 8 13 Q11 13 11 16 Z" fill="url(#g-group)" />
            <circle cx="16" cy="9" r="2.2" fill="url(#g-group)" />
            <path d="M13 16 Q13 13 16 13 Q19 13 19 16 Z" fill="url(#g-group)" />
            <circle cx="12" cy="10.5" r="2.8" fill="url(#g-group-strong)" />
            <path d="M8.5 18.5 Q8.5 14 12 14 Q15.5 14 15.5 18.5 Z" fill="url(#g-group-strong)" />
          </svg>
        </button>
      </div>
    </div>

    <!-- 输入行：输入框 + 发送按钮 -->
    <div class="input-bar__row">
      <!-- 文本输入框 — 默认3行，自适应内容高度 -->
      <van-field
        ref="inputFieldRef"
        v-model="inputText"
        class="input-bar__field"
        placeholder="请输入消息..."
        type="textarea"
        :autosize="{ minHeight: 54, maxHeight: 200 }"
        rows="3"
        :disabled="!store.isLoggedIn"
        @keydown.enter="handleEnterKey"
        @paste="handlePaste"
      />

      <!-- 发送按钮：右下角绝对定位 -->
      <van-button
        class="input-bar__send-btn"
        type="primary"
        size="small"
        :disabled="!canSend"
        :loading="store.loading"
        @click="handleSend"
      >
        发送
      </van-button>
    </div>

    <!-- v1.2 表情面板：位于工具栏与输入行之间，使用 slideUp 动画 -->
    <div v-if="showEmojiPanel" class="emoji-panel">
      <div class="emoji-panel__grid">
        <button
          v-for="emoji in commonEmojis"
          :key="emoji"
          class="emoji-panel__item"
          @click="onEmojiClick(emoji)"
        >{{ emoji }}</button>
      </div>
    </div>

    <!-- 语音状态提示条（百度ASR内联录音/识别时显示） -->
    <div v-if="isVoiceActive && voiceStrategy === 'baidu'" class="input-bar__voice-status">
      <span v-if="isTranscribing">正在识别语音...</span>
      <span v-else>正在语音输入... 点击⏹停止</span>
    </div>

    <!-- 表情面板遮罩（点击外部关闭） -->
    <div v-if="showEmojiPanel" class="emoji-panel__overlay" @click="showEmojiPanel = false"></div>

    <!-- 隐藏的文件输入框（文件上传用，由工具栏按钮触发） -->
    <input
      ref="fileInputRef"
      type="file"
      style="display: none"
      @change="handleFileSelect"
    />
  </div>
</template>

<script setup lang="ts">
/**
 * InputBar 输入栏组件（v1.3 视觉重塑）
 * 布局：[玻璃拟态工具栏（4 按钮）] [表情面板] [输入行：输入框 + 发送按钮]
 * 工具栏：emoji（SVG 表情）/ file（SVG 文件）/ voice（SVG 话筒）/ agent（图片头像 + 5 色徽标）
 * 坐席按钮：5 色徽标 + handleCallAgentClick 路由 6 态动作
 * 输入框固定底部，默认3行可见，高度动态适应
 * 顶部拖拽手柄可手动调节输入栏整体高度
 * 支持粘贴图片上传（Ctrl+V）和文件选择上传
 */
import { ref, computed, nextTick, onMounted, onUnmounted } from 'vue'
import { showToast } from 'vant'
import { storeToRefs } from 'pinia'
import { useConversationStore } from '@/stores/conversation'
import { uploadFile } from '@/api/upload'
import { useWecomVoice } from '@/composables/useWecomVoice'
import { useAudioRecorder } from '@/composables/useAudioRecorder'
import { transcribeAudio } from '@/api/voice'

import {
  computeCallAgentState,
  computeCallAgentBtnText,
  computeCallAgentBtnTitle,
  type CallAgentState,
} from './inputBarCallAgentState'
import {
  computeIntegrationBtnClass,
  computeCallAction,
} from './integrationZoneLogic'

// ============================================================================
// 工具函数：安全提取错误详情（防止 [object Object]）
// ============================================================================
/**
 * 将 error.response.data.detail 安全转换为字符串
 * FastAPI 422 时 detail 是数组，直接拼接会变成 "[object Object]"
 */
function formatErrorDetail(detail: any): string {
  if (!detail) return ''
  if (typeof detail === 'string') return detail
  if (Array.isArray(detail)) {
    // FastAPI 验证错误：取每个元素的 msg 和 loc
    return detail.map((d: any) => {
      if (d.loc && d.msg) return `${d.loc.slice(1).join('.')}: ${d.msg}`
      if (d.msg) return d.msg
      return JSON.stringify(d)
    }).join('; ')
  }
  if (typeof detail === 'object') return JSON.stringify(detail)
  return String(detail)
}

const store = useConversationStore()

// ============================================================================
// 紧急关键词列表（v1.3 保留 — callAgentState 的依赖项）
// ============================================================================
const URGENT_KEYWORDS: RegExp[] = [
  /紧急/i,
  /urgent/i,
  /崩溃/i,
  /无法打开/i,
  /登不上/i,
  /登录不上/i,
  /故障/i,
]

/** 从 store 解构响应式状态（消息/坐席在线/当前会话） */
const { messages, agentOnline, currentConversation } = storeToRefs(store)

/**
 * 是否含紧急关键词（computed）
 * 扫描所有员工消息，任一命中关键词 → true
 */
const hasUrgentKeywords = computed<boolean>(() =>
  messages.value.some(msg =>
    msg.message_type === 'employee' &&
    URGENT_KEYWORDS.some(re => re.test(msg.content))
  )
)

/** 当前会话的 6 态坐席入口状态。 */
const callAgentState = computed<CallAgentState>(() =>
  computeCallAgentState({
    currentConversation: currentConversation.value,
    agentOnline: agentOnline.value,
    canReopen: store.canReopen,
    canCallAgent: store.canCallAgent,
    hasUrgentKeywords: hasUrgentKeywords.value,
  })
)

/** 坐席按钮的 6 态 modifier class。 */
const callAgentBtnClass = computed<Record<string, boolean>>(() =>
  computeIntegrationBtnClass(callAgentState.value)
)

/** 头像按钮状态 class（用于 5 色徽标及紧急态动画）。 */
const agentBtnClass = computed<Record<string, boolean>>(() => ({
  'is-online': callAgentState.value === 'active',
  'is-urgent': callAgentState.value === 'urgent',
  'is-waiting': callAgentState.value === 'waiting',
  'is-offline': callAgentState.value === 'disabled',
  'is-end': callAgentState.value === 'end' || callAgentState.value === 'reopen',
}))

/** 坐席头像右下角状态徽标 class。 */
const agentBadgeClass = computed<Record<string, boolean>>(() => ({
  'is-online': callAgentState.value === 'active',
  'is-urgent': callAgentState.value === 'urgent',
  'is-waiting': callAgentState.value === 'waiting',
  'is-offline': callAgentState.value === 'disabled',
  'is-end': callAgentState.value === 'end' || callAgentState.value === 'reopen',
}))

/** 坐席头像资源（public 目录通过根路径访问）。 */
const agentAvatar = '/avatars/agent.png'

const callAgentBtnTitle = computed<string>(() =>
  computeCallAgentBtnTitle(callAgentState.value, agentOnline.value)
)

/** 输入框文本 */
const inputText = ref<string>('')

/** 输入框组件引用（用于获取 DOM 元素） */
const inputFieldRef = ref<any>(null)

/** 隐藏文件输入框 DOM 引用（用于触发系统文件选择器） */
const fileInputRef = ref<HTMLInputElement | null>(null)

/** 是否可以发送消息（输入框有内容且未在加载中） */
const canSend = computed(() => {
  return inputText.value.trim().length > 0 && !store.loading && store.isLoggedIn
})

/** 是否正在拖拽调节输入栏高度 */
const isInputResizing = ref<boolean>(false)

/** 表情面板是否可见 */
const showEmojiPanel = ref<boolean>(false)

// ============================================================================
// 语音识别功能（双策略：企微 JS-SDK + 百度ASR）
// ============================================================================
const {
  state: voiceState,
  init: initVoice,
  startRecording,
  stopAndTranslate,
  isSupported: isWecomVoiceSupported,
} = useWecomVoice()

/**
 * 语音策略：'wecom'（企微JS-SDK）| 'baidu'（百度ASR）| 'none'（不支持）
 */
const voiceStrategy = computed<'wecom' | 'baidu' | 'none'>(() => {
  if (isWecomVoiceSupported()) return 'wecom'
  if (navigator.mediaDevices && typeof navigator.mediaDevices.getUserMedia === 'function') return 'baidu'
  const ua = navigator.userAgent
  const isWxwork = /wxwork/i.test(ua)
  const isMobile = /Mobile|Android|iPhone|iPad|iPod/i.test(ua)
  const isMac = /Macintosh|Mac OS X/i.test(ua)
  if (isWxwork && !isMobile && !isMac) return 'baidu'
  return 'none'
})

/** 是否显示语音按钮（任一策略可用即显示） */
const showVoiceButton = computed(() => voiceStrategy.value !== 'none')

// 百度ASR 录音控制器
const baiduRecorder = useAudioRecorder()

/** 百度ASR 是否正在录音（响应式，绑定到模板） */
const isBaiduRecording = computed(() => baiduRecorder.isRecording.value)

/** 百度ASR 是否正在识别中（录音停止后、上传后端识别期间） */
const isTranscribing = ref<boolean>(false)

/**
 * 🆕 v1.2:语音识别成功短暂显示状态（1.5s 后自动回默认）
 * 录音停止 → 后端识别成功 → 设为 true → 1.5s 后自动回 false
 */
const voiceRecognitionCompleted = ref<boolean>(false)

/**
 * 语音按钮状态（default / recording / recognized）
 * 优先级：recognized > recording > default
 */
const voiceBtnState = computed<'default' | 'recording' | 'recognized'>(() => {
  if (voiceRecognitionCompleted.value) return 'recognized'
  if (isVoiceActive.value) return 'recording'
  return 'default'
})

/** 语音按钮 3 态的 class（is-voice-default / is-voice-recording / is-voice-recognized） */
const voiceBtnClass = computed<Record<string, boolean>>(() => ({
  'is-voice-default': voiceBtnState.value === 'default',
  'is-voice-recording': voiceBtnState.value === 'recording',
  'is-voice-recognized': voiceBtnState.value === 'recognized',
}))

/**
 * 语音是否激活中（录音中或识别中），用于按钮 UI 状态
 */
const isVoiceActive = computed(() => {
  if (voiceStrategy.value === 'wecom') return voiceState.isRecording
  if (voiceStrategy.value === 'baidu') return isBaiduRecording.value || isTranscribing.value
  return false
})

/** 识别结果是否需要追加前缀空格（如果输入框已有内容，加空格分隔） */
function shouldAddSpaceBefore(text: string): boolean {
  return text.length > 0 && !text.endsWith(' ') && !text.endsWith('\n')
}

// ============================================================================
// 生命周期：Document 级别粘贴监听（修复 van-field @paste 不触发文件粘贴的问题）
// ============================================================================
onMounted(() => {
  document.addEventListener('paste', handleDocPaste)
  document.addEventListener('keydown', handleGlobalKeydown)
  if (isWecomVoiceSupported()) {
    initVoice().catch((err: any) => {
      console.warn('[InputBar] 企微 JS-SDK 初始化失败:', err)
    })
  }
})

onUnmounted(() => {
  document.removeEventListener('paste', handleDocPaste)
  document.removeEventListener('keydown', handleGlobalKeydown)
  if (baiduRecorder.isRecording.value) {
    baiduRecorder.stop()
  }
})

/**
 * Document 级别粘贴处理（备用方案）
 * 做什么：捕获 van-field @paste 未处理的文件粘贴
 */
async function handleDocPaste(event: ClipboardEvent): Promise<void> {
  const target = event.target as HTMLElement
  if (target.tagName === 'TEXTAREA' || target.isContentEditable) return

  const items = event.clipboardData?.items
  if (!items) return

  for (const item of Array.from(items)) {
    if (item.kind === 'file') {
      event.preventDefault()
      const file = item.getAsFile()
      if (!file) continue

      if (file.type.startsWith('image/')) {
        await handleImageUpload(file)
      } else {
        await handleFileUpload(file)
      }
      return
    }
  }
}

/**
 * 常用表情列表（8行x8列 = 64 个常用表情）
 */
const commonEmojis = [
  '😀','😃','😄','😁','😆','😅','🤣','😂',
  '🙂','😊','😇','🥰','😍','🤩','😘','😗',
  '😚','😙','😋','😛','😜','🤪','😝','🤑',
  '🤗','🤭','🤫','🤔','🤐','🤨','😐','😑',
  '😶','😏','😒','🙄','😬','😮','🤯','😲',
  '😳','🥺','😢','😭','😤','😠','😡','🤬',
  '👍','👎','👏','🙌','🤝','💪','✌️','🤞',
  '❤️','🧡','💛','💚','💙','💜','💯','✅',
]

/**
 * 选择表情后插入到输入框
 */
function onEmojiClick(emoji: string): void {
  inputText.value += emoji
  showEmojiPanel.value = false
  nextTick(() => {
    const el = inputFieldRef.value?.$el?.querySelector('textarea') as HTMLTextAreaElement | null
    el?.focus()
  })
}

// ============================================================================
// 消息发送
// ============================================================================

/**
 * 处理 Enter 键
 * 桌面端 Enter 发送，Shift+Enter 换行
 * 移动端不拦截 Enter（让系统默认行为处理）
 */
function handleEnterKey(event: KeyboardEvent): void {
  const isMobile = /Android|iPhone|iPad|iPod/i.test(navigator.userAgent)
  if (isMobile) return

  if (!event.shiftKey) {
    event.preventDefault()
    handleSend()
  }
}

/**
 * 发送消息
 */
async function handleSend(): Promise<void> {
  const content = inputText.value.trim()
  if (!content || store.loading) return

  inputText.value = ''
  await store.sendNewMessage(content)
}

// ============================================================================
// 文件/图片上传
// ============================================================================

/**
 * 处理粘贴事件
 */
async function handlePaste(event: ClipboardEvent): Promise<void> {
  const items = event.clipboardData?.items
  if (!items) return

  for (const item of Array.from(items)) {
    if (item.kind === 'file') {
      event.preventDefault()
      const file = item.getAsFile()
      if (!file) continue

      if (file.type.startsWith('image/')) {
        await handleImageUpload(file)
      } else {
        await handleFileUpload(file)
      }
      return
    }
  }
}

/**
 * 上传图片并发送图片消息
 */
async function handleImageUpload(file: File | Blob): Promise<void> {
  try {
    showToast('图片上传中...')
    const result = await uploadFile(file)
    const fileName = file instanceof File ? file.name : '截图'
    await store.sendNewMessage(`[图片] ${fileName}`, {
      msg_type: 'image',
      media_url: result.url,
      file_name: result.filename,
      file_size: result.file_size,
    })
    showToast('图片发送成功')
  } catch (error: any) {
    console.error('图片上传失败:', error)
    showToast(
      formatErrorDetail(error?.response?.data?.detail) ||
      error?.message ||
      '图片上传失败，请重试'
    )
  }
}

/**
 * 上传文件并发送文件消息
 */
async function handleFileUpload(file: File | Blob): Promise<void> {
  try {
    const fileName = file instanceof File ? file.name : '文件'
    showToast(`文件上传中: ${fileName}`)
    const result = await uploadFile(file)
    await store.sendNewMessage(`[文件] ${result.filename}`, {
      msg_type: 'file',
      media_url: result.url,
      file_name: result.filename,
      file_size: result.file_size,
    })
    showToast('文件发送成功')
  } catch (error: any) {
    console.error('文件上传失败:', error)
    showToast(
      formatErrorDetail(error?.response?.data?.detail) ||
      error?.message ||
      '文件上传失败，请重试'
    )
  }
}

/**
 * 处理文件选择上传
 */
async function handleFileSelect(event: Event): Promise<void> {
  const input = event.target as HTMLInputElement
  const files = input.files
  if (!files || files.length === 0) return

  for (const file of Array.from(files)) {
    try {
      showToast(`正在上传: ${file.name}`)
      const result = await uploadFile(file)
      showToast(`${file.name} 上传成功`)
      console.log('[InputBar] 文件上传成功:', result.url)
    } catch (error: any) {
      console.error('文件上传失败:', error)
      showToast(`${file.name} 上传失败`)
    }
  }

  input.value = ''
}

/**
 * 处理表情按钮点击
 * 弹出/收起简易表情选择器（常用 Emoji 面板）
 */
function handleEmoji(): void {
  showEmojiPanel.value = !showEmojiPanel.value
}

/**
 * 处理文件按钮点击
 * 触发文件选择器（不限类型）— v1.2 直接进系统选择器，不展开面板
 */
function handleFile(): void {
  if (fileInputRef.value) {
    fileInputRef.value.accept = ''
    fileInputRef.value.multiple = true
    fileInputRef.value.click()
  }
}

/**
 * 🆕 v1.9:处理群聊按钮点击
 * 当前 store 暂无 group chat action，群聊功能开发中，先 toast 提示占位
 * 后续接入真实群聊会话时，把 toast 替换为 store.startGroupChat() 即可
 */
function handleGroupChat(): void {
  showToast('群聊功能开发中')
}

/**
 * 处理坐席头像点击，并将 6 态动作路由到会话 store。
 * InputBar 是 v1.3 唯一坐席入口，不向 ChatPanel emit。
 */
async function handleCallAgentClick(): Promise<void> {
  const action = computeCallAction(callAgentState.value)
  try {
    switch (action) {
      case 'callAgent':
        await store.shakeAgent()
        return
      case 'cancelQueue':
        await store.cancelQueue()
        return
      case 'endConversation':
        await store.closeCurrentConversation()
        return
      case 'reopenConversation':
        await store.reopenCurrentConversation()
        return
      case 'none':
        return
    }
  } catch (error: any) {
    console.error('[InputBar] 坐席操作失败:', error)
    showToast(error?.message || '坐席操作失败，请稍后重试')
  }
}

// ============================================================================
// 语音识别交互
// ============================================================================

/**
 * 处理语音按钮点击 / Ctrl+D 快捷键（双策略）
 */
async function handleVoiceToggle(event?: Event): Promise<void> {
  event?.preventDefault()
  event?.stopPropagation()

  if (voiceStrategy.value === 'none') return

  if (voiceStrategy.value === 'wecom') {
    // 企微 JS-SDK 策略（手机端企微）
    try {
      if (voiceState.isRecording) {
        const text = await stopAndTranslate()
        if (text) {
          if (shouldAddSpaceBefore(inputText.value)) {
            inputText.value += ' '
          }
          inputText.value += text
          // 🆕 v1.2:识别成功短暂显示绿色对勾（1.5s 回默认）
          markVoiceRecognized()
          showToast('语音识别完成')
        } else {
          showToast('未识别到语音内容')
        }
      } else {
        await startRecording()
        showToast('正在录音，点击停止')
      }
    } catch (error: any) {
      const errMsg = voiceState.error || error?.message || '语音识别失败'
      showToast(errMsg)
      console.error('[InputBar] 企微语音识别错误:', error)
    }
  } else if (voiceStrategy.value === 'baidu') {
    // 百度ASR 策略（PC/Mac 端）
    if (isBaiduRecording.value) {
      const blob = baiduRecorder.stop()

      if (blob.size < 1600) {
        showToast('录音过短，请说更多内容')
        return
      }

      isTranscribing.value = true
      try {
        const result = await transcribeAudio(blob)
        if (result.error) {
          showToast(result.error)
        } else if (result.text) {
          if (shouldAddSpaceBefore(inputText.value)) {
            inputText.value += ' '
          }
          inputText.value += result.text
          // 🆕 v1.2:识别成功短暂显示绿色对勾（1.5s 回默认）
          markVoiceRecognized()
          showToast('语音识别完成')
        } else {
          showToast('未识别到语音内容')
        }
      } catch (err: any) {
        showToast(err?.message || '语音识别失败')
        console.error('[InputBar] 百度ASR识别错误:', err)
      } finally {
        isTranscribing.value = false
      }
    } else {
      try {
        await baiduRecorder.start()
        showToast('开始语音输入')
      } catch (err: any) {
        showToast(err?.message || '录音启动失败')
        console.error('[InputBar] 百度录音启动失败:', err)
      }
    }
  }
}

/**
 * 🆕 v1.2:语音识别完成短暂显示绿色对勾（1.5s 后回默认态）
 */
function markVoiceRecognized(): void {
  voiceRecognitionCompleted.value = true
  setTimeout(() => {
    voiceRecognitionCompleted.value = false
  }, 1500)
}

/**
 * 全局键盘快捷键处理（Ctrl+D 语音识别）
 */
function handleGlobalKeydown(event: KeyboardEvent): void {
  if (event.ctrlKey && (event.key === 'd' || event.key === 'D')) {
    event.preventDefault()
    if (!showVoiceButton.value) return
    handleVoiceToggle()
  }
}

// ============================================================================
// 拖拽调节输入栏高度
// ============================================================================

/**
 * 拖拽开始：记录初始 Y 坐标
 * 向上拖拽增大输入栏高度，向下拖拽减小
 */
function handleInputResizeStart(event: MouseEvent): void {
  isInputResizing.value = true

  const startY = event.clientY
  const inputBar = (event.target as HTMLElement).closest('.input-bar') as HTMLElement
  const startHeight = inputBar ? inputBar.offsetHeight : 100

  function handleMouseMove(e: MouseEvent): void {
    if (!isInputResizing.value) return

    const deltaY = startY - e.clientY
    let newHeight = startHeight + deltaY

    newHeight = Math.max(100, Math.min(400, newHeight))

    if (inputBar) {
      inputBar.style.height = `${newHeight}px`
      inputBar.style.flexShrink = '0'
    }
  }

  function handleMouseUp(): void {
    isInputResizing.value = false
    document.removeEventListener('mousemove', handleMouseMove)
    document.removeEventListener('mouseup', handleMouseUp)
    document.body.style.cursor = ''
    document.body.style.userSelect = ''
  }

  document.body.style.cursor = 'row-resize'
  document.body.style.userSelect = 'none'
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}
</script>

<style scoped>
/* ==========================================================================
   输入栏容器（v1.9 三区融合关键）
   - 背景透明 → 让 ChatPanel 的渐变背景透出，三区（消息区/工具栏/输入区）连续
   - border-top 保留（仍属容器 chrome，与外部消息区分隔）；内部子元素无 border
   ========================================================================== */
.input-bar {
  background-color: transparent;
  border-top: 1px solid var(--border-color);
  padding: 0 12px 8px;
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
  flex-shrink: 0;
  position: relative;
}

/* v1.9 键盘可达性：所有按钮可见 focus 蓝环 */
.glass-btn:focus-visible,
.agent-btn:focus-visible {
  outline: 2px solid #6366f1;
  outline-offset: 2px;
}

/* ==========================================================================
   v1.9 窄屏 fallback（≤480px）
   - 拱形轨道在窄屏易走样，隐藏 SVG、改胶囊样式
   - 按钮尺寸适度缩小（玻璃按钮 36px / 坐席 52px）
   ========================================================================== */
@media (max-width: 480px) {
  .gem-toolbar {
    height: 56px;
    padding: 0 12px;
    margin: 0 auto 4px;
  }
  .gem-toolbar-bg {
    display: none;
  }
  .gem-row {
    background: rgba(255, 255, 255, 0.55);
    backdrop-filter: blur(28px) saturate(180%);
    -webkit-backdrop-filter: blur(28px) saturate(180%);
    border: 1px solid rgba(255, 255, 255, 0.7);
    border-radius: 20px;
    padding: 6px 12px;
    box-shadow:
      0 1px 0 rgba(255, 255, 255, 0.9) inset,
      0 -1px 0 rgba(99, 102, 241, 0.08) inset,
      0 2px 4px rgba(99, 102, 241, 0.05),
      0 8px 16px rgba(99, 102, 241, 0.08);
  }
  .gem-row .glass-btn {
    width: 36px;
    height: 36px;
  }
  .gem-row .agent-btn.gem {
    width: 52px;
    height: 52px;
    margin: 0 4px;
  }
}

/* ==========================================================================
   v1.9 深色模式预案（prefers-color-scheme: dark）
   - 当前为预留骨架，色彩需后续设计 token 全局对齐
   ========================================================================== */
@media (prefers-color-scheme: dark) {
  .input-bar {
    border-top-color: rgba(255, 255, 255, 0.1);
  }
  .gem-row {
    /* 窄屏 fallback 启用时（≤480px）才生效 */
  }
  /* 在窄屏（≤480px）下，gem-row 会变成胶囊背景，深色模式加深 */
  @media (max-width: 480px) {
    .gem-row {
      background: rgba(30, 30, 40, 0.55);
      border-color: rgba(255, 255, 255, 0.15);
    }
  }
  /* 输入框深色模式 */
  .input-bar__field {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text-primary);
  }
}

/* ── 拖拽手柄 ── */
.input-bar__resize-handle {
  height: 8px;
  cursor: row-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 -12px;
  padding: 2px 0;
}

.input-bar__resize-track {
  width: 40px;
  height: 3px;
  border-radius: 2px;
  background-color: var(--border-color);
  transition: background-color 0.2s, width 0.2s;
}

.input-bar__resize-handle:hover .input-bar__resize-track {
  background-color: var(--accent);
  width: 60px;
}

/* ==========================================================================
   v1.9 圆润拱形工具栏 — InputBar 内顶部居中独立行
   - 位置：resize-handle 之后，emoji-panel / input-bar__row 之前
   - 容器 .gem-toolbar 透明，让消息区背景透出（v1.9 三区融合关键）
   - .gem-toolbar-bg 拱形轨道 SVG（viewBox 0 0 312 84，宽穹顶 x 84..216）
   - 5 按钮：emoji / 文件 / 坐席(60px 居中) / 语音 / 群聊
   - focus-visible 蓝环（键盘可达性）
   - @media (max-width: 480px) 窄屏 fallback：隐藏 SVG、改胶囊
   - @media (prefers-color-scheme: dark) 深色模式预留
   ========================================================================== */
.gem-toolbar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  width: fit-content;
  height: 84px;
  margin: 0 auto 4px;
  background: transparent;
}

.gem-toolbar-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
  overflow: visible;
}

.gem-row {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

/* 旧 .glass-toolbar 兼容层：保留 class 以防外部依赖挂样式，但不渲染（v1.9 不再使用） */
.glass-toolbar {
  /* v1.9 不再使用此容器类，CSS 留空避免旧规则冲突 */
  display: none;
}

/* ==========================================================================
   40px 圆形玻璃按钮（emoji / file / voice）
   ========================================================================== */
.glass-btn {
  width: 40px;
  height: 40px;
  border: 1px solid rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  -webkit-tap-highlight-color: transparent;
  position: relative;
  z-index: 2;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 -1px 0 rgba(0, 0, 0, 0.04) inset,
    0 1px 2px rgba(0, 0, 0, 0.04),
    0 2px 4px rgba(0, 0, 0, 0.04);
  padding: 0;
  outline: none;
  overflow: visible;
}

.glass-btn:hover {
  background: rgba(255, 255, 255, 0.75);
  transform: translateY(-1px) scale(1.06);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 1) inset,
    0 -1px 0 rgba(0, 0, 0, 0.04) inset,
    0 2px 4px rgba(0, 0, 0, 0.06),
    0 8px 16px rgba(99, 102, 241, 0.15);
}

.glass-btn:active {
  transform: translateY(0) scale(0.95);
}

.glass-btn svg {
  width: 22px;
  height: 22px;
  display: block;
  pointer-events: none;
}

/* ── 表情按钮激活态（黄橙渐变） ── */
.glass-btn.is-active-emoji {
  background: linear-gradient(135deg, rgba(251, 191, 36, 0.9) 0%, rgba(245, 158, 11, 0.9) 100%);
  border-color: rgba(255, 255, 255, 0.4);
}

.glass-btn.is-active-emoji::before {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.35) 0%, transparent 50%);
  pointer-events: none;
}

/* ── 语音按钮 3 态（颜色+形态双变） ── */
.glass-btn.is-voice-recording {
  background: linear-gradient(135deg, rgba(239, 68, 68, 0.95) 0%, rgba(220, 38, 38, 0.95) 100%);
  border-color: rgba(255, 255, 255, 0.4);
  animation: recordingPulse 1.5s ease-in-out infinite;
}

@keyframes recordingPulse {
  0%, 100% {
    box-shadow:
      0 0 0 0 rgba(239, 68, 68, 0),
      0 1px 0 rgba(255, 255, 255, 0.9) inset;
  }
  50% {
    box-shadow:
      0 0 0 6px rgba(239, 68, 68, 0.15),
      0 1px 0 rgba(255, 255, 255, 0.9) inset;
  }
}

.glass-btn.is-voice-recognized {
  background: linear-gradient(135deg, rgba(16, 185, 129, 0.95) 0%, rgba(5, 150, 105, 0.95) 100%);
  border-color: rgba(255, 255, 255, 0.4);
}

.glass-btn.is-voice-default {
  /* 默认态：透明玻璃（无额外样式） */
}

.glass-btn:disabled {
  opacity: 0.7;
  cursor: not-allowed;
  animation: none;
}

/* ==========================================================================
   44px 坐席头像按钮（图片头像 + 紫粉渐变边框）
   v1.3 class: .agent-btn（原 .input-bar__agent 重命名）
   v1.9 增强：.agent-btn.gem 修饰符把坐席放大到 60px（较 40px 工具图标大 50%）
   ========================================================================== */
.agent-btn {
  width: 44px;
  height: 44px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 50%;
  position: relative;
  z-index: 2;
  overflow: visible;
  cursor: pointer;
  background: linear-gradient(135deg, #6366f1, #a855f7 50%, #ec4899) padding-box;
  transition: transform 0.25s ease, opacity 0.2s ease, box-shadow 0.25s ease;
  -webkit-tap-highlight-color: transparent;
  outline: none;
}

/* v1.9 gem 修饰符：坐席按钮增大到 60px，居中、不探出、无光晕 */
.gem-row .agent-btn.gem {
  width: 60px;
  height: 60px;
  margin: 0 6px;
  z-index: 3;
  box-shadow: none;
}

.agent-btn::before {
  content: "";
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1 0%, #a855f7 50%, #ec4899 100%);
  z-index: -1;
}

.agent-btn:hover {
  transform: translateY(-1px) scale(1.05);
}

.agent-btn:active {
  transform: scale(0.95);
}

.agent-btn:disabled {
  cursor: not-allowed;
  opacity: 0.72;
}

.agent-btn__avatar {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 15%;
}

/* 6 态 modifier（沿用 v1.2 helper 契约） */
.agent-btn.is-online {
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
}

.agent-btn.is-urgent {
  box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.6), 0 4px 12px rgba(239, 68, 68, 0.3);
  animation: agentUrgentPulse 1.2s ease-in-out infinite;
}

.agent-btn.is-waiting {
  box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.6);
}

.agent-btn.is-end {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.6);
}

.agent-btn.is-offline {
  opacity: 0.4;
  filter: grayscale(0.7);
}

@keyframes agentUrgentPulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.6), 0 4px 12px rgba(239, 68, 68, 0.3); }
  50% { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.4), 0 4px 16px rgba(239, 68, 68, 0.5); }
}

/* 兼容 IntegrationZone computeIntegrationBtnClass 输出的 6 态 class（call-agent-btn--*） */
.agent-btn.call-agent-btn--active {
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
}
.agent-btn.call-agent-btn--urgent {
  animation: agentUrgentPulse 1.2s ease-in-out infinite;
}
.agent-btn.call-agent-btn--waiting {
  box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.6);
}
.agent-btn.call-agent-btn--end,
.agent-btn.call-agent-btn--reopen {
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.6);
}
.agent-btn.call-agent-btn--disabled {
  opacity: 0.4;
  filter: grayscale(0.7);
  cursor: not-allowed;
}

/* ==========================================================================
   坐席头像右下角状态徽标 — 5 色（is-online / is-urgent / is-waiting / is-offline / is-end）
   ========================================================================== */
.agent-badge {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 12px;
  height: 12px;
  border: 2px solid #fff;
  border-radius: 50%;
  z-index: 3;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

.agent-badge.is-online { background: #10b981; }
.agent-badge.is-urgent { background: #ef4444; }
.agent-badge.is-waiting { background: #f59e0b; }
.agent-badge.is-offline { background: #9ca3af; }
.agent-badge.is-end { background: #3b82f6; }

.agent-btn.is-urgent .agent-badge {
  animation: badgePulse 1.5s ease-in-out infinite;
}

@keyframes badgePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6), 0 1px 2px rgba(0, 0, 0, 0.2); }
  50% { box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.3), 0 1px 2px rgba(0, 0, 0, 0.2); }
}

/* ========================================================================
   表情面板：从工具栏方向上滑展开（slideUp）
   ======================================================================== */
.emoji-panel {
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(20px) saturate(180%);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(99, 102, 241, 0.15);
  border-radius: 14px;
  padding: 12px;
  margin-bottom: 8px;
  box-shadow: 0 -4px 16px rgba(99, 102, 241, 0.1);
  animation: slideUp 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  overflow: hidden;
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(20px);
    max-height: 0;
  }
  to {
    opacity: 1;
    transform: translateY(0);
    max-height: 400px;
  }
}

.emoji-panel__grid {
  display: grid;
  grid-template-columns: repeat(8, 36px);
  gap: 4px;
  justify-content: center;
}

.emoji-panel__item {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  border: none;
  background: transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.15s;
  -webkit-tap-highlight-color: transparent;
  outline: none;
}

.emoji-panel__item:hover {
  background: rgba(99, 102, 241, 0.1);
}

.emoji-panel__item:active {
  background: rgba(99, 102, 241, 0.15);
  transform: scale(1.2);
}

/* 表情面板遮罩（点击关闭） */
.emoji-panel__overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 99;
}

/* ==========================================================================
   输入行：块级布局（发送按钮 absolute 右下角）
   ========================================================================== */
.input-bar__row {
  display: block;
  position: relative;
}

/* ==========================================================================
   文本输入框
   ========================================================================== */
.input-bar__field {
  display: block;
  width: 100%;
  background-color: var(--bg-secondary);
  border-radius: 8px;
  padding: 10px 80px 10px 10px;
  border: 1px solid var(--border-color);
  transition: border-color 0.2s;
  box-sizing: border-box;
  font-family: inherit;
  font-size: 14px;
  color: var(--text-primary);
}

.input-bar__field:focus-within {
  border-color: var(--accent);
}

.input-bar__field :deep(.van-field__control) {
  font-size: 14px;
  line-height: 1.5;
}

.input-bar__field :deep(.van-field__body) {
  padding: 0;
}

/* ==========================================================================
   发送按钮
   ========================================================================== */
.input-bar__send-btn {
  position: absolute;
  bottom: 8px;
  right: 8px;
  z-index: 2;
  height: 36px;
  border-radius: 8px;
  min-width: 56px;
}

/* ==========================================================================
   语音状态提示条（百度ASR内联录音时显示）
   ========================================================================== */
.input-bar__voice-status {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  margin: 4px 0;
  font-size: 12px;
  color: #ef4444;
  background: rgba(239, 68, 68, 0.08);
  border-radius: 6px;
  animation: voice-status-blink 1.2s ease-in-out infinite;
  width: fit-content;
}

@keyframes voice-status-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
</style>