diff --git a/IWantToHeal-Thor-v1.1.5.apk b/IWantToHeal-Thor-v1.1.5.apk new file mode 100644 index 0000000..730766c Binary files /dev/null and b/IWantToHeal-Thor-v1.1.5.apk differ diff --git a/android/app/build.gradle b/android/app/build.gradle index 57eb09e..4206613 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -7,8 +7,8 @@ android { applicationId "com.warren.iwanttoheal" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 83 - versionName "1.1.4" + versionCode 84 + versionName "1.1.5" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" aaptOptions { // Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps. diff --git a/android/app/src/main/java/com/warren/iwanttoheal/AndroidDisplayPerformance.java b/android/app/src/main/java/com/warren/iwanttoheal/AndroidDisplayPerformance.java new file mode 100644 index 0000000..e3727b6 --- /dev/null +++ b/android/app/src/main/java/com/warren/iwanttoheal/AndroidDisplayPerformance.java @@ -0,0 +1,51 @@ +package com.warren.iwanttoheal; + +import android.view.Display; +import android.view.Window; +import android.view.WindowManager; + +final class AndroidDisplayPerformance { + + private static final float TARGET_REFRESH_RATE = 60.0f; + + private AndroidDisplayPerformance() {} + + static void preferBatteryRefreshRate(Window window, Display display) { + if (window == null || display == null) return; + Display.Mode currentMode = display.getMode(); + Display.Mode selectedMode = closestBatteryMode(display, currentMode); + if (selectedMode == null) return; + + WindowManager.LayoutParams attributes = window.getAttributes(); + if (attributes.preferredDisplayModeId == selectedMode.getModeId()) return; + attributes.preferredDisplayModeId = selectedMode.getModeId(); + window.setAttributes(attributes); + } + + private static Display.Mode closestBatteryMode(Display display, Display.Mode currentMode) { + Display.Mode selectedMode = null; + float selectedScore = Float.MAX_VALUE; + + for (Display.Mode mode : display.getSupportedModes()) { + if ( + currentMode != null + && ( + mode.getPhysicalWidth() != currentMode.getPhysicalWidth() + || mode.getPhysicalHeight() != currentMode.getPhysicalHeight() + ) + ) { + continue; + } + + float refreshRate = mode.getRefreshRate(); + float score = Math.abs(refreshRate - TARGET_REFRESH_RATE); + if (refreshRate > TARGET_REFRESH_RATE + 0.5f) score += 1000.0f; + if (score < selectedScore) { + selectedMode = mode; + selectedScore = score; + } + } + + return selectedMode; + } +} diff --git a/android/app/src/main/java/com/warren/iwanttoheal/ControllerBridgeActivity.java b/android/app/src/main/java/com/warren/iwanttoheal/ControllerBridgeActivity.java index 55b2023..3949d12 100644 --- a/android/app/src/main/java/com/warren/iwanttoheal/ControllerBridgeActivity.java +++ b/android/app/src/main/java/com/warren/iwanttoheal/ControllerBridgeActivity.java @@ -1,6 +1,10 @@ package com.warren.iwanttoheal; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.view.KeyEvent; @@ -12,15 +16,22 @@ import java.io.File; public abstract class ControllerBridgeActivity extends BridgeActivity { public static final String EXTRA_INITIAL_URL = "com.warren.iwanttoheal.INITIAL_URL"; + private static final String PREFS_NAME = "com.warren.iwanttoheal.performance"; + private static final String CACHE_CLEARED_VERSION_KEY = "webview_cache_cleared_version"; private static final long DPAD_THROTTLE_MS = 220; private long lastDpadDispatchAt = 0; @Override public void onCreate(Bundle savedInstanceState) { - clearWebViewServiceWorkers(); + boolean shouldClearWebViewCache = shouldClearWebViewCacheForCurrentVersion(); + if (shouldClearWebViewCache) clearWebViewServiceWorkers(); super.onCreate(savedInstanceState); + AndroidDisplayPerformance.preferBatteryRefreshRate(getWindow(), getWindowManager().getDefaultDisplay()); if (bridge != null) { - bridge.getWebView().clearCache(true); + if (shouldClearWebViewCache) { + bridge.getWebView().clearCache(true); + markWebViewCacheClearedForCurrentVersion(); + } } loadIntentUrl(); } @@ -35,7 +46,13 @@ public abstract class ControllerBridgeActivity extends BridgeActivity { @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); - if (hasFocus) enableImmersiveMode(); + if (hasFocus) { + enableImmersiveMode(); + AndroidDisplayPerformance.preferBatteryRefreshRate( + getWindow(), + getWindowManager().getDefaultDisplay() + ); + } } @Override @@ -74,6 +91,34 @@ public abstract class ControllerBridgeActivity extends BridgeActivity { deleteIfExists(new File(webViewData, "Service Worker")); } + private boolean shouldClearWebViewCacheForCurrentVersion() { + return performancePreferences().getLong(CACHE_CLEARED_VERSION_KEY, -1L) + != currentVersionCode(); + } + + private void markWebViewCacheClearedForCurrentVersion() { + performancePreferences() + .edit() + .putLong(CACHE_CLEARED_VERSION_KEY, currentVersionCode()) + .apply(); + } + + private SharedPreferences performancePreferences() { + return getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + } + + private long currentVersionCode() { + try { + PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return packageInfo.getLongVersionCode(); + } + return packageInfo.versionCode; + } catch (PackageManager.NameNotFoundException exception) { + return -1L; + } + } + private void deleteIfExists(File file) { if (!file.exists()) return; if (file.isDirectory()) { diff --git a/android/app/src/main/java/com/warren/iwanttoheal/DualScreenPlugin.java b/android/app/src/main/java/com/warren/iwanttoheal/DualScreenPlugin.java index 111de01..d3f6542 100644 --- a/android/app/src/main/java/com/warren/iwanttoheal/DualScreenPlugin.java +++ b/android/app/src/main/java/com/warren/iwanttoheal/DualScreenPlugin.java @@ -259,9 +259,11 @@ public class DualScreenPlugin extends Plugin { private final class TopDisplayPresentation extends Presentation { private final String initialUrl; + private final Display display; TopDisplayPresentation(Context context, Display display, String initialUrl) { super(context, display); + this.display = display; this.initialUrl = initialUrl; } @@ -277,6 +279,7 @@ public class DualScreenPlugin extends Plugin { | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE ); + AndroidDisplayPerformance.preferBatteryRefreshRate(getWindow(), display); FrameLayout container = new FrameLayout(getContext()); container.setBackgroundColor(Color.BLACK); diff --git a/src/App.css b/src/App.css index 0e0a354..ae7b2eb 100644 --- a/src/App.css +++ b/src/App.css @@ -1,5 +1,3 @@ -@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap'); - :root { --ink: #f4eed8; --muted: #a89f87; @@ -12,6 +10,24 @@ --green: #3f9a66; --blue: #3477bb; --purple: #8e68c4; + --body-font: ui-monospace, 'Roboto Mono', 'Droid Sans Mono', Consolas, monospace; + --pixel-font: ui-monospace, 'Roboto Mono', 'Droid Sans Mono', Consolas, monospace; +} + +.combat-touch-lock-status { + background: #101216; + border: 2px solid #d9b55a; + bottom: 18px; + box-shadow: 4px 4px 0 #050609; + color: #fff7df; + font-family: var(--pixel-font); + font-size: 9px; + left: 50%; + padding: 10px 12px; + pointer-events: none; + position: fixed; + transform: translateX(-50%); + z-index: 80; } * { @@ -69,7 +85,7 @@ textarea:focus-visible, } .binding-tabs button { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 48px; } @@ -108,7 +124,7 @@ textarea:focus-visible, align-items: center; color: var(--gold); display: inline-flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; justify-content: flex-end; min-height: 25px; @@ -210,7 +226,7 @@ textarea:focus-visible, .controller-icon-options > span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; padding-left: 7px; } @@ -218,7 +234,7 @@ textarea:focus-visible, .controller-icon-options button { align-items: center; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 8px; justify-content: center; @@ -287,7 +303,7 @@ textarea:focus-visible, .android-display-list strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -305,7 +321,7 @@ textarea:focus-visible, border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; min-height: 44px; outline: 2px solid #4b4855; @@ -384,7 +400,7 @@ textarea:focus-visible, } .dual-startup-prompt button { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 48px; padding: 10px 14px; @@ -431,7 +447,7 @@ textarea:focus-visible, } .controller-keyboard-grid button { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; min-height: 43px; } @@ -456,7 +472,7 @@ textarea:focus-visible, align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 6px; gap: 18px; justify-content: flex-end; @@ -493,7 +509,7 @@ textarea:focus-visible, .dual-bottom-status strong { color: var(--red-bright); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; } @@ -587,7 +603,7 @@ textarea:focus-visible, .dual-top-progress > span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -664,7 +680,7 @@ textarea:focus-visible, border: 2px solid #3a3944; border-radius: 6px; color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 14px; font-weight: 600; margin-top: 10px; @@ -675,7 +691,7 @@ textarea:focus-visible, } .dual-top-member .member-target-key kbd { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: inherit; } @@ -764,7 +780,7 @@ textarea:focus-visible, align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 12px; justify-content: flex-end; @@ -805,7 +821,43 @@ textarea:focus-visible, .dual-top-main.pvp-roguelike-dual-top .dual-top-enemy { align-items: center; display: grid; - grid-template-columns: 84px minmax(0, 1fr) minmax(96px, 108px); + grid-template-columns: 58px minmax(0, 1fr) minmax(142px, 152px); + min-height: 84px; + padding: 8px 10px; +} + +.dual-top-main.pvp-roguelike-dual-top .enemy-portrait { + flex-basis: auto; + height: 58px; +} + +.dual-top-main.pvp-roguelike-dual-top .enemy-info p { + display: none; +} + +.dual-top-main.pvp-roguelike-dual-top .bar-label { + font-size: 17px; +} + +.dual-top-main.pvp-roguelike-dual-top .dual-top-enemy .bar { + height: 18px; +} + +.dual-top-main.pvp-roguelike-dual-top .enemy-info .dual-top-resource { + justify-self: start; + margin-top: 5px; + min-width: 0; + width: min(220px, 100%); +} + +.dual-top-main.pvp-roguelike-dual-top .enemy-info .dual-top-resource strong { + font-size: 7px; + margin-bottom: 4px; + text-align: left; +} + +.dual-top-main.pvp-roguelike-dual-top .enemy-info .dual-top-resource .bar { + height: 8px; } .dual-top-main .dual-top-party-grid { @@ -842,11 +894,18 @@ textarea:focus-visible, .dual-top-cooldowns { align-content: center; display: grid; - gap: 6px; - grid-template-columns: repeat(2, 48px); + gap: 4px; + grid-template-columns: repeat(2, 46px); justify-content: end; } +.dual-top-side-status { + align-items: end; + display: grid; + gap: 4px; + justify-items: end; +} + .dual-top-spell { align-items: center; background: #20232c; @@ -862,8 +921,8 @@ textarea:focus-visible, } .dual-top-cooldowns .dual-top-spell { - height: 38px; - width: 48px; + height: 30px; + width: 46px; } .dual-top-spell:not(:disabled) { @@ -882,9 +941,9 @@ textarea:focus-visible, } .dual-top-cooldowns .dual-top-spell .spell-icon { - font-size: 16px; - height: 26px; - width: 26px; + font-size: 14px; + height: 22px; + width: 22px; } .dual-top-spell > i { @@ -899,25 +958,40 @@ textarea:focus-visible, .dual-top-spell > small { color: #fff4a8; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 10px; position: absolute; } .dual-top-cooldowns .dual-top-spell > small { - font-size: 8px; + font-size: 7px; } .dual-top-resource { align-self: center; color: #82bfff; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; justify-self: end; min-width: 220px; width: min(280px, 100%); } +.dual-top-side-status .dual-top-resource { + min-width: 0; + width: 100%; +} + +.dual-top-side-status .dual-top-resource strong { + font-size: 7px; + margin-bottom: 4px; + text-align: right; +} + +.dual-top-side-status .dual-top-resource .bar { + height: 8px; +} + .dual-top-resource strong { display: block; margin-bottom: 6px; @@ -1072,7 +1146,7 @@ textarea:focus-visible, .dual-controls-progress { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -1091,7 +1165,7 @@ textarea:focus-visible, .dual-controls-mana > span { color: var(--muted); display: block; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; margin-bottom: 6px; text-align: right; @@ -1394,7 +1468,7 @@ textarea:focus-visible, .auth-brand h1 { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: clamp(25px, 4vw, 45px); line-height: 1.3; margin: 10px 0 22px; @@ -1418,7 +1492,7 @@ textarea:focus-visible, border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; min-height: 48px; outline: 2px solid #3e3d47; @@ -1438,7 +1512,7 @@ textarea:focus-visible, .auth-card label { color: var(--muted); display: grid; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 8px; text-transform: uppercase; @@ -1476,7 +1550,7 @@ textarea:focus-visible, align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 10px; margin: 20px 0; @@ -1522,7 +1596,7 @@ textarea:focus-visible, background: var(--gold); border: 2px solid #090a0d; color: #19150e; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; outline: 2px solid #816630; } @@ -1537,7 +1611,7 @@ textarea:focus-visible, border: 0; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 6px; padding: 3px 0; } @@ -1585,7 +1659,7 @@ textarea:focus-visible, } .brand-button strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: clamp(10px, 1.3vw, 14px); } @@ -1598,7 +1672,7 @@ textarea:focus-visible, .character-summary span, .character-summary small { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -1619,6 +1693,7 @@ textarea:focus-visible, .header-xp { background: #090a0d; height: 5px; + overflow: hidden; width: 100px; } @@ -1628,6 +1703,9 @@ textarea:focus-visible, box-shadow: inset 0 3px #b08bdf; display: block; height: 100%; + transition: transform 180ms linear; + width: 100%; + will-change: transform; } h1, @@ -1639,7 +1717,7 @@ p { h1, h2 { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); line-height: 1.45; } @@ -1653,7 +1731,7 @@ h2 { .eyebrow { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; letter-spacing: 1px; margin-bottom: 8px; @@ -1753,7 +1831,7 @@ h2 { .progress-summary > span, .progress-summary > small { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -1863,7 +1941,7 @@ h2 { color: var(--gold); display: flex; flex: 0 0 58px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 19px; height: 58px; justify-content: center; @@ -1875,7 +1953,7 @@ h2 { } .menu-card strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 11px; margin-bottom: 9px; } @@ -1924,7 +2002,7 @@ h2 { border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 42px; outline: 2px solid #41404a; @@ -2060,7 +2138,7 @@ h2 { border: 3px solid #0a0b0e; color: #ef7b66; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 20px; height: 92px; justify-content: center; @@ -2193,7 +2271,7 @@ h2 { .tier-grid strong, .activity-card strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -3208,7 +3286,7 @@ h2 { .activity-select > span, .loot-toolbar span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; text-transform: uppercase; } @@ -3219,7 +3297,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 42px; outline: 2px solid #41404a; @@ -3255,7 +3333,7 @@ h2 { .difficulty-select-row label > span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; text-transform: uppercase; } @@ -3265,7 +3343,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 42px; outline: 2px solid #41404a; @@ -3294,7 +3372,7 @@ h2 { .difficulty-summary strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; } @@ -3376,7 +3454,7 @@ h2 { color: var(--gold); display: flex; flex: 0 0 32px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; height: 32px; justify-content: center; @@ -3388,7 +3466,7 @@ h2 { } .difficulty-title strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -3480,7 +3558,7 @@ h2 { color: var(--gold); display: flex; flex: 0 0 31px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; height: 31px; justify-content: center; @@ -3503,7 +3581,7 @@ h2 { } .loot-encounter-title strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; line-height: 1.4; } @@ -3534,7 +3612,7 @@ h2 { align-items: center; color: var(--rarity-color, var(--ink)); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); justify-content: center; } @@ -3585,7 +3663,7 @@ h2 { .leaderboard-header { background: #15161c; color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -3620,7 +3698,7 @@ h2 { border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 6px; outline: 2px solid #3e3d47; padding: 8px 12px; @@ -3675,7 +3753,7 @@ h2 { border: 2px solid #08090c; color: #19150e; cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #816630; padding: 13px 17px; @@ -3708,7 +3786,7 @@ h2 { .placeholder-runes { color: #4a4855; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 39px; margin-bottom: 25px; word-spacing: 20px; @@ -3732,14 +3810,14 @@ h2 { color: var(--gold); display: flex; flex: 0 0 64px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 64px; justify-content: center; } .talent-preview strong { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 10px; } @@ -3776,7 +3854,7 @@ h2 { border: 2px solid; display: flex; flex: 0 0 48px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 48px; justify-content: center; } @@ -3788,13 +3866,13 @@ h2 { .talent-points strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 22px; } .talent-points span { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; margin-top: 4px; } @@ -3865,7 +3943,7 @@ h2 { .effect-slot span, .effect-pool > button i { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; text-transform: uppercase; } @@ -3876,7 +3954,7 @@ h2 { } .effect-slot strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; line-height: 1.35; margin-top: 8px; @@ -3897,7 +3975,7 @@ h2 { .effect-panel-heading > span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; } @@ -3920,7 +3998,7 @@ h2 { .selected-effect-strip strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; line-height: 1.35; margin-top: 5px; @@ -3986,7 +4064,7 @@ h2 { border: 1px solid #55515f; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 26px; justify-content: center; } @@ -3997,7 +4075,7 @@ h2 { } .effect-pool strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; line-height: 1.35; } @@ -4027,7 +4105,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; min-height: 28px; outline: 2px solid #41404a; @@ -4042,7 +4120,7 @@ h2 { .effect-pager span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -4084,7 +4162,7 @@ h2 { .tier-label span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -4137,7 +4215,7 @@ h2 { color: var(--gold); display: flex; flex: 0 0 37px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 37px; justify-content: center; } @@ -4149,7 +4227,7 @@ h2 { .talent-node-header strong { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; line-height: 1.45; } @@ -4243,7 +4321,7 @@ h2 { border: 2px solid; display: flex; flex: 0 0 48px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 48px; justify-content: center; } @@ -4256,7 +4334,7 @@ h2 { .gear-stat strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 15px; } @@ -4324,7 +4402,7 @@ h2 { border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 44px; outline: 2px solid #41404a; @@ -4346,7 +4424,7 @@ h2 { .equipment-heading > span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -4387,7 +4465,7 @@ h2 { background: #15161c; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 38px; justify-content: center; } @@ -4445,7 +4523,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; outline: 2px solid #41404a; padding: 8px 10px; @@ -4534,7 +4612,7 @@ h2 { } .crafting-filter-grid strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 6px; line-height: 1.35; } @@ -4551,7 +4629,7 @@ h2 { } .crafting-level-row button { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; min-height: 34px; min-width: 48px; @@ -4581,7 +4659,7 @@ h2 { border: 2px solid #090a0d; color: var(--gold); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; min-height: 34px; outline: 2px solid #41404a; @@ -4596,7 +4674,7 @@ h2 { .list-pager span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; text-align: center; } @@ -4626,7 +4704,7 @@ h2 { background: #15161c; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 38px; justify-content: center; } @@ -4679,7 +4757,7 @@ h2 { .crafting-detail-heading span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -4710,7 +4788,7 @@ h2 { .crafting-components span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); text-align: center; } @@ -4752,7 +4830,7 @@ h2 { border: 2px solid #090a0d; color: var(--gold); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; margin-top: 12px; outline: 2px solid #41404a; @@ -4794,7 +4872,7 @@ h2 { background: #15161c; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 38px; justify-content: center; } @@ -4925,7 +5003,7 @@ h2 { align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; justify-content: center; } @@ -4943,7 +5021,7 @@ h2 { border: 2px solid #090a0d; color: #ef8994; cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #694048; padding: 11px 8px; @@ -4959,7 +5037,7 @@ h2 { border: 2px solid #090a0d; color: #89ef94; cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #406948; padding: 11px 8px; @@ -5013,7 +5091,7 @@ h2 { border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 44px; outline: 2px solid #41404a; @@ -5073,7 +5151,7 @@ h2 { color: var(--class-color); display: flex; flex: 0 0 35px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 35px; justify-content: center; } @@ -5084,7 +5162,7 @@ h2 { } .class-picker strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -5164,7 +5242,7 @@ h2 { .ability-slots span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 16px; margin-bottom: 8px; } @@ -5216,7 +5294,7 @@ h2 { background: #15161c; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 38px; justify-content: center; } @@ -5250,7 +5328,7 @@ h2 { border: 2px solid var(--edge); color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; height: 32px; justify-content: center; @@ -5282,7 +5360,7 @@ h2 { color: var(--red-bright); display: flex; flex: 0 0 70px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 25px; height: 70px; justify-content: center; @@ -5326,8 +5404,9 @@ h2 { .bar > i { display: block; height: 100%; - transition: width 180ms linear; - will-change: width; + transition: transform 180ms linear; + width: 100%; + will-change: transform; } .enemy-health { @@ -5350,7 +5429,7 @@ h2 { .hard-enemy-bars .enemy-health em { color: #fff7df; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; font-style: normal; left: 8px; @@ -5389,7 +5468,7 @@ h2 { .panel-heading > span { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; } @@ -5457,7 +5536,7 @@ h2 { border: 2px solid #0a0b0e; color: #21180a; display: none; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 5px; padding: 5px 7px; @@ -5520,7 +5599,7 @@ h2 { align-items: center; border: 1px solid white; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; height: 19px; justify-content: center; @@ -5595,7 +5674,7 @@ h2 { .floating-heal { animation: floating-heal 0.9s ease-out forwards; color: #91f0b0; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; left: 50%; position: absolute; @@ -5723,7 +5802,7 @@ h2 { border: 2px solid #0a0b0e; color: #21180a; display: inline-block; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; line-height: 1; margin: 0 0 5px; @@ -5849,7 +5928,7 @@ h2 { border: 2px solid #0a0b0e; color: #ffe6a7; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 17px; height: 42px; justify-content: center; @@ -5996,14 +6075,14 @@ h2 { .reward-summary .level-gain { color: var(--gold) !important; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 12px !important; } .level-gain small { color: #d8c79d; display: block; - font-family: 'VT323', monospace; + font-family: var(--body-font); font-size: 18px; margin-top: 9px; } @@ -6028,7 +6107,7 @@ h2 { .ability-unlock span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); } .reward-summary .reward-error { @@ -6091,6 +6170,7 @@ h2 { } .upgrade-choice-grid button:hover, +.upgrade-choice-grid button:focus, .upgrade-choice-grid button:focus-visible { outline-color: var(--gold); } @@ -6140,7 +6220,7 @@ h2 { color: var(--gold); display: flex; flex: 0 0 38px; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 38px; justify-content: center; } @@ -6196,7 +6276,7 @@ h2 { .pvp-clear-wrap, .pvp-resource-wrap { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; text-align: right; width: 100%; @@ -6283,7 +6363,7 @@ h2 { align-items: center; color: #fff3c7; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; font-style: normal; inset: 0; @@ -6419,7 +6499,7 @@ h2 { .pvp-upgrade-header > strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 16px; white-space: nowrap; } @@ -6450,6 +6530,10 @@ h2 { box-shadow: inset 0 0 0 2px #6e5727; } +.pvp-upgrade-dialog button:focus { + outline-color: var(--gold); +} + .stadium-screen { min-height: 100dvh; } @@ -6480,7 +6564,7 @@ h2 { .stadium-header > strong { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 26px; } @@ -6493,7 +6577,7 @@ h2 { .stadium-pressure-panel strong { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 16px; } @@ -6512,7 +6596,7 @@ h2 { color: var(--muted); display: flex; flex-wrap: wrap; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 12px; gap: 16px; margin-bottom: 12px; @@ -6535,7 +6619,7 @@ h2 { border: 2px solid #0b0c0f; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); outline: 2px solid #4d4c58; } @@ -6585,7 +6669,7 @@ h2 { .stadium-shop-grid small, .stadium-shop-layout p { color: #f0e8d2; - font-family: 'VT323', monospace; + font-family: var(--body-font); font-size: 22px; line-height: 1.05; } @@ -6600,7 +6684,7 @@ h2 { border: 2px solid #08090c; color: #19150e; cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; margin-top: 22px; outline: 2px solid #816630; @@ -7336,7 +7420,7 @@ h2 { border: 2px solid #090a0d; color: var(--muted); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #494754; padding: 10px 18px; @@ -7364,7 +7448,7 @@ h2 { background: #111217; border: 2px solid #090a0d; color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #3e3d47; padding: 10px 12px; @@ -7378,7 +7462,7 @@ h2 { .admin-group-header { color: var(--gold); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 10px; margin: 12px 0 8px; padding: 8px 4px; @@ -7440,7 +7524,7 @@ h2 { color: var(--gold); cursor: pointer; display: inline-flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; outline: 2px solid #41404a; padding: 8px 10px; @@ -7463,7 +7547,7 @@ h2 { } .admin-glyph { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 16px; height: 32px; line-height: 32px; @@ -7492,7 +7576,7 @@ h2 { .admin-item-stats > span { color: var(--green); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -7506,7 +7590,7 @@ h2 { align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 8px; text-transform: uppercase; @@ -7519,7 +7603,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); flex: 1; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; outline: 2px solid #3e3d47; padding: 6px 8px; @@ -7552,7 +7636,7 @@ h2 { align-items: center; color: var(--muted); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 8px; text-transform: uppercase; @@ -7563,7 +7647,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 36px; outline: 2px solid #41404a; @@ -7572,7 +7656,7 @@ h2 { .admin-loot-title { color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 9px; margin: 8px 0; } @@ -7605,13 +7689,13 @@ h2 { .admin-loot-weight { color: var(--muted); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } .admin-loot-chance { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; } @@ -7619,7 +7703,7 @@ h2 { background: #111217; border: 2px solid #090a0d; color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; outline: 2px solid #3e3d47; padding: 4px 6px; @@ -7635,7 +7719,7 @@ h2 { border: 2px solid #08090c; color: #fff; cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #7a2940; padding: 8px 12px; @@ -7652,7 +7736,7 @@ h2 { .admin-add-section summary { color: var(--gold); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; margin-bottom: 8px; text-transform: uppercase; @@ -7673,7 +7757,7 @@ h2 { color: var(--muted); display: flex; flex-direction: column; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 4px; text-transform: uppercase; @@ -7684,7 +7768,7 @@ h2 { background: #15161c; border: 2px solid #090a0d; color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; outline: 2px solid #41404a; padding: 8px 10px; @@ -7708,7 +7792,7 @@ h2 { color: var(--muted); display: flex; flex-direction: column; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 6px; text-transform: uppercase; @@ -7720,7 +7804,7 @@ h2 { border: 2px solid #090a0d; color: var(--ink); cursor: pointer; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 36px; outline: 2px solid #41404a; @@ -7761,7 +7845,7 @@ h2 { color: var(--muted); display: flex; flex-direction: column; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 8px; text-transform: uppercase; @@ -7774,7 +7858,7 @@ h2 { color: var(--ink); cursor: pointer; flex: 1; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-height: 36px; outline: 2px solid #41404a; @@ -7806,7 +7890,7 @@ h2 { color: var(--muted); display: flex; flex-direction: column; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; gap: 6px; text-transform: uppercase; @@ -7816,7 +7900,7 @@ h2 { background: #111217; border: 2px solid #090a0d; color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-width: 230px; outline: 2px solid #3e3d47; @@ -7871,7 +7955,7 @@ h2 { background: var(--class-color, var(--gold)); color: #111217; display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 13px; height: 38px; justify-content: center; @@ -7911,7 +7995,7 @@ h2 { } .admin-class-hero h2 { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 13px; } @@ -7936,7 +8020,7 @@ h2 { .admin-class-table-head { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; padding: 0 10px; text-transform: uppercase; @@ -8002,7 +8086,7 @@ h2 { .admin-class-talent > div > span { color: var(--gold); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); width: 26px; } @@ -8014,7 +8098,7 @@ h2 { .admin-class-talent em { color: var(--green); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; font-style: normal; } @@ -8048,7 +8132,7 @@ h2 { background: #111217; border: 2px solid #090a0d; color: var(--ink); - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 8px; min-width: 180px; outline: 2px solid #3e3d47; @@ -8101,7 +8185,7 @@ h2 { background: #15161c; color: var(--gold); display: flex; - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); height: 34px; justify-content: center; } @@ -8112,7 +8196,7 @@ h2 { } .workshop-bottom-grid strong { - font-family: 'Press Start 2P', monospace; + font-family: var(--pixel-font); font-size: 7px; line-height: 1.25; } diff --git a/src/App.tsx b/src/App.tsx index 59220e6..d0803dd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import { type GameMode, } from './gameRepository' import { focusFirstControl } from './input.tsx' +import { barFillStyle } from './components/barStyles' const CombatScreen = lazy(() => import('./components/CombatScreen').then((module) => ({ default: module.CombatScreen }))) const CustomizeScreen = lazy(() => import('./components/CustomizeScreen').then((module) => ({ default: module.CustomizeScreen }))) @@ -469,7 +470,7 @@ function App() { Level {profile.character.level} Item Level {profile.gearStats.averageItemLevel.toFixed(1)}