# Card UI Standardization ## Goal Make every card-shaped UI use the same input structure so hover tooltip, click, drag, and future interactions behave the same way everywhere. Target surfaces: - hand cards - reward cards - shop cards - draw pile / discard pile / exhaust pile viewer cards - all deck / class deck / codex cards ## Standard Card Entity Shape Each visible card should have one root entity that owns input. ```text CardRoot - UITransformComponent - SpriteGUIRendererComponent - ButtonComponent - UITouchReceiveComponent - Cost - Name - Desc - Art ``` Rules: 1. `CardRoot` covers the full card rect. 2. `CardRoot` owns both click and hover. 3. Child entities are display only. 4. Child entities must not become the primary input target. ## Required Component Rules ### Card root - `UITransformComponent` - `SpriteGUIRendererComponent` - `ButtonComponent` - `UITouchReceiveComponent` Recommended sprite settings: - `RaycastTarget: true` - card frame sprite on root ### Card children - `Cost`, `Name`, `Desc`: text only - `Art`: sprite only Recommended child sprite settings: - `RaycastTarget: false` That keeps hover/click ownership on the root card entity. ## Path Rules Use the same path naming pattern everywhere: - hand: `/ui/.../CardHand/Card1` - reward: `/ui/.../RewardHud/Reward1` - shop: `/ui/.../ShopHud/Card1` - inspect: `/ui/.../DeckInspectHud/Grid/Card1` - all deck: `/ui/.../DeckAllHud/Grid/Card1` The important part is that each list has a stable root card path ending in a numeric slot. That lets controller code resolve hover target -> slot -> card id without special cases. ## Controller Rules Once UI is standardized, controller logic should follow this shape: 1. Resolve `path` 2. Resolve `slot` from `path` 3. Resolve `cardId` from current backing list 4. Show tooltip from `cardId` Preferred shared methods: - `GetHoveredCardId(path)` - `HoverCardByPath(path)` - `UnhoverCardByPath(path)` The hand should just become one caller of the same shared path-based hover logic rather than having its own special tooltip flow. ## Safe Rollout Order Do not standardize every card surface at once. ### Step 1 Document current structures for: - `RewardHud/Reward1` - `ShopHud/Card1` - `DeckInspectHud/Grid/Card1` - `DeckAllHud/Grid/Card1` ### Step 2 Make `DeckInspectHud/Grid/CardN` match `RewardHud/RewardN` component structure. ### Step 3 Verify game boot and UI load before changing controller hover bindings. ### Step 4 Make `DeckAllHud/Grid/CardN` match the same structure. ### Step 5 After both surfaces are stable, bind hover events in controller code. ## Validation Checklist Before testing hover behavior: - game boots with no `LEA-3015 CannotLoad` - `DefaultGroup.ui` loads cleanly - card roots exist at expected paths - root card sprite has `RaycastTarget: true` - child art sprite has `RaycastTarget: false` - root has both `ButtonComponent` and `UITouchReceiveComponent` After binding hover: - hand tooltip still works - reward tooltip still works - shop tooltip still works - inspect tooltip works - all deck tooltip works - no duplicated tooltip flicker - no drag regression on hand cards ## What Not To Do - do not hand-edit `ui/DefaultGroup.ui` - do not change multiple card surfaces in one shot - do not mix root-input cards with child-input cards - do not add hover logic before confirming the target card entity actually receives input ## Recommended Next Change The next implementation step should be: 1. diff `DeckInspectHud/Grid/Card1` against `RewardHud/Reward1` 2. make only `DeckInspectHud` root card structure match 3. regenerate UI 4. boot test 5. then bind hover for inspect cards only That keeps the blast radius small.