diff --git a/app/globals.css b/app/globals.css index 7c824ce..16f2673 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,59 +3,111 @@ @custom-variant dark (&:is(.dark *)); /* - * Design tokens — the single place to restyle the app. - * (The owner has a specific visual design planned; it lands here and in - * component edits, not in structural changes.) + * THE SKIN — wave 5. Design tokens, the single place to restyle the app. + * + * Mathematical soundness, per the owner's brief: + * - Tailwind's built-in 0.25rem (4px) spacing scale IS the rhythm — every + * padding/margin/gap in the app uses whole units of a 4px base. + * - The type scale below is a declared modular ladder (each --text-* token + * carries its own line-height); components never invent pixel sizes. + * - Radii ladder is 4 / 8 / 12 / 16px multiples of the 4px base. + * - Emphasis colors live in tokens (--lh-ink-strong / --lh-ink-italic) so a + * future settings UI reassigns them (configurable per the owner). */ +/* Palette (owner's hexes): main #141414, raised #1C1C1C, edges #434343. + Mono chrome = JetBrains Mono; prose = Source Sans 3; titles = CMU Serif. */ :root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); + --radius: 8px; + --background: #141414; + --foreground: #e6e6e6; + --card: #1c1c1c; + --card-foreground: #e6e6e6; + --popover: #1c1c1c; + --popover-foreground: #e6e6e6; + --primary: #e6e6e6; + --primary-foreground: #141414; + --secondary: #1c1c1c; + --secondary-foreground: #e6e6e6; + --muted: #1c1c1c; + --muted-foreground: #8d8d8d; + --accent: #2a2a2a; + --accent-foreground: #e6e6e6; + --destructive: oklch(0.704 0.191 22.216); + --border: #434343; + --input: #434343; + --ring: #8d8d8d; + /* Emphasis coloring in teaching prose — ready for the settings UI. */ + --lh-ink-strong: #c96b4a; + --lh-ink-italic: #6fa9d6; + --lh-prose-size: 16.5px; + --lh-prose-leading: 1.5; } +/* The app is always dark (); mirror the same values so + the block stays coherent under Tailwind's variant. */ .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); + --background: #141414; + --foreground: #e6e6e6; + --card: #1c1c1c; + --card-foreground: #e6e6e6; + --popover: #1c1c1c; + --popover-foreground: #e6e6e6; + --primary: #e6e6e6; + --primary-foreground: #141414; + --secondary: #1c1c1c; + --secondary-foreground: #e6e6e6; + --muted: #1c1c1c; + --muted-foreground: #8d8d8d; + --accent: #2a2a2a; + --accent-foreground: #e6e6e6; --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); + --border: #434343; + --input: #434343; + --ring: #8d8d8d; + --lh-ink-strong: #c96b4a; + --lh-ink-italic: #6fa9d6; + --lh-prose-size: 16.5px; + --lh-prose-leading: 1.5; +} + +/* CMU Serif bold (titles) — bundled local file, no CDN dependency. */ +@font-face { + font-family: "lh-cmu"; + src: url("/fonts/cmunbx.ttf") format("truetype"); + font-weight: 700; + font-style: normal; + font-display: swap; } @theme inline { - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); + /* Fonts: chrome = JetBrains Mono, prose = Source Sans 3, titles = CMU + Serif bold. The JetBrains/SourceSans variables attach in app/layout.tsx. */ + --font-ui: var(--font-jetbrains), ui-monospace, SFMono-Regular, monospace; + --font-prose: var(--font-sans3), ui-sans-serif, system-ui, sans-serif; + --font-title: "lh-cmu", serif; + /* The modular type ladder — each size carries its own line-height. + Component sizes must pull from this ladder. */ + --text-xs: 11px; + --text-xs--line-height: 1.4; + --text-sm: 12.5px; + --text-sm--line-height: 1.4; + --text-base: 14px; + --text-base--line-height: 1.45; + --text-lg: 16px; + --text-lg--line-height: 1.45; + --text-xl: 20px; + --text-xl--line-height: 1.4; + --text-2xl: 25px; + --text-2xl--line-height: 1.3; + --text-3xl: 32px; + --text-3xl--line-height: 1.25; + /* Radii ladder — 4/8/12/16 multiples of the 4px base. */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius: 8px; --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); @@ -83,6 +135,25 @@ body { background: var(--color-background); color: var(--color-foreground); + font-family: var(--font-ui); +} + +/* Teaching prose (the markdown renderer's container gets .lh-prose): + Source Sans 3 with the size/leading tokens; emphasis color bound to + the settings-ready tokens. */ +.lh-prose { + font-family: var(--font-prose); + font-size: var(--lh-prose-size); + line-height: var(--lh-prose-leading); +} + +.lh-prose :where(strong, b) { + color: var(--lh-ink-strong); + font-weight: 700; +} + +.lh-prose :where(em, i) { + color: var(--lh-ink-italic); } /* Thin dark native scrollbar (app-wide): dark thumb, transparent track. */ diff --git a/app/layout.tsx b/app/layout.tsx index d108f76..0f1f638 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,9 +1,15 @@ import type { Metadata } from "next"; +import { JetBrains_Mono, Source_Sans_3 } from "next/font/google"; import "katex/dist/katex.min.css"; import "./globals.css"; import { AppShell, SidebarProvider } from "@/components/sidebar"; import { ActivityDock, ActivityProvider } from "@/components/activity-dock"; +// Chrome = JetBrains Mono, teaching prose = Source Sans 3, titles = CMU +// Serif (the bundled lh-cmu @font-face in globals.css — no CDN). +const ui = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains" }); +const prose = Source_Sans_3({ subsets: ["latin"], variable: "--font-sans3" }); + export const metadata: Metadata = { title: "Learning Harness", description: "A teacher agent with a memory — sessions, quizzes, and a knowledge graph of what you know.", @@ -12,7 +18,7 @@ export const metadata: Metadata = { export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - + {children} diff --git a/public/fonts/OFL.txt b/public/fonts/OFL.txt new file mode 100644 index 0000000..a55bb6b --- /dev/null +++ b/public/fonts/OFL.txt @@ -0,0 +1,103 @@ +Copyright (C) Authors of original metafont fonts: +Donald Ervin Knuth (cm, concrete fonts) +1995, 1996, 1997 J"org Knappen, 1990, 1992 Norbert Schwarz (ec fonts) +1992-2006 A.Khodulev, O.Lapko, A.Berdnikov, V.Volovich (lh fonts) +1997-2005 Claudio Beccari (cb greek fonts) +2002 FUKUI Rei (tipa fonts) +2003-2005 Han The Thanh (Vietnamese fonts) +1996-2005 Walter Schmidt (cmbright fonts) + +Copyright (C) 2003-2009, Andrey V. Panov (panov@canopus.iacp.dvo.ru), +with Reserved Font Family Name "Computer Modern Unicode fonts". + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/public/fonts/cmunbx.ttf b/public/fonts/cmunbx.ttf new file mode 100644 index 0000000..9a42c0e Binary files /dev/null and b/public/fonts/cmunbx.ttf differ