# BW Pricing Card — Claude Development Guide

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

## What this plugin does

Ships a single Gutenberg block (`bw/pricing-card`) that renders a 3-up pricing tier section. Cards wrap to a new row after the third. Each card has inline-editable RichText for the tier label, price, description, every feature item, and the button. Sidebar controls cover button URL, one of four button-style presets (Fill / Theme / Secondary / Outline Base), the Most Popular toggle, and add/remove/reorder for both cards and feature items.

## Before making changes

1. Read `docs/SESSION-LOG.md` for recent context.
2. Read `docs/HANDOFF-NOTES.md` for any pending async messages.
3. Read `docs/SPEC.md` for current requirements.
4. Check `docs/KNOWN-ISSUES.md` for active bugs and workarounds.

## Versioning

- Patch (X.Y.Z): bug fix / small iteration.
- Minor (X.Y.0): new feature / task completion.
- Major (X.0.0): breaking change.

Every bump must update all four: plugin header, `BW_PRICING_CARD_VERSION` constant, `CHANGELOG.md`, this file's header.

## Architecture Quick Reference

- Main file: `bw-pricing-card.php` (plugin header + block registration, stays thin)
- Block source: `blocks/bw-pricing-card/`
  - `block.json` — manifest, attributes (cards array + popularLabel)
  - `index.js` — editor UI using `window.wp` globals (no build step). Inline RichText for text fields, `InspectorControls` for structural fields (URL, style, popular, move, remove).
  - `index.asset.php` — declares script dependencies
  - `render.php` — server-side render. RichText fields go through `wp_kses()` (not `esc_html()`) to avoid double-encoding entities like `&amp;`.
  - `style.css` — frontend + editor shared visual rules. Design tokens scoped to `.bw-pricing-card`.
  - `editor.css` — editor-only chrome (add-card placeholder, item-row remove icon).
- Docs: `docs/`

## Conventions

- **No JS build step.** Editor code uses plain ES5-compatible JS against `window.wp.*` globals so the plugin is copy-deployable to any WP site without npm.
- **Button styles are a closed enum** (`fill-base` / `theme-base` / `secondary-base` / `outline-base`) — whitelisted server-side in `render.php` against an array, never trusted directly when building class lists.
- **Text content flows through `wp_kses()`** with a strict allowlist:
  - Tier, price, button text: `array()` — strips all tags, preserves entities.
  - Description, feature items: `array( 'em' => array(), 'strong' => array(), 'b' => array(), 'i' => array() )` — light emphasis only.
- **List padding-left lockdown.** `.bw-pricing-card__list` uses chained-class specificity plus `!important` on `padding-left`, `padding-inline-start`, `margin-left`, `margin-inline-start` to beat parent-theme `ul` defaults (Kadence sets `padding-inline-start` on `.entry-content ul`).
- **Description margin-bottom** also uses the chained-class + `!important` pattern to beat the theme's default `p` margin.

## Never

- Edit `vendor/` (third-party code).
- Commit secrets.
- Release with debug cruft present.
- Release with mismatched version numbers.
