# Pricing Toggle Design

**Date:** 2025-12-15
**Branch:** `feature/pricing-toggle`
**Status:** Approved

## Overview

Add a monthly/yearly billing toggle to the marketing homepage (`public/index.html`) so visitors can view pricing for both billing periods before signing up.

## Requirements

- Toggle between Monthly and Yearly pricing display
- No annual discount (prices are equivalent: annual = monthly × 12)
- Starter tier is annual-only; other tiers support both
- Marketing homepage only (dashboard already handles this)

## Design

### Toggle Component

**Location:** Below the pricing header, after "Choose the plan that meets your needs"

**HTML Structure:**

```html
<div class="pricing-header">
  <span class="eyebrow">Plans</span>
  <h2 id="pricing-heading">Choose the plan that meets your needs</h2>

  <div class="billing-toggle" role="radiogroup" aria-label="Billing period">
    <button role="radio" aria-checked="false" data-interval="monthly">Monthly</button>
    <span class="toggle-separator" aria-hidden="true">·</span>
    <button role="radio" aria-checked="true" data-interval="yearly">Yearly</button>
  </div>
</div>
```

**Visual Styling:**

- Follows existing `.eyebrow` pattern: `letter-spacing: 0.16em`, `text-transform: uppercase`
- Active state: `#38bdf8` cyan, `font-weight: 600`
- Inactive state: `rgba(148, 163, 184, 0.7)` muted slate
- Hover on inactive: subtle cyan underline
- Separator: `rgba(148, 163, 184, 0.5)`
- Gap between elements: `1rem`

**Default state:** "Yearly" selected

### Pricing Card Behavior

**When "Yearly" is selected (default):**

| Tier         | Price Display                   |
| ------------ | ------------------------------- |
| Starter      | $4.00 / month (billed annually) |
| Growth       | $25 / month (billed annually)   |
| Enhanced     | $50 / month (billed annually)   |
| Professional | $200 / month (billed annually)  |

**When "Monthly" is selected:**

| Tier         | Price Display                   | Visual State                                 |
| ------------ | ------------------------------- | -------------------------------------------- |
| Starter      | $4.00 / month (billed annually) | Dimmed (`opacity: 0.5`), "Annual only" badge |
| Growth       | $25 / month                     | Normal                                       |
| Enhanced     | $50 / month                     | Normal (keeps highlight)                     |
| Professional | $200 / month                    | Normal                                       |

### Starter Card Disabled State

When Monthly is selected:

- Card opacity reduced to `0.5`
- "Annual only" badge appears in top-right corner
- Badge styling: `background: rgba(148, 163, 184, 0.2)`, `color: rgba(148, 163, 184, 0.9)`
- Transition: `opacity 0.2s ease`

### JavaScript Behavior

Vanilla JS (no dependencies) for static HTML compatibility:

1. Toggle click updates `aria-checked` on both buttons
2. Toggle `.active` class for styling
3. Update pricing text in Growth/Enhanced/Professional cards
4. Toggle `.pricing-card--disabled` class on Starter
5. Show/hide "Annual only" badge on Starter

**Data attributes on cards:**

```html
<article class="pricing-card" data-tier="growth">
  <p class="pricing-amount" data-monthly="$25" data-yearly="$25 / month (billed annually)">...</p>
</article>
```

### Accessibility

- `role="radiogroup"` on toggle container
- `role="radio"` + `aria-checked` on toggle buttons
- Keyboard navigation: Arrow keys, Enter, Space
- Focus visible: `outline: 2px solid #38bdf8`
- Screen reader announces billing period change

## CSS Additions

```css
.billing-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 1rem;
}

.billing-toggle button {
  background: none;
  border: none;
  color: rgba(148, 163, 184, 0.7);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 0.25rem 0;
  border-bottom: 2px solid transparent;
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}

.billing-toggle button:hover {
  color: rgba(56, 189, 248, 0.8);
  border-bottom-color: rgba(56, 189, 248, 0.3);
}

.billing-toggle button.active,
.billing-toggle button[aria-checked='true'] {
  color: #38bdf8;
  font-weight: 600;
}

.billing-toggle button:focus-visible {
  outline: 2px solid #38bdf8;
  outline-offset: 2px;
}

.toggle-separator {
  color: rgba(148, 163, 184, 0.5);
  font-size: 0.85rem;
}

.pricing-card--disabled {
  opacity: 0.5;
  transition: opacity 0.2s ease;
}

.annual-only-badge {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  background: rgba(148, 163, 184, 0.2);
  color: rgba(148, 163, 184, 0.9);
  font-weight: 600;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
```

## Files to Modify

| File                | Changes                      |
| ------------------- | ---------------------------- |
| `public/index.html` | Add toggle HTML, CSS, and JS |

## Out of Scope

- Annual discount pricing
- Dashboard changes (already has toggle in upgrade modal)
- Stripe checkout flow changes (handled by existing interval selection)
