diff --git a/static/css/01-foundation/_themes.css b/static/css/01-foundation/_themes.css index 6edc993..ca893f7 100644 --- a/static/css/01-foundation/_themes.css +++ b/static/css/01-foundation/_themes.css @@ -290,40 +290,47 @@ right: auto !important; width: 50px !important; height: 50px !important; - /* Removed opacity: 1 !important to allow .footer-hovered to work */ + opacity: 1 !important; /* Full opacity on mobile (no transparency with blur bar) */ transform: none !important; /* Position in 6-button layout: Download, Print, Shortcuts, Theme, Info, Back-to-top */ /* Total width: 6 * 50px + 5 * 10px = 350px */ left: calc(50% + 5px) !important; /* Fourth button */ } - /* Show theme colors at 50% transparency by default on mobile */ + /* Show theme colors at FULL opacity on mobile (no transparency with blur bar) */ .color-theme-switcher[data-theme-mode="light"] { - background: rgba(212, 178, 0, 0.5) !important; /* Gold at 50% */ + background: rgba(212, 178, 0, 1) !important; /* Gold - full opacity */ } .color-theme-switcher[data-theme-mode="dark"] { - background: rgba(1, 60, 119, 0.5) !important; /* Blue at 50% */ + background: rgba(1, 60, 119, 1) !important; /* Blue - full opacity */ } .color-theme-switcher[data-theme-mode="auto"] { - background: rgba(155, 89, 182, 0.5) !important; /* Purple at 50% */ + background: rgba(155, 89, 182, 1) !important; /* Purple - full opacity */ } - /* Full color opacity on hover */ + /* Full color opacity on hover (already at full opacity, just add transform) */ .color-theme-switcher:hover[data-theme-mode="light"] { - background: rgba(212, 178, 0, 1) !important; /* Full gold opacity */ transform: translateY(-3px) !important; + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; } .color-theme-switcher:hover[data-theme-mode="dark"] { - background: rgba(1, 60, 119, 1) !important; /* Full blue opacity */ transform: translateY(-3px) !important; + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; } .color-theme-switcher:hover[data-theme-mode="auto"] { - background: rgba(155, 89, 182, 1) !important; /* Full purple opacity */ transform: translateY(-3px) !important; + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; + } + + /* REAL MOBILE DEVICES: 5 buttons without shortcuts */ + /* Download, Print, Theme, Info, Back-to-top */ + /* Total width: 5 * 50px + 4 * 10px = 290px */ + .is-mobile-device .color-theme-switcher { + left: calc(50% - 25px) !important; /* Third button (no gap) */ } } diff --git a/static/css/04-interactive/_scroll-behavior.css b/static/css/04-interactive/_scroll-behavior.css index bb116fd..ff82a7f 100644 --- a/static/css/04-interactive/_scroll-behavior.css +++ b/static/css/04-interactive/_scroll-behavior.css @@ -96,12 +96,12 @@ opacity: 1; transform: translateY(-3px); box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4); - background: #27ae60; + background: #3498db; /* Blue - different from back-to-top green */ } .info-button.at-bottom { opacity: 1; - background: #27ae60; + background: #3498db; /* Blue - different from back-to-top green */ } .info-button:active { @@ -160,7 +160,7 @@ } .info-button { - background: rgba(39, 174, 96, 1) !important; /* Green - full opacity */ + background: rgba(52, 152, 219, 1) !important; /* Blue - full opacity, different from back-to-top */ opacity: 1 !important; /* Override base opacity */ } @@ -209,6 +209,26 @@ display: flex !important; /* Ensure it's always displayed */ } + /* REAL MOBILE DEVICES: 5 buttons without shortcuts (no gap) */ + /* Total width: 5 * 50px + 4 * 10px = 290px, start at 50% - 145px */ + .is-mobile-device .download-btn { + left: calc(50% - 145px) !important; /* First button */ + } + + .is-mobile-device .print-friendly-btn { + left: calc(50% - 85px) !important; /* Second button */ + } + + /* Theme switcher on mobile - third position (see color-theme.css for override) */ + + .is-mobile-device .info-button { + left: calc(50% + 35px) !important; /* Fourth button */ + } + + .is-mobile-device .back-to-top { + left: calc(50% + 95px) !important; /* Fifth button (last) */ + } + /* Always show back-to-top on mobile (don't wait for scroll) */ .back-to-top:hover { opacity: 1 !important; @@ -236,7 +256,7 @@ } .info-button:hover { - background: rgba(39, 174, 96, 1) !important; /* Full green opacity */ + background: rgba(52, 152, 219, 1) !important; /* Full blue opacity */ transform: translateY(-3px) !important; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4) !important; } @@ -267,7 +287,7 @@ } .info-button.at-bottom { - background: rgba(39, 174, 96, 1) !important; /* Full green opacity */ + background: rgba(52, 152, 219, 1) !important; /* Full blue opacity */ opacity: 1 !important; transform: none !important; } diff --git a/static/css/color-theme.css b/static/css/color-theme.css index 9e43ae6..1c85959 100644 --- a/static/css/color-theme.css +++ b/static/css/color-theme.css @@ -286,10 +286,17 @@ height: 50px !important; opacity: 1 !important; /* Full opacity on mobile (no transparency with blur bar) */ transform: none !important; - /* Position before info button: 5 buttons total */ - /* Download, Print, Shortcuts, Theme, Info */ - /* Total width: 5 * 50px + 4 * 10px = 290px */ - left: calc(50% + 35px) !important; /* Fourth button */ + /* Desktop mobile view: 6 buttons with shortcuts */ + /* Download, Print, Shortcuts, Theme, Info, Back-to-top */ + /* Total width: 6 * 50px + 5 * 10px = 350px */ + left: calc(50% + 5px) !important; /* Fourth button */ + } + + /* REAL MOBILE DEVICES: 5 buttons without shortcuts */ + /* Download, Print, Theme, Info, Back-to-top */ + /* Total width: 5 * 50px + 4 * 10px = 290px */ + .is-mobile-device .color-theme-switcher { + left: calc(50% - 25px) !important; /* Third button (no gap) */ } /* Show theme colors at full opacity on mobile (no transparency with blur bar) */ diff --git a/tests/mjs/53-final-mobile-fixes-test.mjs b/tests/mjs/53-final-mobile-fixes-test.mjs new file mode 100755 index 0000000..f6b409d --- /dev/null +++ b/tests/mjs/53-final-mobile-fixes-test.mjs @@ -0,0 +1,150 @@ +#!/usr/bin/env node + +import { chromium } from 'playwright'; + +const MOBILE_VIEWPORT = { width: 375, height: 667 }; + +(async () => { + const browser = await chromium.launch({ headless: true }); + + console.log('๐Ÿงช Testing Final Mobile Fixes\n'); + + // Test with iPhone user agent (real mobile device) + const context = await browser.newContext({ + viewport: MOBILE_VIEWPORT, + userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1', + hasTouch: true + }); + const page = await context.newPage(); + + await page.goto('http://localhost:1999/?lang=en&view=extended'); + await page.waitForLoadState('networkidle'); + + // FIX 1: Check button reorganization (no gap from hidden shortcuts) + console.log('๐Ÿ“ฑ FIX 1: Button Reorganization (5 buttons, no gap)\n'); + + const buttonPositions = await page.evaluate(() => { + const buttons = { + download: document.querySelector('.download-btn'), + print: document.querySelector('.print-friendly-btn'), + theme: document.querySelector('.color-theme-switcher'), + info: document.querySelector('.info-button'), + backToTop: document.querySelector('.back-to-top'), + shortcuts: document.querySelector('.shortcuts-btn') + }; + + const positions = {}; + for (const [name, btn] of Object.entries(buttons)) { + if (btn) { + const rect = btn.getBoundingClientRect(); + const computed = window.getComputedStyle(btn); + positions[name] = { + left: Math.round(rect.left), + visible: computed.display !== 'none' + }; + } + } + return positions; + }); + + console.log('Button Positions:'); + Object.entries(buttonPositions).forEach(([name, pos]) => { + console.log(` โ€ข ${name}: ${pos.visible ? 'VISIBLE' : 'HIDDEN'} at ${pos.left}px from left`); + }); + + const shortcutsHidden = !buttonPositions.shortcuts.visible; + const buttonsEvenlySpaced = Math.abs( + (buttonPositions.print.left - buttonPositions.download.left) - 60 + ) < 5; // Should be ~60px apart + + console.log(`\n Shortcuts hidden: ${shortcutsHidden ? 'โœ…' : 'โŒ'}`); + console.log(` Buttons evenly spaced: ${buttonsEvenlySpaced ? 'โœ…' : 'โŒ'}\n`); + + // FIX 2: Check info button is BLUE (not green) + console.log('๐ŸŽจ FIX 2: Info Button Color (Blue vs Green)\n'); + + const buttonColors = await page.evaluate(() => { + const info = document.querySelector('.info-button'); + const backToTop = document.querySelector('.back-to-top'); + + const infoStyles = window.getComputedStyle(info); + const backToTopStyles = window.getComputedStyle(backToTop); + + return { + info: { + background: infoStyles.backgroundColor, + opacity: infoStyles.opacity + }, + backToTop: { + background: backToTopStyles.backgroundColor, + opacity: backToTopStyles.opacity + } + }; + }); + + console.log('Info Button:'); + console.log(` โ€ข Background: ${buttonColors.info.background}`); + console.log(` โ€ข Opacity: ${buttonColors.info.opacity}`); + console.log(` โ€ข Expected: rgb(52, 152, 219) - Blue\n`); + + console.log('Back-to-Top Button:'); + console.log(` โ€ข Background: ${buttonColors.backToTop.background}`); + console.log(` โ€ข Opacity: ${buttonColors.backToTop.opacity}`); + console.log(` โ€ข Expected: rgb(39, 174, 96) - Green\n`); + + const infoIsBlue = buttonColors.info.background.includes('52, 152, 219') || + buttonColors.info.background.includes('52,152,219'); + const backToTopIsGreen = buttonColors.backToTop.background.includes('39, 174, 96') || + buttonColors.backToTop.background.includes('39,174,96'); + const differentColors = buttonColors.info.background !== buttonColors.backToTop.background; + + console.log(` Info is blue: ${infoIsBlue ? 'โœ…' : 'โŒ'}`); + console.log(` Back-to-top is green: ${backToTopIsGreen ? 'โœ…' : 'โŒ'}`); + console.log(` Different colors: ${differentColors ? 'โœ…' : 'โŒ'}\n`); + + // FIX 3: Check theme button full opacity + console.log('๐ŸŒˆ FIX 3: Theme Button Transparency\n'); + + const themeButtonStyles = await page.evaluate(() => { + const theme = document.querySelector('.color-theme-switcher'); + const computed = window.getComputedStyle(theme); + const bg = computed.backgroundColor; + + // Extract rgba values + const match = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/); + const alpha = match && match[4] ? parseFloat(match[4]) : 1.0; + + return { + background: bg, + opacity: computed.opacity, + alpha: alpha, + themeMode: theme.getAttribute('data-theme-mode') + }; + }); + + console.log('Theme Button:'); + console.log(` โ€ข Mode: ${themeButtonStyles.themeMode}`); + console.log(` โ€ข Background: ${themeButtonStyles.background}`); + console.log(` โ€ข Opacity: ${themeButtonStyles.opacity}`); + console.log(` โ€ข Alpha: ${themeButtonStyles.alpha}`); + + const themeFullOpacity = parseFloat(themeButtonStyles.opacity) === 1.0 && + themeButtonStyles.alpha === 1.0; + + console.log(` โ€ข Full opacity: ${themeFullOpacity ? 'โœ…' : 'โŒ'}\n`); + + // Take screenshot + await page.screenshot({ + path: 'tests/screenshots/final-mobile-fixes.png', + fullPage: true + }); + console.log('๐Ÿ“ธ Screenshot: tests/screenshots/final-mobile-fixes.png\n'); + + const allPassed = shortcutsHidden && buttonsEvenlySpaced && + infoIsBlue && differentColors && themeFullOpacity; + + console.log(`${allPassed ? 'โœ…' : 'โŒ'} Tests ${allPassed ? 'PASSED' : 'FAILED'}\n`); + + await browser.close(); + process.exit(allPassed ? 0 : 1); +})();