# ACF Field Translation Master–Detail Redesign

Audience: AI coding agents first.

## Goal
Replace accordion-first ACF page with responsive master–detail workspace. Use compact field-group cards for navigation and structured rows for individual fields. Preserve hierarchy, policy meaning, accessibility, layered cached loading, and exact working context through reconciliation.

## Scope
Modify ACF Fields route only. Preserve existing translation-policy model, REST routes, browser cache, WordPress database cache, and mutation behavior. Do NOT add field creation, drag-and-drop, decorative analytics, new cache service, or unrelated admin refactors.

## Architecture

### Page shell
`FieldsTranslatePage` remains route owner and canonical store consumer.

Responsibilities:
- synchronously render layout-shaped skeleton on cold load;
- paint valid memory/localStorage snapshot immediately;
- reconcile REST/plugin-cache results by stable ACF keys;
- retain last valid content on refresh failure;
- own route-level state and cleanup.

### Master pane
`FieldGroupNavigation` behavior:
- width near 320px on wide screens; 260–300px on medium screens;
- immediate client-side search over title, group key, location labels, and descendant field metadata;
- only reliable filters: All and Custom overrides; add Needs review only if current response provides a truthful derivation;
- compact selectable cards show title, field count, location summary, inherited/override summary, and warning state when supported;
- selection uses real buttons with list semantics and `aria-current="true"`;
- Arrow keys move focus; Enter/Space select;
- selected state uses marker, border, and background—not color alone;
- no per-card action clutter, descriptions, illustrations, or individual-field cards.

### Detail pane
`FieldGroupDetail` behavior:
- selected group header shows title, key, field count, location summary, and policy summary;
- separate field search covers label, name, key, and type;
- filters expose only states derivable from current graph: All and Overrides; unsupported/read-only only when metadata is reliable;
- semantic table or structured row list shows Field, Type, Source, Translation mode, and Status;
- field key/name remain visible as secondary technical identity;
- existing per-field immediate-save contract remains authoritative;
- do NOT expose unsupported reference-image controls such as Add Field, pagination, or bulk action until corresponding product/API behavior exists.

### Hierarchy
Use stable ACF keys for every group, field, layout, disclosure, focus, and reconciliation identity.

Disclosure behavior:
- repeaters, groups, flexible-content fields, layouts, and descendants preserve depth;
- parent/layout rows remain visually distinct;
- layout-only rows without policy are read-only;
- closed branches do not mount descendant controls;
- repeated labels never determine identity;
- disclosures use buttons with `aria-expanded` and `aria-controls`.

### State contract
Preserve during route lifetime and revalidation:
- selected group;
- master search and filter;
- detail search and filter;
- open hierarchy keys;
- group-list scroll;
- detail/document scroll;
- logical focus target.

Represent selected group in URL query state:
`#/translations/fields?group=<stable-acf-group-key>`

URL behavior:
- valid URL selection wins on initial route entry;
- selection updates history without full navigation;
- Back/Forward restores selection;
- invalid/disappeared key selects nearest valid group when possible and announces change;
- narrow view returns to group list when no valid detail remains.

Do NOT persist saving flags, transient errors, dialogs, nonces, or live data.

### Responsive contract
- Wide: persistent two-pane workspace, max width near 1440px, 20–24px gap, detail visually dominant.
- Medium: narrower master; hide secondary card metadata before shrinking field controls; field table may scroll within its own overflow wrapper.
- Narrow: drill-in flow. Show group list first; selection opens detail; detail includes “Back to field groups”; returning restores master search and scroll. Do NOT stack full master above full detail.

### Cache and reconciliation contract
Keep existing layered sequence:
1. route-shaped skeleton;
2. valid browser snapshot immediate paint;
3. REST request;
4. plugin database snapshot response when available;
5. newer response reconciled in place;
6. background source refresh;
7. stable-key patch;
8. cache layers update.

Revalidation MUST NOT rebuild page, close disclosures, clear searches, change valid selection, reset scroll/focus, or overwrite an in-progress edit.

Current cache partitioning/invalidation remains unchanged unless verification finds a direct acceptance gap. No new cache subsystem.

### Mutation contract
Per-field policy changes remain immediate and serialized by field key:
1. apply visible value;
2. mark row saving;
3. submit current PATCH route;
4. success announces saved, invalidates relevant cache tag/generation, and revalidates;
5. failure restores prior value, announces error, and retains selection/hierarchy/search/focus/scroll;
6. duplicate submission for same field is blocked while saving.

Use existing real policy vocabulary and available choices. Show inherited versus explicit source directly. Never invent modes or expose invalid choices.

## Empty, loading, and error states
- Cold load: two-pane skeleton matching final dimensions; reduced/no animation under reduced-motion.
- ACF unavailable: explanatory unavailable state, no broken navigation.
- No groups: clear empty state, no empty table.
- Master search empty: include query and clear-search action.
- Detail search empty: selected group remains visible with clear-search action.
- Cached refresh failure: retain content and show non-blocking “Showing saved data. The latest refresh could not be completed.” Retry only when bounded and useful.
- Cold failure: alert region and retry; never endless skeleton.

## Accessibility
- semantic page headings, navigation/list, and table/structured-list roles;
- real buttons for cards, disclosures, Back, and actions;
- `aria-current`, `aria-expanded`, `aria-controls`, labels, captions, and live regions;
- visible `:focus-visible`; selected/status meaning not color-only;
- predictable keyboard selection and navigation;
- preserve focus by stable key; missing focused field falls back to owning disclosure or group heading;
- WCAG AA contrast, practical 44px touch targets, reduced motion, existing theme-driven dark mode.

## Visual system
Use existing admin design tokens, typography, controls, badges, spacing, borders, and dark-mode controller. Keep elevation subtle. Never use inline CSS or hard-coded colors. Detail pane has stronger visual priority. Motion limited to short state transitions.

## Performance
- skeleton synchronously appears;
- valid browser snapshot paints before network;
- plugin-cache hit suppresses source execution under existing policy;
- closed hierarchy branches avoid descendant control mounting;
- searches remain responsive over large graphs;
- refresh patches keyed nodes;
- no request per field;
- all listeners, observers, timers, subscriptions, and abort controllers clean up on route exit.

## Verification

### Focused JS tests
Prove group selection, URL/history restoration, stable key identity, separate searches/filters, nested disclosures, inherited/override display, read-only rows, save success, rollback, cache invalidation, state retention during revalidation, and cleanup.

### Existing cache tests
Run current cache-policy/service suite. Add cache coverage only for an acceptance behavior not already proven. Do NOT duplicate established exhaustive cache tests in UI redesign work.

### Browser verification
Use approved remote browser path against local WordPress. Prove desktop master–detail, narrow drill-in/back, skeleton/cached transition, URL/history selection, keyboard behavior, nested disclosures, save success/rollback where safely testable, focus/scroll retention, no runtime errors, and accessibility in Chromium and Firefox.

Capture before and after screenshots. Compare concrete layout and computed styles to supplied reference rather than claiming visual similarity from code inspection.

## Data contract additions
Extend the existing ACF fields response rather than creating a route:
- each group includes normalized `locations: Array<{ label: string, ruleCount: number }>` derived from ACF location rules;
- each flexible-content layout includes its native ACF `key` when available;
- legacy layouts without a key use deterministic identity `layout:<parent-field-key>:<layout-name>`;
- changing these shapes increments the existing ACF-fields cache schema/version and updates controller contract tests.

Location search and summaries use only normalized `locations`. Override counts recursively include editable descendant fields whose explicit policy differs from inheritance; layout-only/read-only nodes never count. “Custom overrides” means recursive override count greater than zero. Do not show Needs review, warnings, or unsupported filters unless a concrete response predicate is added and tested.

## Routing contract
Update the hash router to parse route path and query separately. `#/translations/fields?group=<key>` resolves to the existing Fields page. Within the mounted Fields route:
- card selection pushes history;
- Back/Forward updates selection without destroying the page instance;
- reconciliation fallback corrects URL with replace history;
- unrelated route changes retain current teardown behavior.

No URL key selects first group on wide/medium screens. Narrow screens start in the group list unless URL names a valid group. If selected group disappears, choose the group at the same previous index, then previous final item when index exceeds length, then first group. Announce fallback.

## Deterministic interface behavior
- Preserve current global mutation queue and global control lock. Do not introduce concurrent mutation semantics in this redesign.
- Global default stays in page header with override explanation.
- Use existing admin responsive breakpoint tokens; narrow drill-in begins at the existing mobile breakpoint. Document owns detail vertical scroll at every size; table wrapper alone may scroll horizontally.
- If selected group is hidden by master filter/search, retain selection and show a clear “selected group is hidden” affordance in the master pane rather than changing it.
- Focus fallback order: exact stable field key → nearest owning disclosure → selected group heading → master pane heading.
- Cached refresh notice persists while the current refresh error exists and clears after successful refresh or explicit retry.
- Skeleton MUST render both master-card and detail-row placeholders.
- Visual comparison source is `/home/user/.claude/image-cache/d48c7b7a-60b2-460d-92b1-7567807256fb/1.png`.

## Architecture Decisions
- Reuse `FieldsTranslatePage`, `DataRegion`, and existing `acf-fields:all` store unless a demonstrated acceptance gap requires otherwise.
- Extract UI units only where current file size and independent behavior warrant it; do not create decorative wrappers.
- Use button-list semantics rather than ARIA listbox. Cards trigger view selection, not value selection; native button behavior is deeper and less error-prone.
- Use URL query selection because stable identity, bookmarking, refresh, and history are explicit requirements.
- Use mobile drill-in, not stacked panes, to preserve orientation and avoid excessive scrolling.
- Limit filters/actions to exact tested response predicates. Reference-image controls without behavior are explicitly excluded.
