v3 used the green wash #eaf3ea for --surface-primary, the page background, which read as too green. Replaced with the palette read from the DEPLOYED CSS of the dashboard, portal and panel (identical across all three): --surface-primary #eaf3ea -> #faf8f5 (cream, page background) --surface-tertiary green -> #f4f2ec (warm chip) --surface-hover green -> #f0ede6 (warm hover) --surface-composer-hover -> #f0ede6 --border-light #cde0cb -> #e4e0d8 (warm neutral border) --presentation #eaf3ea -> #faf8f5 (composer band) --link #4a7a4a -> #4e7a4d (deeper green, 4.70:1 on cream) Accents are unchanged (green-deep #5b8c5a, green-mid #6ba86b) — they are the earthy greens the co-op design system already uses. Dark mode is untouched. Also fixed the two hard-coded washes: the #loading-container flash and the bare html/body background, plus custom2.js COOP_BG.light, which was still painting the browser/PWA chrome #eaf3ea while the manifest said cream.
96 lines
3.6 KiB
JavaScript
96 lines
3.6 KiB
JavaScript
// Co-op UI polish.
|
|
// The auth form and footer are client-rendered (React), so a plain `load`
|
|
// listener runs too early — a MutationObserver re-checks on every DOM change.
|
|
(function () {
|
|
// One-time pin migration (2026-10-20): before the server sent
|
|
// interface.defaultPinnedTools, the client eager-seeded PIN_MCP_ and
|
|
// LAST_WEB_SEARCH_TOGGLE_pinned as 'false' — artifacts of the old default,
|
|
// not user choices (there is no unpin UI yet). Those stored values override
|
|
// the new server defaults forever, leaving Tools/Web Search unpinned.
|
|
// Clear them ONCE per browser; deliberate unpinning afterwards sticks.
|
|
try {
|
|
if (!localStorage.getItem('coopPinMigration20261020')) {
|
|
if (localStorage.getItem('PIN_MCP_') === 'false') localStorage.removeItem('PIN_MCP_');
|
|
if (localStorage.getItem('LAST_WEB_SEARCH_TOGGLE_pinned') === 'false') {
|
|
localStorage.removeItem('LAST_WEB_SEARCH_TOGGLE_pinned');
|
|
}
|
|
localStorage.setItem('coopPinMigration20261020', '1');
|
|
}
|
|
} catch (e) { /* storage unavailable — non-fatal */ }
|
|
|
|
function hideSignupPrompt() {
|
|
document.querySelectorAll('p').forEach(function (p) {
|
|
var link = p.querySelector('a[href*="register"]');
|
|
var text = (p.textContent || '');
|
|
if (link || text.indexOf("Don't have an account") !== -1) {
|
|
p.style.display = 'none';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Footer: turn the plain co-op text (injected at build time) into the
|
|
// linked version — "Inference Cooperative" links to the homepage.
|
|
function fixFooter() {
|
|
var f = document.querySelector('footer');
|
|
if (!f || f.dataset.coopFooter) return;
|
|
f.dataset.coopFooter = '1';
|
|
f.innerHTML =
|
|
'<a href="https://inference.coop">Inference Cooperative</a>' +
|
|
' · Our AI, governed together';
|
|
}
|
|
|
|
// PWA chrome bands (Android status bar + navigation bar, iOS safe areas):
|
|
// LibreChat ships static meta theme-color tags and never updates them, so
|
|
// the OS bands keep the install-time colors. Sync ONE meta tag to the app's
|
|
// RESOLVED theme (html.dark class — LibreChat applies it from the user's
|
|
// theme setting, which defaults to system = the phone's theme). Falls back
|
|
// to the light/dark media-query pair in index.html when this script is off.
|
|
var COOP_BG = { light: '#faf8f5', dark: '#22271f' };
|
|
function syncThemeColor() {
|
|
var dark = document.documentElement.classList.contains('dark');
|
|
var metas = document.querySelectorAll('meta[name="theme-color"]');
|
|
if (!metas.length) return;
|
|
// Replace the media-query pair with a single tag at the resolved color.
|
|
metas.forEach(function (m, i) {
|
|
if (i === 0) {
|
|
m.removeAttribute('media');
|
|
m.setAttribute('content', dark ? COOP_BG.dark : COOP_BG.light);
|
|
} else {
|
|
m.remove();
|
|
}
|
|
});
|
|
}
|
|
var themeObserverRunning = false;
|
|
function startThemeSync() {
|
|
if (themeObserverRunning) return;
|
|
themeObserverRunning = true;
|
|
syncThemeColor();
|
|
new MutationObserver(syncThemeColor).observe(document.documentElement, {
|
|
attributes: true,
|
|
attributeFilter: ['class'],
|
|
});
|
|
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
if (mq && mq.addEventListener) mq.addEventListener('change', syncThemeColor);
|
|
}
|
|
|
|
function run() {
|
|
hideSignupPrompt();
|
|
fixFooter();
|
|
startThemeSync();
|
|
}
|
|
|
|
function start() {
|
|
run();
|
|
new MutationObserver(run).observe(document.body, {
|
|
childList: true,
|
|
subtree: true,
|
|
});
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', start);
|
|
} else {
|
|
start();
|
|
}
|
|
})();
|