# Peejeezet — Full UX Redesign (Design Spec)

- **Date:** 2026-07-09
- **Status:** Approved direction; pending spec review before implementation planning.
- **Author:** AI pairing session (brainstorming → spec).
- **Supersedes/extends:** `docs/superpowers/specs/2026-06-27-peejeezet-overhaul-design.md` (first polish pass).

## Approved decisions (from brainstorming)

| Decision | Choice |
|----------|--------|
| Scope | Entire authenticated app **+** public landing. |
| Depth | **Full redesign** — layouts, components, and styling evolve together. |
| Visual identity | **Refine the Arcade Neon gaming DNA** — disciplined, premium esports-product feel (personality without noise). |
| Theme | **Dark-first + a real, working light mode** with a persisted toggle. |
| Styling backbone | **Hybrid** — keep the custom design-token/CSS system; adopt Flux only for a few interaction primitives. |
| Git | **Skipped** per user. Collect any manual commands instead. |

---

## 1. Goals & Non-goals

### Goals
1. Make the authenticated app **information-dense and action-first** — the primary object (table/grid/record) and its actions lead every screen.
2. Eliminate marketing chrome, duplicated metrics, and vanity numbers from admin screens.
3. Ship a genuinely usable **fee grid** (the signature screen) with sticky headers and colorblind-safe status.
4. Add a **working light mode** with an accessible toggle; keep dark as the default.
5. Standardize interactions: confirm modal (not native `confirm()`), toast feedback, row-action menus, inline form validation, sticky save bars.
6. Meet **WCAG AA** contrast and keyboard/focus/reduced-motion requirements in both themes.
7. Refine the public landing into a disciplined, expressive first impression.

### Non-goals (out of scope)
- No database/schema changes; no new domain features (programs, roles, payments, API, file uploads).
- No change to fee business logic: `syncCurrentFeePeriod()` on `GET /fees`, `lated` storage/normalization, delete = `is_active=false`, `MemberFee` manual timestamps all remain.
- The public landing stays **static marketing** — no DB wiring, no live/fake stats.
- No new runtime dependencies. Flux is already installed; use free-tier components only (see §6 risk).
- No rewrite of controllers/repositories except tiny read-only additions if a KPI genuinely needs one (avoid if existing summary data suffices).

---

## 2. Design principles

1. **Data first, chrome last.** Authenticated screens open with a compact page header (title + one line of context + primary action), then the data. Hero blocks are removed from admin screens; expressive hero energy lives only on the public landing.
2. **One source of truth per number.** One KPI strip of 2–4 decision-driving numbers per screen. Remove duplicated bands and vanity metrics (e.g. "Match rate %", "Active share", the header "Unified responsive interface" pill).
3. **Scannable density.** Tighter rows, clear column hierarchy, sticky headers, tabular numerics (JetBrains Mono) for RM amounts and IDs.
4. **Purposeful motion.** Motion signals state (hover, focus, status change, toast in/out), never decoration. Neon glow becomes a focus/active affordance. Honor `prefers-reduced-motion`.
5. **Consistent, low-friction interactions.** Confirm modal for destructive actions; toast feedback for save/activate/deactivate; row actions in a compact menu; inline field validation; sticky save bars.
6. **Accessible by default.** AA contrast in both themes, visible focus rings, keyboard-navigable menus/modals, real labels. Density never beats legibility.

---

## 3. Design-system foundation

### 3.1 Theme & light mode
- Current state: `partials/head.blade.php` seeds `flux.appearance='dark'` and adds `.dark`; `<html class="dark">` is also hard-set in `layouts/app/sidebar.blade.php` and `welcome.blade.php`. Light tokens already exist in `resources/css/theme/tokens.css` but are unused.
- Change: drive theme from the persisted **Flux appearance** value (`light|dark|system`), defaulting to dark. Remove the hard-coded `class="dark"` from the two layouts so the appearance script/`@fluxAppearance` controls it. Keep the "default to dark on first visit" seed.
- Add a **theme toggle** in: the app top header (all breakpoints), the mobile menu, and the public landing header. The Settings → Appearance page remains the canonical control and must stay in sync.
- Audit **light tokens for AA contrast**; adjust values in `tokens.css` `:root` as needed (text on surfaces, status colors, borders, focus rings).

### 3.2 Color roles (fixed semantics)
- **Accent (violet)** = primary/interactive (buttons, links, active nav, focus).
- **Cyan (secondary)** = secondary/info accents only.
- **Success / warning / danger** = reserved for **fee status** (paid/late/unpaid) and destructive actions — not decoration.
- Reduce ambient glow; glow is reserved for focus/active/hover affordances.
- Status must be distinguishable without color: pair every status with its **letter (P/L/U/N) + icon + label/tooltip**.

### 3.3 Typography & density
- **Chakra Petch** — headings, brand, KPI numbers. **Manrope** — body/UI. **JetBrains Mono** — amounts, IDs, tabular figures.
- Establish a tighter, purposeful type scale (fewer sizes). Introduce a **compact density** for tables/grids (row height, cell padding, header treatment).

### 3.4 Motion
- Micro-transitions (120–200ms) for hover/focus/press; toast slide/fade; status-change flash; modal open/close. All gated by `prefers-reduced-motion` (guard already in `base/globals.css`).

### 3.5 Accessibility baseline
- AA contrast (both themes); `:focus-visible` rings on all interactive elements (extend existing custom-control rings); keyboard operability for menus/modals/toggles; correct roles/labels; `aria-current` on active nav; tables use proper `<th scope>` (already partially present).

---

## 4. Shared component inventory

Built on the existing CSS-layer/token system unless marked Flux.

| Component | Purpose | Notes |
|-----------|---------|-------|
| `page-header` | Compact title + context + primary action | Retires the hero blocks. |
| `kpi-strip` / `kpi` | 2–4 decision metrics | Replaces overlapping metric bands. |
| `data-table` | Dense table: sticky head, aligned numerics, hover | Extends `.member-table`/`.table-shell`. |
| `status-chip` | Fee/member status: color + letter + icon + label | Colorblind-safe. |
| `row-actions` | Compact per-row action menu | **Flux dropdown/menu** (already used in shell). |
| `confirm-modal` | Destructive confirmation | **Flux modal**; replaces native `confirm()`. |
| `toast` | Transient success/error feedback | Flux if free-tier provides it; else token-styled Alpine toast fed by session flash (see §6). |
| `theme-toggle` | light/dark/system | Bound to Flux appearance. |
| `empty-state` | Refined empty/zero states | One clear CTA. |
| `form-field` | Label + control + inline `@error` + help | Reused across all forms. |
| `sticky-save-bar` | Persistent Save/Cancel on forms/editors | With dirty-state indicator on fee manage. |
| `legend` | Compact status legend near grids | |

---

## 5. Per-screen specifications

### 5.1 App shell & navigation (`layouts/app/*`)
- Top header: left = page title/context; right = **theme toggle + user menu** (avatar dropdown) on all breakpoints (desktop currently hides the user menu in the sidebar footer — unify to the header).
- Remove the `Unified responsive interface` pill and the **Resources** nav group (GitHub starter-kit + Laravel docs links).
- Sidebar: keep 4 items with icons + active state; refine spacing/brand/collapsed behavior.
- Mount one global **toast** container in the shell.
- Nav is defined in three places (sidebar, desktop navbar, mobile menu) — keep them in sync; document in `views.md`.

### 5.2 Dashboard (`dashboard.blade.php`)
- Compact header (no marketing paragraph). One **KPI strip**: Active/total members · Coverage % (year) · Outstanding months · Total paid (RM).
- Primary panel: **Members with outstanding fees** — actionable list (name · member_id · outstanding count) deep-linking to `fees.manage`. This is the main CTA.
- Secondary: **Recently joined** (compact) + **Quick actions** toolbar (Add member / View fees / Manage fees).
- Coverage rendered as a slim meter inside/next to the KPI strip, not a large hero aside.
- Refined empty state (no members) with a single CTA.

### 5.3 Members — list (`pages/member/index.blade.php`)
- Remove hero + duplicate mini-stats. Compact header with primary **Add member**.
- Slim KPI strip: Total / Active / Inactive / Visible (drop Match rate / Active share).
- Compact toolbar: search + status `<select>` + Apply/Reset inline.
- **data-table**: sticky header; member name link + `member_id`/`plan` secondary; contact; joined; monthly fee (mono, right-aligned); status chip; fee-record count; **row-actions menu** (View / Edit / Deactivate|Activate).
- Deactivate/Activate → **confirm modal**; result → **toast**. Preserve POST + `@method('DELETE'|'PATCH')` and delete = deactivate.
- Mobile: refined card reflow (keep `data-label`).

### 5.4 Members — profile (`pages/member/show.blade.php`)
- Identity header: name · `member_id` · status chip · plan · joined; actions (Edit, Deactivate/Activate → confirm modal + toast).
- Contact + membership facts (phone, email, monthly fee).
- **Recent fees** list (last 8): period + status chip + amount; each row links to the **fee record editor**; deep link to fee manager.
- Two-column desktop, stacked mobile.

### 5.5 Members — create/edit (`pages/member/{create,edit}.blade.php` + `_fields.blade.php`)
- `_fields` refactored into grouped sections (Identity / Contact / Membership) using `form-field`.
- Correct input types (email, tel, date, number/step for fee), required markers, inline `@error`, helpful placeholders/help text, `old()` repopulation.
- **Sticky save bar** (Save / Cancel); success → toast. Keep POST-redirect-GET (`@method('PUT')` on edit).

### 5.6 Fees — status grid (`pages/fee/index.blade.php`)
- Compact header + one KPI strip (Total members · Coverage % · Total paid · Outstanding).
- **Grid is the star**: sticky first (member) column + sticky month header row; current-month column emphasized; **status-chip** per cell (color + P/L/U/N + tooltip); per-member Year total + All-time in aligned mono; compact persistent legend.
- Compact search toolbar; "Update statuses" → `fees.manage`.
- Preserve year sections and `lated → late` display normalization.
- Mobile: refined per-member card reflow; sticky member column with horizontal scroll fallback.

### 5.7 Fees — manage (`pages/fee/manage.blade.php`)
- Compact header + slim KPI (Selected year · Paid months · Outstanding).
- Editable grid mirrors index ergonomics: sticky member column + sticky month header; each cell a compact status control (segmented cycle or `<select>`) with live chip color; restore member name (id optional).
- **Sticky save bar** with an **unsaved-changes** indicator; flash/validation → toast; refined error summary.
- Keep POST contract `statuses[memberId][Mon]` and `lated` writes.
- Optional convenience (nice-to-have): per-column "set month for all" / per-row "set all months".

### 5.8 Fees — record editor (`pages/fee/record.blade.php`)
- Focused form with member+period context header; fields: status (chip selector), `amount_paid`, `paid_at` (date), `payment_method`, `reference_no`, `remarks`; inline validation; **sticky save**; success → toast; cancel returns to member profile. Reuses existing columns (no migration).

### 5.9 Auth (`pages/auth/*`, `layouts/auth*`)
- Refined centered **auth card**: brand mark, refined inputs + labels + inline errors, primary CTA, secondary links; theme toggle available; responsive; consistent identity. Covers login, register, forgot/reset password, verify-email, confirm-password, two-factor challenge. Fortify backend unchanged.

### 5.10 Settings (Livewire `pages/settings/⚡*`)
- Consistent panels/forms using `form-field`; `action-message` → toast; profile/password/2FA/recovery-codes/delete-account visually consistent.
- **Appearance** page = light/dark/system control, in sync with the header toggle. Stays Livewire.

### 5.11 Public landing (`welcome.blade.php`, `pages/welcome.css`)
- Keep expressive but disciplined: refined hero (brand, tagline, primary CTA = Member login/Enter dashboard, secondary = Learn about us), tightened About / What-we-do / Values / CTA / footer.
- Subtler orbs/rings; purposeful motion honoring reduced-motion; add theme toggle; responsive; AA contrast. Stays **static** (no DB, no stats). Existing `route('login')`/`route('dashboard')` CTAs preserved.

---

## 6. Styling backbone decision (hybrid) + risk

- Backbone stays the custom **token/CSS-layer** system (`resources/css/{theme,base,layout,components,pages}`), extended with the new shared components.
- Flux is used for **modal, dropdown/menu, toast, appearance/toggle** — components with fiddly a11y that Flux already solves and the app already uses (sidebar/menu/profile).
- **Risk:** some Flux components may be Pro-only in `livewire/flux` (free) v2 — most likely **toast**. **Mitigation:** verify each component is available in the free tier during Phase 0; for any Pro-only component, hand-roll an accessible token-styled equivalent (e.g. a small Alpine toast fed by `session('status')`/`session('error')`). Modal and dropdown/menu are already in use, so those are safe.

---

## 7. Accessibility & responsive requirements
- AA contrast verified in both themes (manual check of text/surface/status/border/focus pairs).
- Every interactive element has a visible `:focus-visible` state; menus/modals/toggles fully keyboard-operable; `aria-current` on active nav; `aria-live` region for toasts.
- Tables: `<th scope>` for row/column headers; sticky headers must not trap focus; provide horizontal-scroll fallback with a sticky member column on small screens.
- All motion gated by `prefers-reduced-motion`.

---

## 8. Testing strategy

Project rule: every change must be programmatically tested; run the minimum needed with `php artisan test --compact --filter=...`.

- **Update existing feature tests** that assert on changed copy/markup: `DashboardTest`, `MemberManagementTest`, `FeeIndexAutomationTest`, `FeeManagementTest`, `FeeRecordTest`, `WelcomePageTest`, `Auth/*`, `Settings/*`. Prefer asserting on **stable anchors** (routes, data values, key labels, `data-test` hooks) over volatile marketing copy.
- **Add tests** for new behavior: theme toggle persistence (appearance value), deactivate via confirm-modal still POSTs to `members.destroy` and flips `is_active`, activate flow, toast/flash on success. Add `data-test` attributes where markup assertions are needed.
- **Preserve behavior tests**: fee sync on `GET /fees`, `lated` storage, delete=deactivate, dashboard aggregates, member-fee amount math.
- **Smoke (Pest 4 browser)**: visit each key authenticated page + landing and assert no console/JS errors (guards the new Alpine/Flux interactions). Requires a browser environment.
- **Per PHP edit:** `vendor/bin/pint --dirty --format agent`. **Per asset edit:** `npm run build`.
- **Env caveat:** Laragon CLI PHP has `pdo_sqlite` disabled (see `docs/commands-to-run.md` / progress-log) — run tests against the configured DB or enable the extension first.

---

## 9. Implementation phasing

Each phase ends with: update/adjust tests → run affected tests → `pint` → `npm run build` → update docs.

- **Phase 0 — Foundation:** light-mode wiring + header theme toggle; token/color-role audit (AA); shared components (`page-header`, `kpi-strip`, `data-table`, `status-chip`, `row-actions`, `confirm-modal`, `toast`, `empty-state`, `form-field`, `sticky-save-bar`); motion/a11y baseline; global toast mount; verify Flux free-tier components.
- **Phase 1 — Shell + Dashboard.**
- **Phase 2 — Members (list → profile → form).**
- **Phase 3 — Fees (grid → manage → record).**
- **Phase 4 — Auth + Settings.**
- **Phase 5 — Public landing.**

Phase 0 → 1 first delivers a visible vertical slice (shell + dashboard) to validate the direction on the real running app before rolling out the rest.

---

## 10. Documentation updates required

After implementation, keep both doc sets in sync (per repo convention and standing memory rule):
- `.ai/agents/`: `views.md` (hero → page-header, new shared components, theme toggle, nav sync), `feature-map.md` (landing refined; header/Resources filler removed), `progress-log.md` (append dated entry), `known-fixes.md` (any new gotchas), `conventions.md` if component patterns change.
- `.github/ai/`: `architecture.md`, `conventions.md`, `features.md` where documented UI facts change.

---

## 11. Risks & mitigations

| Risk | Mitigation |
|------|------------|
| Feature tests assert on marketing copy that's being removed | Update tests to stable anchors + `data-test` hooks. |
| Flux toast (and possibly others) Pro-only | Verify in Phase 0; hand-roll token-styled accessible equivalents if needed. |
| Sticky columns + responsive reflow complexity | Progressive enhancement; sticky member column + horizontal-scroll fallback; card reflow on mobile. |
| Light-mode contrast regressions | Audit tokens for AA before rollout; check both themes per phase. |
| CLI `pdo_sqlite` disabled blocks tests | Use configured DB or enable extension; documented in commands file. |
| Scope creep across 11 screens | Strict phasing; ship shell+dashboard slice first; no new features. |

---

## 12. Open questions (none blocking)
- Fee-manage cell control: segmented cycle-button vs `<select>` — decide during Phase 3 build against real ergonomics (default: keep `<select>` for reliability, style it densely).
- Whether to add per-column/per-row bulk-set convenience on fee manage (nice-to-have; defer unless requested).
