From efc3a025aede0ee56e8d6c8d7e7f847b25c7918e Mon Sep 17 00:00:00 2001 From: Konrad Kollnig <5175206+kasnder@users.noreply.github.com> Date: Tue, 22 Sep 2026 23:14:17 +0200 Subject: [PATCH] Refine iOS mobile preview and remove duplicate homepage search --- docs/design/README.md | 6 +++- docs/design/design.css | 60 ++++++++++++++++++++++++++++----------- docs/design/index.html | 6 ++-- docs/design/report.html | 12 +++++++- test/websiteViews.test.js | 14 ++++++++- views/layout.pug | 9 +++--- 6 files changed, 80 insertions(+), 27 deletions(-) diff --git a/docs/design/README.md b/docs/design/README.md index 4f6c51a..95272b5 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -2,6 +2,10 @@ This dependency-free preview contains a homepage and one detailed example report for Wordle!. It uses static example data only: there is no live app search, service integration, or report queue. -Open `index.html` directly in a browser. For HTTP review, serve the `docs/design/` directory with any static server scoped to that directory; the parent preview server uses `http://localhost:4318/` in this session. +Open `index.html` directly in a browser. For HTTP review, serve the `docs/design/` directory with any static server scoped to that directory. + +The mobile refinement retains the existing palette, typography and shared responsive pages. It reduces header and hero spacing on phones, keeps example reports ahead of research statistics, and adds a plain-language report introduction with expandable analysis metadata. Sample-only entries remain visibly labelled on mobile. The live homepage now uses only its main search form; other live pages keep the header search. + +Browser checks covered 320px, 390px and 1280px widths without page-level horizontal overflow, app search, combined tracker filters and the metadata disclosure. Mobile form controls retain 16px text and at least 44px height. This is browser viewport validation, not a physical iPhone Safari test. The preview was checked with `node --check docs/design/preview.js`. Only Wordle! has a local detailed report; Merge Dragons! and Subway Surfers are clearly labelled example entries. diff --git a/docs/design/design.css b/docs/design/design.css index c2f2df8..2b219ad 100644 --- a/docs/design/design.css +++ b/docs/design/design.css @@ -513,6 +513,7 @@ input::placeholder { .back-link { color: var(--muted); + gap: .3rem; font-size: 0.85rem; text-decoration: none; } @@ -832,6 +833,16 @@ input::placeholder { margin: 0; } +.report-takeaway { padding: 1.75rem 0; max-width: 720px; } +.report-takeaway h2 { margin-bottom: .8rem; } +.report-takeaway p:not(.eyebrow) { color: #3c514d; margin-bottom: .8rem; } +.report-takeaway a { display: inline-flex; align-items: center; min-height: 44px; gap: .5rem; } +.report-disclosure { border-bottom: 1px solid var(--border); margin-bottom: 2.5rem; } +.report-disclosure > summary { cursor: pointer; padding: 1rem 0; min-height: 56px; font-weight: 750; } +.report-disclosure > summary span { color: var(--muted); font-size: .85rem; font-weight: 400; margin-left: .5rem; } +.report-disclosure .stale-note { margin: 1rem 0; } +.report-disclosure .metadata { border-bottom: 0; padding-top: .5rem; } + @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; @@ -915,8 +926,9 @@ input::placeholder { .site-header { min-height: 0; - padding-bottom: 1.25rem; - padding-top: 1.25rem; + padding-bottom: .5rem; + padding-top: .75rem; + gap: 0; } .preview-strip__inner { @@ -930,11 +942,27 @@ input::placeholder { } h1 { - font-size: clamp(2.55rem, 13vw, 3.5rem); + font-size: clamp(2rem, 9vw, 2.8rem); + line-height: 1.05; + margin-bottom: 1rem; + } + + .hero { padding-top: 1.25rem; padding-bottom: 1.75rem; } + .hero .eyebrow { margin-bottom: .75rem; } + .preview-strip__inner { gap: 0; padding: .25rem 0; } + .preview-strip nav a, .site-nav a, .site-footer nav a, .wordmark, .back-link { + display: inline-flex; + align-items: center; + min-height: 44px; } + .search-form { gap: .75rem; padding-top: 1rem; } + .field-hint { max-width: none; } + .section-heading { margin-bottom: 1rem; } + .report-disclosure > summary span { display: block; margin: .15rem 0 0 1rem; } .hero__intro { - margin-bottom: 2.6rem; + margin-bottom: 1.5rem; + font-size: 1rem; } .search-form__controls { @@ -947,8 +975,8 @@ input::placeholder { } .featured { - padding-bottom: 4.5rem; - padding-top: 2.6rem; + padding-bottom: 2.5rem; + padding-top: 1.5rem; } .app-row { @@ -968,10 +996,9 @@ input::placeholder { font-size: 0.78rem; } - .app-row__arrow, - .app-row__tag { - display: none; - } + .app-row__arrow { display: none; } + .app-row__tag { grid-column: 2 / -1; justify-self: start; font-size: .7rem; } + .app-row__name { overflow-wrap: anywhere; } .metrics { gap: 1.5rem 0.9rem; @@ -1003,14 +1030,14 @@ input::placeholder { } .report-page { - padding-top: 1.4rem; + padding-top: .25rem; } .report-header { gap: 1rem; grid-template-columns: 64px minmax(0, 1fr); - padding-bottom: 2.2rem; - padding-top: 2.4rem; + padding-bottom: 1.25rem; + padding-top: 1rem; } .app-tile--large { @@ -1025,14 +1052,13 @@ input::placeholder { } .report-header__back { - grid-column: 2; - justify-self: start; + display: none; } .summary { gap: 1.2rem 0.8rem; - padding-bottom: 1.9rem; - padding-top: 1.9rem; + padding-bottom: 1.25rem; + padding-top: .25rem; } .summary-item strong { diff --git a/docs/design/index.html b/docs/design/index.html index 3f8824a..f50078b 100644 --- a/docs/design/index.html +++ b/docs/design/index.html @@ -13,9 +13,9 @@
- Design preview · Example data from 8 September 2026 + Mobile design preview · Example data from 8 September 2026
@@ -36,7 +36,7 @@

Independent app privacy research

-

A closer look at
your iPhone apps.

+

A closer look at your iPhone apps.

Find the tracking software built into iOS apps, and the companies behind it.

+
+

At a glance

+

30 trackers found in the app’s code.

+

These are recognised software components, associated with 25 companies. Their presence does not establish that the app tracked you or sent your data.

+ Explore the detected trackers +
+
30detected trackers
25associated companies
@@ -54,6 +61,8 @@

Wordle!

This preview identifies embedded tracker signatures. It does not report observed network traffic.

+
+ Analysis details Version, dates and limitations

Metadata context. Store details are retained from the last recorded check and may be stale. They do not verify the current app version or current behaviour.

+
diff --git a/test/websiteViews.test.js b/test/websiteViews.test.js index dad7fb4..5d8af76 100644 --- a/test/websiteViews.test.js +++ b/test/websiteViews.test.js @@ -90,6 +90,8 @@ test('production templates preserve the principal page states and data', () => { assert.match(home, /not random/); assert.match(home, /action="\/search"/); assert.match(home, /name="search"/); + assert.equal((home.match(/role="search"/g) || []).length, 1); + assert.doesNotMatch(home, /id="nav-search"/); assert.match(home, /Example App/); const success = render('form.pug', reportBase); @@ -147,8 +149,9 @@ test('production templates preserve the principal page states and data', () => { }); test('search, directory, lookup, statistics, about, request and error states render safely', () => { - const emptySearch = render('form.pug', { data: { search: 'nothing' }, searchResults: [] }); + const emptySearch = render('form.pug', { currentPath: '/search', data: { search: 'nothing' }, searchResults: [] }); assertSingleH1(emptySearch, 'empty search'); + assert.match(emptySearch, /id="nav-search"/); assert.match(emptySearch, /No apps found for/); assert.match(emptySearch, /No matching free app/); @@ -231,6 +234,15 @@ test('Danish pages expose the language toggle and translate report labels and co languageUrl: (target) => languageUrl('/trackers', target), localUrl: (path) => localUrl(path, 'da', '/trackers') }; + const home = render('form.pug', { + ...danish, + currentPath: '/', + localUrl: (path) => localUrl(path, 'da', '/'), + languageUrl: (target) => languageUrl('/', target) + }); + assert.equal((home.match(/role="search"/g) || []).length, 1); + assert.doesNotMatch(home, /id="nav-search"/); + assert.match(home, /action="\/da\/search"/); const directory = render('directory.pug', { ...danish, kind: 'tracker', diff --git a/views/layout.pug b/views/layout.pug index bbb0fcb..45eb63d 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -60,10 +60,11 @@ html(lang=localeCode === 'da' ? 'da-DK' : 'en-GB') a(href=localize('/companies') class=current.startsWith('/company') || current === '/companies' ? 'is-current' : undefined aria-current=current.startsWith('/company') || current === '/companies' ? 'page' : undefined)= translate('Companies') a(href=localize('/statistics') class=current === '/statistics' ? 'is-current' : undefined aria-current=current === '/statistics' ? 'page' : undefined)= translate('Statistics') a(href=localize('/about') class=current === '/about' ? 'is-current' : undefined aria-current=current === '/about' ? 'page' : undefined)= translate('About') - form.nav-search(action=localize('/search') method='GET' role='search') - label.sr-only(for='nav-search')= translate('Search apps') - input#nav-search(type='search' name='search' value=searchData.search || '' placeholder=translate('Search apps placeholder') autocomplete='off') - button.button.button--small(type='submit')= translate('Search') + if current !== '/' + form.nav-search(action=localize('/search') method='GET' role='search') + label.sr-only(for='nav-search')= translate('Search apps') + input#nav-search(type='search' name='search' value=searchData.search || '' placeholder=translate('Search apps placeholder') autocomplete='off') + button.button.button--small(type='submit')= translate('Search') nav.language-toggle(aria-label=translate('Language')) a(href=languageHref('en') class=localeCode === 'en' ? 'is-current' : undefined aria-current=localeCode === 'en' ? 'true' : undefined)= translate('English') a(href=languageHref('da') class=localeCode === 'da' ? 'is-current' : undefined aria-current=localeCode === 'da' ? 'true' : undefined)= translate('Dansk')