diff --git a/app/__init__.py b/app/__init__.py index 9ef04230..acea4120 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -831,7 +831,7 @@ def account_preferences(): valid_themes = { 'glass', 'retro', 'solar', 'paper', 'noir', 'arctic-ice', 'rose-gold', 'cyberpunk-neon', - 'emerald-matrix', 'obsidian', + 'emerald-matrix', 'obsidian', 'rack-console', } if ( not isinstance(data['theme'], str) diff --git a/app/socket_events.py b/app/socket_events.py index b7a8dc88..2dcaf0a2 100644 --- a/app/socket_events.py +++ b/app/socket_events.py @@ -1664,7 +1664,8 @@ def handle_set_theme(data, current_user=None): theme = data.get('theme') valid_themes = [ 'glass', 'retro', 'solar', 'paper', 'noir', - 'arctic-ice', 'rose-gold', 'cyberpunk-neon', 'emerald-matrix', 'obsidian' + 'arctic-ice', 'rose-gold', 'cyberpunk-neon', 'emerald-matrix', 'obsidian', + 'rack-console' ] if theme not in valid_themes: emit('error', {'error': 'Invalid theme'}) diff --git a/design-qa.md b/design-qa.md index 1a64ae5c..5bcfab74 100644 --- a/design-qa.md +++ b/design-qa.md @@ -252,3 +252,56 @@ and context navigation no longer compete in one toolbar. - Remaining P0/P1/P2 findings: none. final result: passed + +## Rack Console theme QA (2026-09-03) + +### Reference and rendered evidence + +- Source visual truth: `/home/heimdall/.codex/generated_images/01a065f7-4668-7430-b372-d629f24bbab0/exec-964d13f7-b9c8-4d59-8050-762296fee235.png` (1672 x 941 px), the selected Rack Console concept. +- Browser-rendered implementation: `/tmp/webssh-rack-console-design-qa/rack-console-implementation-final.png` (1280 x 720 px) at a 1280 x 720 CSS viewport. +- Density normalization: the in-app browser reported `devicePixelRatio: 2` but returned a CSS-pixel screenshot. The source was proportionally normalized to 1280 x 720 for comparison; its aspect ratio differs only by source rounding. +- State: authenticated seeded administrator, Rack Console selected through Settings, Workspaces active, saved hosts visible, Notes open, and no active SSH session. +- Full-view comparison: `/tmp/webssh-rack-console-design-qa/rack-console-comparison-final.png` places the normalized source and final implementation side by side. +- Focused top-rail comparison: `/tmp/webssh-rack-console-design-qa/rack-console-top-comparison-final.png` compares navigation, brand, session controls, borders, and active states at readable scale. +- Focused workspace comparison: `/tmp/webssh-rack-console-design-qa/rack-console-workspace-comparison-final.png` compares the host surface, rack rows, right service module, and bottom telemetry rail. +- Responsive supporting evidence: `/tmp/webssh-rack-console-design-qa/rack-console-mobile.png` and `/tmp/webssh-rack-console-design-qa/rack-console-mobile-menu-v2.png` at 390 x 844 CSS px. + +### Fidelity review + +- Fonts and typography: the implementation preserves WebSSH's shared Inter hierarchy for readable product copy and applies IBM Plex Mono selectively to rack labels, navigation, controls, endpoints, notes, and telemetry. Uppercase labels and restrained tracking reproduce the source's equipment-label character without changing content width or the global type system. +- Spacing and layout rhythm: header, session rail, main content, terminal grid, context workspace, and status bar retain the existing application arrangement. The final comparison preserves the same 1280 x 720 document width with no horizontal overflow. Thicker inner bezels consume only their own box and do not move the major regions. +- Colors and visual tokens: warm graphite surfaces (`#08090a` through `#22262a`), warm off-white text, and one restrained amber accent replace the previous blue-gray treatment. Header faceplate, session rail, recessed terminal, right service module, note well, and bottom telemetry rail have distinct surface treatments rather than sharing one repeated background. +- Image quality and asset fidelity: the theme uses the generated 1586 x 992 gunmetal texture at low opacity inside the recessed terminal and on the authentication dock. It remains sharp at the tested viewport, has no transparency halo or stretched subject, and is not used as a substitute for icons or controls. Existing WebSSH and Material Icons assets remain intact. +- Copy and content: existing product labels, host names, endpoint details, actions, Notes copy, and status text are unchanged. The implementation does not introduce the mockup's illustrative rack IDs because the selected concept was a visual direction and the user explicitly required the existing arrangement to remain intact. +- Icons and controls: existing icon semantics are retained. Buttons, tabs, inputs, host rows, dialogs, and mobile actions share the 2-4 px rack geometry and inset tactile treatment, while active state, success, warning, and destructive colors remain distinguishable. +- Accessibility and resilience: muted text remains covered by the existing 4.5:1 theme regression; keyboard focus uses the brighter amber focus token. Desktop and 390 x 844 mobile states have no horizontal overflow. The mobile action sheet, search, saved connection actions, Quick Connect dialog, and panel close action remain usable. + +### Primary interactions and runtime checks + +- Selected Rack Console through the authenticated Settings flow and verified persistence after returning to Workspaces. +- Filtered saved connections through the host search and restored the full list. +- Opened and closed Quick Connect, verified the dialog remained contained, and preserved existing form behavior. +- Opened the mobile More sheet at 390 x 844 and verified every visible navigation and session action remained contained. +- Compared Glass and Rack Console in the same authenticated state: header, session rail, main content, terminal grid, and right context workspace retain their major geometry and the host grid keeps the same track count. +- Browser console warnings and errors after the final desktop path: none. + +### Comparison history + +#### Pass 1 + +- P1: the right-panel close control inherited IBM Plex Mono and rendered the word `close` beyond its 34 px control instead of the Material Icons glyph. Fixed by restoring the Material Icons family and normal letter spacing specifically on `.context-workspace-close`. +- P2: the mobile More sheet retained the generic 14 px rounded container and looked unrelated to the rack controls around it. Fixed with the Rack Console faceplate, 3 px shell radius, inset highlight, and 2 px mobile control radii. + +#### Pass 2 + +- P2: the first rack header and session rail added outer borders that increased the combined header by 2 px and the session rail by 1 px. Fixed by retaining the existing single header divider and expressing the additional depth with inset shadows; the final header, toolbar, and main-content measurements match Glass exactly. +- P2: the visual hierarchy was initially too flat compared with the selected faceplate direction. Fixed with a restrained graphite header gradient while keeping the terminal texture, right service surface, and status rail materially distinct. + +#### Final pass + +- The normalized full-view and focused comparisons show the selected industrial direction in the existing WebSSH structure: equipment-like rails, square tactile controls, recessed work area, rack-style host rows, a separately treated service module, and segmented telemetry status. +- The source's illustrative corner screws, diagonal chassis cuts, and invented row-ID plates are intentionally not reproduced. They would add decorative assets or content that does not exist in the product and would conflict with the no-rearrangement constraint. +- Remaining P0/P1/P2 findings: none. +- Optional P3 polish: a future purpose-built nine-slice chassis asset could add subtle physical corner hardware if the product later adopts that ornament globally; it is not required for this theme to preserve cohesion or usability. + +final result: passed diff --git a/static/css/style.css b/static/css/style.css index 18d6faa9..94cd896e 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -542,6 +542,61 @@ body[data-theme="obsidian"] { --theme-background-opacity: 0.055; } +body[data-theme="rack-console"] { + --bg-primary: #08090a; + --bg-secondary: #101214; + --bg-tertiary: #171a1d; + --bg-hover: #22262a; + --bg-modal: rgba(10, 11, 12, 0.985); + --bg-gradient: linear-gradient(145deg, #08090a 0%, #151719 100%); + --bg-active: rgba(215, 132, 47, 0.14); + --text-primary: #eeece7; + --text-secondary: #bbb8b1; + --text-muted: #8f8c85; + --border-color: rgba(224, 220, 211, 0.15); + --border-hover: rgba(224, 220, 211, 0.29); + --accent-primary: #d7842f; + --accent-primary-glow: rgba(215, 132, 47, 0.2); + --accent-secondary: #9b968c; + --accent-tertiary: #68a47c; + --success-color: #6db486; + --warning-color: #d99a48; + --error-color: #da6d66; + --info-color: #9ba7b3; + --btn-primary-gradient-end: #aa5f1c; + --btn-primary-text: #0a0b0c; + --btn-primary-shadow: rgba(215, 132, 47, 0.16); + --btn-primary-shadow-hover: rgba(215, 132, 47, 0.26); + --accent-on-text: #0a0b0c; + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.54); + --shadow-md: 0 5px 14px rgba(0, 0, 0, 0.54); + --shadow-lg: 0 12px 30px rgba(0, 0, 0, 0.62); + --shadow-glow: 0 0 14px rgba(215, 132, 47, 0.12); + --term-background: #090a0b; + --term-foreground: #e7e4de; + --term-black: #202326; + --term-red: #d66f68; + --term-green: #70b58a; + --term-yellow: #d99a48; + --term-blue: #8ea4b8; + --term-magenta: #af8fa5; + --term-cyan: #81aaa6; + --term-white: #d5d2cb; + --term-bright-black: #55595d; + --term-bright-red: #e68a83; + --term-bright-green: #91caa5; + --term-bright-yellow: #e9b66d; + --term-bright-blue: #abc0d1; + --term-bright-magenta: #c8a9be; + --term-bright-cyan: #9dc3bf; + --term-bright-white: #ffffff; + --theme-background-image-source: url("../images/theme-backgrounds/rack-console-gunmetal.png?v=5373b8b77cc681b4"); + --theme-background-opacity: 0.085; + --theme-surface-shell: rgba(13, 14, 15, 0.92); + --theme-surface-modal: rgba(10, 11, 12, 0.94); + --theme-surface-card: rgba(18, 20, 22, 0.9); +} + body:is([data-theme="glass"], [data-theme="solar"], [data-theme="paper"], [data-theme="noir"], [data-theme="arctic-ice"], [data-theme="rose-gold"], [data-theme="obsidian"]) .main-content, body:is([data-theme="glass"], [data-theme="solar"], [data-theme="paper"], [data-theme="noir"], [data-theme="arctic-ice"], [data-theme="rose-gold"], [data-theme="obsidian"]) .terminal-pane { background-image: var(--theme-background-image); diff --git a/static/css/webssh-2.css b/static/css/webssh-2.css index 5cabb2f0..1da275ac 100644 --- a/static/css/webssh-2.css +++ b/static/css/webssh-2.css @@ -5316,3 +5316,513 @@ body[data-theme="paper"]:has(.auth-access-dock) { max-height: calc(100dvh - 68px); } } + +/* Rack Console: a component-level industrial system, not a palette swap. */ +body[data-theme="rack-console"] { + --ws2-radius-sm: 2px; + --ws2-radius: 3px; + --ws2-radius-lg: 4px; + --ws2-focus: #efa85e; + --ws2-shadow: 0 14px 34px rgb(0 0 0 / 58%); + --rack-canvas: #08090a; + --rack-faceplate: #101214; + --rack-faceplate-raised: #171a1d; + --rack-recess: #060708; + --rack-rule: rgb(224 220 211 / 16%); + --rack-rule-strong: rgb(224 220 211 / 30%); + --rack-highlight: rgb(255 255 255 / 5%); + color-scheme: dark; +} + +body[data-theme="rack-console"] :where( + .btn, + .form-control, + input[type="text"], + input[type="password"], + input[type="search"], + input[type="number"], + input[type="url"], + input[type="email"], + select, + textarea, + .modal-content, + .account-dropdown-header, + .admin-table-wrap, + .admin-settings-surface, + .admin-setting-row, + .manager-card +) { + border-radius: var(--ws2-radius-sm); +} + +body[data-theme="rack-console"] :where( + .btn, + .form-control, + input[type="text"], + input[type="password"], + input[type="search"], + input[type="number"], + input[type="url"], + input[type="email"], + select, + textarea +) { + box-shadow: + inset 0 1px 0 var(--rack-highlight), + 0 1px 0 rgb(0 0 0 / 72%); +} + +body[data-theme="rack-console"] .btn-primary { + border-color: #ed9f50; + background: #d7842f; + color: #090a0b; + box-shadow: + inset 0 1px 0 rgb(255 232 201 / 28%), + inset 0 -2px 0 rgb(90 43 9 / 34%); +} + +body[data-theme="rack-console"] .btn-primary:hover:not(:disabled) { + border-color: #f2b26f; + background: #e79543; +} + +body[data-theme="rack-console"] .btn-secondary { + border-color: var(--rack-rule-strong); + background: var(--rack-faceplate-raised); + color: var(--text-secondary); +} + +body[data-theme="rack-console"] .btn-secondary:hover:not(:disabled) { + border-color: color-mix(in srgb, var(--accent-primary) 58%, var(--rack-rule-strong)); + background: #202428; + color: var(--text-primary); +} + +body[data-theme="rack-console"] .header { + border: 0; + border-bottom-color: var(--rack-rule-strong); + border-bottom-style: solid; + border-bottom-width: 1px; + background-color: #0c0e10; + background-image: linear-gradient(180deg, #171a1d 0%, #0f1113 46%, #090a0b 100%); + box-shadow: + inset 0 1px 0 var(--rack-highlight), + inset 0 -1px 0 rgb(0 0 0 / 82%), + 0 3px 10px rgb(0 0 0 / 42%); +} + +body[data-theme="rack-console"] .app-brand-logo { + border-color: var(--rack-rule-strong); + border-radius: 2px; + background: #08090a; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + 0 1px 0 #000; +} + +body[data-theme="rack-console"] .header-divider, +body[data-theme="rack-console"] .tab-row-divider { + background: var(--rack-rule-strong); +} + +body[data-theme="rack-console"] .global-nav-item { + border-right: 1px solid var(--rack-rule); + color: var(--text-secondary); + font-family: var(--font-mono); + font-size: 11px; + font-weight: 600; + letter-spacing: 0.055em; + text-transform: uppercase; +} + +body[data-theme="rack-console"] .global-nav-item:first-child { + border-left: 1px solid var(--rack-rule); +} + +body[data-theme="rack-console"] .global-nav-item:hover, +body[data-theme="rack-console"] .global-nav-item.active { + background: #15181b; + color: var(--text-primary); +} + +body[data-theme="rack-console"] .global-nav-item::after { + right: 14px; + bottom: 5px; + left: 14px; + height: 2px; +} + +body[data-theme="rack-console"] .global-nav-item.active::after { + background: var(--accent-primary); + box-shadow: 0 1px 6px rgb(215 132 47 / 28%); +} + +body[data-theme="rack-console"] .account-btn-header { + border: 1px solid transparent !important; + border-radius: 2px; + font-family: var(--font-mono); + font-size: 11px; + letter-spacing: 0.04em; +} + +body[data-theme="rack-console"] .account-btn-header:hover, +body[data-theme="rack-console"] .account-btn-header[aria-expanded="true"] { + border-color: var(--rack-rule-strong) !important; + background: var(--rack-faceplate-raised) !important; +} + +body[data-theme="rack-console"] .session-tabs-row { + border-top-color: #000; + border-bottom: 0; + background: #090a0b; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + inset 0 -1px 0 #000; +} + +body[data-theme="rack-console"] :is( + .tab-row-actions .split-btn, + .tab-row-icon-btn, + .btn-new-tab, + .session-tab +) { + border: 1px solid var(--rack-rule-strong); + border-radius: 2px; + background: #111315; + color: var(--text-secondary); + box-shadow: + inset 0 1px 0 var(--rack-highlight), + inset 0 -2px 0 #050607; +} + +body[data-theme="rack-console"] :is( + .tab-row-actions .split-btn, + .tab-row-icon-btn, + .btn-new-tab, + .session-tab +):hover { + border-color: color-mix(in srgb, var(--accent-primary) 52%, var(--rack-rule-strong)); + background: #1b1e21; + color: var(--text-primary); +} + +body[data-theme="rack-console"] .tab-row-actions .split-btn.active, +body[data-theme="rack-console"] .session-tab.active { + border-color: var(--accent-primary); + background: #17191b; + color: var(--text-primary); + box-shadow: + inset 0 -2px 0 var(--accent-primary), + inset 0 1px 0 var(--rack-highlight); +} + +body[data-theme="rack-console"] .main-content, +body[data-theme="rack-console"] .workspace { + background: var(--rack-canvas); +} + +body[data-theme="rack-console"] .terminal-area { + background: #070809; +} + +body[data-theme="rack-console"] .terminal-grid { + border: 3px double var(--rack-rule-strong); + border-radius: 2px; + background: #060708; + box-shadow: + 0 0 0 1px #000, + 0 0 0 3px #15181a, + inset 0 0 0 1px var(--rack-highlight), + inset 0 0 26px rgb(0 0 0 / 62%); +} + +body[data-theme="rack-console"] .terminal-pane { + border-radius: 1px; + background-color: var(--term-background); + background-image: + linear-gradient(rgb(5 6 7 / 78%), rgb(10 11 12 / 82%)), + var(--theme-background-image); + background-position: center; + background-repeat: no-repeat; + background-size: auto, cover; +} + +body[data-theme="rack-console"] .terminal-pane.active { + border-color: rgb(215 132 47 / 54%); + box-shadow: + inset 0 0 0 1px rgb(215 132 47 / 13%), + inset 0 0 22px rgb(0 0 0 / 48%); +} + +body[data-theme="rack-console"] .pane-empty-icon { + color: var(--text-secondary); + opacity: 0.58; +} + +body[data-theme="rack-console"] .profile-launcher-title, +body[data-theme="rack-console"] .profile-launcher-section-title, +body[data-theme="rack-console"] .profile-launcher-name, +body[data-theme="rack-console"] .workspace-drawer-header h2, +body[data-theme="rack-console"] .notepad-title { + letter-spacing: 0.055em; + text-transform: uppercase; +} + +body[data-theme="rack-console"] .profile-launcher-section-title { + color: var(--text-secondary); + font-family: var(--font-mono); + font-size: 11px; + font-weight: 500; +} + +body[data-theme="rack-console"] .profile-launcher-search { + border: 2px solid #030405; + border-radius: 2px; + background: #0d0f11; + box-shadow: + inset 0 1px 5px rgb(0 0 0 / 72%), + 0 0 0 1px var(--rack-rule-strong); + font-family: var(--font-mono); +} + +body[data-theme="rack-console"] .profile-launcher-card { + border: 1px solid var(--rack-rule-strong); + border-left: 4px solid #373b3f; + border-radius: 2px; + background: #141719; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + inset 0 -1px 0 #050607, + 0 2px 4px rgb(0 0 0 / 28%); + transition: border-color 120ms ease, background-color 120ms ease; +} + +body[data-theme="rack-console"] .profile-launcher-card:hover { + border-color: var(--accent-primary); + border-left-color: var(--accent-primary); + background: #1a1d20; + transform: none; +} + +body[data-theme="rack-console"] .profile-launcher-card:focus-visible { + outline-color: #efa85e; +} + +body[data-theme="rack-console"] .profile-launcher-card.is-favorite { + border-left-color: color-mix(in srgb, var(--accent-primary) 72%, #373b3f); +} + +body[data-theme="rack-console"] .profile-launcher-name { + font-family: var(--font-mono); + font-size: 12px; + font-weight: 600; +} + +body[data-theme="rack-console"] .profile-launcher-action { + padding-left: 18px; + border-left: 1px solid var(--rack-rule); + font-family: var(--font-mono); + letter-spacing: 0.035em; + text-transform: uppercase; +} + +body[data-theme="rack-console"] .profile-launcher-favorite { + color: var(--accent-primary); +} + +body[data-theme="rack-console"] .context-workspace { + border-left: 3px double var(--rack-rule-strong); + background: #0d0f11; + box-shadow: + inset 1px 0 0 #000, + inset 0 0 0 1px var(--rack-highlight), + -8px 0 22px rgb(0 0 0 / 38%); +} + +body[data-theme="rack-console"] .context-workspace-header { + gap: 0; + padding: 5px 6px; + border-bottom-color: var(--rack-rule-strong); + background: #090a0b; + box-shadow: inset 0 -1px 0 #000; +} + +body[data-theme="rack-console"] .context-workspace-tabs { + gap: 3px; +} + +body[data-theme="rack-console"] .context-workspace-tab, +body[data-theme="rack-console"] .context-workspace-close { + border: 1px solid var(--rack-rule); + border-radius: 2px; + background: #131517; + color: var(--text-muted); + box-shadow: inset 0 1px 0 var(--rack-highlight); +} + +body[data-theme="rack-console"] .context-workspace-tab { + font-family: var(--font-mono); + letter-spacing: 0.025em; +} + +body[data-theme="rack-console"] .context-workspace-close { + font-family: "Material Icons"; + letter-spacing: normal; +} + +body[data-theme="rack-console"] .context-workspace-tab:hover:not(:disabled) { + border-color: var(--rack-rule-strong); + background: #1b1e21; + color: var(--text-primary); +} + +body[data-theme="rack-console"] .context-workspace-tab[aria-selected="true"] { + border-color: color-mix(in srgb, var(--accent-primary) 52%, var(--rack-rule)); + background: #1a1c1e; + color: var(--text-primary); +} + +body[data-theme="rack-console"] .context-workspace-tab[aria-selected="true"]::after { + right: 5px; + bottom: -1px; + left: 5px; + height: 3px; + background: var(--accent-primary); +} + +body[data-theme="rack-console"] .context-workspace .notepad-panel, +body[data-theme="rack-console"] .notepad-section { + background-color: #0c0e10; + background-image: none; +} + +body[data-theme="rack-console"] .workspace-drawer-header { + border-bottom-color: var(--rack-rule-strong); + background: #111315; + box-shadow: inset 0 1px 0 var(--rack-highlight); +} + +body[data-theme="rack-console"] .workspace-drawer-header p, +body[data-theme="rack-console"] .notepad-meta { + color: var(--text-muted); +} + +body[data-theme="rack-console"] .notepad-section { + padding: 14px; +} + +body[data-theme="rack-console"] .notepad-input { + border: 1px solid var(--rack-rule-strong); + border-radius: 2px; + background: #090a0b; + color: var(--text-secondary); + box-shadow: + inset 0 2px 8px rgb(0 0 0 / 74%), + 0 0 0 1px #050607; +} + +body[data-theme="rack-console"] .workspace-status-bar { + border: 1px solid #030405; + border-top-color: var(--rack-rule-strong); + background: #0c0e10; + color: var(--text-secondary); + box-shadow: + inset 0 1px 0 var(--rack-highlight), + inset 0 3px 8px rgb(0 0 0 / 48%); + font-family: var(--font-mono); + font-size: 10px; + letter-spacing: 0.025em; + text-transform: uppercase; +} + +body[data-theme="rack-console"] .workspace-status-bar > span { + min-height: 100%; + border-right-color: var(--rack-rule-strong); +} + +body[data-theme="rack-console"] .workspace-status-bar > span:last-child { + border: 1px solid var(--rack-rule); + background: #141719; + color: var(--accent-primary); + box-shadow: inset 0 1px 0 var(--rack-highlight); +} + +body[data-theme="rack-console"] :is( + .modal-content, + .account-dropdown-header, + .lang-dropdown-header, + .theme-dropdown-header, + .manager-card, + .admin-settings-surface, + .admin-table-wrap, + .admin-tabs +) { + border-color: var(--rack-rule-strong); + background-color: var(--rack-faceplate); + background-image: none; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + 0 8px 26px rgb(0 0 0 / 42%); +} + +body[data-theme="rack-console"] :is(.admin-tab, .connection-asset-nav-item, .command-workspace-tab) { + border-radius: 2px; +} + +body[data-theme="rack-console"] :is(.admin-tab, .connection-asset-nav-item, .command-workspace-tab).active { + box-shadow: inset 3px 0 0 var(--accent-primary); +} + +body[data-theme="rack-console"] :is(.auth-access-dock, .auth-card, .auth-form-panel) { + border-radius: 3px; +} + +body[data-theme="rack-console"] .auth-access-dock { + border-color: var(--rack-rule-strong); + background-color: #0c0e10; + background-image: + linear-gradient(rgb(8 9 10 / 88%), rgb(12 14 16 / 92%)), + var(--theme-background-image); + background-size: auto, cover; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + 0 18px 46px rgb(0 0 0 / 52%); +} + +@media (max-width: 767px) { + body[data-theme="rack-console"] .header-buttons, + body[data-theme="rack-console"] .header-buttons.is-open { + border-color: var(--rack-rule-strong); + border-radius: 3px; + background: #0c0e10; + box-shadow: + inset 0 1px 0 var(--rack-highlight), + 0 -18px 44px rgb(0 0 0 / 62%); + } + + body[data-theme="rack-console"] :is( + .mobile-session-summary, + .mobile-menu-btn, + .mobile-more-action, + .mobile-dock-item + ) { + border-radius: 2px; + } + + body[data-theme="rack-console"] .global-nav-item { + border-right: 0; + border-left: 0; + } + + body[data-theme="rack-console"] .profile-launcher-card { + min-height: 0; + padding: 12px; + } + + body[data-theme="rack-console"] .profile-launcher-action { + padding-top: 7px; + padding-left: 0; + border-top: 1px solid var(--rack-rule); + border-left: 0; + } +} diff --git a/static/images/theme-backgrounds/rack-console-gunmetal.png b/static/images/theme-backgrounds/rack-console-gunmetal.png new file mode 100644 index 00000000..40cbddf9 Binary files /dev/null and b/static/images/theme-backgrounds/rack-console-gunmetal.png differ diff --git a/static/js/theme-preference.js b/static/js/theme-preference.js index 8888d9ed..be64efe0 100644 --- a/static/js/theme-preference.js +++ b/static/js/theme-preference.js @@ -12,7 +12,8 @@ 'rose-gold', 'cyberpunk-neon', 'emerald-matrix', - 'obsidian' + 'obsidian', + 'rack-console' ]); function isValid(themeId) { diff --git a/templates/index.html b/templates/index.html index 7b702f57..ea6cab53 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1480,7 +1480,8 @@
Choose the visual theme used across workspaces and settings.