<template>
  <div
    ref="panelRef"
    class="business-panel"
    :class="[
      `is-${panelType}`,
      `is-${donutVariant}`,
      {
        'is-compact': compact,
        'is-column-label-standard': columnLabelStandard,
      },
    ]"
    @mousemove="handleChartTooltipMove"
    @mouseleave="hideChartTooltip"
  >
    <div v-if="!rows.length" class="business-panel-empty">暂无业务统计数据</div>

    <business-stat-list v-else-if="panelType === 'rank'" :rows="rows" compact />

    <div v-else-if="panelType === 'metric'" class="business-metrics">
      <div
        v-for="item in rows.slice(0, 4)"
        :key="item.key || item.name"
        class="business-metric-item"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <span>{{ item.name }}</span>
        <strong>{{ displayValue(item) }}</strong>
        <em>{{ item.unit }}</em>
      </div>
    </div>

    <div v-else-if="panelType === 'iconMetric'" class="business-icon-metrics">
      <div
        v-for="(item, index) in iconMetricRows"
        :key="item.key || item.name"
        class="business-icon-metric-item"
        :class="`is-tone-${index % colors.length}`"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <i class="business-icon-metric-mark" :class="`is-${item.icon}`"><span></span></i>
        <div class="business-icon-metric-copy">
          <span>{{ item.name }}</span>
          <strong>{{ displayValue(item) }}<em v-if="item.unit">{{ item.unit }}</em></strong>
        </div>
      </div>
    </div>

    <div v-else-if="panelType === 'spotlight'" class="business-spotlight">
      <template v-if="spotlightMain">
        <div class="business-spotlight-main" :data-chart-tooltip="chartTooltipText(spotlightMain)">
          <span>{{ spotlightMain.name }}</span>
          <strong>{{ displayValue(spotlightMain) }}<em>{{ spotlightMain.unit }}</em></strong>
          <small>{{ spotlightMain.extra || panel?.note || "核心业务指标" }}</small>
        </div>
        <div class="business-spotlight-side">
          <div
            v-for="(item, index) in rows.slice(1, 4)"
            :key="item.key || item.name"
            class="business-spotlight-chip"
            :data-chart-tooltip="chartTooltipText(item)"
          >
            <i :style="{ borderColor: chartColor(index + 1) }"></i>
            <span>{{ item.name }}</span>
            <strong>{{ displayValue(item) }}<em>{{ item.unit }}</em></strong>
            <small v-if="item.extra">{{ item.extra }}</small>
          </div>
        </div>
      </template>
      <div v-else class="business-panel-empty">暂无业务统计数据</div>
    </div>

    <div
      v-else-if="panelType === 'donut'"
      class="business-donut"
      :class="[
        `is-variant-${donutVariant}`,
        { 'is-dense': pieRows.length > 5 },
      ]"
    >
      <template v-if="pieRows.length">
        <div v-if="donutVariant === 'ring'" class="business-ring-visual">
          <svg class="business-ring-chart" viewBox="0 0 160 160" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
            <circle class="business-ring-halo" cx="80" cy="80" r="39" />
            <circle class="business-ring-track" cx="80" cy="80" r="52" />
            <circle
              v-for="segment in ringSegments"
              :key="segment.key"
              class="business-ring-segment"
              :class="{ 'is-active': segment.index === normalizedActiveIndex }"
              cx="80"
              cy="80"
              r="52"
              :stroke="segment.color"
              :stroke-dasharray="segment.dasharray"
              :stroke-dashoffset="segment.dashoffset"
              :style="{ color: segment.color }"
              :data-chart-tooltip="pieTooltipText(segment.item)"
            />
          </svg>
          <div class="business-ring-inner">
            <strong>{{ getPiePercent(activePieRow) }}</strong>
            <span>{{ activePieRow?.name || "结构占比" }}</span>
          </div>
        </div>
        <div v-else class="business-donut-visual">
          <MPie
            :key="pieKey"
            :data="pieRows"
            :delay="pieLoopDelay"
            :colors="colors"
            :opacity="0.62"
            class="business-three-pie"
          >
            <template #default="{ data }">
              <div class="business-three-pie-center">
                <strong>{{ getPiePercent(data) }}</strong>
                <span>{{ data?.name || "结构占比" }}</span>
              </div>
            </template>
          </MPie>
        </div>
        <div class="business-donut-legend">
          <div
            v-for="(item, index) in pieRows"
            :key="item.key || item.name"
            class="business-donut-row"
            :class="{ 'is-active': index === normalizedActiveIndex }"
            :style="{ '--row-color': chartColor(index), '--row-percent': `${Math.max(4, piePercentValue(item))}%` }"
            :data-chart-tooltip="pieTooltipText(item)"
          >
            <i :style="{ borderColor: chartColor(index) }"></i>
            <span>{{ item.name }}</span>
            <strong>{{ displayValue(item) }}</strong>
            <em>{{ item.unit }}</em>
          </div>
        </div>
      </template>
      <div v-else class="business-panel-empty">暂无业务统计数据</div>
    </div>

    <div v-else-if="panelType === 'rose'" class="business-rose" :class="{ 'is-dense': pieRows.length > 5 }">
      <template v-if="pieRows.length">
        <div class="business-rose-visual">
          <svg viewBox="0 0 150 150" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
            <g class="business-rose-guides">
              <line
                v-for="segment in roseSegments"
                :key="`guide-${segment.key}`"
                :x1="segment.lineStart.x"
                :y1="segment.lineStart.y"
                :x2="segment.lineEnd.x"
                :y2="segment.lineEnd.y"
                :stroke="segment.color"
              />
            </g>
            <g class="business-rose-segments">
              <path
                v-for="segment in roseSegments"
                :key="segment.key"
                class="business-rose-segment"
                :class="{ 'is-active': segment.index === normalizedActiveIndex }"
                :d="segment.path"
                :fill="segment.color"
                :stroke="segment.color"
                :data-chart-tooltip="pieTooltipText(segment.item)"
              />
            </g>
            <circle class="business-rose-glow" cx="75" cy="75" r="24" />
            <circle class="business-rose-hole" cx="75" cy="75" r="16" />
            <g class="business-rose-labels">
              <text
                v-for="segment in roseSegments"
                :key="`label-${segment.key}`"
                :x="segment.label.x"
                :y="segment.label.y"
                :text-anchor="segment.anchor"
              >
                {{ segment.item.name }}
              </text>
            </g>
          </svg>
        </div>
        <div class="business-donut-legend business-rose-legend">
          <div
            v-for="(item, index) in pieRows"
            :key="item.key || item.name"
            class="business-donut-row business-rose-row"
            :class="{ 'is-active': index === normalizedActiveIndex }"
            :data-chart-tooltip="pieTooltipText(item)"
          >
            <i :style="{ borderColor: chartColor(index), background: chartColor(index), color: chartColor(index) }"></i>
            <span>{{ item.name }}</span>
            <strong>{{ displayValue(item) }}</strong>
            <em>{{ item.unit }}</em>
          </div>
        </div>
      </template>
      <div v-else class="business-panel-empty">暂无业务统计数据</div>
    </div>

    <div v-else-if="panelType === 'structure'" class="business-structure">
      <template v-if="structureRows.length">
        <div class="business-structure-overview">
          <div class="business-structure-band">
            <i
              v-for="(item, index) in structureRows"
              :key="item.key || item.name"
              :class="{ 'is-active': index === normalizedActiveIndex }"
              :style="{ width: `${structurePercent(item)}%`, background: chartColor(index), color: chartColor(index) }"
              :title="`${item.name}：${displayValue(item)}${item.unit || ''} ${structurePercentText(item)}`"
              :data-chart-tooltip="structureTooltipText(item)"
            ></i>
          </div>
        </div>
        <div class="business-structure-list">
          <div
            v-for="item in structureLegendRows"
            :key="item.key || item.name"
            class="business-structure-row"
            :class="{ 'is-active': item.displayIndex === normalizedActiveIndex }"
            :style="{ '--row-color': chartColor(item.displayIndex), '--row-percent': `${Math.max(4, structurePercent(item))}%` }"
            :data-chart-tooltip="structureTooltipText(item)"
          >
            <i :style="{ background: chartColor(item.displayIndex), color: chartColor(item.displayIndex) }"></i>
            <span>{{ item.name }}</span>
            <strong>{{ displayValue(item) }}<em>{{ item.unit }}</em></strong>
            <small>{{ structurePercentText(item) }}</small>
          </div>
        </div>
      </template>
      <div v-else class="business-panel-empty">暂无业务统计数据</div>
    </div>

    <div v-else-if="panelType === 'bar' && panel?.variant === 'capacity'" class="business-capacity">
      <template v-if="capacityTotalRow">
        <div class="business-capacity-head" :data-chart-tooltip="chartTooltipText(capacityTotalRow)">
          <span>{{ capacityTotalRow.name }}</span>
          <strong>{{ displayValue(capacityTotalRow) }}<em>{{ capacityTotalRow.unit }}</em></strong>
        </div>
        <div class="business-capacity-band">
          <i
            v-for="(item, index) in capacitySegmentRows"
            :key="item.key || item.name"
            :class="{ 'is-active': index === normalizedActiveIndex }"
            :style="{ width: `${capacitySegmentWidth(item)}%`, background: capacityColor(item, index), color: capacityColor(item, index) }"
            :title="`${item.name}：${displayValue(item)}${item.unit || ''} ${capacityPercent(item)}`"
            :data-chart-tooltip="capacityTooltipText(item)"
          ></i>
        </div>
        <div class="business-capacity-list">
          <div
            v-for="(item, index) in capacitySegmentRows"
            :key="item.key || item.name"
            class="business-capacity-row"
            :class="{ 'is-active': index === normalizedActiveIndex }"
            :data-chart-tooltip="capacityTooltipText(item)"
          >
            <i :style="{ background: capacityColor(item, index), color: capacityColor(item, index) }"></i>
            <span>{{ item.name }}</span>
            <strong>{{ displayValue(item) }}<em>{{ item.unit }}</em></strong>
            <small>{{ capacityPercent(item) }}</small>
          </div>
        </div>
        <div v-if="capacityTopTownRow" class="business-capacity-town" :data-chart-tooltip="chartTooltipText(capacityTopTownRow)">
          <span>{{ capacityTopTownRow.name }}</span>
          <strong>{{ displayValue(capacityTopTownRow) }}<em>{{ capacityTopTownRow.unit }}</em></strong>
        </div>
      </template>
      <div v-else class="business-panel-empty">暂无业务统计数据</div>
    </div>

    <div
      v-else-if="panelType === 'bar'"
      class="business-bars"
      :class="{
        'is-dense': chartRows.length >= 5,
        'is-long': chartRows.length > 10,
        'is-scrollable': chartRows.length > 5,
        'is-single': panel?.span === 1,
        'is-distribution': panel?.variant === 'distribution',
        'is-capacity': panel?.variant === 'capacity',
        'is-rank-bar': panel?.variant === 'rankBar',
        'is-race-bar': isRaceBarVariant,
        'is-few-rows': isRaceBarVariant && chartRows.length <= 3,
        'is-degradation': panel?.variant === 'degradation',
        'is-race-nowrap': panel?.variant === 'raceBarNoWrap',
        'is-race-relaxed': panel?.variant === 'raceBarRelaxed',
      }"
      @wheel.stop
    >
      <div
        v-for="(item, index) in chartRows"
        :key="item.key || item.name"
        class="business-bar-row"
        :class="{ 'is-active': index === normalizedActiveIndex }"
        :style="{ '--bar-color': item.color || item.fillColor || chartColor(index) }"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <span v-if="panel?.variant === 'rankBar'" class="business-bar-rank">{{ index + 1 }}</span>
        <span class="business-bar-name">{{ item.name }}</span>
        <div class="business-bar-track">
          <i :style="{ width: `${barWidth(item)}%`, background: barGradient(index, item) }"></i>
        </div>
        <strong>
          {{ displayValue(item) }}
          <em v-if="item.unit">{{ item.unit }}</em>
          <small v-if="item.extra">{{ item.extra }}</small>
        </strong>
      </div>
    </div>

    <div
      v-else-if="panelType === 'column'"
      class="business-columns"
      :class="[
        `is-variant-${panel?.variant || 'solid'}`,
        {
          'is-dense': chartRows.length > 6,
          'is-scrollable': chartRows.length > 6 && panel?.scrollable !== false,
          'has-unit-label': Boolean(columnUnitLabel),
        },
      ]"
      @wheel.stop="handleColumnWheel"
    >
      <small v-if="columnUnitLabel" class="business-column-unit">单位：{{ columnUnitLabel }}</small>
      <div
        v-for="(item, index) in chartRows"
        :key="item.key || item.name"
        class="business-column-item"
        :class="{
          'is-active': index === normalizedActiveIndex,
          'is-zero': item?.zero === true || item?.isZero === true,
        }"
        :data-hover-value="columnHoverValue(item)"
        :title="columnHoverValue(item)"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <strong v-if="!columnLabelStandard">{{ displayValue(item) }}<em v-if="columnItemUnit(item)">{{ columnItemUnit(item) }}</em></strong>
        <div class="business-column-track">
          <i
            :style="{
              height: `${barWidth(item)}%`,
              background: columnGradient(index, item),
              '--column-load-delay': `${index * 0.075}s`,
            }"
          ></i>
        </div>
        <span>{{ columnLabelStandard ? verticalShortLabel(item.name) : formatPlaceLabel(item.name) }}</span>
      </div>
    </div>

    <div v-else-if="panelType === 'projectTable'" class="business-project-table">
      <div class="business-project-search">
        <input v-model="projectSearchText" type="search" :placeholder="projectSearchPlaceholder" />
      </div>
      <div class="business-project-frame">
        <table>
          <colgroup>
            <col
              v-for="column in projectTableColumns"
              :key="column.key"
              :class="column.className"
              :style="{ width: column.width || undefined }"
            />
          </colgroup>
          <thead>
            <tr>
              <th
                v-for="column in projectTableColumns"
                :key="column.key"
                :class="getProjectCellClass(column)"
              >
                {{ column.label }}
              </th>
            </tr>
          </thead>
          <tbody>
            <tr
              v-for="item in projectTableRows"
              :key="item.key || item.name"
              :class="{ 'is-active': selectedProjectKey === (item.key || item.name) }"
              tabindex="0"
              @click="handleProjectRowClick(item)"
              @keydown.enter.prevent="handleProjectRowClick(item)"
              @keydown.space.prevent="handleProjectRowClick(item)"
            >
              <td
                v-for="column in projectTableColumns"
                :key="column.key"
                :class="getProjectCellClass(column)"
                :title="formatProjectCell(item, column)"
              >
                <strong v-if="column.strong">
                  {{ formatProjectCell(item, column) }}<em v-if="getProjectCellUnit(item, column)">{{ getProjectCellUnit(item, column) }}</em>
                </strong>
                <span
                  v-else-if="column.icon && formatProjectCell(item, column) !== '--'"
                  class="business-project-cell-icon"
                  :class="`business-project-cell-icon--${column.icon}`"
                  role="img"
                  :aria-label="formatProjectCell(item, column)"
                ></span>
                <span v-else>{{ formatProjectCell(item, column) }}</span>
              </td>
            </tr>
          </tbody>
        </table>
        <div v-if="!projectTableRows.length" class="business-project-empty">{{ projectEmptyText }}</div>
      </div>
    </div>

    <div v-else-if="panelType === 'table'" class="business-table" :class="{ 'is-dense': tableRows.length > 8 }">
      <div class="business-table-head">
        <div v-for="index in 2" :key="index" class="business-table-head-group">
          <span>乡镇</span>
          <span>亩产</span>
        </div>
      </div>
      <div class="business-table-body">
        <div
          v-for="(item, index) in tableRows"
          :key="item.key || item.name"
          class="business-table-row"
          :class="{ 'is-active': index === normalizedActiveIndex }"
          :data-chart-tooltip="chartTooltipText(item)"
        >
          <span class="business-table-name">{{ item.name }}</span>
          <div class="business-table-value">
            <strong>{{ displayValue(item) }}<em v-if="item.unit">{{ item.unit }}</em></strong>
            <i>
              <b :style="{ width: `${barWidth(item)}%`, background: barGradient(index) }"></b>
            </i>
          </div>
        </div>
      </div>
    </div>

    <div
      v-else-if="panelType === 'stackColumn'"
      class="business-stack-columns"
      :class="[
        `is-variant-${panel?.variant || 'standard'}`,
        { 'is-dense': stackColumnRows.length > 6 },
      ]"
    >
      <div class="business-stack-legend">
        <span
          v-for="(segment, index) in stackSegments"
          :key="segment.key || segment.name"
        >
          <i :style="{ background: segmentColor(segment, index) }"></i>{{ segment.name }}
        </span>
      </div>
      <div class="business-stack-chart">
        <div
          v-for="(item, index) in stackColumnRows"
          :key="item.key || item.name"
          class="business-stack-item"
          :class="{ 'is-active': index === normalizedActiveIndex }"
          :data-hover-value="stackColumnHoverValue(item)"
          :title="stackColumnHoverValue(item)"
          :data-chart-tooltip="stackColumnTooltipText(item)"
        >
          <strong v-if="showStackColumnValue()" class="business-stack-total">
            {{ formatNumber(stackItemTotal(item)) }}<em v-if="stackColumnUnit(item)">{{ stackColumnUnit(item) }}</em>
          </strong>
          <div class="business-stack-track">
            <i
              v-for="(segment, segmentIndex) in stackItemSegments(item)"
              :key="segment.key || segment.name"
              :style="{ height: `${segment.percent}%`, background: segment.color, color: segment.color }"
              :data-chart-tooltip="stackSegmentTooltipText(item, segment, segmentIndex)"
            ></i>
          </div>
          <span>{{ columnLabelStandard ? verticalShortLabel(item.name) : formatPlaceLabel(item.name) }}</span>
        </div>
      </div>
    </div>

    <div
      v-else-if="panelType === 'peak'"
      class="business-peaks"
      :class="{ 'is-dense': chartRows.length > 5 }"
    >
      <small v-if="peakUnitLabel" class="business-column-unit business-peak-unit">单位：{{ peakUnitLabel }}</small>
      <div
        v-for="(item, index) in chartRows"
        :key="item.key || item.name"
        class="business-peak-item"
        :style="{ '--peak-height': `${barWidth(item)}%`, '--peak-color': chartColor(index) }"
        :data-hover-value="columnHoverValue(item)"
        :title="columnHoverValue(item)"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <strong v-if="!columnLabelStandard">{{ displayValue(item) }}<em v-if="peakItemUnit(item)">{{ peakItemUnit(item) }}</em></strong>
        <div class="business-peak-stage">
          <i></i>
        </div>
        <span>{{ columnLabelStandard ? verticalShortLabel(item.name) : formatPlaceLabel(item.name) }}</span>
      </div>
    </div>

    <div v-else-if="panelType === 'line'" class="business-line">
      <div class="business-line-chart" @mousemove="handleLinePointerMove" @mouseleave="lineHoverIndex = null">
        <svg viewBox="0 0 320 86" preserveAspectRatio="none" aria-hidden="true">
          <path class="business-line-grid" d="M0 18H320M0 44H320M0 70H320" />
          <polyline class="business-line-area" :points="lineAreaPoints" />
          <polyline class="business-line-stroke" :points="linePoints" />
          <circle
            v-for="(point, index) in linePointList"
            :key="index"
            :cx="point.x"
            :cy="point.y"
            r="3"
            class="business-line-dot"
            :class="{ 'is-active': index === activeLineIndex }"
          />
          <circle
            v-for="(point, index) in linePointList"
            :key="`hit-${index}`"
            :cx="point.x"
            :cy="point.y"
            r="13"
            class="business-line-hit"
            @mouseenter="lineHoverIndex = index"
          />
        </svg>
        <div class="business-line-hover-zones" :style="lineLabelStyle">
          <i
            v-for="(point, index) in linePointList"
            :key="`zone-${index}`"
            @mouseenter="lineHoverIndex = index"
          ></i>
        </div>
        <div v-if="activeLinePoint" class="business-line-tooltip" :style="lineTooltipStyle">
          <span>{{ activeLinePoint.item.name }}</span>
          <strong>{{ displayValue(activeLinePoint.item) }}<em v-if="activeLinePoint.item.unit">{{ activeLinePoint.item.unit }}</em></strong>
        </div>
      </div>
      <div class="business-line-labels" :style="lineLabelStyle">
        <span v-for="item in lineLabelRows" :key="item.key || item.name">{{ columnLabelStandard ? verticalShortLabel(item.name) : formatPlaceLabel(item.name) }}</span>
      </div>
    </div>

    <div
      v-else-if="panelType === 'balanceGaugeGrid'"
      class="business-balance-gauge-grid"
      :class="{ 'is-single': balanceGaugeRows.length === 1 }"
    >
      <div
        v-for="(item, index) in balanceGaugeRows"
        :key="item.key || item.name"
        class="business-balance-gauge-card"
        :class="{ 'is-active': index === normalizedActiveIndex }"
        :style="balanceGaugeStyle(item, index)"
        :data-chart-tooltip="gaugeTooltipText(item)"
      >
        <div class="business-balance-gauge-head">
          <strong>{{ gaugeStatusText(item) }}</strong>
        </div>
        <div class="business-balance-gauge-ring">
          <div class="business-balance-gauge-value">
            <strong>{{ displayValue(item) }}</strong>
            <em v-if="displayUnit(item)">{{ displayUnit(item) }}</em>
          </div>
        </div>
        <div class="business-balance-gauge-name">{{ item.name }}</div>
        <div v-if="item.extra" class="business-balance-gauge-extra">{{ item.extra }}</div>
      </div>
    </div>

    <div v-else-if="panelType === 'gauge'" class="business-gauges" :class="{ 'is-dense': gaugeRows.length > 3 }">
      <div
        v-for="(item, index) in gaugeRows"
        :key="item.key || item.name"
        class="business-gauge-item"
        :class="{
          'is-active': index === normalizedActiveIndex,
          'is-safe': gaugeRawValue(item) <= 0,
          'is-low-rate': gaugeRawValue(item) > 0 && gaugeRawValue(item) < 5,
          'is-alert': gaugeRawValue(item) > 100,
        }"
        :style="{
          '--gauge-color': gaugeColor(item, index),
          '--needle-rotate': `${gaugeNeedleAngle(item)}deg`,
        }"
        :data-chart-tooltip="gaugeTooltipText(item)"
      >
        <div class="business-gauge-visual">
          <svg viewBox="0 0 152 96" preserveAspectRatio="xMidYMid meet" aria-hidden="true">
            <path class="business-gauge-track" d="M24 76 A52 52 0 0 1 128 76" pathLength="100" />
            <path
              class="business-gauge-progress"
              d="M24 76 A52 52 0 0 1 128 76"
              pathLength="100"
              :stroke-dasharray="`${gaugeProgress(item)} 100`"
            />
            <path class="business-gauge-glow" d="M38 76 A38 38 0 0 1 114 76" />
          </svg>
          <i class="business-gauge-needle"></i>
          <b class="business-gauge-pivot"></b>
          <div class="business-gauge-value">
            <strong>{{ displayValue(item) }}<em v-if="displayUnit(item)">{{ displayUnit(item) }}</em></strong>
            <small>{{ gaugeStatusText(item) }}</small>
          </div>
        </div>
        <span class="business-gauge-name">{{ item.name }}</span>
        <small v-if="item.extra" class="business-gauge-extra">{{ item.extra }}</small>
      </div>
    </div>

    <div v-else-if="panelType === 'heat'" class="business-heat" :class="{ 'is-dense': heatRows.length > 6 }">
      <div
        v-for="(item, index) in heatRows"
        :key="item.key || item.name"
        class="business-heat-cell"
        :style="heatCellStyle(item, index)"
        :data-chart-tooltip="chartTooltipText(item)"
      >
        <i></i>
        <span>{{ item.name }}</span>
        <strong>{{ displayValue(item) }}<em v-if="item.unit">{{ item.unit }}</em></strong>
      </div>
    </div>

    <div v-else-if="panelType === 'split'" class="business-split" :class="{ 'is-dense': splitRows.length > 10 }">
      <div class="business-split-band">
        <i
          v-for="(item, index) in splitRows"
          :key="item.key || item.name"
          :style="{ width: `${splitWidth(item)}%`, background: chartColor(index) }"
          :data-chart-tooltip="splitTooltipText(item)"
        ></i>
      </div>
      <div class="business-split-list">
        <div
          v-for="(item, index) in splitRows"
          :key="item.key || item.name"
          class="business-split-row"
          :data-chart-tooltip="splitTooltipText(item)"
        >
          <span><i :style="{ background: chartColor(index) }"></i>{{ item.name }}</span>
          <strong>{{ displayValue(item) }}{{ item.unit }}</strong>
        </div>
      </div>
    </div>

    <business-stat-list v-else :rows="rows" compact />

    <teleport to="body">
      <div
        v-if="chartTooltip.visible"
        class="business-chart-tooltip"
        :style="chartTooltipStyle"
      >
        <strong>{{ chartTooltip.title }}</strong>
        <span v-for="line in chartTooltip.lines" :key="line">{{ line }}</span>
      </div>
    </teleport>
  </div>
</template>

<script setup>
import { computed, onBeforeUnmount, onMounted, ref, watch } from "vue"
import BusinessStatList from "./BusinessStatList.vue"
import MPie from "@/components/mPie/index.vue"

const props = defineProps({
  panel: {
    type: Object,
    default: () => ({ rows: [] }),
  },
  compact: {
    type: Boolean,
    default: false,
  },
  columnLabelStandard: {
    type: Boolean,
    default: false,
  },
})
const emit = defineEmits(["row-select"])

const colors = ["#24f6c4", "#32dcff", "#ffe06b", "#7ee269", "#ff9a62", "#9ea7ff"]

const panelType = computed(() => props.panel?.type || "rank")
const rows = computed(() => (props.panel?.rows || []).filter((item) => item?.name))
const pieRows = computed(() => rows.value.map((item) => ({
  ...item,
  value: numericValue(item),
})).filter((item) => item.value > 0))
const values = computed(() => rows.value.map((item) => numericValue(item)).filter((value) => value > 0))
const maxValue = computed(() => Math.max(...values.value, 1))
const sumValue = computed(() => values.value.reduce((sum, value) => sum + value, 0))
const splitRows = computed(() => rows.value.filter((item) => numericValue(item) > 0))
const isRaceBarVariant = computed(() => ["raceBar", "raceBarNoWrap", "raceBarRelaxed", "degradation"].includes(props.panel?.variant))
const chartRows = computed(() => {
  if (panelType.value === "line") {
    return rows.value.filter((item) => item?.value !== undefined && item?.value !== null && item?.value !== "")
  }
  return rows.value.filter((item) => numericValue(item) > 0)
})
const tableRows = computed(() => chartRows.value)
const columnUnitLabel = computed(() => {
  if (panelType.value !== "column") return ""
  return sharedChartUnitLabel()
})
const peakUnitLabel = computed(() => {
  if (panelType.value !== "peak") return ""
  return sharedChartUnitLabel()
})
const structureRows = computed(() => rows.value.filter((item) => numericValue(item) > 0))
const heatRows = computed(() => chartRows.value.slice(0, props.panel?.limit || 8))
const gaugeRows = computed(() =>
  rows.value
    .filter((item) => item?.value !== undefined && item?.value !== null && item?.value !== "")
    .slice(0, props.panel?.limit || 6)
)
const balanceGaugeRows = computed(() =>
  rows.value
    .filter((item) => item?.value !== undefined && item?.value !== null && item?.value !== "")
    .slice(0, props.panel?.limit || 3)
)
const stackSegments = computed(() => props.panel?.segments || [])
const stackColumnRows = computed(() => rows.value.filter((item) => stackItemTotal(item) > 0))
const stackColumnMaxTotal = computed(() => Math.max(...stackColumnRows.value.map((item) => stackItemTotal(item)), 1))
const projectSearchText = ref("")
const selectedProjectKey = ref(null)
const defaultProjectTableColumns = [
  { key: "name", label: "项目名称", field: "name", width: "45%", className: "business-project-col-name" },
  { key: "year", label: "年份", field: "year", width: "13%", fallback: "未知", align: "right", className: "business-project-col-year" },
  { key: "category", label: "类型", field: "category", width: "20%", className: "business-project-col-category" },
  { key: "scale", label: "规模", field: "value", width: "22%", align: "right", strong: true, unitField: "unit", className: "business-project-col-scale" },
]
const projectTableColumns = computed(() => {
  const columns = Array.isArray(props.panel?.columns) && props.panel.columns.length
    ? props.panel.columns
    : defaultProjectTableColumns
  return columns.map((column, index) => ({
    key: column.key || column.field || `column-${index}`,
    label: column.label || column.title || column.name || "",
    field: column.field || column.dataIndex || column.key,
    fields: column.fields || [],
    width: column.width,
    align: column.align,
    strong: Boolean(column.strong),
    unit: column.unit,
    unitField: column.unitField,
    fallback: column.fallback,
    format: column.format,
    icon: column.icon,
    className: column.className,
  }))
})
const projectSearchPlaceholder = computed(() => props.panel?.searchPlaceholder || "搜索项目")
const projectEmptyText = computed(() => props.panel?.emptyText || "无匹配项目")
const projectSearchKeys = computed(() => {
  const keys = Array.isArray(props.panel?.searchKeys) ? props.panel.searchKeys : []
  if (keys.length) return keys
  return [
    ...projectTableColumns.value.flatMap((column) => [column.field, ...(column.fields || [])]),
    "projectName",
    "category",
    "year",
    "measure",
    "townships",
    "metric",
  ].filter(Boolean)
})
const projectTableRows = computed(() => {
  const keyword = normalizeSearch(projectSearchText.value)
  if (!keyword) return limitProjectRows(rows.value)
  return rows.value.filter((item) => normalizeSearch(getProjectSearchText(item)).includes(keyword))
})
const capacityTotalRow = computed(() => rows.value.find((item) => ["forage-total", "wetland-yield-total"].includes(item.key)) || rows.value[0])
const capacitySegmentRows = computed(() => rows.value.filter((item) => [
  "forage-edible",
  "forage-unavailable",
  "wetland-yield-edible",
  "wetland-yield-unavailable",
].includes(item.key)))
const capacityTopTownRow = computed(() => rows.value.find((item) => ["forage-top-town", "wetland-yield-top-town"].includes(item.key)))
const activeDonutIndex = ref(0)
const lineHoverIndex = ref(null)
const panelRef = ref(null)
const panelVisible = ref(true)
const chartTooltip = ref({
  visible: false,
  x: 0,
  y: 0,
  title: "",
  lines: [],
})
let donutTimer = null
let visibilityObserver = null
const pieLoopDelay = 3000
const pieKey = computed(() => `${props.panel?.key || props.panel?.title || "pie"}-${pieRows.value.map((item) => `${item.name}:${item.value}`).join("|")}`)
const chartTooltipStyle = computed(() => {
  const offset = 14
  const tooltipWidth = 190
  const tooltipHeight = 82
  const viewportWidth = typeof window === "undefined" ? 1920 : window.innerWidth
  const viewportHeight = typeof window === "undefined" ? 1080 : window.innerHeight
  const left = Math.min(viewportWidth - tooltipWidth - 8, chartTooltip.value.x + offset)
  const top = Math.min(viewportHeight - tooltipHeight - 8, chartTooltip.value.y + offset)
  return {
    left: `${Math.max(8, left)}px`,
    top: `${Math.max(8, top)}px`,
  }
})

const normalizedActiveIndex = computed(() => {
  const dataLength = activeLoopLength.value
  if (!dataLength) return 0
  return activeDonutIndex.value % dataLength
})

const activeLoopLength = computed(() => {
  if (panelType.value === "structure") return structureRows.value.length
  if (panelType.value === "donut") return pieRows.value.length
  if (panelType.value === "rose") return pieRows.value.length
  if (panelType.value === "bar" && props.panel?.variant === "capacity") return capacitySegmentRows.value.length
  if (panelType.value === "bar") return chartRows.value.length
  if (panelType.value === "column") return chartRows.value.length
  if (panelType.value === "table") return tableRows.value.length
  if (panelType.value === "line") return chartRows.value.length
  if (panelType.value === "balanceGaugeGrid") return balanceGaugeRows.value.length
  if (panelType.value === "gauge") return gaugeRows.value.length
  if (panelType.value === "stackColumn") return stackColumnRows.value.length
  if (panelType.value === "split") return splitRows.value.length
  return 0
})

const activePieRow = computed(() => pieRows.value[normalizedActiveIndex.value] || pieRows.value[0])
const activeStructureRow = computed(() => structureRows.value[normalizedActiveIndex.value] || structureRows.value[0])
const spotlightMain = computed(() => rows.value[0])
const iconMetricRows = computed(() =>
  rows.value.slice(0, 4).map((item, index) => ({
    ...item,
    icon: getMetricIcon(item, index),
  }))
)
const structureLegendRows = computed(() =>
  structureRows.value
    .map((item, index) => ({ ...item, displayIndex: index }))
)

const donutVariant = computed(() => {
  if (panelType.value !== "donut") return "standard"
  return props.panel?.variant === "ring" ? "ring" : "three"
})
const ringSegments = computed(() => {
  const data = pieRows.value
  const count = data.length
  if (!count) return []
  const radius = 52
  const circumference = 2 * Math.PI * radius
  const total = data.reduce((sum, item) => sum + numericValue(item), 0) || 1
  const gap = count > 1 ? Math.min(12, Math.max(7, circumference * 0.028)) : 0
  let cursor = 0
  return data.map((item, index) => {
    const value = numericValue(item)
    const segmentLength = (value / total) * circumference
    const visibleLength = count > 1 ? Math.max(5, segmentLength - gap) : circumference
    const startOffset = cursor + (count > 1 ? gap / 2 : 0)
    cursor += segmentLength
    return {
      key: item.key || item.name || index,
      index,
      item,
      color: chartColor(index),
      dasharray: `${visibleLength.toFixed(2)} ${circumference.toFixed(2)}`,
      dashoffset: `${(-startOffset).toFixed(2)}`,
    }
  })
})
const roseSegments = computed(() => {
  const data = pieRows.value
  const count = data.length
  if (!count) return []
  const max = Math.max(...data.map((item) => numericValue(item)), 1)
  const step = 360 / count
  const gap = Math.min(8, step * 0.16)
  return data.map((item, index) => {
    const value = numericValue(item)
    const isActive = index === normalizedActiveIndex.value
    const radius = 36 + Math.sqrt(value / max) * 31 + (isActive ? 5 : 0)
    const innerRadius = 17
    const start = -90 + index * step + gap / 2
    const end = -90 + (index + 1) * step - gap / 2
    const mid = (start + end) / 2
    const lineStart = polarPoint(75, 75, radius + 3, mid)
    const lineEnd = polarPoint(75, 75, radius + 15, mid)
    const label = polarPoint(75, 75, radius + 20, mid)
    return {
      key: item.key || item.name || index,
      index,
      item,
      color: chartColor(index),
      path: describeRoseSegment(75, 75, innerRadius, radius, start, end),
      lineStart,
      lineEnd,
      label,
      anchor: Math.cos((mid * Math.PI) / 180) >= 0 ? "start" : "end",
    }
  })
})

onMounted(() => {
  setupPanelVisibility()
  syncDonutLoop()
})

onBeforeUnmount(() => {
  cleanupPanelVisibility()
  stopDonutLoop()
})

watch(
  () => [props.panel?.key, rows.value.length],
  () => {
    activeDonutIndex.value = 0
    lineHoverIndex.value = null
    projectSearchText.value = ""
    selectedProjectKey.value = null
    hideChartTooltip()
    syncDonutLoop()
  }
)

watch(panelVisible, () => {
  syncDonutLoop()
})

const linePointList = computed(() => {
  const data = chartRows.value
  const width = 320
  const height = 66
  const top = 10
  const step = data.length > 1 ? width / (data.length - 1) : width
  const lineValues = data.map((item) => numericValue(item)).filter((value) => Number.isFinite(value) && value >= 0)
  const lineMinValue = lineValues.length ? Math.min(...lineValues) : 0
  const lineMaxValue = lineValues.length ? Math.max(...lineValues) : 1
  const lineRange = Math.max(lineMaxValue - lineMinValue, lineMaxValue * 0.08, 1)
  return data.map((item, index) => {
    const value = numericValue(item)
    return {
      x: Math.round(index * step),
      y: Math.round(top + height - ((value - lineMinValue) / lineRange) * height),
      item,
    }
  })
})

const linePoints = computed(() => linePointList.value.map((point) => `${point.x},${point.y}`).join(" "))
const lineAreaPoints = computed(() => {
  if (!linePointList.value.length) return ""
  return `0,86 ${linePoints.value} 320,86`
})
const lineLabelRows = computed(() => chartRows.value)
const lineLabelStyle = computed(() => ({
  gridTemplateColumns: `repeat(${Math.max(lineLabelRows.value.length, 1)}, minmax(0, 1fr))`,
}))
const lineHoverPoint = computed(() => (
  Number.isInteger(lineHoverIndex.value) ? linePointList.value[lineHoverIndex.value] : null
))
const activeLineIndex = computed(() => {
  if (!linePointList.value.length) return 0
  if (Number.isInteger(lineHoverIndex.value)) return lineHoverIndex.value
  return normalizedActiveIndex.value
})
const activeLinePoint = computed(() => {
  if (lineHoverPoint.value) return lineHoverPoint.value
  return linePointList.value[activeLineIndex.value] || linePointList.value[0]
})
const lineTooltipStyle = computed(() => {
  const point = activeLinePoint.value
  if (!point) return {}
  const xPercent = (point.x / 320) * 100
  return {
    left: `${Math.min(84, Math.max(16, xPercent))}%`,
    top: "6px",
    transform: "translateX(-50%)",
  }
})

function numericValue(item) {
  const value = Number(item?.value)
  if (!Number.isNaN(value) && value > 0) return value
  const percent = Number(item?.percent)
  return Number.isNaN(percent) ? 0 : percent
}

function stackItemTotal(item) {
  const values = item?.segments || item?.values || {}
  return stackSegments.value.reduce((sum, segment) => sum + (Number(values[segment.key]) || 0), 0)
}

function stackItemSegments(item) {
  const total = stackItemTotal(item)
  const values = item?.segments || item?.values || {}
  if (!total) return []
  return stackSegments.value.map((segment, index) => {
    const value = Number(values[segment.key]) || 0
    const percentBase = props.panel?.variant === "dual" ? stackColumnMaxTotal.value : total
    return {
      ...segment,
      value,
      percent: Math.max(value > 0 ? 3 : 0, (value / Math.max(percentBase, 1)) * 100),
      color: segmentColor(segment, index),
    }
  })
}

function segmentColor(segment, index) {
  return segment?.color || segment?.fillColor || chartColor(index)
}

function formatNumber(value) {
  const number = Number(value)
  if (Number.isNaN(number)) return "--"
  return Number.isInteger(number) ? `${number}` : `${Number(number.toFixed(2))}`
}

function displayValue(item) {
  if (item?.displayValue !== undefined && item?.displayValue !== null && item?.displayValue !== "") {
    return item.displayValue
  }
  if (item?.value === undefined || item?.value === null || item?.value === "") return "--"
  return formatNumber(item.value)
}

function displayUnit(item) {
  const unit = item?.displayUnit || item?.unit || ""
  if (!unit) return ""
  const value = String(displayValue(item) ?? "")
  return value && value.endsWith(String(unit)) ? "" : unit
}

function sharedChartUnitLabel() {
  const units = [...new Set(chartRows.value.map((item) => item?.displayUnit || item?.unit).filter(Boolean))]
  return units.length === 1 ? units[0] : ""
}

function columnItemUnit(item) {
  const unit = displayUnit(item)
  if (!unit) return ""
  return columnUnitLabel.value === unit ? "" : unit
}

function peakItemUnit(item) {
  const unit = displayUnit(item)
  if (!unit) return ""
  return peakUnitLabel.value === unit ? "" : unit
}

function formatPlaceLabel(value) {
  const text = String(value || "").trim()
  return text.replace(/\s+/g, "")
}

function verticalShortLabel(value) {
  return Array.from(formatPlaceLabel(value)).slice(0, 3).join("")
}

function columnHoverValue(item) {
  const name = formatPlaceLabel(item?.name) || "数据"
  const unit = displayUnit(item)
  return `${name}：${displayValue(item)}${unit}`
}

function tooltipText(title, lines = []) {
  return [
    formatPlaceLabel(title) || "数据",
    ...lines.filter((line) => line !== undefined && line !== null && String(line).trim() !== "").map((line) => String(line)),
  ].join("\n")
}

function chartTooltipText(item, extraLines = []) {
  if (!item) return ""
  const unit = displayUnit(item)
  const value = displayValue(item)
  const lines = []
  if (value !== "--") lines.push(`数值：${value}${unit}`)
  if (item.extra) lines.push(String(item.extra))
  return tooltipText(item.name, [...lines, ...extraLines])
}

function pieTooltipText(item) {
  return chartTooltipText(item, [`占比：${getPiePercent(item)}`])
}

function structureTooltipText(item) {
  return chartTooltipText(item, [`占比：${structurePercentText(item)}`])
}

function capacityTooltipText(item) {
  return chartTooltipText(item, [`占比：${capacityPercent(item)}`])
}

function stackColumnTooltipText(item) {
  const unit = stackColumnUnit(item)
  const segmentLines = stackItemSegments(item)
    .filter((segment) => segment.value > 0)
    .map((segment) => `${segment.name}：${formatNumber(segment.value)}${unit}`)
  return tooltipText(item?.name, [`合计：${formatNumber(stackItemTotal(item))}${unit}`, ...segmentLines])
}

function stackSegmentTooltipText(item, segment) {
  const unit = stackColumnUnit(item)
  return tooltipText(`${formatPlaceLabel(item?.name)} ${segment?.name || ""}`, [`数值：${formatNumber(segment?.value || 0)}${unit}`])
}

function gaugeTooltipText(item) {
  return chartTooltipText(item, [`状态：${gaugeStatusText(item)}`])
}

function splitTooltipText(item) {
  const percent = sumValue.value ? `${formatNumber((numericValue(item) / sumValue.value) * 100)}%` : "--"
  return chartTooltipText(item, [`占比：${percent}`])
}

function handleChartTooltipMove(event) {
  const target = event.target?.closest?.("[data-chart-tooltip], [data-hover-value]")
  if (!target || !panelRef.value?.contains(target)) {
    hideChartTooltip()
    return
  }
  const rawText = target.getAttribute("data-chart-tooltip") || target.getAttribute("data-hover-value") || ""
  const lines = String(rawText).split(/\n+/).map((line) => line.trim()).filter(Boolean)
  if (!lines.length) {
    hideChartTooltip()
    return
  }
  chartTooltip.value = {
    visible: true,
    x: event.clientX,
    y: event.clientY,
    title: lines[0],
    lines: lines.slice(1),
  }
}

function hideChartTooltip() {
  if (!chartTooltip.value.visible) return
  chartTooltip.value = {
    visible: false,
    x: 0,
    y: 0,
    title: "",
    lines: [],
  }
}

function stackColumnHoverValue(item) {
  const name = formatPlaceLabel(item?.name) || "数据"
  const unit = stackColumnUnit(item)
  return `${name}：${formatNumber(stackItemTotal(item))}${unit}`
}

function stackColumnUnit(item) {
  return item?.displayUnit || item?.unit || props.panel?.unit || ""
}

function showStackColumnValue() {
  return props.panel?.showValue === true || props.panel?.variant === "dual"
}

function normalizeSearch(value) {
  return String(value || "").trim().toLowerCase()
}

function getProjectSearchText(item) {
  const values = projectSearchKeys.value.map((key) => getProjectCellRawValue(item, { field: key })).filter((value) => value !== undefined && value !== null)
  return [item?.searchText, ...values].filter(Boolean).join(" ")
}

function limitProjectRows(sourceRows = []) {
  const maxRows = Number(props.panel?.maxRows)
  if (!Number.isFinite(maxRows) || maxRows <= 0) return sourceRows
  return sourceRows.slice(0, maxRows)
}

function getProjectCellRawValue(item, column) {
  const fields = [column?.field, ...(column?.fields || [])].filter(Boolean)
  for (const field of fields) {
    const value = String(field).split(".").reduce((target, key) => target?.[key], item)
    if (value !== undefined && value !== null && value !== "") return value
  }
  return undefined
}

function formatProjectCell(item, column) {
  const value = getProjectCellRawValue(item, column)
  if (value === undefined || value === null || value === "") return column?.fallback || "--"
  if (column?.format === "number") return formatNumber(value)
  if (column?.format === "displayValue") return displayValue({ value })
  return String(value)
}

function getProjectCellUnit(item, column) {
  if (column?.unitField && item?.[column.unitField]) return item[column.unitField]
  return column?.unit || ""
}

function getProjectCellClass(column) {
  return {
    "business-project-name": column?.key === "name",
    "business-project-locate": column?.key === "locate",
    "is-right": column?.align === "right",
    "is-center": column?.align === "center",
    "is-strong": column?.strong,
  }
}

function handleProjectRowClick(item) {
  if (item?.canLocate === false) return
  selectedProjectKey.value = item?.key || item?.name || null
  emit("row-select", item)
}

function handleColumnWheel(event) {
  const target = event?.currentTarget
  if (!target || target.scrollWidth <= target.clientWidth) return
  event.preventDefault()
  const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY
  target.scrollLeft += delta
}

function barWidth(item) {
  const scaleValue = Number(item?.scaleValue)
  const useScaleValue = !(panelType.value === "column" && props.panel?.variant === "plain")
  if (useScaleValue && !Number.isNaN(scaleValue) && scaleValue > 0) {
    return Math.max(8, Math.min(100, Math.round(scaleValue)))
  }
  const value = numericValue(item)
  if (!value) return 8
  const relativeMaxValue = panelType.value === "column" && props.panel?.variant === "plain"
    ? Math.max(...values.value, value)
    : maxValue.value
  return Math.max(8, Math.round((value / relativeMaxValue) * 100))
}

function heatCellStyle(item, index) {
  const width = barWidth(item)
  const alpha = Math.max(0.14, Math.min(0.46, width / 180))
  return {
    "--heat-color": chartColor(index),
    "--heat-bg": hexToRgba(chartColor(index), alpha),
  }
}

function gaugeRawValue(item) {
  const value = Number(item?.value)
  return Number.isFinite(value) ? value : 0
}

function gaugeMaxValue() {
  const configured = Number(props.panel?.max)
  if (Number.isFinite(configured) && configured > 0) return configured
  const max = Math.max(...gaugeRows.value.map((item) => gaugeRawValue(item)), 100)
  return Math.max(max, 100)
}

function gaugeProgress(item) {
  const value = gaugeRawValue(item)
  const max = gaugeMaxValue()
  if (!max || value <= 0) return 0
  return Number(Math.min(100, (value / max) * 100).toFixed(1))
}

function gaugeNeedleAngle(item) {
  return Number((-180 + gaugeProgress(item) * 1.8).toFixed(1))
}

function gaugeColor(item, index) {
  if (item?.color || item?.fillColor) return item.color || item.fillColor
  const value = gaugeRawValue(item)
  if (value <= 0) return "#24f6c4"
  if (value > 100) return "#ffbf5a"
  return chartColor(index)
}

function balanceGaugeProgress(item) {
  const value = Math.max(0, gaugeRawValue(item))
  const max = Math.max(5, ...balanceGaugeRows.value.map((row) => Math.max(0, gaugeRawValue(row))))
  return Math.max(6, Math.min(100, Number(((value / max) * 100).toFixed(1))))
}

function balanceGaugeColor(item) {
  const value = gaugeRawValue(item)
  const status = String(item?.status || item?.level || "")
  if (value > 20 || /严重|重度|高超载/.test(status)) return "#ff5a64"
  if (value > 10 || /中度|预警/.test(status)) return "#ff9a5c"
  if (value > 5 || /轻度/.test(status)) return "#ffe06b"
  if (value <= 0 || /总体可控|合理|正常|达标|无超载/.test(status)) return "#24f6c4"
  return "#30dcff"
}

function balanceGaugeStyle(item) {
  const color = balanceGaugeColor(item)
  return {
    "--balance-color": color,
    "--balance-progress": `${balanceGaugeProgress(item)}%`,
  }
}

function gaugeStatusText(item) {
  if (item?.status || item?.level) return item.status || item.level
  const value = gaugeRawValue(item)
  if (value < 0) return "合理"
  if (value <= 5) return "基本实现草畜平衡"
  if (value <= 10) return "轻度超载"
  if (value > 100) return "高超载"
  return "超载预警"
}

function hexToRgba(hex, alpha = 0.2) {
  const value = String(hex || "").replace("#", "")
  if (value.length !== 6) return `rgba(48, 220, 255, ${alpha})`
  const number = parseInt(value, 16)
  const r = (number >> 16) & 255
  const g = (number >> 8) & 255
  const b = number & 255
  return `rgba(${r}, ${g}, ${b}, ${alpha})`
}

function handleLinePointerMove(event) {
  const length = linePointList.value.length
  if (!length) return
  const rect = event.currentTarget.getBoundingClientRect()
  const ratio = rect.width ? (event.clientX - rect.left) / rect.width : 0
  const index = Math.min(length - 1, Math.max(0, Math.round(ratio * (length - 1))))
  lineHoverIndex.value = index
}

function splitWidth(item) {
  const value = numericValue(item)
  if (!sumValue.value || !value) return 0
  return Math.max(6, (value / sumValue.value) * 100)
}

function structurePercent(item) {
  const value = numericValue(item)
  if (!sumValue.value || !value) return 0
  return Math.max(2, (value / sumValue.value) * 100)
}

function structurePercentText(item) {
  if (!item) return "--"
  if (item.extra) return item.extra
  const value = numericValue(item)
  if (!sumValue.value || !value) return "--"
  return `${formatNumber((value / sumValue.value) * 100)}%`
}

function capacityTotalValue() {
  const total = numericValue(capacityTotalRow.value)
  if (total > 0) return total
  return capacitySegmentRows.value.reduce((sum, item) => sum + numericValue(item), 0)
}

function capacitySegmentWidth(item) {
  const total = capacityTotalValue()
  const value = numericValue(item)
  if (!total || !value) return 0
  return Math.max(6, (value / total) * 100)
}

function capacityPercent(item) {
  const total = capacityTotalValue()
  const value = numericValue(item)
  if (!total || !value) return "--"
  return `${formatNumber((value / total) * 100)}%`
}

function capacityColor(item, index) {
  if (["forage-edible", "wetland-yield-edible"].includes(item?.key)) return "#24f6c4"
  if (["forage-unavailable", "wetland-yield-unavailable"].includes(item?.key)) return "#ffe06b"
  return chartColor(index)
}

function getPiePercent(data) {
  const value = numericValue(data)
  const total = Number(data?.count) || sumValue.value
  if (!value || !total) return "0%"
  return `${formatNumber((value / total) * 100)}%`
}

function piePercentValue(data) {
  const value = numericValue(data)
  const total = Number(data?.count) || sumValue.value
  if (!value || !total) return 0
  return (value / total) * 100
}

function polarPoint(cx, cy, radius, angle) {
  const radian = (angle * Math.PI) / 180
  return {
    x: Number((cx + radius * Math.cos(radian)).toFixed(2)),
    y: Number((cy + radius * Math.sin(radian)).toFixed(2)),
  }
}

function describeRoseSegment(cx, cy, innerRadius, outerRadius, startAngle, endAngle) {
  const outerStart = polarPoint(cx, cy, outerRadius, startAngle)
  const outerEnd = polarPoint(cx, cy, outerRadius, endAngle)
  const innerEnd = polarPoint(cx, cy, innerRadius, endAngle)
  const innerStart = polarPoint(cx, cy, innerRadius, startAngle)
  const largeArc = endAngle - startAngle > 180 ? 1 : 0
  return [
    `M ${outerStart.x} ${outerStart.y}`,
    `A ${outerRadius} ${outerRadius} 0 ${largeArc} 1 ${outerEnd.x} ${outerEnd.y}`,
    `L ${innerEnd.x} ${innerEnd.y}`,
    `A ${innerRadius} ${innerRadius} 0 ${largeArc} 0 ${innerStart.x} ${innerStart.y}`,
    "Z",
  ].join(" ")
}

function chartColor(index) {
  return colors[index % colors.length]
}

function getMetricIcon(item, index) {
  if (item?.icon) return String(item.icon).replace(/[^a-z0-9-]/gi, "")
  const name = String(item?.name || "")
  if (name.includes("利用率") || name.includes("占比")) return "rate"
  if (name.includes("重度") || name.includes("退化")) return "risk"
  if (name.includes("可食") || name.includes("供给")) return "leaf"
  if (name.includes("不可")) return "stack"
  if (name.includes("产量") || name.includes("鲜草")) return "yield"
  if (name.includes("乡镇")) return "town"
  if (name.includes("面积")) return "area"
  return ["yield", "leaf", "rate", "risk"][index % 4]
}

function startDonutLoop() {
  stopDonutLoop()
  const loopLength = activeLoopLength.value
  if (!panelVisible.value) return
  if (loopLength < 2) return
  donutTimer = window.setInterval(() => {
    activeDonutIndex.value = (activeDonutIndex.value + 1) % loopLength
  }, pieLoopDelay)
}

function syncDonutLoop() {
  if (panelVisible.value) {
    startDonutLoop()
  } else {
    stopDonutLoop()
  }
}

function stopDonutLoop() {
  if (!donutTimer) return
  window.clearInterval(donutTimer)
  donutTimer = null
}

function setupPanelVisibility() {
  updatePanelVisibility()
  if (!panelRef.value || typeof window.IntersectionObserver !== "function") return
  visibilityObserver = new IntersectionObserver((entries) => {
    const entry = entries[0]
    panelVisible.value = Boolean(entry?.isIntersecting) && isPanelActuallyVisible()
  })
  visibilityObserver.observe(panelRef.value)
  window.requestAnimationFrame(updatePanelVisibility)
}

function cleanupPanelVisibility() {
  visibilityObserver?.disconnect?.()
  visibilityObserver = null
}

function updatePanelVisibility() {
  panelVisible.value = isPanelActuallyVisible()
}

function isPanelActuallyVisible() {
  const element = panelRef.value
  if (!element) return true
  return Boolean(element.offsetParent || element.getClientRects().length)
}

function barGradient(index, item = {}) {
  const color = item.color || item.fillColor || chartColor(index)
  return `linear-gradient(90deg, ${hexToRgba(color, 0.16)} 0%, ${hexToRgba(color, 0.72)} 42%, ${color} 78%, rgba(255,255,255,0.94) 100%)`
}

function columnGradient(index, item = {}) {
  if (props.panel?.variant === "plain") {
    const color = item.color || item.fillColor
    if (color) return `linear-gradient(180deg, rgba(255,255,255,0.96) 0%, ${hexToRgba(color, 0.96)} 16%, ${hexToRgba(color, 0.72)} 74%, ${hexToRgba(color, 0.18)} 100%)`
    const palette = [
      ["#9BEA55", "#29DFA7"],
      ["#7FEA6A", "#24D5C0"],
      ["#B6E84C", "#47D982"],
    ]
    const [top, bottom] = palette[index % palette.length]
    return `linear-gradient(180deg, rgba(255,255,255,0.96) 0%, ${top} 16%, ${bottom} 76%, rgba(36,246,196,0.18) 100%)`
  }
  const color = item.color || item.fillColor || chartColor(index)
  return `linear-gradient(180deg, rgba(255,255,255,0.96) 0%, ${color} 18%, ${hexToRgba(color, 0.7)} 72%, rgba(50, 220, 255, 0.12) 100%)`
}
</script>

<style lang="scss">
.business-panel {
  height: 100%;
  box-sizing: border-box;
  overflow: hidden;
}

.business-chart-tooltip {
  position: fixed;
  z-index: 9999;
  min-width: 148px;
  max-width: 220px;
  padding: 8px 10px;
  pointer-events: none;
  color: rgba(229, 252, 255, 0.9);
  border: 1px solid rgba(48, 220, 255, 0.44);
  background:
    linear-gradient(135deg, rgba(6, 33, 49, 0.96), rgba(2, 18, 30, 0.92)),
    radial-gradient(circle at 12% 0%, rgba(36, 246, 196, 0.22), transparent 54%);
  box-shadow:
    inset 0 0 18px rgba(48, 220, 255, 0.12),
    0 0 18px rgba(48, 220, 255, 0.24);
  backdrop-filter: blur(3px);

  strong {
    display: block;
    max-width: 100%;
    color: #ffffff;
    font-size: 13px;
    line-height: 16px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  span {
    display: block;
    margin-top: 4px;
    color: rgba(220, 248, 255, 0.78);
    font-size: 12px;
    line-height: 15px;
    white-space: nowrap;
  }
}

.business-panel-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: rgba(255, 255, 255, 0.52);
  font-size: 14px;
}

@keyframes businessDataPulse {
  0%,
  100% {
    filter: brightness(1);
    box-shadow: 0 0 8px rgba(36, 246, 196, 0.12);
  }

  50% {
    filter: brightness(1.22);
    box-shadow: 0 0 16px rgba(36, 246, 196, 0.34);
  }
}

@keyframes businessDataSweep {
  0% {
    transform: translateX(-130%);
  }

  100% {
    transform: translateX(130%);
  }
}

@keyframes businessColumnReload {
  0%,
  8% {
    opacity: 0.46;
    transform: scaleY(0.22);
    filter: saturate(0.82) brightness(0.72);
    box-shadow: 0 0 7px rgba(48, 220, 255, 0.16);
  }

  20% {
    opacity: 0.82;
    transform: scaleY(0.72);
    filter: saturate(1.18) brightness(1.06);
    box-shadow: 0 0 13px rgba(48, 220, 255, 0.38);
  }

  34% {
    opacity: 1;
    transform: scaleY(1);
    filter: saturate(1.32) brightness(1.18);
    box-shadow: 0 0 18px rgba(48, 220, 255, 0.56);
  }

  54% {
    opacity: 1;
    transform: scaleY(1);
    filter: saturate(1.08) brightness(1.06);
    box-shadow: 0 0 14px rgba(48, 220, 255, 0.46);
  }

  100% {
    opacity: 0.62;
    transform: scaleY(0.9);
    filter: saturate(0.94) brightness(0.86);
    box-shadow: 0 0 9px rgba(48, 220, 255, 0.22);
  }
}

@keyframes businessColumnReloadCap {
  0%,
  16% {
    opacity: 0;
    transform: skewX(-36deg) translateY(9px);
  }

  30% {
    opacity: 0.9;
    transform: skewX(-36deg) translateY(0);
  }

  48%,
  100% {
    opacity: 0;
    transform: skewX(-36deg) translateY(-9px);
  }
}

@keyframes businessLineFlow {
  to {
    stroke-dashoffset: -28;
  }
}

@keyframes businessDotPulse {
  0%,
  100% {
    r: 3;
    opacity: 0.82;
  }

  50% {
    r: 4.8;
    opacity: 1;
  }
}

@keyframes businessActiveDotPulse {
  0%,
  100% {
    r: 5.2;
  }

  50% {
    r: 7;
  }
}

.business-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  height: 100%;
  padding: 8px 14px 9px;
  box-sizing: border-box;
}

.business-metric-item {
  min-width: 0;
  padding: 8px 10px;
  background: linear-gradient(135deg, rgba(22, 90, 108, 0.62), rgba(5, 26, 40, 0.68));
  border: 1px solid rgba(48, 220, 255, 0.18);

  span {
    display: block;
    color: rgba(255, 255, 255, 0.62);
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  strong {
    display: inline-block;
    margin-top: 5px;
    color: #1afcff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 22px;
    line-height: 24px;
  }

  em {
    margin-left: 4px;
    color: rgba(255, 255, 255, 0.58);
    font-size: 11px;
    font-style: normal;
  }
}

.business-icon-metrics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 8px 10px;
  height: 100%;
  padding: 8px 14px 9px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-icon-metric-item {
  position: relative;
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr);
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 0;
  padding: 7px 8px;
  box-sizing: border-box;
  overflow: hidden;
  border: 1px solid rgba(48, 220, 255, 0.16);
  background:
    linear-gradient(90deg, rgba(48, 220, 255, 0.1), rgba(48, 220, 255, 0.02)),
    linear-gradient(180deg, rgba(8, 41, 56, 0.72), rgba(4, 20, 32, 0.66));

  &:before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    bottom: 8px;
    width: 2px;
    background: #24f6c4;
    box-shadow: 0 0 10px rgba(36, 246, 196, 0.7);
  }

  &.is-tone-1:before {
    background: #32dcff;
    box-shadow: 0 0 10px rgba(50, 220, 255, 0.7);
  }

  &.is-tone-2:before {
    background: #ffe06b;
    box-shadow: 0 0 10px rgba(255, 224, 107, 0.62);
  }

  &.is-tone-3:before {
    background: #ff9a62;
    box-shadow: 0 0 10px rgba(255, 154, 98, 0.62);
  }
}

.business-icon-metric-mark {
  position: relative;
  display: block;
  width: 42px;
  height: 42px;
  border: 1px solid rgba(48, 220, 255, 0.4);
  border-radius: 8px;
  background:
    radial-gradient(circle at 50% 42%, rgba(36, 246, 196, 0.25), rgba(36, 246, 196, 0.04) 64%),
    linear-gradient(135deg, rgba(48, 220, 255, 0.22), rgba(4, 24, 36, 0.28));
  box-shadow: inset 0 0 16px rgba(48, 220, 255, 0.16), 0 0 12px rgba(48, 220, 255, 0.14);
  overflow: hidden;

  &:before,
  &:after,
  span,
  span:before,
  span:after {
    content: "";
    position: absolute;
    box-sizing: border-box;
  }

  &.is-yield {
    span {
      left: 12px;
      right: 12px;
      bottom: 9px;
      height: 22px;
      border-radius: 10px 10px 4px 4px;
      background: linear-gradient(180deg, #7dfdff, #20d8ff 54%, rgba(36, 246, 196, 0.42));
      box-shadow: 0 0 10px rgba(32, 216, 255, 0.58);
    }

    &:before,
    &:after {
      bottom: 9px;
      width: 6px;
      height: 16px;
      border-radius: 6px 6px 3px 3px;
      background: rgba(126, 226, 105, 0.72);
    }

    &:before {
      left: 7px;
    }

    &:after {
      right: 7px;
    }
  }

  &.is-leaf {
    span {
      left: 10px;
      top: 10px;
      width: 22px;
      height: 22px;
      border-radius: 22px 4px 22px 4px;
      background: linear-gradient(135deg, #7ee269, #24f6c4);
      transform: rotate(-24deg);
      box-shadow: 0 0 12px rgba(36, 246, 196, 0.52);
    }

    span:after {
      left: 10px;
      top: 3px;
      width: 2px;
      height: 18px;
      border-radius: 2px;
      background: rgba(3, 45, 43, 0.5);
      transform: rotate(44deg);
    }
  }

  &.is-rate {
    &:before {
      left: 9px;
      top: 10px;
      width: 24px;
      height: 24px;
      border: 4px solid rgba(50, 220, 255, 0.32);
      border-top-color: #ffe06b;
      border-right-color: #24f6c4;
      border-radius: 50%;
      transform: rotate(38deg);
    }

    span {
      left: 20px;
      top: 20px;
      width: 12px;
      height: 3px;
      border-radius: 3px;
      background: #ffffff;
      transform: rotate(-30deg);
      transform-origin: left center;
      box-shadow: 0 0 8px rgba(255, 255, 255, 0.6);
    }
  }

  &.is-risk {
    &:before {
      left: 10px;
      top: 9px;
      width: 22px;
      height: 22px;
      border-left: 3px solid #ff9a62;
      border-bottom: 3px solid #ff9a62;
      transform: rotate(-45deg);
      box-shadow: -4px 4px 10px rgba(255, 154, 98, 0.34);
    }

    span {
      left: 20px;
      top: 13px;
      width: 3px;
      height: 16px;
      border-radius: 3px;
      background: #ffe06b;
      box-shadow: 0 0 8px rgba(255, 224, 107, 0.54);
    }
  }

  &.is-town {
    span,
    span:before,
    span:after,
    &:before {
      width: 9px;
      height: 9px;
      border-radius: 2px;
      background: #32dcff;
      box-shadow: 0 0 9px rgba(50, 220, 255, 0.5);
    }

    span {
      left: 10px;
      top: 10px;
    }

    span:before {
      left: 13px;
      top: 0;
    }

    span:after {
      left: 0;
      top: 13px;
    }

    &:before {
      left: 23px;
      top: 23px;
      border: 2px solid #24f6c4;
      background: transparent;
    }
  }

  &.is-area {
    &:before {
      left: 8px;
      top: 13px;
      width: 26px;
      height: 16px;
      border: 2px solid #24f6c4;
      transform: skewX(-18deg);
      background: linear-gradient(135deg, rgba(36, 246, 196, 0.34), rgba(50, 220, 255, 0.06));
    }

    span {
      left: 13px;
      top: 19px;
      width: 16px;
      height: 2px;
      background: #32dcff;
      box-shadow: 0 5px 0 rgba(50, 220, 255, 0.7);
    }
  }

  &.is-stack {
    span,
    span:before,
    span:after {
      left: 10px;
      width: 22px;
      height: 5px;
      border-radius: 5px;
      background: linear-gradient(90deg, #32dcff, #24f6c4);
      box-shadow: 0 0 9px rgba(36, 246, 196, 0.34);
    }

    span {
      top: 12px;
    }

    span:before {
      top: 8px;
    }

    span:after {
      top: 16px;
      background: linear-gradient(90deg, #ffe06b, #ff9a62);
    }
  }
}

.business-icon-metric-copy {
  min-width: 0;

  span {
    display: block;
    min-width: 0;
    color: rgba(220, 248, 255, 0.76);
    font-size: 12px;
    line-height: 15px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  strong {
    display: block;
    margin-top: 3px;
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 20px;
    line-height: 22px;
    font-weight: 800;
    text-shadow: 0 0 14px rgba(48, 220, 255, 0.42);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    em {
      margin-left: 3px;
      color: rgba(255, 255, 255, 0.58);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }
}

.business-spotlight {
  display: grid;
  grid-template-columns: 142px minmax(0, 1fr);
  gap: 12px;
  height: 100%;
  padding: 10px 14px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-spotlight-main {
  position: relative;
  min-width: 0;
  padding: 13px 10px 10px;
  border: 1px solid rgba(48, 220, 255, 0.22);
  background:
    radial-gradient(circle at 50% 38%, rgba(36, 246, 196, 0.26), rgba(36, 246, 196, 0.03) 62%),
    linear-gradient(180deg, rgba(48, 220, 255, 0.12), rgba(4, 22, 34, 0.36));
  text-align: center;

  &:before,
  &:after {
    content: "";
    position: absolute;
    left: 18px;
    right: 18px;
    height: 1px;
    background: linear-gradient(90deg, rgba(48, 220, 255, 0), rgba(48, 220, 255, 0.8), rgba(48, 220, 255, 0));
  }

  &:before {
    top: 8px;
  }

  &:after {
    bottom: 8px;
  }

  span,
  small {
    display: block;
    overflow: hidden;
    color: rgba(210, 245, 255, 0.72);
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  strong {
    display: block;
    margin: 10px 0 6px;
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 30px;
    line-height: 32px;
    font-weight: 800;
    text-shadow: 0 0 18px rgba(48, 220, 255, 0.48);
    white-space: nowrap;

    em {
      margin-left: 4px;
      color: rgba(255, 255, 255, 0.64);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 11px;
      font-style: normal;
      font-weight: 500;
    }
  }

  small {
    color: rgba(255, 224, 107, 0.86);
  }
}

.business-spotlight-side {
  display: grid;
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 8px;
  min-width: 0;
}

.business-spotlight-chip {
  position: relative;
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr);
  grid-template-areas:
    "dot name"
    "dot value"
    "dot note";
  align-content: center;
  gap: 1px 8px;
  min-width: 0;
  padding: 8px 10px;
  border: 1px solid rgba(48, 220, 255, 0.12);
  background: linear-gradient(90deg, rgba(48, 220, 255, 0.09), rgba(48, 220, 255, 0.02));
  box-sizing: border-box;

  i {
    grid-area: dot;
    align-self: center;
    width: 8px;
    height: 28px;
    border-left: 3px solid #24f6c4;
  }

  span,
  small {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  span {
    grid-area: name;
    color: rgba(255, 255, 255, 0.7);
    font-size: 11px;
    line-height: 14px;
  }

  strong {
    grid-area: value;
    color: #1afcff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 18px;
    line-height: 20px;
    white-space: nowrap;

    em {
      margin-left: 3px;
      color: rgba(255, 255, 255, 0.56);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }

  small {
    grid-area: note;
    color: rgba(255, 224, 107, 0.76);
    font-size: 10px;
    line-height: 12px;
  }
}

.business-donut {
  display: grid;
  grid-template-columns: 136px minmax(0, 1fr);
  align-items: stretch;
  gap: 8px;
  height: 100%;
  padding: 7px 13px 8px 14px;
  box-sizing: border-box;

  &.is-dense {
    grid-template-columns: 126px minmax(0, 1fr);
    padding: 6px 12px 7px;

    .business-donut-visual {
      width: 126px;
      height: 120px;
    }

    .business-donut-legend {
      justify-content: flex-start;
      gap: 3px;
    }

    .business-donut-row {
      min-height: 20px;
      grid-template-columns: 12px minmax(0, 1fr) 52px 28px;
      gap: 5px;

      span {
        font-size: 11px;
        line-height: 13px;
      }

      strong {
        font-size: 13px;
        line-height: 15px;
      }

      em {
        font-size: 10px;
      }
    }
  }

  &.is-variant-ring {
    grid-template-columns: 132px minmax(0, 1fr);
    align-items: center;
    gap: 11px;
    padding: 8px 13px 8px 15px;

    .business-donut-legend {
      justify-content: stretch;
      gap: 6px;
    }

    .business-donut-row {
      flex: 1 1 0;
      grid-template-columns: 12px minmax(0, 1fr) max-content max-content;
      gap: 5px;
      min-height: 22px;
      padding: 0 1px;

      i {
        width: 8px;
        height: 8px;
        border-width: 2px;
        background: rgba(5, 28, 42, 0.86);
      }

      strong {
        font-size: 16px;
        line-height: 18px;
      }
    }

    &.is-dense {
      grid-template-columns: 148px minmax(0, 1fr);
      gap: 10px;
      padding: 5px 12px 6px 14px;

      .business-ring-visual {
        width: 148px;
        height: 148px;
      }

      .business-ring-chart {
        width: 144px;
        height: 144px;
      }

      .business-ring-inner {
        inset: 37px 32px 35px;

        strong {
          font-size: 22px;
          line-height: 24px;
        }

        span {
          max-width: 74px;
          font-size: 11px;
          line-height: 13px;
        }
      }

      .business-donut-legend {
        align-self: center;
        justify-content: center;
        height: auto;
        max-height: 100%;
        gap: 5px;
      }

      .business-donut-row {
        flex: 1 1 0;
        grid-template-columns: 10px minmax(0, 1fr) max-content max-content;
        gap: 5px;
        min-height: 21px;
        padding: 2px;

        i {
          width: 8px;
          height: 8px;
          border-width: 1px;
        }

        span {
          font-size: 12px;
          line-height: 15px;
        }

        strong {
          font-size: 15px;
          line-height: 17px;
        }

        em {
          font-size: 10px;
        }
      }
    }
  }
}

.business-donut-visual {
  position: relative;
  align-self: center;
  width: 136px;
  height: 136px;
  min-width: 0;
}

.business-rose {
  display: grid;
  grid-template-columns: 158px minmax(0, 1fr);
  align-items: center;
  gap: 4px;
  height: 100%;
  padding: 4px 12px 7px 8px;
  box-sizing: border-box;
}

.business-rose-visual {
  position: relative;
  width: 158px;
  height: 136px;
  min-width: 0;

  svg {
    width: 100%;
    height: 100%;
    overflow: visible;
  }
}

.business-rose-segment {
  opacity: 0.92;
  stroke-width: 1.5;
  stroke-opacity: 0.5;
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity 0.3s ease, filter 0.3s ease, transform 0.3s ease;
  filter:
    drop-shadow(0 2px 2px rgba(0, 10, 18, 0.34))
    drop-shadow(0 0 5px rgba(48, 220, 255, 0.18));

  &.is-active {
    opacity: 1;
    transform: scale(1.035);
    filter:
      drop-shadow(0 3px 5px rgba(0, 10, 18, 0.42))
      drop-shadow(0 0 10px rgba(36, 246, 196, 0.42));
  }
}

.business-rose-guides line {
  stroke-width: 1;
  stroke-opacity: 0.5;
}

.business-rose-labels text {
  fill: rgba(226, 252, 255, 0.68);
  font-size: 8px;
  font-weight: 600;
  dominant-baseline: middle;
}

.business-rose-glow {
  fill: rgba(36, 246, 196, 0.1);
  stroke: rgba(48, 220, 255, 0.24);
  stroke-width: 1;
  filter: drop-shadow(0 0 8px rgba(36, 246, 196, 0.26));
}

.business-rose-hole {
  fill: rgba(3, 18, 30, 0.94);
  stroke: rgba(227, 253, 255, 0.22);
  stroke-width: 1.2;
}

.business-rose-legend {
  gap: 6px;
  padding-right: 0;
}

.business-rose-row {
  grid-template-columns: 13px minmax(0, 1fr) 56px 28px;
  gap: 7px;
  min-height: 23px;

  i {
    width: 10px;
    height: 10px;
    border-width: 1px;
    box-shadow: 0 0 7px currentColor;
  }
}

.business-three-pie {
  width: 100%;
  height: 100%;
}

.business-three-pie-center {
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  width: 100%;
  height: auto;
  color: #fff;
  text-align: center;
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.96);
  pointer-events: none;

  strong {
    color: #fff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 21px;
    line-height: 22px;
    font-weight: 800;
    letter-spacing: 0;
    transform: translateY(-2px);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  span {
    max-width: 86px;
    margin-top: 0;
    color: rgba(255, 255, 255, 0.96);
    font-size: 10px;
    line-height: 11px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.business-ring-visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 132px;
  height: 132px;
  min-width: 0;
  isolation: isolate;

  &:before {
    content: "";
    position: absolute;
    left: 11px;
    right: 11px;
    bottom: 12px;
    height: 24px;
    border-radius: 50%;
    background: radial-gradient(ellipse at center, rgba(48, 220, 255, 0.24), rgba(48, 220, 255, 0) 72%);
    filter: blur(2px);
    pointer-events: none;
  }
}

.business-ring-chart {
  position: relative;
  z-index: 1;
  width: 128px;
  height: 128px;
  overflow: visible;
}

.business-ring-halo {
  fill: rgba(4, 22, 34, 0.88);
  stroke: rgba(48, 220, 255, 0.16);
  stroke-width: 1;
  filter: drop-shadow(0 0 12px rgba(48, 220, 255, 0.18));
}

.business-ring-track,
.business-ring-segment {
  fill: none;
  transform: rotate(-90deg);
  transform-origin: 80px 80px;
}

.business-ring-track {
  stroke: rgba(48, 220, 255, 0.12);
  stroke-width: 22;
}

.business-ring-segment {
  stroke-width: 22;
  stroke-linecap: round;
  opacity: 0.9;
  transition: stroke-width 0.35s ease, opacity 0.35s ease, filter 0.35s ease;
  filter: drop-shadow(0 0 4px rgba(48, 220, 255, 0.3));

  &.is-active {
    stroke-width: 24;
    opacity: 1;
    filter:
      drop-shadow(0 0 4px currentColor)
      drop-shadow(0 0 10px rgba(48, 220, 255, 0.5));
  }
}

.business-ring-inner {
  position: absolute;
  inset: 33px 30px 31px;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  text-align: center;
  text-shadow: 0 0 10px rgba(0, 0, 0, 0.98);
  pointer-events: none;

  strong {
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 22px;
    line-height: 24px;
    font-weight: 800;
    letter-spacing: 0;
  }

  span {
    max-width: 70px;
    margin-top: 2px;
    color: rgba(255, 255, 255, 0.94);
    font-size: 11px;
    line-height: 13px;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.business-donut-legend {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
  height: 100%;
  gap: 7px;
  overflow-y: auto;
  padding-right: 2px;

  &::-webkit-scrollbar {
    width: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.28);
  }
}

.business-donut-row {
  position: relative;
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr) 58px 28px;
  align-items: center;
  gap: 8px;
  min-height: 24px;
  padding: 0 2px;
  overflow: hidden;
  border: 1px solid rgba(48, 220, 255, 0.12);
  background: rgba(48, 220, 255, 0.055);
  transition: background 0.35s ease, border-color 0.35s ease;

  &:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--row-percent);
    background: linear-gradient(90deg, var(--row-color), rgba(48, 220, 255, 0));
    opacity: 0.2;
    pointer-events: none;
  }

  i {
    position: relative;
    z-index: 1;
    width: 10px;
    height: 10px;
    border: 2px solid #24f6c4;
    border-radius: 50%;
    box-sizing: border-box;
  }

  span {
    position: relative;
    z-index: 1;
    min-width: 0;
    color: rgba(255, 255, 255, 0.88);
    font-size: 13px;
    line-height: 15px;
    font-weight: 700;
    white-space: normal;
  }

  strong {
    position: relative;
    z-index: 1;
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 18px;
    font-weight: 800;
    line-height: 20px;
    text-align: right;
  }

  em {
    position: relative;
    z-index: 1;
    color: rgba(255, 255, 255, 0.52);
    font-size: 11px;
    font-style: normal;
    white-space: nowrap;
  }

  &.is-active {
    border-color: rgba(48, 220, 255, 0.22);
    background: linear-gradient(90deg, rgba(48, 220, 255, 0.18), rgba(48, 220, 255, 0.04));

    span,
    strong {
      color: #fff;
    }

    i {
      box-shadow: 0 0 10px currentColor;
      transform: scale(1.2);
    }
  }
}

.business-structure {
  display: grid;
  grid-template-rows: 32px minmax(0, 1fr);
  gap: 7px;
  height: 100%;
  padding: 8px 13px 9px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-structure-overview {
  display: flex;
  align-items: center;
  min-width: 0;
}

.business-structure-band {
  display: flex;
  align-self: center;
  width: 100%;
  height: 25px;
  padding: 4px;
  background: linear-gradient(90deg, rgba(48, 220, 255, 0.14), rgba(36, 246, 196, 0.05));
  border: 1px solid rgba(48, 220, 255, 0.2);
  box-shadow: inset 0 0 18px rgba(48, 220, 255, 0.08);

  i {
    position: relative;
    display: block;
    min-width: 7px;
    height: 100%;
    box-shadow: 0 0 12px currentColor;
    overflow: hidden;

    &:before {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
      opacity: 0;
      transform: translateX(-130%);
    }

    &.is-active {
      animation: businessDataPulse 1.8s ease-in-out infinite;
      z-index: 1;

      &:before {
        opacity: 1;
        animation: businessDataSweep 1.8s ease-in-out infinite;
      }
    }
  }
}

.business-structure-focus {
  min-width: 0;
  padding: 6px 8px;
  background: linear-gradient(135deg, rgba(36, 246, 196, 0.16), rgba(48, 220, 255, 0.05));
  border: 1px solid rgba(48, 220, 255, 0.18);

  span {
    display: block;
    color: rgba(255, 255, 255, 0.52);
    font-size: 10px;
    line-height: 12px;
  }

  strong {
    display: block;
    min-width: 0;
    margin-top: 1px;
    color: #ffffff;
    font-size: 12px;
    line-height: 15px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  em {
    display: inline-block;
    margin-top: 3px;
    color: #1afcff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 17px;
    line-height: 18px;
    font-style: normal;
    font-weight: 800;
  }

  small {
    display: block;
    margin-top: 1px;
    color: rgba(255, 224, 107, 0.9);
    font-size: 11px;
    line-height: 13px;
  }
}

.business-structure-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: minmax(22px, 1fr);
  align-content: stretch;
  gap: 5px;
  min-height: 0;
  overflow: hidden;
  padding-right: 0;

  &::-webkit-scrollbar {
    width: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.28);
  }
}

.business-structure-row {
  position: relative;
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) 70px 42px;
  align-items: center;
  gap: 5px;
  min-height: 0;
  padding: 0 7px;
  overflow: hidden;
  background: rgba(48, 220, 255, 0.04);
  border: 1px solid rgba(48, 220, 255, 0.08);
  transition: border-color 0.3s ease, background 0.3s ease;

  &:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: var(--row-percent);
    background: linear-gradient(90deg, var(--row-color), rgba(48, 220, 255, 0));
    opacity: 0.11;
    pointer-events: none;
  }

  i {
    position: relative;
    z-index: 1;
    width: 7px;
    height: 7px;
    box-shadow: 0 0 8px currentColor;
  }

  span {
    position: relative;
    z-index: 1;
    min-width: 0;
    color: rgba(255, 255, 255, 0.76);
    font-size: 10px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  strong {
    position: relative;
    z-index: 1;
    color: #dffcff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 11px;
    line-height: 13px;
    text-align: right;
    white-space: nowrap;

    em {
      margin-left: 2px;
      color: rgba(255, 255, 255, 0.5);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }

  small {
    position: relative;
    z-index: 1;
    color: rgba(255, 224, 107, 0.82);
    font-family: D-DIN, Arial, sans-serif;
    font-size: 10px;
    line-height: 12px;
    text-align: right;
    white-space: nowrap;
  }

  &.is-active {
    background: linear-gradient(90deg, rgba(36, 246, 196, 0.18), rgba(48, 220, 255, 0.04));
    border-color: rgba(36, 246, 196, 0.36);
    animation: businessDataPulse 1.8s ease-in-out infinite;

    span,
    strong {
      color: #ffffff;
    }
  }
}

.business-capacity {
  display: grid;
  grid-template-rows: 22px 40px minmax(34px, 1fr) 18px;
  gap: 5px;
  height: 100%;
  padding: 8px 14px 7px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-capacity-head,
.business-capacity-town {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  min-width: 0;
}

.business-capacity-head {
  padding-bottom: 3px;
  border-bottom: 1px solid rgba(48, 220, 255, 0.12);
}

.business-capacity-head span,
.business-capacity-town span {
  min-width: 0;
  color: rgba(220, 248, 255, 0.76);
  font-size: 11px;
  line-height: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.business-capacity-head strong,
.business-capacity-town strong {
  color: #ffffff;
  font-family: D-DIN, Arial, sans-serif;
  font-size: 15px;
  line-height: 16px;
  font-weight: 800;
  white-space: nowrap;
  text-shadow: 0 0 10px rgba(48, 220, 255, 0.28);

  em {
    margin-left: 3px;
    color: rgba(255, 255, 255, 0.56);
    font-family: "PingFang SC", Arial, sans-serif;
    font-size: 10px;
    font-style: normal;
    font-weight: 500;
  }
}

.business-capacity-band {
  display: flex;
  align-self: center;
  height: 32px;
  padding: 5px;
  border: 1px solid rgba(48, 220, 255, 0.2);
  background: linear-gradient(90deg, rgba(48, 220, 255, 0.11), rgba(48, 220, 255, 0.03));
  box-shadow: inset 0 0 14px rgba(48, 220, 255, 0.08);

  i {
    position: relative;
    display: block;
    min-width: 8px;
    height: 100%;
    box-shadow: 0 0 12px currentColor;
    overflow: hidden;

    &:before {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
      opacity: 0;
      transform: translateX(-130%);
    }

    &.is-active {
      animation: businessDataPulse 1.8s ease-in-out infinite;
      z-index: 1;

      &:before {
        opacity: 1;
        animation: businessDataSweep 1.8s ease-in-out infinite;
      }
    }
  }
}

.business-capacity-list {
  display: grid;
  align-content: center;
  gap: 4px;
  min-height: 0;
}

.business-capacity-row {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr) 66px 40px;
  align-items: center;
  gap: 5px;
  min-width: 0;

  i {
    width: 7px;
    height: 7px;
    box-shadow: 0 0 8px currentColor;
  }

  span {
    min-width: 0;
    color: rgba(255, 255, 255, 0.76);
    font-size: 10px;
    line-height: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  strong {
    color: #dffcff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 11px;
    line-height: 13px;
    text-align: right;
    white-space: nowrap;

    em {
      margin-left: 2px;
      color: rgba(255, 255, 255, 0.5);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }

  small {
    color: rgba(255, 224, 107, 0.82);
    font-family: D-DIN, Arial, sans-serif;
    font-size: 10px;
    line-height: 12px;
    text-align: right;
    white-space: nowrap;
  }

  &.is-active {
    span,
    strong,
    small {
      color: #ffffff;
    }

    i {
      transform: scale(1.24);
      animation: businessDataPulse 1.8s ease-in-out infinite;
    }
  }
}

.business-capacity-town {
  min-width: 0;
  padding-top: 3px;
  border-top: 1px solid rgba(48, 220, 255, 0.1);

  strong {
    color: #24f6c4;
    font-size: 12px;
    line-height: 13px;
    text-shadow: none;
  }
}

.business-bars {
  display: flex;
  flex-direction: column;
  gap: 8px;
  height: 100%;
  padding: 12px 16px;
  box-sizing: border-box;
  overflow-y: auto;

  &::-webkit-scrollbar {
    width: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.28);
  }

  &.is-dense {
    gap: 4px;
    padding: 6px 14px;

    .business-bar-row {
      min-height: 20px;
    }

    .business-bar-name {
      font-size: 11px;
      line-height: 12px;
    }

    .business-bar-track {
      height: 5px;
      margin-top: 2px;
    }
  }

  &.is-long {
    gap: 2px;
    padding: 3px 14px 4px;

    .business-bar-row {
      min-height: 16px;
    }

    .business-bar-name {
      font-size: 10px;
      line-height: 11px;
    }

    .business-bar-track {
      height: 4px;
      margin-top: 1px;
      padding: 1px;
    }

    .business-bar-row strong {
      font-size: 12px;
      line-height: 12px;
    }

    .business-bar-row strong em,
    .business-bar-row strong small {
      font-size: 10px;
    }
  }

  &.is-single {
    gap: 5px;
    padding: 6px 14px;

    .business-bar-row {
      min-height: 22px;
    }

    .business-bar-name {
      font-size: 11px;
      line-height: 13px;
    }

    .business-bar-track {
      height: 5px;
      margin-top: 2px;
      padding: 1px;
    }

    .business-bar-row strong {
      font-size: 13px;
      line-height: 14px;
    }

    .business-bar-row strong em,
    .business-bar-row strong small {
      font-size: 10px;
    }
  }

  &.is-distribution {
    gap: 6px;
    padding: 8px 15px 9px;

    .business-bar-row {
      min-height: 27px;
      padding: 0 0 2px;
      border-bottom: 1px solid rgba(48, 220, 255, 0.07);
    }

    .business-bar-name {
      position: relative;
      padding-left: 11px;
      color: rgba(231, 250, 255, 0.84);
      font-size: 12px;
      line-height: 14px;

      &:before {
        content: "";
        position: absolute;
        left: 0;
        top: 4px;
        width: 5px;
        height: 5px;
        border-radius: 50%;
        background: #24f6c4;
        box-shadow: 0 0 9px rgba(36, 246, 196, 0.65);
      }
    }

    .business-bar-track {
      height: 7px;
      margin-top: 4px;
      padding: 1px;
      border-color: rgba(48, 220, 255, 0.18);
      background: linear-gradient(90deg, rgba(48, 220, 255, 0.12), rgba(48, 220, 255, 0.03));
    }

    .business-bar-row strong {
      color: #ffffff;
      font-size: 14px;
      line-height: 15px;
      text-shadow: 0 0 10px rgba(48, 220, 255, 0.36);
    }
  }

  &.is-distribution.is-long {
    gap: 3px;
    padding: 5px 14px 6px;

    .business-bar-row {
      min-height: 22px;
    }

    .business-bar-name {
      font-size: 11px;
      line-height: 12px;
    }
  }

  &.is-capacity {
    gap: 12px;
    padding: 12px 16px 10px;
    overflow: hidden;

    .business-bar-row {
      grid-template-columns: minmax(0, 1fr) auto;
      min-height: 24px;
      padding: 0;
      border-bottom: 0;
    }

    .business-bar-name {
      padding-left: 0;
      color: rgba(232, 250, 255, 0.82);
      font-size: 11px;
      line-height: 13px;

      &:before {
        display: none;
      }
    }

    .business-bar-track {
      height: 5px;
      margin-top: 5px;
      padding: 1px;
      border-color: rgba(172, 191, 188, 0.22);
      background: rgba(115, 208, 255, 0.05);
    }

    .business-bar-track i {
      min-width: 10px;
      box-shadow: 0 0 12px rgba(36, 246, 196, 0.32);
    }

    .business-bar-row strong {
      color: #24f6c4;
      font-size: 12px;
      line-height: 13px;
      text-shadow: none;
    }
  }

  &.is-rank-bar {
    gap: 2px;
    padding: 3px 14px 2px;
    overflow: hidden;

    .business-bar-row {
      position: relative;
      grid-template-columns: 26px minmax(0, 1fr) auto;
      grid-template-areas:
        "rank name value"
        "rank track track";
      align-items: center;
      min-height: 18px;
      gap: 1px 8px;
      padding: 1px 0 2px;
      border-bottom: 1px solid rgba(48, 220, 255, 0.075);
    }

    .business-bar-rank {
      grid-area: rank;
      display: flex;
      width: 18px;
      height: 18px;
      align-items: center;
      justify-content: center;
      border: 1px solid rgba(48, 220, 255, 0.28);
      background:
        linear-gradient(180deg, rgba(48, 220, 255, 0.18), rgba(36, 246, 196, 0.055)),
        rgba(4, 28, 42, 0.52);
      color: rgba(232, 252, 255, 0.9);
      font-family: D-DIN, Arial, sans-serif;
      font-size: 11px;
      font-weight: 800;
      box-shadow: inset 0 0 10px rgba(48, 220, 255, 0.08);
    }

    .business-bar-name {
      color: rgba(245, 253, 255, 0.94);
      font-size: 11px;
      line-height: 13px;
      font-weight: 700;
    }

    .business-bar-track {
      position: relative;
      height: 5px;
      margin-top: 0;
      padding: 1px;
      overflow: hidden;
      border-color: rgba(48, 220, 255, 0.2);
      background:
        repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.045) 0 1px, transparent 1px 28px),
        linear-gradient(90deg, rgba(48, 220, 255, 0.13), rgba(36, 246, 196, 0.035));
    }

    .business-bar-track i {
      min-width: 12px;
      box-shadow:
        0 0 10px rgba(48, 220, 255, 0.36),
        inset 0 0 7px rgba(255, 255, 255, 0.22);

      &:before {
        content: "";
        position: absolute;
        right: 0;
        top: -2px;
        width: 3px;
        height: calc(100% + 4px);
        background: rgba(255, 255, 255, 0.86);
        box-shadow: 0 0 10px rgba(255, 255, 255, 0.56);
      }
    }

    .business-bar-row strong {
      color: #ffffff;
      font-size: 13px;
      line-height: 14px;
      text-shadow: 0 0 8px rgba(48, 220, 255, 0.36);
    }

    .business-bar-row strong em,
    .business-bar-row strong small {
      color: rgba(238, 253, 255, 0.78);
      font-size: 10px;
    }

    .business-bar-row.is-active {
      .business-bar-rank {
        border-color: rgba(255, 224, 107, 0.46);
        color: #ffe06b;
        box-shadow:
          inset 0 0 12px rgba(255, 224, 107, 0.1),
          0 0 10px rgba(255, 224, 107, 0.14);
      }
    }
  }

  &.is-race-bar {
    justify-content: flex-start;
    gap: 5px;
    padding: 8px 10px 8px 13px;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(48, 220, 255, 0.46) rgba(48, 220, 255, 0.08);

    &::-webkit-scrollbar {
      width: 4px;
    }

    &::-webkit-scrollbar-track {
      background: rgba(48, 220, 255, 0.08);
    }

    &::-webkit-scrollbar-thumb {
      background: rgba(48, 220, 255, 0.46);
      border-radius: 4px;
    }

    .business-bar-row {
      grid-template-columns: 112px minmax(0, 1fr) 96px;
      grid-template-areas: "name track value";
      align-items: center;
      min-height: 28px;
      gap: 7px;
      padding: 0;
      border-bottom: 0;
    }

    .business-bar-name {
      position: relative;
      padding-left: 13px;
      color: rgba(240, 253, 255, 0.92);
      font-size: 11px;
      line-height: 12px;
      font-weight: 700;
      white-space: normal;
      word-break: break-all;
      overflow: visible;
      text-overflow: clip;

      &:before {
        content: "";
        position: absolute;
        left: 0;
        top: 4px;
        width: 7px;
        height: 7px;
        background: var(--bar-color, currentColor);
        box-shadow: 0 0 8px var(--bar-color, currentColor);
      }
    }

    .business-bar-track {
      position: relative;
      height: 22px;
      margin-top: 0;
      padding: 0;
      overflow: visible;
      border: 0;
      background:
        repeating-linear-gradient(90deg, rgba(214, 250, 255, 0.12) 0 1px, transparent 1px 52px),
        linear-gradient(90deg, rgba(48, 220, 255, 0.08), rgba(48, 220, 255, 0.025));

      &:before {
        content: "";
        position: absolute;
        left: 0;
        top: -8px;
        bottom: -8px;
        width: 1px;
        background: rgba(213, 247, 255, 0.32);
      }
    }

    .business-bar-track i {
      position: relative;
      height: 100%;
      min-width: 18px;
      box-shadow:
        0 0 13px rgba(36, 246, 196, 0.28),
        inset 0 1px 0 rgba(255, 255, 255, 0.26);
    }

    .business-bar-row:nth-child(1) .business-bar-name {
      color: #24f6c4;
    }

    .business-bar-row:nth-child(2) .business-bar-name {
      color: #32dcff;
    }

    .business-bar-row:nth-child(3) .business-bar-name {
      color: #ffe06b;
    }

    .business-bar-row strong {
      grid-area: value;
      color: #ffffff;
      font-size: 14px;
      line-height: 16px;
      text-align: left;
      text-shadow: none;
    }

    .business-bar-row strong em {
      margin-left: 3px;
      color: rgba(238, 253, 255, 0.72);
      font-size: 11px;
    }

    .business-bar-row strong small {
      display: block;
      margin: 1px 0 0;
      color: rgba(238, 253, 255, 0.72);
      font-size: 10px;
      line-height: 11px;
    }
  }

  &.is-race-bar.is-few-rows {
    justify-content: center;
    gap: 13px;
    padding: 15px 12px 16px 13px;

    .business-bar-row {
      min-height: 42px;
      grid-template-columns: 112px minmax(0, 1fr) 96px;
      gap: 9px;
    }

    .business-bar-name {
      padding-left: 15px;
      font-size: 12px;
      line-height: 15px;
      word-break: keep-all;
      white-space: nowrap;

      &:before {
        top: 4px;
        width: 8px;
        height: 8px;
      }
    }

    .business-bar-track {
      height: 25px;

      &:before {
        top: -9px;
        bottom: -9px;
      }
    }

    .business-bar-row strong {
      font-size: 15px;
      line-height: 17px;
    }

    .business-bar-row strong em {
      font-size: 11px;
    }

    .business-bar-row strong small {
      margin-top: 2px;
      font-size: 11px;
      line-height: 12px;
    }
  }

  &.is-race-bar.is-degradation {
    justify-content: flex-start;
    gap: 10px;
    padding: 13px 15px 9px 14px;

    .business-bar-row {
      grid-template-columns: 118px minmax(0, 1fr) 104px;
      min-height: 38px;
      gap: 10px;
    }

    .business-bar-name {
      padding-left: 14px;
      font-size: 12px;
      line-height: 15px;
      word-break: keep-all;
      white-space: nowrap;

      &:before {
        top: 4px;
        width: 8px;
        height: 8px;
      }
    }

    .business-bar-track {
      height: 25px;
      background:
        repeating-linear-gradient(90deg, rgba(214, 250, 255, 0.1) 0 1px, transparent 1px 44px),
        linear-gradient(90deg, rgba(48, 220, 255, 0.1), rgba(48, 220, 255, 0.025));
    }

    .business-bar-track:before {
      top: -6px;
      bottom: -6px;
    }

    .business-bar-row strong {
      font-size: 16px;
      line-height: 17px;
    }

    .business-bar-row strong em {
      font-size: 12px;
    }

    .business-bar-row strong small {
      margin-top: 3px;
      font-size: 12px;
      line-height: 13px;
    }
  }

  &.is-race-nowrap {
    .business-bar-row {
      grid-template-columns: 172px minmax(0, 1fr) 88px;
      gap: 7px;
    }

    .business-bar-name {
      font-size: 12px;
      line-height: 14px;
      white-space: nowrap;
      word-break: keep-all;
      overflow: hidden;
      text-overflow: clip;
    }
  }

  &.is-race-relaxed {
    justify-content: center;
    gap: 11px;
    padding: 14px 14px 15px 14px;

    .business-bar-row {
      grid-template-columns: 168px minmax(0, 1fr) 94px;
      min-height: 42px;
      gap: 8px;
    }

    .business-bar-name {
      font-size: 13px;
      line-height: 16px;
    }

    .business-bar-track {
      height: 27px;

      &:before {
        top: -10px;
        bottom: -10px;
      }
    }

    .business-bar-row strong {
      font-size: 15px;
      line-height: 17px;
    }

    .business-bar-row strong small {
      margin-top: 2px;
      font-size: 11px;
      line-height: 12px;
    }
  }
}

.business-bar-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "name value"
    "track track";
  align-items: end;
  gap: 2px 10px;
  flex: 0 0 auto;
  min-height: 31px;
  max-height: none;
}

.business-bar-name {
  grid-area: name;
  min-width: 0;
  color: rgba(255, 255, 255, 0.78);
  font-size: 12px;
  line-height: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.business-bar-track {
  grid-area: track;
  height: 7px;
  margin-top: 4px;
  padding: 2px;
  background: rgba(48, 220, 255, 0.08);
  border: 1px solid rgba(48, 220, 255, 0.16);

  i {
    position: relative;
    display: block;
    height: 100%;
    min-width: 8px;
    box-shadow: 0 0 12px rgba(48, 220, 255, 0.36);
    overflow: hidden;

    &:after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.55), transparent);
      opacity: 0;
      transform: translateX(-130%);
    }
  }
}

.business-bar-row.is-active {
  .business-bar-track i {
    animation: businessDataPulse 1.8s ease-in-out infinite;

    &:after {
      opacity: 1;
      animation: businessDataSweep 1.8s ease-in-out infinite;
    }
  }

  .business-bar-name,
  strong {
    color: #ffffff;
  }
}

.business-bar-row strong,
.business-split-row strong {
  grid-area: value;
  color: #1afcff;
  font-family: D-DIN, Arial, sans-serif;
  font-size: 14px;
  text-align: right;
  line-height: 15px;
  white-space: nowrap;

  em,
  small {
    margin-left: 2px;
    color: rgba(255, 255, 255, 0.54);
    font-family: "PingFang SC", Arial, sans-serif;
    font-size: 10px;
    font-style: normal;
    font-weight: 500;
  }

  small {
    display: inline;
    margin-left: 4px;
    line-height: 15px;
    white-space: nowrap;
  }
}

.business-bar-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
}

.business-columns {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(28px, 1fr));
  align-items: stretch;
  gap: 6px;
  height: 100%;
  padding: 32px 12px 8px;
  box-sizing: border-box;
  overflow: hidden;

  &:before {
    content: "";
    position: absolute;
    left: 12px;
    right: 12px;
    top: 50px;
    bottom: 41px;
    pointer-events: none;
    background:
      repeating-linear-gradient(
        to bottom,
        rgba(159, 220, 230, 0.22) 0 1px,
        transparent 1px 17px
      );
    opacity: 0;
  }

  &::-webkit-scrollbar {
    height: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.28);
  }

  &.is-dense {
    grid-template-columns: repeat(auto-fit, minmax(24px, 1fr));
    grid-auto-rows: minmax(0, 1fr);
    gap: 4px;
    padding: 34px 10px 8px;

    .business-column-item {
      grid-template-rows: 16px minmax(20px, 1fr) 28px;
      min-width: 0;

      strong {
        width: 100%;
        font-size: 11px;
        line-height: 15px;
        text-align: center;
      }

      span {
        max-width: 100%;
        font-size: 10px;
        line-height: 12px;
        white-space: nowrap;
      }
    }

    .business-column-track {
      width: 14px;
      height: 100%;
      min-height: 20px;
    }
  }

  &.is-variant-pin {
    grid-template-columns: repeat(auto-fit, minmax(24px, 1fr));
    gap: 5px;
    padding: 8px 9px 7px;

    &:before {
      opacity: 0.56;
    }

    .business-column-item {
      position: relative;
      z-index: 1;
      grid-template-rows: 18px minmax(44px, 1fr) 26px;

      strong {
        position: relative;
        z-index: 2;
        min-width: 42px;
        padding-bottom: 2px;
        color: #e8fcff;
        font-size: 11px;
        line-height: 14px;
        text-shadow: 0 0 9px rgba(255, 255, 255, 0.36);

        &:after {
          content: "";
          position: absolute;
          left: 50%;
          bottom: -4px;
          width: 18px;
          height: 1px;
          border-top: 1px dashed rgba(220, 250, 255, 0.62);
          transform: translateX(-2px) rotate(12deg);
          transform-origin: left center;
        }
      }

      span {
        max-width: 48px;
        color: rgba(235, 252, 255, 0.78);
        font-size: 10px;
        line-height: 11px;
        -webkit-line-clamp: 2;
      }
    }

    .business-column-track {
      width: 7px;
      height: 74px;
      min-height: 46px;
      border: 0;
      background: linear-gradient(180deg, rgba(48, 220, 255, 0.07), rgba(48, 220, 255, 0.02));

      &:before {
        content: "";
        position: absolute;
        left: 50%;
        top: 0;
        bottom: 0;
        width: 1px;
        background: rgba(48, 220, 255, 0.22);
        transform: translateX(-50%);
      }

      &:after {
        content: "";
        position: absolute;
        left: 50%;
        bottom: -5px;
        width: 21px;
        height: 6px;
        border-radius: 50%;
        background: radial-gradient(ellipse at center, rgba(48, 220, 255, 0.34), rgba(48, 220, 255, 0) 72%);
        transform: translateX(-50%);
      }

      i {
        left: 1px;
        right: 1px;
        border-radius: 6px 6px 2px 2px;
        box-shadow: 0 0 16px rgba(50, 220, 255, 0.64);

        &:before {
          left: 50%;
          right: auto;
          top: -6px;
          width: 9px;
          height: 9px;
          border: 2px solid #c9fcff;
          border-radius: 2px;
          background: rgba(3, 27, 41, 0.9);
          box-shadow: 0 0 12px rgba(48, 220, 255, 0.72);
          transform: translateX(-50%) rotate(45deg);
          filter: none;
        }

        &:after {
          display: none;
        }
      }
    }
  }

  &.is-variant-slim {
    grid-template-columns: repeat(auto-fit, minmax(26px, 1fr));
    gap: 6px;
    padding: 24px 10px 6px;

    &.is-dense {
      gap: 4px;
      padding: 34px 10px 8px;
    }

    .business-column-track {
      width: 16px;

      i {
        border-radius: 1px 1px 0 0;
      }
    }
  }

  &.is-variant-age {
    grid-template-columns: repeat(5, minmax(48px, 1fr));
    gap: 10px;
    padding: 34px 18px 14px;

    &:before {
      top: 56px;
      bottom: 46px;
      opacity: 0.36;
    }

    .business-column-item {
      grid-template-rows: 20px minmax(78px, 1fr) 28px;
      min-width: 0;
    }

    .business-column-item strong {
      width: 100%;
      color: #ffffff;
      font-size: 13px;
      line-height: 18px;
      text-align: center;
    }

    .business-column-item span {
      max-width: none;
      color: rgba(255, 255, 255, 0.9);
      font-size: 12px;
      line-height: 16px;
      white-space: nowrap;
      -webkit-line-clamp: 1;
    }

    .business-column-track {
      width: 23px;
      height: 92px;
      min-height: 72px;
      border-color: rgba(48, 220, 255, 0.22);
      background:
        linear-gradient(180deg, rgba(48, 220, 255, 0.1), rgba(48, 220, 255, 0.03)),
        rgba(5, 31, 44, 0.38);
    }

    .business-column-track i {
      left: 2px;
      right: 2px;
      min-height: 9px;
      border-radius: 3px 3px 0 0;
    }
  }

  &.is-variant-projectYear {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 3px;
    padding: 25px 14px 9px 8px;

    &:before {
      top: 47px;
      bottom: 43px;
      opacity: 0.42;
    }

    .business-column-item {
      grid-template-rows: 18px minmax(74px, 1fr) 26px;
      min-width: 0;
    }

    .business-column-item strong {
      color: #ffffff;
      font-size: 11px;
      line-height: 18px;
      text-align: center;
      text-shadow: 0 0 9px rgba(255, 255, 255, 0.28);
    }

    .business-column-item span {
      max-width: none;
      color: rgba(240, 253, 255, 0.9);
      font-size: 10px;
      line-height: 15px;
      white-space: nowrap;
      -webkit-line-clamp: 1;
    }

    .business-column-track {
      width: 19px;
      height: 92px;
      min-height: 74px;
      border: 1px solid rgba(48, 220, 255, 0.18);
      background:
        linear-gradient(180deg, rgba(48, 220, 255, 0.1), rgba(48, 220, 255, 0.025)),
        rgba(5, 29, 42, 0.3);
      box-shadow:
        inset 0 0 12px rgba(48, 220, 255, 0.08),
        0 0 10px rgba(48, 220, 255, 0.08);

      &:after {
        content: "";
        position: absolute;
        left: 50%;
        bottom: -6px;
        width: 28px;
        height: 8px;
        border-radius: 50%;
        background: radial-gradient(ellipse at center, rgba(48, 220, 255, 0.38), rgba(48, 220, 255, 0) 72%);
        transform: translateX(-50%);
      }
    }

    .business-column-track i {
      left: 2px;
      right: 2px;
      min-height: 12px;
      border-radius: 4px 4px 1px 1px;
      box-shadow:
        0 0 16px rgba(36, 246, 196, 0.36),
        inset 0 1px 0 rgba(255, 255, 255, 0.26);

      &:before {
        height: 8px;
        top: -5px;
        transform: skewX(-32deg);
      }

      &:after {
        display: none;
      }
    }
  }

  &.is-variant-compact {
    grid-template-columns: repeat(auto-fit, minmax(30px, 1fr));
    gap: 7px;
    padding: 24px 12px 8px;

    &:before {
      top: 44px;
      bottom: 37px;
      opacity: 0.48;
    }

    .business-column-item {
      grid-template-rows: 17px minmax(54px, 1fr) 28px;

      strong {
        font-size: 12px;
        line-height: 16px;
      }

      span {
        max-width: 52px;
        font-size: 10px;
        line-height: 12px;
        -webkit-line-clamp: 2;
      }
    }

    .business-column-track {
      width: 22px;
      min-height: 56px;
      border-color: rgba(36, 246, 196, 0.18);
      background:
        linear-gradient(180deg, rgba(36, 246, 196, 0.08), rgba(48, 220, 255, 0.02)),
        rgba(4, 26, 38, 0.34);

      i {
        left: 2px;
        right: 2px;
        min-height: 10px;
        border-radius: 3px 3px 0 0;
        box-shadow:
          0 0 14px rgba(36, 246, 196, 0.34),
          inset 0 1px 0 rgba(255, 255, 255, 0.22);
      }
    }
  }

  &.is-variant-townCompact {
    grid-template-columns: repeat(10, minmax(0, 1fr));
    gap: 4px;
    padding: 26px 10px 8px;

    &:before {
      top: 47px;
      bottom: 50px;
      opacity: 0.5;
    }

    .business-column-item {
      grid-template-rows: 17px minmax(54px, 1fr) 42px;
      min-width: 0;

      strong {
        width: max-content;
        max-width: 46px;
        font-size: 10px;
        line-height: 14px;
        transform: translateX(0);
      }

      span {
        align-self: start;
        max-width: none;
        height: 38px;
        color: rgba(255, 255, 255, 0.9);
        font-size: 11px;
        line-height: 13px;
        writing-mode: vertical-rl;
        text-orientation: mixed;
        letter-spacing: 0;
        white-space: nowrap;
        -webkit-line-clamp: unset;
      }
    }

    .business-column-track {
      width: 16px;
      min-height: 54px;
      border-color: rgba(36, 246, 196, 0.18);
      background:
        linear-gradient(180deg, rgba(36, 246, 196, 0.08), rgba(48, 220, 255, 0.02)),
        rgba(4, 26, 38, 0.34);

      i {
        left: 2px;
        right: 2px;
        min-height: 9px;
        border-radius: 3px 3px 0 0;
        box-shadow:
          0 0 12px rgba(36, 246, 196, 0.3),
          inset 0 1px 0 rgba(255, 255, 255, 0.22);
      }
    }
  }

  &.is-variant-plain {
    grid-template-columns: repeat(auto-fit, minmax(25px, 1fr));
    gap: 7px;
    padding: 18px 14px 7px;

    &:before {
      top: 37px;
      bottom: 36px;
      opacity: 0.62;
    }

    .business-column-item {
      position: relative;
      z-index: 1;
      grid-template-rows: 16px minmax(52px, 1fr) 28px;

      strong {
        color: rgba(244, 252, 255, 0.88);
        font-size: 11px;
        line-height: 15px;
      }

      span {
        max-width: 44px;
        color: rgba(255, 255, 255, 0.82);
        font-size: 10px;
        line-height: 12px;
        -webkit-line-clamp: 2;
      }
    }

    .business-column-track {
      width: 16px;
      height: 100%;
      min-height: 54px;
      border: 0;
      background: rgba(67, 130, 96, 0.1);
      box-shadow: none;

      i {
        left: 0;
        right: 0;
        min-height: 7px;
        border-radius: 2px 2px 0 0;
        box-shadow:
          0 0 10px rgba(36, 246, 196, 0.28),
          inset 0 1px 0 rgba(255, 255, 255, 0.24);

        &:before,
        &:after {
          display: none;
        }
      }
    }
  }

  &.is-dense.is-scrollable {
    display: flex;
    flex-flow: row nowrap;
    align-items: stretch;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(48, 220, 255, 0.46) rgba(48, 220, 255, 0.08);

    &::-webkit-scrollbar {
      height: 4px;
    }

    &::-webkit-scrollbar-track {
      background: rgba(48, 220, 255, 0.08);
    }

    &::-webkit-scrollbar-thumb {
      background: rgba(48, 220, 255, 0.46);
      border-radius: 4px;
    }

    .business-column-item {
      flex: 0 0 54px;
      width: 54px;
      min-width: 54px;
      height: 100%;
    }
  }

  &.is-dense.is-scrollable.is-variant-slim {
    .business-column-item {
      flex-basis: 50px;
      width: 50px;
      min-width: 50px;
    }
  }

  &.is-dense.is-scrollable.is-variant-plain {
    .business-column-item {
      flex-basis: 48px;
      width: 48px;
      min-width: 48px;
    }
  }

  &.has-unit-label {
    padding-top: 44px;

    &:before {
      top: 60px;
    }

    .business-column-unit {
      left: 12px;
      right: 12px;
      top: 4px;
      text-align: right;
    }
  }

  &.has-unit-label.is-variant-pin {
    padding-top: 38px;

    &:before {
      top: 54px;
    }
  }

  &.has-unit-label.is-variant-plain,
  &.has-unit-label.is-variant-slim,
  &.has-unit-label.is-variant-age,
  &.has-unit-label.is-variant-townCompact,
  &.has-unit-label.is-variant-compact {
    padding-top: 42px;

    &:before {
      top: 58px;
    }
  }
}

.business-column-item {
  display: grid;
  grid-template-rows: 18px minmax(52px, 1fr) 38px;
  justify-items: center;
  min-width: 0;

  strong {
    color: #d9fbff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 13px;
    white-space: nowrap;

    em {
      margin-left: 2px;
      color: rgba(238, 253, 255, 0.72);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 9px;
      font-style: normal;
      font-weight: 600;
    }
  }

  span {
    align-self: center;
    max-width: 76px;
    color: rgba(255, 255, 255, 0.66);
    font-size: 10px;
    line-height: 12px;
    text-align: center;
    overflow: hidden;
    display: block;
    text-overflow: ellipsis;
    white-space: nowrap;
    word-break: keep-all;
  }

  &.is-active {
    strong,
    span {
      color: #ffffff;
    }

    .business-column-track i {
      animation: businessDataPulse 1.8s ease-in-out infinite;
    }
  }
}

.business-column-unit {
  position: absolute;
  right: 14px;
  top: 2px;
  z-index: 2;
  padding: 1px 6px;
  background: linear-gradient(90deg, rgba(4, 23, 34, 0), rgba(4, 23, 34, 0.72));
  color: rgba(238, 253, 255, 0.72);
  font-size: 10px;
  line-height: 14px;
  pointer-events: none;
}

.business-columns.is-variant-slim .business-column-track i,
.business-columns.is-variant-slim .business-column-item.is-active .business-column-track i {
  transform: scaleY(1);
  transform-origin: center bottom;
  animation: businessColumnReload 3.1s cubic-bezier(0.32, 0.72, 0.24, 1) infinite;
  animation-delay: var(--column-load-delay, 0s);
  animation-fill-mode: both;
  will-change: transform, opacity, filter;
}

.business-columns.is-variant-slim .business-column-track i:before,
.business-columns.is-variant-slim .business-column-item.is-active .business-column-track i:before {
  animation: businessColumnReloadCap 3.1s ease-out infinite;
  animation-delay: var(--column-load-delay, 0s);
  animation-fill-mode: both;
}

.business-column-track {
  position: relative;
  width: 22px;
  height: 72px;
  align-self: end;
  background: linear-gradient(180deg, rgba(48, 220, 255, 0.08), rgba(48, 220, 255, 0.02));
  border: 1px solid rgba(48, 220, 255, 0.14);

  i {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    min-height: 8px;
    box-shadow: 0 0 14px rgba(48, 220, 255, 0.46);

    &:before,
    &:after {
      content: "";
      position: absolute;
      left: 0;
      right: 0;
      height: 7px;
      background: inherit;
      transform: skewX(-36deg);
    }

    &:before {
      top: -4px;
      filter: brightness(1.35);
    }

    &:after {
      bottom: -4px;
      filter: brightness(0.72);
    }
  }
}

.business-table {
  display: grid;
  grid-template-rows: 18px minmax(0, 1fr);
  gap: 4px;
  height: 100%;
  padding: 7px 12px 8px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-table-head {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
  align-items: center;
  padding: 0 5px;
  border: 1px solid rgba(48, 220, 255, 0.12);
  background: linear-gradient(90deg, rgba(48, 220, 255, 0.14), rgba(48, 220, 255, 0.03));
}

.business-table-head-group {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  align-items: center;
  gap: 4px;

  span {
    color: rgba(190, 235, 245, 0.7);
    font-size: 10px;
    line-height: 16px;
    white-space: nowrap;
  }
}

.business-table-body {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 3px 7px;
  min-height: 0;
}

.business-table-row {
  display: grid;
  grid-template-columns: 48px minmax(0, 1fr);
  align-items: center;
  gap: 4px;
  min-width: 0;
  min-height: 0;
  padding: 1px 5px;
  border: 1px solid rgba(48, 220, 255, 0.08);
  background: rgba(48, 220, 255, 0.035);
  box-sizing: border-box;

  &:nth-child(2n) {
    background: rgba(36, 246, 196, 0.035);
  }

  &.is-active {
    border-color: rgba(36, 246, 196, 0.34);
    background: linear-gradient(90deg, rgba(36, 246, 196, 0.15), rgba(48, 220, 255, 0.04));
    animation: businessDataPulse 1.8s ease-in-out infinite;

    .business-table-name,
    strong {
      color: #ffffff;
    }
  }
}

.business-table-name {
  min-width: 0;
  color: rgba(235, 252, 255, 0.78);
  font-size: 10px;
  line-height: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.business-table-row strong {
  display: block;
  color: #ffffff;
  font-family: D-DIN, Arial, sans-serif;
  font-size: 11px;
  line-height: 12px;
  text-align: right;
  white-space: nowrap;

  em {
    display: none;
  }
}

.business-table-value {
  min-width: 0;
}

.business-table-value i {
  position: relative;
  display: block;
  height: 3px;
  min-width: 0;
  margin-top: 2px;
  background: rgba(48, 220, 255, 0.08);
  border: 1px solid rgba(48, 220, 255, 0.16);
  overflow: hidden;

  b {
    position: relative;
    display: block;
    height: 100%;
    min-width: 5px;
    box-shadow: 0 0 10px rgba(48, 220, 255, 0.38);
    overflow: hidden;

    &:after {
      content: "";
      position: absolute;
      inset: 0;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.58), transparent);
      opacity: 0;
      transform: translateX(-130%);
    }
  }
}

.business-table-row.is-active .business-table-value i b:after {
  opacity: 1;
  animation: businessDataSweep 1.8s ease-in-out infinite;
}

.business-project-table {
  display: grid;
  grid-template-rows: 28px minmax(0, 1fr);
  gap: 7px;
  height: 100%;
  padding: 7px 10px 8px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-project-search {
  min-width: 0;

  input {
    width: 100%;
    height: 28px;
    padding: 0 10px;
    border: 1px solid rgba(48, 220, 255, 0.22);
    outline: none;
    color: #ffffff;
    font-size: 12px;
    background: linear-gradient(90deg, rgba(48, 220, 255, 0.12), rgba(48, 220, 255, 0.035));
    box-sizing: border-box;
  }

  input::placeholder {
    color: rgba(232, 252, 255, 0.56);
  }

  input:focus {
    border-color: rgba(36, 246, 196, 0.54);
    box-shadow: 0 0 14px rgba(36, 246, 196, 0.14);
  }

  input::-webkit-search-decoration,
  input::-webkit-search-cancel-button {
    display: none;
  }
}

.business-project-frame {
  position: relative;
  min-height: 0;
  border: 1px solid rgba(48, 220, 255, 0.16);
  background: rgba(5, 26, 39, 0.26);
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(48, 220, 255, 0.45) rgba(48, 220, 255, 0.08);

  &::-webkit-scrollbar {
    width: 5px;
  }

  &::-webkit-scrollbar-track {
    background: rgba(48, 220, 255, 0.08);
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.44);
  }

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

  thead {
    position: sticky;
    top: 0;
    z-index: 2;
    background: #0d3144;
    box-shadow: 0 1px 0 rgba(48, 220, 255, 0.2);
  }

  th,
  td {
    height: 28px;
    padding: 0 6px;
    color: rgba(246, 254, 255, 0.92);
    font-size: 11px;
    line-height: 14px;
    text-align: left;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-bottom: 1px solid rgba(48, 220, 255, 0.09);
  }

  tbody td {
    height: auto;
    min-height: 32px;
    padding-top: 3px;
    padding-bottom: 3px;
    line-height: 13px;
    white-space: normal;
    word-break: break-all;
    overflow: visible;
    text-overflow: clip;
  }

  th {
    height: 25px;
    color: rgba(190, 235, 245, 0.78);
    font-weight: 500;
    background: linear-gradient(90deg, rgba(48, 220, 255, 0.16), rgba(48, 220, 255, 0.04));
  }

  tbody tr {
    cursor: pointer;
    background: rgba(48, 220, 255, 0.025);
    transition: background 0.18s ease, box-shadow 0.18s ease;

    &:nth-child(2n) {
      background: rgba(36, 246, 196, 0.026);
    }

    &:hover,
    &:focus-visible,
    &.is-active {
      outline: none;
      background: linear-gradient(90deg, rgba(36, 246, 196, 0.18), rgba(48, 220, 255, 0.055));
      box-shadow: inset 2px 0 0 rgba(36, 246, 196, 0.82);
    }
  }

  td:nth-child(2),
  td:nth-child(4),
  th:nth-child(2),
  th:nth-child(4) {
    text-align: right;
  }

  th.is-right,
  td.is-right {
    text-align: right;
  }

  th.is-center,
  td.is-center {
    text-align: center;
  }

  strong {
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 12px;
    line-height: 14px;
    white-space: nowrap;
  }

  em {
    margin-left: 2px;
    color: rgba(238, 253, 255, 0.72);
    font-size: 10px;
    font-style: normal;
  }

  .business-project-locate {
    color: #53f98f;
    font-weight: 600;
    text-shadow: 0 0 10px rgba(83, 249, 143, 0.3);
  }

  .business-project-cell-icon {
    display: inline-flex;
    position: relative;
    width: 18px;
    height: 18px;
    align-items: center;
    justify-content: center;
    color: #53f98f;
    vertical-align: middle;
  }

  .business-project-cell-icon--locate {
    border: 1.5px solid currentColor;
    border-radius: 50%;
    background:
      linear-gradient(currentColor, currentColor) center top / 1px 3px no-repeat,
      linear-gradient(currentColor, currentColor) center bottom / 1px 3px no-repeat,
      linear-gradient(currentColor, currentColor) left center / 3px 1px no-repeat,
      linear-gradient(currentColor, currentColor) right center / 3px 1px no-repeat,
      rgba(83, 249, 143, 0.08);
    box-shadow:
      0 0 10px rgba(83, 249, 143, 0.34),
      inset 0 0 7px rgba(83, 249, 143, 0.12);

    &::before {
      position: absolute;
      inset: 4px;
      content: "";
      border: 1px solid currentColor;
      border-radius: 50%;
      opacity: 0.76;
    }

    &::after {
      position: absolute;
      width: 3px;
      height: 3px;
      content: "";
      border-radius: 50%;
      background: #ffffff;
      box-shadow: 0 0 7px rgba(255, 255, 255, 0.72);
    }
  }

  tbody tr.is-active .business-project-cell-icon--locate {
    color: #ff4054;
    background:
      linear-gradient(currentColor, currentColor) center top / 1px 3px no-repeat,
      linear-gradient(currentColor, currentColor) center bottom / 1px 3px no-repeat,
      linear-gradient(currentColor, currentColor) left center / 3px 1px no-repeat,
      linear-gradient(currentColor, currentColor) right center / 3px 1px no-repeat,
      rgba(255, 64, 84, 0.14);
    box-shadow:
      0 0 13px rgba(255, 64, 84, 0.52),
      inset 0 0 8px rgba(255, 64, 84, 0.18);
  }

  tbody tr.is-active .business-project-cell-icon--locate::after {
    background: #fff3f5;
    box-shadow: 0 0 8px rgba(255, 255, 255, 0.86);
  }
}

.business-project-col-name {
  width: 45%;
}

.business-project-col-year {
  width: 13%;
}

.business-project-col-category {
  width: 20%;
}

.business-project-col-scale {
  width: 22%;
}

.business-project-empty {
  position: absolute;
  inset: 25px 0 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.58);
  font-size: 12px;
  pointer-events: none;
}

.business-stack-columns {
  display: grid;
  grid-template-rows: 24px minmax(0, 1fr);
  gap: 5px;
  height: 100%;
  padding: 8px 12px 6px;
  box-sizing: border-box;
  overflow: hidden;

  &.is-dense {
    .business-stack-chart {
      gap: 4px;
    }

    .business-stack-track {
      width: 18px;
    }
  }

  &.is-variant-dual {
    grid-template-rows: 24px minmax(0, 1fr);
    gap: 4px;
    padding: 8px 14px 7px;

    .business-stack-legend {
      justify-content: center;
      gap: 14px;
      padding-right: 0;

      span {
        color: rgba(245, 253, 255, 0.9);
        font-size: 11px;
        line-height: 16px;
      }

      i {
        width: 8px;
        height: 8px;
        border-radius: 50%;
      }
    }

    .business-stack-chart {
      position: relative;
      grid-template-columns: repeat(auto-fit, minmax(62px, 1fr));
      align-items: stretch;
      gap: 14px;
      padding: 1px 4px 0;

      &:before {
        content: "";
        position: absolute;
        left: 4px;
        right: 4px;
        top: 25px;
        bottom: 31px;
        background:
          repeating-linear-gradient(
            to bottom,
            rgba(159, 220, 230, 0.15) 0 1px,
            transparent 1px 18px
          );
        pointer-events: none;
      }
    }

    .business-stack-item {
      position: relative;
      z-index: 1;
      grid-template-rows: 18px minmax(62px, 1fr) 27px;
      justify-items: center;
      min-width: 0;

      &.is-active {
        .business-stack-track i {
          animation: businessDataPulse 1.8s ease-in-out infinite;
        }

        span,
        strong {
          color: #ffffff;
        }
      }
    }

    .business-stack-total {
      align-self: end;
      color: rgba(245, 253, 255, 0.9);
      font-family: D-DIN, Arial, sans-serif;
      font-size: 11px;
      line-height: 16px;
      white-space: nowrap;
      text-shadow: 0 0 8px rgba(255, 255, 255, 0.22);

      em {
        margin-left: 2px;
        color: rgba(245, 253, 255, 0.68);
        font-family: "PingFang SC", Arial, sans-serif;
        font-size: 9px;
        font-style: normal;
        font-weight: 600;
      }
    }

    .business-stack-track {
      position: relative;
      align-self: end;
      width: 25px;
      height: 100%;
      min-height: 58px;
      max-height: 94px;
      overflow: visible;
      border: 1px solid rgba(48, 220, 255, 0.14);
      background:
        linear-gradient(180deg, rgba(48, 220, 255, 0.09), rgba(48, 220, 255, 0.025)),
        rgba(5, 30, 42, 0.24);
      box-shadow: inset 0 0 10px rgba(48, 220, 255, 0.05);

      &:after {
        content: "";
        position: absolute;
        left: 50%;
        bottom: -6px;
        width: 42px;
        height: 8px;
        border-radius: 50%;
        background: radial-gradient(ellipse at center, rgba(48, 220, 255, 0.34), rgba(48, 220, 255, 0) 72%);
        transform: translateX(-50%);
        pointer-events: none;
      }

      i {
        position: relative;
        display: block;
        min-height: 3px;
        box-shadow:
          0 0 14px color-mix(in srgb, currentColor 44%, transparent),
          inset 0 1px 0 rgba(255, 255, 255, 0.24);

        &:last-child:before {
          content: "";
          position: absolute;
          left: 0;
          right: 0;
          top: -5px;
          height: 8px;
          background: inherit;
          filter: brightness(1.22);
          transform: skewX(-32deg);
          transform-origin: left bottom;
        }
      }
    }

    .business-stack-item span {
      max-width: 60px;
      color: rgba(250, 254, 255, 0.82);
      font-size: 11px;
      line-height: 13px;
      white-space: nowrap;
      -webkit-line-clamp: 1;
    }
  }
}

.business-stack-legend {
  display: flex;
  justify-content: center;
  gap: 9px;
  min-width: 0;
  overflow: hidden;

  span {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    color: rgba(255, 255, 255, 0.82);
    font-size: 10px;
    line-height: 14px;
    white-space: nowrap;
  }

  i {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    box-shadow: 0 0 8px currentColor;
  }
}

.business-stack-chart {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(24px, 1fr));
  align-items: stretch;
  gap: 6px;
  min-height: 0;
}

.business-stack-item {
  display: grid;
  grid-template-rows: minmax(42px, 1fr) 36px;
  justify-items: center;
  min-width: 0;

  span {
    align-self: center;
    max-width: 100%;
    color: rgba(255, 255, 255, 0.72);
    font-size: 10px;
    line-height: 12px;
    text-align: center;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: pre-line;
    word-break: keep-all;
  }
}

.business-stack-track {
  display: flex;
  flex-direction: column-reverse;
  align-self: end;
  width: 20px;
  height: 100%;
  min-height: 48px;
  max-height: 96px;
  background: linear-gradient(180deg, rgba(48, 220, 255, 0.09), rgba(48, 220, 255, 0.02));
  border: 1px solid rgba(48, 220, 255, 0.12);
  overflow: hidden;

  i {
    display: block;
    min-height: 2px;
    box-shadow: 0 0 10px rgba(48, 220, 255, 0.34);
  }
}

.business-panel.is-column-label-standard {
  .business-columns {
    grid-template-columns: repeat(auto-fit, minmax(20px, 1fr));
    padding: 20px 12px 8px;
  }

  .business-columns.is-dense.is-scrollable {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20px, 1fr));
    align-items: stretch;
    gap: 4px;
    overflow-x: hidden;
    overflow-y: visible;
    overscroll-behavior-x: auto;
    scrollbar-width: none;

    &::-webkit-scrollbar {
      display: none;
    }

    .business-column-item {
      flex: none;
      width: auto;
      min-width: 0;
      height: auto;
    }
  }

  .business-columns:before {
    top: 36px;
    bottom: 44px;
  }

  .business-columns.is-variant-slim,
  .business-columns.is-variant-plain,
  .business-columns.is-variant-age,
  .business-columns.is-variant-compact {
    padding-top: 20px;
  }

  .business-columns.is-dense,
  .business-columns.is-variant-slim.is-dense {
    padding-top: 22px;
  }

  .business-columns.has-unit-label,
  .business-columns.has-unit-label.is-variant-plain,
  .business-columns.has-unit-label.is-variant-slim,
  .business-columns.has-unit-label.is-variant-age,
  .business-columns.has-unit-label.is-variant-townCompact,
  .business-columns.has-unit-label.is-variant-compact {
    padding-top: 34px;

    &:before {
      top: 50px;
    }
  }

  .business-column-item {
    position: relative;
    grid-template-rows: minmax(44px, 1fr) 42px;
    overflow: visible;
  }

  .business-column-item span,
  .business-stack-item span,
  .business-peak-item span {
    display: block;
    align-self: center;
    width: 18px;
    height: 42px;
    max-width: none;
    color: rgba(255, 255, 255, 0.9);
    font-size: 12px;
    font-weight: 700;
    line-height: 16px;
    letter-spacing: 0;
    text-align: center;
    writing-mode: vertical-rl;
    text-orientation: upright;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: clip;
    -webkit-line-clamp: unset;
    word-break: keep-all;
  }

  .business-column-track {
    align-self: end;
  }

  .business-column-item:after,
  .business-stack-item:after,
  .business-peak-item:after {
    content: attr(data-hover-value);
    position: absolute;
    left: 50%;
    top: 0;
    z-index: 8;
    max-width: 128px;
    padding: 4px 8px;
    border: 1px solid rgba(36, 246, 196, 0.46);
    background: rgba(3, 24, 36, 0.94);
    box-shadow: 0 0 14px rgba(36, 246, 196, 0.26);
    color: #ffffff;
    font-size: 12px;
    font-weight: 700;
    line-height: 16px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, 2px);
    transition: opacity 0.16s ease, transform 0.16s ease;
  }

  .business-column-item:hover:after,
  .business-stack-item:hover:after,
  .business-peak-item:hover:after {
    opacity: 1;
    transform: translate(-50%, 0);
  }

  .business-peaks,
  .business-peaks.is-dense {
    grid-template-columns: repeat(auto-fit, minmax(20px, 1fr));
    gap: 4px;
    padding: 34px 10px 8px;
    overflow: hidden;
  }

  .business-peak-item,
  .business-peaks.is-dense .business-peak-item {
    position: relative;
    grid-template-rows: minmax(44px, 1fr) 42px;
    min-width: 0;
    overflow: visible;
  }

  .business-peaks.is-dense .business-peak-item span {
    width: 18px;
    height: 42px;
    max-height: none;
    line-height: 16px;
    writing-mode: vertical-rl;
    text-orientation: upright;
    white-space: nowrap;
  }

  .business-peak-stage {
    align-self: end;
    min-height: 42px;
  }

  .business-peaks.is-dense .business-peak-stage {
    min-height: 42px;
  }

  .business-line {
    grid-template-rows: minmax(0, 1fr) 42px;
  }

  .business-line-labels {
    align-items: start;
  }

  .business-line-labels span {
    display: block;
    justify-self: center;
    width: 18px;
    height: 42px;
    color: rgba(255, 255, 255, 0.9);
    font-size: 12px;
    font-weight: 700;
    line-height: 16px;
    letter-spacing: 0;
    text-align: center;
    writing-mode: vertical-rl;
    text-orientation: upright;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: clip;
    word-break: keep-all;
  }

  .business-stack-columns {
    grid-template-rows: 22px minmax(0, 1fr);
    padding-bottom: 7px;
  }

  .business-stack-item {
    position: relative;
    grid-template-rows: minmax(44px, 1fr) 42px;
    overflow: visible;
  }
}

.business-peaks {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: stretch;
  gap: 8px;
  height: 100%;
  padding: 8px 15px 7px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-peak-unit {
  right: 15px;
}

.business-peaks.is-dense {
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 4px;
  padding: 8px 8px 7px;
}

.business-peak-item {
  display: grid;
  grid-template-rows: 18px minmax(0, 1fr) 22px;
  justify-items: center;
  min-width: 0;

  strong {
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 12px;
    line-height: 16px;
    text-shadow: 0 0 12px rgba(48, 220, 255, 0.45);
    white-space: nowrap;

    em {
      margin-left: 2px;
      color: rgba(238, 253, 255, 0.72);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 9px;
      font-style: normal;
      font-weight: 600;
    }
  }

  span {
    align-self: center;
    max-width: 100%;
    color: rgba(255, 255, 255, 0.68);
    font-size: 10px;
    line-height: 12px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

.business-peaks.is-dense .business-peak-item {
  grid-template-rows: 17px minmax(0, 1fr) 24px;
}

.business-peaks.is-dense .business-peak-item strong {
  font-size: 11px;
  line-height: 15px;
  transform: scale(0.92);
  transform-origin: center top;
}

.business-peaks.is-dense .business-peak-item span {
  line-height: 11px;
  white-space: pre-line;
  writing-mode: horizontal-tb;
  max-height: 24px;
}

.business-peak-stage {
  position: relative;
  width: 100%;
  min-height: 62px;
  align-self: stretch;

  &:before {
    content: "";
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(48, 220, 255, 0.6), transparent);
  }

  i {
    position: absolute;
    left: 50%;
    bottom: 0;
    width: 34px;
    height: var(--peak-height);
    min-height: 20px;
    max-height: 100%;
    transform: translateX(-50%);
    background:
      radial-gradient(ellipse at 50% 100%, var(--peak-color) 0, rgba(36, 246, 196, 0.26) 22%, rgba(36, 246, 196, 0) 62%),
      linear-gradient(180deg, var(--peak-color), rgba(36, 246, 196, 0.04));
    clip-path: polygon(50% 0, 68% 32%, 78% 100%, 22% 100%, 32% 32%);
    filter: drop-shadow(0 0 9px rgba(48, 220, 255, 0.42));

    &:after {
      content: "";
      position: absolute;
      left: 50%;
      top: 0;
      width: 5px;
      height: 5px;
      border-radius: 50%;
      background: #ffffff;
      box-shadow: 0 0 9px var(--peak-color);
      transform: translateX(-50%);
    }
  }
}

.business-peaks.is-dense .business-peak-stage {
  min-height: 58px;

  &:before {
    left: 4px;
    right: 4px;
  }

  i {
    width: 24px;
  }
}

.business-line {
  display: grid;
  grid-template-rows: minmax(0, 1fr) 31px;
  gap: 2px;
  height: 100%;
  padding: 6px 10px 6px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-line-chart {
  position: relative;
  min-height: 0;
  background: linear-gradient(180deg, rgba(48, 220, 255, 0.08), rgba(48, 220, 255, 0.02));
  border: 1px solid rgba(48, 220, 255, 0.1);
  overflow: visible;

  svg {
    width: 100%;
    height: 100%;
  }
}

.business-line-grid {
  stroke: rgba(255, 255, 255, 0.1);
  stroke-width: 1;
}

.business-line-area {
  fill: rgba(36, 246, 196, 0.13);
  stroke: none;
}

.business-line-stroke {
  fill: none;
  stroke: #24f6c4;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 10 8;
  animation: businessLineFlow 2.2s linear infinite;
}

.business-line-dot {
  fill: #fff;
  stroke: #24f6c4;
  stroke-width: 2;
  animation: businessDotPulse 2.2s ease-in-out infinite;
  transition: r 0.28s ease, fill 0.28s ease, stroke 0.28s ease, stroke-width 0.28s ease, filter 0.28s ease;
  transform-box: fill-box;
  transform-origin: center;

  &.is-active {
    r: 5.6;
    fill: #fff6aa;
    stroke: #ffffff;
    stroke-width: 2.8;
    filter:
      drop-shadow(0 0 4px rgba(255, 246, 170, 0.95))
      drop-shadow(0 0 10px rgba(36, 246, 196, 0.78));
    animation: businessActiveDotPulse 1.35s ease-in-out infinite;
  }
}

.business-line-hit {
  fill: transparent;
  stroke: transparent;
  cursor: pointer;
  pointer-events: all;
}

.business-line-hover-zones {
  position: absolute;
  inset: 0;
  display: grid;
  z-index: 1;

  i {
    display: block;
    min-width: 0;
    cursor: pointer;
  }
}

.business-line-tooltip {
  position: absolute;
  z-index: 3;
  min-width: 86px;
  padding: 5px 8px;
  border: 1px solid rgba(48, 220, 255, 0.34);
  background: rgba(3, 18, 30, 0.9);
  box-shadow: 0 0 14px rgba(48, 220, 255, 0.22);
  transform: translate(-50%, calc(-100% - 8px));
  pointer-events: none;
  transition: left 0.28s ease, top 0.28s ease, transform 0.28s ease;

  span {
    display: block;
    color: rgba(220, 248, 255, 0.78);
    font-size: 10px;
    line-height: 12px;
    white-space: nowrap;
  }

  strong {
    display: block;
    margin-top: 2px;
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 16px;
    line-height: 18px;

    em {
      margin-left: 3px;
      color: rgba(255, 255, 255, 0.62);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }
}

.business-line-labels {
  display: grid;
  gap: 2px;
  min-width: 0;
  align-items: start;
  min-height: 0;
  overflow: hidden;

  span {
    min-width: 0;
    color: rgba(255, 255, 255, 0.62);
    font-size: 10px;
    line-height: 12px;
    text-align: center;
    overflow: visible;
    text-overflow: clip;
    white-space: pre-line;
    writing-mode: horizontal-tb;
    justify-self: center;
    max-height: none;
  }
}

.business-heat {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 7px;
  height: 100%;
  padding: 8px 14px 9px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-heat.is-dense {
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
  padding: 8px 10px 9px;

  .business-heat-cell {
    grid-template-rows: 12px 16px 22px;
    gap: 2px;
    padding: 6px 4px 5px;
  }

  .business-heat-cell strong {
    font-size: 14px;
    line-height: 16px;
  }
}

.business-heat-cell {
  position: relative;
  display: grid;
  grid-template-rows: 12px 16px minmax(20px, auto);
  align-items: center;
  align-content: center;
  justify-items: center;
  gap: 3px;
  min-width: 0;
  min-height: 0;
  padding: 6px 5px 5px;
  border: 1px solid rgba(48, 220, 255, 0.12);
  background:
    radial-gradient(circle at 50% 45%, var(--heat-bg), rgba(48, 220, 255, 0.02) 68%),
    linear-gradient(180deg, rgba(48, 220, 255, 0.06), rgba(48, 220, 255, 0.02));
  box-shadow: inset 0 0 16px rgba(48, 220, 255, 0.08);
  overflow: hidden;

  i {
    width: 8px;
    height: 8px;
    border: 2px solid var(--heat-color);
    border-radius: 50%;
    box-shadow: 0 0 10px var(--heat-color);
  }

  span {
    max-width: 100%;
    color: rgba(226, 249, 255, 0.78);
    font-size: 10px;
    line-height: 11px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    word-break: break-all;
  }

  strong {
    max-width: 100%;
    color: #ffffff;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 15px;
    line-height: 17px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    em {
      margin-left: 2px;
      color: rgba(255, 255, 255, 0.54);
      font-family: "PingFang SC", Arial, sans-serif;
      font-size: 10px;
      font-style: normal;
      font-weight: 500;
    }
  }
}

.business-split {
  display: grid;
  grid-template-rows: 42px minmax(0, 1fr);
  gap: 10px;
  height: 100%;
  padding: 13px 16px;
  box-sizing: border-box;
  overflow: hidden;

  &.is-dense {
    grid-template-rows: 22px minmax(0, 1fr);
    gap: 6px;
    padding: 8px 12px;

    .business-split-band {
      height: auto;
    }

    .business-split-list {
      height: auto;
      gap: 3px;
    }

    .business-split-row {
      min-height: 20px;
      padding: 0 6px;

      span {
        font-size: 11px;
      }

      strong {
        font-size: 12px;
      }
    }
  }
}

.business-split-band {
  display: flex;
  height: auto;
  padding: 3px;
  background: rgba(48, 220, 255, 0.08);
  border: 1px solid rgba(48, 220, 255, 0.16);

  i {
    display: block;
    min-width: 8px;
    height: 100%;
  }
}

.business-split-list {
  display: grid;
  grid-auto-rows: minmax(26px, 1fr);
  gap: 6px;
  min-height: 0;
  height: auto;
  overflow-y: auto;
  padding-right: 3px;

  &::-webkit-scrollbar {
    width: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: rgba(48, 220, 255, 0.28);
  }
}

.business-split-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  min-height: 26px;
  padding: 0 9px;
  background: rgba(48, 220, 255, 0.04);
  border: 1px solid rgba(48, 220, 255, 0.08);

  span {
    display: flex;
    align-items: center;
    min-width: 0;
    color: rgba(255, 255, 255, 0.72);
    font-size: 12px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    i {
      flex: 0 0 auto;
      width: 8px;
      height: 8px;
      margin-right: 7px;
    }
  }
}

.business-panel {
  color: #f4feff;
}

.business-panel-empty {
  color: rgba(224, 250, 255, 0.82);
}

.business-metric-item,
.business-icon-metric-item,
.business-spotlight-main,
.business-spotlight-chip,
.business-structure-focus,
.business-structure-row,
.business-line-chart,
.business-heat-cell,
.business-split-row {
  border-color: rgba(60, 225, 255, 0.2);
  background-color: rgba(6, 30, 45, 0.38);
  box-shadow: inset 0 0 0 1px rgba(48, 220, 255, 0.04);
}

.business-metric-item span,
.business-icon-metric-copy span,
.business-spotlight-main span,
.business-spotlight-chip span,
.business-donut-row span,
.business-structure-focus span,
.business-structure-row span,
.business-bar-name,
.business-column-item span,
.business-peak-item span,
.business-line-labels span,
.business-heat-cell span,
.business-split-row span {
  color: rgba(236, 252, 255, 0.92);
}

.business-icon-metric-copy strong,
.business-spotlight-main strong,
.business-donut-row strong,
.business-structure-focus strong,
.business-structure-row strong,
.business-column-item strong,
.business-peak-item strong,
.business-heat-cell strong {
  color: #ffffff;
  text-shadow: 0 0 4px rgba(48, 220, 255, 0.28);
}

.business-metric-item strong,
.business-spotlight-chip strong,
.business-bar-row strong,
.business-split-row strong,
.business-structure-focus em {
  color: #38f8ff;
  text-shadow: 0 0 4px rgba(48, 220, 255, 0.32);
}

.business-metric-item em,
.business-icon-metric-copy strong em,
.business-spotlight-main strong em,
.business-spotlight-chip strong em,
.business-donut-row em,
.business-structure-row strong em,
.business-bar-row strong em,
.business-bar-row strong small,
.business-heat-cell strong em {
  color: rgba(238, 253, 255, 0.72);
}

.business-spotlight-main small,
.business-spotlight-chip small,
.business-structure-focus small,
.business-structure-row small {
  color: rgba(255, 229, 117, 0.96);
}

.business-bar-track,
.business-column-track,
.business-split-band {
  border-color: rgba(72, 228, 255, 0.26);
  background: rgba(60, 225, 255, 0.12);
  box-shadow: inset 0 0 0 1px rgba(48, 220, 255, 0.05);
}

.business-bar-track i,
.business-column-track i,
.business-split-band i {
  box-shadow: 0 0 6px rgba(48, 220, 255, 0.34);
}

.business-bars.is-capacity {
  .business-bar-name {
    color: rgba(236, 252, 255, 0.92);
  }

  .business-bar-row strong {
    color: #24f6c4;
    text-shadow: 0 0 4px rgba(36, 246, 196, 0.3);
  }
}

.business-line-grid {
  stroke: rgba(213, 247, 255, 0.2);
}

.business-line-area {
  fill: rgba(36, 246, 196, 0.18);
}

.business-line-stroke {
  filter: drop-shadow(0 0 2px rgba(36, 246, 196, 0.42));
}

.business-line-dot {
  filter: drop-shadow(0 0 2px rgba(48, 220, 255, 0.46));

  &.is-active {
    filter:
      drop-shadow(0 0 4px rgba(255, 246, 170, 0.95))
      drop-shadow(0 0 10px rgba(36, 246, 196, 0.78));
  }
}

.business-panel,
.business-panel span,
.business-panel strong,
.business-panel em,
.business-panel small {
  color: #ffffff;
  text-shadow: none;
}

.business-panel .business-bar-name,
.business-panel .business-donut-row span,
.business-panel .business-structure-row span,
.business-panel .business-column-item span,
.business-panel .business-peak-item span,
.business-panel .business-line-labels span,
.business-panel .business-heat-cell span,
.business-panel .business-split-row span,
.business-panel .business-icon-metric-copy span,
.business-panel .business-spotlight-chip span {
  color: #ffffff;
}

.business-panel .business-bar-row strong,
.business-panel .business-split-row strong,
.business-panel .business-metric-item strong,
.business-panel .business-spotlight-chip strong,
.business-panel .business-structure-focus em {
  color: #ffffff;
}

.business-panel .business-bar-name,
.business-panel .business-bar-row strong,
.business-panel .business-bar-row strong em,
.business-panel .business-bar-row strong small,
.business-panel .business-column-unit,
.business-panel .business-donut-row span,
.business-panel .business-donut-row strong,
.business-panel .business-donut-row em,
.business-panel .business-icon-metric-copy span,
.business-panel .business-icon-metric-copy strong,
.business-panel .business-icon-metric-copy strong em,
.business-panel .business-line-labels span,
.business-panel .business-metric-item span,
.business-panel .business-metric-item strong,
.business-panel .business-metric-item em,
.business-panel .business-spotlight-main span,
.business-panel .business-spotlight-main strong,
.business-panel .business-spotlight-main strong em,
.business-panel .business-spotlight-main small,
.business-panel .business-spotlight-chip span,
.business-panel .business-spotlight-chip strong,
.business-panel .business-spotlight-chip strong em,
.business-panel .business-spotlight-chip small,
.business-panel .business-structure-focus span,
.business-panel .business-structure-focus strong,
.business-panel .business-structure-focus em,
.business-panel .business-structure-focus small,
.business-panel .business-structure-row span,
.business-panel .business-structure-row strong,
.business-panel .business-structure-row strong em,
.business-panel .business-structure-row small,
.business-panel .business-column-item span,
.business-panel .business-column-item strong,
.business-panel .business-peak-item span,
.business-panel .business-peak-item strong,
.business-panel .business-heat-cell span,
.business-panel .business-heat-cell strong,
.business-panel .business-heat-cell strong em,
.business-panel .business-split-row span,
.business-panel .business-split-row strong {
  color: #ffffff !important;
  text-shadow: none !important;
}

.business-panel .business-column-unit {
  color: rgba(238, 253, 255, 0.72) !important;
}

.business-balance-gauge-grid {
  display: grid;
  height: 100%;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  padding: 8px 12px 10px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-balance-gauge-grid.is-single {
  grid-template-columns: minmax(0, 1fr);
  padding: 12px 16px 14px;

  .business-balance-gauge-card {
    width: min(230px, 100%);
    justify-self: center;
    grid-template-rows: 30px minmax(92px, 1fr) 24px;
    padding: 10px 16px 12px;
  }

  .business-balance-gauge-ring {
    width: min(122px, 56%);
  }

  .business-balance-gauge-value strong {
    font-size: 26px;
    line-height: 30px;
  }

  .business-balance-gauge-name {
    font-size: 16px;
  }

  .business-balance-gauge-extra {
    display: none;
  }
}

.business-balance-gauge-card {
  position: relative;
  display: grid;
  min-width: 0;
  min-height: 0;
  grid-template-rows: 30px minmax(70px, 1fr) 22px 16px;
  justify-items: center;
  padding: 9px 7px 8px;
  overflow: hidden;
  border: 1px solid rgba(48, 220, 255, 0.18);
  background:
    radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--balance-color) 14%, transparent), transparent 55%),
    linear-gradient(180deg, rgba(48, 220, 255, 0.075), rgba(5, 27, 40, 0.46));
  box-shadow:
    inset 0 0 18px rgba(48, 220, 255, 0.07),
    0 0 0 rgba(48, 220, 255, 0);
  transition:
    border-color 0.35s ease,
    box-shadow 0.35s ease,
    background 0.35s ease;

  &::before {
    position: absolute;
    inset: 8px;
    content: "";
    border: 1px solid rgba(255, 255, 255, 0.035);
    pointer-events: none;
  }

  &.is-active {
    border-color: color-mix(in srgb, var(--balance-color) 64%, rgba(48, 220, 255, 0.22));
    background:
      radial-gradient(circle at 50% 46%, color-mix(in srgb, var(--balance-color) 20%, transparent), transparent 58%),
      linear-gradient(180deg, rgba(48, 220, 255, 0.095), rgba(5, 27, 40, 0.52));
    box-shadow:
      inset 0 0 22px rgba(48, 220, 255, 0.09),
      0 0 14px color-mix(in srgb, var(--balance-color) 16%, transparent);
  }
}

.business-balance-gauge-head {
  position: relative;
  z-index: 1;
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: center;

  strong {
    width: 100%;
    overflow: hidden;
    color: var(--balance-color);
    font-size: 11px;
    font-weight: 900;
    text-align: center;
    text-overflow: ellipsis;
    text-shadow: 0 0 8px color-mix(in srgb, var(--balance-color) 34%, transparent);
    white-space: nowrap;
  }
}

.business-balance-gauge-ring {
  position: relative;
  z-index: 1;
  align-self: center;
  width: min(92px, 82%);
  aspect-ratio: 1;
  border-radius: 50%;
  background:
    conic-gradient(from 218deg, var(--balance-color) 0 var(--balance-progress), rgba(93, 175, 199, 0.18) var(--balance-progress) 100%),
    rgba(3, 23, 35, 0.78);
  box-shadow:
    0 0 18px color-mix(in srgb, var(--balance-color) 22%, transparent),
    inset 0 0 18px rgba(0, 0, 0, 0.42);

  &::before {
    position: absolute;
    inset: 12px;
    content: "";
    border-radius: 50%;
    background:
      radial-gradient(circle at 50% 45%, rgba(48, 220, 255, 0.12), rgba(3, 23, 35, 0.98) 62%),
      rgba(3, 23, 35, 0.96);
    box-shadow:
      inset 0 0 12px rgba(0, 0, 0, 0.42),
      inset 0 0 0 1px rgba(48, 220, 255, 0.08);
  }

  &::after {
    position: absolute;
    left: 50%;
    bottom: 9px;
    width: 2px;
    height: 16px;
    content: "";
    background: rgba(0, 10, 18, 0.8);
    transform: translateX(-50%) rotate(35deg);
    transform-origin: 50% 100%;
    box-shadow: 0 0 5px rgba(0, 10, 18, 0.58);
  }
}

.business-balance-gauge-value {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;

  strong {
    color: #ffffff !important;
    font-family: D-DIN, Arial, sans-serif;
    font-size: 22px;
    line-height: 26px;
    font-weight: 900;
    text-shadow: 0 0 10px color-mix(in srgb, var(--balance-color) 42%, transparent) !important;
  }

  em {
    margin-left: 2px;
    color: rgba(238, 253, 255, 0.76) !important;
    font-size: 11px;
    font-style: normal;
    font-weight: 800;
  }
}

.business-balance-gauge-name,
.business-balance-gauge-extra {
  position: relative;
  z-index: 1;
  max-width: 100%;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.business-balance-gauge-name {
  color: #ffffff !important;
  font-size: 15px;
  line-height: 21px;
  font-weight: 900;
  text-shadow: 0 0 8px rgba(48, 220, 255, 0.18) !important;
}

.business-balance-gauge-extra {
  color: rgba(238, 253, 255, 0.66) !important;
  font-size: 11px;
  line-height: 16px;
  font-weight: 700;
}

.business-gauges {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  height: 100%;
  padding: 9px 12px 8px;
  box-sizing: border-box;
  overflow: hidden;
}

.business-gauges.is-dense {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  gap: 7px;
  padding: 8px 12px;
}

.business-gauge-item {
  position: relative;
  display: grid;
  grid-template-rows: minmax(0, 1fr) 17px 14px;
  align-items: center;
  justify-items: center;
  min-width: 0;
  min-height: 0;
  padding: 6px 4px 5px;
  border: 1px solid rgba(48, 220, 255, 0.17);
  background:
    radial-gradient(circle at 50% 58%, rgba(48, 220, 255, 0.15), rgba(48, 220, 255, 0.02) 64%),
    linear-gradient(180deg, rgba(48, 220, 255, 0.09), rgba(5, 26, 39, 0.34));
  box-shadow: inset 0 0 18px rgba(48, 220, 255, 0.08);
  overflow: hidden;

  &:before {
    content: "";
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 31px;
    height: 18px;
    border-radius: 50%;
    background: radial-gradient(ellipse at center, color-mix(in srgb, var(--gauge-color) 48%, transparent), rgba(48, 220, 255, 0));
    filter: blur(2px);
    opacity: 0.58;
    pointer-events: none;
  }

  &.is-active {
    border-color: color-mix(in srgb, var(--gauge-color) 58%, rgba(48, 220, 255, 0.22));
    box-shadow:
      inset 0 0 20px rgba(48, 220, 255, 0.1),
      0 0 10px color-mix(in srgb, var(--gauge-color) 26%, transparent);
  }

  &.is-alert {
    background:
      radial-gradient(circle at 50% 58%, rgba(255, 191, 90, 0.17), rgba(48, 220, 255, 0.02) 66%),
      linear-gradient(180deg, rgba(48, 220, 255, 0.08), rgba(5, 26, 39, 0.34));
  }

  &.is-safe {
    background:
      radial-gradient(circle at 50% 58%, rgba(36, 246, 196, 0.15), rgba(48, 220, 255, 0.02) 66%),
      linear-gradient(180deg, rgba(48, 220, 255, 0.08), rgba(5, 26, 39, 0.34));
  }

  &.is-low-rate {
    &:before {
      opacity: 0.34;
    }

    .business-gauge-progress {
      stroke-width: 6;
      stroke-linecap: butt;
      filter: drop-shadow(0 0 4px color-mix(in srgb, var(--gauge-color) 66%, transparent));
    }

    .business-gauge-needle {
      width: 18px;
      height: 3px;
      opacity: 0.86;
    }

    .business-gauge-pivot {
      width: 7px;
      height: 7px;
    }
  }
}

.business-gauge-visual {
  position: relative;
  align-self: end;
  width: 100%;
  max-width: 116px;
  height: 82px;
  min-width: 0;
}

.business-gauge-visual svg {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 72px;
  overflow: visible;
}

.business-gauge-track,
.business-gauge-progress,
.business-gauge-glow {
  fill: none;
  stroke-linecap: round;
}

.business-gauge-track {
  stroke: rgba(170, 238, 255, 0.17);
  stroke-width: 10;
}

.business-gauge-progress {
  stroke: var(--gauge-color);
  stroke-width: 10;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--gauge-color) 72%, transparent));
}

.business-gauge-glow {
  stroke: rgba(48, 220, 255, 0.16);
  stroke-width: 1.5;
  stroke-dasharray: 3 6;
}

.business-gauge-needle {
  position: absolute;
  left: 50%;
  top: 64px;
  width: 42px;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, #ffffff 0%, var(--gauge-color) 76%, rgba(255, 255, 255, 0));
  box-shadow: 0 0 7px color-mix(in srgb, var(--gauge-color) 72%, transparent);
  transform: rotate(var(--needle-rotate));
  transform-origin: 2px 50%;
}

.business-gauge-pivot {
  position: absolute;
  left: 50%;
  top: 64px;
  width: 9px;
  height: 9px;
  border: 2px solid rgba(255, 255, 255, 0.88);
  border-radius: 50%;
  background: var(--gauge-color);
  box-shadow: 0 0 8px color-mix(in srgb, var(--gauge-color) 72%, transparent);
  transform: translate(-50%, -50%);
}

.business-gauge-value {
  position: absolute;
  left: 0;
  right: 0;
  top: 28px;
  text-align: center;
  pointer-events: none;
}

.business-gauge-value strong {
  display: block;
  color: #ffffff !important;
  font-family: D-DIN, Arial, sans-serif;
  font-size: 18px;
  line-height: 19px;
  font-weight: 800;
  text-shadow: 0 0 8px rgba(48, 220, 255, 0.42) !important;
  white-space: nowrap;
}

.business-gauge-value strong em {
  margin-left: 2px;
  color: rgba(238, 253, 255, 0.76) !important;
  font-family: "PingFang SC", Arial, sans-serif;
  font-size: 10px;
  font-style: normal;
  font-weight: 500;
}

.business-gauge-value small {
  display: block;
  margin-top: 2px;
  color: var(--gauge-color) !important;
  font-size: 10px;
  line-height: 12px;
  white-space: nowrap;
}

.business-gauge-name,
.business-gauge-extra {
  position: relative;
  z-index: 1;
  display: block;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.business-gauge-name {
  color: #ffffff !important;
  font-size: 12px;
  line-height: 16px;
  font-weight: 700;
}

.business-gauge-extra {
  color: rgba(238, 253, 255, 0.68) !important;
  font-size: 10px;
  line-height: 13px;
}
</style>
