<template>
  <div
    class="assembly-dashboard"
    :style="{ width: `${style.width}px`, height: `${style.height}px`, transform: style.transform }"
  >
    <div class="dashboard-shell">
      <header class="dashboard-header">
        <div class="brand">
          <img class="brand-logo" :src="clientLogoUrl" alt="RENLY" />
        </div>
        <h1>装配中心任务看板</h1>
        <div class="current-time">{{ currentTime }}</div>
      </header>

      <main class="dashboard-content">
        <section class="status-row">
          <article v-for="item in topStats" :key="item.key" class="panel stat-card" :class="item.className">
            <div class="stat-title">{{ item.title }}</div>
            <div class="stat-value">
              <span>{{ item.value }}</span>
              <small v-if="item.unit">{{ item.unit }}</small>
            </div>
          </article>
        </section>

        <section class="main-grid">
          <article class="panel table-panel aggregate-panel">
            <div class="panel-caption">装配任务分类汇总</div>
            <!-- <div class="aggregate-tip">统计口径：计划数量 &gt; 完成数量，辅助配件选择“包含”。</div> -->
            <div class="summary-wrap">
              <table class="summary-table">
                <thead>
                  <tr>
                    <th class="group-th">项目</th>
                    <th class="subclass-th">产品</th>
                    <th class="metric-th">指标</th>
                    <!-- <th>条件</th> -->
                    <th class="count-th">数量</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="row in aggregateRows" :key="`${row.categoryKey}-${row.metricKey}`">
                    <td v-if="row.parentRowspan" :rowspan="row.parentRowspan" class="group-cell">
                      <div class="category-total">
                        <span>{{ row.parent }}</span>
                        <strong>{{ row.parentTotal }}</strong>
                      </div>
                    </td>
                    <td
                      v-if="row.childRowspan"
                      :rowspan="row.childRowspan"
                      class="subclass-cell"
                    >
                      
                      <div class="subclass-content">
                        <img class="subclass-image" :src="row.image" alt="" />
                        <div class="category-total subclass-total">
                          <span>{{ row.child }}</span>
                          <strong>{{ row.childTotal }}</strong>
                        </div>
                        
                      </div>
                    </td>
                    <td class="metric-cell" :class="`metric-${row.metricKey}`">{{ row.metric }}</td>
                    <!-- <td class="condition-cell">{{ row.condition }}</td> -->
                    <td class="count-cell" :class="`metric-${row.metricKey}`">{{ row.value }}</td>
                  </tr>
                </tbody>
              </table>
            </div>
          </article>

          <aside class="right-column">
            <article class="panel table-panel">
              <div class="panel-caption">发货任务列表</div>
              <div class="scroll-wrap">
                <table>
                  <thead>
                    <tr>
                      <th class="idx-th">序号</th>
                      <th v-for="column in deliveryColumns" :key="column.key" :style="{ width: column.width }">
                        {{ column.label }}
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="row in deliveryDisplayRows" :key="`delivery-${row._idx}`">
                      <td class="idx-td">{{ row._idx }}</td>
                      <td
                        v-for="column in deliveryColumns"
                        :key="column.key"
                        :class="getCellClass(column.key, row[column.key])"
                      >
                        {{ row[column.key] }}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>

            <article class="panel table-panel task-panel">
              <div class="panel-caption">在制任务列表</div>
              <div class="scroll-wrap">
                <table>
                  <thead>
                    <tr>
                      <th class="idx-th">序号</th>
                      <th v-for="column in taskColumns" :key="column.key" :style="{ width: column.width }">
                        {{ column.label }}
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr v-for="row in taskDisplayRows" :key="`task-${row._idx}`" :class="{ warning: row.urgentQty > 0 }">
                      <td class="idx-td">{{ row._idx }}</td>
                      <td
                        v-for="column in taskColumns"
                        :key="column.key"
                        :class="getCellClass(column.key, row[column.key])"
                      >
                        {{ row[column.key] }}
                      </td>
                    </tr>
                  </tbody>
                </table>
              </div>
            </article>
          </aside>
        </section>
      </main>
    </div>
  </div>
</template>

<script setup>
import { computed, inject, onMounted, onUnmounted, reactive, ref } from 'vue'
import assemblyImage from '@/assets/dashboard/机械.png'
import electricImage from '@/assets/dashboard/电气.png'
import otherImage from '@/assets/dashboard/其他.png'
import valveImage from '@/assets/dashboard/阀.png'

defineOptions({ name: 'AssemblyCenterTaskDashboard' })

const CreateData = inject('CreateData')
const ExecDatabase = inject('ExecDatabase')

const clientLogoUrl = './public/ClientLogo.png'
const now = ref(new Date())
const style = reactive({
  width: 1920,
  height: 1080,
  transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)'
})

let clockTimer = null
let refreshTimer = null
let resizeHandler = null
let scrollTimers = []

const deliveryRows = ref([])
const taskRows = ref([])
const valveTaskRows = ref([])
const systemTaskRows = ref([])
const stagnationRows = ref([])

const deliveryOffset = ref(0)
const taskOffset = ref(0)
const passRate = ref('100%')
const exceptionCount = ref(0)

const VISIBLE_ROWS = {
  delivery: 7,
  task: 7
}

const metricDefinitions = [
  { key: 'dispatch', label: '派工', condition: '派工时间不为空' },
  { key: 'completeSet', label: '齐套', condition: '任务状态为可执行' },
  { key: 'urgent', label: '加急', condition: '加急总数大于0' },
  { key: 'stagnation', label: '滞留', condition: '未及时送检' }
]

const categoryGroups = [
  {
    parent: '部件类',
    children: [
      { key: 'valveMain', label: '阀', image: valveImage },
      { key: 'valveOther', label: '其他', image: otherImage }
    ]
  },
  {
    parent: '系统类',
    children: [
      { key: 'systemElectric', label: '电气', image: electricImage },
      { key: 'systemAssembly', label: '装配', image: assemblyImage }
    ]
  }
]

const pad = value => String(value).padStart(2, '0')

const currentTime = computed(() => {
  const date = now.value
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
})

const topStats = computed(() => [
  { key: 'dispatch', title: '派工汇总', value: getMetricTotal('dispatch'), unit: '条', className: 'blue-stat' },
  { key: 'completeSet', title: '齐套汇总', value: getMetricTotal('completeSet'), unit: '条', className: 'green-stat' },
  { key: 'urgent', title: '加急汇总', value: getMetricTotal('urgent'), unit: '条', className: 'red-stat' },
  { key: 'stagnation', title: '滞留汇总', value: getMetricTotal('stagnation'), unit: '条', className: 'orange-stat' },
  { key: 'passRate', title: '装配合格率', value: passRate.value, unit: '', className: 'green-stat' },
  { key: 'exception', title: '异常未关闭', value: exceptionCount.value, unit: '条', className: 'red-stat' }
])

const aggregateRows = computed(() => {
  const rows = []

  categoryGroups.forEach(group => {
    const parentTotal = getGroupTotal(group)

    group.children.forEach(child => {
      const childTotal = getCategoryTotal(child.key)

      metricDefinitions.forEach(metric => {
        rows.push({
          parent: group.parent,
          parentTotal,
          parentRowspan: rows.filter(item => item.parent === group.parent).length === 0
            ? group.children.length * metricDefinitions.length
            : 0,
          child: child.label,
          childTotal,
          image: child.image,
          childRowspan: metric.key === metricDefinitions[0].key ? metricDefinitions.length : 0,
          categoryKey: child.key,
          metricKey: metric.key,
          metric: metric.label,
          condition: metric.condition,
          value: countRows(child.key, metric.key)
        })
      })
    })
  })

  return rows
})

const deliveryDisplayRows = computed(() => makeDisplayRows(deliveryRows.value, deliveryOffset.value, VISIBLE_ROWS.delivery, false))
const taskDisplayRows = computed(() => makeDisplayRows(taskRows.value, taskOffset.value, VISIBLE_ROWS.task))

onMounted(() => {
  startClock()
  setScale()
  resizeHandler = setScale
  window.addEventListener('resize', resizeHandler)
  searchDashboardData()
  startAllScroll()
  refreshTimer = window.setInterval(searchDashboardData, 600000)
})

onUnmounted(() => {
  if (clockTimer) {
    window.clearInterval(clockTimer)
  }
  if (refreshTimer) {
    window.clearInterval(refreshTimer)
  }
  if (resizeHandler) {
    window.removeEventListener('resize', resizeHandler)
  }
  stopAllScroll()
})

const setScale = () => {
  const scale = getScale()
  style.transform = `scaleY(${scale.y}) scaleX(${scale.x}) translate(-50%, -50%)`
}

const getScale = () => ({
  x: window.innerWidth / style.width,
  y: window.innerHeight / style.height
})

const startClock = () => {
  now.value = new Date()
  clockTimer = window.setInterval(() => {
    now.value = new Date()
  }, 1000)
}

const startAllScroll = () => {
  startScroll(deliveryRows, deliveryOffset, VISIBLE_ROWS.delivery, false)
  startScroll(taskRows, taskOffset, VISIBLE_ROWS.task)
}

const startScroll = (rowsRef, offsetRef, visibleCount, loop = true) => {
  const timerId = window.setInterval(() => {
    if (rowsRef.value.length <= visibleCount) {
      offsetRef.value = 0
      return
    }

    if (loop) {
      offsetRef.value = (offsetRef.value + 1) % rowsRef.value.length
      return
    }

    const maxOffset = rowsRef.value.length - visibleCount
    offsetRef.value = offsetRef.value >= maxOffset ? 0 : offsetRef.value + 1
  }, 2500)
  scrollTimers.push(timerId)
}

const stopAllScroll = () => {
  scrollTimers.forEach(timerId => window.clearInterval(timerId))
  scrollTimers = []
}

const makeDisplayRows = (rows, offset, visibleCount, loop = true) => {
  if (!Array.isArray(rows) || rows.length === 0) {
    return []
  }

  if (!loop) {
    const maxOffset = Math.max(rows.length - visibleCount, 0)
    const safeOffset = Math.min(Math.max(offset, 0), maxOffset)
    return rows.slice(safeOffset, safeOffset + visibleCount).map((row, index) => ({
      ...row,
      _idx: safeOffset + index + 1
    }))
  }

  const displayRows = []
  for (let index = 0; index < visibleCount; index += 1) {
    const rowIndex = (offset + index) % rows.length
    displayRows.push({ ...rows[rowIndex], _idx: rowIndex + 1 })
  }
  return displayRows
}

const searchDashboardData = () => {
  searchDeliveryData()
  searchTaskData()
  searchPassRateData()
  searchUnclosedData()
  searchAggregateTaskData()
  searchStagnationData()
}

const searchDeliveryData = () => {
  queryDashboardData('装配中心任务看板_发货状态查询', [], applyDeliveryData)
}

const searchTaskData = () => {
  queryDashboardData('装配中心任务看板_装配在制任务查询', [], applyTaskData)
}

const searchPassRateData = () => {
  queryDashboardData('装配中心任务看板_装配合格率', [], applyPassRateData)
}

const searchUnclosedData = () => {
  queryDashboardData('装配中心任务看板_异常未关闭总数', [], applyUnclosedData)
}

const searchAggregateTaskData = () => {
  const params = createPlanQueryParams()
  queryDashboardData('计划排产_阀类任务查询', params, rows => {
    valveTaskRows.value = rows.map(row => ({ ...row, _sourceType: 'valve' }))
  }, 50000, 1)
  queryDashboardData('计划排产_系统类任务查询', params, rows => {
    systemTaskRows.value = rows.map(row => ({ ...row, _sourceType: 'system' }))
  }, 50000, 1)
}

const searchStagnationData = () => {
  const params = [
    ['订单号', 0],
    ['合同号', ''],
    ['产品编码', ''],
    ['产品名称', ''],
    ['工序名称', ''],
    ['辅助配件', '包含']
  ]
  queryDashboardData('异常提醒_装配及时送检_查询', params, rows => {
    stagnationRows.value = rows
  })
}

const createPlanQueryParams = () => [
  ['订单号', 0],
  ['物料类型', '自制件'],
  ['合同号', ''],
  ['产品编码', ''],
  ['产品名称', ''],
  ['工序名称', ''],
  ['要求完工日期1', undefined],
  ['要求完工日期2', undefined],
  ['计划开始', ''],
  ['计划完成', ''],
  ['排产状态', '已完成'],
  ['辅助配件', '包含'],
  ['指派对象', '全部']
]

const queryDashboardData = (procedureName, params, applyData, pageSize, pageCurrent) => {
  const data = CreateData('11', procedureName, params, pageSize, pageCurrent)
  ExecDatabase(data)
    .then(response => {
      applyData(getResponseRows(response))
    })
    .catch(error => {
      console.error(`${procedureName} 查询失败:`, error)
      applyData([])
    })
}

const getResponseRows = response => {
  if (response && Array.isArray(response.data)) {
    return response.data
  }
  if (response && response.data && Array.isArray(response.data.rows)) {
    return response.data.rows
  }
  if (response && response.data && Array.isArray(response.data.result)) {
    return response.data.result
  }
  return []
}

const applyDeliveryData = rows => {
  deliveryRows.value = rows.map(item => ({
    productionOrder: normalizeText(item.订单编号 || item.订单号),
    salesOrder: normalizeText(item.合同号),
    materialName: normalizeText(item.物料描述 || item.产品名称),
    materialCode: normalizeText(item.物料编号 || item.产品编码),
    quantity: formatQuantity(item.交货数量 || item.计划数量),
    requiredDate: formatDate(item.要求发货日期),
    completeSet: formatComplete(item.齐套),
    issueStatus: formatSendStatus(item.发料状态),
    operator: normalizeText(item.操作人),
    startStatus: item.合同装配工时
  }))
}

const applyTaskData = rows => {
  taskRows.value = rows.map(item => ({
    productionOrder: normalizeText(item.订单号),
    salesOrder: normalizeText(item.合同号),
    materialName: normalizeText(item.零件名称 || item.产品名称),
    materialCode: normalizeText(item.零件编码 || item.产品编码),
    completeSet: formatComplete(item.齐套),
    issueStatus: formatSendStatus(item.发料状态),
    urgentQty: getUrgentCount(item),
    assignQty: formatQuantity(item.分配数 || item.指派数量 || item.计划数量),
    inspectQty: formatQuantity(item.完成数量),
    assignTarget: normalizeText(item.指派对象 || item.操作人)
  }))
}

const applyPassRateData = rows => {
  const row = rows[0] || {}
  const value = row.总合格率 ?? row.装配合格率 ?? row.合格率
  passRate.value = value === undefined || value === null || value === '' ? '100%' : `${formatQuantity(value)}%`
}

const applyUnclosedData = rows => {
  const row = rows[0] || {}
  exceptionCount.value = toNumber(row.装配异常未关闭总数 ?? row.异常未关闭总数 ?? row.总数)
}

const countRows = (categoryKey, metricKey) => {
  const sourceRows = metricKey === 'stagnation'
    ? stagnationRows.value
    : [...valveTaskRows.value, ...systemTaskRows.value]

  return sourceRows
    .filter(row => isPlanUnfinished(row))
    .filter(row => matchCategory(row, categoryKey))
    .filter(row => matchMetric(row, metricKey))
    .length
}

const getMetricTotal = metricKey => {
  return categoryGroups.reduce((total, group) => {
    return total + group.children.reduce((groupTotal, child) => groupTotal + countRows(child.key, metricKey), 0)
  }, 0)
}

const getCategoryTotal = categoryKey => {
  return metricDefinitions.reduce((total, metric) => total + countRows(categoryKey, metric.key), 0)
}

const getGroupTotal = group => {
  return group.children.reduce((total, child) => total + getCategoryTotal(child.key), 0)
}

const isPlanUnfinished = row => {
  const planQty = toNumber(getField(row, ['计划数量', '计划数']))
  const doneQty = toNumber(getField(row, ['完成数量', '送检数', '完成数']))
  return planQty > doneQty
}

const matchCategory = (row, categoryKey) => {
  const productName = normalizeText(getField(row, ['产品名称', '物料名称', '物料描述', '零件名称']))
  const taskType = normalizeText(getField(row, ['任务类型', '自制件属性', '物料类型']))
  const assignTarget = normalizeText(getField(row, ['指派对象', '操作人', '二次派工']))
  const isValveSource = row._sourceType === 'valve' || taskType.includes('阀')
  const isSystemSource = row._sourceType === 'system' || taskType.includes('系统')

  if (categoryKey === 'valveMain') {
    return isValveSource && productName.includes('阀')
  }
  if (categoryKey === 'valveOther') {
    return isValveSource && !productName.includes('阀')
  }
  if (categoryKey === 'systemElectric') {
    return isSystemSource && assignTarget.includes('电气')
  }
  if (categoryKey === 'systemAssembly') {
    return isSystemSource && (assignTarget.includes('机械') || (assignTarget.includes('装配') && !assignTarget.includes('电气')))
  }
  return false
}

const matchMetric = (row, metricKey) => {
  if (metricKey === 'dispatch') {
    return hasValue(getField(row, ['派工时间']))
  }
  if (metricKey === 'completeSet') {
    return isExecutableTask(row)
  }
  if (metricKey === 'urgent') {
    return isUrgentTask(row)
  }
  if (metricKey === 'stagnation') {
    return true
  }
  return false
}

const isExecutableTask = row => {
  const taskStatus = getField(row, ['任务状态'])
  if (taskStatus !== undefined && taskStatus !== null && taskStatus !== '') {
    return Number(taskStatus) === 1 || String(taskStatus).includes('可执行')
  }

  const completeSet = getField(row, ['齐套'])
  return completeSet === 1 || completeSet === '1' || completeSet === '是'
}

const isUrgentTask = row => {
  return getUrgentCount(row) > 0 ||
    normalizeText(getField(row, ['加急状态', '加急'])).includes('加急') ||
    normalizeText(getField(row, ['优先级'])).includes('是')
}

const getUrgentCount = row => toNumber(getField(row, ['加急总数', '加急数量', '加急数']))

const getField = (row, fields) => {
  for (const field of fields) {
    if (row[field] !== undefined && row[field] !== null) {
      return row[field]
    }
  }
  return ''
}

const hasValue = value => value !== undefined && value !== null && String(value).trim() !== ''

const normalizeText = value => {
  if (value === undefined || value === null) {
    return ''
  }
  return String(value).trim()
}

const toNumber = value => {
  if (value === undefined || value === null || value === '') {
    return 0
  }
  const numberValue = Number(value)
  return Number.isNaN(numberValue) ? 0 : numberValue
}

const formatDate = value => {
  if (!value) {
    return ''
  }
  return String(value).split('T')[0].split(' ')[0]
}

const formatQuantity = value => {
  if (value === undefined || value === null || value === '') {
    return ''
  }
  const numberValue = Number(value)
  if (Number.isNaN(numberValue)) {
    return value
  }
  return Number.isInteger(numberValue)
    ? String(numberValue)
    : String(numberValue).replace(/0+$/, '').replace(/\.$/, '')
}

const formatComplete = value => {
  if (value === '是' || value === '否') {
    return value
  }
  return Number(value || 0) === 1 ? '是' : '否'
}

const formatSendStatus = value => {
  if (value === '发料齐套' || value === '发料缺件' || value === '未发料') {
    return value
  }
  if (Number(value || 0) === 1) {
    return '发料齐套'
  }
  if (Number(value || 0) === 2) {
    return '发料缺件'
  }
  return ''
}

const formatStartStatus = value => {
  return Number(value || 0) > 0 ? '已开工' : '待执行'
}

const getCellClass = (key, value) => {
  if (['completeSet', 'issueStatus', 'startStatus'].includes(key)) {
    if (value === '是' || value === '发料齐套' || value === '已开工') {
      return 'green-cell'
    }
    if (value === '否' || value === '发料缺件' || value === '待执行') {
      return 'orange-cell'
    }
  }
  return ''
}

const deliveryColumns = [
  { label: '生产订单', key: 'productionOrder', width: '82px' },
  { label: '销售订单', key: 'salesOrder', width: '100px' },
  { label: '物料名称', key: 'materialName', width: '142px' },
  { label: '物料编码', key: 'materialCode', width: '164px' },
  { label: '数量', key: 'quantity', width: '58px' },
  { label: '要求发货日期', key: 'requiredDate', width: '108px' },
  // { label: '齐套', key: 'completeSet', width: '54px' },
  // { label: '发料状态', key: 'issueStatus', width: '86px' },
  // { label: '操作人', key: 'operator', width: '76px' },
  { label: '累计工时', key: 'startStatus', width: '82px' }
]

const taskColumns = [
  { label: '生产订单', key: 'productionOrder', width: '82px' },
  { label: '销售订单', key: 'salesOrder', width: '100px' },
  { label: '物料名称', key: 'materialName', width: '150px' },
  { label: '物料编码', key: 'materialCode', width: '172px' },
  { label: '齐套', key: 'completeSet', width: '54px' },
  { label: '发料状态', key: 'issueStatus', width: '86px' },
  { label: '加急数', key: 'urgentQty', width: '64px' },
  { label: '分配数', key: 'assignQty', width: '66px' },
  { label: '送检数', key: 'inspectQty', width: '66px' },
  { label: '指派对象', key: 'assignTarget', width: '86px' }
]
</script>

<style scoped lang="scss">
* {
  box-sizing: border-box;
}

.assembly-dashboard {
  position: fixed;
  left: 50%;
  top: 50%;
  width: 1920px;
  height: 1080px;
  transform-origin: 0 0;
  transition: 0.3s;
  overflow: hidden;
  color: #f3f9ff;
  font-family: 'Microsoft YaHei', Arial, sans-serif;
  background:
    radial-gradient(circle at 20% 18%, rgba(13, 87, 122, 0.34), transparent 28%),
    linear-gradient(180deg, #07001f 0%, #07132d 54%, #071628 100%);
}

.dashboard-shell {
  width: 100%;
  height: 100%;
  padding: 0 15px 15px;
}

.dashboard-header {
  display: grid;
  grid-template-columns: 336px 1fr 442px;
  align-items: center;
  height: 95px;
  border-bottom: 1px solid rgba(21, 162, 240, 0.7);
}

.brand {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  width: 300px;
  height: 72px;
  overflow: visible;
}

.brand-logo {
  width: 224px;
  height: 58px;
  padding: 5px 10px;
  object-fit: contain;
  object-position: left center;
  background: #ffffff;
  border-radius: 6px;
  filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.28));
}

.dashboard-header h1 {
  margin: 0;
  color: #ffffff;
  font-size: 55px;
  font-weight: 900;
  letter-spacing: 0;
  text-align: center;
}

.current-time {
  padding-right: 40px;
  color: #eef7ff;
  font-size: 27px;
  text-align: right;
}

.dashboard-content {
  display: grid;
  grid-template-rows: 120px 1fr;
  gap: 15px;
  height: calc(100% - 95px);
  padding-top: 10px;
}

.status-row {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 15px;
  min-height: 0;
}

.main-grid {
  display: grid;
  grid-template-columns: 780px 1fr;
  gap: 15px;
  min-height: 0;
}

.right-column {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: 15px;
  min-width: 0;
  min-height: 0;
}

.panel {
  position: relative;
  border: 1px solid rgba(29, 153, 229, 0.78);
  background: rgba(3, 16, 48, 0.48);
  box-shadow:
    inset 0 0 18px rgba(27, 130, 214, 0.24),
    0 0 10px rgba(1, 132, 220, 0.18);
}

.panel::before {
  position: absolute;
  inset: -1px;
  content: '';
  pointer-events: none;
  background:
    linear-gradient(90deg, #2bd8ff 0 14px, transparent 14px) left top / 14px 2px no-repeat,
    linear-gradient(180deg, #2bd8ff 0 14px, transparent 14px) left top / 2px 14px no-repeat,
    linear-gradient(270deg, #2bd8ff 0 14px, transparent 14px) right top / 14px 2px no-repeat,
    linear-gradient(180deg, #2bd8ff 0 14px, transparent 14px) right top / 2px 14px no-repeat,
    linear-gradient(90deg, #2bd8ff 0 14px, transparent 14px) left bottom / 14px 2px no-repeat,
    linear-gradient(0deg, #2bd8ff 0 14px, transparent 14px) left bottom / 2px 14px no-repeat,
    linear-gradient(270deg, #2bd8ff 0 14px, transparent 14px) right bottom / 14px 2px no-repeat,
    linear-gradient(0deg, #2bd8ff 0 14px, transparent 14px) right bottom / 2px 14px no-repeat;
}

.panel::after {
  position: absolute;
  inset: 0;
  content: '';
  pointer-events: none;
  box-shadow: inset 0 0 12px rgba(43, 216, 255, 0.12);
}

.stat-card {
  display: grid;
  grid-template-rows: 34px 1fr;
  align-items: center;
  min-width: 0;
  padding: 14px 20px 12px;
}

.stat-title {
  color: #95ddff;
  font-size: 21px;
  font-weight: 700;
}

.stat-value {
  display: flex;
  align-items: baseline;
  justify-content: center;
  min-width: 0;
  color: #ffffff;
  font-weight: 900;
  line-height: 1;
}

.stat-value span {
  font-size: 58px;
}

.stat-value small {
  margin-left: 9px;
  font-size: 22px;
  font-weight: 700;
}

.blue-stat .stat-value span {
  color: #36c8ff;
}

.green-stat .stat-value span {
  color: #18d36f;
}

.red-stat .stat-value span {
  color: #ff3040;
}

.orange-stat .stat-value span {
  color: #ffb13b;
}

.table-panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.panel-caption {
  height: 42px;
  color: #8cd3ff;
  font-size: 30px;
  font-weight: 700;
  line-height: 42px;
  text-align: center;
}

.aggregate-tip {
  height: 28px;
  color: #d6f1ff;
  font-size: 17px;
  line-height: 24px;
  text-align: center;
}

.summary-wrap,
.scroll-wrap {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  padding: 0 9px 10px;
}

table {
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

th,
td {
  border: 1px solid rgba(53, 149, 217, 0.54);
  color: #f1f8ff;
  line-height: 1.18;
  text-align: center;
  vertical-align: middle;
  background: rgba(4, 24, 57, 0.5);
}

th {
  height: 42px;
  color: #bde9ff;
  font-size: 18px;
  font-weight: 600;
  background: rgba(12, 68, 119, 0.34);
}

td {
  height: 45px;
  font-size: 17px;
  white-space: pre-line;
  word-break: break-all;
}

.summary-table th {
  height: 40px;
}

.summary-table td {
  height: 45px;
  font-size: 25px;
}

.group-th {
  width: 82px;
}

.subclass-th {
  width: 210px;
}

.metric-th {
  width: 74px;
}

.count-th {
  width: 78px;
}

.group-cell {
  color: #ffffff;
  font-size: 25px;
  font-weight: 800;
  background: rgba(7, 74, 112, 0.58);
}

.subclass-cell {
  overflow: hidden;
  color: #e8f7ff;
  font-size: 18px;
  font-weight: 700;
  line-height: 1.35;
  background: rgba(7, 45, 82, 0.58);
}

.category-total {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 9px;
  justify-items: center;
  line-height: 1.1;
}

.category-total span {
  color: #ffffff;
  font-size: 32px;
  font-weight: 800;
}

.category-total strong {
  color: #ff3040;
  font-size: 40px;
  font-weight: 900;
  line-height: 1;
  text-shadow: 0 0 10px rgba(255, 48, 64, 0.28);
}

.subclass-total {
  align-content: center;
  justify-items: center;
  min-width: 0;
}

.subclass-total span {
  font-size: 28px;
}

.subclass-total strong {
  font-size: 38px;
}

.subclass-content {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px;
  align-items: center;
  gap: 8px;
  min-height: 126px;
  padding: 8px 8px 8px 14px;
}

.subclass-image {
  width: 230px;
  height: 145px;
  // padding: 6px;
  object-fit: contain;
  // background: rgba(1, 22, 52, 0.9);
  // border: 1px solid rgba(54, 200, 255, 0.38);
  // border-radius: 4px;
  // box-shadow: 0 0 12px rgba(65, 199, 255, 0.24);
}

.metric-cell {
  font-weight: 800;
}

.metric-dispatch {
  color: #36c8ff;
}

.metric-completeSet {
  color: #18d36f;
}

.metric-urgent {
  color: #ff4451;
}

.metric-stagnation {
  color: #ffb13b;
}

.condition-cell {
  padding: 0 12px;
  color: #d7f2ff;
  text-align: left;
}

.count-cell {
  font-size: 26px;
  font-weight: 900;
}

.idx-th,
.idx-td {
  width: 44px;
}

.idx-td {
  color: #89d4ff;
}

.right-column td {
  height: 42px;
  font-size: 16px;
}

.right-column th {
  height: 40px;
  font-size: 16px;
}

.task-panel td {
  height: 42px;
}

.warning td {
  color: #ff4949;
}

.green-cell {
  color: #32ff32;
  font-weight: 700;
}

.orange-cell {
  color: #ffb13b;
  font-weight: 700;
}
</style>
