Scholarly Editorial UI (alan-hirsch)
Use this skill whenever you create or restyle front-end UI in this repo. You are
designing inside an established, documented design system — your job is
fidelity to it, not invention. Match the evidenced style; never introduce a new
look.
North Star
"The Modern Archivist" — a digital monograph. Authoritative, curated,
intellectually warm. The palette is Plum & Parchment: plum is the ink,
parchment is the paper. Hierarchy comes from intentional asymmetry and
tonal depth (layered paper surfaces), not from boxes, borders, or loud color.
Source of truth (read these, in order)
src/app/globals.css — all design tokens (HSL CSS vars) + the canonical
utility-class API (.typo-*, .btn-primary-gradient, .scholarly-glass,
.signature-label, .ghost-border, .tonal-lift, .content-prose).
tailwind.config.ts — token→utility mapping, type scale, radius, glow shadows, motion.
_docs/_build/design/SCHOLARLY_EDITORIAL.md — the written spec (palette, No-Line rule, elevation, do/don'ts).
- Golden components:
src/components/pathways.tsx, src/components/navigation/PublicHeader.tsx, src/app/layout.tsx.
⚠️ Ignore the stale "Pastoral-Warm" docs. DESIGN_CHARTER.md,
DESIGN_CHAIN.md, design-folder README.md, HERO_SECTION_GUIDELINES.md, and
their layers/D0–D6 derivatives describe an abandoned theme (Amethyst/gold
#9460B8/#7A3596, Montserrat + Inter, --radius: 10px). None of those values
exist in src/. They are traps. The truth is globals.css + SCHOLARLY_EDITORIAL.md.
Stack
Next.js 15 App Router (RSC) · Tailwind v3.4 (JS config, HSL vars — not v4/OKLCH/@theme) ·
shadcn/ui "new-york" over Radix · cn() from src/lib/utils.ts · icons only via <Icon> from @/components/ui/icon (never import Lucide directly).
Color — semantic tokens only (zero inline hex)
Use Tailwind semantic classes that resolve to hsl(var(--x)). Light theme:
| Role |
Token / class |
Value |
| Parchment canvas |
bg-background |
#fbf9f4 |
| Ink (never pure black) |
text-foreground |
#1b1c19 |
| Plum ink / primary |
bg-primary / text-primary |
#37203b |
| Deep plum container |
bg-accent / bg-primary-container |
#4e3652 |
| Muted paper |
bg-muted |
#ebe8e3 |
| Featured card fill |
bg-primary-fixed |
#fad8fc |
| Ghost border |
outline-variant |
#cec3cc |
Tonal surface ladder (use these to separate regions instead of borders):
surface-bright (#fefcf8, nav) → surface (#fbf9f4) → surface-container-low
(#f5f3ee) → surface-container (#f0eee9) → surface-container-high (#ebe8e3) →
surface-container-highest (#e4e2dd). Dark theme inverts the same ladder (.dark).
Rules: Never text-black/bg-black/raw hex in TSX. Don't saturate the
background with plum ("purple is the ink, not the paper"). Color is essentially a
plum-on-parchment duotone with restrained accents.
Typography
- Headings: Newsreader (serif) →
font-heading (dominant) or font-serif (both map to Newsreader). Loaded via next/font in src/app/layout.tsx.
- Body/UI: Manrope (sans) →
font-body / default sans.
- Mono: JetBrains Mono →
font-mono.
- Canonical type API: the
.typo-* utility classes (.typo-display,
.typo-h1…h4, .typo-body, .typo-body-lg, .typo-small, .typo-label).
Prefer these over ad-hoc text-[..]. .signature-label = ALL-CAPS Manrope, 0.05em tracking, for eyebrows.
- Headings are tight (
line-height ~1.1, -0.02em tracking) and use weight 700–800; body line-height 1.65. Never pure-black ink.
Spacing, radius, elevation, motion
- Radius:
--radius: 0.5rem (rounded-lg); buttons are pills (rounded-full / rounded-button); cards often rounded-xl. No hard 90° corners.
- Layout: sections
container mx-auto px-4 md:px-8, vertical rhythm py-16 md:py-24; nav/content max-w-7xl mx-auto; reading column max-w-measure (~65ch). .editorial-layout for intentional asymmetry.
- The No-Line rule: do not use 1px solid borders or
<hr> to separate
sections. Transition between tonal surfaces (surface → surface-container-low) instead.
- Elevation: prefer plum-tinted ambient glow (
shadow-primary-glow,
shadow-primary-glow-md/-lg) and .tonal-lift over hard drop shadows. Avoid
pure-black rgba(0,0,0,…) shadows. "If you can clearly see where the shadow ends, it's too dark."
- Motion:
motion/react (the renamed framer-motion). Entrance pattern:
initial={{opacity:0,y:20}} → whileInView={{opacity:1,y:0}},
viewport={{once:true,margin:'-50px'}}, stagger delay: index*0.1. CSS helpers
.fade-up/.card-hover. Always honor prefers-reduced-motion (globals already zeroes durations).
Component patterns
- Compose shadcn primitives from
src/components/ui/* — never edit them for
styling. Add tokens in globals.css/tailwind.config.ts or apply class
overrides via cn(). (The bare shadcn defaults — rounded-md buttons,
rounded-xl cards — are not themselves "the brand"; the editorial flavor lives
in tokens + the globals.css utility classes.)
- Card (
pathways.tsx): group relative flex h-full flex-col rounded-xl overflow-hidden bg-card shadow-md hover:shadow-xl transition-all duration-300,
image top with bg-gradient-to-t from-background/95 via-background/60 to-transparent,
font-serif text-2xl title, arrow reveal on hover.
- Nav (
PublicHeader.tsx): fixed header gaining glass-panel border-b border-border when scrolled; links font-bold uppercase tracking-widest hover:text-primary, active in text-primary with an animated bg-primary
underline (w-0 group-hover:w-1/2, active ? w-full).
- Layering discipline: Tokens → Tailwind → Radix/shadcn → Domain components → Patterns → Pages.
Avoid (drift — do not copy)
- The Pastoral-Warm/Amethyst/Montserrat docs (see warning above).
src/components/_archive/* (deprecated: footer.tsx, navbar.tsx, home-v2, simplified, scholar-profile-v2).
- Heavy
shadow-xl/shadow-2xl and pure-black shadows — real drift vs. the plum-glow/tonal intent.
docs/html/*, public/html/* — unrelated scraped vendor CSS.
- The generic
tailwind-design-system skill (it targets Tailwind v4 / OKLCH / @theme — wrong for this v3 + HSL repo).
- Inline hex anywhere in
src/components (verified clean — keep it that way).
Workflow checklist
- Identify the surface tier and tokens before writing markup.
- Compose from
ui/* primitives + .typo-*/utility classes; add overrides via cn().
- Separate regions with tonal surfaces, not lines.
- Use plum-glow / tonal-lift elevation; pill buttons; 0.5rem corners.
- Newsreader headings, Manrope body; icons via
<Icon>.
- Add
motion/react entrance with reduced-motion respected.
- Verify: no raw hex, no
_archive imports, no stale-doc tokens, no 1px section dividers.
1---2name: scholarly-editorial-ui3description: Front-end UI design expert for the alan-hirsch app's "Scholarly Editorial / Plum & Parchment" design system. Use when building or restyling any page, section, hero, card, nav, or component in this repo — to match the existing visual language. Anchors to src/app/globals.css tokens, tailwind.config.ts, and _docs/_build/design/SCHOLARLY_EDITORIAL.md. Keywords: plum, parchment, Newsreader, Manrope, scholarly, editorial, tonal surfaces, no-line rule, shadcn, Radix, motion/react, design tokens, theming.4---56# Scholarly Editorial UI (alan-hirsch)78Use this skill whenever you create or restyle front-end UI in this repo. You are9designing inside an **established, documented** design system — your job is10fidelity to it, not invention. Match the evidenced style; never introduce a new11look.1213## North Star1415**"The Modern Archivist" — a digital monograph.** Authoritative, curated,16intellectually warm. The palette is **Plum & Parchment**: plum is the *ink*,17parchment is the *paper*. Hierarchy comes from **intentional asymmetry** and18**tonal depth** (layered paper surfaces), not from boxes, borders, or loud color.1920## Source of truth (read these, in order)21221. `src/app/globals.css` — **all design tokens** (HSL CSS vars) + the canonical23 utility-class API (`.typo-*`, `.btn-primary-gradient`, `.scholarly-glass`,24 `.signature-label`, `.ghost-border`, `.tonal-lift`, `.content-prose`).252. `tailwind.config.ts` — token→utility mapping, type scale, radius, glow shadows, motion.263. `_docs/_build/design/SCHOLARLY_EDITORIAL.md` — the written spec (palette, No-Line rule, elevation, do/don'ts).274. Golden components: `src/components/pathways.tsx`, `src/components/navigation/PublicHeader.tsx`, `src/app/layout.tsx`.2829> ⚠️ **Ignore the stale "Pastoral-Warm" docs.** `DESIGN_CHARTER.md`,30> `DESIGN_CHAIN.md`, design-folder `README.md`, `HERO_SECTION_GUIDELINES.md`, and31> their `layers/D0–D6` derivatives describe an **abandoned** theme (Amethyst/gold32> `#9460B8`/`#7A3596`, Montserrat + Inter, `--radius: 10px`). None of those values33> exist in `src/`. They are traps. The truth is `globals.css` + `SCHOLARLY_EDITORIAL.md`.3435## Stack3637Next.js 15 App Router (RSC) · Tailwind **v3.4** (JS config, HSL vars — *not* v4/OKLCH/`@theme`) ·38shadcn/ui "new-york" over Radix · `cn()` from `src/lib/utils.ts` · icons **only** via `<Icon>` from `@/components/ui/icon` (never import Lucide directly).3940## Color — semantic tokens only (zero inline hex)4142Use Tailwind semantic classes that resolve to `hsl(var(--x))`. Light theme:4344| Role | Token / class | Value |45|---|---|---|46| Parchment canvas | `bg-background` | `#fbf9f4` |47| Ink (never pure black) | `text-foreground` | `#1b1c19` |48| Plum ink / primary | `bg-primary` / `text-primary` | `#37203b` |49| Deep plum container | `bg-accent` / `bg-primary-container` | `#4e3652` |50| Muted paper | `bg-muted` | `#ebe8e3` |51| Featured card fill | `bg-primary-fixed` | `#fad8fc` |52| Ghost border | `outline-variant` | `#cec3cc` |5354**Tonal surface ladder** (use these to separate regions instead of borders):55`surface-bright` (#fefcf8, nav) → `surface` (#fbf9f4) → `surface-container-low`56(#f5f3ee) → `surface-container` (#f0eee9) → `surface-container-high` (#ebe8e3) →57`surface-container-highest` (#e4e2dd). Dark theme inverts the same ladder (`.dark`).5859**Rules:** Never `text-black`/`bg-black`/raw hex in TSX. Don't saturate the60background with plum ("purple is the ink, not the paper"). Color is essentially a61plum-on-parchment duotone with restrained accents.6263## Typography6465- **Headings:** Newsreader (serif) → `font-heading` (dominant) or `font-serif` (both map to Newsreader). Loaded via next/font in `src/app/layout.tsx`.66- **Body/UI:** Manrope (sans) → `font-body` / default sans.67- **Mono:** JetBrains Mono → `font-mono`.68- **Canonical type API:** the `.typo-*` utility classes (`.typo-display`,69 `.typo-h1…h4`, `.typo-body`, `.typo-body-lg`, `.typo-small`, `.typo-label`).70 Prefer these over ad-hoc `text-[..]`. `.signature-label` = ALL-CAPS Manrope, 0.05em tracking, for eyebrows.71- Headings are tight (`line-height ~1.1`, `-0.02em` tracking) and use weight 700–800; body `line-height 1.65`. Never pure-black ink.7273## Spacing, radius, elevation, motion7475- **Radius:** `--radius: 0.5rem` (`rounded-lg`); buttons are pills (`rounded-full` / `rounded-button`); cards often `rounded-xl`. No hard 90° corners.76- **Layout:** sections `container mx-auto px-4 md:px-8`, vertical rhythm `py-16 md:py-24`; nav/content `max-w-7xl mx-auto`; reading column `max-w-measure` (~65ch). `.editorial-layout` for intentional asymmetry.77- **The No-Line rule:** **do not** use 1px solid borders or `<hr>` to separate78 sections. Transition between tonal surfaces (`surface` → `surface-container-low`) instead.79- **Elevation:** prefer plum-tinted ambient glow (`shadow-primary-glow`,80 `shadow-primary-glow-md/-lg`) and `.tonal-lift` over hard drop shadows. Avoid81 pure-black `rgba(0,0,0,…)` shadows. "If you can clearly see where the shadow ends, it's too dark."82- **Motion:** `motion/react` (the renamed framer-motion). Entrance pattern:83 `initial={{opacity:0,y:20}}` → `whileInView={{opacity:1,y:0}}`,84 `viewport={{once:true,margin:'-50px'}}`, stagger `delay: index*0.1`. CSS helpers85 `.fade-up`/`.card-hover`. Always honor `prefers-reduced-motion` (globals already zeroes durations).8687## Component patterns8889- Compose **shadcn primitives** from `src/components/ui/*` — **never edit them for90 styling**. Add tokens in `globals.css`/`tailwind.config.ts` or apply class91 overrides via `cn()`. (The bare shadcn defaults — `rounded-md` buttons,92 `rounded-xl` cards — are not themselves "the brand"; the editorial flavor lives93 in tokens + the `globals.css` utility classes.)94- **Card** (`pathways.tsx`): `group relative flex h-full flex-col rounded-xl95 overflow-hidden bg-card shadow-md hover:shadow-xl transition-all duration-300`,96 image top with `bg-gradient-to-t from-background/95 via-background/60 to-transparent`,97 `font-serif text-2xl` title, arrow reveal on hover.98- **Nav** (`PublicHeader.tsx`): `fixed` header gaining `glass-panel border-b99 border-border` when scrolled; links `font-bold uppercase tracking-widest100 hover:text-primary`, active in `text-primary` with an animated `bg-primary`101 underline (`w-0 group-hover:w-1/2`, `active ? w-full`).102- Layering discipline: **Tokens → Tailwind → Radix/shadcn → Domain components → Patterns → Pages**.103104## Avoid (drift — do not copy)105106- The Pastoral-Warm/Amethyst/Montserrat docs (see warning above).107- `src/components/_archive/*` (deprecated: footer.tsx, navbar.tsx, home-v2, simplified, scholar-profile-v2).108- Heavy `shadow-xl`/`shadow-2xl` and pure-black shadows — real drift vs. the plum-glow/tonal intent.109- `docs/html/*`, `public/html/*` — unrelated scraped vendor CSS.110- The generic `tailwind-design-system` skill (it targets Tailwind v4 / OKLCH / `@theme` — wrong for this v3 + HSL repo).111- Inline hex anywhere in `src/components` (verified clean — keep it that way).112113## Workflow checklist1141151. Identify the surface tier and tokens before writing markup.1162. Compose from `ui/*` primitives + `.typo-*`/utility classes; add overrides via `cn()`.1173. Separate regions with tonal surfaces, not lines.1184. Use plum-glow / tonal-lift elevation; pill buttons; 0.5rem corners.1195. Newsreader headings, Manrope body; icons via `<Icon>`.1206. Add `motion/react` entrance with reduced-motion respected.1217. Verify: no raw hex, no `_archive` imports, no stale-doc tokens, no 1px section dividers.