# Card Components - Design System

Two interactive card components with ripple hover effects.

---

## Overview

| Component | Size | Use Case |
|-----------|------|----------|
| Strategy Card | 190x254px | Primary card with metadata |
| Template Card | 190x190px | Secondary/compact card |

**Shared Features:**
- Space Grotesk font
- Grid background pattern
- Interactive ripple hover effect (Orange → Pink → Blue)
- 8px content inset with white overlay

---

## Strategy Card

### Preview
- Corner + icons on all 4 corners
- Title, description with eye icon
- Created by / Last updated metadata
- Edit, Copy, Delete action buttons

### Specs

| Property | Value |
|----------|-------|
| Width | 190px |
| Height | 254px |
| Border Radius | 12px (outer), 8px (inner) |
| Font | Space Grotesk |
| Shadow | 0 4px 20px rgba(0,0,0,0.08) |

### Positions

| Element | X | Y |
|---------|---|---|
| Strategy Name | 18px | 82px |
| Description | 18px | 111px |
| Eye icon | - | 115px |
| Created by | 18px | 154px |
| Last Updated | 18px | 166px |
| Edit icon | 18px | 202px |
| Copy icon | 41px | 202px |
| Delete icon | 64px | 202px |

### HTML

```html
<div class="card-container">
  <!-- Corner decorations -->
  <div class="corner-icon top-left">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M12 5v14M5 12h14"/>
    </svg>
  </div>
  <div class="corner-icon top-right">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M12 5v14M5 12h14"/>
    </svg>
  </div>
  <div class="corner-icon bottom-left">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M12 5v14M5 12h14"/>
    </svg>
  </div>
  <div class="corner-icon bottom-right">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M12 5v14M5 12h14"/>
    </svg>
  </div>

  <div class="strategy-card" id="strategyCard">
    <div class="ripple-grid" id="strategyRippleGrid"></div>

    <div class="card-content">
      <div class="content-inner">
        <div class="grid-bg"></div>
      </div>
      <h1 class="card-title">Strategy Name</h1>
      <p class="card-description">
        An app for strategy idea...
        <svg class="eye-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
          <circle cx="12" cy="12" r="3"/>
        </svg>
      </p>
      <p class="card-meta created">Created by: <span>Username, Date</span></p>
      <p class="card-meta updated">Last Updated: <span>Date, Time</span></p>
      <button class="action-btn edit" title="Edit">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
          <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
        </svg>
      </button>
      <button class="action-btn copy" title="Copy">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
          <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
        </svg>
      </button>
      <button class="action-btn delete" title="Delete">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <polyline points="3 6 5 6 21 6"/>
          <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
        </svg>
      </button>
    </div>
  </div>
</div>
```

### CSS

```css
.card-container {
  position: relative;
  width: 190px;
  height: 254px;
}

/* Corner icons */
.corner-icon {
  position: absolute;
  width: 16px;
  height: 16px;
  z-index: 10;
}
.corner-icon.top-left { top: -8px; left: -8px; }
.corner-icon.top-right { top: -8px; right: -8px; }
.corner-icon.bottom-left { bottom: -8px; left: -8px; }
.corner-icon.bottom-right { bottom: -8px; right: -8px; }

.corner-icon svg {
  width: 100%;
  height: 100%;
  color: #333;
}

.strategy-card {
  position: relative;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  overflow: hidden;
  cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.08);
  width: 190px;
  height: 254px;
}

.strategy-card .ripple-grid {
  border-radius: 12px;
}

.strategy-card .card-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  pointer-events: none;
}

.strategy-card .content-inner {
  position: absolute;
  top: 8px;
  left: 8px;
  right: 8px;
  bottom: 8px;
  background: rgba(255, 255, 255, 0.85);
  border-radius: 8px;
  z-index: 4;
}

.strategy-card .grid-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px);
  background-size: 16px 16px;
  pointer-events: none;
  border-radius: 8px;
}

.strategy-card .card-title {
  position: absolute;
  left: 10px;
  top: 74px;
  font-size: 18px;
  font-weight: 700;
  color: #1a1a1a;
  letter-spacing: -0.3px;
  z-index: 5;
}

.strategy-card .card-description {
  position: absolute;
  left: 10px;
  top: 103px;
  font-size: 11px;
  color: #4a4a4a;
  display: flex;
  align-items: center;
  gap: 4px;
  z-index: 5;
}

.strategy-card .eye-icon {
  width: 14px;
  height: 14px;
  opacity: 0.7;
}

.strategy-card .card-meta {
  position: absolute;
  left: 10px;
  font-size: 10px;
  color: #9a9a9a;
  z-index: 5;
}

.strategy-card .card-meta.created { top: 146px; }
.strategy-card .card-meta.updated { top: 158px; }
.strategy-card .card-meta span { color: #6a6a6a; }

.strategy-card .action-btn {
  position: absolute;
  top: 194px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: opacity 0.2s ease;
  color: #4a4a4a;
  pointer-events: auto;
  z-index: 5;
}

.strategy-card .action-btn:hover { opacity: 0.6; }
.strategy-card .action-btn.edit { left: 10px; }
.strategy-card .action-btn.copy { left: 33px; }
.strategy-card .action-btn.delete { left: 56px; }
.strategy-card .action-btn svg { width: 14px; height: 14px; }
```

---

## Template Card

### Preview
- No corner icons
- Title, description with eye icon
- Edit, Star action buttons
- Popular badge

### Specs

| Property | Value |
|----------|-------|
| Width | 190px |
| Height | 190px |
| Border Radius | 16px (outer), 12px (inner) |
| Font | Space Grotesk |
| Shadow | 0 4px 20px rgba(0,0,0,0.08) |

### Positions

| Element | X | Y |
|---------|---|---|
| Template Name | 20px | 74px |
| Description | 20px | 103px |
| Eye icon | 148px | 108px |
| Edit icon | 20px | 129px |
| Star icon | 43px | 129px |
| Popular badge | 133px | 130px |

### Badge Specs

| Property | Value |
|----------|-------|
| Width | 34px |
| Height | 10px |
| Border Radius | 3px |
| Font Size | 6px |
| Font Weight | 300 (Light) |
| Background | #2a2a2a |

### HTML

```html
<div class="template-card" id="templateCard">
  <div class="ripple-grid" id="templateRippleGrid"></div>

  <div class="card-content">
    <div class="content-inner">
      <div class="grid-bg"></div>
    </div>
    <h1 class="card-title">Template Name</h1>
    <p class="card-description">
      An app for strategy idea...
      <svg class="eye-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
        <circle cx="12" cy="12" r="3"/>
      </svg>
    </p>
    <button class="edit-btn" title="Edit">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
        <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
      </svg>
    </button>
    <button class="star-btn" title="Favorite">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>
      </svg>
    </button>
    <span class="badge">Popular</span>
  </div>
</div>
```

### CSS

```css
.template-card {
  position: relative;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  overflow: hidden;
  cursor: pointer;
  border: 1px solid rgba(0, 0, 0, 0.06);
  width: 190px;
  height: 190px;
}

.template-card .ripple-grid {
  border-radius: 16px;
}

.template-card .card-content {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  pointer-events: none;
}

.template-card .content-inner {
  position: absolute;
  top: 8px;
  left: 8px;
  right: 8px;
  bottom: 8px;
  background: rgba(255, 255, 255, 0.85);
  border-radius: 12px;
  z-index: 0;
}

.template-card .grid-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.03) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.03) 1px, transparent 1px);
  background-size: 16px 16px;
  pointer-events: none;
  border-radius: 12px;
}

.template-card .card-title {
  position: absolute;
  left: 12px;
  top: 66px;
  font-size: 18px;
  font-weight: 700;
  color: #1a1a1a;
  letter-spacing: -0.3px;
  z-index: 1;
}

.template-card .card-description {
  position: absolute;
  left: 12px;
  top: 95px;
  font-size: 11px;
  color: #4a4a4a;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 4px;
}

.template-card .card-description .eye-icon {
  width: 14px;
  height: 14px;
  opacity: 0.7;
  flex-shrink: 0;
}

.template-card .edit-btn {
  position: absolute;
  left: 12px;
  top: 121px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: opacity 0.2s ease;
  color: #3a3a3a;
  pointer-events: auto;
  z-index: 1;
}

.template-card .edit-btn:hover { opacity: 0.6; }
.template-card .edit-btn svg { width: 14px; height: 14px; }

.template-card .star-btn {
  position: absolute;
  left: 35px;
  top: 121px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: opacity 0.2s ease;
  color: #3a3a3a;
  pointer-events: auto;
  z-index: 1;
}

.template-card .star-btn:hover { opacity: 0.6; }
.template-card .star-btn svg { width: 14px; height: 14px; }

.template-card .badge {
  position: absolute;
  left: 125px;
  top: 122px;
  width: 34px;
  height: 10px;
  background: #2a2a2a;
  color: white;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 6px;
  font-weight: 300;
  line-height: 10px;
  text-align: center;
  letter-spacing: 0;
  border-radius: 3px;
  z-index: 1;
}
```

---

## Shared: Ripple Effect

### CSS

```css
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;700&display=swap');

/* Ripple Grid Background */
.ripple-grid {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: grid;
  z-index: 1;
  overflow: hidden;
}

.ripple-cell {
  background-color: rgba(0, 0, 0, 0.02);
  border: 0.5px solid rgba(0, 0, 0, 0.04);
  opacity: 0.4;
  transition: opacity 0.15s ease, background-color 0.15s ease;
}

.ripple-cell:hover {
  opacity: 0.8;
}

.ripple-cell.ripple-active {
  animation: cellRipple var(--duration, 200ms) ease-out var(--delay, 0ms);
}

@keyframes cellRipple {
  0% {
    background-color: rgba(251, 146, 60, 0.5);  /* Orange */
    opacity: 1;
  }
  40% {
    background-color: rgba(244, 114, 182, 0.4); /* Pink */
    opacity: 0.9;
  }
  70% {
    background-color: rgba(147, 197, 253, 0.3); /* Light Blue */
    opacity: 0.7;
  }
  100% {
    background-color: rgba(0, 0, 0, 0.02);
    opacity: 0.4;
  }
}
```

### JavaScript

```javascript
// Ripple effect setup function
function setupRippleGrid(card, gridElement, cardWidth, cardHeight) {
  const cellSize = 19;
  const cols = Math.ceil(cardWidth / cellSize);
  const rows = Math.ceil(cardHeight / cellSize);

  gridElement.style.gridTemplateColumns = `repeat(${cols}, ${cellSize}px)`;
  gridElement.style.gridTemplateRows = `repeat(${rows}, ${cellSize}px)`;

  const cells = [];
  for (let i = 0; i < rows * cols; i++) {
    const cell = document.createElement('div');
    cell.className = 'ripple-cell';
    cell.dataset.row = Math.floor(i / cols);
    cell.dataset.col = i % cols;
    gridElement.appendChild(cell);
    cells.push(cell);
  }

  function triggerRipple(targetRow, targetCol) {
    cells.forEach((cell, idx) => {
      const row = Math.floor(idx / cols);
      const col = idx % cols;
      const distance = Math.hypot(targetRow - row, targetCol - col);
      const delay = distance * 25;
      const duration = 150 + distance * 30;

      cell.classList.remove('ripple-active');
      void cell.offsetWidth; // Force reflow

      cell.style.setProperty('--delay', `${delay}ms`);
      cell.style.setProperty('--duration', `${duration}ms`);
      cell.classList.add('ripple-active');

      setTimeout(() => {
        cell.classList.remove('ripple-active');
      }, delay + duration);
    });
  }

  // Click to trigger ripple
  cells.forEach((cell) => {
    cell.addEventListener('click', () => {
      const row = parseInt(cell.dataset.row);
      const col = parseInt(cell.dataset.col);
      triggerRipple(row, col);
    });
  });

  // Hover to trigger ripple
  let lastRippleTime = 0;
  card.addEventListener('mouseenter', (e) => {
    const now = Date.now();
    if (now - lastRippleTime > 500) { // Throttle
      const rect = gridElement.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;
      const col = Math.floor(x / cellSize);
      const row = Math.floor(y / cellSize);
      triggerRipple(row, col);
      lastRippleTime = now;
    }
  });
}

// Initialize cards
// Strategy Card: 190x254px
setupRippleGrid(
  document.getElementById('strategyCard'),
  document.getElementById('strategyRippleGrid'),
  190, 254
);

// Template Card: 190x190px
setupRippleGrid(
  document.getElementById('templateCard'),
  document.getElementById('templateRippleGrid'),
  190, 190
);
```

---

## Design Tokens

### Colors

| Token | Value | Usage |
|-------|-------|-------|
| `--color-text-primary` | #1a1a1a | Titles |
| `--color-text-secondary` | #4a4a4a | Descriptions |
| `--color-text-muted` | #9a9a9a | Metadata labels |
| `--color-text-meta` | #6a6a6a | Metadata values |
| `--color-icon` | #3a3a3a | Action icons |
| `--color-badge-bg` | #2a2a2a | Badge background |
| `--color-ripple-orange` | rgba(251,146,60,0.5) | Ripple start |
| `--color-ripple-pink` | rgba(244,114,182,0.4) | Ripple mid |
| `--color-ripple-blue` | rgba(147,197,253,0.3) | Ripple end |

### Typography

| Element | Font | Size | Weight |
|---------|------|------|--------|
| Card Title | Space Grotesk | 18px | 700 |
| Description | Space Grotesk | 11px | 400 |
| Metadata | Space Grotesk | 10px | 400 |
| Badge | Space Grotesk | 6px | 300 |

### Spacing

| Token | Value |
|-------|-------|
| Content inset | 8px |
| Grid cell size | 16px |
| Ripple cell size | 19px |
| Icon size | 14px |
