diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index def0ed9..091c73a 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -32,7 +32,7 @@ body:
- "Not sure"
- "Frontend / UI"
- "API routes"
- - "Content / MDX"
+ - "Content / data"
- "Docs / DX"
- "CI / tooling"
- "Other"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index ee9b6b9..30271ec 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -32,7 +32,7 @@
## Checklist
-- [ ] I have read [CONTRIBUTING.md](CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
+- [ ] I have read **[CONTRIBUTING.md](../CONTRIBUTING.md)** and **[CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md)**.
- [ ] No secrets, `.env.local`, or production tokens are included in this PR.
- [ ] **[README.md](../README.md)** / **[`.env.example`](../.env.example)** updated if routes, APIs, user-facing behavior, or env vars changed.
- [ ] **[CLAUDE.md](../CLAUDE.md)** updated if architecture, main data flows, or important paths changed (keeps AI / editor context aligned with README).
diff --git a/AGENTS.md b/AGENTS.md
index 512ac7e..6a612d5 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -116,7 +116,7 @@ Config: [`app/lib/spotify-playlists.ts`](app/lib/spotify-playlists.ts) (`CURATED
- **Mount:** [`app/components/subpage-enter.tsx`](app/components/subpage-enter.tsx) — portaled to `document.body`, `position: fixed` (does not affect layout flow)
- **Discovery order:** explicit `TocSection` (`data-toc-item`) → `.mag-label` → `.mag-card h1/h2`
- **Shown when:** ≥2 entries, viewport gutter ≥28px right of content column, not on excluded paths (`/music-for-life/map`)
-- **Home `/`:** `TocSection` labels — Kai T. Chen, Greeting, Contact; `.mag-label` — Listening, Location, Projects. Identity row uses **`md:flex-row-reverse`** + mobile `order-*` so TOC DOM order matches reading order **without** CSS Grid row-height gaps under the social column.
+- **Home `/`:** `TocSection` labels — Kai T. Chen, Greeting, Contact; `.mag-label` — Listening, Location. Identity row uses a responsive **CSS Grid** (`md:grid-cols-[36%_1fr]`) plus mobile `order-*`; the intro stays first in DOM so TOC order matches reading order while the photo/social column renders first on mobile.
- **Playlist pages:** index = Music for Life + each playlist name (`level={1}`); detail = playlist name + **Tracks** — never one TOC entry per song.
### Performance / loading (recent)
@@ -136,4 +136,3 @@ Config: [`app/lib/spotify-playlists.ts`](app/lib/spotify-playlists.ts) (`CURATED
| Human contribution process | [CONTRIBUTING.md](CONTRIBUTING.md) |
| Short Claude Code stack summary | [CLAUDE.md](CLAUDE.md) |
| Security reporting | [SECURITY.md](SECURITY.md) |
-| Cursor IDE git reminder | [`.cursor/rules/git-workflow.mdc`](.cursor/rules/git-workflow.mdc) |
diff --git a/CLAUDE.md b/CLAUDE.md
index efb0f44..47f2a87 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -19,18 +19,19 @@ Canonical documentation: **[README.md](README.md)** (setup, routes, APIs, env, C
| **Now playing** | `GET /api/spotify/now-playing` — Spotify Web API; optional Supabase writes (`listening_*`) with service role |
| **Last month top** | `GET /api/spotify/last-month-top` — Spotify top tracks (`short_term`, needs `user-top-read`) |
| **Client polling** | `app/hooks/use-now-playing.ts` — polls every **10s** (`cache: "no-store"`) |
-| **GitHub** | `GET /api/github/contributions` — GraphQL calendar; hand-maintained project list in `app/lib/personal-projects.ts` (stars fetched live) |
-| **Weather** | `GET /api/weather` — Open-Meteo (Berkeley); `berkeley-time.tsx` |
-| **Home UI** | Identity + social links; **Listening** / **Location** cards; **Projects** outer card with nested Course + Personal (`projects-split.tsx`); **PageToc** (Kai T. Chen, Greeting, Contact, Listening, Location, Projects) |
+| **GitHub** | `GET /api/github/contributions` — GraphQL calendar endpoint; hand-maintained course/personal lists merge descriptions, topics, stars, and archive state from GitHub |
+| **Weather** | `app/lib/weather.ts` fetches Open-Meteo for home SSR; `GET /api/weather` mirrors it; `berkeley-time.tsx` renders local time |
+| **Home UI** | Identity + Email/GitHub/LinkedIn/X links; **Listening** / server-rendered **Location** cards; **PageToc** (Kai T. Chen, Greeting, Contact, Listening, Location) |
| **Music for Life** | `/music-for-life` — curated Spotify playlists ([`MUSIC_FOR_LIFE_BASE`](lib/spotify-playlists.ts)); `[id]` detail; `/map` Mapbox viewer; old `/playlists` → 301 redirect |
| **Page TOC** | [`page-toc.tsx`](app/components/page-toc.tsx) + [`toc-section.tsx`](app/components/toc-section.tsx) — fixed right rail on `/`, `/about`, `/projects`, `/misc`, `/music-for-life` (not map); auto `.mag-label` + explicit `TocSection` |
-| **Course Projects** | `app/lib/course-projects.ts` — Oxford DUL (`/projects/oxford-dul-2025`) + Notion notes |
+| **Course Projects** | `app/lib/course-projects.ts` — Kai Course Notes entry backed by GitHub metadata; Oxford DUL remains at `/projects/oxford-dul-2025` |
| **Oxford portfolio** | `app/lib/oxford-dul-projects.ts` + `app/projects/oxford-dul-2025/` + `app/components/oxford-dul/` |
-| **Nav** | Bold labels; active link = accent + pill underline (`.nav-link` in `globals.css`) |
+| **Nav** | Desktop/mobile text links use the shared blue/yellow palette with no decorative underline (`.nav-link` in `globals.css`) |
| **List link pattern** | `hover-link-hint.tsx` — leading ↗ on hover, trailing `Label ↗`; row hover bg on list rows |
-| **Misc** | Watching / Remembrance / Things I Love (nested `mag-card-inset` categories) |
-| **Typography** | Geist on `body`; **Nunito** for nav + `.mag-card` / `.mag-label` |
-| **Theme** | `theme-provider.tsx` — default **light** when unset |
+| **Misc** | Things I Love (nested `mag-card-inset` categories) / Resources / Watching / Remembrance |
+| **Typography** | Geist Sans / Mono is the base system; **Nunito** is used across the editorial UI (nav, headings, cards, lists, controls) |
+| **Theme** | White/black page bases; structural blue `#628ea7`; hover yellow `#f8b364`; layered blue card borders/shadows |
+| **Theme mode** | `theme-provider.tsx` — default **light** when unset |
---
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index cc39902..2b4360d 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -71,7 +71,7 @@ reporter of any incident.
For this repository, contact the maintainer:
-- Via the email on the [About](https://kaichen.dev/about) page, or
+- Via [kaichen.dev.37@gmail.com](mailto:kaichen.dev.37@gmail.com) (also available from the homepage Contact links), or
- Through GitHub ([@kaiiiichen](https://github.com/kaiiiichen)) for non-sensitive matters.
For **security vulnerabilities**, do not use a public issue — follow [SECURITY.md](SECURITY.md) instead.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2fec594..a6e415d 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,7 +17,7 @@ Before you contribute:
| Human contributors | This file + [README](README.md) |
| AI coding agents (Cursor, Claude Code, etc.) | [AGENTS.md](AGENTS.md) — **branch + PR workflow** and commit conventions are mandatory |
-Maintainers use **pull requests to `main`**; direct pushes to `main` are discouraged even when permissions allow.
+All changes go through **pull requests to `main`**; do not push directly to `main`, even when permissions allow.
---
@@ -94,11 +94,13 @@ npm run build
- **Next.js 16** App Router, **React 19**, **TypeScript**, **Tailwind CSS 4**, **Vitest 4** for unit tests.
- `dev` and `build` use Next.js' default **Turbopack** bundler (no MDX in this repo).
-- **Fonts:** Geist Sans/Mono on `` / default `body`; **Nunito** for nav and magazine-style cards (see [`app/globals.css`](app/globals.css), [`app/layout.tsx`](app/layout.tsx)).
+- **Fonts:** Geist Sans/Mono provide the base type system; **Nunito** is used across the editorial UI (nav, headings, cards, lists, and controls). See [`app/globals.css`](app/globals.css), [`app/layout.tsx`](app/layout.tsx), and [`app/fonts.ts`](app/fonts.ts).
### Style
- Match existing component patterns, naming, and Tailwind usage.
+- Preserve the shared interaction palette: structural/link blue (`--link-color`), yellow hover/focus (`--link-hover-color`), and the layered blue `.mag-card` border/shadow hierarchy.
+- Keep `PageToc` discovery intact when restructuring pages: prefer explicit `TocSection` targets or existing `.mag-label` sections, and exclude fullscreen routes such as `/music-for-life/map`.
- Prefer **small, reviewable diffs** over large refactors unless discussed in an issue first.
- **Dark mode:** new UI should work in light and dark (`dark:` variants and existing theme patterns).
diff --git a/README.md b/README.md
index 6ebb2f8..c589ccf 100644
--- a/README.md
+++ b/README.md
@@ -17,15 +17,15 @@