# BW Pricing Card — Specification

**Version:** 0.1.0 | **Last Updated:** 2026-04-28

## Purpose

Provide a reusable Gutenberg block for a 3-up pricing tier section — a common landing-page pattern used on event registration, SaaS pricing, and membership pages. Marketing staff can drop the block into any page, edit text directly on each card, and use simple sidebar toggles to mark a card "Most Popular" or pick one of four customizer-aware button styles. Cards wrap automatically to a new row after the third, so authors can add as many tiers as they need.

## Requirements

### Functional
- **R1:** Registers a Gutenberg block named `bw/pricing-card` under the "Design" category.
- **R2:** Stores cards as an array attribute (`cards`). Default seeds three tiers (Early Bird / General Admission / Team of 5+).
- **R3:** Cards display three per row at viewports ≥ 900px and wrap to a new row after the third (CSS Grid `repeat(3, 1fr)`).
- **R4:** Each card has inline-RichText fields for: tier label, price, description, every feature item, and button text.
- **R5:** Per-card sidebar panel exposes structural fields only: button URL, button style (enum), Most Popular toggle, move up/down, remove card.
- **R6:** General sidebar panel exposes: Most Popular ribbon label and global "Add card" button.
- **R7:** Add / remove feature items inline via per-row X icons (visible on hover/focus) and an "Add feature" button below each list.
- **R8:** A dashed `+ Add card` placeholder tile appears at the end of the grid in the editor only, for one-click card creation.
- **R9:** Most Popular variant applies the spec border (`2px solid var(--pv-teal-dk)`) plus a gradient ribbon at the top of the card. Default (non-popular) uses `1.5px solid var(--pv-line)`.
- **R10:** Button style is a closed enum: `fill-base`, `theme-base`, `secondary-base`, `outline-base`. Each maps to a CSS modifier class; styles are intended to be customized to match the theme's customizer button presets.
- **R11:** No JavaScript build step — editor code runs directly against `window.wp.*` globals.

### Non-functional
- WordPress 6.0+ with PHP 7.4+
- Follows WordPress security best practices (output filtered via `wp_kses` for RichText, `esc_attr` / `esc_url` for attributes/URLs, `enum` whitelist for style class)
- Translatable via `bw-pricing-card` text domain
- Does not interfere with other plugins (no global CSS, no hooks on other blocks' attributes — design tokens scoped to `.bw-pricing-card`)

## Acceptance Criteria

| Requirement | Acceptance | Status |
|---|---|---|
| R1  | Block appears in inserter under Design category | ☐ |
| R2  | Three default cards render on a freshly inserted block | ☐ |
| R3  | At ≥ 900px the 4th card wraps onto a new row directly under the 1st | ☐ |
| R4  | Click into any card field, type, save → text persists across reload | ☐ |
| R5  | Sidebar per-card panel exposes only structural fields | ☐ |
| R6  | Editing the ribbon label in General updates every popular card | ☐ |
| R7  | Add / remove feature items works without breaking other cards | ☐ |
| R8  | `+ Add card` placeholder appears at end of grid in editor only | ☐ |
| R9  | Toggling Most Popular swaps to teal border + ribbon | ☐ |
| R10 | All four button-style classes apply distinct CSS variants | ☐ |
| R11 | Plugin activates cleanly on a vanilla WP with no build/bundler present | ☐ |
