From 96a3c09eaa0f491156fa0965747628209c6bd41f Mon Sep 17 00:00:00 2001 From: specificrabbit Date: Thu, 18 Jun 2026 22:48:19 +0800 Subject: [PATCH] Add night mode theme with twinkling stars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a 🌙/☀️ toggle button that switches between day and night themes, persisting the preference to localStorage. Night mode uses a deep dark background with 75 randomly twinkling stars. Respects prefers-color-scheme: dark automatically. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- index.html | 152 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 149 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index ca20e5e..520740e 100644 --- a/index.html +++ b/index.html @@ -22,6 +22,50 @@ --paper: #fbfbfa; --panel: rgba(255, 255, 255, 0.72); --accent: #111; + --steam: #c9c9c7; + --hover-bg: #fff; + --hover-border: #b8b8b8; + } + + @media (prefers-color-scheme: dark) { + :root:not([data-theme="day"]) { + color-scheme: dark; + --ink: #e8e8e4; + --muted: #888880; + --faint: #2c2c30; + --paper: #0c0c14; + --panel: rgba(18, 18, 26, 0.82); + --accent: #e8e8e4; + --steam: rgba(200, 200, 220, 0.55); + --hover-bg: rgba(30, 30, 40, 0.9); + --hover-border: #48484e; + } + } + + [data-theme="night"] { + color-scheme: dark; + --ink: #e8e8e4; + --muted: #888880; + --faint: #2c2c30; + --paper: #0c0c14; + --panel: rgba(18, 18, 26, 0.82); + --accent: #e8e8e4; + --steam: rgba(200, 200, 220, 0.55); + --hover-bg: rgba(30, 30, 40, 0.9); + --hover-border: #48484e; + } + + [data-theme="day"] { + color-scheme: light; + --ink: #151515; + --muted: #7a7a7a; + --faint: #d9d9d9; + --paper: #fbfbfa; + --panel: rgba(255, 255, 255, 0.72); + --accent: #111; + --steam: #c9c9c7; + --hover-bg: #fff; + --hover-border: #b8b8b8; } * { @@ -127,7 +171,7 @@ .steam { position: fixed; z-index: 0; - color: #c9c9c7; + color: var(--steam); font-size: 18px; pointer-events: none; animation: puff 1400ms ease-out forwards; @@ -158,8 +202,8 @@ } .mute-toggle:hover { - background: #fff; - border-color: #b8b8b8; + background: var(--hover-bg); + border-color: var(--hover-border); transform: translateY(-1px); } @@ -180,6 +224,54 @@ pointer-events: none; } + .theme-toggle { + position: fixed; + top: 16px; + right: 62px; + z-index: 10; + display: inline-flex; + width: 38px; + height: 38px; + align-items: center; + justify-content: center; + border: 1px solid var(--faint); + border-radius: 999px; + background: var(--panel); + color: var(--ink); + cursor: pointer; + font-size: 16px; + backdrop-filter: blur(14px); + transition: + border-color 150ms ease, + background 150ms ease, + transform 150ms ease; + } + + .theme-toggle:hover { + background: var(--hover-bg); + border-color: var(--hover-border); + transform: translateY(-1px); + } + + .theme-toggle:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 3px; + } + + .star { + position: fixed; + z-index: 0; + border-radius: 50%; + background: #e8e8e4; + pointer-events: none; + animation: twinkle var(--twinkle-dur, 3s) ease-in-out infinite var(--twinkle-delay, 0s); + } + + @keyframes twinkle { + 0%, 100% { opacity: var(--star-opacity, 0.65); } + 50% { opacity: 0.08; } + } + @keyframes wiggle { 0%, 100% { @@ -273,6 +365,16 @@ + +