Three layout bugs and a mobile experience that had no wayfinding.
The `#proposal` section was clipped, not merely cramped: the submit
button carried `whitespace-nowrap` from the shared button base, giving
it a min-content width of 358px, which sized the section's implicit
`auto` grid track to 406px inside a 343px container. `overflow-hidden`
then sliced the copy and every form field off the right edge of a 375px
screen. Fixed at the root — `whitespace-nowrap` moves out of `base` and
into `headerSize`, where buttons are sized by their label — plus an
explicit `grid-cols-[minmax(0,1fr)]` on the section.
The market stat cards put their source line in absolute position against
a guessed min-height, so the longest label ran underneath it. It is in
the flow now, pinned by `mt-auto`.
Below 980px the header nav is not rendered, which left seventeen screens
of scroll with no way to navigate them. The header gives that width back
to the page — logo and call button only — and <ThumbBar /> takes over:
scroll progress, a live section indicator that opens a section sheet,
and one short CTA, hidden over the hero and over the form.
Card rows now say what they are. Rows of unordered peers keep scrolling
sideways and gain a measured segment indicator (<Rail />), replacing the
two prose "swipe sideways" hints. The launch timeline goes the other
way: sideways scrolling hid week 3-5 from someone reading week 1-2, so
below 900px it becomes four disclosures on a spine — which also recovers
the scroll length the taller hero spent.
Below 560px the type scale steps down half a level and the display
tracking opens back up, and the hero photo zooms past `cover` onto the
wave wall, since fitting by height left only ceiling tiles above the
copy.
Also: the route card inside the market section split into two 165px
columns at 760px, so that split now waits for 980px.
Desktop above 980px is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ports the last single-file page, MedCbezFiz — the medical centre that has no
physiotherapy yet — to the architecture the other three landings now share:
Vite + React 19 + TypeScript + Tailwind v4, Express 5 for the API, zod schema
shared between client and server.
The original is kept in legacy/index.html as the visual reference, with its
instructions alongside it in legacy/README.md. Its 4 MB collapse to 317 KB of
JS plus assets loaded on demand. Fourteen inlined images were extracted; twelve
turned out byte-identical to the medcenter landing's, and the two large device
PNGs (1.5 MB and 750 KB) had identical sources, so the webp conversions from
that landing are reused rather than redone — 664 KB of assets instead of 2.8 MB.
Text was verified rather than eyeballed: the app is server-rendered to static
HTML and its visible text diffed against the legacy file. 280 blocks against
281, and the only difference is the honeypot's screen-reader label, which the
original has no equivalent for.
Two things in the original are dead and were deliberately not ported: 39
.patient-economics / .base-economics-card rules that no element uses, and the
[data-counter] animation handler, which likewise matches nothing on the page.
Both are documented in the README.
Departures from the medcenter landing this was built from, all following the
original: the hero photo is anchored at 65% (72% from 980px), the header is
transparent until 18px of scroll instead of always painted, the revenue band
keeps 32px gutters at every width, and the launch timeline breaks into two
columns at 900px rather than 760px.
Leads post to /api/leads/medical-centers-no-physio, the address the original
page already referenced, into pipeline 10980758. The cabinet_state select has
no counterpart on this form and was dropped from the schema, mapper and check
script. Vite runs on 5175 and the API on 3002 so all four landings can run at
once.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>