> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pcm.game/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementation plan 18.1

# Implementation Plan 18.1: Crucible UI & Combat Loop Integration

This document outlines the comprehensive technical design and step-by-step implementation plan to resolve all accumulated UI/UX cosmetic issues, layout debt, and critical combat loop state bugs identified during the Sprint 18 E2E Sandbox Crucible runs.

***

## 📋 Architectural Context & Objectives

All fixes must adhere to the core guidelines established in Sprint 13 & 14:

* **Zero-Hardcoding Policy**: No physical JSON files or hardcoded credentials. Rely entirely on environment-injected Base64 service accounts.
* **Deterministic State Machine**: Ensure the frontend remains an exact, deterministic mirror of the synced backend state, specifically avoiding unauthorized intermediate terminal states (e.g., preserving `RESOLVED` as the terminal state).
* **Anti-Meta Rules**: The core spatial coordinates (vectors) of the central Target News Stub must remain 100% air-gapped from the player to prevent client-side meta-gaming.

***

## 🛠️ Proposed Changes

### Phase A: The Arena & Compass Overhaul

This phase refactors the Faction Selection lobby and general user navigation shell to align with the political compass and correct terminology.

#### 1. Faction Selection 2x2 Grid Layout

* **File**: `frontend/app/arena/page.tsx`
* **Target**: Refactor the container element rendering the list of available factions.
* **Design**:
  * Utilize CSS Grid with `grid-cols-2 grid-rows-2` to represent the classic Political Compass.
  * Enforce the canonical ordering:
    * **Top-Left**: `AUTH_LEFT` (Authoritarian Left / Red / Labor)
    * **Top-Right**: `AUTH_RIGHT` (Authoritarian Right / Blue / Dinars)
    * **Bottom-Left**: `LIB_LEFT` (Libertarian Left / Green / Pronouns)
    * **Bottom-Right**: `LIB_RIGHT` (Libertarian Right / Yellow / Monke)

#### 2. Faction Selection UI Overlap & Label Copy

* **File**: `frontend/app/arena/page.tsx`
* **Target**: Update the overlay text and layout for the selected faction.
* **Design**:
  * Replace the confusing `"LOCKED"` text badge with `"SELECTED"`.
  * Fix absolute positioning and set `z-index` values so the text badge sits cleanly below or inside a defined action frame without overlapping the faction's primary SVG emblem or icon.

#### 3. Pill Box Placement Relocation

* **File**: `frontend/app/arena/page.tsx`
* **Target**: Completely remove the `"Pill Box"` tracking indicator and container from the Arena Entryway / Faction Selection page.
* **Rationale**: The Pill Box tracking belongs strictly inside the user's personal `/bunker` and during active play in `/arena/[lobbyId]`. Its presence in the entryway creates visual clutter.

#### 4. Deck Stats Terminology Alignment

* **File**: `frontend/app/arena/page.tsx`
* **Target**: Rename core deck statistics text labels to clarify their gameplay impact.
* **Changes**:
  * Rename `MAGNITUDE` to `Vector Impact` (representing the raw power to push the coordinates).
  * Rename `RESILIENCE` to `Coordinate Defense` (representing the defense rating to resist coordinate shifts).
  * Update any localized help-text, tooltips, or descriptions to maintain semantic alignment.

***

### Phase B: The Radial Combat Layout

This phase re-architects the primary screen layout of the active game board into a geographic 2x2 grid matching the Political Compass Meme style.

* **File**: `frontend/app/arena/[lobbyId]/page.tsx`
* **Current Layout**: A landscape split dividing the viewport into a Left Column (Target Vector / HUD) and a Right Column (Contender Vectors horizontal row).
* **Refactored Layout**:
  * Re-architect the combat zone into a nested CSS Grid or absolute container representing the 2x2 Political Compass quadrant structure.
  * **Center**: Place the **Active News Stub** in the dead center of the 2x2 arena grid (applying absolute centering `top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-30`).
  * **Four Corners**: Place the four **Contender Slots** in their respective geographic positions:
    * **Top-Left**: Player aligned with Authoritarian Left.
    * **Top-Right**: Player aligned with Authoritarian Right.
    * **Bottom-Left**: Player aligned with Libertarian Left.
    * **Bottom-Right**: Player aligned with Libertarian Right.
  * **Connecting Rays**: Render modern CSS neon lines or micro-animations extending from the center News Stub out to each contender slot to visually represent the radial "Euclidean pull" on the news vector.
  * **Copy Update**: Change the label `"Active Target Vector"` above the central card to `"Active News Stub"`.

***

### Phase C: Anti-Meta & Stacking Mechanics

This phase secures target card coordinates and fixes selection logic to allow proper item stack builds.

#### 1. News Stub Vector Leak Shield (Anti-Meta Air-Gap)

* **File**: `frontend/components/NewsCard.tsx` & `frontend/app/arena/[lobbyId]/page.tsx`
* **Target**: Add a conditional parameter to the `NewsCard` component to enforce hiding of the coordinate grid.
* **Fix**:
  * Introduce an optional prop: `hideVectorMap?: boolean`.
  * In `NewsCard.tsx`, if `hideVectorMap` is `true`, replace the `CARD FOOTER` (the X/Y grid and green blip radar) with a stylized dark aesthetic block or a generic watermark, fully preventing vector coordinates from rendering on the client.
  * In `frontend/app/arena/[lobbyId]/page.tsx`, ensure `<NewsCard {...tableState.targetVector} />` is explicitly passed `hideVectorMap={true}`.

#### 2. Phantom Item Cards & Combo Stacking Fix

* **File**: `frontend/components/PlayerHand.tsx` & `frontend/lib/cardUtils.ts`
* **Target**: Ensure modifier card clicks append to the `selectedCardIds` React state and feed correctly into the projected coordinates math.
* **Diagnostics**:
  * Item cards in the user's hand may fail to toggle selection if the card metadata does not strictly match the `'ITEM'` string format or if case insensitivity is not handled.
  * **Fix**:
    * Update `getCardType` in `cardUtils.ts` to execute a `.toUpperCase()` comparison on `card.cardType` to handle lowercase anomalies gracefully.
    * Ensure that clicking an Item card (when a Core Meme card is already active) correctly appends its ID to `selectedCardIds` inside `PlayerHand.tsx:handleCardClick`.
    * Enforce that the staged 3D stack correctly overlays the active `modifierCards` in a staggered stack behind the base `Meme` card.
    * Enforce that the projected vector calculations (`calculateProjectedVector` in `cardUtils.ts`) recalculate immediately, updating the **Tactical HUD** preview values upon selection changes.

***

### Phase D: The Resolution Animation

This phase fixes a state-sync race condition that prevents the 3D SVG isometric vector animation from showing.

* **File**: `frontend/app/arena/[lobbyId]/page.tsx`
* **Diagnosis**:
  * The `useEffect` that triggers `isAnimatingMath` to `true` listens *only* to `tableState?.status === 'RESOLVING'`.
  * Because the backend processes resolution instantly, the synced Firestore state transitions from `'DEBATE_PHASE'` directly to `'RESOLVED'` in a single tick.
  * The transient `'RESOLVING'` status is completely skipped by the React state observer, leaving `isAnimatingMath` as `false`. The overlay is bypassed entirely, depriving players of the visual feedback.
* **Fix**:
  * Introduce a round-tracking state hook on the page: `const [lastAnimatedRound, setLastAnimatedRound] = useState<number>(-1);`.
  * Refactor the triggering `useEffect` to listen to BOTH `'RESOLVING'` and `'RESOLVED'` statuses:
    ```typescript theme={null}
    useEffect(() => {
        const currentRound = tableState?.roundNumber ?? 0;
        const isResolutionState = tableState?.status === 'RESOLVING' || tableState?.status === 'RESOLVED';
        
        if (isResolutionState && currentRound > lastAnimatedRound) {
            setIsAnimatingMath(true);
            setLastAnimatedRound(currentRound);
        }
    }, [tableState?.status, tableState?.roundNumber, lastAnimatedRound]);
    ```
  * This ensures that upon entering a resolved phase of a new round, the visual overlay is guaranteed to mount, execute the 4-second SVG Euclidean sweep animation, and gracefully transition to the resolution board only after `onAnimationComplete` fires.

***

## 🧪 Verification Plan

### Automated Verification

Run integration tests in `backend` and `frontend` to verify that states resolve correctly and that prisma queries remain intact:

```bash theme={null}
cd backend && npm run test
```

### Manual Visual Verification Flow

1. **Lobby Creation**: Open `/arena`, choose a faction, and select a deck. Verify the 2x2 grid ordering matches the Compass (AuthLeft top-left, etc.), that `LOCKED` is replaced with `SELECTED` with clean margins, and that the Pill Box is absent.
2. **Tactical Selection**: Select a base card and multiple item modifier cards. Verify that items visually stack behind the base card and that projected coordinates in the HUD update instantly.
3. **News Stub Coords Shield**: Inspect the central News Stub card. Verify that its coordinate map at the bottom is completely invisible (grid hidden).
4. **Resolution Transition**: Play cards, allow the timer to expire, and verify that the `MathResolutionOverlay` sweeps, plots vectors, and completes its full 4-second SVG animation before revealing the post-match summary.
