From 62299c9714e6a4df6e442d58467ef4734ddc5613 Mon Sep 17 00:00:00 2001 From: Evan Date: Sat, 25 Apr 2026 13:53:21 -0600 Subject: [PATCH] standardize UI colors to fit brand guidelines (#3754) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description: We have brand colors: Screenshot 2026-04-25 at 12 52 29 PM So update the homepage & in-game UI to use those colors: Screenshot 2026-04-25 at 12 51
06 PM Also updated buttons to use the o-button element ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: evan --- src/client/AccountModal.ts | 27 ++--- src/client/FlagInput.ts | 2 +- src/client/FlagInputModal.ts | 11 +- src/client/GameModeSelector.ts | 26 ++--- src/client/GameStartingModal.ts | 2 +- src/client/HelpModal.ts | 2 +- src/client/HostLobbyModal.ts | 15 +-- src/client/JoinLobbyModal.ts | 22 ++-- src/client/LanguageModal.ts | 2 +- src/client/PatternInput.ts | 4 +- src/client/SinglePlayerModal.ts | 11 +- src/client/Store.ts | 6 +- src/client/TerritoryPatternsModal.ts | 11 +- src/client/TroubleshootingModal.ts | 10 +- src/client/UserSettingModal.ts | 4 +- src/client/components/DesktopNavBar.ts | 29 +++-- src/client/components/FluentSlider.ts | 6 +- src/client/components/GameConfigSettings.ts | 6 +- .../components/IOSAddToHomeScreenBanner.ts | 12 +- src/client/components/LobbyPlayerView.ts | 4 +- src/client/components/MobileNavBar.ts | 2 +- src/client/components/NewsBox.ts | 2 +- src/client/components/PlayPage.ts | 6 +- src/client/components/RankedModal.ts | 2 +- src/client/components/ToggleInputCard.ts | 4 +- .../components/baseComponents/Button.ts | 104 +++++++++++++----- .../baseComponents/ranking/PlayerRow.ts | 2 +- .../baseComponents/ranking/RankingControls.ts | 2 +- .../baseComponents/setting/SettingSlider.ts | 8 +- .../baseComponents/stats/GameList.ts | 2 +- src/client/components/map/MapDisplay.ts | 2 +- src/client/components/map/MapPicker.ts | 6 +- src/client/graphics/layers/AttacksDisplay.ts | 12 +- src/client/graphics/layers/ControlPanel.ts | 12 +- .../graphics/layers/PlayerInfoOverlay.ts | 18 +-- src/client/graphics/layers/ReplayPanel.ts | 2 +- src/client/graphics/layers/SpawnTimer.ts | 7 +- src/client/graphics/layers/WinModal.ts | 35 +++--- src/client/styles.css | 33 +++++- src/client/styles/components/button.css | 88 --------------- src/client/styles/core/variables.css | 21 ++-- src/client/styles/layout/header.css | 2 +- 42 files changed, 289 insertions(+), 295 deletions(-) delete mode 100644 src/client/styles/components/button.css diff --git a/src/client/AccountModal.ts b/src/client/AccountModal.ts index a1375f12d..6992a47e4 100644 --- a/src/client/AccountModal.ts +++ b/src/client/AccountModal.ts @@ -241,12 +241,12 @@ export class AccountModal extends BaseModal { private renderLogoutButton(): TemplateResult { return html` - + `; } @@ -318,19 +318,20 @@ export class AccountModal extends BaseModal { name="email" .value="${this.email}" @input="${this.handleEmailInput}" - class="w-full pl-4 pr-12 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/20 focus:outline-none focus:ring-2 focus:ring-blue-500/50 focus:border-blue-500/50 transition-all font-medium hover:bg-white/10" + class="w-full pl-4 pr-12 py-3 bg-white/5 border border-white/10 rounded-xl text-white placeholder-white/20 focus:outline-none focus:ring-2 focus:ring-malibu-blue/50 focus:border-malibu-blue/50 transition-all font-medium hover:bg-white/10" placeholder="${translateText( "account_modal.email_placeholder", )}" required /> - + diff --git a/src/client/FlagInput.ts b/src/client/FlagInput.ts index c156dbc53..423c8608a 100644 --- a/src/client/FlagInput.ts +++ b/src/client/FlagInput.ts @@ -73,7 +73,7 @@ export class FlagInput extends LitElement { return html` + >
@@ -128,19 +128,19 @@ export class GameModeSelector extends LitElement { ${this.renderSmallActionCard( translateText("main.create"), this.openHostLobby, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", )} ${!crazyGamesSDK.isOnCrazyGames() ? this.renderSmallActionCard( translateText("mode_selector.ranked_title"), this.openRankedMenu, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", ) : html``} ${this.renderSmallActionCard( translateText("main.join"), this.openJoinLobby, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", )}
@@ -192,7 +192,7 @@ export class GameModeSelector extends LitElement { ${this.renderSmallActionCard( translateText("main.solo"), this.openSinglePlayerModal, - "bg-[#0073b7] hover:bg-sky-500 active:bg-sky-700", + "bg-malibu-blue hover:bg-aquarius active:bg-malibu-blue/80", )} @@ -200,19 +200,19 @@ export class GameModeSelector extends LitElement { ${this.renderSmallActionCard( translateText("main.create"), this.openHostLobby, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", )} ${!crazyGamesSDK.isOnCrazyGames() ? this.renderSmallActionCard( translateText("mode_selector.ranked_title"), this.openRankedMenu, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", ) : html``} ${this.renderSmallActionCard( translateText("main.join"), this.openJoinLobby, - "bg-slate-600 hover:bg-slate-500 active:bg-slate-700", + "bg-surface hover:brightness-[1.08] active:brightness-[0.95] hover:scale-105", )} @@ -253,7 +253,7 @@ export class GameModeSelector extends LitElement { return html` @@ -299,7 +299,7 @@ export class GameModeSelector extends LitElement { return html` + `} + @click=${this.pasteFromClipboard} + > diff --git a/src/client/LanguageModal.ts b/src/client/LanguageModal.ts index 4fd2651e4..1bc9b3da0 100644 --- a/src/client/LanguageModal.ts +++ b/src/client/LanguageModal.ts @@ -58,7 +58,7 @@ export class LanguageModal extends BaseModal { buttonClasses += " animate-pulse font-bold text-white border-2 border-dashed border-cyan-400 shadow-[0_0_15px_rgba(34,211,238,0.2)] bg-gradient-to-r from-red-600 via-yellow-600 via-green-600 via-blue-600 to-purple-600"; } else if (isActive) { - buttonClasses += " bg-blue-500/20 border-blue-500/50"; + buttonClasses += " bg-malibu-blue/20 border-malibu-blue/50"; } else { buttonClasses += " bg-white/5 border-white/10 hover:bg-white/10 hover:border-white/20"; diff --git a/src/client/PatternInput.ts b/src/client/PatternInput.ts index 398158eb8..d36cf6a8e 100644 --- a/src/client/PatternInput.ts +++ b/src/client/PatternInput.ts @@ -111,7 +111,7 @@ export class PatternInput extends LitElement { return html` + > `; diff --git a/src/client/Store.ts b/src/client/Store.ts index 39ee0dc03..f4e80b444 100644 --- a/src/client/Store.ts +++ b/src/client/Store.ts @@ -52,7 +52,7 @@ export class StoreModal extends BaseModal { + >
/ ${translateText("troubleshooting.title")} - + >
`, onBack: () => this.close(), ariaLabel: translateText("common.back"), diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index 30da04355..1d599ad0d 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -335,7 +335,7 @@ export class UserSettingModal extends BaseModal { @@ -77,7 +82,7 @@ export class DesktopNavBar extends LitElement {
`; } diff --git a/src/client/components/baseComponents/ranking/PlayerRow.ts b/src/client/components/baseComponents/ranking/PlayerRow.ts index b954de0e3..9276defe2 100644 --- a/src/client/components/baseComponents/ranking/PlayerRow.ts +++ b/src/client/components/baseComponents/ranking/PlayerRow.ts @@ -240,7 +240,7 @@ export class PlayerRow extends LitElement { private renderTag(tag: string) { return html`
${tag}
diff --git a/src/client/components/baseComponents/ranking/RankingControls.ts b/src/client/components/baseComponents/ranking/RankingControls.ts index 527681c7f..13cd7f33a 100644 --- a/src/client/components/baseComponents/ranking/RankingControls.ts +++ b/src/client/components/baseComponents/ranking/RankingControls.ts @@ -64,7 +64,7 @@ export class RankingControls extends LitElement { return html`
@@ -319,7 +319,7 @@ export class AttacksDisplay extends LitElement implements Layer { >${renderTroops(landAttack.troops)} ${translateText("help_modal.ui_wilderness")}`, className: - "text-left text-sky-400 inline-flex items-center gap-0.5 lg:gap-1 min-w-0", + "text-left text-aquarius inline-flex items-center gap-0.5 lg:gap-1 min-w-0", translate: false, })} ${!landAttack.retreating @@ -329,7 +329,7 @@ export class AttacksDisplay extends LitElement implements Layer { className: "ml-auto text-left shrink-0", disabled: landAttack.retreating, }) - : html`(${translateText("events_display.retreating")}...)`} @@ -374,7 +374,7 @@ export class AttacksDisplay extends LitElement implements Layer { >`, onClick: () => this.eventBus.emit(new GoToUnitEvent(boat)), className: - "text-left text-blue-400 inline-flex items-center gap-0.5 lg:gap-1 min-w-0", + "text-left text-aquarius inline-flex items-center gap-0.5 lg:gap-1 min-w-0", translate: false, })} ${!boat.retreating() @@ -384,7 +384,7 @@ export class AttacksDisplay extends LitElement implements Layer { className: "ml-auto text-left shrink-0", disabled: boat.retreating(), }) - : html`(${translateText("events_display.retreating")}...)`} diff --git a/src/client/graphics/layers/ControlPanel.ts b/src/client/graphics/layers/ControlPanel.ts index f5ae86a93..1bc72d3f5 100644 --- a/src/client/graphics/layers/ControlPanel.ts +++ b/src/client/graphics/layers/ControlPanel.ts @@ -158,13 +158,13 @@ export class ControlPanel extends LitElement implements Layer {
${greenPercent > 0 ? html`
` : ""} ${orangePercent > 0 ? html`
` : ""} @@ -213,13 +213,13 @@ export class ControlPanel extends LitElement implements Layer {
${greenPercent > 0 ? html`
` : ""} ${orangePercent > 0 ? html`
` : ""} @@ -326,7 +326,7 @@ export class ControlPanel extends LitElement implements Layer { .value=${String(Math.round(this.attackRatio * 100))} @input=${(e: Event) => this.handleRatioSliderInput(e)} @pointerup=${(e: Event) => this.handleRatioSliderPointerUp(e)} - class="flex-1 h-1.5 accent-blue-500 cursor-pointer" + class="flex-1 h-1.5 accent-aquarius cursor-pointer" />
`; @@ -373,7 +373,7 @@ export class ControlPanel extends LitElement implements Layer { .value=${String(Math.round(this.attackRatio * 100))} @input=${(e: Event) => this.handleRatioSliderInput(e)} @pointerup=${(e: Event) => this.handleRatioSliderPointerUp(e)} - class="w-full h-1.5 accent-blue-500 cursor-pointer" + class="w-full h-1.5 accent-aquarius cursor-pointer" />
diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts index 3d5e55ad0..515ad5edb 100644 --- a/src/client/graphics/layers/PlayerInfoOverlay.ts +++ b/src/client/graphics/layers/PlayerInfoOverlay.ts @@ -322,18 +322,18 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
${renderTroops(attackingTroops)} 0 ? html`
` : ""} diff --git a/src/client/graphics/layers/ReplayPanel.ts b/src/client/graphics/layers/ReplayPanel.ts index fdef51510..ea48bbb60 100644 --- a/src/client/graphics/layers/ReplayPanel.ts +++ b/src/client/graphics/layers/ReplayPanel.ts @@ -98,7 +98,7 @@ export class ReplayPanel extends LitElement implements Layer { private renderSpeedButton(value: ReplaySpeedMultiplier, label: string) { const backgroundColor = - this._replaySpeedMultiplier === value ? "bg-blue-400" : ""; + this._replaySpeedMultiplier === value ? "bg-malibu-blue" : ""; return html` + > ${this.isRankedGame ? html` - + > ` : null} -
`; diff --git a/src/client/styles.css b/src/client/styles.css index 08bbc3ba6..3e1db2116 100644 --- a/src/client/styles.css +++ b/src/client/styles.css @@ -5,7 +5,32 @@ @theme { --default-ring-width: 3px; - --default-ring-color: var(text-[#0073b7]); + --default-ring-color: var(--color-malibu-blue); + + /* Openfront.io brand palette — see Openfront_Brand_Guidelines.pdf §4 */ + --color-malibu-blue: #0084d1; + --color-aquarius: #3fa9f5; + --color-dawn-blue: #cccccc; + --color-bright-white: #ffffff; + + /* Openfront Masters sub-brand */ + --color-cyber-yellow: #ffd700; + --color-limestone: #999999; + + /* Background & decorative — not for standalone UI use */ + --color-deep-navy: #0a1628; + --color-hex-cyan: #00c8ff; + --color-frame-orange: #f97316; + + /* App-specific surface colors */ + --color-surface: #0a1628; + + --shadow-malibu-blue: 0 0 15px rgba(0, 132, 209, 0.2); + --shadow-malibu-blue-soft: 0 0 12px rgba(0, 132, 209, 0.2); + --shadow-malibu-blue-strong: 0 0 15px rgba(0, 132, 209, 0.3); + --shadow-malibu-blue-pill: 0 0 6px rgba(0, 132, 209, 0.35); + --shadow-malibu-blue-ring-sm: 0 0 0 4px rgba(0, 132, 209, 0.2); + --shadow-malibu-blue-ring-lg: 0 0 0 6px rgba(0, 132, 209, 0.3); } @layer base { @@ -113,7 +138,7 @@ body { padding: 15px 20px; font-size: 16px; cursor: pointer; - background-color: #0073b7; + background-color: var(--color-malibu-blue); color: white; border: none; border-radius: 8px; @@ -123,7 +148,7 @@ body { } .start-game-button:not(:disabled):hover { - background-color: #0073b7; + background-color: var(--color-aquarius); } .start-game-button:disabled { @@ -580,7 +605,7 @@ label.option-card:hover { /* News Button Notification */ news-button .active button { position: relative; - border-color: #0073b7 !important; + border-color: var(--color-malibu-blue) !important; border-width: 2px !important; box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.5), diff --git a/src/client/styles/components/button.css b/src/client/styles/components/button.css deleted file mode 100644 index 5ee0eb2a1..000000000 --- a/src/client/styles/components/button.css +++ /dev/null @@ -1,88 +0,0 @@ -.c-button { - background: var(--primaryColor); - color: #fff; - cursor: pointer; - outline: none; - display: inline-block; - font-size: 16px; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.05em; - border: 1px solid transparent; - text-align: center; - padding: 0.8rem 1rem; - border-radius: 0.75rem; - transition: var(--transition); - - @media (min-width: 1024px) { - font-size: 18px; - } -} - -.c-button:hover, -.c-button:active, -.c-button:focus { - background: var(--primaryColorHover); - transition: var(--transition); - transform: translateY(-1px); -} - -.c-button:disabled { - background: var(--primaryColorDisabled); - opacity: 0.7; - cursor: not-allowed; - transition: var(--transition); -} - -.c-button--secondary { - background: var(--secondaryColor); - color: var(--fontColor); -} - -.c-button--secondary:hover, -.c-button--secondary:active, -.c-button--secondary:focus { - background: var(--secondaryColorHover); -} - -.c-button--block { - display: block; - width: 100%; -} - -.c-button--blockDesktop { - display: block; - width: 100%; - - @media (min-width: 1024px) { - width: auto; - margin: 0 auto; - } -} - -.dark .c-button { - background: var(--primaryColorDark); - color: var(--fontColorLight); -} - -.dark .c-button:hover, -.dark .c-button:active, -.dark .c-button:focus { - background: var(--primaryColorHoverDark); -} - -.dark .c-button:disabled { - background: var(--primaryColorDisabledDark); - opacity: 0.7; -} - -.dark .c-button--secondary { - background: var(--secondaryColorDark); - color: var(--fontColorDark); -} - -.dark .c-button--secondary:hover, -.dark .c-button--secondary:active, -.dark .c-button--secondary:focus { - background: var(--secondaryColorHoverDark); -} diff --git a/src/client/styles/core/variables.css b/src/client/styles/core/variables.css index 6ed17b5d6..eb803871b 100644 --- a/src/client/styles/core/variables.css +++ b/src/client/styles/core/variables.css @@ -7,33 +7,26 @@ --fontColor: #202020; --fontColorLight: #fff; - /* Palette: Deep French Blue / Muted Cyan / Black / Forest Teal */ - --frenchBlue: #1f3a70; /* Deeper French Blue */ - --cyanBlue: #0f6ca3; /* Muted Cyan secondary */ - --tealAccent: #1f6c5a; /* Darker Teal accent */ - - --primaryColor: var(--frenchBlue); - --primaryColorHover: var(--tealAccent); + --primaryColorHover: var(--color-malibu-blue); --primaryColorDisabled: linear-gradient( to right, rgb(74, 74, 74), rgb(61, 61, 61) ); - --secondaryColor: var(--cyanBlue); - --secondaryColorHover: var(--cyanBlue); + --secondaryColor: var(--color-malibu-blue); + --secondaryColorHover: var(--color-aquarius); --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - --primaryColorDark: var(--frenchBlue); - --primaryColorHoverDark: var(--tealAccent); + --primaryColorHoverDark: var(--color-malibu-blue); --primaryColorDisabledDark: #4b5563; - --secondaryColorDark: var(--tealAccent); - --secondaryColorHoverDark: var(--frenchBlue); + --secondaryColorDark: var(--color-malibu-blue); + --secondaryColorHoverDark: var(--color-aquarius); --fontColorDark: #f3f4f6; /* Achievements */ --medal-easy: #cd7f32; --medal-medium: #c0c0c0; - --medal-hard: #ffd700; + --medal-hard: var(--color-cyber-yellow); --medal-impossible: #d32f2f; --medal-custom: #2196f3; } diff --git a/src/client/styles/layout/header.css b/src/client/styles/layout/header.css index e753d12ec..5d2ada7c5 100644 --- a/src/client/styles/layout/header.css +++ b/src/client/styles/layout/header.css @@ -30,6 +30,6 @@ } .l-header__highlightText { - color: #0073b7; + color: var(--color-malibu-blue); font-weight: 700; }