diff --git a/index.html b/index.html
index 7585f4a0..4d94d156 100644
--- a/index.html
+++ b/index.html
@@ -10,7 +10,7 @@
-
+
diff --git a/src/contexts/ThemeContext.ts b/src/contexts/ThemeContext.ts
index c6d9cdfc..1c073e0b 100644
--- a/src/contexts/ThemeContext.ts
+++ b/src/contexts/ThemeContext.ts
@@ -1,6 +1,7 @@
import { createContext } from "react";
-export type StyleName = "smooth" | "brutalist" | "geocities" | "nyt";
+export type StyleName =
+ "smooth" | "brutalist" | "geocities" | "nyt" | "kanagawa";
export type ColorScheme = "auto" | "light" | "dark";
export interface ThemeContextValue {
diff --git a/src/main.tsx b/src/main.tsx
index 9a67ebf7..a8925178 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -11,6 +11,7 @@ import "./themes/smooth.css";
import "./themes/brutalist.css";
import "./themes/geocities.css";
import "./themes/nyt.css";
+import "./themes/kanagawa.css";
await loadCatalog();
diff --git a/src/pages/UserPublicProfile.tsx b/src/pages/UserPublicProfile.tsx
index ebdafdbe..f44d7b00 100644
--- a/src/pages/UserPublicProfile.tsx
+++ b/src/pages/UserPublicProfile.tsx
@@ -1186,6 +1186,13 @@ export function UserPublicProfile() {
>
Times
+
diff --git a/src/themes/kanagawa.css b/src/themes/kanagawa.css
new file mode 100644
index 00000000..f4252795
--- /dev/null
+++ b/src/themes/kanagawa.css
@@ -0,0 +1,134 @@
+/* ══════════════════════════════════════════════════════════════════════
+ Kanagawa theme — after rebelot/kanagawa.nvim, itself after Hokusai's
+ "The Great Wave off Kanagawa". Ink-wash surfaces, muted woodblock hues,
+ and monospace type throughout, as befits an editor colorscheme.
+
+ Dark scheme → Wave (sumiInk page, fujiWhite ink, crystalBlue accent).
+ Light scheme → Lotus (lotusInk ink, lotusBlue accent), on paper cooled
+ from lotusWhite's yellow to a neutral off-white.
+ ══════════════════════════════════════════════════════════════════════ */
+
+/* ── Palette (light-dark: see tokens.css) ─────────────────────────── */
+:root[data-style="kanagawa"] {
+ --font-mono:
+ "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
+ --font-body: var(--font-mono);
+ --font-display: var(--font-mono);
+
+ /* Softer, smaller corners than smooth — woodblock, not bubble. */
+ --radius-xs: 2px;
+ --radius-sm: 3px;
+ --radius-md: 4px;
+ --radius-lg: 6px;
+ --radius-xl: 8px;
+
+ /* Text — fujiWhite / oldWhite / springViolet1 · lotusInk1 / lotusGray2 / lotusViolet2 */
+ --color-text: light-dark(#545464, #dcd7ba);
+ --color-text-secondary: light-dark(#716e61, #c8c093);
+ --color-text-muted: light-dark(#766b90, #938aa9);
+ --color-on-accent: light-dark(#faf8f1, #16161d);
+
+ /* Surfaces — sunken < bg < surface < raised.
+ Wave: sumiInk0 · sumiInk3 · sumiInk4 · sumiInk5.
+ Lotus: lotusWhite desaturated to near-neutral off-whites. */
+ --color-bg: light-dark(#f3f1e8, #1f1f28);
+ --color-surface: light-dark(#faf9f4, #2a2a37);
+ --color-surface-raised: light-dark(#ffffff, #363646);
+ --color-surface-sunken: light-dark(#e9e6da, #16161d);
+
+ /* Borders — hairlines tinted from the ink */
+ --color-border: light-dark(rgb(84 84 100 / 0.18), rgb(220 215 186 / 0.13));
+ --color-border-subtle: light-dark(
+ rgb(84 84 100 / 0.1),
+ rgb(220 215 186 / 0.08)
+ );
+
+ /* Accent — crystalBlue / lotusBlue4 */
+ --color-accent: light-dark(#4d699b, #7e9cd8);
+ --color-accent-hover: light-dark(#624c83, #7fb4ca);
+ --color-accent-soft: light-dark(
+ rgb(77 105 155 / 0.12),
+ rgb(126 156 216 / 0.14)
+ );
+ --color-focus-ring: light-dark(
+ rgb(77 105 155 / 0.35),
+ rgb(126 156 216 / 0.45)
+ );
+
+ /* Links */
+ --color-link: light-dark(#4d699b, #7e9cd8);
+ --color-link-hover: light-dark(#624c83, #7fb4ca);
+
+ /* Danger — waveRed on winterRed / lotusRed */
+ --color-danger: light-dark(#c84053, #e46876);
+ --color-danger-bg: light-dark(#f6e0dd, #43242b);
+ --color-danger-hover: light-dark(#a8344a, #ff5d62);
+
+ /* Success — springGreen on winterGreen / lotusGreen */
+ --color-success: light-dark(#56703c, #98bb6c);
+ --color-success-bg: light-dark(#e3ead9, #2b3328);
+ --color-success-hover: light-dark(#4a6133, #b0cf85);
+
+ /* Warning — roninYellow / lotusOrange */
+ --color-warning: light-dark(#cc6d00, #ff9e3b);
+
+ /* Overlays */
+ --color-overlay: light-dark(rgb(84 84 100 / 0.3), rgb(22 22 29 / 0.7));
+ --color-header-user-bg: transparent;
+ --color-header-user-bg-hover: light-dark(
+ rgb(84 84 100 / 0.08),
+ rgb(220 215 186 / 0.08)
+ );
+
+ /* Misc */
+ --color-option-bg: light-dark(#faf9f4, #2a2a37);
+ --color-option-border: light-dark(
+ rgb(84 84 100 / 0.1),
+ rgb(220 215 186 / 0.08)
+ );
+
+ /* Theme-only hues — waveBlue2 / lotusBlue3 for rules, oniViolet /
+ lotusViolet4 for the brand, waveBlue1 / lotusBlue1 for selections. */
+ --kngw-wave: light-dark(#9fb5c9, #2d4f67);
+ --kngw-violet: light-dark(#624c83, #957fb8);
+ --kngw-selection: light-dark(#c7d7e0, #223249);
+
+ /* Shape & depth — flat like an editor, deep only where things float */
+ --border-width: 1px;
+ --shadow-1: 0 1px 2px light-dark(rgb(84 84 100 / 0.1), rgb(0 0 0 / 0.3));
+ --shadow-2: 0 8px 24px -6px light-dark(rgb(84 84 100 / 0.2), rgb(0 0 0 / 0.5));
+ --shadow-3: 0 24px 56px -12px
+ light-dark(rgb(84 84 100 / 0.3), rgb(0 0 0 / 0.7));
+
+ /* Component skins */
+ --header-bg: var(--color-bg);
+ --input-focus-bg: var(--color-surface-sunken);
+ --overlay-filter: blur(2px);
+ --modal-border: var(--color-border);
+ --card-border: var(--color-border-subtle);
+ --card-hover-border: var(--color-accent);
+ --tab-border: transparent;
+ --btn-primary-shadow: none;
+ --btn-primary-shadow-hover: none;
+}
+
+/* ══════════════════════════════════════════════════════════════════════
+ Structural overrides
+ ══════════════════════════════════════════════════════════════════════ */
+
+[data-style="kanagawa"] ::selection {
+ background: var(--kngw-selection);
+}
+
+[data-style="kanagawa"] .app-header-brand {
+ color: var(--kngw-violet);
+}
+
+/* ── Header — a wave-blue rule, like the editor's split border ───── */
+[data-style="kanagawa"] .app-header {
+ border-bottom: 2px solid var(--kngw-wave);
+}
+
+[data-style="kanagawa"] .feed-sort-btn:hover:not(.active) {
+ background: var(--color-accent-soft);
+}