Decisions — Ralfing

Phase 1 (2026-08-14)

Project slug: ralfing

The Google listing name is 62 characters ("Rolfing | Strukturelle Integration – Komplementärtherapeut Ralf Eggenberger") and phase1

auto-derived an unusable folder name from it. ralfing is his own brand name — the domain,

the Instagram handle, the LinkedIn company, the YouTube channel, and his stated motto

("Ralfing – Für mehr Lebensqualität"). Repo and Cloudflare project use the same slug.

Category: physiotherapy-osteopathy-chiropractic

Reasoning in build/category-mapping.md. Short version: treatment series + insurance +

named conditions + credentials, none of which the massage or reflexology specs model.

Palette: adopt the Instagram petrol as the dark anchor — operator-approved

His site gave him aquamarine #7FFFD4 and apricot #FFC180 on off-white, with no dark tone;

that absence is why the current site reads washed out and fails contrast on body copy.

His Instagram was already using a deep petrol — sampled at #398489, covering 78% of the

quote-card area — which is the same hue family as the aquamarine, just dropped in value.

Taking it as primary (darkened to #1A4A4F so white text clears 9.8:1) unifies website and

Instagram instead of inventing a colour. Aquamarine and apricot carry over untouched, so

returning clients still recognise the brand.

Typography: keep Crimson Text, replace Roboto

Crimson Text at wide tracking is the one deliberate typographic decision the old site made, and

it is unused anywhere else in the portfolio — kept, at readable weight and full contrast.

Roboto was a Joomla/Cassiopeia default rather than a choice; replaced with Schibsted Grotesk,

which handles long German body copy better and avoids the portfolio's crowded Karla/Jost/Work Sans lane.

Locales: DE (primary, canonical) + EN — operator-approved

He practises in English per the EMR register, Zürich-Oerlikon has an international catchment,

and 6 of 8 Google reviews arrived in or were translated to English. The existing site is DE-only.

Photography: use his own Google Places uploads — operator-approved

The site's gallery images are Joomla _thumb.webp derivatives (17–27 KB) and are unusable at

width. The three Google Places photos are attributed to "Ralfing.ch" (his own uploads) at

4800×3204. Build with those; request originals and a model release for the recognisable client

in the current hero.

Two studios treated as navigation, not an address list

Choosing Oerlikon vs Baden is choosing Thursday/Saturday vs Friday. The current site buries both

addresses in the footer. The rebuild promotes location choice into the hero and the booking flow.

Styleguide sample content replaced by hand

render-styleguide.mjs copies styleguide-html-template.html, whose demo content is hardcoded

reflexology copy ("Reflexology", "Maternity", "Hand reflex", "A calm hour for your body to settle").

For a client-facing review artifact that reads as the wrong business. Patched

brand/styleguide.html directly with real Ralfing content.

⚠️ Re-running render-styleguide.mjs will overwrite these edits.

→ Logged as a suite issue for a spec doc: the template's sample block should be parameterised

per category, or fed from content/identity.md.

Phase 2 (2026-08-14)

Distinctiveness warning reviewed and accepted

check-distinctiveness.mjs flags primary #1A4A4F as within 48 RGB units of

silvia-jayet-reflexologie (#2a302a) — exactly on its threshold. Rejected as a false

positive after checking perceptual distance:

| | hue | saturation | lightness |

|---|---|---|---|

| Ralfing #1A4A4F | 185.7° | 50.5% | 20.6% |

| Silvia #2a302a | 120.0° | 6.7% | 17.6% |

66° apart in hue and 7.5× the saturation: one is a saturated petrol/teal, the other a

near-neutral dark olive-grey. The RGB Euclidean heuristic under-separates dark colours, where a

fixed distance covers far more perceptual ground than it does in the midtones. The petrol is also

source-derived (sampled from his Instagram, not invented), so changing it to satisfy the metric

would make the brand *less* faithful.

→ Suite observation: the check would separate dark tones better in HSL/OKLab than in RGB.

Hero layout also differs from the last five (left-text-photo-right ×3): full-bleed photograph

with a petrol scrim, text overlaid left, and a two-studio day-picker beneath the CTAs.

/impressum redirect corrected by hand

redirect-map.mjs mapped the old German /impressum to /en/imprint/ with a confidence score of

1.00 — it matched on route similarity with no locale awareness. The old site was German-only,

so every legacy URL must land on a German route. Corrected in site/public/_redirects; the two

/neuheiten* URLs scored 0.00 and were mapped by hand (announcement → /standorte/, intro post →

/strukturelle-integration/).

→ Suite issue: the matcher should prefer a same-locale target, or at minimum refuse to

cross a locale boundary at high confidence.

Dark-band link colour bug (caught in visual QA)

Links inside .band--dark inherited the starter's a { color: var(--color-primary) }, which is

the band's own background — rendering the contact list on /standorte/ invisible. Fixed with an

explicit .band--dark a:not(.btn) rule. Worth watching for in any build whose primary doubles

as a section background.

Phase 2b — operator revisions (2026-08-14)

Four changes requested after reviewing the first deploy.

Imagery expanded from 3 to 11 photographs

The first build used only the three Google Places uploads. The old site's own images turned out to be

usable after all: the gallery files are 600×600 (fine as square tiles, just not full-bleed), and four

others are 1065–1200px wide. Full-resolution originals do not exist behind the _thumb names —

every _thumb-less and _large/_medium/_orig variant returns 404, so 600×600 is genuinely all

there is for those three.

Imported with SEO filenames: praxis-oerlikon-behandlung, oederlin-areal-baden,

praxisraum-baden-eingang, ralf-eggenberger-portrait, ralf-eggenberger-portrait-quadrat,

haltungsanalyse-im-stehen, arbeit-an-schulter-und-arm, faszien-arbeit-am-fuss.

Placement: home 9 · method 5 · about 3 · services 2 · locations 2. The old site showed 8 in total.

Instagram was not used as a source in the end — it was unnecessary once the site's own library

opened up, and the site images are higher resolution and unambiguously his.

Two finds worth noting: the Oederlin building shot is the single best asset for the Baden studio (and

the signage on it confirms the spelling is *Oederlin*, not "Oderlin" as the old site writes), and the

teal portrait happens to sit almost exactly on the brand petrol — an accident that makes the palette

look deliberate.

Addresses are now the map link

Both in the footer and on the studio cards, the address block itself links to Google Maps. Previously

there was a separate "Google Maps" link beside an inert address — but the address is what people

actually tap. The explicit button stays on the cards for discoverability.

Reviews link out to Google

Each quoted review's attribution links to that specific review's Google permalink (captured from the

Places API google_maps_uri), and the footer carries a "Bewertungen auf Google" link to the full

profile. Quotes that can be checked in one click are worth considerably more than quotes that cannot.

All rel="nofollow"; still no aggregateRating markup anywhere.

OneDoc booking embedded in-page

Previously a button that sent the visitor to onedoc.ch. Now the widget itself renders on

/termin-vereinbaren/ and /en/booking/ via its iframe plus the postMessage height handshake

(origin-checked against *.onedoc.ch, widget-id matched). The locale is passed through, so the

English page loads the English widget.

Two details that mattered:

widget leaves dead space beneath it.

The old site did embed the same widget, but behind its cookie-consent layer — so the booking page

rendered empty until a visitor accepted cookies. Here it loads directly, with no consent gate in

front of the primary conversion.

QA note for future runs: full-page Playwright screenshots do not trigger loading="lazy"
images or cross-origin iframes below the fold — they photograph as blank boxes and look exactly
like broken images. Both "bugs" found in this round were that artifact. Verify with a scroll pass
plus naturalWidth checks before changing any code. All 26 images across the five content pages
were confirmed loading, 0 broken.

Deferred to the client (see content/operator-notes.md)

Opening hours conflict, the missing 75/90-minute prices, the EMR/ZSR number, the UID for the

impressum, domain/DNS control, and whether the OneDoc booking widget stays.