v3: new Kanagawa style, after kanagawa.nvim — Wave palette in dark, a cooled Lotus in light, all JetBrains Mono
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 40s

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
khannurien
2026-09-19 20:37:18 +00:00
parent b8af349ed7
commit 20d717f879
5 changed files with 145 additions and 2 deletions

View File

@@ -10,7 +10,7 @@
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192x192.png?v=__ICON_VERSION__" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Saira:ital,wght@0,100..900;1,100..900&family=Space+Grotesk:wght@400;700;900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Saira:ital,wght@0,100..900;1,100..900&family=Space+Grotesk:wght@400;700;900&display=swap" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#01152a" />
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#faf5e9" />

View File

@@ -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 {

View File

@@ -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();

View File

@@ -1186,6 +1186,13 @@ export function UserPublicProfile() {
>
Times
</button>
<button
type="button"
className={style === "kanagawa" ? "active" : ""}
onClick={() => setStyle("kanagawa")}
>
Kanagawa
</button>
</div>
</div>
<div className="profile-appearance-row">

134
src/themes/kanagawa.css Normal file
View File

@@ -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);
}