diff options
| author | Gab Virebent <gabriel1@virebent.art> | 2026-07-02 03:58:31 +0200 |
|---|---|---|
| committer | Gab Virebent <gabriel1@virebent.art> | 2026-07-02 03:58:31 +0200 |
| commit | 52eb46afad75d76c707ed11bbddddbcf5e121deb (patch) | |
| tree | 728a5590c028e16a8a824274b7657b235439fea2 | |
| parent | 4da18fe598f243c777d330ba9d50f1ecd4382b05 (diff) | |
| download | nymdrop-52eb46afad75d76c707ed11bbddddbcf5e121deb.tar.gz nymdrop-52eb46afad75d76c707ed11bbddddbcf5e121deb.tar.xz nymdrop-52eb46afad75d76c707ed11bbddddbcf5e121deb.zip | |
Add light/dark theme toggle, fix dark theme text contrast
Theme state persists via localStorage, applied pre-paint by theme-init.js
to avoid flash. All JS moved to external files (app.js, theme-init.js)
to keep script-src 'self' CSP intact, no inline scripts.
Dark theme footer/notice/tagline colors were too close to the background
(footer nearly matched the card border color) and hard to read; brightened
to readable grays while leaving the light theme and submit button untouched.
| -rw-r--r-- | static/app.js | 30 | ||||
| -rw-r--r-- | static/index.html | 10 | ||||
| -rw-r--r-- | static/style.css | 153 | ||||
| -rw-r--r-- | static/theme-init.js | 5 |
4 files changed, 161 insertions, 37 deletions
diff --git a/static/app.js b/static/app.js new file mode 100644 index 0000000..1168281 --- /dev/null +++ b/static/app.js @@ -0,0 +1,30 @@ +document.getElementById('file').addEventListener('change', function() { + const name = this.files.length ? this.files[0].name : ''; + document.getElementById('filename').textContent = name; +}); + +(function() { + var toggleBtn = document.getElementById('theme-toggle'); + + function isLight() { + return document.documentElement.getAttribute('data-theme') === 'light'; + } + + function updateIcon() { + // Shows the icon for the theme you'd switch TO. + toggleBtn.textContent = isLight() ? '\u{1F319}' : '☀️'; + } + + toggleBtn.addEventListener('click', function() { + if (isLight()) { + document.documentElement.removeAttribute('data-theme'); + localStorage.setItem('nymdrop-theme', 'dark'); + } else { + document.documentElement.setAttribute('data-theme', 'light'); + localStorage.setItem('nymdrop-theme', 'light'); + } + updateIcon(); + }); + + updateIcon(); +})(); diff --git a/static/index.html b/static/index.html index c957a01..33e5868 100644 --- a/static/index.html +++ b/static/index.html @@ -6,10 +6,13 @@ <meta name="referrer" content="no-referrer"> <title>NymDrop — Secure Submission</title> <link rel="stylesheet" href="/style.css"> + <script src="/theme-init.js"></script> </head> <body> <div class="card"> + <button id="theme-toggle" class="theme-toggle" type="button" aria-label="Toggle light/dark theme"></button> + <div class="logo"> <div class="logo-icon">⬡</div> <h1>NYMDROP</h1> @@ -51,11 +54,6 @@ </div> <div class="footer">NYMDROP · ZERO KNOWLEDGE · ZERO LOGS</div> <script src="/crypto.js"></script> -<script> - document.getElementById('file').addEventListener('change', function() { - const name = this.files.length ? this.files[0].name : ''; - document.getElementById('filename').textContent = name; - }); -</script> +<script src="/app.js"></script> </body> </html> diff --git a/static/style.css b/static/style.css index 3b077d7..d463876 100644 --- a/static/style.css +++ b/static/style.css @@ -1,8 +1,74 @@ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } +:root { + --bg: #0d1117; + --card-bg: #161b22; + --card-border: #21262d; + --card-shadow: rgba(0,255,160,0.04); + --text: #c9d1d9; + --heading: #e6edf3; + --tagline: #8b949e; + --label: #8b949e; + --field-bg: #0d1117; + --field-border: #30363d; + --accent-green: #00ffa0; + --accent-blue: #0080ff; + --accent-blue-text: #58a6ff; + --badge-green-bg: rgba(0,255,160,0.08); + --badge-green-border: rgba(0,255,160,0.2); + --badge-blue-bg: rgba(0,128,255,0.08); + --badge-blue-border: rgba(0,128,255,0.2); + --badge-gray-bg: rgba(255,255,255,0.04); + --badge-gray-text: #8b949e; + --badge-gray-border: #30363d; + --file-label-bg: #21262d; + --status-error: #f85149; + --divider: #21262d; + --notice: #8b949e; + --notice-span: #c9d1d9; + --footer: #7d8590; + --btn-text: #0d1117; + --toggle-bg: #21262d; + --toggle-border: #30363d; + --toggle-color: #8b949e; +} + +html[data-theme="light"] { + --bg: #f6f8fa; + --card-bg: #ffffff; + --card-border: #d0d7de; + --card-shadow: rgba(0,0,0,0.06); + --text: #24292f; + --heading: #1b1f24; + --tagline: #6e7781; + --label: #57606a; + --field-bg: #f6f8fa; + --field-border: #d0d7de; + --accent-green: #067d4f; + --accent-blue: #0969da; + --accent-blue-text: #0969da; + --badge-green-bg: rgba(6,125,79,0.08); + --badge-green-border: rgba(6,125,79,0.25); + --badge-blue-bg: rgba(9,105,218,0.08); + --badge-blue-border: rgba(9,105,218,0.25); + --badge-gray-bg: rgba(0,0,0,0.04); + --badge-gray-text: #57606a; + --badge-gray-border: #d0d7de; + --file-label-bg: #eaeef2; + --status-error: #cf222e; + --divider: #d0d7de; + --notice: #8c959f; + --notice-span: #57606a; + --footer: #afb8c1; + --btn-text: #ffffff; + --toggle-bg: #eaeef2; + --toggle-border: #d0d7de; + --toggle-color: #57606a; +} + body { - background: #0d1117; - color: #c9d1d9; + background: var(--bg); + color: var(--text); font-family: 'Courier New', Courier, monospace; min-height: 100vh; display: flex; @@ -10,48 +76,73 @@ body { align-items: center; justify-content: center; padding: 2rem 1rem; + transition: background-color 0.15s, color 0.15s; } .card { - background: #161b22; - border: 1px solid #21262d; + position: relative; + background: var(--card-bg); + border: 1px solid var(--card-border); border-radius: 8px; padding: 2.5rem 2rem; width: 100%; max-width: 580px; - box-shadow: 0 0 40px rgba(0,255,160,0.04); + box-shadow: 0 0 40px var(--card-shadow); + transition: background-color 0.15s, border-color 0.15s; } +.theme-toggle { + position: absolute; + top: 1rem; + right: 1rem; + width: 32px; + height: 32px; + background: var(--toggle-bg); + border: 1px solid var(--toggle-border); + border-radius: 6px; + color: var(--toggle-color); + font-size: 0.95rem; + line-height: 1; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: border-color 0.2s, color 0.2s; +} + +.theme-toggle:hover { border-color: var(--accent-blue-text); color: var(--accent-blue-text); } + .logo { display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.5rem; + padding-right: 2.5rem; } .logo-icon { width: 32px; height: 32px; - background: linear-gradient(135deg, #00ffa0, #0080ff); + background: linear-gradient(135deg, var(--accent-green), var(--accent-blue)); border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 1rem; - color: #0d1117; + color: var(--bg); font-weight: bold; } h1 { font-size: 1.4rem; font-weight: bold; - color: #e6edf3; + color: var(--heading); letter-spacing: 0.15em; } .tagline { font-size: 0.72rem; - color: #484f58; + color: var(--tagline); margin-bottom: 2rem; letter-spacing: 0.03em; } @@ -71,14 +162,14 @@ h1 { font-weight: bold; } -.badge-green { background: rgba(0,255,160,0.08); color: #00ffa0; border: 1px solid rgba(0,255,160,0.2); } -.badge-blue { background: rgba(0,128,255,0.08); color: #58a6ff; border: 1px solid rgba(0,128,255,0.2); } -.badge-gray { background: rgba(255,255,255,0.04); color: #8b949e; border: 1px solid #30363d; } +.badge-green { background: var(--badge-green-bg); color: var(--accent-green); border: 1px solid var(--badge-green-border); } +.badge-blue { background: var(--badge-blue-bg); color: var(--accent-blue-text); border: 1px solid var(--badge-blue-border); } +.badge-gray { background: var(--badge-gray-bg); color: var(--badge-gray-text); border: 1px solid var(--badge-gray-border); } label { display: block; font-size: 0.72rem; - color: #8b949e; + color: var(--label); margin-bottom: 0.4rem; text-transform: uppercase; letter-spacing: 0.08em; @@ -87,52 +178,52 @@ label { textarea { width: 100%; height: 160px; - background: #0d1117; - border: 1px solid #30363d; + background: var(--field-bg); + border: 1px solid var(--field-border); border-radius: 6px; - color: #c9d1d9; + color: var(--text); font-family: 'Courier New', Courier, monospace; font-size: 0.88rem; padding: 0.9rem; resize: vertical; margin-bottom: 1.4rem; - transition: border-color 0.2s; + transition: border-color 0.2s, background-color 0.15s, color 0.15s; outline: none; } -textarea:focus { border-color: #00ffa0; box-shadow: 0 0 0 2px rgba(0,255,160,0.08); } +textarea:focus { border-color: var(--accent-green); box-shadow: 0 0 0 2px var(--badge-green-bg); } .file-section { margin-bottom: 1.8rem; } .file-label { display: inline-block; - background: #21262d; - border: 1px solid #30363d; + background: var(--file-label-bg); + border: 1px solid var(--field-border); border-radius: 6px; - color: #8b949e; + color: var(--label); font-size: 0.78rem; padding: 0.5rem 1rem; cursor: pointer; transition: border-color 0.2s, color 0.2s; } -.file-label:hover { border-color: #58a6ff; color: #58a6ff; } +.file-label:hover { border-color: var(--accent-blue-text); color: var(--accent-blue-text); } #file { display: none; } #filename { font-size: 0.72rem; - color: #58a6ff; + color: var(--accent-blue-text); margin-left: 0.6rem; vertical-align: middle; } .submit-btn { width: 100%; - background: linear-gradient(135deg, #00ffa0 0%, #0080ff 100%); + background: linear-gradient(135deg, var(--accent-green) 0%, var(--accent-blue) 100%); border: none; border-radius: 6px; - color: #0d1117; + color: var(--btn-text); font-family: 'Courier New', Courier, monospace; font-size: 0.9rem; font-weight: bold; @@ -151,29 +242,29 @@ textarea:focus { border-color: #00ffa0; box-shadow: 0 0 0 2px rgba(0,255,160,0.0 font-size: 0.78rem; min-height: 1.2rem; text-align: center; - color: #00ffa0; + color: var(--accent-green); } -#status.error { color: #f85149; } +#status.error { color: var(--status-error); } .divider { border: none; - border-top: 1px solid #21262d; + border-top: 1px solid var(--divider); margin: 2rem 0 1.2rem; } .notice { font-size: 0.68rem; - color: #3d444d; + color: var(--notice); line-height: 1.7; } -.notice span { color: #484f58; } +.notice span { color: var(--notice-span); } .footer { margin-top: 1.5rem; font-size: 0.62rem; - color: #21262d; + color: var(--footer); text-align: center; letter-spacing: 0.05em; } diff --git a/static/theme-init.js b/static/theme-init.js new file mode 100644 index 0000000..95b9a95 --- /dev/null +++ b/static/theme-init.js @@ -0,0 +1,5 @@ +(function() { + if (localStorage.getItem('nymdrop-theme') === 'light') { + document.documentElement.setAttribute('data-theme', 'light'); + } +})(); |
