Files
rpg-companion-sillytavern/src/styles/_08_themes.css
T
ARIA df7d3b3a38 Fixes #13: CSS performance optimizations
- Add CSS minification support to build script (--minify flag)
  - Pure JS minifier: removes comments, whitespace, redundant chars
  - Reports size reduction percentage
  - Preserves CSS custom properties, data URIs, strings

- Refactor _08_themes.css: extend CSS custom properties pattern
  - Define theme-specific properties per theme (--rpg-content-bg,
    --rpg-content-box-shadow, --rpg-header-text-shadow, etc.)
  - Replace triple-theme selector duplication with single [data-theme]
    selectors — children inherit variables automatically
  - Reduces themes.css from 379 to ~220 lines
  - Reduces style.css from 305KB to 294KB (3.8% reduction)

- Add build:css:min npm script for production builds
- Add 9 tests for CSS build: minification, size reduction, CSS
  variable preservation, data URI preservation, theme refactoring
2026-07-12 14:55:36 +02:00

277 lines
9.4 KiB
CSS

/* ============================================
THEME VARIATIONS
============================================ */
/* Sci-Fi / Synthwave Theme */
.rpg-panel[data-theme="sci-fi"] {
--rpg-bg: #0a0e27;
--rpg-accent: #1a1f3a;
--rpg-text: #00fff9;
--rpg-highlight: #ff006e;
--rpg-border: #8b00ff;
--rpg-shadow: rgba(139, 0, 255, 0.5);
--rpg-content-bg: linear-gradient(135deg, #1a1f3a 0%, #0a0e27 100%);
--rpg-content-box-shadow: 0 0 40px rgba(139, 0, 255, 0.4), inset 0 0 30px rgba(0, 0, 0, 0.5);
--rpg-content-border: 2px solid #8b00ff;
--rpg-header-text-shadow: 0 0 20px #ff006e, 0 0 40px #8b00ff;
--rpg-divider-bg: linear-gradient(to right, transparent, #8b00ff, #ff006e, #8b00ff, transparent);
--rpg-thoughts-bg: linear-gradient(135deg, rgba(10, 14, 39, 0.9) 0%, rgba(26, 31, 58, 0.8) 50%, rgba(10, 14, 39, 0.9) 100%);
}
/* Apply sci-fi theme to thought panel */
#rpg-thought-panel[data-theme="sci-fi"],
#rpg-thought-icon[data-theme="sci-fi"],
#rpg-alt-present-characters[data-theme="sci-fi"],
.rpg-mobile-toggle[data-theme="sci-fi"] {
--rpg-bg: #0a0e27;
--rpg-accent: #1a1f3a;
--rpg-text: #00fff9;
--rpg-highlight: #ff006e;
--rpg-border: #8b00ff;
--rpg-shadow: rgba(139, 0, 255, 0.5);
}
/* Fantasy / Rustic Parchment Theme */
.rpg-panel[data-theme="fantasy"] {
--rpg-bg: #2b1810;
--rpg-accent: #3d2414;
--rpg-text: #f4e8d0;
--rpg-highlight: #d4af37;
--rpg-border: #8b6914;
--rpg-shadow: rgba(0, 0, 0, 0.7);
--rpg-bg-image: linear-gradient(rgba(43, 24, 16, 0.9), rgba(43, 24, 16, 0.9)), url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><filter id="noise"><feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="4" /></filter><rect width="100" height="100" filter="url(%23noise)" opacity="0.1"/></svg>');
--rpg-content-bg: linear-gradient(135deg, #3d2414 0%, #2b1810 100%);
--rpg-content-box-shadow: 0 8px 32px rgba(0, 0, 0, 0.8), inset 0 0 40px rgba(139, 105, 20, 0.2);
--rpg-content-border: 3px solid #8b6914;
--rpg-content-border-style: ridge;
--rpg-header-font-family: 'Georgia', serif;
--rpg-header-text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
--rpg-divider-content: '❦';
--rpg-divider-font-size: clamp(1rem, 1.5vw, 1.5rem);
--rpg-thoughts-bg: linear-gradient(135deg, rgba(43, 24, 16, 0.92) 0%, rgba(61, 36, 20, 0.88) 50%, rgba(43, 24, 16, 0.92) 100%);
}
/* Apply fantasy theme to thought panel */
#rpg-thought-panel[data-theme="fantasy"],
#rpg-thought-icon[data-theme="fantasy"],
#rpg-alt-present-characters[data-theme="fantasy"],
.rpg-mobile-toggle[data-theme="fantasy"] {
--rpg-bg: #2b1810;
--rpg-accent: #3d2414;
--rpg-text: #f4e8d0;
--rpg-highlight: #d4af37;
--rpg-border: #8b6914;
--rpg-shadow: rgba(0, 0, 0, 0.7);
}
/* Cyberpunk / Neon Grid Theme */
.rpg-panel[data-theme="cyberpunk"] {
--rpg-bg: #000000;
--rpg-accent: #0d0d0d;
--rpg-text: #00ff41;
--rpg-highlight: #ff2a6d;
--rpg-border: #05d9e8;
--rpg-shadow: rgba(5, 217, 232, 0.5);
--rpg-bg-image: linear-gradient(rgba(0, 0, 0, 0.95), rgba(0, 0, 0, 0.95)), repeating-linear-gradient(0deg, rgba(5, 217, 232, 0.1) 0px, transparent 1px, transparent 2px, rgba(5, 217, 232, 0.1) 3px), repeating-linear-gradient(90deg, rgba(5, 217, 232, 0.1) 0px, transparent 1px, transparent 2px, rgba(5, 217, 232, 0.1) 3px);
--rpg-bg-size: 100% 100%, 30px 30px, 30px 30px;
--rpg-content-bg: linear-gradient(135deg, rgba(13, 13, 13, 0.9) 0%, rgba(0, 0, 0, 0.9) 100%);
--rpg-content-box-shadow: 0 0 40px rgba(255, 42, 109, 0.4), inset 0 0 30px rgba(5, 217, 232, 0.2);
--rpg-content-border: 2px solid #05d9e8;
--rpg-header-font-family: 'Courier New', monospace;
--rpg-header-letter-spacing: 0.125em;
--rpg-header-text-shadow: 0 0 10px #ff2a6d, 0 0 20px #05d9e8, 0 0 30px #ff2a6d;
--rpg-divider-bg: linear-gradient(to right, transparent, #05d9e8, #ff2a6d, #05d9e8, transparent);
--rpg-divider-height: 0.188rem;
--rpg-thoughts-bg: linear-gradient(135deg, rgba(0, 0, 0, 0.92) 0%, rgba(13, 13, 13, 0.85) 50%, rgba(0, 0, 0, 0.92) 100%);
}
/* Apply cyberpunk theme to thought panel */
#rpg-thought-panel[data-theme="cyberpunk"],
#rpg-thought-icon[data-theme="cyberpunk"],
#rpg-alt-present-characters[data-theme="cyberpunk"],
.rpg-mobile-toggle[data-theme="cyberpunk"] {
--rpg-bg: #000000;
--rpg-accent: #0d0d0d;
--rpg-text: #00ff41;
--rpg-highlight: #ff2a6d;
--rpg-border: #05d9e8;
--rpg-shadow: rgba(5, 217, 232, 0.5);
}
/* ============================================
THEME SUPPORT FOR ALL PANEL ELEMENTS
Uses CSS custom properties defined above — no selector duplication needed.
Any element inside .rpg-panel inherits the theme variables automatically.
============================================ */
/* Apply theme background image if defined */
.rpg-panel[data-theme] {
background-image: var(--rpg-bg-image, none);
background-size: var(--rpg-bg-size, auto);
}
/* Content box theming via custom properties */
.rpg-panel[data-theme] .rpg-content-box {
background: var(--rpg-content-bg);
box-shadow: var(--rpg-content-box-shadow);
border: var(--rpg-content-border);
border-style: var(--rpg-content-border-style, solid);
}
/* Header theming */
.rpg-panel[data-theme] .rpg-panel-header h3,
.rpg-panel[data-theme] .rpg-stats-title,
.rpg-panel[data-theme] .rpg-info-header,
.rpg-panel[data-theme] .rpg-thoughts-header {
font-family: var(--rpg-header-font-family, inherit);
text-shadow: var(--rpg-header-text-shadow, none);
letter-spacing: var(--rpg-header-letter-spacing, normal);
}
/* Divider theming */
.rpg-panel[data-theme] .rpg-divider {
background: var(--rpg-divider-bg);
height: var(--rpg-divider-height, auto);
}
.rpg-panel[data-theme] .rpg-divider::after {
content: var(--rpg-divider-content, none);
font-size: var(--rpg-divider-font-size, inherit);
}
/* Thoughts content theming */
.rpg-panel[data-theme] .rpg-thoughts-content::before {
background: var(--rpg-thoughts-bg);
}
/* Tabs navigation theming */
.rpg-panel[data-theme] .rpg-tabs-nav {
border-bottom-color: var(--rpg-border);
}
.rpg-panel[data-theme] .rpg-tab-btn {
background: var(--rpg-accent);
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-tab-btn:hover {
background: var(--rpg-highlight);
border-color: var(--rpg-highlight);
}
.rpg-panel[data-theme] .rpg-tab-btn.active {
background: var(--rpg-highlight);
border-color: var(--rpg-highlight);
color: var(--rpg-bg);
}
/* Inventory subtabs theming */
.rpg-panel[data-theme] .rpg-inventory-subtabs {
border-bottom-color: var(--rpg-border);
}
.rpg-panel[data-theme] .rpg-inventory-subtab {
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-inventory-subtab:hover {
border-color: var(--rpg-highlight);
color: var(--rpg-highlight);
}
.rpg-panel[data-theme] .rpg-inventory-subtab.active {
border-color: var(--rpg-highlight);
color: var(--rpg-highlight);
}
/* Quests subtabs theming */
.rpg-panel[data-theme] .rpg-quests-subtabs {
border-bottom-color: var(--rpg-border);
}
.rpg-panel[data-theme] .rpg-quests-subtab {
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-quests-subtab:hover {
border-color: var(--rpg-highlight);
color: var(--rpg-highlight);
}
.rpg-panel[data-theme] .rpg-quests-subtab.active {
border-color: var(--rpg-highlight);
color: var(--rpg-highlight);
}
/* Storage locations theming */
.rpg-panel[data-theme] .rpg-storage-location {
border-color: var(--rpg-border);
}
.rpg-panel[data-theme] .rpg-storage-header {
background: var(--rpg-highlight);
}
.rpg-panel[data-theme] .rpg-storage-content {
background: var(--rpg-accent);
}
/* Button theming */
.rpg-panel[data-theme] .rpg-inventory-edit-btn,
.rpg-panel[data-theme] .rpg-inventory-add-btn,
.rpg-panel[data-theme] .rpg-inventory-remove-btn,
.rpg-panel[data-theme] .rpg-quest-edit,
.rpg-panel[data-theme] .rpg-quest-remove,
.rpg-panel[data-theme] .rpg-add-quest-btn {
background: var(--rpg-accent);
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-inventory-add-btn,
.rpg-panel[data-theme] .rpg-add-quest-btn {
background: transparent;
border-color: var(--rpg-highlight);
color: var(--rpg-highlight);
}
/* Inventory/quest items theming */
.rpg-panel[data-theme] .rpg-inventory-text,
.rpg-panel[data-theme] .rpg-quest-item,
.rpg-panel[data-theme] .rpg-main-quest-display {
background: var(--rpg-accent);
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-quest-item:hover {
border-color: var(--rpg-highlight);
}
/* Hints and empty states theming */
.rpg-panel[data-theme] .rpg-inventory-hint,
.rpg-panel[data-theme] .rpg-quest-hint,
.rpg-panel[data-theme] .rpg-inventory-empty,
.rpg-panel[data-theme] .rpg-quest-empty {
border-color: var(--rpg-highlight);
color: var(--rpg-text);
}
/* Input fields theming */
.rpg-panel[data-theme] .rpg-inline-input,
.rpg-panel[data-theme] .rpg-quest-edit-form input,
.rpg-panel[data-theme] .rpg-quest-edit-form textarea {
background: var(--rpg-bg);
border-color: var(--rpg-border);
color: var(--rpg-text);
}
.rpg-panel[data-theme] .rpg-inline-input:focus,
.rpg-panel[data-theme] .rpg-quest-edit-form input:focus,
.rpg-panel[data-theme] .rpg-quest-edit-form textarea:focus {
border-color: var(--rpg-highlight);
}