Three bugs caught via devtools on live site:
**1. CSP 'font-src 'self' data:' violation × 3 per landing load.**
BaseLayout was loading Geist + Geist_Mono via next/font/google. In
prod builds Next.js self-hosts those under /_next/static, but the
generated CSS still references `--font-sans: "Geist", …` which some
browsers resolve by re-requesting fonts.gstatic.com. Since we ship
Anthropic Sans/Serif/Mono self-hosted already (/fonts/*.woff2 via
@font-face in globals.css), the Geist dependency was pure overhead.
Removed `next/font/google` imports entirely. Added a `.cm-root`
class on <html> that remaps the Tailwind `--font-sans/--font-mono`
tokens to our `--cm-font-sans/--cm-font-mono` vars — so every
Tailwind `font-sans` / `font-mono` utility now resolves to Anthropic
families. No Google Fonts fetch, no CSP violation.
**2. /pricing 401 on public visit.**
`<Plan>` calls `useCustomer()` → `GET /api/billing/customer` which
needs auth. Unauthed visitor on /pricing → 401 in devtools + wasted
round trip. Gated `useCustomer` on `authClient.useSession()` —
query `enabled: !!session?.user`. Public visitors now skip the fetch
entirely; signed-in users still get their customer record.
**3. Residual "Welcome back! 👋" on /auth/login (both locales).**
Emoji sweep (e91fc80) missed the i18n translation files. Removed 👋
from en/auth.json + es/auth.json login header titles.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
167 lines
5.1 KiB
CSS
167 lines
5.1 KiB
CSS
@import "@turbostarter/ui/globals.css";
|
|
@import "@turbostarter/ui-web/globals.css";
|
|
|
|
@source "../../../../../packages/ui";
|
|
|
|
/* ============================================================
|
|
claudemesh — Anthropic design system
|
|
Fonts, tokens, and primitives extracted from claude.com
|
|
============================================================ */
|
|
|
|
@font-face {
|
|
font-family: "Anthropic Sans";
|
|
src: url("/fonts/AnthropicSans-Roman.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
@font-face {
|
|
font-family: "Anthropic Sans";
|
|
src: url("/fonts/AnthropicSans-Italic.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
@font-face {
|
|
font-family: "Anthropic Serif";
|
|
src: url("/fonts/AnthropicSerif-Roman.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
@font-face {
|
|
font-family: "Anthropic Serif";
|
|
src: url("/fonts/AnthropicSerif-Italic.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
@font-face {
|
|
font-family: "Anthropic Mono";
|
|
src: url("/fonts/AnthropicMono-Roman.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
@font-face {
|
|
font-family: "Anthropic Mono";
|
|
src: url("/fonts/AnthropicMono-Italic.woff2") format("woff2");
|
|
font-weight: 300 800;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
|
|
:root {
|
|
/* --- Anthropic swatch palette (extracted from claude.com) --- */
|
|
--cm-clay: #d97757;
|
|
--cm-clay-hover: #c96442;
|
|
--cm-fig: #c46686;
|
|
--cm-oat: #e3dacc;
|
|
--cm-cactus: #bcd1ca;
|
|
|
|
--cm-gray-000: #ffffff;
|
|
--cm-gray-050: #faf9f5;
|
|
--cm-gray-150: #f0eee6;
|
|
--cm-gray-350: #c2c0b6;
|
|
--cm-gray-450: #9c9a92;
|
|
--cm-gray-800: #262624;
|
|
--cm-gray-850: #1f1e1d;
|
|
--cm-gray-900: #141413;
|
|
|
|
--cm-bg: var(--cm-gray-900);
|
|
--cm-bg-elevated: var(--cm-gray-850);
|
|
--cm-bg-hover: var(--cm-gray-800);
|
|
--cm-fg: var(--cm-gray-050);
|
|
--cm-fg-secondary: #c2c0b6;
|
|
--cm-fg-tertiary: #87867f;
|
|
--cm-border: rgba(217, 119, 87, 0.2);
|
|
--cm-border-hover: rgba(217, 119, 87, 0.5);
|
|
|
|
/* --- Type families --- */
|
|
--cm-font-sans: "Anthropic Sans", -apple-system, system-ui, Arial, sans-serif;
|
|
--cm-font-serif: "Anthropic Serif", Georgia, "Times New Roman", serif;
|
|
--cm-font-mono: "Anthropic Mono", "JetBrains Mono", ui-monospace, monospace;
|
|
|
|
/* --- Type scale (fluid, from Anthropic clamps) --- */
|
|
--cm-text-h1: clamp(2.125rem, 1.8rem + 2.6vw, 3.25rem);
|
|
--cm-text-h2: clamp(1.875rem, 1.625rem + 1.95vw, 2.75rem);
|
|
--cm-text-h3: clamp(1.75rem, 1.607rem + 1.12vw, 2.25rem);
|
|
--cm-text-body-lg: clamp(1.1875rem, 1.17rem + 0.14vw, 1.25rem);
|
|
|
|
/* --- Spacing --- */
|
|
--cm-gutter: 2rem;
|
|
--cm-max-w: 90rem;
|
|
|
|
/* --- Radii --- */
|
|
--cm-radius-xs: 0.25rem;
|
|
--cm-radius-md: 0.5rem;
|
|
--cm-radius-lg: 1rem;
|
|
|
|
/* --- Motion --- */
|
|
--cm-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
--cm-dur: 300ms;
|
|
}
|
|
|
|
/* ============================================================
|
|
Map shadcn/ui tokens → claudemesh palette
|
|
Overrides the TurboStarter-inherited orange theme so every
|
|
Button/Card/Input/Dialog/etc renders in the claudemesh dark
|
|
palette, not the white/neutral defaults. Applies to BOTH
|
|
the light variant and the dark variant of the active
|
|
[data-theme="orange"] selector — we want the same dark
|
|
claudemesh look regardless of system preference.
|
|
============================================================ */
|
|
:root,
|
|
[data-theme="orange"],
|
|
[data-theme="orange"] .dark,
|
|
.dark {
|
|
--background: var(--cm-bg);
|
|
--foreground: var(--cm-fg);
|
|
--card: var(--cm-bg-elevated);
|
|
--card-foreground: var(--cm-fg);
|
|
--popover: var(--cm-bg-elevated);
|
|
--popover-foreground: var(--cm-fg);
|
|
--primary: var(--cm-clay);
|
|
--primary-foreground: var(--cm-gray-050);
|
|
--secondary: var(--cm-bg-elevated);
|
|
--secondary-foreground: var(--cm-fg-secondary);
|
|
--muted: var(--cm-bg-elevated);
|
|
--muted-foreground: var(--cm-fg-tertiary);
|
|
--accent: var(--cm-bg-elevated);
|
|
--accent-foreground: var(--cm-fg);
|
|
--destructive: #dc2626;
|
|
--destructive-foreground: var(--cm-gray-050);
|
|
--success: #16a34a;
|
|
--success-foreground: var(--cm-gray-050);
|
|
--border: var(--cm-border);
|
|
--input: var(--cm-border);
|
|
--ring: var(--cm-clay);
|
|
--radius: var(--cm-radius-md);
|
|
|
|
--sidebar: var(--cm-bg-elevated);
|
|
--sidebar-foreground: var(--cm-fg);
|
|
--sidebar-primary: var(--cm-clay);
|
|
--sidebar-primary-foreground: var(--cm-gray-050);
|
|
--sidebar-accent: var(--cm-bg-hover);
|
|
--sidebar-accent-foreground: var(--cm-fg);
|
|
--sidebar-border: var(--cm-border);
|
|
--sidebar-ring: var(--cm-clay);
|
|
}
|
|
|
|
/* Tailwind's @variant light path — when no data-theme or no dark class,
|
|
Tailwind emits the light branch. Override it too so there's no
|
|
white-background flash on any shadcn surface. */
|
|
:root {
|
|
color-scheme: dark;
|
|
}
|
|
|
|
/* Override the Tailwind default --font-sans / --font-mono CSS vars
|
|
(which BaseLayout used to populate from next/font/google Geist).
|
|
We self-host Anthropic Sans/Serif/Mono now — no Google Fonts fetch,
|
|
no CSP font-src violation. */
|
|
.cm-root {
|
|
--font-sans: var(--cm-font-sans);
|
|
--font-mono: var(--cm-font-mono);
|
|
--font-serif: var(--cm-font-serif);
|
|
}
|