diff --git a/apps/twig/build/app-icon.png b/apps/twig/build/app-icon.png
index eaac618d1..a20cb7c11 100644
Binary files a/apps/twig/build/app-icon.png and b/apps/twig/build/app-icon.png differ
diff --git a/apps/twig/forge.config.ts b/apps/twig/forge.config.ts
index 598d88120..3e262acdf 100644
--- a/apps/twig/forge.config.ts
+++ b/apps/twig/forge.config.ts
@@ -131,8 +131,8 @@ const config: ForgeConfig = {
"{**/*.node,**/spawn-helper,**/.vite/build/claude-cli/**,**/.vite/build/plugins/posthog/**,**/.vite/build/codex-acp/**,**/node_modules/node-pty/**,**/node_modules/@parcel/**,**/node_modules/file-icon/**}",
},
prune: false,
- name: "Twig",
- executableName: "Twig",
+ name: "PostHog Code",
+ executableName: "PostHog Code",
icon: "./build/app-icon", // Forge adds .icns/.ico/.png based on platform
appBundleId: "com.posthog.array", // TODO: Migrate to twig
appCategoryType: "public.app-category.productivity",
diff --git a/apps/twig/index.html b/apps/twig/index.html
index 3647b283c..6b829c8c6 100644
--- a/apps/twig/index.html
+++ b/apps/twig/index.html
@@ -3,9 +3,9 @@
-
+
- Twig
+ PostHog Code
diff --git a/apps/twig/src/main/bootstrap.ts b/apps/twig/src/main/bootstrap.ts
index 7635fccef..e91a457ac 100644
--- a/apps/twig/src/main/bootstrap.ts
+++ b/apps/twig/src/main/bootstrap.ts
@@ -16,7 +16,7 @@ const isDev = !app.isPackaged;
// Set app name for single-instance lock, crashReporter, etc
const appName = isDev ? "twig-dev" : "Twig";
-app.setName(isDev ? "Twig (Development)" : "Twig");
+app.setName(isDev ? "PostHog Code (Development)" : "PostHog Code");
// Set userData path for @posthog/twig
const appDataPath = app.getPath("appData");
diff --git a/apps/twig/src/main/menu.ts b/apps/twig/src/main/menu.ts
index 23ab31531..975f713cf 100644
--- a/apps/twig/src/main/menu.ts
+++ b/apps/twig/src/main/menu.ts
@@ -48,18 +48,18 @@ export function buildApplicationMenu(): void {
function buildAppMenu(): MenuItemConstructorOptions {
return {
- label: "Twig",
+ label: "PostHog Code",
submenu: [
{
- label: "About Twig",
+ label: "About PostHog Code",
click: () => {
const info = getSystemInfo();
dialog
.showMessageBox({
type: "info",
- title: "About Twig",
- message: "Twig",
+ title: "About PostHog Code",
+ message: "PostHog Code",
detail: info,
buttons: ["Copy", "OK"],
defaultId: 1,
@@ -149,7 +149,7 @@ function buildFileMenu(): MenuItemConstructorOptions {
const logContent = await readFile(logPath, "utf-8");
const header = [
"=".repeat(60),
- " Twig Log Export",
+ " PostHog Code Log Export",
"=".repeat(60),
"",
getSystemInfo(),
diff --git a/apps/twig/src/main/services/oauth/service.ts b/apps/twig/src/main/services/oauth/service.ts
index 44b6d4fde..08fffc7e5 100644
--- a/apps/twig/src/main/services/oauth/service.ts
+++ b/apps/twig/src/main/services/oauth/service.ts
@@ -365,9 +365,9 @@ export class OAuthService {
error: "Authorization failed",
};
const messages = {
- success: "You can close this window and return to Twig.",
- cancelled: "You can close this window and return to Twig.",
- error: "You can close this window and return to Twig.",
+ success: "You can close this window and return to PostHog Code.",
+ cancelled: "You can close this window and return to PostHog Code.",
+ error: "You can close this window and return to PostHog Code.",
};
return `
diff --git a/apps/twig/src/main/services/shell/service.test.ts b/apps/twig/src/main/services/shell/service.test.ts
index 0e67d1acf..0038c21d7 100644
--- a/apps/twig/src/main/services/shell/service.test.ts
+++ b/apps/twig/src/main/services/shell/service.test.ts
@@ -222,7 +222,7 @@ describe("ShellService", () => {
expect.any(Array),
expect.objectContaining({
env: expect.objectContaining({
- TERM_PROGRAM: "Twig",
+ TERM_PROGRAM: "PostHog Code",
COLORTERM: "truecolor",
FORCE_COLOR: "3",
}),
diff --git a/apps/twig/src/main/services/shell/service.ts b/apps/twig/src/main/services/shell/service.ts
index 2fee5e5cb..7265cb369 100644
--- a/apps/twig/src/main/services/shell/service.ts
+++ b/apps/twig/src/main/services/shell/service.ts
@@ -54,7 +54,7 @@ function buildShellEnv(
}
Object.assign(env, {
- TERM_PROGRAM: "Twig",
+ TERM_PROGRAM: "PostHog Code",
COLORTERM: "truecolor",
FORCE_COLOR: "3",
...additionalEnv,
diff --git a/apps/twig/src/main/trpc/routers/os.ts b/apps/twig/src/main/trpc/routers/os.ts
index 137b0a279..3a62188f7 100644
--- a/apps/twig/src/main/trpc/routers/os.ts
+++ b/apps/twig/src/main/trpc/routers/os.ts
@@ -143,7 +143,7 @@ export const osRouter = router({
const options = input.options;
const result = await dialog.showMessageBox(win, {
type: options?.type || "info",
- title: options?.title || "Twig",
+ title: options?.title || "PostHog Code",
message: options?.message || "",
detail: options?.detail,
buttons:
diff --git a/apps/twig/src/renderer/App.tsx b/apps/twig/src/renderer/App.tsx
index e4f6f4a44..97bf2e2f4 100644
--- a/apps/twig/src/renderer/App.tsx
+++ b/apps/twig/src/renderer/App.tsx
@@ -145,14 +145,14 @@ function App() {
initialize();
}, []);
- // Handle transition into main app (from onboarding completion)
+ // Handle transition into main app — only show the dark overlay if dark mode is active
useEffect(() => {
const isInMainApp = isAuthenticated && hasCompletedOnboarding;
- if (!wasInMainApp.current && isInMainApp) {
+ if (!wasInMainApp.current && isInMainApp && isDarkMode) {
setShowTransition(true);
}
wasInMainApp.current = isInMainApp;
- }, [isAuthenticated, hasCompletedOnboarding]);
+ }, [isAuthenticated, hasCompletedOnboarding, isDarkMode]);
const handleTransitionComplete = () => {
setShowTransition(false);
@@ -173,12 +173,7 @@ function App() {
const renderContent = () => {
if (!isAuthenticated) {
return (
-
+
);
@@ -187,13 +182,7 @@ function App() {
// Access check loading state
if (hasTwigAccess === null) {
return (
-
+
@@ -207,13 +196,7 @@ function App() {
// Access gate: show invite code screen if flag is not enabled
if (!hasTwigAccess) {
return (
-
+
);
@@ -221,13 +204,7 @@ function App() {
if (!hasCompletedOnboarding) {
return (
-
+
);
diff --git a/apps/twig/src/renderer/assets/images/bw-logo.png b/apps/twig/src/renderer/assets/images/bw-logo.png
new file mode 100644
index 000000000..a20cb7c11
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/bw-logo.png differ
diff --git a/apps/twig/src/renderer/assets/images/color-logo.png b/apps/twig/src/renderer/assets/images/color-logo.png
new file mode 100644
index 000000000..5c4f961d2
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/color-logo.png differ
diff --git a/apps/twig/src/renderer/assets/images/robo-zen.png b/apps/twig/src/renderer/assets/images/robo-zen.png
new file mode 100644
index 000000000..fd2d5e461
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/robo-zen.png differ
diff --git a/apps/twig/src/renderer/assets/images/wordmark-alt.png b/apps/twig/src/renderer/assets/images/wordmark-alt.png
new file mode 100644
index 000000000..938b60040
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/wordmark-alt.png differ
diff --git a/apps/twig/src/renderer/assets/images/wordmark.png b/apps/twig/src/renderer/assets/images/wordmark.png
new file mode 100644
index 000000000..e568369c6
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/wordmark.png differ
diff --git a/apps/twig/src/renderer/assets/images/zen.png b/apps/twig/src/renderer/assets/images/zen.png
new file mode 100644
index 000000000..babf0bc9e
Binary files /dev/null and b/apps/twig/src/renderer/assets/images/zen.png differ
diff --git a/apps/twig/src/renderer/components/ConnectivityPrompt.tsx b/apps/twig/src/renderer/components/ConnectivityPrompt.tsx
index 376d8c77c..61a01ecd8 100644
--- a/apps/twig/src/renderer/components/ConnectivityPrompt.tsx
+++ b/apps/twig/src/renderer/components/ConnectivityPrompt.tsx
@@ -28,8 +28,8 @@ export function ConnectivityPrompt({
- Twig requires an internet connection to use AI features. Check
- your connection and try again.
+ PostHog Code requires an internet connection to use AI features.
+ Check your connection and try again.
diff --git a/apps/twig/src/renderer/components/LoginTransition.tsx b/apps/twig/src/renderer/components/LoginTransition.tsx
index 6eec6494a..19414c7f6 100644
--- a/apps/twig/src/renderer/components/LoginTransition.tsx
+++ b/apps/twig/src/renderer/components/LoginTransition.tsx
@@ -19,7 +19,7 @@ export function LoginTransition({
position: "fixed",
inset: 0,
zIndex: 10000,
- background: "var(--cave-charcoal)",
+ background: "var(--gray-12)",
}}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
diff --git a/apps/twig/src/renderer/components/ScopeReauthPrompt.tsx b/apps/twig/src/renderer/components/ScopeReauthPrompt.tsx
index c2180be09..4b95ce505 100644
--- a/apps/twig/src/renderer/components/ScopeReauthPrompt.tsx
+++ b/apps/twig/src/renderer/components/ScopeReauthPrompt.tsx
@@ -45,8 +45,8 @@ export function ScopeReauthPrompt() {
- Twig has been updated with new features that require additional
- permissions. Please sign in again to continue.
+ PostHog Code has been updated with new features that require
+ additional permissions. Please sign in again to continue.
diff --git a/apps/twig/src/renderer/components/ThemeWrapper.tsx b/apps/twig/src/renderer/components/ThemeWrapper.tsx
index 3e3c06fad..6fb794ecb 100644
--- a/apps/twig/src/renderer/components/ThemeWrapper.tsx
+++ b/apps/twig/src/renderer/components/ThemeWrapper.tsx
@@ -23,8 +23,8 @@ export function ThemeWrapper({ children }: { children: React.ReactNode }) {
return (
{data.version
? `Version ${data.version} has been downloaded and is ready to install.`
- : "A new version of Twig has been downloaded and is ready to install."}
+ : "A new version of PostHog Code has been downloaded and is ready to install."}
@@ -170,7 +170,7 @@ export function UpdatePrompt() {
- Twig is up to date{versionSuffix}
+ PostHog Code is up to date{versionSuffix}
diff --git a/apps/twig/src/renderer/components/ZenHedgehog.tsx b/apps/twig/src/renderer/components/ZenHedgehog.tsx
new file mode 100644
index 000000000..c8e22249e
--- /dev/null
+++ b/apps/twig/src/renderer/components/ZenHedgehog.tsx
@@ -0,0 +1,75 @@
+import roboZen from "@renderer/assets/images/robo-zen.png";
+import zenHedgehog from "@renderer/assets/images/zen.png";
+import { useRef, useState } from "react";
+
+const DELAY_MS = 400; // calm pause before shaking starts
+const GROW_MS = 3500; // time to reach full intensity
+const MAX_X = 15; // px
+const MAX_ROTATE = 7; // deg
+const MIN_FREQ = 8; // Hz at onset
+const MAX_FREQ = 26; // Hz at peak
+
+export function ZenHedgehog() {
+ const [hovered, setHovered] = useState(false);
+ const imgRef = useRef(null);
+ const rafRef = useRef(null);
+ const enterTimeRef = useRef(null);
+
+ const tick = (now: number) => {
+ if (!enterTimeRef.current) enterTimeRef.current = now;
+ const elapsed = now - enterTimeRef.current;
+ const t = Math.max(0, elapsed - DELAY_MS);
+ const progress = Math.min(t / GROW_MS, 1);
+ const amplitude = progress * progress; // quadratic ease-in
+
+ if (amplitude > 0 && imgRef.current) {
+ const freq = MIN_FREQ + (MAX_FREQ - MIN_FREQ) * progress;
+ const phase = (now / 1000) * freq * 2 * Math.PI;
+ const x = Math.sin(phase) * MAX_X * amplitude;
+ const rotate = Math.sin(phase + 0.5) * MAX_ROTATE * amplitude;
+ const scale = 1 + Math.sin(phase * 1.7) * 0.03 * amplitude;
+ imgRef.current.style.transform = `translateX(${x}px) rotate(${rotate}deg) scale(${scale})`;
+ }
+
+ rafRef.current = requestAnimationFrame(tick);
+ };
+
+ const handleMouseEnter = () => {
+ setHovered(true);
+ enterTimeRef.current = null;
+ rafRef.current = requestAnimationFrame(tick);
+ };
+
+ const handleMouseLeave = () => {
+ setHovered(false);
+ if (rafRef.current) {
+ cancelAnimationFrame(rafRef.current);
+ rafRef.current = null;
+ }
+ enterTimeRef.current = null;
+ if (imgRef.current) {
+ imgRef.current.style.transform = "";
+ }
+ };
+
+ return (
+ // biome-ignore lint/a11y/noStaticElementInteractions: decorative hover animation
+
+

+
+ );
+}
diff --git a/apps/twig/src/renderer/features/auth/components/AuthScreen.tsx b/apps/twig/src/renderer/features/auth/components/AuthScreen.tsx
index bb3b0c6db..bef401dba 100644
--- a/apps/twig/src/renderer/features/auth/components/AuthScreen.tsx
+++ b/apps/twig/src/renderer/features/auth/components/AuthScreen.tsx
@@ -1,9 +1,9 @@
import { DraggableTitleBar } from "@components/DraggableTitleBar";
+import { ZenHedgehog } from "@components/ZenHedgehog";
import { useAuthStore } from "@features/auth/stores/authStore";
-import { Callout, Flex, Spinner, Text } from "@radix-ui/themes";
+import { Callout, Flex, Spinner, Text, Theme } from "@radix-ui/themes";
import posthogIcon from "@renderer/assets/images/posthog-icon.svg";
-import treeBg from "@renderer/assets/images/tree-bg.svg";
-import twigLogo from "@renderer/assets/images/twig-logo.svg";
+import phWordmark from "@renderer/assets/images/wordmark-alt.png";
import { trpcVanilla } from "@renderer/trpc/client";
import { REGION_LABELS } from "@shared/constants/oauth";
import type { CloudRegion } from "@shared/types/oauth";
@@ -85,211 +85,210 @@ export function AuthScreen() {
const errorMessage = getErrorMessage(error);
return (
-
-
+
+
+
- {/* Background */}
-
-
-
- {/* Left side with card */}
-
- {/* Scrim behind card area */}
+ {/* Background */}
- {/* Auth card */}
+ {/* Right panel — zen hedgehog */}
- {/* Logo */}
-
+
+
+ {/* Left side with card */}
+
+ {/* Auth card */}
+
+ >
+ {/* Logo */}
+
- {/* Error */}
- {errorMessage && (
-
- {errorMessage}
-
- )}
+ {/* Error */}
+ {errorMessage && (
+
+ {errorMessage}
+
+ )}
- {/* Pending state */}
- {isPending && (
-
- Waiting for authorization...
-
- )}
+ {/* Pending state */}
+ {isPending && (
+
+ Waiting for authorization...
+
+ )}
- {/* Primary CTA */}
-
-
-
- Redirects to PostHog.com
-
-
+ {/* Primary CTA */}
+
+
+
+ Redirects to PostHog.com
+
+
- {/* Region + secondary links */}
-
-
+ {/* Region + secondary links */}
+
+
-
- {authMode === "login" ? (
- <>
-
- Don't have an account?{" "}
-
-
- >
- ) : (
- <>
-
- Already have an account?{" "}
-
-
- >
- )}
-
+
+ {authMode === "login" ? (
+ <>
+
+ Don't have an account?{" "}
+
+
+ >
+ ) : (
+ <>
+
+ Already have an account?{" "}
+
+
+ >
+ )}
+
+
-
- {/* Right side - shows background */}
-
-
+ {/* Right side - shows background */}
+
+
+
);
}
diff --git a/apps/twig/src/renderer/features/auth/components/InviteCodeScreen.tsx b/apps/twig/src/renderer/features/auth/components/InviteCodeScreen.tsx
index 47281a449..9a71bed91 100644
--- a/apps/twig/src/renderer/features/auth/components/InviteCodeScreen.tsx
+++ b/apps/twig/src/renderer/features/auth/components/InviteCodeScreen.tsx
@@ -1,8 +1,8 @@
import { DraggableTitleBar } from "@components/DraggableTitleBar";
import { useAuthStore } from "@features/auth/stores/authStore";
-import { Callout, Flex, Spinner, Text } from "@radix-ui/themes";
-import treeBg from "@renderer/assets/images/tree-bg.svg";
-import twigLogo from "@renderer/assets/images/twig-logo.svg";
+import { Callout, Flex, Spinner, Text, Theme } from "@radix-ui/themes";
+import phWordmark from "@renderer/assets/images/wordmark-alt.png";
+import zenHedgehog from "@renderer/assets/images/zen.png";
import { useMutation } from "@tanstack/react-query";
import { useState } from "react";
@@ -25,166 +25,164 @@ export function InviteCodeScreen() {
const errorMessage = redeemMutation.error?.message ?? null;
return (
-
-
+
+
+
- {/* Background */}
-
-
-
- {/* Left side with card */}
-
- {/* Scrim behind card area */}
+ {/* Background */}
- {/* Invite code card */}
+ {/* Right panel — zen hedgehog */}
- {/* Logo */}
+
-
+ {/* Invite code card */}
+
- Enter your invite code to get started
-
+ {/* Logo */}
+
- {/* Error */}
- {errorMessage && (
-
- {errorMessage}
-
- )}
+
+ Enter your invite code to get started
+
- {/* Form */}
-
-
- {/* Log out link */}
-
-
-
- {/* Right side - shows background */}
-
-
+ {/* Right side - shows background */}
+
+
+
);
}
diff --git a/apps/twig/src/renderer/features/auth/components/RegionSelect.tsx b/apps/twig/src/renderer/features/auth/components/RegionSelect.tsx
index 904a4872b..4d8f3fc5e 100644
--- a/apps/twig/src/renderer/features/auth/components/RegionSelect.tsx
+++ b/apps/twig/src/renderer/features/auth/components/RegionSelect.tsx
@@ -21,7 +21,7 @@ export function RegionSelect({
if (!expanded) {
return (
-
+
{regionLabel}
{" \u00B7 "}
@@ -52,11 +52,11 @@ export function RegionSelect({
PostHog region
-
+
-
)}
@@ -216,7 +206,7 @@ export function GitIntegrationStep({
GitHub connected
@@ -224,7 +214,7 @@ export function GitIntegrationStep({
size="1"
align="center"
style={{
- color: "var(--cave-charcoal)",
+ color: "var(--gray-12)",
opacity: 0.7,
}}
>
@@ -248,7 +238,7 @@ export function GitIntegrationStep({
No git integration found
@@ -256,7 +246,7 @@ export function GitIntegrationStep({
size="1"
align="center"
style={{
- color: "var(--cave-charcoal)",
+ color: "var(--gray-12)",
opacity: 0.7,
}}
>
@@ -298,21 +288,14 @@ export function GitIntegrationStep({
alignItems: "center",
}}
>
-
+
Connect GitHub
@@ -323,7 +306,7 @@ export function GitIntegrationStep({
variant="ghost"
loading={isFetching}
onClick={handleRefresh}
- style={{ color: "var(--cave-charcoal)" }}
+ style={{ color: "var(--gray-12)" }}
>
Refresh status
@@ -347,7 +330,7 @@ export function GitIntegrationStep({
variant="ghost"
loading={isFetching}
onClick={handleRefresh}
- style={{ color: "var(--cave-charcoal)" }}
+ style={{ color: "var(--gray-12)" }}
>
Refresh status
@@ -370,20 +353,13 @@ export function GitIntegrationStep({
size="3"
variant="ghost"
onClick={onBack}
- style={{ color: "var(--cave-charcoal)" }}
+ style={{ color: "var(--gray-12)" }}
>
Back
{hasGitIntegration ? (
-
+
Continue
@@ -392,7 +368,7 @@ export function GitIntegrationStep({
size="3"
variant="outline"
onClick={handleContinue}
- style={{ color: "var(--cave-charcoal)" }}
+ style={{ color: "var(--gray-12)" }}
>
Skip for now
diff --git a/apps/twig/src/renderer/features/onboarding/components/OnboardingFlow.tsx b/apps/twig/src/renderer/features/onboarding/components/OnboardingFlow.tsx
index 2a194451d..a57a964a3 100644
--- a/apps/twig/src/renderer/features/onboarding/components/OnboardingFlow.tsx
+++ b/apps/twig/src/renderer/features/onboarding/components/OnboardingFlow.tsx
@@ -1,8 +1,8 @@
import { DraggableTitleBar } from "@components/DraggableTitleBar";
+import { ZenHedgehog } from "@components/ZenHedgehog";
import { useAuthStore } from "@features/auth/stores/authStore";
import { SignOut } from "@phosphor-icons/react";
-import { Button, Flex } from "@radix-ui/themes";
-import onboardingBg from "@renderer/assets/images/tree-bg.svg";
+import { Button, Flex, Theme } from "@radix-ui/themes";
import { AnimatePresence, motion } from "framer-motion";
import { useOnboardingFlow } from "../hooks/useOnboardingFlow";
@@ -21,120 +21,130 @@ export function OnboardingFlow() {
};
return (
-
-
-
- {/* Background */}
-
-
-
- {/* Content */}
+
+
+
+ {/* Background */}
+
+
+ {/* Right panel — zen hedgehog */}
+
+
+
+
+ {/* Content */}
-
- {currentStep === "welcome" && (
-
-
-
- )}
+
+
+ {currentStep === "welcome" && (
+
+
+
+ )}
- {currentStep === "billing" && (
-
-
-
- )}
+ {currentStep === "billing" && (
+
+
+
+ )}
- {currentStep === "org-billing" && (
-
-
-
- )}
+ {currentStep === "org-billing" && (
+
+
+
+ )}
- {currentStep === "git-integration" && (
-
-
-
- )}
-
-
+ {currentStep === "git-integration" && (
+
+
+
+ )}
+
+
-
-
-
- Log out
-
+
+
+
+ Log out
+
+
-
+
);
}
diff --git a/apps/twig/src/renderer/features/onboarding/components/OrgBillingStep.tsx b/apps/twig/src/renderer/features/onboarding/components/OrgBillingStep.tsx
index a4126924f..4e0eb32d7 100644
--- a/apps/twig/src/renderer/features/onboarding/components/OrgBillingStep.tsx
+++ b/apps/twig/src/renderer/features/onboarding/components/OrgBillingStep.tsx
@@ -10,7 +10,7 @@ import {
Skeleton,
Text,
} from "@radix-ui/themes";
-import twigLogo from "@renderer/assets/images/twig-logo.svg";
+import phWordmark from "@renderer/assets/images/wordmark-alt.png";
import { logger } from "@renderer/lib/logger";
import { useQueryClient } from "@tanstack/react-query";
import { AnimatePresence, motion } from "framer-motion";
@@ -77,8 +77,8 @@ export function OrgBillingStep({ onNext, onBack }: OrgBillingStepProps) {
>
Choose your organization
-
- Select which organization should be billed for your Twig usage.
+
+ Select which organization should be billed for your PostHog Code
+ usage.
@@ -137,9 +135,8 @@ export function OrgBillingStep({ onNext, onBack }: OrgBillingStepProps) {
px="4"
py="3"
style={{
- backgroundColor: "rgba(255, 255, 255, 0.7)",
- border: "2px solid rgba(0, 0, 0, 0.1)",
- backdropFilter: "blur(8px)",
+ backgroundColor: "var(--color-panel-solid)",
+ border: "2px solid var(--gray-4)",
}}
>
@@ -183,7 +180,7 @@ export function OrgBillingStep({ onNext, onBack }: OrgBillingStepProps) {
size="3"
variant="ghost"
onClick={onBack}
- style={{ color: "var(--cave-charcoal)" }}
+ style={{ color: "var(--gray-12)" }}
>
Back
@@ -192,10 +189,6 @@ export function OrgBillingStep({ onNext, onBack }: OrgBillingStepProps) {
size="3"
onClick={handleContinue}
disabled={!effectiveSelectedOrgId || isLoading || isSwitching}
- style={{
- backgroundColor: "var(--cave-charcoal)",
- color: "var(--cave-cream)",
- }}
>
{isSwitching ? "Switching..." : "Continue"}
{!isSwitching && }
@@ -228,20 +221,19 @@ function OrgCard({
py="3"
onClick={onSelect}
style={{
- backgroundColor: "rgba(255, 255, 255, 0.7)",
+ backgroundColor: "var(--color-panel-solid)",
border: isSelected
? "2px solid var(--accent-9)"
- : "2px solid rgba(0, 0, 0, 0.1)",
+ : "2px solid var(--gray-4)",
cursor: "pointer",
transition: "all 0.2s ease",
- backdropFilter: "blur(8px)",
}}
>
{name}
@@ -260,7 +252,7 @@ function OrgCard({
flexShrink="0"
style={{
borderRadius: "50%",
- border: isSelected ? "none" : "2px solid rgba(0, 0, 0, 0.2)",
+ border: isSelected ? "none" : "2px solid var(--gray-7)",
backgroundColor: isSelected ? "var(--accent-9)" : "transparent",
display: "flex",
alignItems: "center",
diff --git a/apps/twig/src/renderer/features/onboarding/components/ProjectSelect.tsx b/apps/twig/src/renderer/features/onboarding/components/ProjectSelect.tsx
index 3d2c3a32e..82c4eb13a 100644
--- a/apps/twig/src/renderer/features/onboarding/components/ProjectSelect.tsx
+++ b/apps/twig/src/renderer/features/onboarding/components/ProjectSelect.tsx
@@ -28,7 +28,7 @@ export function ProjectSelect({
if (projects.length <= 1) {
return (
-
+
{projectName}
);
@@ -36,7 +36,7 @@ export function ProjectSelect({
return (
-
+
{projectName}
{" · "}
diff --git a/apps/twig/src/renderer/features/onboarding/components/StepIndicator.tsx b/apps/twig/src/renderer/features/onboarding/components/StepIndicator.tsx
index c5f613519..17d1d45ac 100644
--- a/apps/twig/src/renderer/features/onboarding/components/StepIndicator.tsx
+++ b/apps/twig/src/renderer/features/onboarding/components/StepIndicator.tsx
@@ -22,9 +22,7 @@ export function StepIndicator({
height: 8,
borderRadius: "50%",
backgroundColor:
- index <= currentIndex
- ? "var(--accent-9)"
- : "rgba(255, 255, 255, 0.3)",
+ index <= currentIndex ? "var(--accent-9)" : "var(--gray-5)",
transition: "background-color 0.3s ease",
}}
/>
diff --git a/apps/twig/src/renderer/features/onboarding/components/WelcomeStep.tsx b/apps/twig/src/renderer/features/onboarding/components/WelcomeStep.tsx
index 1fffaeb81..d2c3cf63e 100644
--- a/apps/twig/src/renderer/features/onboarding/components/WelcomeStep.tsx
+++ b/apps/twig/src/renderer/features/onboarding/components/WelcomeStep.tsx
@@ -7,7 +7,7 @@ import {
Stack,
} from "@phosphor-icons/react";
import { Box, Button, Flex } from "@radix-ui/themes";
-import twigLogo from "@renderer/assets/images/twig-logo.svg";
+import phWordmark from "@renderer/assets/images/wordmark-alt.png";
import { FeatureListItem } from "./FeatureListItem";
interface WelcomeStepProps {
@@ -49,18 +49,24 @@ const FEATURES = [
export function WelcomeStep({ onNext }: WelcomeStepProps) {
return (
-
+
{/* Left side - features list */}
-
+
{FEATURES.map((feature) => (
-
+
Get Started
diff --git a/apps/twig/src/renderer/features/sessions/components/GeneratingIndicator.tsx b/apps/twig/src/renderer/features/sessions/components/GeneratingIndicator.tsx
index 159cd9dc8..6e981f4d8 100644
--- a/apps/twig/src/renderer/features/sessions/components/GeneratingIndicator.tsx
+++ b/apps/twig/src/renderer/features/sessions/components/GeneratingIndicator.tsx
@@ -49,7 +49,7 @@ export function GeneratingIndicator({ startedAt }: GeneratingIndicatorProps) {
className="select-none text-accent-11"
style={{ userSelect: "none", WebkitUserSelect: "none" }}
>
-
+
{ACTIVITIES[activityIndex]}...
(Esc to interrupt
diff --git a/apps/twig/src/renderer/features/settings/components/FolderSettingsView.tsx b/apps/twig/src/renderer/features/settings/components/FolderSettingsView.tsx
index 5c0e4bc3a..0ed1232e8 100644
--- a/apps/twig/src/renderer/features/settings/components/FolderSettingsView.tsx
+++ b/apps/twig/src/renderer/features/settings/components/FolderSettingsView.tsx
@@ -123,9 +123,9 @@ export function FolderSettingsView() {
Option 2: Remove the repository
- This will remove the repository from Twig, including all
- associated tasks and their workspaces. This action cannot be
- undone.
+ This will remove the repository from PostHog Code, including
+ all associated tasks and their workspaces. This action
+ cannot be undone.
- This will remove the repository from Twig, including all
- associated tasks and their workspaces. This action cannot be
- undone.
+ This will remove the repository from PostHog Code, including
+ all associated tasks and their workspaces. This action
+ cannot be undone.
- In Bypass Permissions mode, Twig will not ask for your approval
- before running potentially dangerous commands.
+ In Bypass Permissions mode, PostHog Code will not ask for your
+ approval before running potentially dangerous commands.
This mode should only be used in a sandboxed container/VM that
diff --git a/apps/twig/src/renderer/features/settings/components/sections/GeneralSettings.tsx b/apps/twig/src/renderer/features/settings/components/sections/GeneralSettings.tsx
index 986f173ff..72ed1b388 100644
--- a/apps/twig/src/renderer/features/settings/components/sections/GeneralSettings.tsx
+++ b/apps/twig/src/renderer/features/settings/components/sections/GeneralSettings.tsx
@@ -91,7 +91,7 @@ export function GeneralSettings() {
if (permission !== "granted") {
toast.info("Notifications are blocked", {
description:
- "Allow Twig notifications in System Settings > Notifications",
+ "Allow PostHog Code notifications in System Settings > Notifications",
});
return;
}
@@ -356,7 +356,8 @@ export function GeneralSettings() {
{notificationsDenied && (
Notifications are blocked by macOS. To enable them, open System
- Settings > Notifications > Twig and turn on Allow Notifications.
+ Settings > Notifications > PostHog Code and turn on Allow
+ Notifications.
)}
diff --git a/apps/twig/src/renderer/features/sidebar/components/ProjectSwitcher.tsx b/apps/twig/src/renderer/features/sidebar/components/ProjectSwitcher.tsx
index bc2fe94fc..906d3ba28 100644
--- a/apps/twig/src/renderer/features/sidebar/components/ProjectSwitcher.tsx
+++ b/apps/twig/src/renderer/features/sidebar/components/ProjectSwitcher.tsx
@@ -253,7 +253,7 @@ export function ProjectSwitcher() {
onClick={() => handleOpenExternal("https://twig.com")}
>
- Twig Website
+ PostHog Code Website
= (payload: EventPayloadMap[T]) => void;
function getTerminalTheme(isDarkMode: boolean) {
- // Warm cave-inspired terminal colors
return isDarkMode
? {
background: "transparent",
- foreground: "#f7eddf",
- cursor: "#dc9300",
- cursorAccent: "#f7eddf",
- selectionBackground: "rgba(255, 203, 129, 0.3)",
- selectionForeground: "#f7eddf",
+ foreground: "#e6e6e6",
+ cursor: "#f8be2a",
+ cursorAccent: "#131316",
+ selectionBackground: "rgba(248, 190, 42, 0.25)",
+ selectionForeground: "#e6e6e6",
}
: {
background: "transparent",
- foreground: "#2d2b29",
- cursor: "#dc9300",
- cursorAccent: "#2d2b29",
- selectionBackground: "rgba(255, 189, 87, 0.4)",
- selectionForeground: "#2d2b29",
+ foreground: "#0d0d0d",
+ cursor: "#f54d00",
+ cursorAccent: "#f2f3ee",
+ selectionBackground: "rgba(245, 77, 0, 0.2)",
+ selectionForeground: "#0d0d0d",
};
}
diff --git a/apps/twig/src/renderer/lib/notifications.ts b/apps/twig/src/renderer/lib/notifications.ts
index 12497250e..04a58b3c5 100644
--- a/apps/twig/src/renderer/lib/notifications.ts
+++ b/apps/twig/src/renderer/lib/notifications.ts
@@ -56,7 +56,7 @@ export function notifyPromptComplete(
if (desktopNotifications) {
sendDesktopNotification(
- "Twig",
+ "PostHog Code",
`"${truncateTitle(taskTitle)}" finished`,
willPlayCustomSound,
);
@@ -85,7 +85,7 @@ export function notifyPermissionRequest(taskTitle: string): void {
if (desktopNotifications) {
sendDesktopNotification(
- "Twig",
+ "PostHog Code",
`"${truncateTitle(taskTitle)}" needs your input`,
willPlayCustomSound,
);
diff --git a/apps/twig/src/renderer/main.tsx b/apps/twig/src/renderer/main.tsx
index f8f8b0e30..52e3c0176 100644
--- a/apps/twig/src/renderer/main.tsx
+++ b/apps/twig/src/renderer/main.tsx
@@ -10,7 +10,9 @@ import "./styles/globals.css";
const log = logger.scope("app");
log.info("Twig renderer booting up");
-document.title = import.meta.env.DEV ? "Twig (Development)" : "Twig";
+document.title = import.meta.env.DEV
+ ? "PostHog Code (Development)"
+ : "PostHog Code";
const rootElement = document.getElementById("root");
if (!rootElement) throw new Error("Root element not found");
diff --git a/apps/twig/src/renderer/styles/globals.css b/apps/twig/src/renderer/styles/globals.css
index 7aafee8e0..1ab144ce3 100644
--- a/apps/twig/src/renderer/styles/globals.css
+++ b/apps/twig/src/renderer/styles/globals.css
@@ -121,27 +121,40 @@
}
:root {
- --cave-cream: #f7eddf;
- --cave-charcoal: #2d2b29;
- --fire-glow: rgba(255, 140, 60, 0.15);
- --fire-glow-bright: rgba(255, 120, 50, 0.6);
+ --ph-orange: #f54d00;
+ --ph-yellow: #f8be2a;
}
-/* Campfire pulse animation for generating indicator */
-@keyframes campfire-pulse {
+/* Zen hedgehog float animation for auth/onboarding screens */
+@keyframes zen-float {
+ 0%,
+ 100% {
+ transform: translateY(0px);
+ }
+ 50% {
+ transform: translateY(-14px);
+ }
+}
+
+.zen-float {
+ animation: zen-float 3.5s ease-in-out infinite;
+}
+
+/* Pulse animation for generating indicator */
+@keyframes ph-pulse {
0%,
100% {
opacity: 1;
- color: var(--orange-9);
+ color: var(--accent-9);
}
50% {
opacity: 0.5;
- color: var(--orange-11);
+ color: var(--accent-11);
}
}
-.campfire-pulse {
- animation: campfire-pulse 1s ease-in-out infinite;
+.ph-pulse {
+ animation: ph-pulse 1s ease-in-out infinite;
}
.radix-themes {
@@ -638,336 +651,168 @@ body {
:root,
.light,
.light-theme {
- --yellow-1: #ecebe9;
- --yellow-2: #f1e5d5;
- --yellow-3: #fcd9ac;
- --yellow-4: #ffcb81;
- --yellow-5: #ffbd57;
- --yellow-6: #f1b154;
- --yellow-7: #de9f41;
- --yellow-8: #ce8500;
- --yellow-9: #dc9300;
- --yellow-10: #d08800;
- --yellow-11: #8a5400;
- --yellow-12: #4d3616;
-
- --yellow-a1: #8924ea05;
- --yellow-a2: #ffb7782d;
- --yellow-a3: #ffd59fd2;
- --yellow-a4: #ffcb81;
- --yellow-a5: #ffbd57;
- --yellow-a6: #ff00002d;
- --yellow-a7: #d88000b8;
- --yellow-a8: #ce8500;
- --yellow-a9: #dc9300;
- --yellow-a10: #d08800;
- --yellow-a11: #8a5400;
- --yellow-a12: #3d2300e7;
-
- --yellow-contrast: #fff;
- --yellow-surface: #f1e3d0cc;
- --yellow-indicator: #dc9300;
- --yellow-track: #dc9300;
-}
-
-@supports (color: color(display-p3 1 1 1)) {
- @media (color-gamut: p3) {
- :root,
- .light,
- .light-theme {
- --yellow-1: oklch(93.9% 0.0029 73.83);
- --yellow-2: oklch(92.6% 0.0248 73.83);
- --yellow-3: oklch(90.5% 0.0701 73.83);
- --yellow-4: oklch(87.5% 0.1103 73.83);
- --yellow-5: oklch(84.3% 0.1411 73.83);
- --yellow-6: oklch(80.3% 0.1324 73.83);
- --yellow-7: oklch(74.6% 0.1315 73.83);
- --yellow-8: oklch(67.5% 0.1525 73.83);
- --yellow-9: oklch(71.9% 0.1525 73.83);
- --yellow-10: oklch(68.2% 0.1525 73.83);
- --yellow-11: oklch(49.4% 0.1525 73.83);
- --yellow-12: oklch(35.2% 0.0567 73.83);
-
- --yellow-a1: color(display-p3 0.4745 0.0157 0.6902 / 0.017);
- --yellow-a2: color(display-p3 1 0.2745 0 / 0.059);
- --yellow-a3: color(display-p3 1 0.7647 0.4549 / 0.471);
- --yellow-a4: color(display-p3 1 0.6863 0.2157 / 0.53);
- --yellow-a5: color(display-p3 1 0.4902 0 / 0.412);
- --yellow-a6: color(display-p3 0.8863 0.5333 0 / 0.573);
- --yellow-a7: color(display-p3 0.7843 0.4667 0 / 0.646);
- --yellow-a8: color(display-p3 0.7255 0.4353 0 / 0.804);
- --yellow-a9: color(display-p3 0.7882 0.4902 0 / 0.783);
- --yellow-a10: color(display-p3 0.7373 0.4471 0 / 0.8);
- --yellow-a11: color(display-p3 0.4549 0.2627 0 / 0.885);
- --yellow-a12: color(display-p3 0.2078 0.1255 0 / 0.885);
-
- --yellow-contrast: #fff;
- --yellow-surface: color(display-p3 0.9373 0.8902 0.8275 / 0.8);
- --yellow-indicator: oklch(71.9% 0.1525 73.83);
- --yellow-track: oklch(71.9% 0.1525 73.83);
- }
- }
+ /* PostHog brand orange scale (accent for light mode) */
+ --orange-1: #fff5f0;
+ --orange-2: #ffe8dc;
+ --orange-3: #ffd0b8;
+ --orange-4: #ffb38a;
+ --orange-5: #ff8f56;
+ --orange-6: #f57030;
+ --orange-7: #e05a18;
+ --orange-8: #c94800;
+ --orange-9: #f54d00;
+ --orange-10: #e64600;
+ --orange-11: #a33300;
+ --orange-12: #4d1800;
+
+ --orange-a1: rgba(245, 77, 0, 0.04);
+ --orange-a2: rgba(245, 77, 0, 0.1);
+ --orange-a3: rgba(245, 77, 0, 0.18);
+ --orange-a4: rgba(245, 77, 0, 0.3);
+ --orange-a5: rgba(245, 77, 0, 0.42);
+ --orange-a6: rgba(245, 77, 0, 0.54);
+ --orange-a7: rgba(200, 60, 0, 0.64);
+ --orange-a8: rgba(180, 50, 0, 0.76);
+ --orange-a9: rgba(245, 77, 0, 0.9);
+ --orange-a10: rgba(220, 70, 0, 0.9);
+ --orange-a11: rgba(160, 48, 0, 0.94);
+ --orange-a12: rgba(60, 16, 0, 0.94);
+
+ --orange-contrast: #fff;
+ --orange-surface: rgba(255, 245, 240, 0.8);
+ --orange-indicator: #f54d00;
+ --orange-track: #f54d00;
}
:root,
.light,
.light-theme {
- /* Warm cave-inspired gray palette */
- --gray-1: #f7eddf;
- --gray-2: #f1e5d5;
- --gray-3: #ebe1d3;
- --gray-4: #ddd5c7;
- --gray-5: #cec6b8;
- --gray-6: #b8b0a2;
- --gray-7: #a39b8d;
- --gray-8: #9a9282;
- --gray-9: #6e665a;
- --gray-10: #5e564a;
- --gray-11: #3d3832;
- --gray-12: #2d2b29;
-
- --gray-a1: #3d280005;
- --gray-a2: #3d28000a;
- --gray-a3: #3d280012;
- --gray-a4: #3d28001f;
- --gray-a5: #3d28002d;
- --gray-a6: #3d28003d;
- --gray-a7: #3d280052;
- --gray-a8: #3d280066;
- --gray-a9: #3d28009e;
- --gray-a10: #3d2800ad;
- --gray-a11: #3d2800c7;
- --gray-a12: #2d2b29ed;
+ /* PostHog-inspired neutral greenish-grey palette */
+ --gray-1: #f2f3ee;
+ --gray-2: #eceee8;
+ --gray-3: #e4e5de;
+ --gray-4: #d8dbd1;
+ --gray-5: #cbd0c3;
+ --gray-6: #bcc1b4;
+ --gray-7: #a9af9f;
+ --gray-8: #93998a;
+ --gray-9: #6b7165;
+ --gray-10: #5a6054;
+ --gray-11: #3a4036;
+ --gray-12: #0d0d0d;
+
+ --gray-a1: rgba(20, 24, 10, 0.02);
+ --gray-a2: rgba(20, 24, 10, 0.05);
+ --gray-a3: rgba(20, 24, 10, 0.1);
+ --gray-a4: rgba(20, 24, 10, 0.16);
+ --gray-a5: rgba(20, 24, 10, 0.22);
+ --gray-a6: rgba(20, 24, 10, 0.29);
+ --gray-a7: rgba(20, 24, 10, 0.38);
+ --gray-a8: rgba(20, 24, 10, 0.48);
+ --gray-a9: rgba(20, 24, 10, 0.62);
+ --gray-a10: rgba(20, 24, 10, 0.7);
+ --gray-a11: rgba(20, 24, 10, 0.79);
+ --gray-a12: rgba(13, 13, 13, 0.92);
--gray-contrast: #ffffff;
- --gray-surface: #f7eddfcc;
- --gray-indicator: #6e665a;
- --gray-track: #6e665a;
-}
-
-@supports (color: color(display-p3 1 1 1)) {
- @media (color-gamut: p3) {
- :root,
- .light,
- .light-theme {
- /* Warm cave-inspired gray palette (P3) */
- --gray-1: oklch(95.5% 0.015 75);
- --gray-2: oklch(93% 0.02 75);
- --gray-3: oklch(91% 0.022 75);
- --gray-4: oklch(87.5% 0.02 75);
- --gray-5: oklch(83% 0.018 75);
- --gray-6: oklch(76% 0.016 75);
- --gray-7: oklch(69% 0.014 75);
- --gray-8: oklch(65% 0.012 75);
- --gray-9: oklch(50% 0.015 75);
- --gray-10: oklch(44% 0.015 75);
- --gray-11: oklch(33% 0.012 75);
- --gray-12: oklch(26% 0.01 75);
-
- --gray-a1: color(display-p3 0.24 0.16 0 / 0.02);
- --gray-a2: color(display-p3 0.24 0.16 0 / 0.04);
- --gray-a3: color(display-p3 0.24 0.16 0 / 0.07);
- --gray-a4: color(display-p3 0.24 0.16 0 / 0.12);
- --gray-a5: color(display-p3 0.24 0.16 0 / 0.18);
- --gray-a6: color(display-p3 0.24 0.16 0 / 0.24);
- --gray-a7: color(display-p3 0.24 0.16 0 / 0.32);
- --gray-a8: color(display-p3 0.24 0.16 0 / 0.4);
- --gray-a9: color(display-p3 0.24 0.16 0 / 0.62);
- --gray-a10: color(display-p3 0.24 0.16 0 / 0.68);
- --gray-a11: color(display-p3 0.24 0.16 0 / 0.78);
- --gray-a12: color(display-p3 0.18 0.17 0.16 / 0.93);
-
- --gray-contrast: #ffffff;
- --gray-surface: color(display-p3 0.969 0.929 0.875 / 80%);
- --gray-indicator: oklch(50% 0.015 75);
- --gray-track: oklch(50% 0.015 75);
- }
- }
+ --gray-surface: rgba(242, 243, 238, 0.8);
+ --gray-indicator: #6b7165;
+ --gray-track: #6b7165;
}
:root,
.light,
.light-theme,
.radix-themes {
- --color-background: #f7eddf;
- --terminal-foreground: #2d2b29;
+ --color-background: #f2f3ee;
+ --terminal-foreground: #0d0d0d;
--terminal-background: transparent;
- --terminal-cursor: #dc9300;
- --terminal-cursor-accent: #f7eddf;
- --terminal-selection-bg: rgba(255, 189, 87, 0.4);
- --terminal-selection-fg: #2d2b29;
+ --terminal-cursor: #f54d00;
+ --terminal-cursor-accent: #f2f3ee;
+ --terminal-selection-bg: rgba(245, 77, 0, 0.2);
+ --terminal-selection-fg: #0d0d0d;
}
.dark,
.dark-theme {
- --orange-1: #181410;
- --orange-2: #1e1911;
- --orange-3: #2e210e;
- --orange-4: #3f2700;
- --orange-5: #4c3101;
- --orange-6: #5a3e13;
- --orange-7: #6e5022;
- --orange-8: #8d662d;
- --orange-9: #f1a82c;
- --orange-10: #e69d18;
- --orange-11: #f9b858;
- --orange-12: #fbe3c4;
-
- --orange-a1: #d5000004;
- --orange-a2: #fb7c000a;
- --orange-a3: #f983001c;
- --orange-a4: #fe79002e;
- --orange-a5: #ff8c003c;
- --orange-a6: #fd9f0f4c;
- --orange-a7: #ffb13861;
- --orange-a8: #ffb34483;
- --orange-a9: #ffb12ef0;
- --orange-a10: #ffad19e4;
- --orange-a11: #ffbc5af9;
- --orange-a12: #ffe7c7fb;
-
- --orange-contrast: #2d1f0a;
- --orange-surface: #271d0e80;
- --orange-indicator: #f1a82c;
- --orange-track: #f1a82c;
-}
-
-@supports (color: color(display-p3 1 1 1)) {
- @media (color-gamut: p3) {
- .dark,
- .dark-theme {
- --orange-1: oklch(19.6% 0.01 74.81);
- --orange-2: oklch(21.5% 0.0156 74.81);
- --orange-3: oklch(26% 0.037 74.81);
- --orange-4: oklch(29.5% 0.0632 74.81);
- --orange-5: oklch(33.6% 0.0699 74.81);
- --orange-6: oklch(38.7% 0.0689 74.81);
- --orange-7: oklch(45.3% 0.0738 74.81);
- --orange-8: oklch(53.9% 0.089 74.81);
- --orange-9: oklch(78.3% 0.1533 74.81);
- --orange-10: oklch(74.9% 0.1533 74.81);
- --orange-11: oklch(82.6% 0.1347 74.81);
- --orange-12: oklch(92.9% 0.0492 74.81);
-
- --orange-a1: color(display-p3 0.9569 0 0 / 0.009);
- --orange-a2: color(display-p3 0.9804 0.5333 0 / 0.035);
- --orange-a3: color(display-p3 0.9961 0.6 0 / 0.099);
- --orange-a4: color(display-p3 1 0.5294 0 / 0.167);
- --orange-a5: color(display-p3 1 0.6078 0 / 0.218);
- --orange-a6: color(display-p3 1 0.6784 0.1686 / 0.278);
- --orange-a7: color(display-p3 1 0.7412 0.3137 / 0.359);
- --orange-a8: color(display-p3 1 0.749 0.3569 / 0.488);
- --orange-a9: color(display-p3 1 0.7412 0.3098 / 0.894);
- --orange-a10: color(display-p3 1 0.7255 0.2706 / 0.847);
- --orange-a11: color(display-p3 1 0.7843 0.4353 / 0.932);
- --orange-a12: color(display-p3 1 0.9216 0.8078 / 0.966);
-
- --orange-contrast: #2d1f0a;
- --orange-surface: color(display-p3 0.1412 0.1098 0.0588 / 0.5);
- --orange-indicator: oklch(78.3% 0.1533 74.81);
- --orange-track: oklch(78.3% 0.1533 74.81);
- }
- }
+ /* PostHog brand yellow scale (accent for dark mode) */
+ --yellow-1: #14120a;
+ --yellow-2: #1a1608;
+ --yellow-3: #261e07;
+ --yellow-4: #362900;
+ --yellow-5: #443300;
+ --yellow-6: #524007;
+ --yellow-7: #6b561a;
+ --yellow-8: #8c7230;
+ --yellow-9: #f8be2a;
+ --yellow-10: #ebb520;
+ --yellow-11: #fcc84e;
+ --yellow-12: #fde8b8;
+
+ --yellow-a1: rgba(248, 190, 42, 0.02);
+ --yellow-a2: rgba(248, 190, 42, 0.05);
+ --yellow-a3: rgba(248, 190, 42, 0.1);
+ --yellow-a4: rgba(248, 190, 42, 0.18);
+ --yellow-a5: rgba(248, 190, 42, 0.25);
+ --yellow-a6: rgba(248, 190, 42, 0.35);
+ --yellow-a7: rgba(248, 190, 42, 0.48);
+ --yellow-a8: rgba(248, 190, 42, 0.62);
+ --yellow-a9: rgba(248, 190, 42, 0.92);
+ --yellow-a10: rgba(230, 175, 30, 0.9);
+ --yellow-a11: rgba(252, 200, 78, 0.96);
+ --yellow-a12: rgba(253, 232, 184, 0.98);
+
+ --yellow-contrast: #1a1200;
+ --yellow-surface: rgba(20, 18, 10, 0.5);
+ --yellow-indicator: #f8be2a;
+ --yellow-track: #f8be2a;
}
.dark,
.dark-theme {
- /* Warm cave-inspired dark gray palette */
- --gray-1: #1a1815;
- --gray-2: #211e1a;
- --gray-3: #2a2621;
- --gray-4: #322e28;
- --gray-5: #3b362f;
- --gray-6: #453f37;
- --gray-7: #524b42;
- --gray-8: #6e665a;
- --gray-9: #8a8275;
- --gray-10: #9a9282;
- --gray-11: #c4baa8;
- --gray-12: #f7eddf;
-
- --gray-a1: #00000000;
- --gray-a2: #f7eddf08;
- --gray-a3: #f7eddf10;
- --gray-a4: #f7eddf18;
- --gray-a5: #f7eddf20;
- --gray-a6: #f7eddf2a;
- --gray-a7: #f7eddf38;
- --gray-a8: #f7eddf52;
- --gray-a9: #f7eddf6a;
- --gray-a10: #f7eddf7a;
- --gray-a11: #f7eadfb8;
- --gray-a12: #f7eddfed;
+ /* PostHog-inspired cool blue-grey dark palette */
+ --gray-1: #131316;
+ --gray-2: #18181f;
+ --gray-3: #1e1e28;
+ --gray-4: #24243e;
+ --gray-5: #2a2a37;
+ --gray-6: #2e2e3d;
+ --gray-7: #40405a;
+ --gray-8: #616180;
+ --gray-9: #7c7c9e;
+ --gray-10: #8d8daa;
+ --gray-11: #9898b6;
+ --gray-12: #e6e6e6;
+
+ --gray-a1: rgba(200, 200, 240, 0);
+ --gray-a2: rgba(200, 200, 240, 0.03);
+ --gray-a3: rgba(200, 200, 240, 0.07);
+ --gray-a4: rgba(200, 200, 240, 0.1);
+ --gray-a5: rgba(200, 200, 240, 0.14);
+ --gray-a6: rgba(200, 200, 240, 0.18);
+ --gray-a7: rgba(200, 200, 240, 0.24);
+ --gray-a8: rgba(200, 200, 240, 0.36);
+ --gray-a9: rgba(200, 200, 240, 0.48);
+ --gray-a10: rgba(200, 200, 240, 0.55);
+ --gray-a11: rgba(200, 200, 240, 0.7);
+ --gray-a12: rgba(230, 230, 230, 0.92);
--gray-contrast: #ffffff;
- --gray-surface: rgba(26, 24, 21, 0.5);
- --gray-indicator: #8a8275;
- --gray-track: #8a8275;
-}
-
-@supports (color: color(display-p3 1 1 1)) {
- @media (color-gamut: p3) {
- .dark,
- .dark-theme {
- /* Warm cave-inspired dark gray palette (P3) */
- --gray-1: oklch(18% 0.012 75);
- --gray-2: oklch(21% 0.014 75);
- --gray-3: oklch(25% 0.016 75);
- --gray-4: oklch(28% 0.016 75);
- --gray-5: oklch(32% 0.015 75);
- --gray-6: oklch(36% 0.014 75);
- --gray-7: oklch(42% 0.013 75);
- --gray-8: oklch(50% 0.015 75);
- --gray-9: oklch(60% 0.014 75);
- --gray-10: oklch(65% 0.012 75);
- --gray-11: oklch(80% 0.018 75);
- --gray-12: oklch(95.5% 0.015 75);
-
- --gray-a1: color(display-p3 0 0 0 / 0);
- --gray-a2: color(display-p3 0.969 0.929 0.875 / 0.03);
- --gray-a3: color(display-p3 0.969 0.929 0.875 / 0.065);
- --gray-a4: color(display-p3 0.969 0.929 0.875 / 0.095);
- --gray-a5: color(display-p3 0.969 0.929 0.875 / 0.125);
- --gray-a6: color(display-p3 0.969 0.929 0.875 / 0.165);
- --gray-a7: color(display-p3 0.969 0.929 0.875 / 0.22);
- --gray-a8: color(display-p3 0.969 0.929 0.875 / 0.32);
- --gray-a9: color(display-p3 0.969 0.929 0.875 / 0.42);
- --gray-a10: color(display-p3 0.969 0.929 0.875 / 0.48);
- --gray-a11: color(display-p3 0.969 0.929 0.875 / 0.72);
- --gray-a12: color(display-p3 0.969 0.929 0.875 / 0.93);
-
- --gray-contrast: #ffffff;
- --gray-surface: color(display-p3 0.1 0.094 0.082 / 50%);
- --gray-indicator: oklch(60% 0.014 75);
- --gray-track: oklch(60% 0.014 75);
- }
- }
+ --gray-surface: rgba(19, 19, 22, 0.5);
+ --gray-indicator: #7c7c9e;
+ --gray-track: #7c7c9e;
}
.dark,
.dark-theme,
:is(.dark, .dark-theme) :where(.radix-themes:not(.light, .light-theme)) {
- --color-background: #1a1815;
- --terminal-foreground: #f7eddf;
+ --color-background: #131316;
+ --terminal-foreground: #e6e6e6;
--terminal-background: transparent;
- --terminal-cursor: #dc9300;
- --terminal-cursor-accent: #f7eddf;
- --terminal-selection-bg: rgba(255, 203, 129, 0.3);
- --terminal-selection-fg: #f7eddf;
-}
-
-/* Organic/cave-like border radius utility */
-.cave-organic {
- border-radius: 2px 6px 4px 8px;
- box-shadow: inset 0 0 8px rgba(0, 0, 0, 0.03);
-}
-
-.cave-organic-sm {
- border-radius: 1px 4px 2px 5px;
-}
-
-.cave-organic-lg {
- border-radius: 4px 10px 6px 12px;
+ --terminal-cursor: #f8be2a;
+ --terminal-cursor-accent: #131316;
+ --terminal-selection-bg: rgba(248, 190, 42, 0.25);
+ --terminal-selection-fg: #e6e6e6;
}
/* Buttons and menu items should have pointer cursor */
@@ -978,6 +823,23 @@ button,
cursor: pointer;
}
+/* PostHog Lemon UI button style — applies to solid buttons in explicitly-light Theme wrappers
+ (auth screen, onboarding flow). Uses the 3D depth shadow and lift-on-hover effect. */
+.radix-themes[data-appearance="light"] .rt-Button[data-variant="solid"] {
+ box-shadow: 0 3px 0 -1px var(--accent-8);
+ border-radius: 6px;
+ transition:
+ transform 100ms ease,
+ box-shadow 100ms ease;
+}
+.radix-themes[data-appearance="light"] .rt-Button[data-variant="solid"]:hover {
+ transform: translateY(-1px);
+}
+.radix-themes[data-appearance="light"] .rt-Button[data-variant="solid"]:active {
+ transform: translateY(1px);
+ box-shadow: none;
+}
+
/* Custom hover states for Select/Menu items - slightly lighter than background */
.rt-SelectItem[data-highlighted],
.rt-BaseMenuItem[data-highlighted] {
diff --git a/apps/twig/tailwind.config.js b/apps/twig/tailwind.config.js
index 1f7b92410..a65f69307 100644
--- a/apps/twig/tailwind.config.js
+++ b/apps/twig/tailwind.config.js
@@ -18,14 +18,9 @@ module.exports = {
},
},
colors: {
- cave: {
- cream: "#f7eddf",
- charcoal: "#2d2b29",
- },
- fire: {
- glow: "rgba(255, 140, 60, 0.15)",
- },
posthog: {
+ orange: "#f54d00",
+ yellow: "#f8be2a",
50: "#fef2f2",
100: "#fee2e2",
200: "#fecaca",
@@ -37,13 +32,6 @@ module.exports = {
800: "#991b1b",
900: "#7f1d1d",
},
- dark: {
- bg: "#0a0a0a",
- surface: "#1a1a1a",
- border: "#2a2a2a",
- text: "#e5e5e5",
- "text-muted": "#a3a3a3",
- },
},
fontFamily: {
mono: [
diff --git a/apps/twig/tests/e2e/fixtures/electron.ts b/apps/twig/tests/e2e/fixtures/electron.ts
index ab52c90e0..d774ff3ff 100644
--- a/apps/twig/tests/e2e/fixtures/electron.ts
+++ b/apps/twig/tests/e2e/fixtures/electron.ts
@@ -13,11 +13,11 @@ function getAppPath(): string {
if (process.platform === "darwin") {
const arm64Path = path.join(
outDir,
- "Twig-darwin-arm64/Twig.app/Contents/MacOS/Twig",
+ "PostHog Code-darwin-arm64/PostHog Code.app/Contents/MacOS/PostHog Code",
);
const x64Path = path.join(
outDir,
- "Twig-darwin-x64/Twig.app/Contents/MacOS/Twig",
+ "PostHog Code-darwin-x64/PostHog Code.app/Contents/MacOS/PostHog Code",
);
if (existsSync(arm64Path)) return arm64Path;
@@ -29,7 +29,10 @@ function getAppPath(): string {
}
if (process.platform === "win32") {
- const winPath = path.join(outDir, "Twig-win32-x64/Twig.exe");
+ const winPath = path.join(
+ outDir,
+ "PostHog Code-win32-x64/PostHog Code.exe",
+ );
if (existsSync(winPath)) return winPath;
throw new Error(
@@ -38,7 +41,7 @@ function getAppPath(): string {
}
if (process.platform === "linux") {
- const linuxPath = path.join(outDir, "Twig-linux-x64/Twig");
+ const linuxPath = path.join(outDir, "PostHog Code-linux-x64/PostHog Code");
if (existsSync(linuxPath)) return linuxPath;
throw new Error(
diff --git a/apps/twig/tests/e2e/tests/main-process.spec.ts b/apps/twig/tests/e2e/tests/main-process.spec.ts
index d388c0d16..f5f6ee790 100644
--- a/apps/twig/tests/e2e/tests/main-process.spec.ts
+++ b/apps/twig/tests/e2e/tests/main-process.spec.ts
@@ -6,7 +6,7 @@ test.describe("Main Process", () => {
return app.getName();
});
- expect(appName).toBe("Twig");
+ expect(appName).toBe("PostHog Code");
});
test("app is packaged correctly", async ({ electronApp }) => {
diff --git a/apps/twig/tests/e2e/tests/smoke.spec.ts b/apps/twig/tests/e2e/tests/smoke.spec.ts
index b07220019..393e9309f 100644
--- a/apps/twig/tests/e2e/tests/smoke.spec.ts
+++ b/apps/twig/tests/e2e/tests/smoke.spec.ts
@@ -9,7 +9,7 @@ test.describe("Smoke Tests", () => {
expect(window).toBeTruthy();
const title = await window.title();
- expect(title).toContain("Twig");
+ expect(title).toContain("PostHog Code");
});
test("app renders initial UI (auth or main layout)", async ({ window }) => {