# DS-02: Figma Component Production Specs

## Component Build Order

### Phase A: Base Components (Build First)

---

## 1. RP/Button

### Component Set: `RP/Button`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `primary`, `secondary`, `outline`, `ghost`, `danger`, `accent`, `link` | `primary` |
| `size` | Enum | `sm`, `md`, `lg` | `md` |
| `state` | Enum | `default`, `hover`, `active`, `focus`, `disabled` | `default` |
| `icon-left` | Boolean | true/false | false |
| `icon-right` | Boolean | true/false | false |
| `loading` | Boolean | true/false | false |

### Dimensions

| Size | Height | Padding H | Font Size | Font Weight | Border Radius |
|------|--------|-----------|-----------|-------------|---------------|
| `sm` | 32px | 12px | 14px | Semibold (600) | 6px |
| `md` | 40px | 16px | 16px | Semibold (600) | 8px |
| `lg` | 48px | 24px | 18px | Semibold (600) | 8px |

### Type Styles

| Type | BG | Text | Border | Hover BG | Active BG |
|------|----|------|--------|----------|-----------|
| `primary` | `color/secondary` (#1E5FA8) | `color/inverse-text` (#FFF) | none | #1a5296 | #154480 |
| `secondary` | `color/primary` (#0B3A66) | `color/inverse-text` (#FFF) | none | #092f57 | #072548 |
| `outline` | transparent | `color/secondary` (#1E5FA8) | 1px `color/secondary` | rgba(30,95,168,0.08) | rgba(30,95,168,0.15) |
| `ghost` | transparent | `color/body-text` (#1E293B) | none | rgba(0,0,0,0.05) | rgba(0,0,0,0.1) |
| `danger` | `color/danger` (#DC2626) | `color/inverse-text` (#FFF) | none | #c91f1f | #b01b1b |
| `accent` | `color/accent` (#D4A017) | `color/inverse-text` (#FFF) | none | #c09015 | #ac8013 |
| `link` | transparent | `color/secondary` (#1E5FA8) | none | underline | underline |

### Disabled State
- BG: `color/disabled-bg` (#F1F5F9)
- Text: `color/disabled-text` (#94A3B8)
- Border: none
- Cursor: not-allowed
- Opacity: 1 (no opacity change — use color only)

### Focus State
- Ring: 2px solid `color/secondary` (#1E5FA8)
- Ring offset: 2px
- Applied to all types

### Loading State
- Replace text with spinner icon (16px)
- Button disabled
- Width preserved (no shrink)

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: 8px (between icon and text)
- Padding: Per size table above
- Sizing: Hug content (width), Fixed height

### Figma Structure
```
RP/Button (Component Set)
├── primary/sm/default
├── primary/sm/hover
├── primary/sm/active
├── primary/sm/focus
├── primary/sm/disabled
├── primary/md/default
├── ... (all combinations)
├── primary/lg/default
├── secondary/sm/default
├── ... (all types × sizes × states)
├── link/md/default
└── link/md/hover
```

---

## 2. RP/Input

### Component Set: `RP/Input`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `text`, `email`, `password`, `tel`, `number`, `date` | `text` |
| `size` | Enum | `sm`, `md`, `lg` | `md` |
| `state` | Enum | `default`, `hover`, `focus`, `error`, `success`, `disabled` | `default` |
| `has-label` | Boolean | true/false | true |
| `has-helper` | Boolean | true/false | false |
| `has-icon-left` | Boolean | true/false | false |
| `has-icon-right` | Boolean | true/false | false |

### Dimensions

| Size | Height | Padding H | Font Size | Border Radius |
|------|--------|-----------|-----------|---------------|
| `sm` | 32px | 10px | 14px | 6px |
| `md` | 40px | 12px | 16px | 8px |
| `lg` | 48px | 16px | 18px | 8px |

### State Styles

| State | BG | Border | Text | Helper |
|-------|----|--------|------|--------|
| `default` | `color/surface` (#FFF) | 1px `color/border` (#E2E8F0) | `color/body-text` | `color/muted-text` |
| `hover` | `color/surface` | 1px `color/border-strong` (#CBD5E1) | `color/body-text` | `color/muted-text` |
| `focus` | `color/surface` | 2px `color/secondary` (#1E5FA8) | `color/body-text` | `color/muted-text` |
| `error` | `color/surface` | 2px `color/danger` (#DC2626) | `color/body-text` | `color/danger` |
| `success` | `color/surface` | 2px `color/success` (#22C55E) | `color/body-text` | `color/success` |
| `disabled` | `color/disabled-bg` | 1px `color/border` | `color/disabled-text` | `color/disabled-text` |

### Label
- Font: `Label/Base` (14px, Medium, 500)
- Color: `color/body-text`
- Position: Above input, 4px gap
- Required indicator: Red asterisk `*` after label text

### Helper Text
- Font: `Caption/Base` (12px, Regular, 400)
- Position: Below input, 4px gap
- Error: `color/danger`
- Success: `color/success`
- Default: `color/muted-text`

### Password Toggle
- Right icon: Eye (default) / Eye-off (revealed)
- Position: Right side of input, 12px from edge
- Size: 20px icon
- Click toggles between password/text type

### Auto-Layout
- Container: Vertical, gap 4px
- Input field: Horizontal, gap 8px (icon + text)
- Sizing: Fill width

---

## 3. RP/Badge

### Component Set: `RP/Badge`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `success`, `warning`, `danger`, `info`, `neutral` | `neutral` |
| `pill` | Boolean | true/false | true |
| `size` | Enum | `sm`, `md` | `md` |

### Dimensions

| Size | Height | Padding H | Font Size | Border Radius |
|------|--------|-----------|-----------|---------------|
| `sm` | 20px | 6px | 11px | 10px (pill) / 4px (square) |
| `md` | 24px | 8px | 12px | 12px (pill) / 4px (square) |

### Type Styles

| Type | BG | Text | Border |
|------|----|------|--------|
| `success` | rgba(34,197,94,0.1) | #16a34a | none |
| `warning` | rgba(245,158,11,0.1) | #d97706 | none |
| `danger` | rgba(220,38,38,0.1) | #dc2626 | none |
| `info` | rgba(59,130,246,0.1) | #2563eb | none |
| `neutral` | rgba(100,116,139,0.1) | #475569 | none |

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: 4px (icon + text)
- Sizing: Hug

---

## 4. RP/Avatar

### Component Set: `RP/Avatar`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `xs`, `sm`, `md`, `lg` | `md` |
| `has-image` | Boolean | true/false | false |
| `online` | Boolean | true/false | false |
| `border` | Boolean | true/false | false |

### Dimensions

| Size | Diameter | Font Size | Online Dot | Border Width |
|------|----------|-----------|------------|--------------|
| `xs` | 24px | 10px | 6px | 2px |
| `sm` | 32px | 12px | 8px | 2px |
| `md` | 40px | 14px | 10px | 2px |
| `lg` | 48px | 16px | 12px | 2px |

### Styles
- BG (no image): `color/secondary` (#1E5FA8)
- Text (no image): `color/inverse-text` (#FFF)
- Border: 2px `color/surface` (#FFF)
- Online dot: `color/success` (#22C55E), positioned bottom-right, 2px from edge
- Image: `object-fit: cover`, circular clip

### Auto-Layout
- Frame: Fixed width/height, circular (border-radius: full)
- No auto-layout (absolute positioning for online dot)

---

## 5. RP/Toggle

### Component Set: `RP/Toggle`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg` | `md` |
| `value` | Enum | `off`, `on` | `off` |
| `disabled` | Boolean | true/false | false |

### Dimensions

| Size | Track W | Track H | Thumb D | Thumb Offset |
|------|---------|---------|---------|--------------|
| `sm` | 32px | 18px | 14px | 2px |
| `md` | 40px | 22px | 18px | 2px |
| `lg` | 48px | 26px | 22px | 2px |

### States

| State | Track BG | Thumb BG | Thumb Position |
|-------|----------|----------|----------------|
| `off/default` | `color/border-strong` (#CBD5E1) | #FFF | Left |
| `off/hover` | #94A3B8 | #FFF | Left |
| `on/default` | `color/secondary` (#1E5FA8) | #FFF | Right |
| `on/hover` | #1a5296 | #FFF | Right |
| `disabled` | `color/disabled-bg` | `color/disabled-text` | Left |

### Auto-Layout
- Track: Fixed size, border-radius: full
- Thumb: Absolute positioned, centered vertically

---

## 6. RP/Card

### Component Set: `RP/Card`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `shadow` | Enum | `none`, `xs`, `sm`, `md`, `lg`, `xl` | `sm` |
| `padding` | Enum | `none`, `sm`, `md`, `lg` | `md` |
| `hover` | Boolean | true/false | false |
| `border` | Boolean | true/false | false |

### Dimensions

| Padding | Value |
|---------|-------|
| `none` | 0px |
| `sm` | 12px |
| `md` | 16px |
| `lg` | 24px |

### Styles
- BG: `color/surface` (#FFF)
- Border: 1px `color/border` (if border=true)
- Border Radius: 12px
- Shadow: Per shadow variable
- Hover: Shadow increases one level, slight translateY(-1px)

### Auto-Layout
- Direction: Vertical
- Gap: 0 (content manages spacing)
- Padding: Per padding variable
- Sizing: Fill width, Hug height

---

## 7. RP/Tabs

### Component Set: `RP/Tabs`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `variant` | Enum | `underline`, `pill`, `boxed` | `underline` |
| `scrollable` | Boolean | true/false | false |

### Dimensions
- Height: 40px (underline), 36px (pill), 36px (boxed)
- Tab padding: 12px horizontal
- Gap between tabs: 0 (underline), 4px (pill/boxed)

### Variant Styles

| Variant | Active BG | Active Text | Active Indicator | Inactive BG | Inactive Text |
|---------|-----------|-------------|------------------|-------------|---------------|
| `underline` | transparent | `color/secondary` | 2px bottom border `color/secondary` | transparent | `color/muted-text` |
| `pill` | `color/secondary` | `color/inverse-text` | none | transparent | `color/body-text` |
| `boxed` | `color/surface` | `color/secondary` | 1px border `color/secondary` | transparent | `color/muted-text` |

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: Per variant
- Sizing: Fill width (scrollable) or Hug (non-scrollable)

---

## 8. RP/Toast

### Component Set: `RP/Toast`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `success`, `warning`, `danger`, `info` | `info` |
| `position` | Enum | `top-right`, `top-center`, `bottom-right`, `bottom-center` | `top-right` |
| `dismissible` | Boolean | true/false | true |

### Dimensions
- Width: 360px (max)
- Padding: 12px 16px
- Border Radius: 8px
- Gap: 12px (icon + text + close)

### Type Styles

| Type | BG | Border | Icon Color | Text Color |
|------|----|--------|------------|------------|
| `success` | #f0fdf4 | 1px #bbf7d0 | #22c55e | #166534 |
| `warning` | #fffbeb | 1px #fde68a | #f59e0b | #92400e |
| `danger` | #fef2f2 | 1px #fecaca | #dc2626 | #991b1b |
| `info` | #eff6ff | 1px #bfdbfe | #3b82f6 | #1e40af |

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: 12px
- Sizing: Fill width (max 360px)

---

## 9. RP/Banner

### Component Set: `RP/Banner`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `success`, `warning`, `danger`, `info` | `info` |
| `dismissible` | Boolean | true/false | true |

### Dimensions
- Padding: 12px 16px
- Border Radius: 8px
- Gap: 12px

### Type Styles

| Type | BG | Border | Icon | Text |
|------|----|--------|------|------|
| `success` | #f0fdf4 | 1px #bbf7d0 | #22c55e | #166534 |
| `warning` | #fffbeb | 1px #fde68a | #f59e0b | #92400e |
| `danger` | #fef2f2 | 1px #fecaca | #dc2626 | #991b1b |
| `info` | #eff6ff | 1px #bfdbfe | #3b82f6 | #1e40af |

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: 12px
- Sizing: Fill width

---

## 10. RP/ProgressBar

### Component Set: `RP/ProgressBar`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg` | `md` |
| `color` | Enum | `primary`, `success`, `warning`, `danger`, `accent` | `primary` |
| `show-value` | Boolean | true/false | false |
| `animated` | Boolean | true/false | false |

### Dimensions

| Size | Track Height | Border Radius |
|------|-------------|---------------|
| `sm` | 4px | 2px |
| `md` | 8px | 4px |
| `lg` | 12px | 6px |

### Color Mapping

| Color | Fill |
|-------|------|
| `primary` | `color/secondary` (#1E5FA8) |
| `success` | `color/success` (#22C55E) |
| `warning` | `color/warning` (#F59E0B) |
| `danger` | `color/danger` (#DC2626) |
| `accent` | `color/accent` (#D4A017) |

### Auto-Layout
- Track: Fixed height, Fill width, border-radius: full
- Fill: Fixed height, variable width (percentage), border-radius: full
- Value text: Right-aligned, 8px from track

---

## 11. RP/KPICard

### Component Set: `RP/KPICard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `color` | Enum | `primary`, `success`, `warning`, `danger`, `accent` | `primary` |
| `format` | Enum | `number`, `currency`, `percentage` | `number` |
| `has-trend` | Boolean | true/false | false |
| `has-sparkline` | Boolean | true/false | false |

### Dimensions
- Width: Fill (min 200px)
- Padding: 20px
- Border Radius: 12px
- Shadow: `shadow/sm`

### Layout
```
┌──────────────────────────────────┐
│  [Icon]  Label                   │
│                                  │
│  Value              Trend Arrow  │
│  (KPI/Value)        +X%         │
│                                  │
│  [Sparkline chart — optional]    │
└──────────────────────────────────┘
```

### Auto-Layout
- Direction: Vertical
- Gap: 8px
- Padding: 20px
- Sizing: Fill width

---

## 12. RP/Modal

### Component Set: `RP/Modal`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg`, `xl` | `md` |
| `has-header` | Boolean | true/false | true |
| `has-footer` | Boolean | true/false | true |

### Dimensions

| Size | Width | Max Height |
|------|-------|------------|
| `sm` | 400px | 80vh |
| `md` | 560px | 80vh |
| `lg` | 720px | 80vh |
| `xl` | 960px | 80vh |

### Layout
```
┌──────────────────────────────────────┐
│  Title                    [✕ Close]  │  ← Header (optional)
├──────────────────────────────────────┤
│                                      │
│  Content area                        │
│  (scrollable)                        │
│                                      │
├──────────────────────────────────────┤
│  [Cancel]              [Confirm]     │  ← Footer (optional)
└──────────────────────────────────────┘
```

### Auto-Layout
- Container: Vertical, gap 0
- Header: Horizontal, padding 20px 24px, gap 8px
- Content: Vertical, padding 0 24px 24px, gap 16px
- Footer: Horizontal, padding 16px 24px, gap 8px, justify: end

---

## 13. RP/SearchInput

### Component Set: `RP/SearchInput`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg` | `md` |
| `state` | Enum | `default`, `focused`, `results` | `default` |

### Dimensions
- Same as RP/Input
- Left icon: Search (20px)
- Right: Clear button (X) when has value

### Auto-Layout
- Same as RP/Input with search icon

---

## 14. RP/Accordion

### Component Set: `RP/Accordion`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `state` | Enum | `closed`, `open` | `closed` |

### Dimensions
- Padding: 16px 20px
- Border: 1px `color/border`
- Border Radius: 8px
- Chevron: 20px, rotates 90° on open

### Auto-Layout
- Direction: Vertical
- Gap: 0
- Sizing: Fill width

---

## 15. RP/EmptyState

### Component Set: `RP/EmptyState`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `has-cta` | Boolean | true/false | false |

### Dimensions
- Padding: 48px 24px
- Icon: 48px
- Title: `Display/H5`
- Description: `Body/SM`, `color/muted-text`
- CTA: RP/Button (primary, md)

### Auto-Layout
- Direction: Vertical
- Alignment: Center
- Gap: 12px
- Sizing: Fill width

---

## 16. RP/Skeleton

### Component Set: `RP/Skeleton`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `text`, `circle`, `rect`, `card` | `text` |

### Dimensions

| Type | Width | Height | Border Radius |
|------|-------|--------|---------------|
| `text` | 100% | 16px | 4px |
| `circle` | 40px | 40px | full |
| `rect` | 100% | 200px | 8px |
| `card` | 100% | 120px | 12px |

### Styles
- BG: `color/border` (#E2E8F0) — Light
- BG: `color/border` (#334155) — Dark
- Shimmer: Linear gradient animation (left to right)

---

## 17. RP/OPSRing

### Component Set: `RP/OPSRing`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg`, `xl` | `md` |
| `color-zone` | Enum | `green`, `amber`, `red` | `green` |

### Dimensions

| Size | Diameter | Stroke Width | Font Size (center) |
|------|----------|-------------|-------------------|
| `sm` | 64px | 6px | 14px |
| `md` | 120px | 8px | 24px |
| `lg` | 180px | 10px | 36px |
| `xl` | 240px | 12px | 48px |

### Color Zones

| Zone | Score Range | Stroke Color |
|------|------------|--------------|
| `green` | 80–100% | `gamification/ring-green` |
| `amber` | 60–79% | `gamification/ring-amber` |
| `red` | 0–59% | `gamification/ring-red` |

### SVG Structure
```
<svg width="{diameter}" height="{diameter}">
  <circle cx="50%" cy="50%" r="45%" fill="none" stroke="{ring-bg}" stroke-width="{stroke-width}" />
  <circle cx="50%" cy="50%" r="45%" fill="none" stroke="{zone-color}" stroke-width="{stroke-width}"
          stroke-dasharray="{percentage * circumference}" stroke-dashoffset="0"
          stroke-linecap="round" transform="rotate(-90 50% 50%)" />
  <text x="50%" y="50%" text-anchor="middle" dominant-baseline="central">{score}%</text>
</svg>
```

---

## 18. RP/TierBadge

### Component Set: `RP/TierBadge`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `tier` | Enum | `bronze`, `silver`, `gold`, `platinum`, `diamond` | `bronze` |
| `highlighted` | Boolean | true/false | false |

### Dimensions
- Height: 32px
- Padding: 4px 12px
- Border Radius: 16px (pill)
- Icon: 16px
- Font: `Label/Base` (14px, Medium)

### Tier Styles

| Tier | BG | Text | Icon |
|------|----|------|------|
| `bronze` | `gamification/bronze-bg` | `gamification/bronze` | 🥉 |
| `silver` | `gamification/silver-bg` | `gamification/silver` | 🥈 |
| `gold` | `gamification/gold-bg` | `gamification/gold` | 🥇 |
| `platinum` | `gamification/platinum-bg` | `gamification/platinum` | 💎 |
| `diamond` | `gamification/diamond-bg` | `gamification/diamond` | 👑 |

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: 6px
- Sizing: Hug

---

## 19. RP/StreakBadge

### Component Set: `RP/StreakBadge`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `size` | Enum | `sm`, `md`, `lg` | `md` |

### Dimensions

| Size | Icon Size | Font Size | Gap |
|------|-----------|-----------|-----|
| `sm` | 16px | 12px | 4px |
| `md` | 24px | 14px | 6px |
| `lg` | 32px | 18px | 8px |

### Styles
- Icon: 🔥 flame, `gamification/flame`
- Text: `gamification/flame`, bold
- BG: `gamification/flame` at 10% opacity
- Border Radius: full (pill)

### Auto-Layout
- Direction: Horizontal
- Alignment: Center
- Gap: Per size
- Sizing: Hug

---

## 20. RP/DataTable

### Component Set: `RP/DataTable`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `state` | Enum | `loading`, `empty`, `data`, `paginated` | `data` |
| `striped` | Boolean | true/false | false |

### Dimensions
- Header height: 48px
- Row height: 52px
- Cell padding: 12px 16px
- Border: 1px `color/border`
- Border Radius: 12px (outer)

### Styles
- Header BG: `color/background` (#F5F7FA)
- Header Text: `Label/Base` (14px, Medium)
- Row BG: `color/surface` (#FFF)
- Row Hover: `color/background`
- Striped Row: `color/background` (every other)
- Cell Text: `Body/SM` (14px, Regular)
- Sort icon: 16px, `color/muted-text`

### Auto-Layout
- Container: Vertical, gap 0
- Header: Horizontal, gap 0
- Rows: Vertical, gap 0
- Pagination: Horizontal, gap 8px, padding 12px 16px

---

## 21. RP/FileUpload

### Component Set: `RP/FileUpload`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `state` | Enum | `empty`, `hover`, `selected`, `error`, `uploading` | `empty` |

### Dimensions
- Min height: 120px
- Padding: 24px
- Border: 2px dashed `color/border`
- Border Radius: 12px

### States

| State | Border | BG | Icon | Text |
|-------|--------|----|------|------|
| `empty` | 2px dashed `color/border` | `color/surface` | Upload icon (32px) | "Upload file" + "PDF, DOC, DOCX. Max 5MB." |
| `hover` | 2px dashed `color/secondary` | rgba(30,95,168,0.05) | Upload icon | Same |
| `selected` | 2px solid `color/success` | rgba(34,197,94,0.05) | Check icon | File name + size |
| `error` | 2px dashed `color/danger` | rgba(220,38,38,0.05) | Alert icon | Error message |
| `uploading` | 2px solid `color/secondary` | rgba(30,95,168,0.05) | Spinner | "Uploading... X%" |

### Auto-Layout
- Direction: Vertical
- Alignment: Center
- Gap: 8px
- Sizing: Fill width

---

## 22. RP/NotificationBell

### Component Set: `RP/NotificationBell`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `count` | Number | 0–99+ | 0 |
| `open` | Boolean | true/false | false |

### Dimensions
- Button: 44×44px (touch target)
- Icon: 20px
- Badge: 18px diameter, positioned top-right, 2px offset
- Badge text: 10px, bold, white
- Dropdown: 360px wide, max 400px height

### Badge Colors
- Count > 0: `color/danger` (#DC2626) BG, white text
- Count = 0: Hidden

### Dropdown
- BG: `color/surface-elevated`
- Shadow: `shadow/lg`
- Border Radius: 12px
- Max items: 5
- Each item: Avatar + text + time + unread dot
- Footer: [View All Notifications] link

---

## 23. RP/ChildSwitcher

### Component Set: `RP/ChildSwitcher`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `state` | Enum | `closed`, `open-2`, `open-5+` | `closed` |

### Dimensions
- Trigger: Auto-width, 40px height
- Dropdown: 280px wide, max 320px height
- Each child row: 56px height, 12px padding
- Gap between rows: 0

### Layout
```
Trigger: [Avatar 32px] [Name + Class] [Chevron 16px]
Dropdown:
  [Avatar 32px] [Name] [OPS mini-ring] [Active indicator]
  [Avatar 32px] [Name] [OPS mini-ring]
  ─────────────────────────────────────
  [+ Add Another Child]
```

---

## 24. RP/CredentialCard

### Component Set: `RP/CredentialCard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `revealed` | Boolean | true/false | false |

### Dimensions
- Padding: 24px
- Border Radius: 12px
- Border: 1px `color/border`
- BG: `color/surface`

### Layout
```
┌──────────────────────────────────────┐
│  Student Name                        │
│                                      │
│  Student ID                          │
│  ┌────────────────────────┐ [Copy]  │
│  │ RP-2026-00001          │         │
│  └────────────────────────┘         │
│  (JetBrains Mono, 18px, bold)       │
│                                      │
│  Temporary Password                  │
│  ┌────────────────────────┐ 👁 [Copy]│
│  │ ••••••••               │         │
│  └────────────────────────┘         │
│                                      │
│  Class: JSS 2                        │
└──────────────────────────────────────┘
```

---

## 25. RP/SessionCard

### Component Set: `RP/SessionCard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `mode` | Enum | `online`, `physical`, `hybrid` | `online` |
| `status` | Enum | `scheduled`, `in-progress`, `completed` | `scheduled` |

### Dimensions
- Padding: 16px
- Border Radius: 12px
- Border: 1px `color/border`

### Mode Badges
| Mode | Badge BG | Badge Text |
|------|----------|------------|
| `online` | rgba(59,130,246,0.1) | #2563eb |
| `physical` | rgba(34,197,94,0.1) | #16a34a |
| `hybrid` | rgba(245,158,11,0.1) | #d97706 |

### Status Badges
| Status | Badge BG | Badge Text |
|--------|----------|------------|
| `scheduled` | rgba(100,116,139,0.1) | #475569 |
| `in-progress` | rgba(34,197,94,0.1) | #16a34a |
| `completed` | rgba(100,116,139,0.1) | #94a3b8 |

---

## 26. RP/GoalCard

### Component Set: `RP/GoalCard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `status` | Enum | `active`, `completed` | `active` |

### Dimensions
- Padding: 16px
- Border Radius: 12px
- Border: 1px `color/border`

### Layout
```
┌──────────────────────────────────────┐
│  Goal Title                          │
│  ████████████████░░░░ 75%            │
│  Target: Dec 31, 2026                │
└──────────────────────────────────────┘
```

---

## 27. RP/InvoiceCard

### Component Set: `RP/InvoiceCard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `status` | Enum | `draft`, `sent`, `partially_paid`, `paid`, `overdue`, `cancelled`, `refunded` | `sent` |

### Dimensions
- Padding: 16px
- Border Radius: 12px
- Border: 1px `color/border`

### Status Colors
| Status | Badge BG | Badge Text |
|--------|----------|------------|
| `draft` | rgba(100,116,139,0.1) | #475569 |
| `sent` | rgba(59,130,246,0.1) | #2563eb |
| `partially_paid` | rgba(245,158,11,0.1) | #d97706 |
| `paid` | rgba(34,197,94,0.1) | #16a34a |
| `overdue` | rgba(220,38,38,0.1) | #dc2626 |
| `cancelled` | rgba(100,116,139,0.1) | #94a3b8 |
| `refunded` | rgba(245,158,11,0.1) | #d97706 |

---

## 28. RP/Timeline

### Component Set: `RP/Timeline`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `variant` | Enum | `vertical`, `horizontal` | `vertical` |

### Dimensions
- Line width: 2px
- Dot: 12px diameter
- Gap between items: 24px
- Padding left: 24px (vertical)

---

## 29. RP/Calendar

### Component Set: `RP/Calendar`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `variant` | Enum | `month`, `heatmap` | `month` |

### Dimensions
- Cell: 36px × 36px
- Gap: 2px
- Header: 32px height
- Month navigation: 40px height

### Heatmap Colors
- Present: `gamification/heatmap-present`
- Late: `gamification/heatmap-late`
- Absent: `gamification/heatmap-absent`
- No class: `gamification/heatmap-noclass`

---

## 30. RP/QuestionBuilder

### Component Set: `RP/QuestionBuilder`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `mc`, `multi`, `tf`, `short`, `essay`, `match`, `fill`, `upload`, `numeric` | `mc` |

### Dimensions
- Container: Fill width
- Tab bar: 40px height, scrollable
- Form area: Padding 24px

### Tab Labels
| Tab | Label |
|-----|-------|
| `mc` | MCQ |
| `multi` | Multi |
| `tf` | T/F |
| `short` | Short |
| `essay` | Essay |
| `match` | Match |
| `fill` | Fill |
| `upload` | Upload |
| `numeric` | Numeric |

---

## 31. RP/Classroom

### Component Set: `RP/Classroom`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `role` | Enum | `teacher`, `student` | `student` |

### Dimensions
- Container: Full viewport (100vw × 100vh)
- Video area: Fill
- Controls bar: 64px height, bottom
- Sidebar: 280px width (toggleable)

---

## 32. RP/PaystackButton

### Component Set: `RP/PaystackButton`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `state` | Enum | `default`, `processing`, `success`, `error` | `default` |

### Dimensions
- Same as RP/Button (lg)
- Processing: Spinner + "Processing..."
- Success: Check icon + "Payment Confirmed"
- Error: X icon + "Payment Failed"

---

## 33. RP/DigestCard

### Component Set: `RP/DigestCard`

**Properties:**
| Property | Type | Values | Default |
|----------|------|--------|---------|
| `type` | Enum | `daily`, `weekly` | `daily` |

### Dimensions
- Padding: 16px
- Border Radius: 12px
- Border: 1px `color/border`

---

## 34. RP/ProgressBar (duplicate — already #10)

See #10 above.

---

## Component Build Summary

| # | Component | Variants | States | Complexity | Sprint |
|---|-----------|----------|--------|------------|--------|
| 1 | Button | 7×3×5 | 5 | Medium | 1 |
| 2 | Input | 6×3×6 | 6 | Medium | 1 |
| 3 | Badge | 5×2×2 | 1 | Low | 1 |
| 4 | Avatar | 4×2×2 | 2 | Low | 1 |
| 5 | Toggle | 3×2×2 | 3 | Low | 1 |
| 6 | Card | 5×2×2 | 3 | Low | 1 |
| 7 | Tabs | 3×2 | 3 | Medium | 1 |
| 8 | Toast | 4×4 | 3 | Medium | 1 |
| 9 | Banner | 4×2 | 2 | Low | 1 |
| 10 | ProgressBar | 3×5×2 | 2 | Low | 1 |
| 11 | KPICard | 4×3×2 | 2 | Medium | 1 |
| 12 | Modal | 4×2×2 | 2 | Medium | 1 |
| 13 | SearchInput | 3×3 | 3 | Medium | 1 |
| 14 | Accordion | 2 | 2 | Low | 1 |
| 15 | EmptyState | 2 | 2 | Low | 1 |
| 16 | Skeleton | 4 | 1 | Low | 1 |
| 17 | OPSRing | 4×3 | 1 | High | 1 |
| 18 | TierBadge | 5×2 | 1 | Medium | 1 |
| 19 | StreakBadge | 3 | 1 | Medium | 1 |
| 20 | DataTable | 4×2 | 4 | High | 1 |
| 21 | FileUpload | 5 | 5 | High | 1 |
| 22 | NotificationBell | 2 | 2 | Medium | 1 |
| 23 | ChildSwitcher | 3 | 3 | Medium | 1 |
| 24 | CredentialCard | 2 | 2 | Medium | 1 |
| 25 | SessionCard | 3×3 | 1 | Medium | 1 |
| 26 | GoalCard | 2 | 1 | Low | 1 |
| 27 | InvoiceCard | 7 | 1 | Medium | 1 |
| 28 | Timeline | 2 | 1 | Low | 1 |
| 29 | Calendar | 2 | 1 | High | 1 |
| 30 | QuestionBuilder | 9 | 1 | Very High | 3 |
| 31 | Classroom | 2 | 1 | High | 3 |
| 32 | PaystackButton | 4 | 4 | Medium | 6 |
| 33 | DigestCard | 2 | 1 | Low | 7 |