Mobile Phase 7: theme-conformance pass — light-flip + retire legacy badges
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.
This commit is contained in:
@@ -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 `<BottomSheet>`/`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 `<style>` shades: login glow/scrollbar/table-hover/KPI green, legacy off-palette `.badge-*`, dark shadows) → **Phase 7**. Verified render-smoke + jsdom toggle harness (7/7). **No real-phone check.** Earlier (`ee9db64`): **P4 Pipeline** + **P5 Reminders** (swipe-done/snooze) — detail in `ROADMAP.md`.
|
||||
- **This session — Phase 7 theme-conformance pass (frontend-only, `frontend/index.html`).** Routed ~50 remaining hardcoded color literals through themed `:root` vars so every surface flips under `[data-theme="light"]`, finishing the P6 migration. **28 new themed vars** (theme-stable ones — accent glows, selection indicators, the solid danger button — intentionally dark-only; dark appearance preserved). Covered: mobile bottom-tab-bar (`--nav-bg`, wiring the previously-dead token) + bottom-center mobile toast (new `slideInUp` keyframe); 3 money-green literals → `--money`; the **legacy Material `.badge-*` family (12 classes) retired** onto the brand StageChip/`--chip-*`/`--badge-priority`/new `--badge-danger-bg` slots (drops the 2nd color system per DESIGN §2/§7); and the desktop-light rough edges (logout/danger buttons, table hover/stripe/footer, sidebar+header gradients, scrollbars, toast error/success, context-menu danger, thesis banner/accents, grid selection & drag/resize indicators, skeleton loaders). Verified: **design-checker** inventory → scoped plan; **CSSOM render-smoke** (both theme rules parse, all flips distinct), full `var()`-resolution + brace balance; **reviewer** APPROVE-WITH-NITS (the one P2 — mobile toast slid in from the right vs its new bottom-center rest — **fixed** via `slideInUp`). **No real-phone check.** **NB: the `.badge-*` remap may be largely cosmetic — several legacy badge classes have no live JSX caller; a legacy-usage sweep (ROADMAP) will confirm what to delete.**
|
||||
- **Prior 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 `<style>` shades: login glow/scrollbar/table-hover/KPI green, legacy off-palette `.badge-*`, dark shadows) → **resolved in Phase 7 (this session)**. Verified render-smoke + jsdom toggle harness (7/7). **No real-phone check.** Earlier (`ee9db64`): **P4 Pipeline** + **P5 Reminders** (swipe-done/snooze) — detail in `ROADMAP.md`.
|
||||
- **Live (deployed):** W2 NL query (v94; remaining: in-room smoke + web "Ask" box); W1 reminders (v93); grid Pipeline (v88); Matrix intake + Gmail capture (DWD) + daily digest; Thesis/Architect (dual-approval); outreach — all draft-only.
|
||||
- **Tests:** **37/37 backend green** (`python3 backend/run_tests.py`; +`test_fundraising_update_row.py`), `py_compile` clean, render-smoke green, fresh-DB migrate clean.
|
||||
- **Next (next session = finish features):** 1) **Phase 7 design-conformance pass** against the full Claude Design export (`design/_imports/2026-06-19_zip-file/`) — buttons/colors/spacing/functionality across all surfaces, incl. finishing the P6 desktop-light rough edges (run `design-checker`). **Then (Grant, after feature-complete):** deploy P0–P6 + P3b + view-reorder in one s9pk (**authorize + version-bump first**) and device-test light/dark on a real phone. Later backlog: W2 web Ask box + smoke; W3 bot grid-mutations; W1b nurture-gap.
|
||||
- **Open / risks:** all mobile work + **P6 light theme + P3b edit** **built but never deployed or tested on a real phone/browser** (render-smoke + jsdom only — verify on a device, both themes); **P6 desktop-light has known rough edges** (bespoke `<style>` shades, legacy `.badge-*` family, dark shadows → Phase 7); W2 happy-path only; **Claude/Architect path unverified live on the box**; v2.0 reserve-asset spine **not canonical** (needs dual sign-off); doc drift — `crm-overview.md`/`EVALUATION.md` still call `lp_profiles` live.
|
||||
- **Next (finish features):** 1) **mobile visual-conformance check** — compare the 4 mobile screens (Grid/Pipeline/Reminders/Contacts) against the Claude Design export comps (`design/_imports/2026-06-19_zip-file/`); 2) **mobile functional-parity check** — verify wired behaviour (taps/swipes/pills, the DB actions, not visuals) matches the export's `store.js`/`*App.dc.html`; 3) **PWA wiring** (manifest + service worker + icons; mind StartOS serving + the no-build single-file setup). **Then (Grant, after feature-complete):** deploy P0–P7 + P3b + view-reorder in one s9pk (**authorize + version-bump first**) and device-test light/dark on a real phone. Later backlog: legacy-`.badge-*`/legacy-functionality usage sweep + delete; W2 web Ask box + smoke; W3 bot grid-mutations; W1b nurture-gap.
|
||||
- **Open / risks:** all mobile work + **light theme (mobile + desktop, Phase 7) + P3b edit** **built but never deployed or tested on a real phone/browser** (render-smoke + jsdom/CSSOM only — verify on a device, both themes); W2 happy-path only; **Claude/Architect path unverified live on the box**; v2.0 reserve-asset spine **not canonical** (needs dual sign-off); doc drift — `crm-overview.md`/`EVALUATION.md` still call `lp_profiles` live.
|
||||
|
||||
@@ -201,6 +201,8 @@ Open design questions (settled at build time): send time = **6 PM box-local** (c
|
||||
|
||||
**Keep the Contacts table — as the read-only per-person directory it already is.** Confirmed 2026-06-16: the grid models **investor entity → many people** correctly today. The grid "contacts" column is a multi-pill editor; each pill syncs to a `fundraising_contacts` row AND its own classic `contacts` row (5-person family office → 1 investor + 5 contacts, linked via `fundraising_contacts.contact_id`, migration 0004). The Contacts page is **read-only for creation** (header: "added from the Fundraising Grid"; no New-Contact button), edit-only via the detail slide-over — the desired flow already holds. Email capture already rolls **multiple people up to one investor** (matcher indexes each pill's email separately, all → same `fundraising_investor_id`; `email_investor_links` records both investor and specific person). No build here — future email-surfacing UI should present comms grouped by investor across all its people.
|
||||
|
||||
**Legacy-usage sweep — what's still wired, what's dead, what can be deleted (Grant, 2026-06-19; after mobile feature-complete).** Phase 7's `.badge-*` remap surfaced that several legacy badge classes (lead/outreach/meeting/due-diligence/committed/funded) have no — or near-no — live JSX caller, and Grant flagged other likely-dead legacy bits (e.g. the `investor type` field). Once the mobile redesign is feature-complete, do a systematic pass: for each legacy component / CSS class / endpoint / DB field, determine whether it still renders or runs anywhere (JSX callers, `do_GET`/`do_POST` dispatch, DB reads), then soft-retire/delete the genuinely-dead ones (never hard-delete data — archive per convention; `refactor-scout`/`janitor` can inventory). Start list: the orphaned `.badge-*` classes, `investor type`, and other classic-CRM remnants not reachable from the grid-canonical flow.
|
||||
|
||||
### Front-end: pre-compile JSX, drop runtime Babel (optional, larger)
|
||||
*Logged 2026-06-16 during the v0.1.0:82 vendor+SRI work. The scoped fix shipped: React/ReactDOM/Babel are now vendored + SRI-pinned and served same-origin, and a jsdom render smoke check gates every build (`docs/guides/packaging.md`). This is the bigger alternative we deliberately deferred.*
|
||||
|
||||
|
||||
+150
-81
@@ -83,6 +83,7 @@
|
||||
--btn-secondary-hover: #3b4e63;
|
||||
--badge-priority-bg: #f59e0b22;
|
||||
--badge-priority-text: #fcd34d;
|
||||
--badge-danger-bg: #dc262622; /* high-priority badge fill (text = --danger-text) */
|
||||
/* pipeline-stage chips — bg / text / border (comp stageColors) */
|
||||
--chip-lead-bg: #70859b22; --chip-lead-text: #8ea2b7; --chip-lead-border: #2635488a;
|
||||
--chip-engaged-bg: #3b82c422; --chip-engaged-text: #93c5fd; --chip-engaged-border: #3b82c44d;
|
||||
@@ -92,6 +93,33 @@
|
||||
/* reminder status badges (open/snoozed/done/cancelled) — light values derived,
|
||||
since the comp models reminder URGENCY rather than these four statuses */
|
||||
--rem-open: #7fb0d3; --rem-snoozed: #b08fd3; --rem-done: #7fd3a3; --rem-cancelled: #70859b;
|
||||
/* --- Phase 7 (2026-06-19): leftover literals that didn't flip in P6 (DESIGN §8). --- */
|
||||
--nav-bg: rgba(17, 26, 39, 0.92); /* mobile bottom-tab-bar */
|
||||
--panel-grad-end: #101926; /* sidebar / header gradient bottom stop */
|
||||
--header-grad-top: #121d2b; /* header gradient top stop */
|
||||
--accent-grad-end: #295f91; /* sub-nav active gradient (theme-stable accent) */
|
||||
--logout-bg: #7f1d1d; /* destructive logout button */
|
||||
--logout-bg-hover: #991b1b;
|
||||
--table-stripe: #101b28; /* table even-row */
|
||||
--table-hover: #172435; /* table row hover */
|
||||
--table-foot-bg: #0f1b2a; /* sticky aggregate footer */
|
||||
--grid-shell-bg: #0c141f; /* grid viewport container + its scrollbar track */
|
||||
--scrollbar-track: #0f1723; /* scrollbar gutter / recessed thumb edge */
|
||||
--scrollbar-thumb: #2b3f54; /* grid scrollbar thumb */
|
||||
--toast-error-bg: #1f1a1a; --toast-error-border: #7f1d1d;
|
||||
--toast-success-bg: #1a1f1a; --toast-success-border: #15803d;
|
||||
--ctx-danger-hover-bg: #3b1b24; /* context-menu destructive hover */
|
||||
--ctx-danger-hover-text: #ffd3d3;
|
||||
--thesis-banner-bg: #1a2233;
|
||||
--locked-cell-bg: rgba(143, 75, 75, 0.12); /* desktop grid cell locked-by-other */
|
||||
/* Phase 7b — desktop component literals (sidebar nav / grid interactions / thesis). */
|
||||
--nav-active-glow: #6ea6d455; /* accent inset glow on active nav (theme-stable) */
|
||||
--accent-bright: #4a9adf; /* selection / drag indicators (theme-stable accent) */
|
||||
--accent-wash: #3b82c455; /* accent hover/glow wash (theme-stable) */
|
||||
--danger-btn-bg: #dc2626; /* solid destructive button (theme-stable) */
|
||||
--danger-btn-bg-hover: #b91c1c;
|
||||
--cell-selected-bg: #1a2a3c; /* grid selected-cell fill (flips) */
|
||||
--cell-selected-glow: #9ac7ec40; /* grid selected-cell inset glow (flips) */
|
||||
}
|
||||
|
||||
/* Light theme (P6, adopted 2026-06-19). Dark stays the default + brand identity; a
|
||||
@@ -124,12 +152,33 @@
|
||||
--btn-secondary-hover: #dde5ef;
|
||||
--badge-priority-bg: #e08e0922;
|
||||
--badge-priority-text: #a76a07;
|
||||
--badge-danger-bg: #c0322f1f;
|
||||
--chip-lead-bg: #5a6b7d14; --chip-lead-text: #5a6b7d; --chip-lead-border: #d6dde7;
|
||||
--chip-engaged-bg: #3b82c416; --chip-engaged-text: #2266a0; --chip-engaged-border: #bcd2ea;
|
||||
--chip-diligence-bg: #e0b34122; --chip-diligence-text: #8a6c12; --chip-diligence-border: #e4d29a;
|
||||
--chip-commitment-bg: #10b98118; --chip-commitment-text: #057a55; --chip-commitment-border: #a9ddca;
|
||||
--chip-default-bg: #5a6b7d12; --chip-default-text: #84909e; --chip-default-border: #d6dde7;
|
||||
--rem-open: #2266a0; --rem-snoozed: #7a4fa8; --rem-done: #057a55; --rem-cancelled: #84909e;
|
||||
/* Phase 7 light overrides (accent-grad-end is theme-stable → dark only). */
|
||||
--nav-bg: #ffffffd9;
|
||||
--panel-grad-end: #f4f7fb;
|
||||
--header-grad-top: #ffffff;
|
||||
--logout-bg: #fbe2e2;
|
||||
--logout-bg-hover: #f6cccc;
|
||||
--table-stripe: #f1f5f9;
|
||||
--table-hover: #e3e9f1;
|
||||
--table-foot-bg: #f4f7fb;
|
||||
--grid-shell-bg: #eef2f7;
|
||||
--scrollbar-track: #dfe6ef;
|
||||
--scrollbar-thumb: #c2cdda;
|
||||
--toast-error-bg: #fdeeee; --toast-error-border: #d99a9a;
|
||||
--toast-success-bg: #edf7f0; --toast-success-border: #9cc9ad;
|
||||
--ctx-danger-hover-bg: #fbe4e4;
|
||||
--ctx-danger-hover-text: #c0322f;
|
||||
--thesis-banner-bg: #f4f7fb;
|
||||
--locked-cell-bg: rgba(192, 50, 47, 0.10);
|
||||
--cell-selected-bg: #dbe8f5;
|
||||
--cell-selected-glow: #2f6ea955;
|
||||
}
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
@@ -154,7 +203,7 @@
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
background: linear-gradient(180deg, var(--bg-panel) 0%, #101926 100%);
|
||||
background: linear-gradient(180deg, var(--bg-panel) 0%, var(--panel-grad-end) 100%);
|
||||
border-right: 1px solid var(--border);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
@@ -239,13 +288,13 @@
|
||||
.nav-item.active {
|
||||
background: linear-gradient(180deg, var(--accent) 0%, var(--accent-strong) 100%);
|
||||
color: white;
|
||||
box-shadow: inset 0 0 0 1px #6ea6d455;
|
||||
box-shadow: inset 0 0 0 1px var(--nav-active-glow);
|
||||
}
|
||||
|
||||
.nav-item-icon {
|
||||
font-size: 14px;
|
||||
min-width: 24px;
|
||||
color: #89a9c4;
|
||||
color: var(--text-muted);
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
font-weight: 600;
|
||||
line-height: 1;
|
||||
@@ -280,7 +329,7 @@
|
||||
}
|
||||
|
||||
.sub-nav-item.active {
|
||||
background: linear-gradient(180deg, var(--accent-strong) 0%, #295f91 100%);
|
||||
background: linear-gradient(180deg, var(--accent-strong) 0%, var(--accent-grad-end) 100%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -289,7 +338,7 @@
|
||||
}
|
||||
|
||||
.sub-nav-item.view-drag-over {
|
||||
box-shadow: inset 0 2px 0 #4a9adf;
|
||||
box-shadow: inset 0 2px 0 var(--accent-bright);
|
||||
}
|
||||
|
||||
.column-header-inner {
|
||||
@@ -302,7 +351,7 @@
|
||||
}
|
||||
|
||||
.column-drag-indicator {
|
||||
color: #7f95ab;
|
||||
color: var(--text-subtle);
|
||||
font-family: 'IBM Plex Mono', monospace;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
@@ -317,8 +366,8 @@
|
||||
}
|
||||
|
||||
.table th.column-drag-over {
|
||||
box-shadow: inset -3px 0 0 #4a9adf;
|
||||
background: #172635;
|
||||
box-shadow: inset -3px 0 0 var(--accent-bright);
|
||||
background: var(--table-hover);
|
||||
}
|
||||
|
||||
.column-resize-handle {
|
||||
@@ -340,25 +389,25 @@
|
||||
bottom: 4px;
|
||||
width: 2px;
|
||||
border-radius: 1px;
|
||||
background: #36506a;
|
||||
background: var(--border-strong);
|
||||
opacity: 0.55;
|
||||
transition: opacity 0.15s ease, background-color 0.15s ease;
|
||||
}
|
||||
|
||||
.column-resize-handle:hover {
|
||||
background: #3b82c455;
|
||||
background: var(--accent-wash);
|
||||
}
|
||||
|
||||
.column-resize-handle:hover::before {
|
||||
opacity: 1;
|
||||
background: #78acd8;
|
||||
background: var(--accent);
|
||||
}
|
||||
|
||||
.grid-cell-selected {
|
||||
outline: 2px solid #4a9adf;
|
||||
outline: 2px solid var(--accent-bright);
|
||||
outline-offset: -2px;
|
||||
background: #1a2a3c;
|
||||
box-shadow: inset 0 0 0 1px #9ac7ec40;
|
||||
background: var(--cell-selected-bg);
|
||||
box-shadow: inset 0 0 0 1px var(--cell-selected-glow);
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
@@ -393,8 +442,8 @@
|
||||
}
|
||||
|
||||
.context-menu-item.context-menu-danger:hover {
|
||||
background: #3b1b24;
|
||||
color: #ffd3d3;
|
||||
background: var(--ctx-danger-hover-bg);
|
||||
color: var(--ctx-danger-hover-text);
|
||||
}
|
||||
|
||||
.context-menu-sep {
|
||||
@@ -413,7 +462,7 @@
|
||||
|
||||
.logout-btn {
|
||||
padding: 10px 12px;
|
||||
background-color: #7f1d1d;
|
||||
background-color: var(--logout-bg);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
color: var(--danger-text);
|
||||
@@ -423,7 +472,7 @@
|
||||
}
|
||||
|
||||
.logout-btn:hover {
|
||||
background-color: #991b1b;
|
||||
background-color: var(--logout-bg-hover);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@@ -434,7 +483,7 @@
|
||||
}
|
||||
|
||||
.header {
|
||||
background: linear-gradient(180deg, #121d2b 0%, #101926 100%);
|
||||
background: linear-gradient(180deg, var(--header-grad-top) 0%, var(--panel-grad-end) 100%);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
@@ -468,11 +517,11 @@
|
||||
.content::-webkit-scrollbar-thumb {
|
||||
background: var(--border);
|
||||
border-radius: 20px;
|
||||
border: 2px solid #101926;
|
||||
border: 2px solid var(--scrollbar-track);
|
||||
}
|
||||
|
||||
.content::-webkit-scrollbar-track {
|
||||
background: #0f1723;
|
||||
background: var(--scrollbar-track);
|
||||
}
|
||||
|
||||
.page-container {
|
||||
@@ -608,11 +657,11 @@
|
||||
}
|
||||
|
||||
.button-danger {
|
||||
background-color: #dc2626;
|
||||
background-color: var(--danger-btn-bg);
|
||||
}
|
||||
|
||||
.button-danger:hover {
|
||||
background-color: #b91c1c;
|
||||
background-color: var(--danger-btn-bg-hover);
|
||||
}
|
||||
|
||||
.table {
|
||||
@@ -649,7 +698,7 @@
|
||||
max-height: calc(100vh - 280px);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #0c141f;
|
||||
background: var(--grid-shell-bg);
|
||||
box-shadow: inset 0 1px 0 #ffffff06;
|
||||
}
|
||||
|
||||
@@ -658,13 +707,13 @@
|
||||
}
|
||||
|
||||
.grid-table-shell::-webkit-scrollbar-thumb {
|
||||
background: #2b3f54;
|
||||
background: var(--scrollbar-thumb);
|
||||
border-radius: 20px;
|
||||
border: 2px solid #0f1723;
|
||||
border: 2px solid var(--scrollbar-track);
|
||||
}
|
||||
|
||||
.grid-table-shell::-webkit-scrollbar-track {
|
||||
background: #0c141f;
|
||||
background: var(--grid-shell-bg);
|
||||
}
|
||||
|
||||
.table th {
|
||||
@@ -712,16 +761,16 @@
|
||||
}
|
||||
|
||||
.table tbody tr:nth-child(even) td {
|
||||
background: #101b28;
|
||||
background: var(--table-stripe);
|
||||
}
|
||||
|
||||
.table tr:hover {
|
||||
background-color: #172435;
|
||||
background-color: var(--table-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.table tr:hover td {
|
||||
background-color: #172435;
|
||||
background-color: var(--table-hover);
|
||||
}
|
||||
|
||||
.table th.sticky-col {
|
||||
@@ -741,27 +790,27 @@
|
||||
}
|
||||
|
||||
.table tbody tr:nth-child(even) td.sticky-col {
|
||||
background: #101b28;
|
||||
background: var(--table-stripe);
|
||||
}
|
||||
|
||||
.table tr:hover td.sticky-col {
|
||||
background-color: #172435;
|
||||
background-color: var(--table-hover);
|
||||
}
|
||||
|
||||
.fundraising-table tfoot td {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
z-index: 4;
|
||||
background: #0f1b2a;
|
||||
border-top: 1px solid #2a3d52;
|
||||
box-shadow: 0 -1px 0 #1d2c3d;
|
||||
background: var(--table-foot-bg);
|
||||
border-top: 1px solid var(--border-strong);
|
||||
box-shadow: 0 -1px 0 var(--border);
|
||||
}
|
||||
|
||||
.fundraising-table tfoot td.sticky-col {
|
||||
z-index: 7;
|
||||
left: 0;
|
||||
box-shadow: 1px 0 0 var(--border), 0 -1px 0 #1d2c3d;
|
||||
background: #0f1b2a;
|
||||
box-shadow: 1px 0 0 var(--border), 0 -1px 0 var(--border);
|
||||
background: var(--table-foot-bg);
|
||||
}
|
||||
|
||||
.badge {
|
||||
@@ -774,9 +823,11 @@
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* Legacy badges remapped onto the brand themed slots (Phase 7 — retires the original
|
||||
Material palette; aligns stage badges with the StageChip / --chip-* system). */
|
||||
.badge-investor {
|
||||
background-color: #10b98122;
|
||||
color: #6ee7b7;
|
||||
background-color: var(--chip-commitment-bg);
|
||||
color: var(--money);
|
||||
}
|
||||
|
||||
.badge-prospect {
|
||||
@@ -785,58 +836,58 @@
|
||||
}
|
||||
|
||||
.badge-advisor {
|
||||
background-color: #f59e0b22;
|
||||
color: #fcd34d;
|
||||
background-color: var(--badge-priority-bg);
|
||||
color: var(--badge-priority-text);
|
||||
}
|
||||
|
||||
.badge-other {
|
||||
background-color: #70859b44;
|
||||
background-color: var(--chip-default-bg);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.badge-lead {
|
||||
background-color: #ec407a22;
|
||||
color: #f48fb1;
|
||||
background-color: var(--chip-lead-bg);
|
||||
color: var(--chip-lead-text);
|
||||
}
|
||||
|
||||
.badge-outreach {
|
||||
background-color: #ff9800aa;
|
||||
color: #fff3cd;
|
||||
background-color: var(--badge-priority-bg);
|
||||
color: var(--badge-priority-text);
|
||||
}
|
||||
|
||||
.badge-meeting {
|
||||
background-color: #2196f322;
|
||||
color: #90caf9;
|
||||
}
|
||||
|
||||
.badge-due-diligence {
|
||||
background-color: #2563eb22;
|
||||
background-color: var(--accent-soft);
|
||||
color: var(--accent-light);
|
||||
}
|
||||
|
||||
.badge-due-diligence {
|
||||
background-color: var(--chip-diligence-bg);
|
||||
color: var(--chip-diligence-text);
|
||||
}
|
||||
|
||||
.badge-committed {
|
||||
background-color: #ff5722aa;
|
||||
color: #ffccbc;
|
||||
background-color: var(--chip-commitment-bg);
|
||||
color: var(--chip-commitment-text);
|
||||
}
|
||||
|
||||
.badge-funded {
|
||||
background-color: #4caf5022;
|
||||
color: #a5d6a7;
|
||||
background-color: var(--chip-commitment-bg);
|
||||
color: var(--money);
|
||||
}
|
||||
|
||||
.badge-high {
|
||||
background-color: #dc262622;
|
||||
background-color: var(--badge-danger-bg);
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
.badge-medium {
|
||||
background-color: #f59e0b22;
|
||||
color: #fcd34d;
|
||||
background-color: var(--badge-priority-bg);
|
||||
color: var(--badge-priority-text);
|
||||
}
|
||||
|
||||
.badge-low {
|
||||
background-color: #6b7280aa;
|
||||
color: #d1d5db;
|
||||
background-color: var(--chip-default-bg);
|
||||
color: var(--chip-default-text);
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
@@ -918,13 +969,13 @@
|
||||
}
|
||||
|
||||
.toast.error {
|
||||
border-color: #7f1d1d;
|
||||
background-color: #1f1a1a;
|
||||
border-color: var(--toast-error-border);
|
||||
background-color: var(--toast-error-bg);
|
||||
}
|
||||
|
||||
.toast.success {
|
||||
border-color: #15803d;
|
||||
background-color: #1a1f1a;
|
||||
border-color: var(--toast-success-border);
|
||||
background-color: var(--toast-success-bg);
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
@@ -938,6 +989,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Mobile toast sits bottom-center, so it rises in instead of sliding from the right. */
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
transform: translateY(60px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes modalIn {
|
||||
from {
|
||||
transform: translateY(8px) scale(0.985);
|
||||
@@ -966,7 +1029,7 @@
|
||||
.skeleton-block {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: linear-gradient(180deg, #101926 0%, #0e1824 100%);
|
||||
background: linear-gradient(180deg, var(--bg-input) 0%, var(--bg-base) 100%);
|
||||
padding: 14px;
|
||||
box-shadow: inset 0 1px 0 #ffffff06;
|
||||
}
|
||||
@@ -974,7 +1037,7 @@
|
||||
.skeleton-line {
|
||||
height: 11px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--border) 0%, #3a526d 48%, var(--border) 100%);
|
||||
background: linear-gradient(90deg, var(--border) 0%, var(--border-strong) 48%, var(--border) 100%);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.35s linear infinite;
|
||||
margin-bottom: 10px;
|
||||
@@ -1095,7 +1158,7 @@
|
||||
.kanban-card-amount {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #10b981;
|
||||
color: var(--money);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
@@ -1301,7 +1364,7 @@
|
||||
.thesis-version-row.active {
|
||||
border-color: var(--accent);
|
||||
background-color: var(--bg-panel-elevated);
|
||||
box-shadow: inset 0 0 0 1px #3b82c455;
|
||||
box-shadow: inset 0 0 0 1px var(--accent-wash);
|
||||
}
|
||||
|
||||
.thesis-line-name {
|
||||
@@ -1401,7 +1464,7 @@
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 18px;
|
||||
background-color: #1a2233;
|
||||
background-color: var(--thesis-banner-bg);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: 8px;
|
||||
color: var(--text-secondary);
|
||||
@@ -1410,8 +1473,8 @@
|
||||
}
|
||||
|
||||
.thesis-ws-banner.ready {
|
||||
background-color: #10b9810f;
|
||||
border-color: #1f6f54;
|
||||
background-color: var(--chip-commitment-bg);
|
||||
border-color: var(--chip-commitment-border);
|
||||
}
|
||||
|
||||
.thesis-ws-banner-icon {
|
||||
@@ -1430,7 +1493,7 @@
|
||||
|
||||
.thesis-ws-node.selected {
|
||||
border-color: var(--accent);
|
||||
box-shadow: inset 0 0 0 1px #3b82c455;
|
||||
box-shadow: inset 0 0 0 1px var(--accent-wash);
|
||||
}
|
||||
|
||||
.thesis-ws-node-head {
|
||||
@@ -1470,7 +1533,7 @@
|
||||
|
||||
.thesis-ws-children {
|
||||
padding-left: 18px;
|
||||
border-left: 1px solid #1d2a3a;
|
||||
border-left: 1px solid var(--border);
|
||||
margin: 4px 0 4px 18px;
|
||||
}
|
||||
|
||||
@@ -1599,15 +1662,15 @@
|
||||
}
|
||||
|
||||
.index-job-pill.running {
|
||||
color: #fcd34d;
|
||||
background-color: #f59e0b22;
|
||||
color: var(--badge-priority-text);
|
||||
background-color: var(--badge-priority-bg);
|
||||
}
|
||||
|
||||
.index-job-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #fcd34d;
|
||||
background-color: var(--badge-priority-text);
|
||||
animation: index-job-pulse 1.2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@@ -1865,7 +1928,7 @@
|
||||
|
||||
.pipeline-stage-amount {
|
||||
font-size: 11px;
|
||||
color: #10b981;
|
||||
color: var(--money);
|
||||
}
|
||||
|
||||
.csv-preview {
|
||||
@@ -1919,7 +1982,7 @@
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
color: #10b981;
|
||||
color: var(--money);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
@@ -1991,7 +2054,7 @@
|
||||
z-index: 200;
|
||||
height: calc(var(--mobile-tab-bar-h) + env(safe-area-inset-bottom, 0px));
|
||||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||||
background: rgba(17, 26, 39, 0.92);
|
||||
background: var(--nav-bg);
|
||||
backdrop-filter: blur(8px);
|
||||
-webkit-backdrop-filter: blur(8px);
|
||||
border-top: 1px solid var(--border);
|
||||
@@ -2426,6 +2489,12 @@
|
||||
.desktop-only { display: none !important; }
|
||||
/* keep content clear of the fixed bottom bar */
|
||||
.content { padding-bottom: calc(var(--mobile-tab-bar-h) + env(safe-area-inset-bottom, 0px) + 16px); }
|
||||
/* DESIGN §4: toast is bottom-center above the tab bar on mobile, not bottom-right. */
|
||||
.toast {
|
||||
left: 16px; right: 16px; max-width: none;
|
||||
bottom: calc(var(--mobile-tab-bar-h) + env(safe-area-inset-bottom, 0px) + 8px);
|
||||
animation-name: slideInUp;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -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`
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user