Wherry/frontend/css/theme.css
2026-07-11 00:01:26 +03:00

371 lines
11 KiB
CSS

/* ── Wherry Themes ─────────────────────────────────────────────────────────
Six themes: Ember (dark · copper), Frost (light · blue), Midnight
(dark · indigo), Forest (dark · green), Dawn (light · peach), Ash
(high-contrast dark · neutral).
Every colour the UI uses is a token; component styles never hardcode a
hex. Soft/hover variants are derived with color-mix() so the whole
palette can be retuned by touching only the base tokens.
The active theme is selected via `data-theme="…"` on the <html> element.
──────────────────────────────────────────────────────────────────────── */
/* ══════════════ 1. Ember (default dark · copper accent) ═══════════════ */
:root,
[data-theme="ember"] {
--bg-base: #0b0d11;
--bg-panel: #181c24;
--bg-content: #12151b;
--bg-toolbar: #12151b;
--bg-tab-active: #12151b;
--bg-tab-idle: #14171e;
--bg-queue: #0f1116;
--bg-header: #10131a;
--bg-row-hover: rgba(255, 255, 255, 0.055);
--bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
--accent: #d9804f;
--accent-hover: #e28e5d;
--accent-dim: #9c5433;
--accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
--on-accent: #221208;
--green: #7dc98f;
--green-soft: color-mix(in srgb, var(--green) 14%, transparent);
--red: #e2604c;
--red-hover: #e97561;
--red-soft: color-mix(in srgb, var(--red) 14%, transparent);
--yellow: #e3b341;
--yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
--blue: #6aa9e9;
--blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
--text-primary: #eceef2;
--text-dim: #99a0ac;
--text-hint: #656c79;
--border: #232833;
--separator: #262b35;
}
/* ══════════════ 2. Frost (light · cool blue accent) ════════════════════ */
[data-theme="frost"] {
--bg-base: #f4f6fa;
--bg-panel: #ffffff;
--bg-content: #fafbfd;
--bg-toolbar: #ffffff;
--bg-tab-active: #ffffff;
--bg-tab-idle: #f0f2f6;
--bg-queue: #f8f9fc;
--bg-header: #edf0f5;
--bg-row-hover: rgba(0, 0, 0, 0.04);
--bg-row-sel: color-mix(in srgb, var(--accent) 14%, transparent);
--accent: #4a8fe0;
--accent-hover: #5d9de8;
--accent-dim: #3570b0;
--accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 28%, transparent);
--on-accent: #ffffff;
--green: #38a169;
--green-soft: color-mix(in srgb, var(--green) 12%, transparent);
--red: #d95c4a;
--red-hover: #e06d5c;
--red-soft: color-mix(in srgb, var(--red) 12%, transparent);
--yellow: #c9952e;
--yellow-soft: color-mix(in srgb, var(--yellow) 12%, transparent);
--blue: #4a8fe0;
--blue-soft: color-mix(in srgb, var(--blue) 12%, transparent);
--text-primary: #1a1d23;
--text-dim: #5f6672;
--text-hint: #9098a5;
--border: #dce0e8;
--separator: #e2e6ee;
}
/* ══════════════ 3. Midnight (dark · indigo accent) ══════════════════════ */
[data-theme="midnight"] {
--bg-base: #0d0e17;
--bg-panel: #161827;
--bg-content: #10121e;
--bg-toolbar: #10121e;
--bg-tab-active: #10121e;
--bg-tab-idle: #131523;
--bg-queue: #0e0f1a;
--bg-header: #0f111d;
--bg-row-hover: rgba(255, 255, 255, 0.055);
--bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
--accent: #8b7cf7;
--accent-hover: #9d90f9;
--accent-dim: #6355c9;
--accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
--on-accent: #110e24;
--green: #6fcb8a;
--green-soft: color-mix(in srgb, var(--green) 14%, transparent);
--red: #e06070;
--red-hover: #e87481;
--red-soft: color-mix(in srgb, var(--red) 14%, transparent);
--yellow: #dbb84a;
--yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
--blue: #6a8ce8;
--blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
--text-primary: #e8eaf2;
--text-dim: #949ab0;
--text-hint: #5e6480;
--border: #222540;
--separator: #262948;
}
/* ══════════════ 4. Forest (dark · green accent) ═════════════════════════ */
[data-theme="forest"] {
--bg-base: #0b120e;
--bg-panel: #141f17;
--bg-content: #0e1611;
--bg-toolbar: #0e1611;
--bg-tab-active: #0e1611;
--bg-tab-idle: #111a13;
--bg-queue: #0c130f;
--bg-header: #0d1510;
--bg-row-hover: rgba(255, 255, 255, 0.055);
--bg-row-sel: color-mix(in srgb, var(--accent) 17%, transparent);
--accent: #5bba70;
--accent-hover: #6ec982;
--accent-dim: #3d8f4f;
--accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 32%, transparent);
--on-accent: #0c1e10;
--green: #5bba70;
--green-soft: color-mix(in srgb, var(--green) 14%, transparent);
--red: #d96050;
--red-hover: #e07262;
--red-soft: color-mix(in srgb, var(--red) 14%, transparent);
--yellow: #d4ad40;
--yellow-soft: color-mix(in srgb, var(--yellow) 14%, transparent);
--blue: #5b94c9;
--blue-soft: color-mix(in srgb, var(--blue) 14%, transparent);
--text-primary: #e2efe5;
--text-dim: #91a899;
--text-hint: #5c7565;
--border: #1e3325;
--separator: #223b29;
}
/* ══════════════ 5. Dawn (light · warm peach accent) ═════════════════════ */
[data-theme="dawn"] {
--bg-base: #faf6f3;
--bg-panel: #ffffff;
--bg-content: #fdfaf8;
--bg-toolbar: #ffffff;
--bg-tab-active: #ffffff;
--bg-tab-idle: #f6f0ea;
--bg-queue: #fbf7f4;
--bg-header: #f2ebe5;
--bg-row-hover: rgba(0, 0, 0, 0.04);
--bg-row-sel: color-mix(in srgb, var(--accent) 14%, transparent);
--accent: #d9735a;
--accent-hover: #e0846c;
--accent-dim: #b05a44;
--accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 28%, transparent);
--on-accent: #ffffff;
--green: #4b8b5e;
--green-soft: color-mix(in srgb, var(--green) 12%, transparent);
--red: #c95a4a;
--red-hover: #d86c5c;
--red-soft: color-mix(in srgb, var(--red) 12%, transparent);
--yellow: #b8993a;
--yellow-soft: color-mix(in srgb, var(--yellow) 12%, transparent);
--blue: #5a80b8;
--blue-soft: color-mix(in srgb, var(--blue) 12%, transparent);
--text-primary: #2c2420;
--text-dim: #736760;
--text-hint: #9f928a;
--border: #e6dbd3;
--separator: #ede2da;
}
/* ══════════════ 6. Ash (high-contrast dark · neutral gray) ══════════════ */
[data-theme="ash"] {
--bg-base: #0a0a0c;
--bg-panel: #141416;
--bg-content: #0e0e10;
--bg-toolbar: #0e0e10;
--bg-tab-active: #0e0e10;
--bg-tab-idle: #111113;
--bg-queue: #0c0c0e;
--bg-header: #0d0d0f;
--bg-row-hover: rgba(255, 255, 255, 0.07);
--bg-row-sel: color-mix(in srgb, var(--accent) 20%, transparent);
--accent: #c0c4cc;
--accent-hover: #d4d8e0;
--accent-dim: #8a8e98;
--accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
--accent-ring: color-mix(in srgb, var(--accent) 35%, transparent);
--on-accent: #0a0a0c;
--green: #8fd4a0;
--green-soft: color-mix(in srgb, var(--green) 16%, transparent);
--red: #f07060;
--red-hover: #f58476;
--red-soft: color-mix(in srgb, var(--red) 16%, transparent);
--yellow: #e8c860;
--yellow-soft: color-mix(in srgb, var(--yellow) 16%, transparent);
--blue: #80b4e8;
--blue-soft: color-mix(in srgb, var(--blue) 16%, transparent);
--text-primary: #f0f2f5;
--text-dim: #b0b4be;
--text-hint: #787c88;
--border: #2c2e36;
--separator: #32343c;
}
/* ══════════════ Shared base styles ════════════════════════════════════════ */
/* Sizes — identical across all themes */
:root {
--sidebar-w: 216px;
--toolbar-h: 52px;
--tabbar-h: 36px;
--queue-collapsed-h: 34px;
--queue-expanded-h: 192px;
--status-h: 28px;
--row-h: 32px;
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 10px;
--radius-card: 14px;
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text",
"Segoe UI", "Noto Sans", "Ubuntu", "Cantarell", "DejaVu Sans", sans-serif;
--font-mono: "SF Mono", ui-monospace, Menlo, Consolas, "Noto Sans Mono",
"DejaVu Sans Mono", monospace;
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
/* Transition for theme switching — animates colour changes smoothly */
--theme-transition: background-color 0.3s var(--ease-out),
color 0.3s var(--ease-out),
border-color 0.3s var(--ease-out),
box-shadow 0.3s var(--ease-out);
}
/* Apply theme transitions when [data-theme] changes */
html.theme-transitioning,
html.theme-transitioning *,
html.theme-transitioning *::before,
html.theme-transitioning *::after {
transition: var(--theme-transition) !important;
}
* {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
background: var(--bg-base);
color: var(--text-primary);
font-family: var(--font-sans);
font-size: 13px;
overflow: hidden;
-webkit-font-smoothing: antialiased;
user-select: none;
}
#app {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
button,
input,
select {
font-family: inherit;
color: inherit;
}
button {
appearance: none;
background: none;
border: none;
padding: 0;
cursor: pointer;
font-size: inherit;
}
p {
margin: 0;
}
::selection {
background: var(--accent-ring);
color: var(--text-primary);
}
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
::-webkit-scrollbar {
width: 9px;
height: 9px;
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-hint);
}
::-webkit-scrollbar-track {
background: transparent;
}
/* ── Utility text-colour classes ─────────────────────────────────────────── */
.text-primary { color: var(--text-primary); }
.text-dim { color: var(--text-dim); }
.text-hint { color: var(--text-hint); }
.text-accent { color: var(--accent); }
.text-green { color: var(--green); }
.text-red { color: var(--red); }
.text-yellow { color: var(--yellow); }
.text-blue { color: var(--blue); }
.mono { font-family: var(--font-mono); }