---
version: alpha
name: Custard Schoolbook
description: "Retro-modern learning UI: ochre actions on cream paper, heavy Epilogue headlines and hard-offset shadows on a modern 4px grid."
colors:
  background: "#fbf6ec"
  foreground: "#1b1812"
  card: "#fffdf8"
  card-foreground: "#1b1812"
  popover: "#fffdf8"
  popover-foreground: "#1b1812"
  primary: "#96600a"
  primary-foreground: "#ffffff"
  secondary: "#f3ecde"
  secondary-foreground: "#2e291f"
  muted: "#f3ecde"
  muted-foreground: "#5a503e"
  accent: "#ffedc9"
  accent-foreground: "#3f2605"
  destructive: "#b92646"
  destructive-foreground: "#ffffff"
  success: "#2a6520"
  success-foreground: "#ffffff"
  warning: "#f8e46e"
  warning-foreground: "#392e00"
  border: "#cec2ad"
  input: "#ad9f8a"
  ring: "#96600a"
  dark-background: "#1b1812"
  dark-foreground: "#fbf6ec"
  dark-card: "#2e291f"
  dark-card-foreground: "#fbf6ec"
  dark-popover: "#2e291f"
  dark-popover-foreground: "#fbf6ec"
  dark-primary: "#e8a52d"
  dark-primary-foreground: "#271602"
  dark-secondary: "#433c2e"
  dark-secondary-foreground: "#f3ecde"
  dark-muted: "#433c2e"
  dark-muted-foreground: "#cec2ad"
  dark-accent: "#3f2605"
  dark-accent-foreground: "#ffedc9"
  dark-destructive: "#ef677f"
  dark-destructive-foreground: "#340210"
  dark-success: "#6cb451"
  dark-success-foreground: "#0a1f08"
  dark-warning: "#cfb31a"
  dark-warning-foreground: "#231b00"
  dark-border: "#5a503e"
  dark-input: "#71654f"
  dark-ring: "#e8a52d"
typography:
  display-lg:
    fontFamily: Epilogue
    fontSize: 56px
    fontWeight: 800
    lineHeight: 1.05
    letterSpacing: -0.03em
  display-md:
    fontFamily: Epilogue
    fontSize: 40px
    fontWeight: 800
    lineHeight: 1.1
    letterSpacing: -0.025em
  heading-lg:
    fontFamily: Epilogue
    fontSize: 28px
    fontWeight: 700
    lineHeight: 1.2
    letterSpacing: -0.015em
  heading-md:
    fontFamily: Epilogue
    fontSize: 20px
    fontWeight: 700
    lineHeight: 1.3
    letterSpacing: -0.01em
  heading-sm:
    fontFamily: Karla
    fontSize: 16px
    fontWeight: 700
    lineHeight: 1.4
  body-lg:
    fontFamily: Karla
    fontSize: 18px
    fontWeight: 400
    lineHeight: 1.6
  body-md:
    fontFamily: Karla
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.6
  body-sm:
    fontFamily: Karla
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
  label:
    fontFamily: Karla
    fontSize: 14px
    fontWeight: 700
    lineHeight: 1.25
    letterSpacing: 0.01em
  caption:
    fontFamily: Karla
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0.02em
  code:
    fontFamily: IBM Plex Mono
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.55
rounded:
  sm: 2px
  md: 6px
  lg: 10px
  xl: 16px
  full: 9999px
spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
  2xl: 48px
  3xl: 64px
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  button-secondary:
    backgroundColor: "{colors.secondary}"
    textColor: "{colors.secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  button-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  input:
    backgroundColor: "{colors.background}"
    textColor: "{colors.foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 44px
  card:
    backgroundColor: "{colors.card}"
    textColor: "{colors.card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  popover:
    backgroundColor: "{colors.popover}"
    textColor: "{colors.popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text:
    backgroundColor: "{colors.background}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt:
    backgroundColor: "{colors.muted}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge:
    backgroundColor: "{colors.accent}"
    textColor: "{colors.accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-success:
    backgroundColor: "{colors.success}"
    textColor: "{colors.success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-warning:
    backgroundColor: "{colors.warning}"
    textColor: "{colors.warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  button-primary-dark:
    backgroundColor: "{colors.dark-primary}"
    textColor: "{colors.dark-primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  button-secondary-dark:
    backgroundColor: "{colors.dark-secondary}"
    textColor: "{colors.dark-secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  button-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 20px
    height: 44px
  input-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 44px
  card-dark:
    backgroundColor: "{colors.dark-card}"
    textColor: "{colors.dark-card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  popover-dark:
    backgroundColor: "{colors.dark-popover}"
    textColor: "{colors.dark-popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt-dark:
    backgroundColor: "{colors.dark-muted}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge-dark:
    backgroundColor: "{colors.dark-accent}"
    textColor: "{colors.dark-accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-success-dark:
    backgroundColor: "{colors.dark-success}"
    textColor: "{colors.dark-success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-warning-dark:
    backgroundColor: "{colors.dark-warning}"
    textColor: "{colors.dark-warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
  badge-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 24px
---

# Custard Schoolbook

## Overview

Custard Schoolbook is for learning products that borrow from 70s textbooks, 80s software manuals and risograph print. The retro cues are limited to three things: the ochre and cream palette, Epilogue 700-800 headlines, and zero-blur offset shadows. Spacing, contrast and control sizes follow current accessibility practice. Text pairs meet at least 4.5:1 in both modes, and controls are 44px tall, so lessons stay readable over long sessions.

Moods: retro, friendly, bold, warm. Built for: education, e-learning, publishing. Density: comfortable.

Every color has a light value and a dark value. Tokens named `dark-*` are the dark-mode counterparts of the token with the same role name.

## Colors

Ochre (OKLCH hue about 70) is the only action color. It is used for primary, ring, links and progress. In light mode primary is brand.600 #96600a with white text (about 5.3:1). Against the cream background it measures about 4.9:1. The neutral ramp is tinted toward the same hue: steps 400-700 were nudged from olive toward brown so mid-greys don't go muddy. Ink is neutral.950 #1b1812, a brown-black rather than grey. Destructive is crimson (danger.600 #b92646, about 6.1:1 with white), roughly 60° of hue away from ochre, so an error never reads as a darker primary. Warning stays lemon yellow (warning.200 fill with warning.900 text) so it is not confused with the brand. Success is a warm textbook green (success.700 with white, about 7:1). In dark mode, background is neutral.950 and card/popover are neutral.900, one step lifted. Primary moves to brand.400 #e8a52d with brand.950 text (about 8:1), giving a CRT-amber glow without neon saturation.

- **Primary** `#96600a` / dark `#e8a52d`: the single action color. Primary buttons, links, focus ring.
- **Background / Foreground** `#fbf6ec` / dark `#1b1812` on `#1b1812` / dark `#fbf6ec`: page surface and body text.
- **Card** `#fffdf8` / dark `#2e291f`: raised surfaces.
- **Secondary** `#f3ecde` / dark `#433c2e`: secondary buttons and quiet controls.
- **Muted** `#f3ecde` / dark `#433c2e` with **muted-foreground** `#5a503e` / dark `#cec2ad`: helper text, table stripes, disabled-looking surfaces.
- **Accent** `#ffedc9` / dark `#3f2605`: highlights, selected rows, badges.
- **Destructive** `#b92646` / dark `#ef677f`, **Success** `#2a6520` / dark `#6cb451`, **Warning** `#f8e46e` / dark `#cfb31a`: status only, always paired with an icon or label.
- **Border** `#cec2ad` / dark `#5a503e`, **Input** `#ad9f8a` / dark `#71654f`, **Ring** `#96600a` / dark `#e8a52d`.

All text/background pairs above pass WCAG AA (4.5:1) in both modes; this is checked automatically at build time.

## Typography

Display and heading sizes follow a 1.4 ratio: 20 → 28 → 40 → 56px. Tracking tightens as size grows: heading-md -0.01em, heading-lg -0.015em, display-md -0.025em, display-lg -0.03em. Epilogue uses only weights 700 and 800. Karla (400/500/700) sets all body text, forms and buttons. Body sizes step 14 → 16 → 18px with line heights of 1.5-1.6 for long reading. IBM Plex Mono 400/500 (typography.code, 14/1.55) is reserved for code, keyboard shortcuts, quiz answer keys and data labels.

- Display: **Epilogue** (fallback system-ui, sans-serif)
- Interface: **Karla** (fallback system-ui, sans-serif)
- Mono: **IBM Plex Mono** (fallback ui-monospace, monospace)

| Token | Font | Size | Line height | Weight |
|---|---|---|---|---|
| display-lg | Epilogue | 56px | 1.05 | 800 |
| display-md | Epilogue | 40px | 1.1 | 800 |
| heading-lg | Epilogue | 28px | 1.2 | 700 |
| heading-md | Epilogue | 20px | 1.3 | 700 |
| heading-sm | Karla | 16px | 1.4 | 700 |
| body-lg | Karla | 18px | 1.6 | 400 |
| body-md | Karla | 16px | 1.6 | 400 |
| body-sm | Karla | 14px | 1.5 | 400 |
| label | Karla | 14px | 1.25 | 700 |
| caption | Karla | 12px | 1.4 | 500 |
| code | IBM Plex Mono | 14px | 1.55 | 400 |

## Layout

Comfortable density on a 4px base grid (space.1 = 4px). Reading columns max out at about 68ch (about 680px at body-md), and page containers at 1160px. Buttons and inputs are 44px tall. Card padding is space.6 (24px). Page sections are separated by space.12 to space.16 (48-64px).

Spacing uses a 4px base: xs = 4px, sm = 8px, md = 16px, lg = 24px, xl = 32px, 2xl = 48px, 3xl = 64px.

## Elevation & Depth

Depth uses hard-offset, zero-blur shadows: sm 2px, md 4px, lg 8px, all in brand.950 at 85% opacity, paired with a 2px border. Cards and raised buttons use shadow.sm. Popovers and dialogs use shadow.lg. In dark mode the shadow nearly disappears against neutral.950, so the 2px border carries the edge. No blurred shadows anywhere.

- sm: `2px 2px 0 rgba(39, 22, 2, 0.85)`
- md: `4px 4px 0 rgba(39, 22, 2, 0.85)`
- lg: `8px 8px 0 rgba(39, 22, 2, 0.85)`

## Shapes

Controls use radius.md (6px) and cards use radius.lg (10px), for a printed-label feel. radius.full is limited to badges and progress tracks. Cards, inputs and buttons use a 2px border: border (neutral.300 light / neutral.700 dark) on cards, input (neutral.400 / neutral.600) on fields.

Radius scale: sm 2px, md 6px, lg 10px, xl 16px, full 9999px.

## Components

Components ending in `-dark` are the dark-mode versions. Button: 44px tall, 20px horizontal padding, label type. Input: 44px tall with a 1px input-colored border; focus shows a 2px ring in the ring color. Card: 24px padding, 1px border, sm shadow. Badge: pill, caption type.

## Do's and Don'ts

- **Do:** Use primary (brand.600 in light, brand.400 in dark) for one main action per view, such as 'Start lesson'. Use secondary or ghost buttons for every other action in that view.
- **Do:** Set display-lg (56px, -0.03em), display-md (40px, -0.025em) and heading-lg (28px, -0.015em) in Epilogue 800/800/700. Keep the token letterSpacing values; don't loosen them.
- **Do:** Give cards and raised buttons a 2px border plus shadow.sm. Use shadow.lg only for dialogs and popovers.
- **Do:** In dark mode, let the 2px border (neutral.700) define card and dialog edges, since the brand.950 shadow barely shows on neutral.950.
- **Do:** Set lesson copy in body-md (Karla 16px / 1.6) or body-lg (18px / 1.6). Cap reading columns at 68ch.
- **Do:** Show focus on buttons and inputs as a 2px ring in the ring token with a 2px offset. It measures at least 3:1 against background in both modes.
- **Do:** Use typography.code (IBM Plex Mono 14px) only for code samples, keyboard shortcuts and quiz answer keys.
- **Do:** Pair every success, warning and destructive state with an icon or text label so meaning never depends on color alone.
- **Don't:** Don't add blur to shadows. Every shadow token is a zero-blur offset (2/4/8px).
- **Don't:** Don't use brand ochre for errors. Use destructive (danger.600 light / danger.400 dark), and keep warning on the warning scale (warning.200 fill with warning.900 text in light).
- **Don't:** Don't set Epilogue below 20px (heading-md) or under weight 700. Use Karla heading-sm or label for anything smaller.
- **Don't:** Don't use brand.500 or lighter for text or icons on background or card in light mode. Brand.500 is about 2.9:1 and brand.400 about 2:1 on neutral.50.
- **Don't:** Don't use #000000, #ffffff or cool grey for page backgrounds. Stay on the neutral ramp; light card and popover may use #fffdf8.
- **Don't:** Don't place more than one primary-filled button in the same card, dialog footer or toolbar.
- **Don't:** Don't round buttons or inputs beyond radius.md (6px) or cards beyond radius.lg (10px). Reserve radius.full for badges and progress tracks.
