|
30 | 30 | --smoke:rgba(11,114,133,.18); --lossbar:rgba(209,67,63,.5); --glow:0; |
31 | 31 | --smoke-hot:#064a57; --smoke-mid:#1596ad; --smoke-cool:#b3722f; |
32 | 32 | } |
33 | | - /* Amber: the old amber-phosphor CRT — warm orange trace on near-black */ |
34 | | - html[data-theme="amber"] { |
35 | | - --bg:#0c0a06; --panel:#16120b; --screen:#080602; --line:#2a2115; |
36 | | - --phos:#ffb340; --amber:#ffd28a; --alert:#ff6b4a; --ink:#e8d5b0; --dim:#8a7550; |
37 | | - --grid-axis:#3a2e1c; --grid-split:#1e1810; |
38 | | - --smoke:rgba(255,179,64,.16); --lossbar:rgba(255,107,74,.5); --glow:7; |
39 | | - --smoke-hot:#fff0d0; --smoke-mid:#ffb340; --smoke-cool:#8a6020; |
40 | | - --shadow:0 1px 2px rgba(0,0,0,.6); --shadow-lg:0 10px 30px rgba(0,0,0,.5); |
| 33 | + /* Nord — the arctic palette that ships in half the terminals on earth. |
| 34 | + Desaturated blue-greys with a single frost accent; nothing shouts. */ |
| 35 | + html[data-theme="nord"] { |
| 36 | + --bg:#2e3440; --panel:#3b4252; --screen:#292e39; --line:#434c5e; |
| 37 | + --phos:#88c0d0; --amber:#ebcb8b; --alert:#bf616a; --ink:#e5e9f0; --dim:#7b88a1; |
| 38 | + --grid-axis:#4c566a; --grid-split:#373e4c; |
| 39 | + --smoke:rgba(136,192,208,.18); --lossbar:rgba(191,97,106,.55); --glow:5; |
| 40 | + --smoke-hot:#eceff4; --smoke-mid:#88c0d0; --smoke-cool:#5e81ac; |
| 41 | + --shadow:0 1px 2px rgba(0,0,0,.35); --shadow-lg:0 10px 30px rgba(0,0,0,.30); |
41 | 42 | } |
42 | | - /* Mono: high-contrast black on white — for printing and bright rooms */ |
43 | | - html[data-theme="mono"] { |
44 | | - --bg:#ffffff; --panel:#fbfbfb; --screen:#ffffff; --line:#d8d8d8; |
45 | | - --phos:#111111; --amber:#666666; --alert:#c00000; --ink:#111111; --dim:#777777; |
46 | | - --grid-axis:#c8c8c8; --grid-split:#ededed; |
47 | | - --smoke:rgba(17,17,17,.22); --lossbar:rgba(192,0,0,.45); --glow:0; |
48 | | - --smoke-hot:#000000; --smoke-mid:#444444; --smoke-cool:#999999; |
49 | | - --shadow:0 1px 2px rgba(0,0,0,.08); --shadow-lg:0 8px 24px rgba(0,0,0,.10); |
| 43 | + /* Solarized Light — Ethan Schoonover's palette, tuned for long reading sessions. |
| 44 | + Warm paper base, muted cyan trace, red reserved strictly for loss. */ |
| 45 | + html[data-theme="solarized"] { |
| 46 | + --bg:#fdf6e3; --panel:#fffbf0; --screen:#fffdf6; --line:#e5ddc8; |
| 47 | + --phos:#2aa198; --amber:#b58900; --alert:#dc322f; --ink:#586e75; --dim:#93a1a1; |
| 48 | + --grid-axis:#d6cfba; --grid-split:#efe8d5; |
| 49 | + --smoke:rgba(42,161,152,.22); --lossbar:rgba(220,50,47,.45); --glow:0; |
| 50 | + --smoke-hot:#0f5f5a; --smoke-mid:#2aa198; --smoke-cool:#93a1a1; |
| 51 | + --shadow:0 1px 3px rgba(101,123,131,.12); --shadow-lg:0 10px 28px rgba(101,123,131,.16); |
50 | 52 | } |
51 | | - /* Midnight: deep blue, low blue-light glare for night shifts */ |
52 | | - html[data-theme="midnight"] { |
53 | | - --bg:#0a0e1a; --panel:#111726; --screen:#070a14; --line:#1e2740; |
54 | | - --phos:#6db3ff; --amber:#ffc857; --alert:#ff5c7a; --ink:#c3d2e8; --dim:#5a6b85; |
55 | | - --grid-axis:#243050; --grid-split:#131a2c; |
56 | | - --smoke:rgba(109,179,255,.16); --lossbar:rgba(255,92,122,.5); --glow:6; |
57 | | - --smoke-hot:#e8f4ff; --smoke-mid:#6db3ff; --smoke-cool:#3a5580; |
58 | | - --shadow:0 1px 2px rgba(0,0,0,.5); --shadow-lg:0 10px 30px rgba(0,0,0,.45); |
| 53 | + /* Amber CRT — a DEC VT220 in a dim room. One hue, three intensities, that is it. */ |
| 54 | + html[data-theme="amber"] { |
| 55 | + --bg:#100c04; --panel:#1a1409; --screen:#0a0702; --line:#3a2c14; |
| 56 | + --phos:#ffb000; --amber:#ffcc55; --alert:#ff5f2e; --ink:#f0c674; --dim:#8a6d3a; |
| 57 | + --grid-axis:#463a1c; --grid-split:#221a0c; |
| 58 | + --smoke:rgba(255,176,0,.16); --lossbar:rgba(255,95,46,.5); --glow:8; |
| 59 | + --smoke-hot:#fff3d0; --smoke-mid:#ffb000; --smoke-cool:#7a5410; |
| 60 | + --shadow:0 1px 2px rgba(0,0,0,.6); --shadow-lg:0 10px 30px rgba(0,0,0,.55); |
59 | 61 | } |
60 | 62 | * { box-sizing:border-box; margin:0; } |
61 | 63 | body { background:var(--bg); color:var(--ink); font-family:var(--mono); padding:18px 22px; } |
|
112 | 114 | <div class="mark">pingping ●</div> |
113 | 115 | <div class="tag">One binary. One graph. Zero guesswork.</div> |
114 | 116 | <button class="pill" id="themeBtn" title="switch theme" style="margin-left:auto">◐ <span id="themeName">dark</span></button> |
115 | | - <button class="pill" id="themeSave" title="save this theme as the default for everyone on this install">save as default</button> |
116 | 117 | </header> |
117 | 118 |
|
118 | 119 | <div class="row"> |
|
176 | 177 | <script> |
177 | 178 | const $ = id => document.getElementById(id); |
178 | 179 | const cssv = n => getComputedStyle(document.documentElement).getPropertyValue(n).trim(); |
179 | | -const THEMES = ['dark', 'daylight', 'arctic', 'amber', 'mono', 'midnight']; |
| 180 | +const THEMES = ['dark', 'daylight', 'arctic', 'nord', 'solarized', 'amber']; |
180 | 181 | let theme = localStorage.getItem('pp_theme') || 'dark'; |
181 | 182 | if (!THEMES.includes(theme)) theme = 'dark'; |
182 | | -// 本地没手动选过 -> 跟随服务端保存的默认主题 |
183 | | -if (!localStorage.getItem('pp_theme')) { |
184 | | - fetch('/api/theme').then(r => r.json()).then(d => { |
185 | | - if (d.theme && THEMES.includes(d.theme) && d.theme !== theme) { |
186 | | - theme = d.theme; applyTheme(); render(); |
187 | | - } |
188 | | - }).catch(() => {}); |
189 | | -} |
190 | 183 | function applyTheme() { |
191 | 184 | if (theme === 'dark') delete document.documentElement.dataset.theme; |
192 | 185 | else document.documentElement.dataset.theme = theme; |
|
418 | 411 | applyTheme(); |
419 | 412 | render(); |
420 | 413 | }; |
421 | | -$('themeSave').onclick = async () => { |
422 | | - const btn = $('themeSave'), old = btn.textContent; |
423 | | - try { |
424 | | - await fetch('/api/theme', { method: 'POST', body: theme }); |
425 | | - btn.textContent = 'saved ✓'; |
426 | | - } catch { btn.textContent = 'failed'; } |
427 | | - setTimeout(() => { btn.textContent = old; }, 1500); |
428 | | -}; |
429 | | - |
430 | 414 | window.addEventListener('resize', () => chart && chart.resize()); |
431 | 415 | </script> |
432 | 416 | </body> |
|
0 commit comments