From 490cab92a3e7a66be007607d400d6f43efb09228 Mon Sep 17 00:00:00 2001 From: Keysat Date: Fri, 19 Jun 2026 18:28:49 -0500 Subject: [PATCH] =?UTF-8?q?Mobile=20Phase=207:=20theme-conformance=20pass?= =?UTF-8?q?=20=E2=80=94=20light-flip=20+=20retire=20legacy=20badges?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Route remaining hardcoded UI colors through themed :root vars so they flip under [data-theme="light"], finishing the P6 light-theme migration. - Mobile: bottom-tab-bar -> --nav-bg; toast bottom-center above the tab bar, rising in via a new slideInUp keyframe. - Money: --money for the kanban/pipeline-stage/stat amount literals. - Badges: remap the legacy Material .badge-* family onto the brand StageChip/--chip-* + --badge-priority/-danger slots, retiring the second palette (DESIGN sections 2/7). - Desktop-light: logout/danger buttons, table hover/stripe/footer, sidebar & header gradients, scrollbars, toast states, context-menu danger, thesis banner/accents, grid selection & drag indicators, skeleton loaders. 28 new themed vars (theme-stable ones dark-only); dark appearance preserved. Frontend-only. Verified via CSSOM render-smoke, var resolution, brace check; reviewer approve-with-nits (toast-rise fixed). Unverified on a real device. Also refresh AGENTS.md Current state and add a ROADMAP legacy-usage-sweep note. --- AGENTS.md | 11 ++- ROADMAP.md | 2 + frontend/index.html | 231 ++++++++++++++++++++++++++++---------------- 3 files changed, 158 insertions(+), 86 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index bc85781..caa3e34 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -107,12 +107,13 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude ## Current state -_**Box live at v0.1.0:94**; `main` ahead by mobile Phases 0–6 + P3b name/pill edit + drag-reorder views — **all deploy-pending** (no s9pk built yet). **The fundraising grid + email capture is the canonical system of record.** Active thread: **mobile-first redesign** — **all 4 surfaces + light theme + P3b (name/pill edit) done; BRIEF §3a editable set complete**. **Plan (Grant, 2026-06-19): finish features first — P3b done → Phase 7 design-conformance pass next — then Grant does device testing + deploy** (NOT before; everything is unverified on a real phone). Per-phase detail + backlog: `ROADMAP.md` / `EVALUATION.md`; history: git log + `start9/0.4/startos/versions/`._ +_**Box live at v0.1.0:94**; `main` ahead by mobile Phases 0–7 + P3b name/pill edit + drag-reorder views — **all deploy-pending** (no s9pk built yet). **The fundraising grid + email capture is the canonical system of record.** Active thread: **mobile-first redesign** — **all 4 surfaces + light theme + P3b + Phase 7 theme-conformance done**. **Plan (Grant, 2026-06-19): finish features first — Phase 7 done → next is design/functional conformance-vs-export checks + PWA wiring, then Grant does device testing + deploy** (NOT before; everything is unverified on a real phone). Per-phase detail + backlog: `ROADMAP.md` / `EVALUATION.md`; history: git log + `start9/0.4/startos/versions/`._ - **Mobile redesign — all 4 core surfaces built + committed (Grid · Contacts · Pipeline · Reminders).** Each is a rules-of-hooks-safe `useIsMobile()` wrapper → `Mobile*`/`Desktop*` pair (**desktop untouched**), re-authored against the real API on shared primitives ``/`useIsMobile()`/`StageChip`/`MobileDetailRow`. Foundation: bottom-tab bar + `:root` mobile vars (P1); 4-stage enum + read-only derived grid signals (`existing_investor`/`last_activity_at`/`staleness`/`opportunity_id`) injected on GET, **stripped on write at both points** (P0/P3a `_computed_row_values` + `stripComputedRows`). **Mobile writes use one-row endpoints only — never whole-grid PUT** (BRIEF §3a): log-communication, pipeline link/stage, reminders, and now **`POST /api/fundraising/update-row`** (P3b name/pill edit). Per-phase detail in `ROADMAP.md`. -- **This session — P3b investor name + contact-pill edit (committed `3f93daf`, frontend + backend).** New **version-safe `POST /api/fundraising/update-row`** (`handle_update_fundraising_row`) — the one-row read-fresh-modify-write twin of `handle_log_fundraising_communication`: reads the canonical grid blob server-side, mutates ONLY the target row's `investor_name`/`contacts`, writes back with a version bump + `sync_fundraising_relational`. Never a whole-grid payload → can't clobber concurrent edits to other rows (BRIEF §3a). Server-side `_sanitize_fundraising_contacts` (9-field whitelist; drops name+email-empty pills) is the trust boundary. Frontend: `MobileFundraisingGrid` detail gains an **Edit** bottom-sheet (investor-name input + pill add/edit/remove of name·email·title, preserving each pill's location/LinkedIn fields, **client-side dedup** by email→name) → saves through update-row → reloads; money stays desktop-only. Pill removal is **soft** on the classic `contacts` directory (only the grid pill + `fundraising_contacts` row drop). New CSS is theme-var-only (`.pill-edit*`/`.sheet-addbtn`/`.fs-detail-edit`). Verified: **`backend/test_fundraising_update_row.py`** (24 assertions over real HTTP — rename/add/edit/remove, other-row-untouched, relational + classic-contacts sync, soft-remove, name-only-pill kept, 5 guards); full suite **37/37**; render-smoke green; throwaway jsdom-375px harness drove the real edit flow (14/14: open→edit→rename→remove→add→save, asserted `POST update-row` + **no whole-grid PUT** + preserved fields). Reviewer-passed (nits were deliberate sibling-pattern parity). **No real-phone check.** -- **Prior session (`e6a8945`) — P6 light theme (frontend-only).** App-wide light theme behind `:root[data-theme="light"]` (dark default; pre-paint boot script reads `localStorage.venture_crm_theme`); toggle in desktop sidebar footer + mobile top bar off one `App` `theme` state. 44 themed `:root` slots (dark == originals byte-for-byte), 319 hex→`var()` migrated, `StageChip` className-based. **Mobile light complete; desktop-light rough edges** (bespoke ` @@ -8788,7 +8857,7 @@ verticalAlign: 'top', cursor: col.readOnly ? 'default' : (isLockedByOther ? 'not-allowed' : 'cell'), boxShadow: isLockedByOther ? 'inset 0 0 0 1px var(--danger-soft)' : undefined, - background: isLockedByOther ? 'rgba(143, 75, 75, 0.12)' : undefined, + background: isLockedByOther ? 'var(--locked-cell-bg)' : undefined, minWidth: `${col.width || 140}px`, width: `${col.width || 140}px` }}