diff --git a/index.html b/index.html index 4161a8c..fec5f01 100644 --- a/index.html +++ b/index.html @@ -28,7 +28,7 @@ document.documentElement.style.colorScheme = isDark ? "dark" : "light"; document .querySelector('meta[name="theme-color"]') - ?.setAttribute("content", isDark ? "#050505" : "#ffffff"); + ?.setAttribute("content", isDark ? "#000000" : "#ffffff"); })(); diff --git a/src/App.test.tsx b/src/App.test.tsx index 9b17950..364d9ba 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -208,6 +208,15 @@ describe("App", () => { name: /turn signals into evidence/i, }), ).toBeInTheDocument(); + for (const nextStep of [ + "Design a bounded pilot", + "Publish what happened", + "Choose the next move", + ]) { + expect( + within(howItWorks).getByRole("heading", { name: nextStep }), + ).toBeInTheDocument(); + } expect(howItWorks).toHaveTextContent(/no payment or commitment/i); expect( within(howItWorks).getByRole("link", { diff --git a/src/App.tsx b/src/App.tsx index 7d3044c..e0fd95f 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -105,6 +105,27 @@ const validationSteps = [ description: "Use aggregate demand—not private member activity—to decide whether to refine, pause, or prepare a small, permission-based pilot.", }, + { + icon: Wrench, + number: "04", + title: "Design a bounded pilot", + description: + "Define the participants, permissions, safeguards, measures, and stop conditions before testing the idea in the real world.", + }, + { + icon: BookOpen, + number: "05", + title: "Publish what happened", + description: + "Share outcomes, limits, surprises, and participant feedback without exposing private member activity or sensitive data.", + }, + { + icon: ArrowRight, + number: "06", + title: "Choose the next move", + description: + "Use the evidence to refine, repeat, pause, or archive the concept. Nothing advances automatically and every decision stays explainable.", + }, ]; const ideaTerrains = [ @@ -216,7 +237,7 @@ function HomePage() { showExplore={false} showStartIdea={false} /> -
+
(
- - {number} - +
+

{title} diff --git a/src/features/admin/admin-page.tsx b/src/features/admin/admin-page.tsx index f23f0da..4d56202 100644 --- a/src/features/admin/admin-page.tsx +++ b/src/features/admin/admin-page.tsx @@ -129,7 +129,7 @@ function AdminDashboard({ return ( <> -
+
diff --git a/src/features/auth/auth-callback-page.tsx b/src/features/auth/auth-callback-page.tsx index b9b1266..9ee8f8e 100644 --- a/src/features/auth/auth-callback-page.tsx +++ b/src/features/auth/auth-callback-page.tsx @@ -8,7 +8,7 @@ import { } from "@/features/auth/auth-return-path"; const pageClassName = - "field-grid contour-field relative grid min-h-screen place-items-center overflow-hidden bg-background px-6 py-12 text-foreground"; + "relative grid min-h-screen place-items-center overflow-hidden bg-background px-6 py-12 text-foreground"; const backdropClassName = "hidden"; const cardClassName = "field-panel relative w-full max-w-md border-t-4 border-t-primary p-8 text-center"; diff --git a/src/features/auth/auth-page.tsx b/src/features/auth/auth-page.tsx index 0dc32ce..64a12bd 100644 --- a/src/features/auth/auth-page.tsx +++ b/src/features/auth/auth-page.tsx @@ -81,7 +81,7 @@ export function AuthPage({ mode }: AuthPageProps) { } return ( -
+
-
+
{ideaQuery.isPending ? (
-
+
diff --git a/src/features/ideas/idea-editor-page.tsx b/src/features/ideas/idea-editor-page.tsx index 630fff5..8db37b1 100644 --- a/src/features/ideas/idea-editor-page.tsx +++ b/src/features/ideas/idea-editor-page.tsx @@ -216,7 +216,7 @@ export function IdeaEditorPage() { function EditorShell({ children }: { children: React.ReactNode }) { return ( -
+
-
+
diff --git a/src/features/profiles/profile-page.tsx b/src/features/profiles/profile-page.tsx index e4818b7..ac542b5 100644 --- a/src/features/profiles/profile-page.tsx +++ b/src/features/profiles/profile-page.tsx @@ -6,7 +6,7 @@ import { getPublicProfile } from "@/features/profiles/profile-service"; function ProfileShell({ children }: { children: ReactNode }) { return ( -
+
{ expect(window.localStorage.getItem("ideascape.theme")).toBe("dark"); expect(document.querySelector('meta[name="theme-color"]')).toHaveAttribute( "content", - "#050505", + "#000000", ); }); diff --git a/src/features/theme/theme-provider.tsx b/src/features/theme/theme-provider.tsx index 12f7775..e26781c 100644 --- a/src/features/theme/theme-provider.tsx +++ b/src/features/theme/theme-provider.tsx @@ -50,7 +50,7 @@ export function ThemeProvider({ children }: PropsWithChildren) { document.documentElement.style.colorScheme = theme; document .querySelector('meta[name="theme-color"]') - ?.setAttribute("content", theme === "dark" ? "#050505" : "#ffffff"); + ?.setAttribute("content", theme === "dark" ? "#000000" : "#ffffff"); }, [theme]); const value = useMemo( diff --git a/src/index.css b/src/index.css index f0bd017..3cbac3a 100644 --- a/src/index.css +++ b/src/index.css @@ -79,7 +79,7 @@ --chart-4: #a3a3a3; --chart-5: #e5e5e5; --radius: 0.375rem; - --sidebar: #fafafa; + --sidebar: #ffffff; --sidebar-foreground: #0a0a0a; --sidebar-primary: #0a0a0a; --sidebar-primary-foreground: #ffffff; @@ -90,14 +90,14 @@ } .dark { - --background: #050505; + --background: #000000; --foreground: #fafafa; - --card: #171717; + --card: #000000; --card-foreground: #fafafa; - --popover: #171717; + --popover: #000000; --popover-foreground: #fafafa; --primary: #fafafa; - --primary-foreground: #0a0a0a; + --primary-foreground: #000000; --secondary: #262626; --secondary-foreground: #fafafa; --muted: #262626; @@ -115,10 +115,10 @@ --chart-3: #a3a3a3; --chart-4: #525252; --chart-5: #262626; - --sidebar: #0a0a0a; + --sidebar: #000000; --sidebar-foreground: #fafafa; --sidebar-primary: #fafafa; - --sidebar-primary-foreground: #0a0a0a; + --sidebar-primary-foreground: #000000; --sidebar-accent: #262626; --sidebar-accent-foreground: #fafafa; --sidebar-border: #737373; @@ -144,53 +144,6 @@ } } -.field-grid { - background-image: - linear-gradient( - to right, - color-mix(in oklch, var(--border), transparent 55%) 1px, - transparent 1px - ), - linear-gradient( - to bottom, - color-mix(in oklch, var(--border), transparent 55%) 1px, - transparent 1px - ); - background-size: 32px 32px; -} - -.contour-field { - position: relative; - isolation: isolate; -} - -.contour-field::before { - position: absolute; - z-index: -1; - inset: 0; - pointer-events: none; - content: ""; - background-image: - radial-gradient( - ellipse at 108% 24%, - transparent 0 9rem, - color-mix(in oklch, var(--primary), transparent 82%) 9.05rem 9.12rem, - transparent 9.17rem 12rem, - color-mix(in oklch, var(--primary), transparent 88%) 12.05rem 12.12rem, - transparent 12.17rem 16rem, - var(--signal) 16.05rem 16.12rem, - transparent 16.17rem - ), - radial-gradient( - ellipse at -8% 86%, - transparent 0 7rem, - color-mix(in oklch, var(--primary), transparent 88%) 7.05rem 7.12rem, - transparent 7.17rem 10rem, - color-mix(in oklch, var(--primary), transparent 91%) 10.05rem 10.12rem, - transparent 10.17rem - ); -} - @layer components { .site-shell { @apply mx-auto w-full max-w-[90rem] px-4 sm:px-8 lg:px-12; diff --git a/src/theme-css.test.ts b/src/theme-css.test.ts index 3e56bd0..dfaeeea 100644 --- a/src/theme-css.test.ts +++ b/src/theme-css.test.ts @@ -294,6 +294,9 @@ describe("civic field-notebook design system", () => { it("uses only black, white, grayscale, and one bright orange signal", () => { expect(rootTheme).toContain("--background: #ffffff"); + expect(rootTheme).toContain("--card: #ffffff"); + expect(rootTheme).toContain("--popover: #ffffff"); + expect(rootTheme).toContain("--sidebar: #ffffff"); expect(rootTheme).toContain("--foreground: #0a0a0a"); expect(rootTheme).toContain("--primary: #0a0a0a"); expect(rootTheme).toContain("--signal: #ff5a1f"); @@ -302,7 +305,10 @@ describe("civic field-notebook design system", () => { expect(rootTheme).toContain("--border: #737373"); expect(rootTheme).toContain("--input: #737373"); expect(rootTheme).toContain("--radius: 0.375rem"); - expect(darkTheme).toContain("--background: #050505"); + expect(darkTheme).toContain("--background: #000000"); + expect(darkTheme).toContain("--card: #000000"); + expect(darkTheme).toContain("--popover: #000000"); + expect(darkTheme).toContain("--sidebar: #000000"); expect(darkTheme).toContain("--foreground: #fafafa"); expect(darkTheme).toContain("--primary: #fafafa"); expect(darkTheme).toContain("--signal: #ff5a1f"); @@ -398,10 +404,15 @@ describe("civic field-notebook design system", () => { ); }); - it("provides map-grid and contour-field composition primitives", () => { - expect(stylesheet).toMatch(/\.field-grid\s*\{[\s\S]*background-image:/); - expect(stylesheet).toMatch( - /\.contour-field::before\s*\{[\s\S]*background-image:/, + it("uses flat pure canvases without grid or contour backgrounds", () => { + const productionSources = listVisualSourceFiles( + resolve(process.cwd(), "src"), + ).map((file) => readFileSync(file, "utf8")); + expect(stylesheet).not.toContain("background-image:"); + expect(stylesheet).not.toContain(".field-grid"); + expect(stylesheet).not.toContain(".contour-field"); + expect(productionSources.join("\n")).not.toMatch( + /\b(?:field-grid|contour-field)\b/, ); });