## Why

When an admin creates a lunch menu and sends a `custom_items` entry whose name matches an existing lunch item (case-insensitive, trimmed), the API reuses the existing item but silently ignores the `price` sent in the request. The item keeps its old price, so once a dish changes price, employees still see — and are charged — the old price on new menus.

## What Changes

- `POST /api/v1/admin/lunch-menus`: when a `custom_items` entry matches an existing lunch item and carries a non-null `price`, update that item's `price` to the new value.
- When a matching `custom_items` entry has `price` omitted or `null`, keep the existing item's price (do NOT reset it to `default_item_price`).
- New items (no name match) keep current behavior: created with `price ?? default_item_price`.
- New validation: if the same request contains two or more `custom_items` entries with the same normalized name (`lower(trim(name))`) but different prices, reject the request with a 422 validation error.
- Item creation, price updates and menu creation run in one DB transaction so a failed request does not leave item prices changed.

Out of scope: `items[{id}]` payload (carries no price, unchanged), the update-menu endpoint, and per-menu pricing.

## Capabilities

### New Capabilities
- `lunch-menu-custom-item-pricing`: How `custom_items` sent when creating a lunch menu are matched against existing lunch items and how their price is applied.

### Modified Capabilities

## Impact

- Code: `packages/w3suga/lunch-ordering/src/Http/Controllers/LunchMenuController.php` (`store()`), plus its OpenAPI annotation for `custom_items.price`.
- Data: `lunch_items.price` is now updated by menu creation. The price is global, so other open menus containing the same item will charge the new price for orders placed afterwards; existing orders keep their snapshotted `lunch_orders.price`.
- API: requests with conflicting duplicate `custom_items` that were previously accepted now return 422.
- No migrations, no new dependencies.
