# KPI Card Templates / KPI卡片模板

> Extracted from SKILL.md v2.1.0 — reference for cockpit KPI card HTML, CSS, and mode-switching patterns.

---

## Zone 2: KPI Section HTML Template

```html
<!-- Zone 2: KPI Section -->
<!-- Component ID: KPI-CARD-GRID-01 -->
<section class="kpi-section" aria-label="关键指标概览">
  <div class="kpi-grid">
    <!-- IDX-001: 累计投资规模 -->
    <div class="kpi-card" data-indicator="IDX-001" role="button" tabindex="0">
      <div class="kpi-icon">📊</div>
      <div class="kpi-name">累计投资规模</div>
      <div class="kpi-value">125.8亿</div>
      <div class="kpi-change positive">+12.3%</div>
      <div class="kpi-aux">较去年同期</div>
      <a class="kpi-detail-btn" href="detail.html?indicator=IDX-001&amp;company=all&amp;year=2026">详情→</a>
    </div>

    <!-- IDX-002: 投资项目数 -->
    <div class="kpi-card" data-indicator="IDX-002" role="button" tabindex="0">
      <div class="kpi-icon">📁</div>
      <div class="kpi-name">投资项目数</div>
      <div class="kpi-value">156个</div>
      <div class="kpi-change positive">+8</div>
      <div class="kpi-aux">较上月新增</div>
      <a class="kpi-detail-btn" href="detail.html?indicator=IDX-002&amp;company=all&amp;year=2026">详情→</a>
    </div>

    <!-- IDX-008: 在管资产规模 -->
    <div class="kpi-card" data-indicator="IDX-008" role="button" tabindex="0">
      <div class="kpi-icon">💼</div>
      <div class="kpi-name">在管资产规模</div>
      <div class="kpi-value">89.2亿</div>
      <div class="kpi-change negative">-2.1%</div>
      <div class="kpi-aux">较上月</div>
      <a class="kpi-detail-btn" href="detail.html?indicator=IDX-008&amp;company=all&amp;year=2026">详情→</a>
    </div>

    <!-- IDX-003: 累计退出金额 -->
    <div class="kpi-card" data-indicator="IDX-003" role="button" tabindex="0">
      <div class="kpi-icon">✅</div>
      <div class="kpi-name">累计退出金额</div>
      <div class="kpi-value">32.5亿</div>
      <div class="kpi-change positive">+5.8%</div>
      <div class="kpi-aux">较去年同期</div>
      <a class="kpi-detail-btn" href="detail.html?indicator=IDX-003&amp;company=all&amp;year=2026">详情→</a>
    </div>
  </div>
</section>
```

## KPI Card Specifications

| Requirement | Spec |
|-------------|------|
| Card count | 5 (IDX-001 ~ IDX-005) |
| Layout | CSS Grid, gap 20px |
| Card structure | icon(24px) + name(18px #374151) + value(32px Bold #111827) + change(16px 正#059669/负#DC2626) + aux(14px #6B7280) + button |
| Visual style | border-radius 12px, box-shadow 0 2px 8px rgba(0,0,0,0.08), padding 24px |
| Grid breakpoints | XL ≥1200px = 5 cols, 768-1199px = 4 cols, 576-767px = 2 cols, <576px = 1 col |
| Interaction | Click card or "详情→" → navigate to standalone `detail.html` |

## KPI Card CSS

```css
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;
}

.kpi-card {
  background: var(--bg-card);
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  position: relative;
  cursor: pointer;
  transition: box-shadow 0.2s, opacity 0.5s ease;
}

.kpi-card:hover {
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
}

.kpi-icon { width: 24px; height: 24px; margin-bottom: 8px; }
.kpi-name { font-size: 18px; color: #374151; margin-bottom: 8px; }
.kpi-value { font-size: 32px; font-weight: 700; color: #111827; margin-bottom: 4px; }
.kpi-change.positive { color: #059669; font-size: 16px; }
.kpi-change.negative { color: #DC2626; font-size: 16px; }
.kpi-aux { font-size: 14px; color: #6B7280; }

.kpi-detail-btn {
  position: absolute;
  right: 12px;
  bottom: 12px;
  font-size: 14px;
  color: var(--primary-blue);
  background: none;
  border: none;
  cursor: pointer;
  text-decoration: none;
}

/* Responsive */
@media (max-width: 1199px) { .kpi-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 767px)  { .kpi-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 575px)  { .kpi-grid { grid-template-columns: 1fr; } }
```

---

## V12 Pattern 1: KPI Card 3-Mode System

KPI cards support three visual modes (fold/detail/drawer) via CSS container classes and a global JS switch. Each `.kpi-card` contains three internal containers, only one visible at a time.

**CSS pattern:**
```css
.kpi-card .kpi-mode-fold,
.kpi-card .kpi-mode-detail,
.kpi-card .kpi-mode-drawer { display: none; }

.kpi-card.kpi-card-fold .kpi-mode-fold     { display: block; }
.kpi-card.kpi-card-detail .kpi-mode-detail { display: block; }
.kpi-card.kpi-card-drawer .kpi-mode-drawer { display: block; }
```

**JS mode switcher:**
```javascript
function setCardStyle(mode) {
  // mode: 'fold' | 'detail' | 'drawer'
  document.querySelectorAll('.kpi-card').forEach(function(card) {
    card.classList.remove('kpi-card-fold', 'kpi-card-detail', 'kpi-card-drawer');
    card.classList.add('kpi-card-' + mode);
  });
}
```

- **Fold mode**: compact card with icon + name + value only
- **Detail mode**: expanded with trend arrow, aux text, and detail link
- **Drawer mode**: minimal card rendered inside the slide-in drawer panel

---

## V12 Pattern 3: Mini-Card Grid Pattern

Compact info cards rendered in a responsive auto-fit grid, typically used in drawer panels and detail sections.

**CSS:**
```css
.mini-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 12px;
}

.mini-card {
  background: #FFFFFF;
  border: 1px solid #E5E7EB;
  border-radius: 8px;
  padding: 12px 16px;
  transition: box-shadow 0.2s ease;
}

.mini-card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); }
.mini-card .mini-card-label { font-size: 12px; color: #6B7280; margin-bottom: 4px; }
.mini-card .mini-card-value { font-size: 18px; font-weight: 700; color: #111827; }
```

**HTML structure:**
```html
<div class="mini-card-grid">
  <div class="mini-card">
    <div class="mini-card-label">储备项目</div>
    <div class="mini-card-value">23</div>
  </div>
  <!-- more cards ... -->
</div>
```

---

## V12 Pattern 7: CSS Arrow Replacing Emoji

Replace emoji fold/unfold triggers with a pure CSS arrow that rotates on state change.

**CSS:**
```css
.fold-trigger { position: relative; cursor: pointer; user-select: none; }

.fold-trigger::after {
  content: '›';
  display: inline-block;
  font-size: 20px;
  font-weight: 700;
  color: #6B7280;
  transition: transform 0.2s ease;
  transform: rotate(0deg);
  margin-left: 6px;
}

.fold-trigger.expanded::after { transform: rotate(90deg); }
```

**JS toggle:**
```javascript
function toggleFold(triggerEl, targetEl) {
  var isExpanded = triggerEl.classList.toggle('expanded');
  targetEl.style.display = isExpanded ? 'block' : 'none';
}
```

---

## V12 Pattern 8: Drawer Optimization

Drawer/slide-in panel: 520px width, rounded left corners, `pointer-events: auto` on overlay for reliable mask-click-to-close.

**CSS:**
```css
.drawer-overlay {
  position: fixed; top: 0; left: 0; width: 100%; height: 100%;
  background: rgba(0, 0, 0, 0.45); z-index: 200;
  display: none; pointer-events: auto;
}
.drawer-overlay.active { display: block; }

.drawer-panel {
  position: fixed; top: 0; right: 0; width: 520px; height: 100%;
  background: #F8FAFC; box-shadow: -4px 0 20px rgba(0, 0, 0, 0.15);
  z-index: 201; overflow-y: auto;
  border-radius: 12px 0 0 12px;
  transform: translateX(0); transition: transform 0.3s ease;
}
.drawer-panel.hidden { transform: translateX(100%); }
.drawer-body { padding: 24px; }
.drawer-body .mini-card-grid { margin-bottom: 20px; }
```

**JS show/hide:**
```javascript
function openDrawer() {
  document.getElementById('drawer-overlay').classList.add('active');
  document.getElementById('drawer-panel').classList.remove('hidden');
}
function closeDrawer() {
  document.getElementById('drawer-overlay').classList.remove('active');
  document.getElementById('drawer-panel').classList.add('hidden');
}
document.getElementById('drawer-overlay').addEventListener('click', closeDrawer);
```
