Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/api/auth/forgot-password/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function POST(req: NextRequest) {
return NextResponse.json(
{
success: false,
error: result.error.errors[0].message,
error: result.error.issues[0].message,
code: 'VALIDATION_ERROR',
},
{ status: 400 },
Expand Down
2 changes: 1 addition & 1 deletion app/api/auth/profile/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export async function PUT(req: NextRequest) {
return NextResponse.json(
{
success: false,
error: result.error.errors[0].message,
error: result.error.issues[0].message,
code: 'VALIDATION_ERROR',
},
{ status: 400 },
Expand Down
2 changes: 1 addition & 1 deletion app/api/auth/signin/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function POST(req: NextRequest) {
return NextResponse.json(
{
success: false,
error: result.error.errors[0].message,
error: result.error.issues[0].message,
code: 'VALIDATION_ERROR',
},
{ status: 400 },
Expand Down
2 changes: 1 addition & 1 deletion app/api/auth/signup/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function POST(req: NextRequest) {
// Validate input
const result = SignUpSchema.safeParse(body);
if (!result.success) {
return jsonError(result.error.errors[0].message, 'VALIDATION_ERROR', HTTP_STATUS.BAD_REQUEST);
return jsonError(result.error.issues[0].message, 'VALIDATION_ERROR', HTTP_STATUS.BAD_REQUEST);
}

const { email, password } = result.data;
Expand Down
2 changes: 1 addition & 1 deletion app/api/custom-bots/[id]/import-document/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { logger } from '@/lib/logger';
const DOMAIN_ERROR = 'Failed to import document to bot';

const ImportDocumentSchema = z.object({
document_id: z.string().uuid('Invalid document ID'),
document_id: z.string().guid('Invalid document ID'),
});

interface RouteParams {
Expand Down
2 changes: 1 addition & 1 deletion app/api/settings/validate-key/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function POST(req: NextRequest) {

if (!parseResult.success) {
return jsonError(
parseResult.error.errors[0].message,
parseResult.error.issues[0].message,
'VALIDATION_ERROR',
HTTP_STATUS.BAD_REQUEST,
);
Expand Down
2 changes: 1 addition & 1 deletion app/auth/forgot-password/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function ForgotPasswordPage() {
// Validate with Zod
const result = ForgotPasswordSchema.safeParse({ email });
if (!result.success) {
setError(result.error.errors[0].message);
setError(result.error.issues[0].message);
setLoading(false);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion app/auth/reset-password/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function ResetPasswordPage() {
// Validate with Zod
const result = ResetPasswordSchema.safeParse({ password, confirmPassword });
if (!result.success) {
setError(result.error.errors[0].message);
setError(result.error.issues[0].message);
setLoading(false);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion app/auth/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function SignInPage() {
// Validate with Zod
const result = SignInSchema.safeParse({ email, password });
if (!result.success) {
setError(result.error.errors[0].message);
setError(result.error.issues[0].message);
setLoading(false);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion app/auth/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function SignUpPage() {
// Validate with Zod
const result = SignUpSchema.safeParse({ email, password, confirmPassword });
if (!result.success) {
setError(result.error.errors[0].message);
setError(result.error.issues[0].message);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default async function Blog() {

<Link
href={`/blog/${post.slug}` as Route}
className="mt-6 inline-flex items-center text-sm font-medium text-action hover:text-opacity-80"
className="mt-6 inline-flex items-center text-sm font-medium text-action hover:text-action/80"
>
Read more
<svg
Expand Down
2 changes: 1 addition & 1 deletion app/bots/BotNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export const BotNavigation: React.FC<BotNavigationProps> = ({
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-900 bg-opacity-50 transition-opacity" />
<div className="fixed inset-0 bg-gray-900/50 transition-opacity" />
</Transition.Child>

<div className="fixed inset-0 overflow-hidden">
Expand Down
4 changes: 2 additions & 2 deletions app/contact/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export default function ContactPage() {
We've received your message and will get back to you soon.
</p>
<button
className="mt-5 rounded-md bg-action px-4 py-2 text-sm font-medium text-white hover:bg-opacity-90 transition-opacity"
className="mt-5 rounded-md bg-action px-4 py-2 text-sm font-medium text-white hover:bg-action/90 transition-colors"
onClick={() => setIsSubmitted(false)}
>
Send another message
Expand Down Expand Up @@ -192,7 +192,7 @@ export default function ContactPage() {
<button
type="submit"
disabled={isSubmitting}
className="w-full rounded-md bg-action px-4 py-2 text-sm font-medium text-white hover:bg-opacity-90 transition-opacity disabled:bg-opacity-70"
className="w-full rounded-md bg-action px-4 py-2 text-sm font-medium text-white hover:bg-action/90 transition-colors disabled:bg-action/70"
>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
Expand Down
75 changes: 30 additions & 45 deletions app/globals.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import 'tailwindcss';

@plugin '@tailwindcss/forms';
@plugin '@tailwindcss/typography';

/*
* ============================================================================
Expand All @@ -10,9 +11,9 @@
* toy chatbot. Editorial ink + one authoritative warm accent (notarial ochre).
* No generic "AI gradient" blue/purple. Typography (serif display) carries it.
*
* Every color/radius/shadow used in the product is defined HERE. tailwind.config
* maps utilities to these vars; components consume semantic classes only.
* Retheme = edit this block. Nothing else.
* Every color/radius/shadow used in the product is defined HERE. Tailwind v4
* CSS-first config: the @theme block below maps utility names to these vars;
* components consume semantic classes only. Retheme = edit this block.
*/
:root {
/* Tier 1 — Primitive palette (raw values; never used directly by components) */
Expand All @@ -26,16 +27,26 @@
--primitive-surface: #ffffff;
--primitive-border: #e8e2d8; /* warm hairline */

/* Tier 2 — Semantic tokens (what things MEAN — always use these) */
/* Back-compat for any legacy rgb() consumers */
--foreground-rgb: 26, 23, 20;
--background-rgb: 250, 248, 244;
}

/*
* Tier 2 — Semantic tokens (what things MEAN — always use these).
* `inline` so utilities resolve through the primitive vars above and the
* next/font vars (--font-inter / --font-fraunces) set on <html> in layout.tsx.
*/
@theme inline {
--color-brand: var(--primitive-ink-950); /* the Botsmann mark / authority */
--color-action: var(--primitive-ochre-600); /* primary CTAs, links, accents */
--color-action-hover: var(--primitive-ochre-700);
--color-action-tint: var(--primitive-ochre-50);
--color-bg: var(--primitive-paper);
--color-paper: var(--primitive-paper); /* page background */
--color-surface: var(--primitive-surface);
--color-border: var(--primitive-border);
--color-text: var(--primitive-ink-950);
--color-text-muted: var(--primitive-ink-500);
--color-edge: var(--primitive-border);
--color-ink: var(--primitive-ink-950);
--color-ink-muted: var(--primitive-ink-500);

/* Radii — restrained, editorial (not bubbly) */
--radius-card: 12px;
Expand All @@ -45,14 +56,14 @@
--shadow-card: 0 1px 2px rgb(26 23 20 / 0.04), 0 1px 3px rgb(26 23 20 / 0.06);
--shadow-card-hover: 0 4px 12px rgb(26 23 20 / 0.08), 0 2px 4px rgb(26 23 20 / 0.06);

/* Back-compat for any legacy rgb() consumers */
--foreground-rgb: 26, 23, 20;
--background-rgb: 250, 248, 244;
/* Bound to next/font CSS vars set in app/layout.tsx */
--font-sans: var(--font-inter), system-ui, sans-serif;
--font-serif: var(--font-fraunces), Georgia, serif;
}

body {
color: var(--color-text);
background: var(--color-bg);
color: var(--primitive-ink-950);
background: var(--primitive-paper);
}

/* Smooth scrolling for anchor links */
Expand Down Expand Up @@ -84,13 +95,13 @@ html {

@layer components {
.btn-primary {
@apply rounded-btn bg-action px-4 py-2 text-sm md:text-base font-medium text-white hover:bg-action-hover transition-colors shadow-card hover:shadow-card-hover md:px-5 md:py-2.5 focus:outline-none focus:ring-2 focus:ring-action focus:ring-opacity-40;
@apply rounded-btn bg-action px-4 py-2 text-sm md:text-base font-medium text-white hover:bg-action-hover transition-colors shadow-card hover:shadow-card-hover md:px-5 md:py-2.5 focus:outline-none focus:ring-2 focus:ring-action/40;
}
.btn-secondary {
@apply rounded-btn border border-edge px-4 py-2 text-sm md:text-base font-medium text-ink hover:bg-action-tint transition-colors shadow-card hover:shadow-card-hover md:px-5 md:py-2.5 focus:outline-none focus:ring-2 focus:ring-action focus:ring-opacity-20;
@apply rounded-btn border border-edge px-4 py-2 text-sm md:text-base font-medium text-ink hover:bg-action-tint transition-colors shadow-card hover:shadow-card-hover md:px-5 md:py-2.5 focus:outline-none focus:ring-2 focus:ring-action/20;
}
.input-primary {
@apply w-full rounded-btn border border-edge bg-surface px-4 py-3 text-ink outline-none transition-colors focus:border-action focus:ring-2 focus:ring-action focus:ring-opacity-20;
@apply w-full rounded-btn border border-edge bg-surface px-4 py-3 text-ink outline-none transition-colors focus:border-action focus:ring-2 focus:ring-action/20;
}
}

Expand All @@ -116,32 +127,6 @@ html {
left: 0;
}

@layer utilities {
.aspect-w-16 {
position: relative;
padding-bottom: calc(var(--tw-aspect-h) / var(--tw-aspect-w) * 100%);
--tw-aspect-w: 16;
}

.aspect-h-7 {
--tw-aspect-h: 7;
}

.aspect-h-9 {
--tw-aspect-h: 9;
}

.aspect-w-16 > * {
position: absolute;
height: 100%;
width: 100%;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
}

/* Mobile menu fixes */
body.overflow-hidden {
/* Prevent content jumping when scrollbar disappears */
Expand Down
8 changes: 5 additions & 3 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import Script from 'next/script';

// Brand typeface: a serif display (Fraunces) carries the editorial / "real
// counsel" identity for headings & wordmark; Inter handles UI/body copy.
// Bound to CSS vars consumed by tailwind.config (font-serif / font-sans).
// Bound to CSS vars consumed by the @theme block in globals.css (font-sans /
// font-serif). Named --font-inter/--font-fraunces so the @theme aliases
// --font-sans/--font-serif can reference them without a circular var().
const sans = Inter({
subsets: ['latin'],
variable: '--font-sans',
variable: '--font-inter',
display: 'swap',
});

const serif = Fraunces({
subsets: ['latin'],
weight: ['400', '500', '600', '700'],
style: ['normal', 'italic'],
variable: '--font-serif',
variable: '--font-fraunces',
display: 'swap',
});

Expand Down
2 changes: 1 addition & 1 deletion app/settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default function SettingsPage() {
});

if (!result.success) {
setProfileError(result.error.errors[0].message);
setProfileError(result.error.issues[0].message);
return;
}

Expand Down
4 changes: 2 additions & 2 deletions components/ConsultationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default function ConsultationForm() {
</p>
<button
onClick={() => setSubmitSuccess(false)}
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-action hover:bg-opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-action"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-action hover:bg-action/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-action"
>
Submit another response
</button>
Expand Down Expand Up @@ -174,7 +174,7 @@ export default function ConsultationForm() {
<button
type="submit"
disabled={isSubmitting}
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-action hover:bg-opacity-90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-action disabled:opacity-50"
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-action hover:bg-action/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-action disabled:opacity-50"
>
{isSubmitting ? 'Submitting...' : 'Join the Community'}
</button>
Expand Down
8 changes: 2 additions & 6 deletions components/blog/MDXComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ const MDXComponents = {
return (
<a
href={href}
className="text-action hover:text-opacity-80"
className="text-action hover:text-action/80"
target="_blank"
rel="noopener noreferrer"
{...props}
Expand All @@ -205,11 +205,7 @@ const MDXComponents = {
}

return (
<Link
href={(href || '/') as Route}
className="text-action hover:text-opacity-80"
{...props}
/>
<Link href={(href || '/') as Route} className="text-action hover:text-action/80" {...props} />
);
},

Expand Down
8 changes: 2 additions & 6 deletions components/blog/ServerMDXContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const ServerMDXComponents = {
return (
<a
href={href}
className="text-action hover:text-opacity-80"
className="text-action hover:text-action/80"
target="_blank"
rel="noopener noreferrer"
{...props}
Expand All @@ -76,11 +76,7 @@ const ServerMDXComponents = {
}

return (
<Link
href={(href || '/') as Route}
className="text-action hover:text-opacity-80"
{...props}
/>
<Link href={(href || '/') as Route} className="text-action hover:text-action/80" {...props} />
);
},

Expand Down
2 changes: 1 addition & 1 deletion components/navigation/BotSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export function BotSwitcher({
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel static style={getDropdownStyle()} className="w-64">
<div className="overflow-hidden rounded-xl bg-white shadow-xl ring-1 ring-black ring-opacity-5 border border-gray-100">
<div className="overflow-hidden rounded-xl bg-white shadow-xl ring-1 ring-black/5 border border-gray-100">
{/* Header */}
<div className="border-b border-gray-100 bg-gray-50 px-4 py-3">
<p className="text-xs font-medium text-gray-500 uppercase tracking-wider">
Expand Down
2 changes: 1 addition & 1 deletion components/navigation/MegaMenuPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function MegaMenuPanel({ items, config, onNavigate }: MegaMenuPanelProps)
}[columns];

return (
<div className="overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 border border-gray-100">
<div className="overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black/5 border border-gray-100">
{/* Optional Header */}
{config?.header && (
<div
Expand Down
2 changes: 1 addition & 1 deletion components/navigation/SiteMenuDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function SiteMenuDropdown({ className = '' }: SiteMenuDropdownProps) {
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel static style={getDropdownStyle()} className="w-56">
<div className="overflow-hidden rounded-xl bg-white shadow-xl ring-1 ring-black ring-opacity-5 border border-gray-100">
<div className="overflow-hidden rounded-xl bg-white shadow-xl ring-1 ring-black/5 border border-gray-100">
{/* Header */}
<div className="border-b border-gray-100 bg-action-tint px-4 py-3">
<Link href="/" onClick={() => close()} className="flex items-center gap-2">
Expand Down
Loading