No theme touches playback, any theme; the header clears the iOS status-bar blur

Every theme's full-window overlays are off while a video is open, the picture
is never filtered or blended, the player's lettering is plain. --blur, as in To
Do and Notes: the header (the top row of the app), dialogs, the full-screen
player's note and an expanded KVM start below iOS 26's scroll-edge blur in a
Home Screen app; zero on desktop and in a Safari tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-24 00:05:04 -07:00
co-authored by Claude Opus 5.5
parent 01e0da9022
commit 1c5cd2b0de
2 changed files with 41 additions and 15 deletions
+22 -8
View File
@@ -67,17 +67,31 @@ if (await page.locator('canvas.vp-sphere').count()) {
}
await page.screenshot({ path: `${SHOTS}/h1-auto.png` })
// No theme touches playback: under Retro the scanlines are off and the controls keep a plain font.
// No theme touches playback: for every theme the stylesheet has rules for, no full-window
// overlay is drawn, the picture isn't filtered, and the player's lettering is plain.
{
const was = await page.evaluate(() => document.documentElement.getAttribute('data-theme'))
await page.evaluate(() => document.documentElement.setAttribute('data-theme', 'retro'))
const r = await page.evaluate(() => {
const app = document.querySelector('.app')
const over = app ? getComputedStyle(app, '::after').display : 'none'
const font = getComputedStyle(document.querySelector('.vp button')).fontFamily
return { over, font }
const themes = await page.evaluate(() => {
const ids = new Set()
for (const sh of document.styleSheets) { let rules; try { rules = sh.cssRules } catch { continue }
const walk = (rs) => { for (const r of rs) { if (r.cssRules) walk(r.cssRules); for (const m of (r.selectorText ?? '').matchAll(/data-theme="([^"]+)"/g)) ids.add(m[1]) } }
walk(rules) }
return [...ids]
})
check('Retro leaves the video alone', r.over === 'none' && !/mono|courier/i.test(r.font), JSON.stringify(r))
const bad = []
for (const t of themes) {
const r = await page.evaluate((t) => {
document.documentElement.setAttribute('data-theme', t)
const els = [document.documentElement, document.body, document.querySelector('.app'), document.querySelector('#root')].filter(Boolean)
const overlays = els.flatMap((e) => ['::before', '::after'].map((p) => getComputedStyle(e, p))).filter((c) => c.display !== 'none' && c.content !== 'none' && c.content !== 'normal' && (c.position === 'fixed' || c.position === 'absolute')).length
const pics = [...document.querySelectorAll('.vp video, .vp canvas')].map((e) => getComputedStyle(e).filter).filter((f) => f !== 'none').length
const c = getComputedStyle(document.querySelector('.vp'))
const b = getComputedStyle(document.querySelector('.vp button'))
return { overlays, pics, plain: !/mono|courier/i.test(b.fontFamily) && c.fontWeight === '400' && c.letterSpacing === 'normal' && c.textShadow === 'none' }
}, t)
if (r.overlays || r.pics || !r.plain) bad.push(`${t}: ${JSON.stringify(r)}`)
}
check(`no theme touches the video (${themes.length} themes with their own rules)`, themes.length > 0 && bad.length === 0, bad.join(' / ') || themes.join(', '))
await page.evaluate((t) => t ? document.documentElement.setAttribute('data-theme', t) : document.documentElement.removeAttribute('data-theme'), was)
}