<template>
  <CustomNav title="血糖" leftType="back" />
  <view class="page">

    <view class="header">
      <view class="month-selector">
        <button class="btn" @click="prevMonth">‹</button>
        <view class="month-label">{{ displayYear }}年 {{ displayMonth }}月</view>
        <button class="btn" @click="nextMonth">›</button>
      </view>
      <picker mode="date" :value="pickerValue" @change="onPickerChange">
        <view class="picker-display">切换月份</view>
      </picker>
    </view>

    <!-- 趋势图 - 简化canvas设置 -->
    <view class="chart-wrap">
      <view class="chart-header">本月趋势</view>
      <canvas 
        canvas-id="bgChart" 
        id="bgChart" 
        class="chart-canvas"
        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
      ></canvas>
    </view>

    <view class="content">
      <view class="summary">共 {{ records.length }} 条记录，本月平均：{{ averageGlucose }} mmol/L</view>

      <view class="list">
        <view v-if="records.length === 0" class="empty">暂无记录，点击右下角 + 添加</view>
        <view v-for="item in records" :key="item.id" class="list-item">
          <view class="date">{{ item.date }}</view>
          <view class="value">{{ item.value }} mmol/L · {{ item.type }}</view>
          <button class="btn-delete" @click="confirmDeleteRecord(item.id)">✕</button>
        </view>
      </view>
    </view>

    <view class="fab" @click="openAdd">
      <view class="fab-inner">+</view>
    </view>

    <view class="modal" v-if="showAdd">
      <view class="modal-backdrop" @click="closeAdd"></view>
      <view class="modal-panel">
        <view class="drag-handle"></view>
        <view class="modal-header"><text class="modal-title">添加血糖</text></view>

        <view class="modal-inner">
          <view class="form-row">
            <text class="label">日期</text>
            <picker mode="date" :value="addDate" @change="onAddDateChange">
              <view class="picker-display">{{ addDateLabel }}</view>
            </picker>
          </view>

          <view class="form-row type-toggle">
            <text class="label">类型</text>
            <view class="type-buttons">
              <button :class="['type-btn', { active: typeIndex === 0 }]" @click="setType(0)">{{ types[0] }}</button>
              <button :class="['type-btn', { active: typeIndex === 1 }]" @click="setType(1)">{{ types[1] }}</button>
            </view>
          </view>

          <view class="form-row">
            <text class="label">{{ types[typeIndex] }}血糖</text>
            <view style="display:flex;align-items:center;gap:8px">
              <input type="number" v-model.number="addGlucose" class="input" :placeholder="`${types[typeIndex]}血糖`" />
              <text class="unit">mmol/L</text>
            </view>
          </view>
        </view>

        <view class="ruler-wrap">
          <ScaleRuler v-if="showAdd" :min="2" :max="16" :step="0.1" :gutter="12" :initialValue="addGlucose ?? 6" @update="onRulerUpdate" @change="onRulerChange" />
        </view>

        <view class="fixed-footer">
          <button class="btn-primary btn-full" @click="confirmAdd">保存</button>
        </view>
      </view>
    </view>

  </view>
  <TabBar />
</template>

<script setup lang="ts">
import { ref, computed, onMounted, watch, nextTick, onBeforeUnmount, getCurrentInstance } from 'vue'
import uCharts from '@qiun/ucharts'
import CustomNav from '@/components/custom-nav.vue'
import TabBar from '@/components/tab-bar.vue'
import ScaleRuler from '@/components/scale-ruler.vue'

type RecordItem = { id: string; date: string; value: number; type: string }

// 当前展示年月
const current = ref(new Date())
const pickerValue = ref(formatPickerDate(current.value))

// 明确的canvas尺寸（将由 getCanvasSize 初始化以匹配设备宽度）
const canvasWidth = ref(700) // 初始值，会在 mounted 时覆盖
const canvasHeight = ref(280)

// 获取Canvas实际尺寸的函数 - 参考微信小程序示例使用固定尺寸
function getCanvasSize(): Promise<{ width: number; height: number }> {
  return new Promise((resolve) => {
    // 使用固定尺寸，参考微信小程序示例
    const windowWidth = uni.getSystemInfoSync().windowWidth;
    const width = windowWidth; // 占满屏幕宽度
    const height = 280 / 750 * windowWidth; // 280rpx转换为px，与CSS高度匹配
    resolve({ width, height });
  });
}

function formatPickerDate(d: Date) {
  const y = d.getFullYear()
  const m = String(d.getMonth() + 1).padStart(2, '0')
  const day = String(d.getDate()).padStart(2, '0')
  return `${y}-${m}-${day}`
}

const displayYear = computed(() => current.value.getFullYear())
const displayMonth = computed(() => current.value.getMonth() + 1)

const records = ref<RecordItem[]>(generateMockRecords(current.value))

function generateMockRecords(d: Date): RecordItem[] {
  const y = d.getFullYear()
  const m = d.getMonth()
  const arr: RecordItem[] = []
  const n = Math.floor(Math.random() * 7)
  const typesLocal = ['空腹', '随机']
  for (let i = 0; i < n; i++) {
    const day = Math.max(1, Math.floor(Math.random() * 28) + 1)
    const date = new Date(y, m, day)
    const val = Number((3 + Math.random() * 10).toFixed(1))
    const type = typesLocal[Math.random() > 0.5 ? 0 : 1]
    arr.push({ 
      id: `${y}${m}${i}${Date.now()}`, 
      date: formatDisplayDate(date), 
      value: val, 
      type 
    })
  }
  return arr.sort((a, b) => (a.date < b.date ? 1 : -1))
}

// 将 records 聚合为每天一个点（取最新记录）
function aggregateDaily(recordsArr: RecordItem[], year: number, month: number) {
  const map = new Map<number, RecordItem>()
  for (const r of recordsArr) {
    const parts = r.date.split('-')
    if (parts.length >= 3) {
      const y = parseInt(parts[0], 10)
      const m = parseInt(parts[1], 10) - 1
      const d = parseInt(parts[2], 10)
      if (y === year && m === month) {
        // 覆盖同一天，保留最新的（数组头部为最新）
        map.set(d, r)
      }
    }
  }
  // 返回按日索引的数组
  return map
}

function formatDisplayDate(d: Date) {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
}

const averageGlucose = computed(() => {
  if (records.value.length === 0) return '--'
  const sum = records.value.reduce((s, r) => s + r.value, 0)
  return (sum / records.value.length).toFixed(1)
})

function daysInMonth(year: number, month: number) {
  return new Date(year, month + 1, 0).getDate()
}

// Canvas / uCharts 绘图 - 修复版本
const chartInstance = ref<any>(null)
const vm = getCurrentInstance()
let chartInitialized = false
let chartBusy = false // 绘图锁，防止并发初始化/更新

// 简化的图表绘制函数
async function drawChart() {
  // 防止并发调用
  if (chartBusy) return
  chartBusy = true

  // 防止重复初始化（已初始化则更新数据）
  if (chartInitialized && chartInstance.value) {
    try {
      await updateChartData()
    } finally {
      chartBusy = false
    }
    return
  }

  // 清理旧实例
  if (chartInstance.value) {
    try {
      if (chartInstance.value.destroy) {
        chartInstance.value.destroy()
      }
    } catch (e) {
      console.warn('Destroy chart error:', e)
    }
    chartInstance.value = null
  }

  if (typeof uCharts === 'undefined') {
    console.warn('uCharts not available')
    return
  }

  // 动态获取 Canvas 容器的宽高 (单位: px)
  const size = await getCanvasSize();
  const cssWidth = size.width;
  const cssHeight = size.height;

  // 获取可靠的设备像素比 - 固定为1避免高分辨率设备上元素过大
  const pixelRatio = 1; // 关键修复：固定pixelRatio为1

  // 为避免 X 轴标签或绘图区域右侧溢出，保留右侧间距，让绘图区域略窄于 canvas
  const rightGap = Math.max(24, Math.round(cssWidth * 0.04)) // 最小 24px 或 4% 屏宽
  const chartWidth = Math.max(cssWidth - rightGap, Math.round(cssWidth * 0.85))

  console.log('Canvas 尺寸与像素比:', { cssWidth, cssHeight, pixelRatio });

  const year = current.value.getFullYear()
  const month = current.value.getMonth()
  const days = daysInMonth(year, month)
  
  // 生成合理的categories - 只显示关键日期
  const categories: string[] = []
  const showLabelDays = []
  
  // 选择要显示的标签：1号、中间几天、最后一天
  if (days > 0) {
    showLabelDays.push(1) // 第1天
    if (days > 1) showLabelDays.push(days) // 最后一天
    // 中间添加2-3个关键点
    if (days > 7) showLabelDays.push(Math.ceil(days / 3))
    if (days > 14) showLabelDays.push(Math.ceil(days * 2 / 3))
  }
  
  for (let d = 1; d <= days; d++) {
    if (showLabelDays.includes(d)) {
      categories.push(`${d}日`)
    } else {
      categories.push('')
    }
  }

  // 只为有记录的天生成categories和data，避免将无数据天设为0
  const data: number[] = []
  const filteredCategories: string[] = []
  // 使用Map按日聚合，保留最新记录（records 数组头部为最新）
  const dayMap = new Map<number, RecordItem>()
  for (const r of records.value) {
    const parts = r.date.split('-')
    if (parts.length >= 3) {
      const y = parseInt(parts[0], 10)
      const m = parseInt(parts[1], 10) - 1
      const d = parseInt(parts[2], 10)
      if (y === year && m === month) {
        // 以最后遍历到的（数组顺序保证头部为最新）作为最终值
        dayMap.set(d, r)
      }
    }
  }

  // 将有数据的日期按日顺序输出
  const sortedDays = Array.from(dayMap.keys()).sort((a, b) => a - b)
  for (const d of sortedDays) {
    const rec = dayMap.get(d)!
    filteredCategories.push(`${d}日`)
    data.push(rec.value)
  }

  // 如果没有任何数据，则回退为整月空数据（避免 uCharts 抛错）
  const categoriesToUse = filteredCategories.length ? filteredCategories : categories

  // 计算合理的Y轴范围
  const validData = data.filter(v => v > 0)
  const minVal = validData.length ? Math.floor(Math.min(...validData)) - 1 : 2
  const maxVal = validData.length ? Math.ceil(Math.max(...validData)) + 1 : 12

  const series = [{
    name: '血糖',
    data: data,
    color: '#ff6a00'
  }]

  // 获取canvas上下文
  let ctx: any = null
  try {
    if (typeof uni !== 'undefined' && typeof uni.createCanvasContext === 'function') {
      // 小程序环境：优先尝试传入组件实例
      try {
        ctx = vm?.proxy ? uni.createCanvasContext('bgChart', vm.proxy) : uni.createCanvasContext('bgChart')
      } catch (e) {
        // 再尝试不传vm
        try { ctx = uni.createCanvasContext('bgChart') } catch (err) { ctx = null }
      }
    }
  } catch (e) {
    ctx = null
  }

  // H5环境尝试使用DOM获取2D上下文
  if (!ctx && typeof document !== 'undefined') {
    try {
      // 重试逻辑：初次可能未渲染到 DOM
      let el: HTMLCanvasElement | null = null
      for (let attempt = 0; attempt < 3; attempt++) {
        el = document.getElementById('bgChart') as HTMLCanvasElement | null
        if (el) break
        // 短延迟后重试（非阻塞）
        await new Promise(r => setTimeout(r, 50))
      }
      
      if (el && el.getContext) {
        // Ensure canvas actual pixel size matches cssWidth * pixelRatio
        try {
          const physicalW = Math.floor(cssWidth * pixelRatio)
          const physicalH = Math.floor(cssHeight * pixelRatio)
          if (el.width !== physicalW || el.height !== physicalH) {
            el.width = physicalW
            el.height = physicalH
            // also adjust style to keep layout consistent
            el.style.width = cssWidth + 'px'
            el.style.height = cssHeight + 'px'
          }
        } catch (e) {
          console.warn('Set canvas physical size failed', e)
        }
        ctx = el.getContext('2d')
      }
    } catch (e) {
      ctx = null
    }
  }

  if (!ctx) {
    console.warn('Unable to obtain canvas context for uCharts. Ensure canvas-id matches and vm proxy is available on mini-program.')
    return
  }

  console.log('Canvas config:', {
    width: cssWidth,
    height: cssHeight,
    pixelRatio,
    categoriesLength: categories.length,
    dataPoints: data.length
  })

  // 简化的uCharts配置 - 关闭所有可能产生重叠的选项
  const config = {
    $this: vm?.proxy,
    canvasId: 'bgChart',
    context: ctx,
    type: 'line',
    fontSize: 10, // 全局字体大小，参考微信小程序示例
    categories: categoriesToUse,
    series: series,
    // 使用比 canvas 略窄的绘图宽度并设置 padding 来避免右边溢出
    width: chartWidth,
    padding: [10, rightGap + 8, 18, 10],
    height: cssHeight,
    pixelRatio: pixelRatio,
    background: 'transparent',
    animation: false, // 关闭动画避免干扰
    enableScroll: false,
    dataLabel: false, // 关键：关闭数据点标签
    legend: {
      show: false
    },
    xAxis: {
      disableGrid: true, // 简化网格
      axisLine: true,
      axisLineColor: '#e0e0e0',
      fontColor: '#666666',
      fontSize: 10, // 进一步调小X轴字体
      boundaryGap: 'justify'
    },
    yAxis: {
      disableGrid: false,
      gridColor: '#f5f5f5',
      splitNumber: 4, // 减少分割数
      min: minVal,
      max: maxVal,
      axisLine: true,
      axisLineColor: '#e0e0e0',
      fontColor: '#666666',
      fontSize: 10, // 进一步调小Y轴字体
      format: (val: number) => val % 1 === 0 ? `${val}mmol/L` : '' // 只显示整数值
    },
    extra: {
      line: {
        type: 'curve',
        width: 1, // 进一步调细线宽
        activeType: 'point', // 简化点样式
        point: {
          radius: 0.5, // 进一步调小数据点半径
          strokeWidth: 0.5 // 调小边框宽度
        }
      },
      tooltip: {
        showBox: false, // 关闭提示框避免重叠
        showCategory: false
      }
    }
  }

  try {
    // 在创建新实例前确保销毁旧实例
    if (chartInstance.value && chartInstance.value.destroy) {
      try { chartInstance.value.destroy() } catch (e) { console.warn('destroy before init failed', e) }
      chartInstance.value = null
      chartInitialized = false
    }

    chartInstance.value = new uCharts(config)
    chartInitialized = true
    console.log('uCharts initialized successfully')
  } catch (error) {
    console.error('uCharts init error:', error)
    chartInitialized = false
  }
  chartBusy = false
}

// 更新数据而不重新初始化
async function updateChartData() {
  if (chartBusy) return
  chartBusy = true

  if (!chartInstance.value || !chartInitialized) {
    try {
      await drawChart()
    } finally {
      chartBusy = false
    }
    return
  }

  const year = current.value.getFullYear()
  const month = current.value.getMonth()
  const days = daysInMonth(year, month)
  
  const categories: string[] = []
  const showLabelDays = []
  
  if (days > 0) {
    showLabelDays.push(1)
    if (days > 1) showLabelDays.push(days)
    if (days > 7) showLabelDays.push(Math.ceil(days / 3))
    if (days > 14) showLabelDays.push(Math.ceil(days * 2 / 3))
  }
  
  for (let d = 1; d <= days; d++) {
    if (showLabelDays.includes(d)) {
      categories.push(`${d}日`)
    } else {
      categories.push('')
    }
  }

  // 只为有记录的天生成categories和data
  const data: number[] = []
  const filteredCategories: string[] = []
  const dayMap = new Map<number, RecordItem>()
  for (const r of records.value) {
    const parts = r.date.split('-')
    if (parts.length >= 3) {
      const y = parseInt(parts[0], 10)
      const m = parseInt(parts[1], 10) - 1
      const d = parseInt(parts[2], 10)
      if (y === year && m === month) {
        dayMap.set(d, r)
      }
    }
  }
  const sortedDays = Array.from(dayMap.keys()).sort((a, b) => a - b)
  for (const d of sortedDays) {
    const rec = dayMap.get(d)!
    filteredCategories.push(`${d}日`)
    data.push(rec.value)
  }
  const categoriesToUse = filteredCategories.length ? filteredCategories : categories

  const validData = data.filter(v => v > 0)
  const minVal = validData.length ? Math.floor(Math.min(...validData)) - 1 : 2
  const maxVal = validData.length ? Math.ceil(Math.max(...validData)) + 1 : 12

  try {
    // 使用uCharts的更新方法，仅更新有数据的分类和序列
    // 若实例存在，先更新宽度/padding（如果有配置）以避免右侧溢出
    try {
      const size = await getCanvasSize()
      const cssWidth = size.width
      const rightGap = Math.max(24, Math.round(cssWidth * 0.04))
      const chartWidth = Math.max(cssWidth - rightGap, Math.round(cssWidth * 0.85))
      if (chartInstance.value.opts) {
        chartInstance.value.opts.width = chartWidth
        chartInstance.value.opts.padding = [10, rightGap + 8, 18, 10]
      }
    } catch (e) {
      // 忽略尺寸更新错误
    }

    chartInstance.value.updateData({
      categories: categoriesToUse,
      series: [{
        name: '血糖',
        data: data,
        color: '#ff6a00'
      }]
    })

    // 更新Y轴范围
    chartInstance.value.opts.yAxis.min = minVal
    chartInstance.value.opts.yAxis.max = maxVal

  } catch (error) {
    console.error('Update chart error:', error)
    // 如果更新失败，重新销毁并重建实例
    try {
      if (chartInstance.value && chartInstance.value.destroy) chartInstance.value.destroy()
    } catch (e) { console.warn('destroy on update failure failed', e) }
    chartInstance.value = null
    chartInitialized = false
    try {
      await drawChart()
    } catch (e) { console.error('re-init after update failure also failed', e) }
  }
  chartBusy = false
}

onMounted(() => {
  // 延迟确保DOM渲染完成
  setTimeout(async () => {
    await nextTick()
    // 由 getCanvasSize 计算并覆盖 canvasWidth/canvasHeight（确保模板样式和绘图一致）
    try {
      const size = await getCanvasSize()
      canvasWidth.value = size.width
      canvasHeight.value = size.height
    } catch (e) {
      console.warn('getCanvasSize failed on mounted', e)
    }
    await drawChart()
  }, 500)
})

// 简化监听，避免频繁重绘
watch([() => current.value], async () => {
  setTimeout(async () => {
    await updateChartData()
  }, 100)
})

watch([() => records.value], async () => {
  setTimeout(async () => {
    await updateChartData()
  }, 100)
}, { deep: true })

onBeforeUnmount(() => {
  if (chartInstance.value && chartInstance.value.destroy) {
    try {
      chartInstance.value.destroy()
    } catch (e) {
      console.warn('uCharts destroy error:', e)
    }
  }
  chartInstance.value = null
  chartInitialized = false
})

// 强制重建图表（用于切换月份时彻底刷新，如同退出页面再进入）
async function rebuildChart() {
  // 如果正在绘制，等一小会儿再销毁
  if (chartBusy) {
    // 等待最大 300ms，避免长时间阻塞
    await new Promise(r => setTimeout(r, 50))
  }
  try {
    if (chartInstance.value && chartInstance.value.destroy) {
      try { chartInstance.value.destroy() } catch (e) { console.warn('destroy in rebuildChart failed', e) }
    }
  } catch (e) {
    console.warn('rebuildChart destroy error', e)
  }
  chartInstance.value = null
  chartInitialized = false
  // 等待 DOM/Tick 稳定
  await nextTick()
  // 重新初始化
  try {
    await drawChart()
  } catch (e) {
    console.error('rebuildChart drawChart failed', e)
  }
}

// 其他函数保持不变
async function prevMonth() {
  const d = new Date(current.value)
  d.setMonth(d.getMonth() - 1)
  current.value = d
  pickerValue.value = formatPickerDate(d)
  records.value = generateMockRecords(d)
  await rebuildChart()
}

async function nextMonth() {
  const d = new Date(current.value)
  d.setMonth(d.getMonth() + 1)
  current.value = d
  pickerValue.value = formatPickerDate(d)
  records.value = generateMockRecords(d)
  await rebuildChart()
}

async function onPickerChange(e: any) {
  const val = e?.detail?.value || e
  const parts = (val as string).split('-')
  if (parts.length >= 2) {
    const y = parseInt(parts[0], 10)
    const m = parseInt(parts[1], 10) - 1
    const d = new Date(y, m, 1)
    current.value = d
    pickerValue.value = formatPickerDate(d)
    records.value = generateMockRecords(d)
    await rebuildChart()
  }
}

// 添加逻辑保持不变
const showAdd = ref(false)
const addDate = ref(formatPickerDate(new Date()))
const addDateLabel = ref(formatDisplayDate(new Date()))
const types = ['空腹', '随机']
const typeIndex = ref(0)
const addGlucose = ref<number | null>(null)

function setType(idx: number) { typeIndex.value = idx }

function onTypeChange(e: any) { typeIndex.value = e?.detail?.value ?? e }
function onRulerUpdate(v: number) { addGlucose.value = Number(v.toFixed ? Number(v.toFixed(1)) : v) }
function onRulerChange(v: number) { addGlucose.value = Number(v.toFixed ? Number(v.toFixed(1)) : v) }

function openAdd() { showAdd.value = true; if (!addGlucose.value) addGlucose.value = 6 }
function closeAdd() { showAdd.value = false; addGlucose.value = null }

function onAddDateChange(e: any) { const val = e?.detail?.value || e; addDate.value = val; addDateLabel.value = val.replace(/^(.{10}).*$/, '$1') }

async function confirmAdd() {
  if (!addGlucose.value) { 
    uni.showToast && uni.showToast({ title: '请输入血糖值', icon: 'none' }); 
    return 
  }
  const id = `user-${Date.now()}`
  const item: RecordItem = { 
    id, 
    date: addDateLabel.value, 
    value: Number(Number(addGlucose.value).toFixed(1)), 
    type: types[typeIndex.value] 
  }
  const parts = addDate.value.split('-')
  const addY = parseInt(parts[0], 10)
  const addM = parseInt(parts[1], 10) - 1
  if (addY === current.value.getFullYear() && addM === current.value.getMonth()) { 
    records.value = [item, ...records.value] 
  }
  uni.showToast && uni.showToast({ title: '已添加', icon: 'success' })
  closeAdd()
  // 新增记录后彻底重建图表，确保像退出再进入一样刷新
  try {
    await rebuildChart()
  } catch (e) {
    console.warn('rebuildChart after add failed', e)
  }
}

async function confirmDeleteRecord(id: string) { 
  if (typeof uni !== 'undefined' && uni.showModal) { 
    uni.showModal({ 
      title: '删除', 
      content: '确认删除该条记录吗？', 
      success: async (res: any) => { 
        if (res.confirm) {
          records.value = records.value.filter(r => r.id !== id)
          try { await rebuildChart() } catch (e) { console.warn('rebuildChart after delete failed', e) }
        }
      } 
    }) 
  } else { 
    records.value = records.value.filter(r => r.id !== id)
    try { await rebuildChart() } catch (e) { console.warn('rebuildChart after delete failed', e) }
  } 
}
</script>

<style scoped>
.page { 
  min-height: calc(100vh); 
  padding-top: calc(var(--status-bar-height) + 44px); 
  background: #f5f6f8; 
  box-sizing: border-box 
}

.header { 
  padding: 20rpx 40rpx 
}

.month-selector { 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  gap: 12rpx 
}

.month-label { 
  font-size: 34rpx; 
  color: #333 
}

.btn { 
  background: transparent; 
  border: none; 
  font-size: 36rpx; 
  color: #666 
}

.content { 
  padding: 20rpx 24rpx 100rpx 24rpx 
}

.chart-wrap { 
  background: #fff; 
  border-radius: 12rpx; 
  padding: 24rpx; 
  margin: 0 24rpx 20rpx 24rpx; 
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03) 
}

.chart-header { 
  font-size: 32rpx; 
  color: #333; 
  margin-bottom: 20rpx; 
  font-weight: 600 
}

/* 关键修复：确保canvas样式正确，参考微信小程序示例 */
.chart-canvas {
  width: 750rpx;
  height: 280rpx;
  background-color: #FFFFFF;
  display: block;
}

.summary { 
  padding: 20rpx; 
  color: #666; 
  font-size: 28rpx 
}

.list { 
  background: #fff; 
  border-radius: 12rpx; 
  padding: 10rpx; 
  box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03) 
}

.empty { 
  padding: 40rpx; 
  text-align: center; 
  color: #999 
}

.list-item { 
  display: flex; 
  align-items: center; 
  padding: 20rpx; 
  border-bottom: 1rpx solid #f0f0f0 
}

.list-item .date { 
  color: #666 
}

.list-item .value { 
  color: #333; 
  font-weight: 600; 
  flex: 1; 
  text-align: right 
}

.btn-delete { 
  width: 80rpx; 
  height: 60rpx; 
  min-width: 60rpx; 
  min-height: 60rpx; 
  display: inline-flex; 
  align-items: center; 
  justify-content: center; 
  background: #fff0f0; 
  color: #d9534f; 
  border: 1rpx solid rgba(217,83,79,0.15); 
  border-radius: 8rpx; 
  margin-left: 30rpx 
}

.fab { 
  position: fixed; 
  right: 28rpx; 
  bottom: 160rpx; 
  width: 110rpx; 
  height: 110rpx; 
  border-radius: 999px; 
  background: linear-gradient(180deg, #ff7a00, #ff4a00); 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  box-shadow: 0 6rpx 18rpx rgba(0, 0, 0, 0.2); 
  z-index: 1200 
}

.fab-inner { 
  color: #fff; 
  font-size: 56rpx; 
  line-height: 56rpx 
}

.modal { 
  position: fixed; 
  left: 0; 
  right: 0; 
  top: 0; 
  bottom: 0; 
  display: flex; 
  align-items: flex-end; 
  justify-content: center; 
  z-index: 1300 
}

.modal-backdrop { 
  position: absolute; 
  left: 0; 
  right: 0; 
  top: 0; 
  bottom: 0; 
  background: rgba(0, 0, 0, 0.4) 
}

.modal-panel { 
  position: relative; 
  width: 100%; 
  background: #fff; 
  border-top-left-radius: 18rpx; 
  border-top-right-radius: 18rpx; 
  padding: 28rpx 24rpx 140rpx 24rpx; 
  box-shadow: 0 -8rpx 30rpx rgba(0,0,0,0.12) 
}

.modal-title { 
  font-size: 56rpx; 
  margin-block: 60rpx; 
  color: #222; 
  font-weight: 700; 
  letter-spacing: 1rpx 
}

.modal-inner { 
  max-width: 70%; 
  margin: 0 auto 
}

.form-row { 
  display: flex; 
  align-items: center; 
  justify-content: space-between; 
  margin-bottom: 34rpx; 
  padding: 14rpx 0; 
  font-size: 32rpx 
}

.input { 
  width: 150rpx; 
  text-align: right; 
  padding: 16rpx; 
  border-radius: 14rpx; 
  border: 1rpx solid #eee; 
  background: #fff7f0 
}

.picker-display { 
  color: #333 
}

.btn-primary { 
  background: #ff6a00; 
  color: #fff; 
  padding: 18rpx 22rpx; 
  border-radius: 16rpx; 
  text-align: center; 
  width: 50%; 
  box-shadow: 0 10rpx 28rpx rgba(255,106,0,0.18) 
}

.drag-handle { 
  width: 64rpx; 
  height: 6rpx; 
  background: rgba(0,0,0,0.08); 
  border-radius: 999px; 
  margin: 10rpx auto 14rpx auto 
}

.modal-header { 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  gap: 12rpx; 
  margin-bottom: 6rpx 
}

.label { 
  color: #666 
}

.ruler-wrap { 
  margin: 12rpx 0 
}

.type-buttons { 
  display: flex; 
  gap: 12rpx 
}

.type-btn { 
  padding: 8rpx 18rpx; 
  border-radius: 12rpx; 
  border: 1rpx solid #eee; 
  background: #fff; 
  color: #333 
}

.type-btn.active { 
  background: #ff6a00; 
  color: #fff; 
  border-color: #ff6a00 
}

.unit { 
  color: #666; 
  font-size: 28rpx 
}

.fixed-footer { 
  position: absolute; 
  left: 0; 
  right: 0; 
  bottom: 40rpx; 
  padding: 0 24rpx 
}

.btn-full { 
  width: 100%; 
  padding: 18rpx; 
  border-radius: 12rpx; 
}
</style>