From 86094d5a2e4267984533ed0ba3412427b8be26b3 Mon Sep 17 00:00:00 2001 From: Chisel Date: Tue, 3 Feb 2026 10:37:41 +0000 Subject: [PATCH 1/7] feat: refine the visual design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added DM Sans from Google Fonts - Applied it to body text and the timer display - Introduced CSS custom properties (:root) for colours and spacing - Primary accent gold: #d4af37 (replacing #ffd700) - Slightly muted accent green for buttons and highlights - Light border (rgba(255,255,255,0.08)) - Stronger backdrop blur (12px) - Softer box-shadow - Gold colour variable - Subtle inner glow on timer digits - sans-serif fallback added for the font stack - Background: rgba(0,0,0,0.4) with blur - Top border and shadow to separate it from content - Thin bottom border on the wrapper - Border and light inset shadow on character-type tiles - Focus states for keyboard/D-pad: :focus-visible with green ring - Size: min 48×48px for Settings, Info, Fullscreen (TV-friendly) - Micro-interactions: Shorter transitions (~150–200ms) and scale(0.98) on active - Softer transitions and focus rings - Borders for clearer hierarchy - Matching borders and stronger box-shadows - Extra blur on settings and What's New dialogs - Consistent border-radius via variables (--radius-sm, --radius-md, --radius-lg) - Shared transition variables for timing - Unified accent colour usage across components - CSP update: style-src and font-src now allow Google Fonts (fonts.googleapis.com and fonts.gstatic.com). --- index.html | 8 +- styles.css | 402 +++++++++++++++++++++++++++++++++-------------------- 2 files changed, 262 insertions(+), 148 deletions(-) diff --git a/index.html b/index.html index de37838..65d1392 100644 --- a/index.html +++ b/index.html @@ -71,12 +71,18 @@ /> Tower Timer + + + diff --git a/styles.css b/styles.css index 1858e8b..40ed3a7 100644 --- a/styles.css +++ b/styles.css @@ -1,12 +1,51 @@ +:root { + /* Colour palette */ + --colour-bg: #1a1a1a; + --colour-surface: rgba(33, 33, 33, 0.75); + --colour-surface-elevated: rgba(42, 42, 42, 0.95); + --colour-border: rgba(255, 255, 255, 0.08); + --colour-border-strong: rgba(255, 255, 255, 0.15); + --colour-text: #ffffff; + --colour-text-muted: rgba(255, 255, 255, 0.7); + --colour-text-subtle: rgba(255, 255, 255, 0.6); + --colour-accent: #45a049; + --colour-accent-hover: #3d8b40; + --colour-accent-muted: rgba(76, 175, 80, 0.25); + --colour-gold: #d4af37; + --colour-gold-bright: #e6c547; + --colour-good: rgba(25, 118, 210, 0.7); + --colour-evil: rgba(211, 47, 47, 0.7); + --colour-button-secondary: #2c3e2c; + --colour-button-secondary-hover: #3c513c; + --colour-blitz: #f44336; + --colour-blitz-hover: #e53935; + /* Spacing and radius */ + --radius-sm: 6px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --transition-fast: 150ms ease; + --transition-normal: 200ms ease; + /* Focus ring for accessibility / TV remote */ + --focus-ring: 3px solid var(--colour-accent); +} + * { margin: 0; padding: 0; box-sizing: border-box; } +/* Fire TV / keyboard: clear focus indication */ +button:focus-visible, +select:focus-visible, +input:focus-visible { + outline: none; +} + body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, - Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif; min-height: 100vh; display: flex; flex-direction: column; @@ -14,8 +53,8 @@ body { align-items: center; gap: 0.25rem; padding-top: 0.25rem; - background-color: #1a1a1a; - color: #ffffff; + background-color: var(--colour-bg); + color: var(--colour-text); position: relative; } @@ -252,12 +291,14 @@ body[data-pace='blitz'] .portrait-warning-dialog button:hover { } .container { - background-color: rgba(33, 33, 33, 0.7); + background-color: var(--colour-surface); padding: 0.75rem; - border-radius: 12px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3); + border-radius: var(--radius-lg); + border: 1px solid var(--colour-border); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); text-align: center; - backdrop-filter: blur(8px); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); width: 95%; max-width: 1000px; display: flex; @@ -282,12 +323,12 @@ h1 { .timer-display .time { font-size: min(15vw, 11rem); - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI Condensed', - 'Segoe UI', Roboto; - font-weight: bold; - color: #ffd700; + font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, + 'Segoe UI Condensed', 'Segoe UI', Roboto, sans-serif; + font-weight: 700; + color: var(--colour-gold); font-variant-numeric: tabular-nums; - text-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + text-shadow: 0 4px 12px rgba(0, 0, 0, 0.4), 0 0 24px rgba(212, 175, 55, 0.15); line-height: 0.9; display: flex; flex-direction: row; @@ -297,7 +338,7 @@ h1 { } .timer-display.wake-up-countdown .time { - color: #4caf50; + color: var(--colour-accent); animation: pulse-text 2s infinite; } @@ -314,12 +355,12 @@ h1 { .nominations-countdown { font-size: min(4vw, 1.5rem); - color: rgba(255, 255, 255, 0.9); + color: var(--colour-text); text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); margin-top: 0.5rem; padding: 0.25rem 0.75rem; - background: rgba(76, 175, 80, 0.25); - border-radius: 6px; + background: var(--colour-accent-muted); + border-radius: var(--radius-sm); line-height: 1.2; } @@ -370,31 +411,38 @@ h1 { } .preset-btn { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); color: white; padding: 0.5rem 1rem; font-size: 1.2rem; min-width: 3rem; + transition: background-color var(--transition-fast), + transform var(--transition-fast), box-shadow var(--transition-fast); } .preset-btn:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); +} + +.preset-btn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.4); } .preset-btn.active { - background-color: #4caf50; + background-color: var(--colour-accent); } .minute-btn { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); } .minute-btn:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); } .minute-btn.active { - background-color: #4caf50; + background-color: var(--colour-accent); } #startBtn { @@ -403,26 +451,31 @@ h1 { right: 0.5rem; transform: translateY(-50%); z-index: 2; - background-color: #4caf50; + background-color: var(--colour-accent); color: white; padding: 1.5rem 1rem; - border: none; - border-radius: 6px; + border: 1px solid rgba(76, 175, 80, 0.2); + border-radius: var(--radius-sm); cursor: pointer; font-size: 1.2rem; font-weight: 600; - transition: all 0.2s; + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); min-width: 140px; min-height: 80px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); backdrop-filter: blur(8px); - border: 1px solid rgba(76, 175, 80, 0.2); display: flex; align-items: center; justify-content: center; gap: 0.5rem; } +#startBtn:focus-visible { + outline: none; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25), 0 0 0 3px rgba(76, 175, 80, 0.5); +} + #startBtn .button-content { display: flex; flex-direction: column; @@ -454,13 +507,13 @@ h1 { } #startBtn:hover { - background-color: #45a049; + background-color: var(--colour-accent-hover); transform: translateY(calc(-50% + 1px)); } #startBtn:active { - background-color: #3d8b40; - transform: translateY(calc(-50% + 2px)); + background-color: var(--colour-accent-hover); + transform: translateY(calc(-50% + 2px)) scale(0.98); } #startBtn:disabled { @@ -475,12 +528,17 @@ h1 { min-width: 120px; } +#resetBtn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.5); +} + #resetBtn:hover { background-color: #6b3410; } #accelerateBtn { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); color: white; min-width: 160px; display: inline-flex; @@ -489,10 +547,16 @@ h1 { gap: 0.5rem; position: relative; overflow: hidden; - transition: all 0.2s; + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); --progress-width: 0%; } +#accelerateBtn:focus-visible { + outline: none; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2), 0 0 0 3px rgba(76, 175, 80, 0.4); +} + #accelerateBtn::before { content: ''; position: absolute; @@ -529,15 +593,15 @@ h1 { } #fullscreenBtn { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); color: white; padding: 0.75rem; min-width: auto; position: static; opacity: 0.7; - transition: opacity 0.2s; - height: 42px; - width: 42px; + transition: opacity var(--transition-fast); + height: 48px; + width: 48px; } #fullscreenBtn:hover { @@ -587,34 +651,44 @@ h1 { #settingsBtn, #infoBtn, #fullscreenBtn { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); border: none; padding: 0.75rem; cursor: pointer; color: #ffffff; - border-radius: 4px; - transition: all 0.2s; + border-radius: var(--radius-md); + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); display: flex; align-items: center; justify-content: center; - height: 42px; - width: 42px; + min-height: 48px; + min-width: 48px; + height: 48px; + width: 48px; position: static; } +#settingsBtn:focus-visible, +#infoBtn:focus-visible, +#fullscreenBtn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.5); +} + #settingsBtn:hover, #infoBtn:hover, #fullscreenBtn:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); } #settingsBtn:active, #infoBtn:active, #fullscreenBtn:active { - background-color: #2c3e2c; - transform: translateY(0); + background-color: var(--colour-button-secondary); + transform: translateY(0) scale(0.98); } .settings-icon, @@ -659,17 +733,17 @@ h1 { /* Settings Dialog */ .settings-dialog { - border: none; - border-radius: 16px; + border: 1px solid var(--colour-border); + border-radius: var(--radius-xl); padding: 0; - background-color: rgba(33, 33, 33, 0.95); - color: #ffffff; + background-color: var(--colour-surface-elevated); + color: var(--colour-text); max-width: 95vw; width: 600px; max-height: 90vh; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.4); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); position: fixed; top: 50%; left: 50%; @@ -701,7 +775,7 @@ h1 { font-size: 1rem; margin: 0; margin-bottom: 0.25rem; - color: rgba(255, 255, 255, 0.7); + color: var(--colour-text-muted); text-align: center; font-weight: normal; } @@ -731,7 +805,7 @@ h1 { .dialog-content h3 { font-size: 1rem; margin: 0 0 0.75rem 0; - color: #4caf50; + color: var(--colour-accent); font-weight: 500; } @@ -741,8 +815,8 @@ h1 { display: flex; flex-direction: column; background: rgba(255, 255, 255, 0.05); - border-radius: 12px; - border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: var(--radius-lg); + border: 1px solid var(--colour-border-strong); height: fit-content; position: relative; } @@ -750,7 +824,7 @@ h1 { .setting-group h3 { font-size: 0.95rem; margin: 0 0 0.35rem 0; - color: #4caf50; + color: var(--colour-accent); font-weight: 500; } @@ -798,14 +872,14 @@ h1 { .info-value { font-size: 1.1rem; - font-weight: bold; - color: #4caf50; + font-weight: 700; + color: var(--colour-accent); font-variant-numeric: tabular-nums; } .info-value-note { font-size: 0.8rem; - color: rgba(255, 255, 255, 0.6); + color: var(--colour-text-subtle); font-weight: normal; } @@ -889,10 +963,10 @@ body[data-pace='blitz'] .info-value { -webkit-appearance: none; width: 12px; height: 12px; - background: #4caf50; + background: var(--colour-accent); border-radius: 50%; cursor: pointer; - transition: transform 0.2s; + transition: transform var(--transition-fast); } .volume-slider::-webkit-slider-thumb:hover { @@ -902,7 +976,7 @@ body[data-pace='blitz'] .info-value { .volume-value { min-width: 48px; font-size: 0.9rem; - color: rgba(255, 255, 255, 0.7); + color: var(--colour-text-muted); } .dialog-buttons { @@ -922,7 +996,7 @@ body[data-pace='blitz'] .info-value { } .dialog-buttons button.primary-btn { - background: #4caf50; + background: var(--colour-accent); color: white; } @@ -931,13 +1005,18 @@ body[data-pace='blitz'] .info-value { color: white; } +.dialog-buttons button { + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); +} + .dialog-buttons button:hover { transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); } .dialog-buttons button.primary-btn:hover { - background: #45a049; + background: var(--colour-accent-hover); } .dialog-buttons button:not(.primary-btn):hover { @@ -969,6 +1048,8 @@ body[data-pace='blitz'] .info-value { padding: 0; width: 95%; max-width: 1000px; + border-bottom: 1px solid var(--colour-border); + padding-bottom: 0.5rem; } .character-counts { @@ -984,8 +1065,8 @@ body[data-pace='blitz'] .info-value { font-size: 0.8rem; padding: 0.15rem 0.5rem; margin-top: 0.25rem; - background: rgba(76, 175, 80, 0.3); - border-radius: 4px; + background: var(--colour-accent-muted); + border-radius: var(--radius-md); display: inline-block; line-height: 1; } @@ -997,7 +1078,7 @@ body[data-pace='blitz'] .info-value { transform: translateY(-50%); z-index: 2; font-size: 1.25rem; - font-weight: bold; + font-weight: 700; color: #ffffff; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); margin: 0; @@ -1008,11 +1089,11 @@ body[data-pace='blitz'] .info-value { justify-content: center; white-space: nowrap; background: #f5f1e6; - border-radius: 6px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + border-radius: var(--radius-sm); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); backdrop-filter: blur(8px); border: 1px solid rgba(139, 69, 19, 0.2); - transition: background-color 0.3s ease; + transition: background-color var(--transition-normal); width: 120px; } @@ -1106,59 +1187,61 @@ body[data-pace='blitz'] .info-value { } .clocktower-presets button.current-day { - box-shadow: 0 0 0 2px #ffd700; + box-shadow: 0 0 0 2px var(--colour-gold); animation: pulse 2s infinite; } @keyframes pulse { 0% { - box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.5); + box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.5); } 50% { - box-shadow: 0 0 0 4px rgba(255, 215, 0, 0.2); + box-shadow: 0 0 0 4px rgba(212, 175, 55, 0.2); } 100% { - box-shadow: 0 0 0 2px rgba(255, 215, 0, 0.5); + box-shadow: 0 0 0 2px rgba(212, 175, 55, 0.5); } } .character-type { flex: 1; min-width: 100px; - background-color: #2a2a2a; - border-radius: 8px; + background-color: var(--colour-surface-elevated); + border-radius: var(--radius-md); padding: 0.5rem; text-align: center; - transition: background-color 0.3s; + transition: background-color var(--transition-normal); display: flex; flex-direction: column; align-items: center; + border: 1px solid var(--colour-border); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05); } .character-type .label { font-size: 1rem; - color: rgba(255, 255, 255, 0.9); + color: var(--colour-text-muted); margin-bottom: 0.25rem; font-weight: 500; } .character-type .amount { font-size: 2.5rem; - font-weight: bold; - color: #fff; + font-weight: 700; + color: var(--colour-text); line-height: 1; } /* Good team (blue background) */ .character-type:nth-child(1), .character-type:nth-child(2) { - background: rgba(25, 118, 210, 0.7); + background: var(--colour-good); } /* Evil team (red background) */ .character-type:nth-child(3), .character-type:nth-child(4) { - background: rgba(211, 47, 47, 0.7); + background: var(--colour-evil); } .character-type.traveller { @@ -1195,23 +1278,29 @@ body[data-pace='blitz'] .info-value { .clocktower-presets button { padding: 0.35rem 0.75rem; font-size: 1.1rem; - background-color: #2c3e2c; - border: none; - border-radius: 5px; + background-color: var(--colour-button-secondary); + border: 1px solid var(--colour-border); + border-radius: var(--radius-sm); color: white; cursor: pointer; - transition: background-color 0.3s; + transition: background-color var(--transition-fast), + transform var(--transition-fast), box-shadow var(--transition-fast); width: 100%; } +.clocktower-presets button:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.4); +} + .clocktower-presets button:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); } .clocktower-presets button.active { - background-color: #4caf50; + background-color: var(--colour-accent); box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.2); } @@ -1257,8 +1346,8 @@ body:has(.clocktower-settings.visible) #regularTimerControls { /* Info Dialog */ .info-dialog { padding: 0; - border: none; - border-radius: 12px; + border: 1px solid var(--colour-border); + border-radius: var(--radius-lg); background-color: #1a2b1a; color: white; max-width: 600px; @@ -1340,13 +1429,13 @@ body:has(.clocktower-settings.visible) #regularTimerControls { } .version-display span:nth-child(2) { - color: #4caf50; + color: var(--colour-accent); font-weight: bold; font-size: 1rem; } .changelog-link { - color: #4caf50; + color: var(--colour-accent); text-decoration: none; font-size: 0.9rem; margin-left: 0.5rem; @@ -1400,7 +1489,7 @@ body:has(.clocktower-settings.visible) #regularTimerControls { } .disclaimer a { - color: #4caf50; + color: var(--colour-accent); text-decoration: none; } @@ -1419,7 +1508,7 @@ body:has(.clocktower-settings.visible) #regularTimerControls { } .main-site-link a { - color: #4caf50; + color: var(--colour-accent); text-decoration: none; } @@ -1462,25 +1551,25 @@ body:has(.clocktower-settings.visible) #regularTimerControls { padding: 0.5rem; font-size: 1rem; border: 1px solid #4a4a4a; - border-radius: 4px; - background-color: #2c3e2c; + border-radius: var(--radius-md); + background-color: var(--colour-button-secondary); color: white; cursor: pointer; } .game-pace-select:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); } .game-pace-select:focus { outline: none; - border-color: #4caf50; + border-color: var(--colour-accent); box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2); } .game-pace-display { font-size: 1rem; - color: #ffd700; + color: var(--colour-gold); text-align: center; margin-top: 0.25rem; } @@ -1661,10 +1750,10 @@ button:disabled { } .number-input-group button { - background-color: #2c3e2c; + background-color: var(--colour-button-secondary); color: white; border: none; - border-radius: 6px; + border-radius: var(--radius-sm); width: 32px; height: 32px; font-size: 1.25rem; @@ -1672,11 +1761,17 @@ button:disabled { display: flex; align-items: center; justify-content: center; - transition: background-color 0.2s; + transition: background-color var(--transition-fast), + transform var(--transition-fast); } .number-input-group button:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); +} + +.number-input-group button:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.4); } .number-input-group input[type='number'] { @@ -1694,10 +1789,10 @@ button:disabled { .setting-group input[type='checkbox'] { width: 24px; height: 24px; - accent-color: #4caf50; + accent-color: var(--colour-accent); cursor: pointer; position: relative; - border-radius: 4px; + border-radius: var(--radius-md); } /* Add spacing between setting groups in the same column */ @@ -1749,9 +1844,9 @@ button:disabled { .playlist-link { font-size: 0.8rem; - color: #4caf50; + color: var(--colour-accent); text-decoration: none; - transition: color 0.2s ease, opacity 0.2s ease; + transition: color var(--transition-fast), opacity var(--transition-fast); display: flex; align-items: center; gap: 0.35rem; @@ -1764,7 +1859,7 @@ button:disabled { .playlist-link::before { content: '→'; - color: #4caf50; + color: var(--colour-accent); } /* YouTube playlist input styling */ @@ -1793,17 +1888,17 @@ button:disabled { /* What's New Dialog */ .whats-new-dialog { - border: none; - border-radius: 16px; + border: 1px solid var(--colour-border); + border-radius: var(--radius-xl); padding: 0; - background-color: rgba(33, 33, 33, 0.95); - color: #ffffff; + background-color: var(--colour-surface-elevated); + color: var(--colour-text); max-width: 95vw; width: 500px; max-height: 80vh; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); + box-shadow: 0 25px 50px rgba(0, 0, 0, 0.4); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); position: fixed; top: 50%; left: 50%; @@ -1861,11 +1956,11 @@ button:disabled { .version-number { font-size: 1.2rem; font-weight: bold; - color: #4caf50; + color: var(--colour-accent); } .version-date { - color: rgba(255, 255, 255, 0.7); + color: var(--colour-text-muted); font-size: 0.9rem; } @@ -1876,7 +1971,7 @@ button:disabled { } .changes-section h3 { - color: #4caf50; + color: var(--colour-accent); margin-bottom: 0.25rem; font-size: 1rem; } @@ -1896,7 +1991,7 @@ button:disabled { .changes-section li::before { content: '•'; - color: #4caf50; + color: var(--colour-accent); position: absolute; left: 0; } @@ -2112,24 +2207,25 @@ button:disabled { width: 32px; height: 32px; padding: 0; - border: 1px solid rgba(255, 255, 255, 0.2); - border-radius: 6px; - background: #2c3e2c; + border: 1px solid var(--colour-border-strong); + border-radius: var(--radius-sm); + background: var(--colour-button-secondary); color: #fff; cursor: pointer; - transition: all 0.2s ease; + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); } .preview-sound:hover { - background: #3c513c; + background: var(--colour-button-secondary-hover); transform: translateY(-1px); - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); + box-shadow: 0 3px 8px rgba(0, 0, 0, 0.25); border-color: rgba(255, 255, 255, 0.3); } .preview-sound:active { - transform: scale(0.95) translateY(0); + transform: scale(0.98) translateY(0); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } @@ -2140,7 +2236,7 @@ button:disabled { } .preview-sound.playing { - background: #4caf50; + background: var(--colour-accent); border-color: rgba(255, 255, 255, 0.4); color: white; box-shadow: 0 0 12px rgba(76, 175, 80, 0.4); @@ -2330,7 +2426,7 @@ button:disabled { .portrait-warning-dialog h2 { margin: 0; - color: #4caf50; + color: var(--colour-accent); font-size: 1.5rem; } @@ -2347,18 +2443,18 @@ button:disabled { } .portrait-warning-dialog button { - background-color: #4caf50; + background-color: var(--colour-accent); color: white; border: none; padding: 0.75rem 1.5rem; - border-radius: 6px; + border-radius: var(--radius-sm); cursor: pointer; font-size: 1rem; - transition: background-color 0.2s; + transition: background-color var(--transition-fast); } .portrait-warning-dialog button:hover { - background-color: #45a049; + background-color: var(--colour-accent-hover); } /* Optimize for shorter viewports */ @@ -2444,11 +2540,12 @@ button:disabled { .tab-button { background: none; border: none; - color: rgba(255, 255, 255, 0.7); + color: var(--colour-text-muted); padding: 0.5rem 1rem; - border-radius: 6px; + border-radius: var(--radius-sm); cursor: pointer; - transition: all 0.2s; + transition: background-color var(--transition-fast), + color var(--transition-fast); font-size: 0.95rem; } @@ -2457,8 +2554,13 @@ button:disabled { color: white; } +.tab-button:focus-visible { + outline: none; + box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.4); +} + .tab-button.active { - background: #4caf50; + background: var(--colour-accent); color: white; } @@ -2538,7 +2640,11 @@ button:disabled { left: 0; right: 0; z-index: 999; - background: none; + background: rgba(0, 0, 0, 0.4); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border-top: 1px solid var(--colour-border); + box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.2); } .left-buttons { @@ -2564,11 +2670,13 @@ button:disabled { padding: 8px 16px; font-size: 1.1rem; border: none; - border-radius: 5px; + border-radius: var(--radius-sm); color: white; cursor: pointer; - transition: all 0.2s; - height: 42px; + transition: transform var(--transition-fast), + box-shadow var(--transition-fast), background-color var(--transition-fast); + min-height: 48px; + height: 48px; display: flex; align-items: center; justify-content: center; @@ -2601,9 +2709,9 @@ button:disabled { } #accelerateBtn:hover { - background-color: #3c513c; + background-color: var(--colour-button-secondary-hover); transform: translateY(-1px); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); } /* Keyboard Shortcuts Styles */ From 8b126c87f8360944b0797832f8b4d61bc7de68f8 Mon Sep 17 00:00:00 2001 From: Chisel Date: Tue, 3 Feb 2026 10:41:48 +0000 Subject: [PATCH 2/7] chore(changelog): update changelog for version 1.0.25 --- changelog.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/changelog.js b/changelog.js index b3c6bf5..d8f733f 100644 --- a/changelog.js +++ b/changelog.js @@ -1,7 +1,19 @@ // Version tracking -export const APP_VERSION = '1.0.24'; +export const APP_VERSION = '1.0.25'; export const CHANGELOG = { + '1.0.25': { + date: '2026-02-03', + changes: { + improvements: [ + 'Visual design refresh: DM Sans typography, refined colour palette, and polished UI', + 'Improved focus states for keyboard and TV remote navigation', + 'Refined timer display with subtle glow; softer shadows and transitions throughout', + 'Bottom bar and character counts styling; consistent border-radius and spacing', + 'Resolve code linting warnings', + ], + }, + }, '1.0.24': { date: '2026-02-02', changes: { From 2de30889ac347957f0146d341c5c2ad0dc1e4ec3 Mon Sep 17 00:00:00 2001 From: Chisel Date: Tue, 3 Feb 2026 12:04:23 +0000 Subject: [PATCH 3/7] fix: resolve sonarqube findings --- index.html | 2 +- script.js | 165 ++++++++++++++++++++++++++--------------------------- 2 files changed, 83 insertions(+), 84 deletions(-) diff --git a/index.html b/index.html index 65d1392..405a3d6 100644 --- a/index.html +++ b/index.html @@ -91,7 +91,7 @@ src="https://www.googletagmanager.com/gtag/js?id=G-DHYFSVZZHW" >