feat: per-theme accent + Activity WhatsApp(en)/GitHub cards, softer icon borders

- theme: store accent separately for light/dark (theme-core/controls)
- en contacts: WhatsApp card instead of VK (wa.me link)
- Activity: add GitHub card (logo webp) in both locales
- mp-card__image border uses --line to match card (less contrast)
This commit is contained in:
root committed 2026-09-16 14:46:08 +02:00
1 parent 302855efcf
commit 97ea48bc6f
25 files changed
+235 -47

No files matched your search

+33 -12
View File
@@ -7,6 +7,7 @@ import {
L_RANGE,
RADIUS_IDS,
THEME_MODE_IDS,
effectiveThemeMode,
FONT_IDS,
MESH_BG_IDS,
applyThemeState,
@@ -40,9 +41,13 @@ export function initThemeControls() {
applyThemeState(state);
ensureThemeFontLoaded(state.font);
function acc() {
return state[effectiveThemeMode(state)] || state.light;
}
function syncHueSlider() {
hueSlider.value = String(Math.round(state.h));
hueSlider.setAttribute("aria-valuenow", String(Math.round(state.h)));
hueSlider.value = String(Math.round(acc().h));
hueSlider.setAttribute("aria-valuenow", String(Math.round(acc().h)));
}
function persistAndApply() {
@@ -65,8 +70,8 @@ export function initThemeControls() {
}
syncHueSlider();
drawSLPlane(canvas, state.h);
updateKnob(knob, state.s, state.l);
drawSLPlane(canvas, acc().h);
updateKnob(knob, acc().s, acc().l);
syncAriaRadioGroup(radiusBtns, "data-radius-option", state.radius);
syncAriaRadioGroup(themeModeBtns, "data-theme-mode", state.mode);
syncAriaRadioGroup(fontBtns, "data-font-option", state.font);
@@ -75,6 +80,15 @@ export function initThemeControls() {
bindOptionButtons(radiusBtns, "data-radius-option", RADIUS_IDS, "radius");
bindOptionButtons(fontBtns, "data-font-option", FONT_IDS, "font");
bindOptionButtons(themeModeBtns, "data-theme-mode", THEME_MODE_IDS, "mode");
themeModeBtns.forEach((btn) =>
btn.addEventListener("click", () => {
if (!panel.hidden) {
syncHueSlider();
drawSLPlane(canvas, acc().h);
updateKnob(knob, acc().s, acc().l);
}
}),
);
if (meshBgBtns.length >= 2) bindOptionButtons(meshBgBtns, "data-mesh-bg-option", MESH_BG_IDS, "meshBg");
function setPanelOpen(open) {
@@ -84,8 +98,8 @@ export function initThemeControls() {
btn.setAttribute("aria-label", open ? "Закрыть настройки стиля" : "Настройки стиля");
});
if (open) {
drawSLPlane(canvas, state.h);
updateKnob(knob, state.s, state.l);
drawSLPlane(canvas, acc().h);
updateKnob(knob, acc().s, acc().l);
syncAriaRadioGroup(themeModeBtns, "data-theme-mode", state.mode);
syncAriaRadioGroup(fontBtns, "data-font-option", state.font);
if (meshBgBtns.length >= 2) syncAriaRadioGroup(meshBgBtns, "data-mesh-bg-option", state.meshBg);
@@ -95,6 +109,11 @@ export function initThemeControls() {
subscribePrefersColorSchemeChange(() => {
if (state.mode !== "system") return;
applyThemeState(state);
if (!panel.hidden) {
syncHueSlider();
drawSLPlane(canvas, acc().h);
updateKnob(knob, acc().s, acc().l);
}
});
panelBtns.forEach((btn) => {
@@ -143,9 +162,10 @@ export function initThemeControls() {
if (r.width <= 0 || r.height <= 0) return;
const x = clampNum(((clientX - r.left) / r.width) * 100, 0, 100, 0) / 100;
const y = clampNum(((clientY - r.top) / r.height) * 100, 0, 100, 0) / 100;
state.s = Math.round(PICK.sMin + x * S_RANGE);
state.l = Math.round(PICK.lMin + (1 - y) * L_RANGE);
updateKnob(knob, state.s, state.l);
const a = acc();
a.s = Math.round(PICK.sMin + x * S_RANGE);
a.l = Math.round(PICK.lMin + (1 - y) * L_RANGE);
updateKnob(knob, a.s, a.l);
persistAndApply();
}
@@ -168,10 +188,11 @@ export function initThemeControls() {
});
hueSlider.addEventListener("input", () => {
state.h = clampNum(hueSlider.value, 0, 360, state.h);
const a = acc();
a.h = clampNum(hueSlider.value, 0, 360, a.h);
syncHueSlider();
drawSLPlane(canvas, state.h);
updateKnob(knob, state.s, state.l);
drawSLPlane(canvas, a.h);
updateKnob(knob, a.s, a.l);
persistAndApply();
});
}