<template>
  <div id="app">
    <div v-if="!pdfUrl" class="upload-container">
      <h1>PDF 文档阅读器</h1>
      <p class="subtitle">支持高亮、批注、朗读和导入导出批注</p>
      
      <div class="upload-section">
        <div class="upload-card">
          <div class="upload-icon">📄</div>
          <h3>选择本地 PDF 文件</h3>
          <label for="file-upload" class="upload-btn">
            选择文件
          </label>
          <input
            id="file-upload"
            type="file"
            @change="handleFileUpload"
            accept="application/pdf"
            style="display: none"
          />
        </div>
        
        <div class="divider">或</div>
        
        <div class="upload-card">
          <div class="upload-icon">🔗</div>
          <h3>输入 PDF URL</h3>
          <div class="url-input-wrapper">
            <input
              v-model="pdfUrlInput"
              type="text"
              placeholder="https://example.com/document.pdf"
              class="url-input"
              @keyup.enter="loadFromUrl"
            />
            <button @click="loadFromUrl" class="load-btn">
              加载
            </button>
          </div>
        </div>
      </div>
      
      <div class="demo-section">
        <p>没有 PDF 文件？试试我们的演示文档：</p>
        <button @click="loadDemoPdf" class="demo-btn">
          加载示例 PDF
        </button>
      </div>
    </div>
    
    <div v-else class="reader-container">
      <div class="reader-header">
        <button @click="reset" class="back-btn">
          ← 返回文件选择
        </button>
        <h2>{{ fileName }}</h2>
        
        <div class="toolbar-group">
          <div class="zoom-container">
            <button @click="fitToWidth" class="tool-btn" title="适应宽度">
              <span class="icon">↔</span>
              <span class="label">宽度</span>
            </button>
            <button @click="fitToPage" class="tool-btn" title="适应页面">
              <span class="icon">▢</span>
              <span class="label">页面</span>
            </button>
            <div class="zoom-divider"></div>
            <button @click="zoomOut" class="tool-btn icon-only" title="缩小">
              <span class="icon">−</span>
            </button>
            <span class="zoom-level">{{ Math.round(scale * 100) }}%</span>
            <button @click="zoomIn" class="tool-btn icon-only" title="放大">
              <span class="icon">+</span>
            </button>
          </div>
        </div>
        
        <div class="toolbar-divider"></div>
        
        <div class="toolbar-group">
          <div class="color-picker-wrapper">
            <button @click="toggleColorPicker" class="tool-btn" :class="{ active: showColorPicker }" title="高亮颜色">
              <div 
                class="color-preview" 
                :style="{ backgroundColor: currentColor }"
              ></div>
              <span class="label">颜色</span>
            </button>
            <Transition name="dropdown">
              <div v-if="showColorPicker" class="color-picker-dropdown" @click.stop>
                <div 
                  v-for="color in colors" 
                  :key="color"
                  class="color-option"
                  :class="{ active: currentColor === color }"
                  :style="{ backgroundColor: color }"
                  @click="selectColor(color)"
                ></div>
              </div>
            </Transition>
          </div>
          
          <button
            @click="addHighlight"
            :disabled="!selectedText"
            class="tool-btn primary"
            title="高亮选中文本"
          >
            <span class="icon">✨</span>
            <span class="label">高亮</span>
          </button>
          
          <div class="speech-controls">
            <button
              @click="toggleSpeech"
              :disabled="!selectedText && !isSpeaking"
              class="tool-btn"
              :class="{ active: isSpeaking }"
              title="朗读控制"
            >
              <span class="icon">{{ isSpeaking ? '⏹' : '🔊' }}</span>
              <span class="label">{{ isSpeaking ? '停止' : '朗读' }}</span>
            </button>
            <button
              @click="toggleSpeechControls"
              class="tool-btn icon-only"
              title="朗读设置"
            >
              <span class="icon">⚙</span>
            </button>
            <Transition name="dropdown">
              <div v-if="showSpeechControls" class="speech-dropdown" @click.stop>
                <div class="speech-control-item">
                  <label class="control-label">语速</label>
                  <div class="rate-control">
                    <button @click="decreaseRate" class="rate-btn" title="减慢语速">−</button>
                    <span class="rate-value">{{ Math.round(speechRate * 100) }}%</span>
                    <button @click="increaseRate" class="rate-btn" title="加快语速">+</button>
                  </div>
                </div>
                <div class="speech-control-item">
                  <label class="control-label">语音</label>
                  <select v-model="selectedVoice" class="voice-select">
                    <option v-for="voice in availableVoices" :key="voice.voiceURI" :value="voice">
                      {{ voice.name }} ({{ voice.lang }})
                    </option>
                  </select>
                </div>
                <div class="speech-control-item">
                  <label class="control-label">测试朗读</label>
                  <button @click="testSpeech" class="test-speech-btn">
                    测试语音
                  </button>
                </div>
              </div>
            </Transition>
          </div>
        </div>
        
        <div class="toolbar-divider"></div>
        
        <div class="toolbar-group">
          <button @click="exportAnnotations" class="tool-btn" title="导出批注">
            <span class="icon">📤</span>
            <span class="label">导出</span>
          </button>
          <label class="tool-btn" title="导入批注">
            <span class="icon">📥</span>
            <span class="label">导入</span>
            <input type="file" @change="importAnnotations" accept=".json" class="hidden-input" />
          </label>
          <button @click="clearAll" class="tool-btn danger" title="清空所有">
            <span class="icon">🗑️</span>
          </button>
        </div>
      </div>
      
      <div class="reader-content">
        <div class="pdf-wrapper">
          <PdfReader 
            :src="pdfUrl" 
            :scale="scale"
            :highlights="highlights"
            @update:scale="scale = $event"
            @text-selected="selectedText = $event"
          />
        </div>
        
        <div class="sidebar">
          <div class="sidebar-header">
            <h3 class="sidebar-title">
              <span class="title-icon">📝</span>
              批注和高亮
              <span class="annotation-count">{{ allAnnotations.length }}</span>
            </h3>
          </div>
          
          <div class="sidebar-content">
            <div
              v-for="item in allAnnotations"
              :key="item.id"
              class="annotation-item"
              :class="{ active: selectedAnnotationId === item.id }"
              @click="selectedAnnotationId = item.id"
            >
              <div class="item-header">
                <div
                  class="item-color"
                  :style="{ backgroundColor: item.color }"
                ></div>
                <span class="item-time">{{ formatDate(item.createdAt) }}</span>
                <button @click.stop="deleteHighlight(item.id)" class="item-delete" title="删除">
                  ✕
                </button>
              </div>
              <div class="item-text">{{ item.text }}</div>
              <div v-if="item.annotation" class="item-annotation">
                <span class="annotation-label">批注：</span>
                {{ item.annotation }}
              </div>
              <div class="item-edit">
                <textarea
                  v-model="item.annotation"
                  placeholder="添加批注..."
                  class="annotation-textarea"
                  @blur="saveAnnotation(item)"
                  @click.stop
                ></textarea>
              </div>
            </div>
            
            <div v-if="allAnnotations.length === 0" class="empty-state">
              <div class="empty-icon">📖</div>
              <p class="empty-text">暂无批注和高亮</p>
              <p class="empty-hint">选中文本后点击"高亮"按钮</p>
            </div>
          </div>
        </div>
      </div>
      
      <div v-if="showAnnotationModal" class="modal-overlay" @click.self="closeAnnotationModal">
        <div class="modal">
          <div class="modal-header">
            <h4 class="modal-title">添加批注</h4>
            <button @click="closeAnnotationModal" class="modal-close">✕</button>
          </div>
          <div class="modal-body">
            <div class="selected-text-preview">
              <span class="preview-label">高亮文本：</span>
              <p class="preview-text">{{ currentHighlight?.text }}</p>
            </div>
            <textarea
              v-model="annotationInput"
              placeholder="在此输入批注内容..."
              class="modal-textarea"
            ></textarea>
            <div v-if="currentHighlight?.annotation" class="existing-annotation">
              <span class="existing-label">当前批注：</span>
              <p class="existing-text">{{ currentHighlight.annotation }}</p>
            </div>
          </div>
          <div class="modal-footer">
            <button @click="closeAnnotationModal" class="modal-btn secondary">取消</button>
            <button @click="saveAnnotationModal" class="modal-btn primary">保存</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { saveAs } from 'file-saver'
import PdfReader from './components/PdfReader/index.vue'

const pdfUrl = ref('')
const pdfUrlInput = ref('')
const fileName = ref('文档')
const scale = ref(1.0)
const selectedText = ref('')

const highlights = ref([])
const nextId = ref(1)
const isSpeaking = ref(false)
const synthesis = ref(null)
const selectedAnnotationId = ref(null)
const showAnnotationModal = ref(false)
const currentHighlight = ref(null)
const annotationInput = ref('')
const showColorPicker = ref(false)
const showSpeechControls = ref(false)
const colors = ['#FFEB3B', '#4CAF50', '#2196F3', '#F44336', '#9C27B0', '#FF9800']
const currentColor = ref('#FFEB3B')

const speechRate = ref(1.0)
const availableVoices = ref([])
const selectedVoice = ref(null)
const utterance = ref(null)

const allAnnotations = computed(() => {
  return [...highlights.value].sort((a, b) => {
    return new Date(b.createdAt) - new Date(a.createdAt)
  })
})

function handleFileUpload(event) {
  const file = event.target.files[0]
  if (!file) return
  
  fileName.value = file.name
  pdfUrl.value = URL.createObjectURL(file)
}

function loadFromUrl() {
  if (!pdfUrlInput.value.trim()) return
  
  fileName.value = '远程文档'
  pdfUrl.value = pdfUrlInput.value.trim()
}

function loadDemoPdf() {
  fileName.value = '示例文档'
  pdfUrl.value = 'https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf'
}

function reset() {
  if (pdfUrl.value.startsWith('blob:')) {
    URL.revokeObjectURL(pdfUrl.value)
  }
  pdfUrl.value = ''
  pdfUrlInput.value = ''
  fileName.value = '文档'
  scale.value = 1.0
}

function fitToWidth() {
  scale.value = 1.0
}

function fitToPage() {
  scale.value = 0.8
}

function zoomIn() {
  if (scale.value < 2) {
    scale.value = Math.min(2, scale.value + 0.1)
  }
}

function zoomOut() {
  if (scale.value > 0.3) {
    scale.value = Math.max(0.3, scale.value - 0.1)
  }
}

function toggleColorPicker() {
  showColorPicker.value = !showColorPicker.value
  showSpeechControls.value = false
}

function toggleSpeechControls() {
  showSpeechControls.value = !showSpeechControls.value
  showColorPicker.value = false
}

function selectColor(color) {
  currentColor.value = color
  showColorPicker.value = false
}

function addHighlight() {
  if (!selectedText.value) return
  
  const highlight = {
    id: nextId.value++,
    text: selectedText.value,
    color: currentColor.value,
    annotation: '',
    createdAt: new Date().toISOString(),
  }
  
  highlights.value.push(highlight)
  saveToStorage()
  
  currentHighlight.value = highlight
  annotationInput.value = ''
  showAnnotationModal.value = true
  
  selectedText.value = ''
}

function deleteHighlight(id) {
  highlights.value = highlights.value.filter((h) => h.id !== id)
  if (selectedAnnotationId.value === id) {
    selectedAnnotationId.value = null
  }
  saveToStorage()
}

function clearAll() {
  if (confirm('确定要清空所有高亮和批注吗？')) {
    highlights.value = []
    nextId.value = 1
    selectedAnnotationId.value = null
    localStorage.removeItem('pdf-reader-data')
  }
}

function closeAnnotationModal() {
  showAnnotationModal.value = false
  currentHighlight.value = null
  annotationInput.value = ''
}

function saveAnnotationModal() {
  if (currentHighlight.value) {
    currentHighlight.value.annotation = annotationInput.value
    saveToStorage()
  }
  closeAnnotationModal()
}

function saveAnnotation(item) {
  saveToStorage()
}

function initSpeech() {
  try {
    if (!synthesis.value) {
      synthesis.value = window.speechSynthesis
    }
    
    const updateVoices = () => {
      try {
        availableVoices.value = synthesis.value.getVoices()
        if (availableVoices.value.length > 0 && !selectedVoice.value) {
          const chineseVoice = availableVoices.value.find(v => v.lang.includes('zh'))
          selectedVoice.value = chineseVoice || availableVoices.value[0]
        }
      } catch (e) {
        console.error('获取语音列表失败:', e)
      }
    }
    
    updateVoices()
    if (synthesis.value.onvoiceschanged !== undefined) {
      synthesis.value.onvoiceschanged = updateVoices
    }
  } catch (e) {
    console.error('初始化语音合成失败:', e)
  }
}

function toggleSpeech() {
  if (!synthesis.value) {
    initSpeech()
  }

  if (isSpeaking.value) {
    stopSpeech()
  } else {
    speakSelection()
  }
  showSpeechControls.value = false
}

function speakSelection() {
  try {
    if (!synthesis.value) {
      initSpeech()
    }

    const text = selectedText.value || '请先选择要朗读的文本'
    if (!text) return

    stopSpeech()

    utterance.value = new SpeechSynthesisUtterance(text)
    utterance.value.lang = 'zh-CN'
    utterance.value.rate = speechRate.value
    utterance.value.pitch = 1
    utterance.value.volume = 1
    
    if (selectedVoice.value) {
      utterance.value.voice = selectedVoice.value
    }

    utterance.value.onstart = () => {
      isSpeaking.value = true
    }

    utterance.value.onend = () => {
      isSpeaking.value = false
    }

    utterance.value.onerror = (event) => {
      console.error('语音合成错误:', event)
      isSpeaking.value = false
      alert('语音合成失败，请检查浏览器设置')
    }

    synthesis.value.speak(utterance.value)
  } catch (e) {
    console.error('朗读失败:', e)
    isSpeaking.value = false
    alert('朗读失败，请检查浏览器设置')
  }
}

function stopSpeech() {
  try {
    if (synthesis.value) {
      synthesis.value.cancel()
    }
  } catch (e) {
    console.error('停止朗读失败:', e)
  }
  isSpeaking.value = false
}

function testSpeech() {
  try {
    if (!synthesis.value) {
      initSpeech()
    }

    const testText = '这是一段测试语音，用于检查朗读功能是否正常工作。'
    const testUtterance = new SpeechSynthesisUtterance(testText)
    testUtterance.lang = 'zh-CN'
    testUtterance.rate = speechRate.value
    
    if (selectedVoice.value) {
      testUtterance.voice = selectedVoice.value
    }

    synthesis.value.speak(testUtterance)
  } catch (e) {
    console.error('测试朗读失败:', e)
    alert('测试朗读失败，请检查浏览器设置')
  }
}

function increaseRate() {
  if (speechRate.value < 3) {
    speechRate.value = Math.min(3, speechRate.value + 0.1)
  }
}

function decreaseRate() {
  if (speechRate.value > 0.5) {
    speechRate.value = Math.max(0.5, speechRate.value - 0.1)
  }
}

function saveToStorage() {
  try {
    localStorage.setItem(
      'pdf-reader-data',
      JSON.stringify({
        highlights: highlights.value,
        nextId: nextId.value,
      })
    )
  } catch (e) {
    console.error('保存失败:', e)
  }
}

function loadFromStorage() {
  try {
    const saved = localStorage.getItem('pdf-reader-data')
    if (saved) {
      const data = JSON.parse(saved)
      highlights.value = data.highlights || []
      nextId.value = data.nextId || 1
    }
  } catch (e) {
    console.error('加载失败:', e)
  }
}

function exportAnnotations() {
  const data = {
    version: '1.0.0',
    exportDate: new Date().toISOString(),
    highlights: JSON.parse(JSON.stringify(highlights.value)),
  }
  const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
  saveAs(blob, 'pdf-annotations.json')
}

async function importAnnotations(event) {
  const file = event.target.files[0]
  if (!file) return

  try {
    const text = await file.text()
    const data = JSON.parse(text)
    highlights.value = data.highlights || []
    if (highlights.value.length > 0) {
      nextId.value = Math.max(...highlights.value.map((h) => h.id)) + 1
    }
    saveToStorage()
  } catch (e) {
    alert('导入失败，请确保文件格式正确')
  }
  event.target.value = ''
}

function formatDate(dateString) {
  return new Date(dateString).toLocaleString('zh-CN', {
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

function handleClickOutside(event) {
  if (!event.target.closest('.color-picker-wrapper') && !event.target.closest('.speech-controls')) {
    showColorPicker.value = false
    showSpeechControls.value = false
  }
}

onMounted(() => {
  loadFromStorage()
  initSpeech()
  document.addEventListener('click', handleClickOutside)
})

onUnmounted(() => {
  stopSpeech()
  document.removeEventListener('click', handleClickOutside)
})
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
  background-color: #f8f9fa;
  color: #333;
}

#app {
  min-height: 100vh;
}

.upload-container {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}

.upload-container h1 {
  font-size: 42px;
  font-weight: 700;
  margin-bottom: 10px;
  color: #2c3e50;
}

.subtitle {
  font-size: 16px;
  color: #7f8c8d;
  margin-bottom: 40px;
}

.upload-section {
  display: flex;
  flex-direction: column;
  gap: 20px;
  width: 100%;
  max-width: 600px;
}

.upload-card {
  background-color: #fff;
  padding: 40px;
  border-radius: 12px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
  text-align: center;
}

.upload-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.upload-card h3 {
  font-size: 20px;
  margin-bottom: 20px;
  color: #34495e;
}

.upload-btn,
.load-btn,
.demo-btn,
.back-btn {
  padding: 12px 32px;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.upload-btn,
.load-btn,
.demo-btn {
  background-color: #3498db;
  color: #fff;
}

.upload-btn:hover,
.load-btn:hover,
.demo-btn:hover {
  background-color: #2980b9;
}

.divider {
  text-align: center;
  color: #95a5a6;
  font-size: 14px;
  margin: 10px 0;
}

.url-input-wrapper {
  display: flex;
  gap: 10px;
}

.url-input {
  flex: 1;
  padding: 12px 16px;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 14px;
  outline: none;
  transition: border-color 0.2s;
}

.url-input:focus {
  border-color: #3498db;
}

.demo-section {
  margin-top: 40px;
  text-align: center;
}

.demo-section p {
  color: #7f8c8d;
  margin-bottom: 16px;
}

.reader-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.reader-header {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 12px 20px;
  background-color: #fff;
  border-bottom: 1px solid #ddd;
  z-index: 100;
  flex-wrap: wrap;
}

.reader-header h2 {
  font-size: 18px;
  color: #2c3e50;
  flex-shrink: 0;
}

.back-btn {
  background-color: #ecf0f1;
  color: #34495e;
  padding: 8px 16px;
  font-size: 14px;
  flex-shrink: 0;
}

.back-btn:hover {
  background-color: #bdc3c7;
}

.reader-content {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.pdf-wrapper {
  flex: 1;
  overflow: auto;
  background: linear-gradient(135deg, #f0f2f5 0%, #e6e9f0 100%);
  background-attachment: fixed;
}

.sidebar {
  width: 340px;
  background: #fff;
  border-left: 1px solid #e4e7ed;
  display: flex;
  flex-direction: column;
  box-shadow: -4px 0 20px rgba(0, 0, 0, 0.04);
  overflow: hidden;
}

.sidebar-header {
  padding: 18px 20px;
  border-bottom: 1px solid #f0f0f0;
  background: #fafafa;
}

.sidebar-title {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  color: #303133;
  display: flex;
  align-items: center;
  gap: 8px;
}

.title-icon {
  font-size: 18px;
}

.annotation-count {
  font-size: 13px;
  font-weight: 600;
  color: #409eff;
  background: #ecf5ff;
  padding: 2px 10px;
  border-radius: 12px;
  margin-left: auto;
}

.sidebar-content {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
}

.annotation-item {
  background: #fafafa;
  border: 1px solid #f0f0f0;
  border-radius: 10px;
  padding: 14px;
  margin-bottom: 10px;
  transition: all 0.2s;
  cursor: pointer;
}

.annotation-item:hover {
  background: #f5f7fa;
  border-color: #e4e7ed;
}

.annotation-item.active {
  background: #ecf5ff;
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}

.item-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.item-color {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.item-time {
  font-size: 12px;
  color: #909399;
  margin-left: auto;
}

.item-delete {
  width: 22px;
  height: 22px;
  border: none;
  background: transparent;
  color: #c0c4cc;
  cursor: pointer;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  transition: all 0.2s;
}

.item-delete:hover {
  background: #fef0f0;
  color: #f56c6c;
}

.item-text {
  font-size: 13px;
  color: #303133;
  line-height: 1.6;
  margin-bottom: 8px;
  padding: 8px 10px;
  background: #fff;
  border-radius: 6px;
  border-left: 2px solid #409eff;
}

.item-annotation {
  font-size: 12px;
  color: #606266;
  line-height: 1.6;
  padding: 8px 10px;
  background: #e6f7ff;
  border-radius: 6px;
  margin-bottom: 8px;
}

.annotation-label {
  font-weight: 600;
  color: #1890ff;
  margin-right: 4px;
}

.item-edit {
  margin-top: 6px;
}

.annotation-textarea {
  width: 100%;
  min-height: 52px;
  padding: 8px 10px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.5;
  resize: vertical;
  font-family: inherit;
  box-sizing: border-box;
  transition: all 0.2s;
}

.annotation-textarea:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

.empty-state {
  text-align: center;
  padding: 48px 16px;
  color: #909399;
}

.empty-icon {
  font-size: 48px;
  margin-bottom: 12px;
  opacity: 0.4;
}

.empty-text {
  font-size: 14px;
  margin-bottom: 6px;
  font-weight: 500;
}

.empty-hint {
  font-size: 13px;
  opacity: 0.7;
}

.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}

.modal {
  background: #fff;
  border-radius: 14px;
  width: 480px;
  max-width: 90%;
  max-height: 80vh;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.25);
  display: flex;
  flex-direction: column;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 22px;
  border-bottom: 1px solid #f0f0f0;
}

.modal-title {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
  color: #303133;
}

.modal-close {
  width: 30px;
  height: 30px;
  border: none;
  background: #f5f7fa;
  color: #909399;
  cursor: pointer;
  border-radius: 6px;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.modal-close:hover {
  background: #f0f0f0;
  color: #606266;
}

.modal-body {
  padding: 22px;
  overflow-y: auto;
  flex: 1;
}

.selected-text-preview {
  margin-bottom: 14px;
}

.preview-label {
  font-size: 12px;
  font-weight: 600;
  color: #909399;
  display: block;
  margin-bottom: 6px;
}

.preview-text {
  padding: 10px 14px;
  background: #f5f7fa;
  border-radius: 8px;
  color: #303133;
  font-size: 13px;
  line-height: 1.6;
  margin: 0;
  border-left: 2px solid #409eff;
}

.modal-textarea {
  width: 100%;
  min-height: 100px;
  padding: 10px 14px;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.6;
  resize: vertical;
  font-family: inherit;
  box-sizing: border-box;
  transition: all 0.2s;
}

.modal-textarea:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

.existing-annotation {
  margin-top: 14px;
  padding: 10px 14px;
  background: #fafafa;
  border-radius: 8px;
}

.existing-label {
  font-size: 12px;
  font-weight: 600;
  color: #909399;
  display: block;
  margin-bottom: 6px;
}

.existing-text {
  margin: 0;
  color: #606266;
  font-size: 13px;
  line-height: 1.6;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 22px;
  border-top: 1px solid #f0f0f0;
  background: #fafafa;
}

.modal-btn {
  padding: 9px 22px;
  border: none;
  border-radius: 7px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.modal-btn.secondary {
  background: #e4e7ed;
  color: #606266;
}

.modal-btn.secondary:hover {
  background: #dcdfe6;
}

.modal-btn.primary {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
}

.modal-btn.primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.35);
}

.toolbar-group {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.toolbar-divider {
  width: 1px;
  height: 32px;
  background: #e4e7ed;
  margin: 0 12px;
}

.tool-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: #606266;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
  line-height: 1;
  position: relative;
}

.tool-btn:hover:not(:disabled) {
  background: #f5f7fa;
  color: #409eff;
}

.tool-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.tool-btn.primary {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
}

.tool-btn.primary:hover:not(:disabled) {
  background: linear-gradient(135deg, #5a6fd6 0%, #6a4190 100%);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.35);
}

.tool-btn.danger:hover:not(:disabled) {
  background: #fef0f0;
  color: #f56c6c;
}

.tool-btn.active {
  background: #ecf5ff;
  color: #409eff;
}

.tool-btn.icon-only {
  padding: 8px 10px;
}

.tool-btn .icon {
  font-size: 16px;
  line-height: 1;
}

.tool-btn .label {
  white-space: nowrap;
}

.zoom-container {
  display: flex;
  align-items: center;
  gap: 4px;
  background: #f5f7fa;
  padding: 4px 8px;
  border-radius: 8px;
}

.zoom-divider {
  width: 1px;
  height: 20px;
  background: #e4e7ed;
  margin: 0 4px;
}

.zoom-level {
  color: #606266;
  font-size: 13px;
  font-weight: 600;
  min-width: 48px;
  text-align: center;
  user-select: none;
}

.color-picker-wrapper {
  position: relative;
}

.color-preview {
  width: 18px;
  height: 18px;
  border-radius: 4px;
  border: 2px solid #e4e7ed;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.5);
}

.color-picker-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  padding: 10px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  display: flex;
  gap: 8px;
  z-index: 100;
  border: 1px solid #e4e7ed;
}

.speech-controls {
  position: relative;
  display: flex;
  align-items: center;
}

.speech-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  padding: 16px;
  background: #fff;
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
  z-index: 100;
  border: 1px solid #e4e7ed;
  min-width: 200px;
}

.speech-control-item {
  margin-bottom: 16px;
}

.speech-control-item:last-child {
  margin-bottom: 0;
}

.control-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: #909399;
  margin-bottom: 8px;
}

.rate-control {
  display: flex;
  align-items: center;
  gap: 10px;
}

.rate-btn {
  width: 28px;
  height: 28px;
  border: 1px solid #dcdfe6;
  background: #fff;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s;
}

.rate-btn:hover {
  border-color: #409eff;
  color: #409eff;
}

.rate-value {
  flex: 1;
  text-align: center;
  font-size: 13px;
  font-weight: 600;
  color: #606266;
}

.voice-select {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  font-size: 13px;
  background: #fff;
  cursor: pointer;
  transition: all 0.2s;
}

.voice-select:focus {
  outline: none;
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.1);
}

.test-speech-btn {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid #409eff;
  background: #ecf5ff;
  color: #409eff;
  border-radius: 6px;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.test-speech-btn:hover {
  background: #409eff;
  color: #fff;
}

.dropdown-enter-active,
.dropdown-leave-active {
  transition: all 0.2s ease;
}

.dropdown-enter-from,
.dropdown-leave-to {
  opacity: 0;
  transform: translateY(-8px);
}

.color-option {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  cursor: pointer;
  border: 2px solid transparent;
  transition: all 0.2s;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
}

.color-option:hover {
  transform: scale(1.15);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.color-option.active {
  border-color: #409eff;
  box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.2);
}

.hidden-input {
  display: none;
}
</style>
