cdnV2

git clone https://github.com/notamitgamer/cdnV2.git
· rebuilt hourlyOpen on GitHub
commit 3206cafb941f4342674d1abc9d7292e504e84a02
parent 5b61476518e2efbc784ffe516447e9c9f9b88a5f
Author: notamitgamer-bot <noreply@github.com>
Date:   Wed, 30 Sep 2026 09:34:04 +0000

ui: shared light/dark tokens and plain text navbar

- add templates/_styles.html (--ui-* tokens, prefers-color-scheme dark)
- rewrite _navbar.html: system fonts, text links, no gradients/shadows
- included via _navbar.html so every page gets the tokens (static route only serves manifest/sw, so a partial is used instead of style.css)

Diffstat:
Mapp/templates/_navbar.html | 210++++++++++++++++---------------------------------------------------------------
Aapp/templates/_styles.html | 35+++++++++++++++++++++++++++++++++++
2 files changed, 78 insertions(+), 167 deletions(-)

diff --git a/app/templates/_navbar.html b/app/templates/_navbar.html @@ -1,184 +1,60 @@ +{% include "_styles.html" %} <style> -/* Shared navbar - single source of truth, included via this partial on every - page. Self-contained with its own hardcoded values rather than each page's local theme variables, so it looks and behaves - identically everywhere regardless of what a given page's own :root defines. */ +/* Navbar + breadcrumb. Uses the shared --ui- tokens from _styles.html. */ .navbar-wrapper { - position: sticky; - top: 0; - z-index: 100; - background: #09090b; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); - margin-bottom: 2.75rem; - box-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.2); + position: sticky; top: 0; z-index: 100; + background: var(--ui-bg); + border-bottom: 1px solid var(--ui-border); + margin-bottom: 1.5rem; + font-family: var(--ui-font); } .navbar { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1.25rem 5%; - max-width: 1000px; - margin: 0 auto; -} -.wordmark { - font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - font-weight: 500; - font-size: 1.1rem; - color: #f4f4f5 !important; - text-decoration: none !important; - letter-spacing: -0.01em; - transition: opacity 0.2s; -} -.wordmark:hover { opacity: 0.8; } -.wordmark-slash { color: #818cf8; } -.navlinks { - display: flex; - align-items: center; - gap: 0.6rem; + display: flex; align-items: center; justify-content: space-between; gap: 1rem; + max-width: var(--ui-width); margin: 0 auto; padding: 0.75rem 1rem; } +.wordmark { font-weight: 600; font-size: 1rem; color: var(--ui-text) !important; text-decoration: none !important; white-space: nowrap; } +.navlinks { display: flex; align-items: center; gap: 0.25rem; overflow-x: auto; } .navlinks a { - display: flex; - align-items: center; - justify-content: center; - width: 2.1rem; - height: 2.1rem; - color: #b8b8c0; - border-radius: 8px; - transition: all 0.2s ease; - padding: 0; -} -.navlinks a:hover { - color: #f4f4f5; - background: rgba(255, 255, 255, 0.05); -} -.navlinks a.active { - color: #818cf8; - background: rgba(129, 140, 248, 0.12); -} -.breadcrumb-container { - max-width: 1000px; - margin: 0 auto; - padding: 0 5% 1rem 5%; - background: #09090b; + padding: 0.4rem 0.7rem; border-radius: var(--ui-radius); + color: var(--ui-muted); font-size: 0.9rem; text-decoration: none; white-space: nowrap; } +.navlinks a:hover { color: var(--ui-text); background: var(--ui-surface); } +.navlinks a.active { color: var(--ui-accent); background: var(--ui-accent-bg); font-weight: 500; } +.breadcrumb-container { max-width: var(--ui-width); margin: 0 auto; padding: 0 1rem 0.75rem; } .breadcrumb { - display: flex; - align-items: center; - gap: 0.5rem; - flex-wrap: wrap; - color: #b8b8c0; - font-weight: 500; - font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - font-size: 0.85rem; -} -.breadcrumb a { - color: #f4f4f5; - text-decoration: none; - padding: 0.2rem 0.4rem; - margin: -0.2rem -0.4rem; - border-radius: 4px; - transition: background 0.15s, color 0.15s; -} -.breadcrumb a:hover { - color: #818cf8; - background: #1e1e22; - text-decoration: none; -} -.breadcrumb-collapsed { - position: relative; - display: inline-flex; -} -.breadcrumb-ellipsis { - background: #121214; - border: 1px solid rgba(255, 255, 255, 0.08); - color: #b8b8c0; - border-radius: 6px; - padding: 0.25rem 0.75rem; - cursor: pointer; - font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - font-size: 0.9rem; - line-height: 1.4; - transition: all 0.2s; -} -.breadcrumb-ellipsis:hover { - color: #f4f4f5; - border-color: rgba(255, 255, 255, 0.15); - background: #1e1e22; -} + display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; + color: var(--ui-muted); font-family: var(--ui-mono); font-size: 0.85rem; +} +.breadcrumb a { color: var(--ui-accent); text-decoration: none; } +.breadcrumb a:hover { text-decoration: underline; } +.breadcrumb-collapsed { position: relative; display: inline-flex; } +.breadcrumb-ellipsis, .copy-path-btn { + background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: var(--ui-radius); + color: var(--ui-muted); cursor: pointer; font: inherit; line-height: 1.4; +} +.breadcrumb-ellipsis { padding: 0.1rem 0.6rem; } +.copy-path-btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.3rem; margin-left: 0.4rem; } +.breadcrumb-ellipsis:hover, .copy-path-btn:hover { color: var(--ui-text); border-color: var(--ui-muted); } .breadcrumb-menu { - display: none; - position: absolute; - top: calc(100% + 8px); - left: 0; - min-width: 180px; - max-width: 70vw; - max-height: 260px; - overflow-y: auto; - background: #121214; - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 8px; - padding: 0.5rem; - flex-direction: column; - gap: 0.25rem; - z-index: 20; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); + display: none; position: absolute; top: calc(100% + 6px); left: 0; + min-width: 180px; max-width: 70vw; max-height: 260px; overflow-y: auto; + flex-direction: column; gap: 0.15rem; padding: 0.35rem; z-index: 20; + background: var(--ui-bg); border: 1px solid var(--ui-border); border-radius: var(--ui-radius); } .breadcrumb-menu.open { display: flex; } -.breadcrumb-menu a { - padding: 0.75rem 1rem; - border-radius: 6px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin: 0; -} -.copy-path-btn { - background: #121214; - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 6px; - color: #b8b8c0; - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - padding: 0.4rem; - margin-left: 0.5rem; - transition: all 0.2s; -} -.copy-path-btn:hover { - color: #f4f4f5; - border-color: rgba(255, 255, 255, 0.15); - background: #1e1e22; -} -.copy-path-btn:active { - transform: scale(0.95); -} -@media (max-width: 480px) { - .navbar { padding: 1rem 1.25rem; } - .navlinks { gap: 0.25rem; } -} +.breadcrumb-menu a { padding: 0.5rem 0.75rem; border-radius: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.breadcrumb-menu a:hover { background: var(--ui-surface); text-decoration: none; } </style> <div class="navbar-wrapper"> <header class="navbar"> - <a href="/" class="wordmark">amit<span class="wordmark-slash">/</span>cdn</a> - <nav class="navlinks"> - <a href="/find" class="{{ 'active' if page == 'search' }}" title="Find" aria-label="Find"{{ ' aria-current="page"'|safe if page == 'search' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg> - </a> - <a href="/new" class="{{ 'active' if page == 'upload' }}" title="New / Upload" aria-label="New / Upload"{{ ' aria-current="page"'|safe if page == 'upload' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> - </a> - <a href="/gh-sync" class="{{ 'active' if page == 'gh-sync' }}" title="GitHub Actions Sync" aria-label="GitHub Actions Sync"{{ ' aria-current="page"'|safe if page == 'gh-sync' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg> - </a> - <a href="/documentation" class="{{ 'active' if page == 'documentation' }}" title="Documentation" aria-label="Documentation"{{ ' aria-current="page"'|safe if page == 'documentation' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg> - </a> - <a href="/history" class="{{ 'active' if page == 'history' }}" title="History" aria-label="History"{{ ' aria-current="page"'|safe if page == 'history' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg> - </a> - <a href="/shorten" class="{{ 'active' if page == 'shorten' }}" title="URL Shortener" aria-label="URL Shortener"{{ ' aria-current="page"'|safe if page == 'shorten' }}> - <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg> - </a> + <a href="/" class="wordmark">amit/cdn</a> + <nav class="navlinks" aria-label="Primary"> + <a href="/find" class="{{ 'active' if page == 'search' }}"{{ ' aria-current="page"'|safe if page == 'search' }}>Find</a> + <a href="/new" class="{{ 'active' if page == 'upload' }}"{{ ' aria-current="page"'|safe if page == 'upload' }}>Upload</a> + <a href="/gh-sync" class="{{ 'active' if page == 'gh-sync' }}"{{ ' aria-current="page"'|safe if page == 'gh-sync' }}>Sync</a> + <a href="/documentation" class="{{ 'active' if page == 'documentation' }}"{{ ' aria-current="page"'|safe if page == 'documentation' }}>Docs</a> + <a href="/history" class="{{ 'active' if page == 'history' }}"{{ ' aria-current="page"'|safe if page == 'history' }}>History</a> + <a href="/shorten" class="{{ 'active' if page == 'shorten' }}"{{ ' aria-current="page"'|safe if page == 'shorten' }}>Shorten</a> </nav> </header> {% if not (page == 'listing' and not path) %} diff --git a/app/templates/_styles.html b/app/templates/_styles.html @@ -0,0 +1,35 @@ +<style> +/* Shared design tokens (light by default, dark via prefers-color-scheme). + Prefixed --ui- so they never collide with a page's own legacy variables + while pages are being migrated. Included once, via _navbar.html. */ +:root { + color-scheme: light dark; + --ui-bg: #ffffff; + --ui-surface: #f6f8fa; + --ui-border: #d0d7de; + --ui-text: #1f2328; + --ui-muted: #59636e; + --ui-accent: #0b5fff; + --ui-accent-bg: #eaf1ff; + --ui-danger: #cf222e; + --ui-success: #1a7f37; + --ui-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + --ui-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + --ui-radius: 6px; + --ui-width: 960px; +} +@media (prefers-color-scheme: dark) { + :root { + --ui-bg: #0d1117; + --ui-surface: #161b22; + --ui-border: #30363d; + --ui-text: #e6edf3; + --ui-muted: #9198a1; + --ui-accent: #4c8dff; + --ui-accent-bg: #12233f; + --ui-danger: #f85149; + --ui-success: #3fb950; + } +} +:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; } +</style>