Stop phones zooming when a field is focused

- Viewport: maximum-scale=1 and user-scalable=no (app-like, no pinch or
  double-tap zoom on phones).
- Mobile-only rule keeps every input/textarea/select at 16px so iOS
  Safari's focus auto-zoom never triggers (it ignores user-scalable=no for
  that). Deliberately unlayered so it beats the per-component Tailwind
  sizes; desktop keeps the designed 12-14px fields.

New zoom suite (6 checks): viewport meta, gate input, settings key input,
notes textarea and every study-feed field at >= 16px on a phone, desktop
sizes unchanged. Install sheet 64/64, pwa 16/16, final-ux 12/12,
security 8/8, contrast 20/20.
This commit is contained in:
Martin Dvořák 2026-10-07 12:14:10 +00:00
commit 080306f111
3 changed files with 21 additions and 1 deletions

View file

@ -777,6 +777,10 @@ Things I chose while building, with the reasoning:
device, uses Chrome's deferred `beforeinstallprompt` for a one-tap install where available, and device, uses Chrome's deferred `beforeinstallprompt` for a one-tap install where available, and
stays reachable from Settings. It is mounted in the root layout, so it can appear over any stays reachable from Settings. It is mounted in the root layout, so it can appear over any
screen — including the key gate — without blocking the page underneath. screen — including the key gate — without blocking the page underneath.
30. **Phones don't zoom, and mobile fields are 16px.** The viewport sets `maximum-scale=1` /
`user-scalable=no` for an app-like feel, and a mobile-only rule keeps every input and textarea at
16px so iOS Safari's focus auto-zoom never fires (iOS ignores `user-scalable=no` for that).
Desktop keeps the designed 12–14px field sizes.
14. **`gpt-oss:120b` does all content work — but it cannot read images** (`this model does not 14. **`gpt-oss:120b` does all content work — but it cannot read images** (`this model does not
support image input`), so `VISION_MODEL` has to stay a multimodal model (`gemma4:31b-cloud`). support image input`), so `VISION_MODEL` has to stay a multimodal model (`gemma4:31b-cloud`).
Text-only inputs — pasted text, PDFs with a text layer, DOCX/PPTX/ODT — never touch the vision Text-only inputs — pasted text, PDFs with a text layer, DOCX/PPTX/ODT — never touch the vision

View file

@ -550,6 +550,18 @@ body {
} }
} }
/* Mobile form fields ----------------------------------------------------- */
/* iOS Safari zooms the whole page when a focused field's text is under 16px
(it ignores user-scalable=no for that). Deliberately unlayered so it wins
over the per-component Tailwind sizes, and only on phone-sized screens. */
@media (max-width: 639px) {
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
textarea,
select {
font-size: 16px;
}
}
/* Reduced motion --------------------------------------------------------- */ /* Reduced motion --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
*, *,

View file

@ -41,7 +41,11 @@ export const metadata: Metadata = {
export const viewport: Viewport = { export const viewport: Viewport = {
width: "device-width", width: "device-width",
initialScale: 1, initialScale: 1,
maximumScale: 5, // Phones: no pinch/double-tap zoom (the app-like feel). The input font-size
// rule in globals.css is what actually stops iOS Safari's focus auto-zoom,
// which ignores user-scalable=no.
maximumScale: 1,
userScalable: false,
viewportFit: "cover", viewportFit: "cover",
themeColor: [ themeColor: [
{ media: "(prefers-color-scheme: light)", color: "#f8fafc" }, { media: "(prefers-color-scheme: light)", color: "#f8fafc" },