diff --git a/src/components/ring-burst-icon.tsx b/src/components/ring-burst-icon.tsx
new file mode 100644
index 0000000..6b8796b
--- /dev/null
+++ b/src/components/ring-burst-icon.tsx
@@ -0,0 +1,53 @@
+type RingBurstIconProps = {
+ className?: string
+}
+
+// 11×11 pixel grid — the "ring burst" mark from docs/criticalbit-logo-r3.html.
+// 1 = filled cell; eight rays radiate from a hollow core.
+const RING_GRID = [
+ [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
+ [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
+ [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
+ [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
+ [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
+ [1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1],
+ [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
+ [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0],
+ [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0],
+ [0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0],
+ [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
+] as const
+
+// Each cell sits in a CELL-wide slot; GAP keeps a crisp pixel seam between them.
+const CELL = 4
+const GAP = 1
+const SPAN = RING_GRID.length * CELL - GAP // 11 × 4 − 1 = 43
+
+const RING_CELLS = RING_GRID.flatMap((row, r) =>
+ row.flatMap((filled, c) => (filled ? [{ x: c * CELL, y: r * CELL }] : []))
+)
+
+/**
+ * The criticalbit ring burst. Renders as `currentColor`, so set the colour with
+ * a `text-*` utility and the size with `size-*` (or any width/height class).
+ */
+export function RingBurstIcon({ className }: RingBurstIconProps) {
+ return (
+
+ )
+}
diff --git a/src/components/wordmark.tsx b/src/components/wordmark.tsx
new file mode 100644
index 0000000..3941fa9
--- /dev/null
+++ b/src/components/wordmark.tsx
@@ -0,0 +1,29 @@
+import { cn } from "@/lib/utils"
+
+type WordmarkProps = {
+ className?: string
+ /** Render the trailing ".gg". Turn off for compact placements like the navbar. */
+ showTld?: boolean
+}
+
+/**
+ * The split wordmark: "critical" in Geist Sans, "BIT" in Geist Pixel Grid, and a
+ * trailing ".gg". Every part is sized in `em`, so the whole lockup scales with
+ * the inherited font size — set a `text-*` utility on the parent or via
+ * `className` to resize it.
+ */
+export function Wordmark({ className, showTld = true }: WordmarkProps) {
+ return (
+
+
+ critical
+
+
+ BIT
+
+ {showTld && (
+ .gg
+ )}
+
+ )
+}
diff --git a/src/index.css b/src/index.css
index fa64c83..cf7dcf6 100644
--- a/src/index.css
+++ b/src/index.css
@@ -4,8 +4,8 @@
@custom-variant dark (&:is(.dark *));
@font-face {
- font-family: "Geist Pixel Line";
- src: url("/fonts/GeistPixel-Line.woff2") format("woff2");
+ font-family: "Geist Pixel Grid";
+ src: url("/fonts/GeistPixel-Grid.woff2") format("woff2");
font-weight: normal;
font-style: normal;
font-display: swap;
@@ -15,7 +15,7 @@
:root {
--radius: 0.625rem;
--font-sans: "Geist Variable", ui-sans-serif, system-ui, sans-serif;
- --font-pixel: "Geist Pixel Line", monospace;
+ --font-pixel: "Geist Pixel Grid", monospace;
--background: oklch(0.97 0.01 230);
--foreground: oklch(0.22 0.02 260);
@@ -36,8 +36,6 @@
--border: oklch(0.9 0.01 230);
--input: oklch(0.9 0.01 230);
--ring: oklch(0.88 0.08 210);
- --brand-emerald: oklch(0.85 0.11 165);
- --brand-emerald-foreground: oklch(0.18 0.015 270);
--chart-1: oklch(0.88 0.08 210);
--chart-2: oklch(0.75 0.17 165);
--chart-3: oklch(0.75 0.15 75);
@@ -74,8 +72,6 @@
--border: oklch(0.28 0.02 270);
--input: oklch(0.28 0.02 270);
--ring: oklch(0.82 0.11 220);
- --brand-emerald: oklch(0.75 0.17 165);
- --brand-emerald-foreground: oklch(0.18 0.015 270);
--chart-1: oklch(0.82 0.11 220);
--chart-2: oklch(0.75 0.17 165);
--chart-3: oklch(0.8 0.12 80);
@@ -113,8 +109,6 @@
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
- --color-brand-emerald: var(--brand-emerald);
- --color-brand-emerald-foreground: var(--brand-emerald-foreground);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
diff --git a/src/main.tsx b/src/main.tsx
index 51c2797..7f5c960 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -5,6 +5,7 @@ import { createRoot } from "react-dom/client"
import { reactErrorHandler } from "@sentry/react"
// @ts-expect-error -- fontsource CSS-only import, no types
import "@fontsource-variable/geist"
+import { BrandLockup } from "./components/brand-lockup"
import { ErrorBoundary } from "./components/error-boundary"
import { NotFound } from "./components/not-found"
import { ThemeProvider } from "./components/theme-provider"
@@ -39,7 +40,7 @@ function AppShellSkeleton() {
<>