` element with `text-lg lg:text-xl leading-relaxed` containing `wp_kses_post( $intro )`. + +No new fields, no new CSS file — Tailwind utilities cover the layout. + +## page.php Wiring + +`page.php` changes from rendering the body directly to: + +1. Output the article container (existing behavior). +2. If `get_field( 'intro' )` is non-empty, call `get_template_part( 'views/partials/page-intro' )`. +3. Render `the_content` (existing behavior). +4. Render the sidebar if `hasSidebar()` (existing behavior). + +The hero is still rendered by `header.php` before this template runs. No other behavior changes. + +## Data Flow + +- Editor experience: on every page (and post) edit screen, the existing Page Heading meta box shows the existing fields plus two new ones (Hero Image, Vector). The editor uploads the assets, sets a background color if desired, writes the optional heading override, intro, and CTAs, then writes the body in the standard block editor. +- Render: `header.php` loads the page-hero partial → `page.php` loads the page-intro partial (if intro is set) → `the_content` renders the body blocks. +- Per-page variation: hero image, vector, intro text, and body content. Everything else is shared. + +## Error Handling and Edge Cases + +- `hero_image` empty → hero uses the existing dark background color (or the default dark text-only style). +- `hero_vector` empty → no vector renders; the right side of the hero is empty space. +- `intro` empty → page-intro partial is not loaded; the page goes straight from hero to body. +- `heading` empty → falls back to `getTheTitle()` (existing behavior, unchanged). +- Background color set without a hero image → existing behavior; no change. +- No sidebar field set → existing `hasSidebar()` filter returns false → no sidebar (existing behavior). +- Lazy-loaded images must await `load`/`complete` before Playwright reads dimensions (existing project convention; see `tests/mobile-homepage.spec.js:641`). + +## Out of Scope + +- New ACF blocks. This layout uses the existing Page Heading meta box, not the block editor. +- Front page, single posts, archives, search, 404 changes. +- Homepage-hero block changes. +- The contact-block, pull-quote, our-work, or other existing blocks. +- A new contact CTA block in the page body. The mockup's bottom dark block is the existing site footer. +- Migration of existing pages' content. + +## Verification + +- Add `tests/inner-page.spec.js` covering: + - Desktop (1280px): hero, intro, body render in that order. When hero image is set, it is visible behind the hero. When vector is set, it sits on the right of the hero. + - Mobile (402px): same order. Vector fills the lower portion of the hero. Intro is centered and within the 48rem max-width. No clipped text. + - 320px and 767px: nothing clips, vector scales proportionally, intro remains readable. + - A page with no `intro` field renders hero + body with no empty intro wrapper. + - A page with no `hero_image` and no `hero_vector` renders the existing dark text-only hero unchanged. +- Add a test page fixture (or use an existing page) to drive the test. If no fixture exists, the test seeds a page in a `beforeAll` and tears it down in `afterAll`. +- Run `npm run build` to regenerate `static/dist/`. +- Run the full Playwright suite (`npx playwright test`) — including the existing `tests/mobile-homepage.spec.js` and `tests/site-a11y.spec.js` — to confirm no regressions. +- Run `composer lint` to catch PHPCS issues. +- Capture a 1280px and a 402px full-page screenshot of the test fixture for visual comparison against `notes/inner-page-mockup.png`. + +## Acceptance Criteria + +1. Every WordPress page renders the new layout when the page-hero partial is active. +2. The hero shows the page title (or heading override) and, when supplied, a background image and a decorative vector on the right. +3. When the `intro` field is set, a centered narrow column appears under the hero. When empty, it is omitted entirely (no empty wrapper). +4. The body renders `the_content` as before, with the standard block editor. +5. The hero background image is masked so text on the left remains readable at all viewports. +6. The vector scales proportionally from 320px through desktop and is repositioned below 768px to fill the lower portion of the hero. +7. The page renders without console errors, axe violations, or PHPCS errors. +8. Existing single posts, archives, search, and 404 pages render the page-hero partial unchanged. +9. Existing tests (`mobile-homepage`, `site-a11y`) continue to pass.