diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx
index b443933..4915a10 100644
--- a/apps/web/app/(app)/layout.tsx
+++ b/apps/web/app/(app)/layout.tsx
@@ -4,7 +4,7 @@ import { AppShellHeader } from "@/components/app-shell-header";
export default function AppShellLayout({ children }: { children: ReactNode }) {
return (
-
+
diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
new file mode 100644
index 0000000..f817248
--- /dev/null
+++ b/apps/web/app/globals.css
@@ -0,0 +1,67 @@
+/* Studiqo authenticated app — tokens aligned with docs/frontend/studiqo-style-guide.md */
+
+@import "tailwindcss";
+
+@theme inline {
+ /* Semantic palette (warm education) */
+ --color-canvas: #f5f1ea;
+ --color-surface: #fffcf7;
+ --color-raised: #f0ebe3;
+ --color-line: #e4ddd3;
+ --color-line-strong: #c4b8a8;
+ --color-ink: #1c1917;
+ --color-ink-muted: #57534e;
+ --color-ink-faint: #78716c;
+ --color-accent: #2a5f5a;
+ --color-accent-hover: #1f4744;
+ --color-accent-soft: rgb(42 95 90 / 0.14);
+ --color-danger: #b91c1c;
+ --color-success: #15803d;
+
+ /* next/font variables are set on */
+ --font-sans: var(--font-ui), "Source Sans 3", ui-sans-serif, system-ui, sans-serif;
+ --font-serif-display: var(--font-display), Georgia, "Times New Roman", serif;
+}
+
+@layer base {
+ *,
+ *::before,
+ *::after {
+ box-sizing: border-box;
+ }
+
+ html {
+ color-scheme: light;
+ }
+
+ body {
+ @apply m-0 min-h-screen bg-canvas font-sans text-base leading-normal text-ink antialiased;
+ }
+}
+
+@layer components {
+ .app-nav-link {
+ @apply inline-block rounded-lg px-3.5 py-2 text-sm leading-snug text-ink-muted transition-colors duration-200 ease-in-out hover:bg-raised hover:text-ink focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 focus-visible:ring-offset-2 focus-visible:ring-offset-canvas motion-reduce:transition-none;
+ }
+
+ .app-nav-link[aria-current="page"] {
+ @apply bg-accent-soft font-semibold text-accent;
+ }
+
+ .app-brand-link {
+ @apply text-lg font-semibold leading-snug tracking-tight text-ink no-underline transition-colors duration-200 hover:text-accent focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 focus-visible:ring-offset-2 focus-visible:ring-offset-surface motion-reduce:transition-none;
+ }
+
+ .app-btn {
+ @apply inline-flex min-h-11 cursor-pointer items-center justify-center rounded-lg border border-line-strong bg-surface px-4 text-sm font-semibold leading-snug text-ink transition-colors duration-200 ease-in-out hover:bg-raised hover:border-ink-faint focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 focus-visible:ring-offset-2 focus-visible:ring-offset-surface motion-reduce:transition-none;
+ }
+
+ .app-btn-primary {
+ @apply border-accent bg-accent text-white hover:border-accent-hover hover:bg-accent-hover hover:text-white;
+ }
+
+ /* Focus ring offset matches header surface (nav row uses default canvas offset). */
+ .app-nav-link--on-surface {
+ @apply focus-visible:ring-offset-surface;
+ }
+}
diff --git a/apps/web/app/layout.tsx b/apps/web/app/layout.tsx
index dedba19..5b6816d 100644
--- a/apps/web/app/layout.tsx
+++ b/apps/web/app/layout.tsx
@@ -1,10 +1,25 @@
+import { Fraunces, Source_Sans_3 } from "next/font/google";
import type { ReactNode } from "react";
import { Providers } from "./providers";
+import "./globals.css";
+
+const fraunces = Fraunces({
+ subsets: ["latin"],
+ variable: "--font-display",
+ display: "swap",
+});
+
+const sourceSans = Source_Sans_3({
+ subsets: ["latin"],
+ variable: "--font-ui",
+ display: "swap",
+});
+
export default function RootLayout({ children }: { children: ReactNode }) {
return (
-
+
{children}
diff --git a/apps/web/app/t/[tenantSlug]/(public)/layout.tsx b/apps/web/app/t/[tenantSlug]/(public)/layout.tsx
index 2613295..37986b7 100644
--- a/apps/web/app/t/[tenantSlug]/(public)/layout.tsx
+++ b/apps/web/app/t/[tenantSlug]/(public)/layout.tsx
@@ -2,7 +2,5 @@ import type { ReactNode } from "react";
/** Invitation flows are public (no session required). */
export default function TenantPublicLayout({ children }: { children: ReactNode }) {
- return (
-
{children}
- );
+ return
{children}
;
}
diff --git a/apps/web/app/t/[tenantSlug]/tenant-chrome.tsx b/apps/web/app/t/[tenantSlug]/tenant-chrome.tsx
index 7ef5528..0c300e9 100644
--- a/apps/web/app/t/[tenantSlug]/tenant-chrome.tsx
+++ b/apps/web/app/t/[tenantSlug]/tenant-chrome.tsx
@@ -22,38 +22,33 @@ export function TenantChrome({
);
return (
-