feat: tune light theme, reduce accent color usage overall
This commit is contained in:
@@ -24,7 +24,8 @@
|
||||
|
||||
function readCssColor(name, fallback) {
|
||||
if (typeof document === "undefined") return fallback;
|
||||
const raw = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
const scope = hostEl || document.documentElement;
|
||||
const raw = getComputedStyle(scope).getPropertyValue(name).trim();
|
||||
return raw || fallback;
|
||||
}
|
||||
|
||||
@@ -65,7 +66,11 @@
|
||||
const muted = readCssColor("--admin-muted", "#9aa7a2");
|
||||
const border = readCssColor("--admin-border", "rgba(255,255,255,0.12)");
|
||||
const accent = readCssColor("--accent", "#00fe7a");
|
||||
const lineStroke = readCssColor("--admin-text", "#e8f0ec");
|
||||
const lineStroke = readCssColor(
|
||||
"--admin-chart-stroke",
|
||||
readCssColor("--admin-text", "#e8f0ec"),
|
||||
);
|
||||
const lineFill = readCssColor("--admin-chart-fill", "rgba(120, 140, 132, 0.14)");
|
||||
|
||||
return {
|
||||
width: w,
|
||||
@@ -94,7 +99,7 @@
|
||||
stroke: lineStroke,
|
||||
width: 2,
|
||||
cap: "round",
|
||||
fill: "rgba(120, 140, 132, 0.14)",
|
||||
fill: lineFill,
|
||||
},
|
||||
],
|
||||
axes: [
|
||||
|
||||
@@ -12,6 +12,21 @@ const TOKEN_TO_CSS_VAR = {
|
||||
muted: "--muted",
|
||||
dim: "--dim",
|
||||
danger: "--danger",
|
||||
danger_text: "--danger-text",
|
||||
danger_soft: "--danger-soft",
|
||||
danger_border: "--danger-border",
|
||||
success: "--success",
|
||||
success_text: "--success-text",
|
||||
success_soft: "--success-soft",
|
||||
success_border: "--success-border",
|
||||
warning: "--warning",
|
||||
warning_text: "--warning-text",
|
||||
warning_soft: "--warning-soft",
|
||||
warning_border: "--warning-border",
|
||||
info: "--info",
|
||||
info_text: "--info-text",
|
||||
info_soft: "--info-soft",
|
||||
info_border: "--info-border",
|
||||
blue: "--blue",
|
||||
radius: "--radius",
|
||||
font_sans: "--font-sans",
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
.admin-btn.admin-btn-primary {
|
||||
background: var(--accent);
|
||||
color: #02110a;
|
||||
color: var(--accent-contrast);
|
||||
border-color: color-mix(in srgb, var(--accent) 70%, #000);
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -129,31 +129,31 @@
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-ghost:hover:not(:disabled) {
|
||||
background: rgba(255, 255, 255, 0.04);
|
||||
background: var(--surface-hover);
|
||||
color: var(--admin-text);
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-danger {
|
||||
background: color-mix(in srgb, #ff5757 80%, #000);
|
||||
background: color-mix(in srgb, var(--danger) 80%, #000);
|
||||
color: #fff;
|
||||
border-color: color-mix(in srgb, #ff5757 60%, #000);
|
||||
border-color: color-mix(in srgb, var(--danger) 60%, #000);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-danger:hover:not(:disabled) {
|
||||
background: #ff5757;
|
||||
border-color: #ff5757;
|
||||
background: var(--danger);
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-danger-soft {
|
||||
color: #ffb4b4;
|
||||
color: var(--danger-text);
|
||||
background: var(--admin-surface-2);
|
||||
border-color: color-mix(in srgb, #ff6b6b 30%, transparent);
|
||||
border-color: var(--danger-border);
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-danger-soft:hover:not(:disabled) {
|
||||
background: color-mix(in srgb, #ff6b6b 14%, var(--admin-surface));
|
||||
border-color: color-mix(in srgb, #ff6b6b 50%, transparent);
|
||||
background: var(--danger-soft);
|
||||
border-color: color-mix(in srgb, var(--danger) 50%, transparent);
|
||||
}
|
||||
|
||||
.admin-btn.admin-btn-icon {
|
||||
@@ -183,21 +183,21 @@
|
||||
}
|
||||
|
||||
.admin-badge.admin-badge-success {
|
||||
border-color: color-mix(in srgb, var(--accent) 36%, transparent);
|
||||
color: var(--accent);
|
||||
background: color-mix(in srgb, var(--accent) 12%, var(--admin-surface));
|
||||
border-color: var(--success-border);
|
||||
color: var(--success-text);
|
||||
background: var(--success-soft);
|
||||
}
|
||||
|
||||
.admin-badge.admin-badge-danger {
|
||||
border-color: color-mix(in srgb, #ff6b6b 32%, transparent);
|
||||
color: #ffb4b4;
|
||||
background: color-mix(in srgb, #ff6b6b 12%, var(--admin-surface));
|
||||
border-color: var(--danger-border);
|
||||
color: var(--danger-text);
|
||||
background: var(--danger-soft);
|
||||
}
|
||||
|
||||
.admin-badge.admin-badge-warning {
|
||||
border-color: color-mix(in srgb, #ffd166 32%, transparent);
|
||||
color: #ffd166;
|
||||
background: color-mix(in srgb, #ffd166 12%, var(--admin-surface));
|
||||
border-color: var(--warning-border);
|
||||
color: var(--warning-text);
|
||||
background: var(--warning-soft);
|
||||
}
|
||||
|
||||
.admin-badge.admin-badge-muted {
|
||||
@@ -270,7 +270,7 @@
|
||||
|
||||
.admin-extend-control .admin-btn.admin-btn-primary {
|
||||
background: var(--accent);
|
||||
color: #02110a;
|
||||
color: var(--accent-contrast);
|
||||
border-color: color-mix(in srgb, var(--accent) 70%, #000);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@@ -546,11 +546,11 @@
|
||||
}
|
||||
|
||||
.admin-revenue-kpi-growth.is-up {
|
||||
color: color-mix(in srgb, #3ecf8e 92%, var(--admin-text));
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.admin-revenue-kpi-growth.is-down {
|
||||
color: color-mix(in srgb, #ff6b6b 88%, var(--admin-text));
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
.admin-revenue-chart {
|
||||
@@ -2088,11 +2088,11 @@
|
||||
}
|
||||
|
||||
.admin-traffic-card-premium {
|
||||
border-color: color-mix(in srgb, var(--accent) 30%, var(--admin-border));
|
||||
border-color: var(--info-border);
|
||||
}
|
||||
|
||||
.admin-traffic-card-warning {
|
||||
border-color: color-mix(in srgb, #ffb454 46%, var(--admin-border));
|
||||
border-color: var(--warning-border);
|
||||
}
|
||||
|
||||
.admin-traffic-head,
|
||||
@@ -2134,11 +2134,11 @@
|
||||
}
|
||||
|
||||
.admin-traffic-bar-premium span {
|
||||
background: linear-gradient(90deg, #66e3ff, var(--accent));
|
||||
background: linear-gradient(90deg, var(--info), color-mix(in srgb, var(--info) 64%, #ffffff));
|
||||
}
|
||||
|
||||
.admin-traffic-card-warning .admin-traffic-bar span {
|
||||
background: linear-gradient(90deg, #ffb454, #ff6b6b);
|
||||
background: linear-gradient(90deg, var(--warning), var(--danger));
|
||||
}
|
||||
|
||||
.admin-traffic-meta {
|
||||
@@ -2656,8 +2656,8 @@
|
||||
}
|
||||
|
||||
.admin-switch-root[data-state="checked"] {
|
||||
background: color-mix(in srgb, var(--accent) 80%, var(--admin-elev));
|
||||
border-color: color-mix(in srgb, var(--accent) 50%, transparent);
|
||||
background: color-mix(in srgb, var(--success) 82%, var(--admin-elev));
|
||||
border-color: color-mix(in srgb, var(--success) 52%, transparent);
|
||||
}
|
||||
|
||||
.admin-switch-root:focus-visible {
|
||||
@@ -3080,9 +3080,9 @@
|
||||
}
|
||||
|
||||
.admin-danger-zone {
|
||||
border: 1px solid color-mix(in srgb, #ff6b6b 32%, transparent);
|
||||
border: 1px solid var(--danger-border);
|
||||
border-radius: 12px;
|
||||
background: color-mix(in srgb, #ff6b6b 6%, var(--admin-surface));
|
||||
background: var(--danger-soft);
|
||||
padding: 14px 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -3099,13 +3099,13 @@
|
||||
.admin-danger-zone-head strong {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #ffb4b4;
|
||||
color: var(--danger-text);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.admin-danger-zone-head small {
|
||||
color: color-mix(in srgb, #ffb4b4 70%, var(--admin-muted));
|
||||
color: color-mix(in srgb, var(--danger-text) 70%, var(--admin-muted));
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,21 @@
|
||||
--muted: #a9b4b0;
|
||||
--dim: #68736f;
|
||||
--danger: #ff6b6b;
|
||||
--danger-text: #ffb4b4;
|
||||
--danger-soft: color-mix(in srgb, var(--danger) 12%, var(--panel));
|
||||
--danger-border: color-mix(in srgb, var(--danger) 34%, var(--border));
|
||||
--success: #3ecf8e;
|
||||
--success-text: #7ff0b9;
|
||||
--success-soft: color-mix(in srgb, var(--success) 12%, var(--panel));
|
||||
--success-border: color-mix(in srgb, var(--success) 34%, var(--border));
|
||||
--warning: #ffd166;
|
||||
--warning-text: #ffd166;
|
||||
--warning-soft: color-mix(in srgb, var(--warning) 12%, var(--panel));
|
||||
--warning-border: color-mix(in srgb, var(--warning) 34%, var(--border));
|
||||
--info: #2d9cff;
|
||||
--info-text: #8ed0ff;
|
||||
--info-soft: color-mix(in srgb, var(--info) 12%, var(--panel));
|
||||
--info-border: color-mix(in srgb, var(--info) 34%, var(--border));
|
||||
--blue: #2d9cff;
|
||||
--radius: 8px;
|
||||
--accent-contrast: #03100a;
|
||||
|
||||
@@ -171,15 +171,15 @@
|
||||
}
|
||||
|
||||
.admin-cn-badge-destructive {
|
||||
background: color-mix(in srgb, var(--danger) 16%, var(--admin-surface));
|
||||
border-color: color-mix(in srgb, var(--danger) 35%, var(--admin-border));
|
||||
color: color-mix(in srgb, var(--danger) 92%, var(--admin-text));
|
||||
background: var(--danger-soft);
|
||||
border-color: var(--danger-border);
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
.admin-cn-badge-success {
|
||||
background: color-mix(in srgb, var(--accent) 14%, var(--admin-surface));
|
||||
border-color: color-mix(in srgb, var(--accent) 32%, var(--admin-border));
|
||||
color: color-mix(in srgb, var(--accent) 88%, var(--admin-text));
|
||||
background: var(--success-soft);
|
||||
border-color: var(--success-border);
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.admin-cn-badge-muted {
|
||||
|
||||
@@ -574,8 +574,8 @@ a {
|
||||
|
||||
.device-disconnect-button,
|
||||
.device-danger-button {
|
||||
border-color: color-mix(in srgb, var(--danger) 62%, var(--border));
|
||||
color: #ffb8b8;
|
||||
border-color: var(--danger-border);
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
.devices-empty-card {
|
||||
@@ -957,7 +957,7 @@ a {
|
||||
|
||||
.tariff-warning-card {
|
||||
justify-content: flex-start;
|
||||
color: var(--warning, #ffd166);
|
||||
color: var(--warning-text);
|
||||
}
|
||||
|
||||
.confirm-summary-card {
|
||||
@@ -1067,10 +1067,10 @@ a {
|
||||
.field-error-tooltip {
|
||||
z-index: 120;
|
||||
max-width: 280px;
|
||||
border: 1px solid color-mix(in srgb, var(--danger) 60%, var(--border));
|
||||
border: 1px solid var(--danger-border);
|
||||
border-radius: 8px;
|
||||
background: #2a1010;
|
||||
color: #ffd8d8;
|
||||
background: var(--danger-soft);
|
||||
color: var(--danger-text);
|
||||
padding: 8px 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.3;
|
||||
@@ -1286,16 +1286,16 @@ a {
|
||||
|
||||
.settings-row-linked {
|
||||
grid-template-columns: 28px minmax(0, 1fr);
|
||||
border-color: color-mix(in srgb, var(--accent) 38%, var(--border));
|
||||
background: color-mix(in srgb, var(--accent) 11%, var(--surface-muted));
|
||||
border-color: var(--success-border);
|
||||
background: var(--success-soft);
|
||||
}
|
||||
|
||||
.settings-row-linked > svg:first-child {
|
||||
color: var(--accent);
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.settings-row-linked strong {
|
||||
color: var(--accent);
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.emoji-flag {
|
||||
@@ -1772,7 +1772,7 @@ a {
|
||||
}
|
||||
|
||||
.status-line {
|
||||
color: var(--accent);
|
||||
color: var(--success-text);
|
||||
font-size: 12px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
@@ -1800,7 +1800,7 @@ a {
|
||||
bottom: 16px;
|
||||
z-index: 120;
|
||||
max-width: min(420px, calc(100vw - 32px));
|
||||
border: 1px solid color-mix(in srgb, var(--accent) 46%, var(--border));
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius);
|
||||
background: color-mix(in srgb, var(--panel) 92%, transparent);
|
||||
box-shadow: var(--shadow-popover);
|
||||
|
||||
@@ -11,6 +11,21 @@
|
||||
--muted: #475569;
|
||||
--dim: #64748b;
|
||||
--danger: #dc2626;
|
||||
--danger-text: #b91c1c;
|
||||
--danger-soft: color-mix(in srgb, var(--danger) 9%, var(--panel));
|
||||
--danger-border: color-mix(in srgb, var(--danger) 34%, var(--border));
|
||||
--success: #16a34a;
|
||||
--success-text: #166534;
|
||||
--success-soft: color-mix(in srgb, var(--success) 10%, var(--panel));
|
||||
--success-border: color-mix(in srgb, var(--success) 34%, var(--border));
|
||||
--warning: #d97706;
|
||||
--warning-text: #92400e;
|
||||
--warning-soft: color-mix(in srgb, var(--warning) 11%, var(--panel));
|
||||
--warning-border: color-mix(in srgb, var(--warning) 34%, var(--border));
|
||||
--info: #2563eb;
|
||||
--info-text: #1d4ed8;
|
||||
--info-soft: color-mix(in srgb, var(--info) 9%, var(--panel));
|
||||
--info-border: color-mix(in srgb, var(--info) 30%, var(--border));
|
||||
--blue: #2563eb;
|
||||
--radius: 8px;
|
||||
--accent-contrast: #ffffff;
|
||||
@@ -22,9 +37,9 @@
|
||||
--overlay-scrim: rgba(15, 23, 42, 0.34);
|
||||
--nav-bg: rgba(255, 255, 255, 0.88);
|
||||
--rail-bg: rgba(255, 255, 255, 0.72);
|
||||
--shadow-soft: 0 16px 38px rgba(15, 23, 42, 0.08);
|
||||
--shadow-strong: 0 24px 64px rgba(15, 23, 42, 0.16);
|
||||
--shadow-popover: 0 18px 34px rgba(15, 23, 42, 0.14);
|
||||
--shadow-soft: 0 6px 18px rgba(15, 23, 42, 0.06);
|
||||
--shadow-strong: 0 18px 44px rgba(15, 23, 42, 0.12);
|
||||
--shadow-popover: 0 14px 28px rgba(15, 23, 42, 0.12);
|
||||
--inset-highlight: rgba(255, 255, 255, 0.75);
|
||||
--admin-bg: #f7f8fb;
|
||||
--admin-surface: #ffffff;
|
||||
@@ -34,7 +49,33 @@
|
||||
--admin-border-strong: rgba(15, 23, 42, 0.18);
|
||||
--admin-text: #0f172a;
|
||||
--admin-muted: #64748b;
|
||||
--admin-dim: #94a3b8;
|
||||
--admin-dim: #64748b;
|
||||
--admin-chart-stroke: #065f46;
|
||||
--admin-chart-fill: rgba(6, 95, 70, 0.22);
|
||||
}
|
||||
|
||||
.theme-key-light .ui-spinner,
|
||||
.theme-key-light .brand-mark-spinner {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.theme-key-light .telegram-button-spinner {
|
||||
border-color: rgba(255, 255, 255, 0.35);
|
||||
border-top-color: #ffffff;
|
||||
}
|
||||
|
||||
.theme-key-light .btn-primary,
|
||||
.theme-key-light .admin-btn.admin-btn-primary,
|
||||
.theme-key-light .admin-extend-control .admin-btn.admin-btn-primary {
|
||||
background: color-mix(in srgb, var(--accent) 50%, #000000);
|
||||
border-color: color-mix(in srgb, var(--accent) 42%, #000000);
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.theme-key-light .btn-primary:hover:not(:disabled),
|
||||
.theme-key-light .admin-btn.admin-btn-primary:hover:not(:disabled),
|
||||
.theme-key-light .admin-extend-control .admin-btn.admin-btn-primary:hover:not(:disabled) {
|
||||
background: color-mix(in srgb, var(--accent) 52%, #000000);
|
||||
}
|
||||
|
||||
.theme-key-light.app-shell {
|
||||
@@ -44,3 +85,47 @@
|
||||
.theme-key-light .phone-screen {
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
/* Flatten Settings rows: no gradient sheen, no inset highlight that reads as a 3D bevel */
|
||||
.theme-key-light .settings-row {
|
||||
background: var(--panel);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.theme-key-light .settings-row-linked {
|
||||
background: var(--success-soft);
|
||||
}
|
||||
|
||||
/* Avatar/profile card: bigger lift, but rows below have an opaque background and
|
||||
stack above, so the shadow stays visually under them instead of bleeding through. */
|
||||
.theme-key-light .settings-profile {
|
||||
box-shadow:
|
||||
0 10px 24px rgba(15, 23, 42, 0.10),
|
||||
inset 0 1px 0 var(--inset-highlight);
|
||||
}
|
||||
|
||||
.theme-key-light .settings-links-block {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Slightly stronger axis/grid contrast for the revenue chart on a light surface */
|
||||
.theme-key-light .admin-revenue-svg-frame {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
/* Bonus section: drop accent color from body strongs; only the bonus-system heading
|
||||
and explicitly-accent card headings stay tinted — and they use the same darkened
|
||||
accent technique as .btn-primary on light, so they remain readable on white. */
|
||||
.theme-key-light .bonus-card strong {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.theme-key-light .bonus-card-head strong,
|
||||
.theme-key-light .card-heading-accent {
|
||||
color: color-mix(in srgb, var(--accent) 50%, #000000);
|
||||
}
|
||||
|
||||
.theme-key-light .bonus-card-head > svg {
|
||||
color: color-mix(in srgb, var(--accent) 50%, #000000);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"use_primary_accent": true,
|
||||
"use_in_admin": true,
|
||||
"css_file": "style.css",
|
||||
"assets_version": 1,
|
||||
"assets_version": 2,
|
||||
"tokens": {
|
||||
"color_scheme": "light"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,21 @@ class ThemeTokens(BaseModel):
|
||||
muted: Optional[str] = None
|
||||
dim: Optional[str] = None
|
||||
danger: Optional[str] = None
|
||||
danger_text: Optional[str] = None
|
||||
danger_soft: Optional[str] = None
|
||||
danger_border: Optional[str] = None
|
||||
success: Optional[str] = None
|
||||
success_text: Optional[str] = None
|
||||
success_soft: Optional[str] = None
|
||||
success_border: Optional[str] = None
|
||||
warning: Optional[str] = None
|
||||
warning_text: Optional[str] = None
|
||||
warning_soft: Optional[str] = None
|
||||
warning_border: Optional[str] = None
|
||||
info: Optional[str] = None
|
||||
info_text: Optional[str] = None
|
||||
info_soft: Optional[str] = None
|
||||
info_border: Optional[str] = None
|
||||
blue: Optional[str] = None
|
||||
radius: Optional[str] = None
|
||||
font_sans: Optional[str] = None
|
||||
@@ -350,7 +365,7 @@ def _builtin_theme_assets_need_refresh(key: str, target_dir: Path) -> bool:
|
||||
except OSError:
|
||||
return True
|
||||
if key == "light":
|
||||
return ".theme-key-light.app-shell" not in style
|
||||
return "--success-text" not in style or ".theme-key-light.app-shell" not in style
|
||||
if key == "ascii":
|
||||
return (
|
||||
".theme-key-ascii" not in style
|
||||
|
||||
Reference in New Issue
Block a user