cdnV2

git clone https://github.com/notamitgamer/cdnV2.git
· rebuilt hourlyOpen on GitHub
commit 4bcfcc2fa99ea0ef92e30b9a2b4a54259522a41d
parent 62ea0bb343510a8c5cd635bb27c7fb1f98fe3b76
Author: Amit Dutta <mail@amit.is-a.dev>
Date:   Wed, 30 Sep 2026 20:08:28 +0530

Merge pull request #26 from notamitgamer/ui/corporate-simple-frontend

WIP: Corporate-simple frontend redesign
Diffstat:
Mapp/main.py | 4----
Mapp/storage.py | 53-----------------------------------------------------
Mapp/templates/_navbar.html | 232++++++++++++++++++++++---------------------------------------------------------
Aapp/templates/_styles.html | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/templates/documentation.html | 38++++++++++++++++++--------------------
Mapp/templates/gh_sync_docs.html | 28+++++++++++++---------------
Mapp/templates/index.html | 195+++++++++++++++++++++++--------------------------------------------------------
Mapp/templates/url_shortener.html | 60++++++++++++++++++++++++++++++------------------------------
8 files changed, 240 insertions(+), 429 deletions(-)

diff --git a/app/main.py b/app/main.py @@ -27,7 +27,6 @@ from .storage import ( upload_temp_file, upload_folder_scoped, repo_stats, - get_recent_activity, search_files, write_batch_manifest, get_batch_manifest, @@ -984,9 +983,6 @@ async def serve(request: Request, path: str): "raw_base_url": RAW_BASE_URL, } - if not clean_path: - extra_ctx["recent_activity"] = await get_recent_activity() - ctx = await render_context(extra_ctx) return templates.TemplateResponse( diff --git a/app/storage.py b/app/storage.py @@ -224,59 +224,6 @@ async def repo_stats(): _set_cache(cache_key, result) return result -_UPLOAD_FILE_RE = re.compile(r"^Upload (.+?)(?: with huggingface_hub)?$") -_GH_SYNC_RE = re.compile(r"^gh-sync: update (.+)$") - -def _do_list_repo_commits(): - return list(api.list_repo_commits(repo_id=HF_REPO_ID, repo_type="dataset")) - -async def get_recent_activity(limit: int = 3): - """Recently changed top-level paths, newest first, deduped by path. - - Derived from commit titles (list_repo_commits doesn't return changed - file paths directly), so this is best-effort: commits whose title - doesn't match one of this app's own upload patterns are skipped rather - than guessed at. Cached briefly since it's one extra HF API call. - """ - cache_key = "recent_activity" - cached = _get_cache(cache_key) - if cached is not None: - return cached - - try: - commits = await asyncio.to_thread(_do_list_repo_commits) - except Exception: - return [] - - seen_paths = set() - result = [] - for commit in commits: - title = (commit.title or "").strip() - gh_match = _GH_SYNC_RE.match(title) - upload_match = _UPLOAD_FILE_RE.match(title) if not gh_match else None - if gh_match: - # already "owner/repo" - that whole pair is the unit, don't truncate it - top_level = gh_match.group(1).strip().strip("/") - elif upload_match: - raw_path = upload_match.group(1).strip().strip("/") - top_level = raw_path.split("/")[0] if raw_path else "" - else: - continue - if not top_level or _is_hidden_path(top_level): - continue - if top_level in seen_paths: - continue - seen_paths.add(top_level) - result.append({ - "path": top_level, - "iso_time": commit.created_at.isoformat() if commit.created_at else None, - }) - if len(result) >= limit: - break - - _set_cache(cache_key, result) - return result - async def search_files(query: str): q = query.strip().lower() if not q: diff --git a/app/templates/_navbar.html b/app/templates/_navbar.html @@ -1,184 +1,80 @@ +{% 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; } .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; -} + display: inline-flex; align-items: center; gap: 0.4rem; + padding: 0.4rem 0.65rem; border-radius: var(--ui-radius); + color: var(--ui-muted); font-size: 0.9rem; text-decoration: none; white-space: nowrap; +} +.navlinks a svg { flex-shrink: 0; } +.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; } +.nav-toggle { + display: none; align-items: center; justify-content: center; + width: 2.25rem; height: 2.25rem; padding: 0; + background: transparent; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); + color: var(--ui-text); cursor: pointer; +} +.nav-toggle:hover { background: var(--ui-surface); } +.nav-toggle .icon-close { display: none; } +.nav-toggle[aria-expanded="true"] .icon-open { display: none; } +.nav-toggle[aria-expanded="true"] .icon-close { display: block; } +@media (max-width: 720px) { + .navbar { flex-wrap: wrap; } + .nav-toggle { display: inline-flex; } + .navlinks { display: none; flex-basis: 100%; flex-direction: column; align-items: stretch; gap: 0.15rem; padding-top: 0.5rem; } + .navlinks.open { display: flex; } + .navlinks a { padding: 0.65rem 0.75rem; font-size: 1rem; } +} +.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> + <button type="button" class="nav-toggle" aria-label="Toggle menu" aria-expanded="false" aria-controls="primary-nav" onclick="var o=document.getElementById('primary-nav').classList.toggle('open');this.setAttribute('aria-expanded',o)"><svg class="icon-open" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg><svg class="icon-close" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg></button> + <nav class="navlinks" id="primary-nav" aria-label="Primary"> + <a href="/find" class="{{ 'active' if page == 'search' }}"{{ ' aria-current="page"'|safe if page == 'search' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg><span>Find</span></a> + <a href="/new" class="{{ 'active' if page == 'upload' }}"{{ ' aria-current="page"'|safe if page == 'upload' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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><span>Upload</span></a> + <a href="/shorten" class="{{ 'active' if page == 'shorten' }}"{{ ' aria-current="page"'|safe if page == 'shorten' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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><span>Shorten</span></a> + <a href="/history" class="{{ 'active' if page == 'history' }}"{{ ' aria-current="page"'|safe if page == 'history' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg><span>History</span></a> + <a href="/gh-sync" class="{{ 'active' if page == 'gh-sync' }}"{{ ' aria-current="page"'|safe if page == 'gh-sync' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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><span>Sync</span></a> + <a href="/documentation" class="{{ 'active' if page == 'documentation' }}"{{ ' aria-current="page"'|safe if page == 'documentation' }}><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><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><span>Docs</span></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,59 @@ +<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-accent-solid: #0b5fff; /* filled buttons/badges with white text */ + --ui-danger: #cf222e; + --ui-success: #116329; + --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-accent-solid: #2f6feb; + --ui-danger: #f85149; + --ui-success: #3fb950; + } +} +:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; } + +/* ---- Shared polish (loads after page CSS, so it wins at equal specificity) ---- */ +body { font-family: var(--ui-font); line-height: 1.55; -webkit-font-smoothing: antialiased; } +h1 { font-size: clamp(1.6rem, 3.2vw, 2.1rem) !important; font-weight: 600 !important; letter-spacing: -0.01em !important; line-height: 1.25; } +/* UI text in sans; monospace stays for paths, file names and code */ +input, button, textarea, select, .btn, .folder-option, .folder-picker-label, .file-pill, .file-ext-tag, footer, .history-tab { font-family: var(--ui-font) !important; } +/* Notices: neutral info banner instead of an accent bar */ +blockquote { border-left: 1px solid var(--ui-border) !important; background: var(--ui-surface); border-radius: var(--ui-radius); max-width: none !important; } +/* Inputs and buttons */ +.filter-input, .search-input, .url-input { font-size: 0.95rem; background: var(--ui-bg); } +.filter-input:focus, .search-input:focus, .url-input:focus { border-color: var(--ui-accent) !important; outline: 2px solid var(--ui-accent-bg); } +.btn { font-weight: 500 !important; } +.btn-primary { font-weight: 500 !important; } +/* Destination chips become a compact segmented control */ +.folder-option { border-radius: var(--ui-radius) !important; font-size: 0.85rem !important; font-weight: 500 !important; background: var(--ui-bg); } +.folder-option.active { background: var(--ui-accent-solid) !important; border-color: var(--ui-accent-solid) !important; color: #fff !important; } +.file-pill { border-radius: var(--ui-radius) !important; font-weight: 500 !important; } +/* Lists: quiet hover, tabular numbers for sizes */ +.list-item:hover { background: var(--ui-surface); } +.item-size, .file-pill { font-variant-numeric: tabular-nums; } +footer { color: var(--ui-muted); font-size: 0.85rem; } +@media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation-duration: 0.01ms !important; } } +</style> diff --git a/app/templates/documentation.html b/app/templates/documentation.html @@ -10,36 +10,34 @@ <link rel="icon" type="image/png" sizes="16x16" href="/static/icons/favicon-16x16.png"> <link rel="icon" type="image/svg+xml" href="/static/icons/logo.svg"> <link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png"> -<meta name="theme-color" content="#09090b"> -<meta name="color-scheme" content="dark"> -<link rel="preconnect" href="https://fonts.googleapis.com"> -<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> -<link href="https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@500;600;700&family=Work+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> +<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> +<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)"> +<meta name="color-scheme" content="light dark"> <style> - :root{--bg:#09090b;--surface:#121214;--surface-2:#1e1e22;--border:#27272a;--text:#f4f4f5;--muted:#a1a1aa;--accent:#818cf8;--get:#4ade80;--post:#818cf8;--err:#f87171;} + :root{--bg:var(--ui-bg);--surface:var(--ui-surface);--surface-2:var(--ui-surface);--border:var(--ui-border);--text:var(--ui-text);--muted:var(--ui-muted);--accent:var(--ui-accent);--get:var(--ui-success);--post:var(--ui-accent);--err:var(--ui-danger);} *{box-sizing:border-box;} - body{background:var(--bg);color:var(--text);font-family:'Work Sans',system-ui,sans-serif;margin:0;line-height:1.6;} + body{background:var(--bg);color:var(--text);font-family:var(--ui-font);margin:0;line-height:1.6;} .wrap{max-width:1000px;margin:0 auto;padding:48px 20px 96px;} - h1{font-family:'Zilla Slab',Georgia,serif;font-weight:600;font-size:1.9rem;margin-bottom:.2em;} - h2{font-size:1.15rem;margin:0 0 1rem;font-family:'JetBrains Mono',monospace;} + h1{font-family:var(--ui-font);font-weight:600;font-size:1.9rem;margin-bottom:.2em;} + h2{font-size:1.15rem;margin:0 0 1rem;font-family:var(--ui-mono);} h3{font-size:.95rem;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:1.1em 0 .4em;} p{color:var(--muted);margin:.4em 0;} - code{font-family:'JetBrains Mono',monospace;background:var(--surface-2);padding:.15em .4em;border-radius:4px;font-size:.85em;color:var(--text);word-break:break-word;overflow-wrap:anywhere;} - pre{font-family:'JetBrains Mono',monospace;background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:14px;overflow-x:auto;font-size:.82rem;margin:.5em 0;} + code{font-family:var(--ui-mono);background:var(--surface-2);padding:.15em .4em;border-radius:4px;font-size:.85em;color:var(--text);word-break:break-word;overflow-wrap:anywhere;} + pre{font-family:var(--ui-mono);background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:14px;overflow-x:auto;font-size:.82rem;margin:.5em 0;} a{color:var(--accent);} .lede{max-width:70ch;} - .toc{background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:1.1rem 1.3rem;margin:1.6rem 0 2.4rem;} + .toc{background:var(--surface);border:1px solid var(--border);border-radius:6px;padding:1.1rem 1.3rem;margin:1.6rem 0 2.4rem;} .toc h3{margin-top:0;} .toc ol{margin:0;padding-left:1.2em;color:var(--muted);columns:2;font-size:.92rem;} .toc a{color:var(--text);text-decoration:none;} .toc a:hover{color:var(--accent);} - .endpoint{border:1px solid var(--border);border-radius:10px;padding:1.4rem 1.5rem;margin-bottom:1.6rem;background:var(--surface);scroll-margin-top:20px;} + .endpoint{border:1px solid var(--border);border-radius:6px;padding:1.4rem 1.5rem;margin-bottom:1.6rem;background:var(--surface);scroll-margin-top:20px;} .route-row{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;margin-bottom:.6rem;} - .method{font-family:'JetBrains Mono',monospace;font-weight:700;font-size:.78rem;padding:.2rem .5rem;border-radius:5px;letter-spacing:.03em;} - .method.get{background:rgba(74,222,128,.12);color:var(--get);} - .method.post{background:rgba(129,140,248,.15);color:var(--post);} - .route-path{font-family:'JetBrains Mono',monospace;font-size:1rem;color:var(--text);} - .domain-tag{font-family:'JetBrains Mono',monospace;font-size:.72rem;color:var(--muted);background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:.15rem .4rem;} + .method{font-family:var(--ui-mono);font-weight:700;font-size:.78rem;padding:.2rem .5rem;border-radius:5px;letter-spacing:.03em;} + .method.get{background:color-mix(in srgb,var(--ui-success) 14%,transparent);color:var(--get);} + .method.post{background:var(--ui-accent-bg);color:var(--post);} + .route-path{font-family:var(--ui-mono);font-size:1rem;color:var(--text);} + .domain-tag{font-family:var(--ui-mono);font-size:.72rem;color:var(--muted);background:var(--surface-2);border:1px solid var(--border);border-radius:5px;padding:.15rem .4rem;} .endpoint > p:first-of-type{margin-top:0;} table{width:100%;border-collapse:collapse;margin:.5em 0;font-size:.88rem;} th,td{text-align:left;padding:.4em .6em;border-bottom:1px solid var(--border);vertical-align:top;} @@ -48,9 +46,9 @@ td.desc{color:var(--muted);} .err-list{list-style:none;padding:0;margin:.4em 0;} .err-list li{padding:.3em 0;font-size:.88rem;overflow:hidden;} - .err-code{font-family:'JetBrains Mono',monospace;color:var(--err);font-weight:600;float:left;width:3.2em;margin-right:.6em;} + .err-code{font-family:var(--ui-mono);color:var(--err);font-weight:600;float:left;width:3.2em;margin-right:.6em;} section{margin-top:2.6rem;} - section > h2 { font-family:'Zilla Slab',Georgia,serif; font-size:1.4rem; font-weight:600; color:var(--text); } + section > h2 { font-family:var(--ui-font); font-size:1.4rem; font-weight:600; color:var(--text); } .footnote{font-size:.82rem;color:var(--muted);margin-top:3rem;border-top:1px solid var(--border);padding-top:1.2rem;} footer{margin-top:4rem;padding-top:1.5rem;border-top:1px solid var(--border);font-size:.85rem;color:var(--muted);} </style> diff --git a/app/templates/gh_sync_docs.html b/app/templates/gh_sync_docs.html @@ -10,21 +10,19 @@ <link rel="icon" type="image/png" sizes="16x16" href="/static/icons/favicon-16x16.png"> <link rel="icon" type="image/svg+xml" href="/static/icons/logo.svg"> <link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png"> -<meta name="theme-color" content="#09090b"> -<meta name="color-scheme" content="dark"> +<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> +<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)"> +<meta name="color-scheme" content="light dark"> -<link rel="preconnect" href="https://fonts.googleapis.com"> -<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> -<link href="https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@500;600;700&family=Work+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> :root { - --bg: #09090b; - --surface: #121214; - --surface-2: #1e1e22; - --border: #27272a; - --text: #f4f4f5; - --muted: #a1a1aa; - --accent: #818cf8; + --bg: var(--ui-bg); + --surface: var(--ui-surface); + --surface-2: var(--ui-surface); + --border: var(--ui-border); + --text: var(--ui-text); + --muted: var(--ui-muted); + --accent: var(--ui-accent); } *, @@ -43,7 +41,7 @@ body { background: var(--bg); color: var(--text); - font-family: 'Work Sans', system-ui, sans-serif; + font-family: var(--ui-font); margin: 0; line-height: 1.6; } @@ -55,7 +53,7 @@ } h1 { - font-family: 'Zilla Slab', Georgia, 'Times New Roman', serif; + font-family: var(--ui-font); font-weight: 600; font-size: 1.9rem; margin-bottom: .2em; @@ -73,7 +71,7 @@ } code, pre { - font-family: 'JetBrains Mono', monospace; + font-family: var(--ui-mono); } code { diff --git a/app/templates/index.html b/app/templates/index.html @@ -13,8 +13,9 @@ <link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png"> <link rel="manifest" href="/static/manifest.json"> - <meta name="theme-color" content="#09090b"> - <meta name="color-scheme" content="dark"> + <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> + <meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)"> + <meta name="color-scheme" content="light dark"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-title" content="amit/cdn"> @@ -27,34 +28,28 @@ <script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.4/dist/turbo.es2017-esm.js"></script> - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@500;600;700&family=Work+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> - <style> :root { - --bg: #09090b; - --surface: #121214; - --surface-2: #1e1e22; - --surface-3: #27272a; - --text-main: #f4f4f5; - --text-dim: #b8b8c0; - - --accent-primary: #818cf8; - --accent-primary-hover: #a5b4fc; - --accent-secondary: #f97316; - --success: #10b981; - --danger: #ef4444; - --border: rgba(255, 255, 255, 0.08); - --border-hover: rgba(255, 255, 255, 0.15); - - --font-heading: 'Zilla Slab', Georgia, 'Times New Roman', serif; - --font-body: 'Work Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; - --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - - --radius-md: 8px; - --radius-lg: 12px; - --radius-xl: 16px; + /* Legacy names mapped onto the shared --ui- tokens (_styles.html) */ + --bg: var(--ui-bg); + --surface: var(--ui-surface); + --surface-2: var(--ui-surface); + --surface-3: var(--ui-border); + --text-main: var(--ui-text); + --text-dim: var(--ui-muted); + --accent-primary: var(--ui-accent); + --accent-primary-hover: var(--ui-accent); + --accent-secondary: var(--ui-accent-solid); + --success: var(--ui-success); + --danger: var(--ui-danger); + --border: var(--ui-border); + --border-hover: var(--ui-muted); + --font-heading: var(--ui-font); + --font-body: var(--ui-font); + --font-mono: var(--ui-mono); + --radius-md: 6px; + --radius-lg: 6px; + --radius-xl: 6px; } * { box-sizing: border-box; } @@ -100,7 +95,7 @@ font-family: var(--font-heading); font-size: clamp(2.2rem, 5vw, 3rem); letter-spacing: -0.02em; - color: #ffffff; + color: var(--text-main); font-weight: 600; margin: 0 0 1.25rem 0; line-height: 1.1; @@ -121,46 +116,6 @@ .site-notice { margin-top: 0.5rem; } - .recent-activity { - margin-bottom: 2.25rem; - border: 1px solid var(--border); - border-radius: var(--radius-md); - background: var(--surface); - overflow: hidden; - } - .recent-activity-heading { - display: flex; - align-items: center; - gap: 0.5rem; - color: var(--text-dim); - font-size: 0.9rem; - font-weight: 500; - padding: 0.7rem 1rem; - } - .recent-activity-list { - list-style: none; - margin: 0; - padding: 0 1rem 0.6rem; - } - .recent-activity-list li { - display: flex; - justify-content: space-between; - align-items: baseline; - gap: 1rem; - padding: 0.35rem 0; - border-top: 1px solid var(--border); - font-size: 0.9rem; - } - .recent-activity-list li:first-child { border-top: none; } - .recent-activity-list a { text-decoration: none; } - .recent-activity-list a:hover { text-decoration: underline; } - .recent-activity-time { - color: var(--text-dim); - font-size: 0.8rem; - white-space: nowrap; - flex-shrink: 0; - } - a { color: var(--accent-primary); text-decoration: none; transition: color 0.15s;} a:hover { color: var(--accent-primary-hover); text-decoration: underline; } @@ -232,7 +187,7 @@ flex-direction: column; gap: 0.25rem; z-index: 20; - box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4); + box-shadow: none; } .breadcrumb-menu.open { display: flex; } @@ -283,7 +238,7 @@ font-family: var(--font-mono); font-size: 0.9rem; transition: all 0.2s ease; - box-shadow: 0 2px 10px rgba(0,0,0,0.1) inset; + box-shadow: none; } .search-input { font-size: 1rem; padding: 1rem 2.5rem 1rem 1.25rem; } @@ -291,7 +246,7 @@ outline: none; background: var(--surface-2); border-color: var(--accent-primary); - box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.15); + box-shadow: none; } .filter-input::placeholder, .search-input::placeholder, .url-input::placeholder { color: var(--text-dim); @@ -340,7 +295,7 @@ border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; - box-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.2); + box-shadow: none; margin-bottom: 2rem; display: flex; flex-direction: column; @@ -359,8 +314,8 @@ } .list-group .filter-input:focus, .list-group .search-input:focus { - background: rgba(255, 255, 255, 0.02); - box-shadow: inset 3px 0 0 var(--accent-primary); + background: var(--ui-surface); + box-shadow: none; } .list-item { @@ -378,10 +333,10 @@ border-bottom: none; } .list-item:hover { - background: rgba(255, 255, 255, 0.03); + background: var(--ui-surface); } .list-item:active { - background: rgba(255, 255, 255, 0.05); + background: var(--ui-surface); } .item-name { @@ -449,7 +404,7 @@ } .download-icon:hover { color: var(--accent-primary); - background: rgba(129, 140, 248, 0.1); + background: var(--ui-accent-bg); } .download-icon:active { transform: scale(0.9); @@ -483,15 +438,15 @@ .btn:disabled { opacity: 0.6; cursor: not-allowed; } .btn-primary { - background: var(--accent-primary) !important; + background: var(--ui-accent-solid) !important; color: #ffffff !important; - border-color: var(--accent-primary) !important; + border-color: var(--ui-accent-solid) !important; font-weight: 600; transition: none !important; } .btn-primary:hover:not(:disabled), .btn-primary:focus:not(:disabled), .btn-primary:active:not(:disabled) { - background: var(--accent-primary) !important; - border-color: var(--accent-primary) !important; + background: var(--ui-accent-solid) !important; + border-color: var(--ui-accent-solid) !important; color: #ffffff !important; } .btn-primary svg { stroke: #ffffff !important; } @@ -512,7 +467,6 @@ border-color: var(--border-hover); } .icon-btn:hover:not(:disabled) svg { stroke: var(--accent-primary); } - .icon-btn:active:not(:disabled) { transform: scale(0.95); } .file-card { border: 1px solid var(--border); @@ -527,10 +481,6 @@ align-items: center; justify-content: center; background-color: var(--surface-2); - background-image: - linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px), - linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px); - background-size: 24px 24px; border-bottom: 1px solid var(--border); min-height: 200px; padding: 3rem 1rem; @@ -574,7 +524,7 @@ margin: 0 0 0.75rem 0; font-weight: 600; font-size: 1.5rem; - color: #ffffff; + color: var(--text-main); word-break: break-all; } .file-meta-row { @@ -588,8 +538,8 @@ font-size: 0.75rem; font-weight: 600; color: var(--accent-primary); - border: 1px solid rgba(129, 140, 248, 0.2); - background: rgba(129, 140, 248, 0.05); + border: 1px solid var(--ui-accent); + background: var(--ui-accent-bg); border-radius: 6px; padding: 0.35rem 0.85rem; letter-spacing: 0.5px; @@ -605,12 +555,12 @@ margin: 0 auto 2.5rem auto; font-size: 0.85rem; word-break: break-all; - background: rgba(0, 0, 0, 0.3); + background: var(--ui-surface); display: inline-block; padding: 0.75rem 1.25rem; border-radius: var(--radius-md); border: 1px solid var(--border); - box-shadow: inset 0 2px 4px rgba(0,0,0,0.2); + box-shadow: none; max-width: 90%; } .file-actions { @@ -663,7 +613,7 @@ cursor: pointer; color: var(--text-dim); margin-bottom: 1.5rem; - background: rgba(255, 255, 255, 0.02); + background: var(--ui-surface); transition: all 0.2s ease; display: flex; flex-direction: column; @@ -680,9 +630,9 @@ } #dropzone:hover, #dropzone.dragover { border-color: var(--accent-primary); - background: rgba(129, 140, 248, 0.08); + background: var(--ui-accent-bg); color: var(--accent-primary); - box-shadow: 0 0 0 4px rgba(129, 140, 248, 0.1); + box-shadow: none; } #dropzone:hover svg, #dropzone.dragover svg { color: var(--accent-primary); @@ -693,7 +643,7 @@ border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; - box-shadow: 0 4px 20px -2px rgba(0, 0, 0, 0.2); + box-shadow: none; } .file-row { @@ -707,8 +657,8 @@ .file-row:last-child { border-bottom: none; } - .file-row.done { background: rgba(16, 185, 129, 0.05); } - .file-row.error { background: rgba(239, 68, 68, 0.05); } + .file-row.done { background: var(--ui-surface); } + .file-row.error { background: var(--ui-surface); } .turbo-progress-bar { height: 3px; @@ -752,8 +702,8 @@ .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; - background: rgba(0, 0, 0, 0.8); - backdrop-filter: blur(4px); + background: rgba(0, 0, 0, 0.5); + display: flex; align-items: center; justify-content: center; z-index: 1000; } @@ -764,12 +714,12 @@ padding: 2rem; max-width: 440px; width: 90%; - box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); + box-shadow: none; } .modal h3 { font-family: var(--font-heading); margin-top: 0; margin-bottom: 1rem; - color: #fff; font-size: 1.4rem; + color: var(--text-main); font-size: 1.4rem; font-weight: 600; } .modal p { margin-bottom: 2rem; color: var(--text-dim); } @@ -825,7 +775,7 @@ } .history-tab:hover { color: var(--text-main); - background: rgba(255, 255, 255, 0.03); + background: var(--ui-surface); } .history-tab.active { color: var(--text-main); @@ -859,7 +809,7 @@ font-size: 1.4rem; font-weight: 600; margin: 0; - color: #ffffff; + color: var(--text-main); } .clear-history-btn { background: transparent; @@ -897,22 +847,6 @@ <a href="/gh-sync">Sync</a> at the top to see how to set it up. Project assets live here; files and paths may change over time, so use direct links with that in mind. </blockquote> - {% if recent_activity %} - <div class="recent-activity" id="recent-activity"> - <div class="recent-activity-heading"> - <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" 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> - <span>Recently modified</span> - </div> - <ul class="recent-activity-list"> - {% for entry in recent_activity %} - <li> - <a href="/{{ entry.path }}/">{{ entry.path }}/</a> - {% if entry.iso_time %}<time class="recent-activity-time" datetime="{{ entry.iso_time }}">{{ entry.iso_time }}</time>{% endif %} - </li> - {% endfor %} - </ul> - </div> - {% endif %} {% endif %} {% if page == 'listing' %} @@ -1037,6 +971,7 @@ </a> <button onclick="copyToClipboard('{{ cdn_base_url }}/{{ path }}', this)" class="btn">Copy Link</button> <button onclick="copyToClipboard('{{ raw_base_url }}/{{ path }}', this)" class="btn">Copy Raw Link</button> + <button onclick="copyToClipboard('{{ cdn_base_url }}/api/get/{{ path | urlencode }}', this)" class="btn" title="Anyone opening this link downloads the file directly">Copy Download Link</button> </div> </div> </div> @@ -1769,7 +1704,7 @@ const label = batchId ? 'this batch' : (path ? path.split('/').pop() : 'root'); document.getElementById('zip-modal-text').innerHTML = `Are you sure you want to download <strong>${label}</strong>?<br><br>` + - `This will package <strong style="color:#fff;">${data.file_count} file(s)</strong> totaling <strong style="color:#fff;">${data.size_str}</strong> into a .zip.`; + `This will package <strong style="color:var(--text-main);">${data.file_count} file(s)</strong> totaling <strong style="color:var(--text-main);">${data.size_str}</strong> into a .zip.`; document.getElementById('zip-modal-confirm').href = downloadUrl; zipModalOverlay.style.display = 'flex'; @@ -1957,24 +1892,6 @@ } </script> <script> - // --- Recently modified: convert timestamps to the visitor's own timezone. --- - (function () { - document.querySelectorAll('.recent-activity-time[datetime]').forEach(function (el) { - var d = new Date(el.getAttribute('datetime')); - if (isNaN(d.getTime())) return; - var now = new Date(); - var diffMs = now - d; - var diffMin = Math.round(diffMs / 60000); - var label; - if (diffMin < 1) label = 'just now'; - else if (diffMin < 60) label = diffMin + 'm ago'; - else if (diffMin < 60 * 24) label = Math.round(diffMin / 60) + 'h ago'; - else label = d.toLocaleString(undefined, { month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }); - el.textContent = label; - el.title = d.toLocaleString(); - }); - })(); - // --- Visited history: silently logs file/folder pages viewed on this browser, // shown on /history. localStorage only - there's no account system, so this is // per-browser, same limitation as ordinary browser history. diff --git a/app/templates/url_shortener.html b/app/templates/url_shortener.html @@ -11,32 +11,32 @@ <link rel="icon" type="image/svg+xml" href="/static/icons/logo.svg"> <link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png"> <link rel="manifest" href="/static/manifest.json"> - <meta name="theme-color" content="#09090b"> - <meta name="color-scheme" content="dark"> + <meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)"> +<meta name="theme-color" content="#0d1117" media="(prefers-color-scheme: dark)"> + <meta name="color-scheme" content="light dark"> <script type="module" src="https://cdn.jsdelivr.net/npm/@hotwired/turbo@8.0.4/dist/turbo.es2017-esm.js"></script> - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Zilla+Slab:wght@500;600;700&family=Work+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> :root { - --bg: #09090b; - --surface: #121214; - --surface-2: #1e1e22; - --surface-3: #27272a; - --text-main: #f4f4f5; - --text-dim: #b8b8c0; - --accent-primary: #818cf8; - --accent-primary-hover: #a5b4fc; - --success: #10b981; - --danger: #ef4444; - --border: rgba(255, 255, 255, 0.08); - --border-hover: rgba(255, 255, 255, 0.15); - --font-heading: 'Zilla Slab', Georgia, 'Times New Roman', serif; - --font-body: 'Work Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; - --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - --radius-md: 8px; - --radius-lg: 12px; - --radius-xl: 16px; + /* Legacy names mapped onto the shared --ui- tokens (_styles.html) */ + --bg: var(--ui-bg); + --surface: var(--ui-surface); + --surface-2: var(--ui-surface); + --surface-3: var(--ui-border); + --text-main: var(--ui-text); + --text-dim: var(--ui-muted); + --accent-primary: var(--ui-accent); + --accent-primary-hover: var(--ui-accent); + --accent-secondary: var(--ui-accent-solid); + --success: var(--ui-success); + --danger: var(--ui-danger); + --border: var(--ui-border); + --border-hover: var(--ui-muted); + --font-heading: var(--ui-font); + --font-body: var(--ui-font); + --font-mono: var(--ui-mono); + --radius-md: 6px; + --radius-lg: 6px; + --radius-xl: 6px; } * { -webkit-tap-highlight-color: transparent; } @@ -63,7 +63,7 @@ font-family: var(--font-heading); font-size: clamp(2.2rem, 5vw, 3rem); letter-spacing: -0.02em; - color: #ffffff; + color: var(--text-main); font-weight: 600; margin: 0 0 1.25rem 0; line-height: 1.1; @@ -104,7 +104,7 @@ outline: none; background: var(--surface-2); border-color: var(--accent-primary); - box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.15); + box-shadow:none; } .url-input::placeholder { color: var(--text-dim); } .input-clear-btn { @@ -145,8 +145,8 @@ .btn:hover:not(:disabled) { background: var(--surface-3); border-color: var(--border-hover); text-decoration: none; color: var(--text-main); } .btn:active:not(:disabled) { transform: scale(0.97); } .btn:disabled { opacity: 0.6; cursor: not-allowed; } - .btn-primary { background: var(--accent-primary) !important; color: #ffffff !important; border-color: var(--accent-primary) !important; font-weight: 600; transition: none !important; } - .btn-primary:hover:not(:disabled), .btn-primary:focus:not(:disabled), .btn-primary:active:not(:disabled) { background: var(--accent-primary) !important; border-color: var(--accent-primary) !important; color: #ffffff !important; } + .btn-primary { background: var(--ui-accent-solid) !important; color: #ffffff !important; border-color: var(--ui-accent-solid) !important; font-weight: 600; transition: none !important; } + .btn-primary:hover:not(:disabled), .btn-primary:focus:not(:disabled), .btn-primary:active:not(:disabled) { background: var(--ui-accent-solid) !important; border-color: var(--ui-accent-solid) !important; color: #ffffff !important; } .btn-primary svg { stroke: #ffffff !important; } .icon-btn { display: inline-flex; @@ -173,7 +173,7 @@ font-family: var(--font-heading); font-size: 1.2rem; margin: 0 0 1rem 0; - color: #fff; + color: var(--text-main); } .result-url { font-family: var(--font-mono); @@ -197,8 +197,8 @@ color: var(--danger); margin-top: 1rem; padding: 1rem 1.25rem; - border: 1px solid rgba(239, 68, 68, 0.5); - background: rgba(239, 68, 68, 0.1); + border: 1px solid var(--ui-danger); + background: color-mix(in srgb, var(--ui-danger) 10%, transparent); border-radius: var(--radius-md); } .info-text {