<template>
  <div class="cloud-config">
    <!-- 网盘类型开关 -->
    <el-card class="toggle-card" style="margin-bottom: 20px;">
      <template #header><span>📂 网盘设置及授权</span></template>
      <div class="cloud-toggle-grid">
        <div
          v-for="ct in cloudTypes"
          :key="ct.type"
          class="cloud-toggle-chip"
        >
          <img :src="ct.icon" class="cloud-icon-img" />
          <span class="cloud-label">{{ ct.label }}</span>
          <el-tag v-if="ct.type === 'others'" size="small" type="info">关</el-tag>
          <el-switch
            :model-value="ct.enabled"
            size="small"
            @change="(val: boolean) => handleCloudToggle(ct.type, val)"
          />
        </div>
      </div>
      <div class="form-tip" style="margin-top: 12px;">
        关闭的网盘类型在搜索结果中不会展示。修改后立即生效，无需点击保存。
      </div>
    </el-card>

    <div class="toolbar">
      <el-button type="primary" @click="openDialog(null)">新增配置</el-button>
      <el-button @click="verifyAll">全部重新验证</el-button>
    </div>

    <el-card shadow="never" class="table-card">
      <template #header><span>📋 网盘配置列表</span></template>
      <el-table :data="configs" stripe style="width: 100%" empty-text="暂无网盘配置，点击上方「新增配置」添加">
        <el-table-column label="网盘类型" width="110">
          <template #default="{ row }">
            <CloudBadge :cloud_type="row.cloud_type" />
          </template>
      </el-table-column>
      <el-table-column prop="nickname" label="昵称" width="140">
        <template #default="{ row }">
          <span v-if="row.nickname" class="nickname-text">{{ row.nickname }}</span>
          <el-text v-else type="info" size="small">未设置</el-text>
        </template>
      </el-table-column>
      <el-table-column prop="promotion_account" label="推广账号" width="160">
        <template #default="{ row }">
          <span v-if="row.promotion_account" class="promotion-text">{{ row.promotion_account }}</span>
          <el-text v-else type="info" size="small">-</el-text>
        </template>
      </el-table-column>
      <el-table-column prop="cloud_type_uid" label="标识(__uid)" width="180">
        <template #default="{ row }">
          <span v-if="row.cloud_type_uid" class="uid-cell">{{ row.cloud_type_uid }}</span>
          <el-text v-else type="info" size="small">-</el-text>
        </template>
      </el-table-column>
      <el-table-column label="验证" width="80" align="center">
        <template #default="{ row }">
          <span v-if="row._verifying" class="verifying">
            <el-icon class="is-loading"><Loading /></el-icon>
          </span>
          <el-tag v-else-if="row.verification_status === 'valid'" type="success" size="small">有效</el-tag>
          <el-tag v-else-if="row.verification_status === 'invalid'" type="danger" size="small">无效</el-tag>
          <el-tag v-else type="info" size="small">未验证</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="空间" width="200">
        <template #default="{ row }">
          <div v-if="row.storage_total && row.storage_total !== '-'" class="storage-cell">
            <div class="storage-bar-wrap">
              <div
                class="storage-bar-fill"
                :style="{ width: storagePercent(row) + '%' }"
                :class="storageBarClass(row)"
              ></div>
            </div>
            <div class="storage-text">
              <span class="storage-used">{{ row.storage_used || '计算中...' }}</span>
              <span class="storage-sep">/</span>
              <span class="storage-total">{{ row.storage_total }}</span>
              <span class="storage-free">(可用 {{ storageFree(row) }})</span>
            </div>
          </div>
          <el-text v-else type="info" size="small">—</el-text>
        </template>
      </el-table-column>
      <!-- 转存统计 -->
      <el-table-column label="转存数" width="80" align="center">
        <template #default="{ row }">
          <span v-if="row.total_saves > 0" class="save-count">{{ row.total_saves }}次</span>
          <el-text v-else type="info" size="small">-</el-text>
        </template>
      </el-table-column>
      <el-table-column label="转存启用" width="80" align="center">
        <template #default="{ row }">
          <el-switch
            :model-value="row.is_active !== 0"
            size="small"
            @change="(val: boolean) => handleToggleTransfer(row, val)"
          />
        </template>
      </el-table-column>
      <el-table-column label="默认账号" width="100" align="center">
        <template #default="{ row }">
          <el-switch
            :model-value="row.is_primary === 1"
            :disabled="!row.is_active"
            size="small"
            @change="(val: boolean) => handleTogglePrimary(row, val)"
          />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="390" align="center">
        <template #default="{ row }">
          <el-button text type="primary" @click="openDialog(row)">编辑</el-button>
          <el-button text type="primary" @click="verifyOne(row)">验证</el-button>
          <el-popconfirm title="确定删除该配置？" @confirm="handleDelete(row)">
            <template #reference>
              <el-button text type="danger">删除</el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
    </el-card>

    <!-- 新增/编辑弹窗 -->
    <el-dialog v-model="dialogVisible" :title="editingId ? '编辑配置' : '新增配置'" width="560px">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
        <!-- 白名单目录提示 -->
        <el-alert
          v-show="whitelistDirs.length > 0"
          type="warning"
          show-icon
          :closable="false"
          style="margin-bottom: 18px;"
        >
          <template #title>
            <div style="line-height: 1.6;">
              <div>🧹 请在网盘主目录内创建：<b>{{ whitelistDirs.join('、') }}</b> 目录</div>
              <div>并将你的重要文件移至该目录，<b>只有这个目录不会被自动清理</b></div>
            </div>
          </template>
        </el-alert>
        <el-form-item label="网盘类型" prop="cloud_type">
          <el-select v-model="form.cloud_type" style="width: 100%" :disabled="!!editingId" @change="onCloudTypeChange">
            <el-option
              v-for="[key, label] in cloudTypeOptions"
              :key="key"
              :label="label"
              :value="key"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="推广平台及账号" prop="promotion_account" style="margin-bottom: 18px;">
          <el-input
            v-model="form.promotion_account"
            placeholder="请填写您的推广平台及账号，例：蜂小推-13288889999"
            clearable
          />
        </el-form-item>
        <el-form-item label="Cookie" prop="cookie">
          <el-input
            v-model="form.cookie"
            type="textarea"
            :autosize="{ minRows: 2, maxRows: 4 }"
            :placeholder="cookiePlaceholder"
            input-style="font-family: monospace; font-size: 12px;"
          />
        </el-form-item>
        <!-- Cookie 获取教程（根据网盘类型切换） -->
        <el-form-item label=" " v-if="form.cloud_type && form.cloud_type !== ''" class="cookie-tips-item">
          <div class="cookie-tips" :class="`cookie-tips-${form.cloud_type}`">
            <div class="cookie-tips-header">
              <span class="cookie-tips-title">📖 {{ cloudTypeLabel }} Cookie 获取教程</span>
            </div>
            <ol class="cookie-tips-steps" v-html="cookieTutorialHtml"></ol>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { Loading } from '@element-plus/icons-vue'
import { CLOUD_LABELS } from '../../types'
import type { CloudType, CloudConfig } from '../../types'
import { ElMessage } from 'element-plus'
import { getCloudConfigs, saveCloudConfig, updateCloudConfig, deleteCloudConfig, testCloudConnection, getCloudTypes, toggleCloudType, setPrimary } from '../../api'
import { getSystemConfigs } from '../../api'
import CloudBadge from '../../components/CloudBadge.vue'
import type { ElForm } from 'element-plus'

interface CloudTypeInfo { type: string; label: string; icon: string; enabled: boolean }
const cloudTypes = ref<CloudTypeInfo[]>([])

const formRef = ref<InstanceType<typeof ElForm>>()
const configs = ref<(CloudConfig & { _verifying?: boolean })[]>([])
const dialogVisible = ref(false)
const saving = ref(false)
const editingId = ref<number | null>(null)

const defaultForm = () => ({
  cloud_type: '' as CloudType | '',
  nickname: '',
  promotion_account: '',
  is_transfer_enabled: false,
  cookie: '',
  _verifying: false,
  _storageUsed: '',
  _storageTotal: '',
})

const form = reactive<{
  cloud_type: CloudType | ''
  nickname: string
  promotion_account: string
  is_transfer_enabled: boolean
  cookie: string
  _verifying: boolean
  _storageUsed: string
  _storageTotal: string
}>(defaultForm())

const rules = computed(() => ({
  cloud_type: [{ required: true, message: '请选择网盘类型', trigger: 'change' }],
  nickname: [{ required: false, message: '请填写昵称（区分多个同类型网盘）', trigger: 'blur' }],
  promotion_account: [{ required: true, message: '请填写推广平台及账号', trigger: 'blur' }],
}))

const cloudTypeOptions = computed(() => {
  return Object.entries(CLOUD_LABELS) as [CloudType, string][]
})

const cookiePlaceholder = computed(() => {
  if (!form.cloud_type) return '请先选择网盘类型'
  const t = form.cloud_type
  if (t === 'quark' || t === 'baidu') return `请输入 ${CLOUD_LABELS[t] || t} 的完整 Cookie`
  return editingId.value ? '留空则保持原有' : '输入完整 Cookie'
})

const cloudTypeLabel = computed(() => {
  return CLOUD_LABELS[form.cloud_type as CloudType] || form.cloud_type || ''
})

/** Cookie 获取教程 HTML（根据不同网盘类型） */
const cookieTutorialHtml = computed(() => {
  const t = form.cloud_type
  if (!t) return ''
  const tutorials: Record<string, string> = {
    quark: `<li>在电脑上打开 <a href="https://pan.quark.cn" target="_blank">pan.quark.cn</a> 并登录你的夸克账号</li>
<li>按 <code>F12</code> 打开开发者工具 → 切换到 <strong>网络 (Network)</strong> 选项卡</li>
<li>刷新页面，在请求列表中点击任意一个请求（如 <code>account/info</code>）</li>
<li>在右侧 <strong>请求头 (Request Headers)</strong> 中找到 <code>Cookie</code> 字段</li>
<li>复制整个 Cookie 值（<b>从开头到结束的完整内容</b>），粘贴到上方输入框</li>
<li>点击「<b>自动获取</b>」按钮验证 Cookie 是否有效</li>
<div class="cookie-tips-note">⚠️ 必须包含 <code>__st=s%...</code> 字段！请复制浏览器请求头的 <b>整个 Cookie</b>（F12 → Network → 请求头 → Cookie 项），不要只复制部分。</div>`,

    baidu: `<li>在电脑上打开 <a href="https://pan.baidu.com" target="_blank">pan.baidu.com</a> 并登录你的百度账号</li>
<li>按 <code>F12</code> 打开开发者工具 → 切换到 <strong>网络 (Network)</strong> 选项卡</li>
<li>刷新页面，在请求列表中点击任意一个请求</li>
<li>在右侧 <strong>请求头 (Request Headers)</strong> 中找到 <code>Cookie</code> 字段</li>
<li>复制整个 Cookie 值，粘贴到上方输入框</li>
<li>点击「<b>自动获取</b>」按钮验证 Cookie 是否有效</li>
<div class="cookie-tips-note">💡 需要包含 <code>BDUSS</code> 和 <code>STOKEN</code></div>`,

    aliyun: `<li>在电脑上打开 <a href="https://www.aliyundrive.com" target="_blank">aliyundrive.com</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>
<div class="cookie-tips-note">💡 需包含 <code>token</code> 等有效字段</div>`,

    '115': `<li>在电脑上打开 <a href="https://115.com" target="_blank">115.com</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>
<div class="cookie-tips-note">💡 需包含 <code>UID</code>、<code>CID</code>、<code>SEID</code> 等字段</div>`,

    tianyi: `<li>在电脑上打开 <a href="https://cloud.189.cn" target="_blank">cloud.189.cn</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>
<div class="cookie-tips-note">💡 需包含 <code>COOKIE_LOGIN_USER</code>、<code>SESSION</code> 等字段</div>`,

    '123pan': `<li>在电脑上打开 <a href="https://www.123pan.com" target="_blank">123pan.com</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>`,

    uc: `<li>在电脑上打开 <a href="https://drive.uc.cn" target="_blank">drive.uc.cn</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>`,

    xunlei: `<li>在电脑上打开 <a href="https://pan.xunlei.com" target="_blank">pan.xunlei.com</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>`,

    pikpak: `<li>在电脑上打开 <a href="https://www.mypikpak.com" target="_blank">mypikpak.com</a> 并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，找到任意请求 → 复制 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>`,
  }
  return tutorials[t] || `<li>在电脑上打开该网盘网站并登录</li>
<li>按 <code>F12</code> 打开开发者工具 → <strong>网络 (Network)</strong></li>
<li>刷新页面，复制任意请求的 <code>Cookie</code></li>
<li>粘贴到上方输入框，点击「自动获取」验证</li>`
})

onMounted(async () => {
  await loadConfigs()
  await loadCloudTypes()
  await loadSystemConfigs()
})

// 每30分钟自动验证一次
let verifyTimer: ReturnType<typeof setInterval> | null = null
onMounted(() => {
  verifyTimer = setInterval(() => {
    autoVerifyAll()
  }, 30 * 60 * 1000)
})
onUnmounted(() => {
  if (verifyTimer) clearInterval(verifyTimer)
})

async function loadCloudTypes() {
  try {
    const result = await getCloudTypes()
    cloudTypes.value = result.types
  } catch (e) { console.error('加载网盘类型失败', e) }
}

/** 加载系统配置，提取清理白名单目录 */
const systemConfigs = ref<Record<string, string>>({})
const whitelistDirs = computed(() => {
  try {
    const raw = systemConfigs.value.cleanup_whitelist_dirs || '[]'
    const arr = JSON.parse(raw)
    return Array.isArray(arr) && arr.length > 0 ? arr : []
  } catch { return [] }
})

async function loadSystemConfigs() {
  try {
    const list = await getSystemConfigs()
    const map: Record<string, string> = {}
    for (const item of list) {
      map[item.key] = item.value
    }
    systemConfigs.value = map
  } catch (e) { console.error('加载系统配置失败', e) }
}

async function handleCloudToggle(type: string, enabled: boolean) {
  const ct = cloudTypes.value.find(c => c.type === type)
  if (!ct) return
  try {
    await toggleCloudType(type, enabled)
    ct.enabled = enabled
  } catch (e: any) { ElMessage.error(e.message || '切换失败'); ct.enabled = !enabled }
}

async function loadConfigs() {
  try {
    configs.value = await getCloudConfigs()
  } catch (e) {
    console.error('加载网盘配置失败', e)
  }
}

async function handleToggleTransfer(row: CloudConfig, enabled: boolean) {
  const newVal = enabled ? 1 : 0
  try {
    await updateCloudConfig({
      id: row.id!,
      cloud_type: row.cloud_type,
      nickname: row.nickname || '',
      promotion_account: row.promotion_account || '',
      is_active: newVal,
      cookie: undefined, // don't send cookie on toggle-only
    })
    row.is_active = newVal
    ElMessage.success(enabled ? '转存已开启' : '转存已关闭')
  } catch (e: any) {
    ElMessage.error(e.response?.data?.error || '操作失败')
  }
}

async function handleTogglePrimary(row: CloudConfig, enabled: boolean) {
  try {
    await setPrimary(row.id!, enabled)
    row.is_primary = enabled ? 1 : 0
    ElMessage.success(enabled ? `已将「${row.nickname || row.cloud_type}」设为默认账号` : '已取消默认账号')
  } catch (e: any) {
    ElMessage.error(e.response?.data?.error || e.message || '操作失败')
  }
}

async function autoVerifyAll() {
  for (const cfg of configs.value) {
    if (cfg.cookie_preview || cfg.nickname) {
      await verifyOne(cfg, true)
    }
  }
}

async function verifyAll() {
  for (const cfg of configs.value) {
    if ((cfg.cookie_preview || cfg.nickname) && !cfg._verifying) {
      await verifyOne(cfg, false)
    }
  }
  ElMessage.success('全部验证完成')
}

async function verifyOne(row: CloudConfig & { _verifying?: boolean }, silent = false) {
  if (!row.cookie_preview && !row.nickname) {
    if (!silent) ElMessage.warning('该配置没有 Cookie，请先编辑保存后再验证')
    return
  }
  row._verifying = true
  try {
    const result = await testCloudConnection(row.cloud_type, undefined, row.id)
    row.verification_status = result.success ? 'valid' : 'invalid'
    if (result.success) {
      if (result.nickname && !row.nickname) row.nickname = result.nickname
      if (result.storage_used) row.storage_used = result.storage_used
      if (result.storage_total) row.storage_total = result.storage_total
      if (!silent) ElMessage.success(`${CLOUD_LABELS[row.cloud_type]}：${result.message}`)
    } else {
      if (!silent) ElMessage.error(`${CLOUD_LABELS[row.cloud_type]}：${result.message}`)
    }
  } catch (e: any) {
    row.verification_status = 'invalid'
    if (!silent) ElMessage.error(`${CLOUD_LABELS[row.cloud_type]}：验证失败`)
  } finally {
    row._verifying = false
  }
}

function openDialog(row: CloudConfig | null) {
  if (row) {
    editingId.value = row.id ?? null
    form.cloud_type = row.cloud_type
    form.nickname = row.nickname || ''
    form.promotion_account = row.promotion_account || ''
    form.is_transfer_enabled = row.is_active !== 0
    form.cookie = row.cookie || ''
    form._verifying = false
    form._storageUsed = ''
    form._storageTotal = ''
  } else {
    editingId.value = null
    form.cloud_type = '' as CloudType | ''
    form.nickname = ''
    form.promotion_account = ''
    form.is_transfer_enabled = false
    form.cookie = ''
    form._verifying = false
    form._storageUsed = ''
    form._storageTotal = ''
  }
  dialogVisible.value = true
}

function onCloudTypeChange() {
  // Cookie 输入框提示会自动更新（computed）
}

async function handleSave() {
  // 1. 表单校验（含推广账号必填）
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return
  saving.value = true
  try {
    // 2. 如果有 Cookie，验证 Cookie 有效/无效（不回填昵称和空间）
    if (form.cookie) {
      try {
        const verifyResult = await testCloudConnection(form.cloud_type as CloudType, form.cookie)
        if (!verifyResult.success) {
          ElMessage.error(`Cookie验证失败：${verifyResult.message}`)
          saving.value = false
          return
        }
      } catch (e: any) {
        ElMessage.error(`Cookie验证失败：${e.response?.data?.error || '网络错误'}`)
        saving.value = false
        return
      }
    }
    // 3. 保存配置
    if (editingId.value) {
      await updateCloudConfig({
        id: editingId.value,
        cloud_type: form.cloud_type as CloudType,
        nickname: form.nickname,
        promotion_account: form.promotion_account,
        is_active: form.is_transfer_enabled ? 1 : 0,
        cookie: form.cookie || undefined,
      })
      ElMessage.success('配置更新成功')
    } else {
      const saved = await saveCloudConfig({
        cloud_type: form.cloud_type as CloudType,
        nickname: form.nickname,
        promotion_account: form.promotion_account,
        is_active: form.is_transfer_enabled ? 1 : 0,
        cookie: form.cookie,
      })
      ElMessage.success('配置保存成功')
    }
    dialogVisible.value = false
    editingId.value = null
    await loadConfigs()
  } catch (e: any) {
    ElMessage.error(e.response?.data?.error || '保存失败')
  } finally {
    saving.value = false
  }
}

async function handleDelete(row: CloudConfig) {
  try {
    await deleteCloudConfig(row.id!)
    ElMessage.success('删除成功')
    await loadConfigs()
  } catch (e) {
    ElMessage.error('删除失败')
  }
}

/** 解析字节数 → 数值 */
function parseBytes(s: string): number {
  const m = s.match(/^([\d.]+)\s*(B|KB|MB|GB|TB)$/i)
  if (!m) return 0
  const n = parseFloat(m[1])
  const units: Record<string, number> = { B: 1, KB: 1024, MB: 1024**2, GB: 1024**3, TB: 1024**4 }
  return n * (units[m[2].toUpperCase()] || 1)
}

function storagePercent(row: CloudConfig): number {
  if (!row.storage_total || row.storage_total === '-' || !row.storage_used) return 0
  const total = parseBytes(row.storage_total)
  const used = parseBytes(row.storage_used)
  if (total === 0) return 0
  return Math.min(100, Math.round((used / total) * 100))
}

function storageBarClass(row: CloudConfig): string {
  const pct = storagePercent(row)
  if (pct >= 90) return 'bar-danger'
  if (pct >= 70) return 'bar-warning'
  return 'bar-normal'
}

function storageFree(row: CloudConfig): string {
  if (!row.storage_total || row.storage_total === '-') return '?'
  if (!row.storage_used) return '计算中...'
  const total = parseBytes(row.storage_total)
  const used = parseBytes(row.storage_used)
  if (total === 0) return '?'
  const free = total - used
  if (free < 1024) return '小于 1 KB'
  if (free < 1024 * 1024) return (free / 1024).toFixed(1) + ' KB'
  if (free < 1024 * 1024 * 1024) return (free / (1024 * 1024)).toFixed(1) + ' MB'
  if (free < 1024 * 1024 * 1024 * 1024) return (free / (1024 * 1024 * 1024)).toFixed(1) + ' GB'
  return (free / (1024 * 1024 * 1024 * 1024)).toFixed(1) + ' TB'
}
</script>

<style scoped>
.cloud-config {
  /* Uses global card styles from App.vue */
}

/* ── Table card wrapper ── */
.table-card {
  border-radius: var(--radius-lg);
  border: 1px solid var(--border) !important;
  margin-bottom: 20px;
}
.table-card :deep(.el-card__header) {
  font-size: 15px;
  font-weight: 600;
  background: var(--bg-card-header);
  border-bottom: 1px solid var(--border);
  padding: 12px 18px;
}
.table-card :deep(.el-card__body) {
  padding: 0;
}

/* ── Toolbar ── */
.toolbar {
  margin-bottom: 16px;
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

/* ── Table cells ── */
.nickname-text {
  font-weight: 600;
  color: var(--text);
}
.promotion-text {
  font-size: 12px;
  color: var(--text-secondary);
}
.uid-cell {
  font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
  font-size: 11px;
  color: var(--text-tertiary);
  letter-spacing: 0.3px;
}
.save-count {
  font-size: 12px;
  color: var(--text-tertiary);
}
.verifying {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--text-tertiary);
}

/* ── Storage bar ── */
.storage-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 2px 0;
}
.storage-bar-wrap {
  height: 4px;
  background: var(--border-light);
  border-radius: 2px;
  overflow: hidden;
}
.storage-bar-fill {
  height: 100%;
  border-radius: 2px;
  transition: width 0.3s;
}
.storage-bar-fill.bar-normal { background: #67c23a; }
.storage-bar-fill.bar-warning { background: #e6a23c; }
.storage-bar-fill.bar-danger { background: #f56c6c; }
.storage-text {
  font-size: 11px;
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  gap: 3px;
}
.storage-used { color: var(--text-secondary); font-weight: 600; }
.storage-total { color: var(--text); font-weight: 600; }
.storage-free { color: var(--text-tertiary); }

/* ── Cookie tutorial card ── */
.cookie-tips-item :deep(.el-form-item__content) {
  margin-left: 0 !important;
}
.cookie-tips {
  background: #f8faff;
  border: 1px solid #e8f0fe;
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  font-size: 12px;
  line-height: 1.8;
  color: var(--text-secondary);
  width: 100%;
  box-sizing: border-box;
}
.cookie-tips-header {
  margin-bottom: 10px;
}
.cookie-tips-title {
  font-weight: 700;
  color: var(--primary);
  font-size: 13px;
}
.cookie-tips-steps {
  margin: 0;
  padding-left: 20px;
}
.cookie-tips-steps li {
  margin-bottom: 4px;
}
.cookie-tips-steps code {
  background: var(--primary-soft);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 11px;
  font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
}
.cookie-tips-note {
  margin-top: 8px;
  padding: 6px 10px;
  background: #fffbe6;
  border: 1px solid #fff3c4;
  border-radius: 4px;
  color: #8a6d3b;
  font-size: 11px;
  line-height: 1.5;
}
.cookie-tips-note code {
  background: #f5f0e0;
  font-size: 11px;
}

[data-theme="dark"] .cookie-tips {
  background: rgba(64, 158, 255, 0.06);
  border-color: rgba(64, 158, 255, 0.15);
}
[data-theme="dark"] .cookie-tips-title {
  color: #66b1ff;
}
[data-theme="dark"] .cookie-tips-steps code {
  background: rgba(64, 158, 255, 0.12);
}
[data-theme="dark"] .cookie-tips-note {
  background: rgba(255, 193, 7, 0.1);
  border-color: rgba(255, 193, 7, 0.2);
  color: #d4a84b;
}
[data-theme="dark"] .cookie-tips-note code {
  background: rgba(255, 193, 7, 0.12);
}

/* ── Cloud toggle (re-used from AdminDashboard) ── */
.cloud-toggle-grid { display: flex; flex-wrap: wrap; gap: 8px; }
.cloud-toggle-chip { display: flex; align-items: center; gap: 6px; padding: 8px 10px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); }
.cloud-toggle-chip:hover { border-color: var(--primary); }
.cloud-icon-img { width: 20px; height: 20px; object-fit: contain; flex-shrink: 0; }
.cloud-label { font-size: 13px; font-weight: 500; }

/* ── Dialog refinements ── */
:deep(.el-dialog__header) {
  font-weight: 700;
  font-size: 16px;
}
:deep(.el-dialog__body) {
  padding: 20px 24px;
}
:deep(.el-dialog__wrapper .el-dialog) {
  border-radius: var(--radius-lg);
}
</style>
