diff --git a/src/http/landing/assets.zig b/src/http/landing/assets.zig index 618f70a..b9a0065 100644 --- a/src/http/landing/assets.zig +++ b/src/http/landing/assets.zig @@ -12,25 +12,29 @@ pub const css = \\ --bg: #070807; --panel: #101210; --panel-2: #151915; --line: #273026; \\ --text: #f0f1ec; --muted: #aaa69b; --dim: #69645c; --accent: #91adff; \\ --green: #39c178; --pink: #f05f8e; --focus: #c9d7ff; --glass: rgba(255,255,255,.085); + \\ --glass-a: #39c178; --glass-b: #91adff; --glass-c: #f05f8e; --glass-d: #f5d85d; \\ color-scheme: dark; \\} \\html[data-theme="dark"] { \\ --bg: #070807; --panel: #101210; --panel-2: #151915; --line: #273026; \\ --text: #f0f1ec; --muted: #aaa69b; --dim: #69645c; --accent: #91adff; \\ --green: #39c178; --pink: #f05f8e; --focus: #c9d7ff; --glass: rgba(255,255,255,.085); + \\ --glass-a: #39c178; --glass-b: #91adff; --glass-c: #f05f8e; --glass-d: #f5d85d; \\ color-scheme: dark; \\} \\@media (prefers-color-scheme: light) { \\ :root { \\ --bg: #f6f4ed; --panel: #fffdf7; --panel-2: #ece8dd; --line: #d8d0c0; \\ --text: #161412; --muted: #625c53; --dim: #8f8679; --accent: #315dcb; - \\ --green: #1b7340; --pink: #b72e5c; --focus: #163f9f; --glass: rgba(255,255,255,.72); color-scheme: light; + \\ --green: #1b7340; --pink: #b72e5c; --focus: #163f9f; --glass: rgba(255,255,255,.72); + \\ --glass-a: #1b7340; --glass-b: #315dcb; --glass-c: #b72e5c; --glass-d: #b88713; color-scheme: light; \\ } \\} \\html[data-theme="light"] { \\ --bg: #f6f4ed; --panel: #fffdf7; --panel-2: #ece8dd; --line: #d8d0c0; \\ --text: #161412; --muted: #625c53; --dim: #8f8679; --accent: #315dcb; \\ --green: #1b7340; --pink: #b72e5c; --focus: #163f9f; --glass: rgba(255,255,255,.72); + \\ --glass-a: #1b7340; --glass-b: #315dcb; --glass-c: #b72e5c; --glass-d: #b88713; \\ color-scheme: light; \\} \\* { box-sizing: border-box; } @@ -122,8 +126,8 @@ pub const css = \\.entropy-bars i { \\ position: relative; flex: 1 1 0; min-width: 5px; height: var(--h); min-height: 6px; \\ border-radius: 999px 999px 2px 2px; background: - \\ linear-gradient(180deg, #f5d85d 0%, #58e07d 42%, #69b7ff 72%, #f06ca8 100%); - \\ box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 5px 18px rgba(105,183,255,.18); + \\ linear-gradient(180deg, var(--glass-d) 0%, var(--glass-a) 42%, var(--glass-b) 72%, var(--glass-c) 100%); + \\ box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 5px 18px color-mix(in srgb, var(--glass-b) 18%, transparent); \\ transform: translateY(var(--y)); opacity: .78; \\ transition: opacity .16s ease, transform .16s ease, filter .16s ease; \\} @@ -138,7 +142,7 @@ pub const css = \\.entropy-axis { display: flex; justify-content: space-between; color: var(--dim); font-size: 9px; } \\.signal-empty { color: var(--dim); font-size: 11px; } \\@media (prefers-reduced-motion: reduce) { - \\ body::before, body::after, .pulse::before { animation: none; } + \\ body::before, body::after { animation: none; } \\ .entropy-label, .entropy-bars i { transition: none; } \\} \\.pulse { @@ -151,16 +155,6 @@ pub const css = \\ overflow: hidden; max-width: 100%; backdrop-filter: blur(24px) saturate(1.18); -webkit-backdrop-filter: blur(24px) saturate(1.18); \\ box-shadow: inset 0 1px 0 rgba(255,255,255,.16), inset 0 -24px 60px rgba(255,255,255,.035), 0 20px 54px rgba(0,0,0,.16); \\} - \\.pulse::before { - \\ content: ""; position: absolute; inset: 0; pointer-events: none; - \\ background: linear-gradient(100deg, transparent 0 38%, rgba(255,255,255,.16) 47%, transparent 57% 100%); - \\ transform: translateX(-75%); animation: glass-sweep 9s ease-in-out infinite; - \\} - \\@keyframes glass-sweep { - \\ 0%, 18% { transform: translateX(-80%); opacity: 0; } - \\ 38% { opacity: .5; } - \\ 58%, 100% { transform: translateX(85%); opacity: 0; } - \\} \\.pulse > div { min-width: 0; } \\.pulse-kicker { color: var(--dim); font-size: 11px; text-transform: lowercase; } \\.pulse-row { display: flex; align-items: center; gap: 10px; min-width: 0; } @@ -202,7 +196,7 @@ pub const css = \\.collection a:hover { color: var(--accent); } \\.collection code { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; } \\.collection span { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; } - \\.collection i { position: absolute; left: 0; bottom: 0; height: 2px; background: linear-gradient(90deg, #f05f8e 0%, #91adff 48%, #39c178 100%); } + \\.collection i { position: absolute; left: 0; bottom: 0; height: 2px; background: linear-gradient(90deg, var(--glass-c) 0%, var(--glass-b) 48%, var(--glass-a) 100%); } \\.empty { color: var(--muted); margin: 0; } \\.sheet { position: fixed; inset: 0; z-index: 20; display: none; align-items: center; justify-content: center; padding: 16px; background: rgba(0, 0, 0, 0.42); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); } \\.sheet.open { display: flex; } @@ -226,7 +220,26 @@ pub const css = \\.client-body { padding: 15px 16px 17px; } \\.hint { margin: 0 0 12px; color: var(--dim); font-size: 11px; } \\.pref-section { display: grid; gap: 10px; margin-bottom: 16px; } + \\.pref-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; } \\.pref-label { color: var(--dim); font-size: 11px; text-transform: lowercase; } + \\#accent-value { color: var(--dim); font-size: 11px; } + \\.hue-slider { width: 100%; margin: 0; accent-color: var(--glass-a); cursor: pointer; } + \\.hue-slider::-webkit-slider-runnable-track { + \\ height: 10px; border: 1px solid color-mix(in srgb, var(--line) 80%, white 8%); border-radius: 999px; + \\ background: linear-gradient(90deg, hsl(0 80% 62%), hsl(60 82% 62%), hsl(120 76% 56%), hsl(180 78% 58%), hsl(240 82% 68%), hsl(300 78% 64%), hsl(360 80% 62%)); + \\} + \\.hue-slider::-webkit-slider-thumb { + \\ appearance: none; width: 20px; height: 20px; margin-top: -6px; border: 1px solid rgba(255,255,255,.42); + \\ border-radius: 999px; background: var(--glass-a); box-shadow: 0 3px 12px rgba(0,0,0,.26), inset 0 1px 0 rgba(255,255,255,.34); + \\} + \\.hue-slider::-moz-range-track { + \\ height: 10px; border: 1px solid color-mix(in srgb, var(--line) 80%, white 8%); border-radius: 999px; + \\ background: linear-gradient(90deg, hsl(0 80% 62%), hsl(60 82% 62%), hsl(120 76% 56%), hsl(180 78% 58%), hsl(240 82% 68%), hsl(300 78% 64%), hsl(360 80% 62%)); + \\} + \\.hue-slider::-moz-range-thumb { + \\ width: 18px; height: 18px; border: 1px solid rgba(255,255,255,.42); border-radius: 999px; + \\ background: var(--glass-a); box-shadow: 0 3px 12px rgba(0,0,0,.26), inset 0 1px 0 rgba(255,255,255,.34); + \\} \\.theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } \\.theme-option { min-height: 42px; border: 1px solid color-mix(in srgb, var(--line) 82%, white 6%); border-radius: 12px; background: color-mix(in srgb, var(--panel) 72%, transparent); color: var(--muted); font: inherit; font-size: 11px; cursor: pointer; box-shadow: inset 0 1px 0 rgba(255,255,255,.10); } \\.theme-option:hover, .theme-option.active { color: var(--text); border-color: color-mix(in srgb, var(--signal-a, var(--green)) 62%, var(--line)); } @@ -269,6 +282,7 @@ pub const script = \\(function() { \\ var key = 'zds.preferredClient'; \\ var themeKey = 'zds.theme'; + \\ var accentKey = 'zds.accentHue'; \\ var clients = [ \\ { value: 'bsky', label: 'Bluesky', icon: 'https://web-cdn.bsky.app/static/apple-touch-icon.png', url: function(handle, did) { return 'https://bsky.app/profile/' + handle; } }, \\ { value: 'blacksky', label: 'Blacksky', icon: 'https://blacksky.community/static/apple-touch-icon.png', url: function(handle, did) { return 'https://blacksky.community/profile/' + handle; } }, @@ -281,6 +295,25 @@ pub const script = \\ function write(value) { try { localStorage.setItem(key, value); } catch (_) {} } \\ function readTheme() { try { return localStorage.getItem(themeKey) || 'system'; } catch (_) { return 'system'; } } \\ function writeTheme(value) { try { value === 'system' ? localStorage.removeItem(themeKey) : localStorage.setItem(themeKey, value); } catch (_) {} } + \\ function readAccent() { try { return localStorage.getItem(accentKey) || '154'; } catch (_) { return '154'; } } + \\ function writeAccent(value) { try { localStorage.setItem(accentKey, value); } catch (_) {} } + \\ function clampHue(value) { + \\ var hue = Number(value); + \\ if (!Number.isFinite(hue)) hue = 154; + \\ return ((Math.round(hue) % 360) + 360) % 360; + \\ } + \\ function hsl(hue, saturation, lightness) { return 'hsl(' + clampHue(hue) + ' ' + saturation + '% ' + lightness + '%)'; } + \\ function applyAccent(value) { + \\ var hue = clampHue(value); + \\ document.documentElement.style.setProperty('--glass-a', hsl(hue, 72, 58)); + \\ document.documentElement.style.setProperty('--glass-b', hsl(hue + 76, 84, 72)); + \\ document.documentElement.style.setProperty('--glass-c', hsl(hue + 144, 78, 66)); + \\ document.documentElement.style.setProperty('--glass-d', hsl(hue + 214, 82, 68)); + \\ var slider = document.getElementById('accent-hue'); + \\ var output = document.getElementById('accent-value'); + \\ if (slider) slider.value = String(hue); + \\ if (output) output.textContent = String(hue) + 'deg'; + \\ } \\ function applyTheme(value) { \\ if (value === 'light' || value === 'dark') document.documentElement.dataset.theme = value; \\ else delete document.documentElement.dataset.theme; @@ -308,6 +341,8 @@ pub const script = \\ document.querySelectorAll('.theme-option').forEach(function(btn) { \\ btn.addEventListener('click', function() { writeTheme(btn.dataset.theme); applyTheme(btn.dataset.theme); }); \\ }); + \\ var accent = document.getElementById('accent-hue'); + \\ if (accent) accent.addEventListener('input', function() { writeAccent(accent.value); applyAccent(accent.value); }); \\ document.getElementById('settings').addEventListener('click', function() { sheet.classList.add('open'); }); \\ document.getElementById('system').addEventListener('click', function() { systemSheet.classList.add('open'); }); \\ document.getElementById('close-client').addEventListener('click', function() { sheet.classList.remove('open'); }); @@ -316,6 +351,7 @@ pub const script = \\ systemSheet.addEventListener('click', function(event) { if (event.target === systemSheet) systemSheet.classList.remove('open'); }); \\ document.addEventListener('keydown', function(event) { if (event.key === 'Escape') { sheet.classList.remove('open'); systemSheet.classList.remove('open'); } }); \\ applyTheme(readTheme()); + \\ applyAccent(readAccent()); \\ syncLinks(); \\})(); ; diff --git a/src/http/landing/mod.zig b/src/http/landing/mod.zig index f66c35e..2f427b5 100644 --- a/src/http/landing/mod.zig +++ b/src/http/landing/mod.zig @@ -140,6 +140,10 @@ fn render(allocator: std.mem.Allocator) ![]const u8 { \\ \\ \\ + \\
+ \\
+ \\ + \\
\\
open profiles with
\\
\\