Typography round 1 (owner): the three-font rule enforced + Source Sans session titles

- The hidden fourth font: Tailwind's font-mono/font-sans utilities fall to
  the SYSTEM stacks (SFMono/Menlo — a font the app never chose), and
  streamdown's code-block chrome, mermaid-error, and the demo-card meta
  all use them — so every teaching-prose code block rendered in the
  system mono. Fixed at the token level: @theme now aliases --font-mono →
  JetBrains Mono and --font-sans → Source Sans 3, so every utility use
  resolves to the app's three fonts (chrome=JetBrains, prose=Source Sans,
  display=CMU bold).
- Session titles: Source Sans 3 (the human-words voice — the same font
  the words were typed in; mono = machine data stays on the meta line).
  One rule, finally applied to the picker too. CMU bold titles are the
  queued experiment if this reads wrong live.

Gates: typecheck, lint, 469/469. Live: title "Source Sans 3" 12.5px,
meta "JetBrains Mono" 11px; code blocks now JetBrains.
This commit is contained in:
amosblomqvist
2026-09-17 13:13:26 +03:00
parent c9ba4a1b06
commit 1b7dbe2898
2 changed files with 13 additions and 2 deletions
+7 -1
View File
@@ -82,10 +82,16 @@
@theme inline { @theme inline {
/* Fonts: chrome = JetBrains Mono, prose = Source Sans 3, titles = CMU /* Fonts: chrome = JetBrains Mono, prose = Source Sans 3, titles = CMU
Serif bold. The JetBrains/SourceSans variables attach in app/layout.tsx. */ Serif bold. The JetBrains/SourceSans variables attach in app/layout.tsx.
(owner, typography round) The Tailwind defaults are ALIASED to the app
fonts: `font-mono`/`font-sans` utilities would otherwise fall to the
SYSTEM stacks — a fourth font the app never chose — and streamdown's
code-block chrome + mermaid-error + demo-card all use them. */
--font-ui: var(--font-jetbrains), ui-monospace, SFMono-Regular, monospace; --font-ui: var(--font-jetbrains), ui-monospace, SFMono-Regular, monospace;
--font-prose: var(--font-sans3), ui-sans-serif, system-ui, sans-serif; --font-prose: var(--font-sans3), ui-sans-serif, system-ui, sans-serif;
--font-title: "lh-cmu", serif; --font-title: "lh-cmu", serif;
--font-mono: var(--font-jetbrains), ui-monospace, SFMono-Regular, monospace;
--font-sans: var(--font-sans3), ui-sans-serif, system-ui, sans-serif;
/* The modular type ladder — each size carries its own line-height. /* The modular type ladder — each size carries its own line-height.
Component sizes must pull from this ladder. */ Component sizes must pull from this ladder. */
--text-xxs: 10px; --text-xxs: 10px;
+6 -1
View File
@@ -133,7 +133,12 @@ export function SessionRow({
> >
<SessionStatus busy={chat.busy} /> <SessionStatus busy={chat.busy} />
<span className="min-w-0 flex-1"> <span className="min-w-0 flex-1">
<span className="block truncate">{chat.title}</span> {/* Titles are the learner's/teacher's WORDS — Source Sans 3, the
same voice the words were typed in (every input is lh-prose);
the meta line below stays JetBrains Mono (machine data). One
rule, finally applied to the picker too (owner, typography
round): mono = chrome, Source Sans = human words. */}
<span className="block truncate font-prose">{chat.title}</span>
<span className="block text-xs text-muted-foreground">{sessionMeta(chat)}</span> <span className="block text-xs text-muted-foreground">{sessionMeta(chat)}</span>
</span> </span>
</button> </button>