Dark mode: portal (tokens/toggle) + dsh chat (vars + toggle)
This commit is contained in:
@@ -6,8 +6,16 @@
|
|||||||
<title>DeepSeek Harness — {{ DSH_USER }}</title>
|
<title>DeepSeek Harness — {{ DSH_USER }}</title>
|
||||||
<link rel="stylesheet" href="/static/app.css">
|
<link rel="stylesheet" href="/static/app.css">
|
||||||
<style>
|
<style>
|
||||||
|
:root {
|
||||||
|
--canvas-soft: #f7f7f7; --surface: #ffffff; --surface-2: #f2f2f1; --hairline: #e6e6e6;
|
||||||
|
--ink: #111111; --ink-secondary: #333333; --ink-muted: #666666; --ink-faint: #999999; --primary: #0075de;
|
||||||
|
}
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--canvas-soft: #141518; --surface: #1c1e22; --surface-2: #24262c; --hairline: #33363d;
|
||||||
|
--ink: #f5f6f7; --ink-secondary: #dcdee2; --ink-muted: #a9adb6; --ink-faint: #727680; --primary: #3d8be0;
|
||||||
|
}
|
||||||
html, body { height: 100%; margin: 0; }
|
html, body { height: 100%; margin: 0; }
|
||||||
body { display: flex; flex-direction: column; }
|
body { display: flex; flex-direction: column; background: var(--surface, #fff); color: var(--ink, #111); }
|
||||||
header.top { flex: none; }
|
header.top { flex: none; }
|
||||||
.app { display: flex; flex: 1; min-height: 0; }
|
.app { display: flex; flex: 1; min-height: 0; }
|
||||||
#sidebar {
|
#sidebar {
|
||||||
@@ -15,7 +23,7 @@
|
|||||||
display: flex; flex-direction: column; background: var(--canvas-soft, #f7f7f7);
|
display: flex; flex-direction: column; background: var(--canvas-soft, #f7f7f7);
|
||||||
}
|
}
|
||||||
#sidebar h2 { font: 600 12px/1.3 var(--font-family, sans-serif); color: var(--ink-faint, #999); margin: 12px 12px 6px; }
|
#sidebar h2 { font: 600 12px/1.3 var(--font-family, sans-serif); color: var(--ink-faint, #999); margin: 12px 12px 6px; }
|
||||||
#newBtn, #dlBtn { margin: 4px 12px; padding: 7px 10px; border: 1px solid #ddd; border-radius: 8px; background: #fff; cursor: pointer; text-align: left; }
|
#newBtn, #dlBtn { margin: 4px 12px; padding: 7px 10px; border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px; background: #fff; cursor: pointer; text-align: left; }
|
||||||
#sessions { list-style: none; margin: 0; padding: 0 8px; overflow: auto; flex: 1; }
|
#sessions { list-style: none; margin: 0; padding: 0 8px; overflow: auto; flex: 1; }
|
||||||
#sessions li {
|
#sessions li {
|
||||||
display: flex; align-items: center; gap: 6px; padding: 7px 8px; margin: 2px 0;
|
display: flex; align-items: center; gap: 6px; padding: 7px 8px; margin: 2px 0;
|
||||||
@@ -30,11 +38,11 @@
|
|||||||
.bubble { position: relative; white-space: pre-wrap; }
|
.bubble { position: relative; white-space: pre-wrap; }
|
||||||
.bubble .copy {
|
.bubble .copy {
|
||||||
position: absolute; top: 4px; right: 4px; display: none;
|
position: absolute; top: 4px; right: 4px; display: none;
|
||||||
font-size: 11px; padding: 2px 6px; border: 1px solid #ddd; border-radius: 6px; background: #fff; cursor: pointer; color: #555;
|
font-size: 11px; padding: 2px 6px; border: 1px solid var(--hairline, #e6e6e6); border-radius: 6px; background: #fff; cursor: pointer; color: #555;
|
||||||
}
|
}
|
||||||
.msg:hover .bubble .copy { display: block; }
|
.msg:hover .bubble .copy { display: block; }
|
||||||
.modelrow { display: flex; gap: 8px; align-items: center; }
|
.modelrow { display: flex; gap: 8px; align-items: center; }
|
||||||
.modelrow select { border: 1px solid #ddd; border-radius: 8px; padding: 6px 8px; font-size: 13px; }
|
.modelrow select { border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px; padding: 6px 8px; font-size: 13px; }
|
||||||
|
|
||||||
.modelrow label { font-size: 12px; color: #777; }
|
.modelrow label { font-size: 12px; color: #777; }
|
||||||
|
|
||||||
@@ -42,7 +50,7 @@
|
|||||||
.composer { display: flex; flex-direction: column; gap: 8px; padding: 8px 12px; }
|
.composer { display: flex; flex-direction: column; gap: 8px; padding: 8px 12px; }
|
||||||
#input {
|
#input {
|
||||||
width: 100%; min-height: 2.9em; padding: 9px 11px; box-sizing: border-box;
|
width: 100%; min-height: 2.9em; padding: 9px 11px; box-sizing: border-box;
|
||||||
border: 1px solid #ddd; border-radius: 8px;
|
border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px;
|
||||||
font: 15px/1.4 var(--font-family, sans-serif); resize: vertical;
|
font: 15px/1.4 var(--font-family, sans-serif); resize: vertical;
|
||||||
}
|
}
|
||||||
.send-row { display: flex; justify-content: flex-end; }
|
.send-row { display: flex; justify-content: flex-end; }
|
||||||
@@ -56,10 +64,10 @@
|
|||||||
#toolsBody { padding: 0 12px 10px; }
|
#toolsBody { padding: 0 12px 10px; }
|
||||||
#toolsBody.hidden { display: none; }
|
#toolsBody.hidden { display: none; }
|
||||||
.tools-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
|
.tools-row { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
|
||||||
.tools-row input[type=text], .tools-row input[type=file] { flex: 2 1 170px; border: 1px solid #ddd; border-radius: 8px; padding: 6px 10px; font-size: 13px; }
|
.tools-row input[type=text], .tools-row input[type=file] { flex: 2 1 170px; border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px; padding: 6px 10px; font-size: 13px; }
|
||||||
.tools-row button { flex: 0 0 auto; border: 1px solid #ddd; border-radius: 8px; padding: 6px 10px; cursor: pointer; background: #fff; }
|
.tools-row button { flex: 0 0 auto; border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px; padding: 6px 10px; cursor: pointer; background: #fff; }
|
||||||
.modelrow { display: flex; gap: 8px; align-items: center; }
|
.modelrow { display: flex; gap: 8px; align-items: center; }
|
||||||
.modelrow select { border: 1px solid #ddd; border-radius: 8px; padding: 5px 8px; font-size: 13px; }
|
.modelrow select { border: 1px solid var(--hairline, #e6e6e6); border-radius: 8px; padding: 5px 8px; font-size: 13px; }
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
#menuBtn { display: inline-flex !important; }
|
#menuBtn { display: inline-flex !important; }
|
||||||
#sidebar {
|
#sidebar {
|
||||||
@@ -79,7 +87,8 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header class="top" style="display:flex;align-items:center;gap:8px;padding:10px 14px">
|
<header class="top" style="display:flex;align-items:center;gap:8px;padding:10px 14px">
|
||||||
<button id="menuBtn" type="button" aria-label="Conversations" title="Conversations" style="display:none;align-items:center;justify-content:center;background:none;border:1px solid #ddd;border-radius:8px;padding:4px 9px;font-size:17px;cursor:pointer;line-height:1">☰</button>
|
<button id="menuBtn" type="button" aria-label="Conversations" title="Conversations" style="display:none;align-items:center;justify-content:center;background:none;border:1px solid var(--hairline, #e6e6e6);border-radius:8px;padding:4px 9px;font-size:17px;cursor:pointer;line-height:1">☰</button>
|
||||||
|
<button id="themeBtn" type="button" title="Toggle dark mode" style="background:none;border:1px solid var(--hairline, #e6e6e6);border-radius:8px;padding:4px 8px;font-size:16px;cursor:pointer;color:var(--ink, #111)">🌙</button>
|
||||||
<div class="logo">DeepSeek Harness</div>
|
<div class="logo">DeepSeek Harness</div>
|
||||||
<div class="who" style="margin-left:auto">{{ DSH_SLOT }} · <span class="model">{{ DSH_MODEL }}</span></div>
|
<div class="who" style="margin-left:auto">{{ DSH_SLOT }} · <span class="model">{{ DSH_MODEL }}</span></div>
|
||||||
</header>
|
</header>
|
||||||
@@ -301,6 +310,23 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
fetchModels(); loadSessions();
|
fetchModels(); loadSessions();
|
||||||
|
|
||||||
|
// dark mode toggle (dsh standalone page)
|
||||||
|
(function () {
|
||||||
|
var root = document.documentElement;
|
||||||
|
var saved = null; try { saved = localStorage.getItem('dshTheme'); } catch(_) {}
|
||||||
|
if (saved === 'dark' || (!saved && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) root.setAttribute('data-theme', 'dark');
|
||||||
|
var b = document.getElementById('themeBtn');
|
||||||
|
if (b) {
|
||||||
|
function sync(){ b.textContent = root.getAttribute('data-theme') === 'dark' ? '☀️' : '🌙'; }
|
||||||
|
b.addEventListener('click', function () {
|
||||||
|
if (root.getAttribute('data-theme') === 'dark') { root.removeAttribute('data-theme'); try{localStorage.setItem('dshTheme','light');}catch(_){} }
|
||||||
|
else { root.setAttribute('data-theme','dark'); try{localStorage.setItem('dshTheme','dark');}catch(_){} }
|
||||||
|
sync();
|
||||||
|
});
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -71,7 +71,7 @@ a:hover { text-decoration: underline; }
|
|||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
font: var(--type-body-sm);
|
font: var(--type-body-sm);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
border: 1px solid rgb(221, 221, 221);
|
border: 1px solid var(--hairline);
|
||||||
border-radius: var(--rounded-xs);
|
border-radius: var(--rounded-xs);
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
}
|
}
|
||||||
@@ -340,3 +340,8 @@ button.button, input[type="submit"].button { font-family: inherit; }
|
|||||||
.page { padding: var(--space-lg) var(--space-md); }
|
.page { padding: var(--space-lg) var(--space-md); }
|
||||||
.greeting { font: var(--type-heading-2); }
|
.greeting { font: var(--type-heading-2); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- Dark-mode tweaks (hardcoded colours that need a dark variant) ---------- */
|
||||||
|
[data-theme="dark"] .form-error { background: #3a2424; color: #ffb4ab; border-color: #7a4e4c; }
|
||||||
|
[data-theme="dark"] .tool-icon { color: #1c1e22; }
|
||||||
|
[data-theme="dark"] .category-pill { background: var(--surface-2); }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
/* --- Surface --- */
|
/* --- Surface --- */
|
||||||
--canvas-soft: #f6f5f4;
|
--canvas-soft: #f6f5f4;
|
||||||
--surface: #ffffff;
|
--surface: #ffffff;
|
||||||
|
--surface-2: #f2f2f1;
|
||||||
--hairline: #e6e6e6;
|
--hairline: #e6e6e6;
|
||||||
|
|
||||||
/* --- Text --- */
|
/* --- Text --- */
|
||||||
@@ -86,5 +87,23 @@
|
|||||||
--rounded-full: 9999px;
|
--rounded-full: 9999px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dark mode — flip the semantic tokens only (components use var(--…)). */
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--canvas-soft: #141518;
|
||||||
|
--surface: #1c1e22;
|
||||||
|
--surface-2: #24262c;
|
||||||
|
--hairline: #33363d;
|
||||||
|
--ink: #f5f6f7;
|
||||||
|
--ink-secondary: #dcdee2;
|
||||||
|
--ink-muted: #a9adb6;
|
||||||
|
--ink-faint: #727680;
|
||||||
|
--primary: #3d8be0;
|
||||||
|
--primary-active: #5d9ff0;
|
||||||
|
--on-primary: #ffffff;
|
||||||
|
--secondary: #10142a;
|
||||||
|
--shadow-level-1: rgba(0, 0, 0, 0.45) 0 1px 3px;
|
||||||
|
--shadow-level-2: rgba(0, 0, 0, 0.55) 0 5px 22px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Numerals: enable OpenType lnum */
|
/* Numerals: enable OpenType lnum */
|
||||||
html { font-feature-settings: "lnum" 1; }
|
html { font-feature-settings: "lnum" 1; }
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
<span>{{ user.full_name }}</span>
|
<span>{{ user.full_name }}</span>
|
||||||
</div>
|
</div>
|
||||||
<a href="/account/password" class="button-utility" title="Change password">Password</a>
|
<a href="/account/password" class="button-utility" title="Change password">Password</a>
|
||||||
|
<button type="button" id="themeToggle" class="button-utility" title="Toggle dark mode" aria-label="Toggle dark mode">🌙</button>
|
||||||
<a href="/logout" class="button-utility">Sign out</a>
|
<a href="/logout" class="button-utility">Sign out</a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -32,5 +33,25 @@
|
|||||||
<main>
|
<main>
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var root = document.documentElement;
|
||||||
|
var saved = null;
|
||||||
|
try { saved = localStorage.getItem('fhlTheme'); } catch (_) {}
|
||||||
|
var dark = saved === 'dark' || (!saved && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||||
|
if (dark) root.setAttribute('data-theme', 'dark');
|
||||||
|
function sync() {
|
||||||
|
var b = document.getElementById('themeToggle');
|
||||||
|
if (b) b.textContent = root.getAttribute('data-theme') === 'dark' ? '☀️' : '🌙';
|
||||||
|
}
|
||||||
|
var t = document.getElementById('themeToggle');
|
||||||
|
if (t) t.addEventListener('click', function () {
|
||||||
|
if (root.getAttribute('data-theme') === 'dark') { root.removeAttribute('data-theme'); try { localStorage.setItem('fhlTheme','light'); } catch(_){} }
|
||||||
|
else { root.setAttribute('data-theme','dark'); try { localStorage.setItem('fhlTheme','dark'); } catch(_){} }
|
||||||
|
sync();
|
||||||
|
});
|
||||||
|
sync();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user