diff --git a/DECISIONS.md b/DECISIONS.md
index ff08b25..dc8089b 100644
--- a/DECISIONS.md
+++ b/DECISIONS.md
@@ -620,3 +620,26 @@ Add an optional **canton dimension**, scoped to Switzerland for now:
### Consequences
- Canton selection works immediately via the fallback; authored cantons enrich the panel. Only VERIFIED canton claims may publish (gate-enforced). Scaffold verified: `astro check` 0 errors, 277 tests.
- A future "add a canton" = add an entry to a corridor's `cantons` (like adding a task) — sourced + fact-verified + founder-gated. Non-CH corridors are unaffected (no canton step).
+
+---
+
+## ADR-0022 — Apple web design language (supersedes ADR-0019)
+
+**Date:** 2026-06-14
+**Status:** Accepted
+**Decided by:** Founder (Anika Williams) — requested an Apple-style reskin
+
+### Context
+The founder asked to move the customer-facing UI from the ADR-0019 "Trust & Authority" system (navy `#0F172A`, CTA `#0369A1`, self-hosted **EB Garamond** display + **Lato** body) to **Apple's web design language** — system font, Apple systemBlue accent, generous whitespace, pill CTAs, card radii. This is a visual-language change only; the accuracy/provenance/compliance machinery is untouched.
+
+### Decision
+Adopt the Apple web token set as the single foundation for all customer-facing UI. **Tokens (light):** label `#1d1d1f`, secondaryLabel `#6e6e73`, tertiaryLabel `#86868b`, accent/systemBlue `#0071e3` (hover `#0066cc`), surface `#f5f5f7`, card `#ffffff`, separator `#d2d2d7`, success `#34C759`/`#248a3d` (text), warning soft `#fff8e6` bg + `#7a5b00` text, danger `#FF3B30`/`#d70015` (text). Exposed as CSS custom properties in `global.css` and as semantic Tailwind names (`label`, `secondaryLabel`, `surface`, `card`, `separator`, `accent`, `link`, `success`, `danger`, `warning.soft`). Names are **dark-mode-ready** (CSS vars + `darkMode: 'class'`) but **only light values are defined — no dark theme is built yet.** **Typography:** the SF system stack (`-apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro Display', 'Helvetica Neue', Arial, system-ui, sans-serif`); heading weights up to 600 (Apple semibold). **EB Garamond + Lato retired** (no `@fontsource` import / `` / preload remains; font files left on disk, unreferenced — zero web-font fetch). **Spacing/radii:** Apple rhythm — inputs `rounded-field` (12px), cards `rounded-card` (18px), primary CTAs `rounded-pill` (980px).
+
+### Implementation notes
+- **The legacy `brand-*` scale was REMAPPED in place to the Apple systemBlue family** rather than ripped out of ~80 call sites across `CorridorApp.tsx`, `index.astro`, and the corridor page. `brand-600` = `#0071e3` (white text 4.70:1, AA), `brand-700` = `#0066cc` (5.57:1), `brand-800` = `#0058b0`, `brand-900` = `#00428a`; light fills `brand-50/100` retuned to match. Every existing CTA/link/ring keeps working and now renders Apple blue. `font-serif` is aliased to the same SF stack so legacy display headings render without pulling a serif web font.
+- **Shared chrome restyled to the tokens:** `BaseLayout` (white canvas, system font, surface footer, separator borders), `Footer` (inline in BaseLayout), `Disclaimer` (soft-warning callout), `ConsentBanner` (card, pill buttons, accent focus rings, native `accent-color`). Content/links/ARIA/Impressum/height-publishing logic all unchanged.
+- Contrast re-verified at every used stop (AA): label on surface 15.46:1; secondaryLabel on white 5.07:1, on surface 4.66:1; white on accent 4.70:1; brand-700 link on brand-50 fill 4.92:1; soft-warning text on soft-warning bg 5.96:1.
+
+### Scope / caveats
+- **Styling only. All trust/content invariants preserved:** the "Verified against official sources" badge, per-task Source line + last-verified date, "not legal advice" notice, the focus-trapped post-intake disclaimer **modal gate**, the "Sources & legal notes" fold, footer Impressum, and the route-not-covered + Russia-sanctions notices all remain — only their classes changed. Zero `src/content/` edits; no claim/provenance/disclaimer wording changed; the no-JS static guide and SEO/zero-JS-default posture are intact. Astro's React-islands-only model is unchanged.
+- `frontend-engineer` is pinned to `claude-fable-5`, unavailable in this environment — implemented on Opus 4.8 (CLAUDE.md's designated fallback).
diff --git a/FOUNDER-TLDR.md b/FOUNDER-TLDR.md
index 1bc1757..0d06fc8 100644
--- a/FOUNDER-TLDR.md
+++ b/FOUNDER-TLDR.md
@@ -10,6 +10,18 @@ coming next. Newest updates are at the top.
---
+## 2026-06-14 — The whole site got a clean, Apple-style redesign
+
+**What changed.** We re-dressed the *entire* website in Apple's design language — the same calm look-and-feel principles Apple uses on its own site. Clean typography using the system font your device already has (so there's nothing extra to download), Apple's restrained colour palette, lots of breathing room, rounded cards, and the signature pill-shaped buttons — across the home page, the questionnaire, the plan, and the legal pages. It's a fresh coat of paint only: every word, fact, source link, the "Verified against official sources" badge, the disclaimer pop-up, and the journey map all work exactly as before. We retired the old custom fonts, so the site fetches nothing from Google and loads a touch faster. We also tightened readability and tap-target sizes so it's easier to use for everyone.
+
+**Why it matters.** A calmer, more familiar, more professional look builds trust — which counts for a lot when people are making life-changing decisions on these pages — and the lighter setup helps speed and privacy.
+
+**What you'd notice today.** The site looks noticeably cleaner and more modern end to end — same content, much calmer presentation. (Review copy — **not live**.)
+
+**What's next.** Your review; a dark-mode version could follow.
+
+---
+
## 2026-06-14 — Plain English everywhere: the legal codes are gone from what you read
**What changed.** We stripped the law-and-statute jargon out of everything you actually *read* in a Switzerland plan. No more "Art. 30 para. 1 let. b FNIA" or "Arts. 42-44" tucked inside the sentences — the steps, titles, summaries and warnings now say it in plain English ("this is a decision the canton makes at its discretion — you have no automatic right" instead of an article number). The official law sources did **not** disappear: they're moved into a "Sources & legal notes" dropdown on each step, so "Verified against official sources" still holds. We kept the real legal meaning exactly — whether something is your *right* or the authorities' *discretion* — only the code-numbers are gone.
diff --git a/ROADMAP.md b/ROADMAP.md
index d991a44..5037394 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -6,7 +6,7 @@
>
> Legend: ✅ done · 🚧 in progress · ⏳ planned · 🔁 ongoing · 🗓️ backlog
-Last updated: 2026-06-14 (Plain-language reading surface (founder mandate "no legal jargon"): all statute/act/article/SR-code citations (FNIA, ASEO, VZAE, OASA, "Art. 30 para. 1 let. b", "Arts. 42-44", SR 142.20, "concubinage") removed from us-ch's DEFAULT-VISIBLE prose (titles, summary/tldr, step text/tips, warnings, document descriptions) and rewritten in plain English — the entitlement-vs-discretion meaning preserved in substance; the law-named per-step source links moved into the collapsed "Sources & legal notes" fold (the actionable canton-office link stays inline); precise citations remain in keyFacts/detail/source links (the Reference/Sources folds), so provenance + "verified against official sources" hold. Two-agent: content-researcher rewrote → fact-verifier independently confirmed no jargon remains + meaning preserved + provenance untouched (VERIFICATION_LOG 2026-06-14); compliance PASS; astro check 0 / build+gate (15 pages) / 281 tests. Scope: us-ch; other 7 corridors' prose to follow. Interactive "journey map" + pure-state gamification (design-research-led; builds on the calmer-UI branch; stacked on it): the flat "Your journey" sidebar list is now a connected, chapter-grouped VISUAL PATH (chapters from an authored category→chapter map in `src/utils/journeyChapters.ts`: Before you go / Your permit / After you arrive / Settling in), each node carrying its real state (done/available/current/locked) from `statusFor()` + a per-node document meter from `docProgress()`; available nodes are clickable, LOCKED nodes stay readable (only Mark-done gated) and show the SPECIFIC "Unlocks after: …" prerequisite from `dependsOn`. Plus a per-task document meter on the card, an instant motivation micro-confirmation, a non-punitive "Welcome back" continuity line, and per-chapter milestone notes extending the existing momentum toast. Everything is a pure projection of existing state — NO dark patterns (no streaks/countdowns/points/false-approval), enforced by a unit test (`tests/journeyChapters.test.ts`) that BANS outcome/approval words in chapter copy. Disclaimer modal gate + provenance + Impressum + Russia/route-not-covered notices untouched; prefers-reduced-motion respected; keyboard-accessible nodes. Verified: astro check 0 / build+gate (15 pages) / 281 tests; a11y PASS (WCAG 2.2 AA audited); trust/dark-pattern review PASS. Deferred: endowed head-start pre-credit, wizard auto-advance, interactive canton map (needs sourced boundary geometry). Calmer/encouraging UI overhaul (design-research-led; pending human-lawyer sign-off): removed the gold "not legal advice" banner everywhere; after the intake a REQUIRED disclaimer modal gate (role=dialog, focus-trapped, no bypass, compliance-owned wording single-sourced in `src/utils/disclaimer.ts`, acked in localStorage `rg-disclaimer-ack-v1`) must be confirmed before the plan renders — also gates shared-link opens; task cards re-sequenced action-first (tldr→steps→documents) with key facts/legal citations/detail behind one "Reference" fold and the caveats consolidated into one "Sources & legal notes" fold (a short "not legal advice" line stays always-visible per card per compliance); plain-language intake options (dropped L/B/C permit codes & "concubinage"); stable phase-based progress ("Your route→situation→details") with progressbar a11y; warm all-breakpoint intro; quiet per-step momentum + calmer document gate. Disclaimer still in the modal + footer (every page) + per-card + Impressum + no-JS guide. Compliance verdict: CONDITIONAL — the modal-acknowledgement posture (vs a persistent banner) needs human-lawyer sign-off before merge; astro check 0 / build+gate / 277 tests green; a11y reviewed (modal focus-trap OK). Cantonal fee/timeline transparency: 12 us-ch steps that have no single federal fee/processing-time figure (the employer-sponsored work permit, the family-reunification routes, the retirement permit, the study permits/sub-steps) now show a user-facing "Fees & processing time" note that these are set by the canton — or, for study admission, the institution — and to confirm locally; driven by a presentation-only `localCostTimeline` task hint (no invented numbers, no new sourced claims, ADR-0007/ADR-0021), plus a "varies by canton" caveat now always shown in the "Your canton" panel. Canton-aware plan-step links: the six "apply at / contact your cantonal authority of the canton where you live/study" steps (family reunification ×3, unmarried-partner concubinage, retirement, study) now deep-link the user's *selected* canton's own migration office (ZH Migrationsamt, GE OCPM, VD SPOP, ZG, BS) instead of the federal SEM directory of all 26 — falling back to that directory for not-yet-sourced cantons, so no dead ends. A `StepLinkSchema.cantonOffice` rendering hint (asserts no fact, no provenance) drives a frontend-only swap to the already-VERIFIED canton migrationOffice claim; static SSR full-guide stays federal (can't know the canton). Build/gate/`astro check`/277 tests green; fact-verifier (accurate, no overreach) + provenance-integrity verified; ADR-0021. Outbound links: the written-guide's 109 external source links now open in a new tab (target=_blank + rel=noopener noreferrer), matching the planner — readers don't lose their place. Plan UI: the desktop plan sidebar (progress / answers / journey) is now collapsible (Hide/Show), giving the task panel full width; mobile already had this. Canton dimension for Switzerland (ADR-0021): corridor-embedded `cantons` schema + provenance gate; CH-only "which canton?" intake step (searchable combobox over 26 cantons, optional) + `cn` share-param + "Your canton" plan panel with a verified SEM-directory fallback; per-canton sourced detail for ZH/GE/VD/ZG/BS in the two-agent pipeline. Earlier: Link audit: all 950 source links render-checked — 147 good, 23 Fedlex "under preparation" links flagged + the us-ch fix applied (79 occurrences → static-HTML, independently fact-verifier re-verified; re-audit now 0 suspect / 170 good). The weekly link-auditor now also checks anchor-reach — a `#article` link that loads but whose section never renders (SPA shell) goes RED on SPA domains (fedlex-class regressions); france-visas added to manual-check (403s the bot, fine for users). Live run: 0 errors / 142 URLs. Plan-personalisation correctness: "Who's joining you?" companion multi-select (partner/children/"It's just me") replaces the children yes/no; family/dependant steps gated to who is actually coming; full-guide route labels; cross-corridor plan-correctness regression suite — ADR-0020. UI/UX "Trust & Authority" design system adopted — audit fixes 1–10: AA-contrast CTAs, 44px touch targets, readable legal text, EB Garamond + Lato self-hosted fonts, brand tokens, consent-overlap fix, home/wizard trust framing, plus polish 11–13 (SVG icons, consistent focus rings, tighter line-length); ADR-0019. Earlier: 8 corridors published + intake availability dots, ADR-0018; source-snapshot cache, ADR-0017; corridor production via agent teams in two runs, ADR-0016; all-routes intake + launch waitlist, ADR-0015; launch-readiness drafts, og:image, dormant consent+analytics, ADR-0013; us-ch founder approval, ADR-0014; go-live blocked on domain + lawyer review)
+Last updated: 2026-06-14 (Apple web design-language reskin (ADR-0022, supersedes ADR-0019; founder direction): the ENTIRE site (home, corridor page + no-JS guide, the plan island, legal/about/contact, shared chrome) reskinned to Apple's web design language — SF system-font stack (EB Garamond/Lato retired → no web-font fetch), Apple token set (label #1d1d1f, secondaryLabel #6e6e73, accent #0071e3, surface #f5f5f7, separator #d2d2d7), generous whitespace, rounded cards, pill primary buttons. Styling-only: zero content/YAML/provenance/logic changes; all trust UI preserved (Verified badge, Source + last-verified lines, disclaimer modal gate, journey map, canton panel, Sources & legal-notes fold, Impressum, route-not-covered + Russia notices). A11y: contrast lifted to AA (tertiaryLabel #6b6b70 = 5.30:1; placeholders → secondaryLabel 5.07:1), 44px hit targets, scalable type ramp (no hardcoded micro-px); apple-hig design-reviewer PASS. Dark mode deferred (tokens dark-ready). astro check 0 / build + gate (15 pages) / 281 tests; verified live (Playwright). Plain-language reading surface (founder mandate "no legal jargon"): all statute/act/article/SR-code citations (FNIA, ASEO, VZAE, OASA, "Art. 30 para. 1 let. b", "Arts. 42-44", SR 142.20, "concubinage") removed from us-ch's DEFAULT-VISIBLE prose (titles, summary/tldr, step text/tips, warnings, document descriptions) and rewritten in plain English — the entitlement-vs-discretion meaning preserved in substance; the law-named per-step source links moved into the collapsed "Sources & legal notes" fold (the actionable canton-office link stays inline); precise citations remain in keyFacts/detail/source links (the Reference/Sources folds), so provenance + "verified against official sources" hold. Two-agent: content-researcher rewrote → fact-verifier independently confirmed no jargon remains + meaning preserved + provenance untouched (VERIFICATION_LOG 2026-06-14); compliance PASS; astro check 0 / build+gate (15 pages) / 281 tests. Scope: us-ch; other 7 corridors' prose to follow. Interactive "journey map" + pure-state gamification (design-research-led; builds on the calmer-UI branch; stacked on it): the flat "Your journey" sidebar list is now a connected, chapter-grouped VISUAL PATH (chapters from an authored category→chapter map in `src/utils/journeyChapters.ts`: Before you go / Your permit / After you arrive / Settling in), each node carrying its real state (done/available/current/locked) from `statusFor()` + a per-node document meter from `docProgress()`; available nodes are clickable, LOCKED nodes stay readable (only Mark-done gated) and show the SPECIFIC "Unlocks after: …" prerequisite from `dependsOn`. Plus a per-task document meter on the card, an instant motivation micro-confirmation, a non-punitive "Welcome back" continuity line, and per-chapter milestone notes extending the existing momentum toast. Everything is a pure projection of existing state — NO dark patterns (no streaks/countdowns/points/false-approval), enforced by a unit test (`tests/journeyChapters.test.ts`) that BANS outcome/approval words in chapter copy. Disclaimer modal gate + provenance + Impressum + Russia/route-not-covered notices untouched; prefers-reduced-motion respected; keyboard-accessible nodes. Verified: astro check 0 / build+gate (15 pages) / 281 tests; a11y PASS (WCAG 2.2 AA audited); trust/dark-pattern review PASS. Deferred: endowed head-start pre-credit, wizard auto-advance, interactive canton map (needs sourced boundary geometry). Calmer/encouraging UI overhaul (design-research-led; pending human-lawyer sign-off): removed the gold "not legal advice" banner everywhere; after the intake a REQUIRED disclaimer modal gate (role=dialog, focus-trapped, no bypass, compliance-owned wording single-sourced in `src/utils/disclaimer.ts`, acked in localStorage `rg-disclaimer-ack-v1`) must be confirmed before the plan renders — also gates shared-link opens; task cards re-sequenced action-first (tldr→steps→documents) with key facts/legal citations/detail behind one "Reference" fold and the caveats consolidated into one "Sources & legal notes" fold (a short "not legal advice" line stays always-visible per card per compliance); plain-language intake options (dropped L/B/C permit codes & "concubinage"); stable phase-based progress ("Your route→situation→details") with progressbar a11y; warm all-breakpoint intro; quiet per-step momentum + calmer document gate. Disclaimer still in the modal + footer (every page) + per-card + Impressum + no-JS guide. Compliance verdict: CONDITIONAL — the modal-acknowledgement posture (vs a persistent banner) needs human-lawyer sign-off before merge; astro check 0 / build+gate / 277 tests green; a11y reviewed (modal focus-trap OK). Cantonal fee/timeline transparency: 12 us-ch steps that have no single federal fee/processing-time figure (the employer-sponsored work permit, the family-reunification routes, the retirement permit, the study permits/sub-steps) now show a user-facing "Fees & processing time" note that these are set by the canton — or, for study admission, the institution — and to confirm locally; driven by a presentation-only `localCostTimeline` task hint (no invented numbers, no new sourced claims, ADR-0007/ADR-0021), plus a "varies by canton" caveat now always shown in the "Your canton" panel. Canton-aware plan-step links: the six "apply at / contact your cantonal authority of the canton where you live/study" steps (family reunification ×3, unmarried-partner concubinage, retirement, study) now deep-link the user's *selected* canton's own migration office (ZH Migrationsamt, GE OCPM, VD SPOP, ZG, BS) instead of the federal SEM directory of all 26 — falling back to that directory for not-yet-sourced cantons, so no dead ends. A `StepLinkSchema.cantonOffice` rendering hint (asserts no fact, no provenance) drives a frontend-only swap to the already-VERIFIED canton migrationOffice claim; static SSR full-guide stays federal (can't know the canton). Build/gate/`astro check`/277 tests green; fact-verifier (accurate, no overreach) + provenance-integrity verified; ADR-0021. Outbound links: the written-guide's 109 external source links now open in a new tab (target=_blank + rel=noopener noreferrer), matching the planner — readers don't lose their place. Plan UI: the desktop plan sidebar (progress / answers / journey) is now collapsible (Hide/Show), giving the task panel full width; mobile already had this. Canton dimension for Switzerland (ADR-0021): corridor-embedded `cantons` schema + provenance gate; CH-only "which canton?" intake step (searchable combobox over 26 cantons, optional) + `cn` share-param + "Your canton" plan panel with a verified SEM-directory fallback; per-canton sourced detail for ZH/GE/VD/ZG/BS in the two-agent pipeline. Earlier: Link audit: all 950 source links render-checked — 147 good, 23 Fedlex "under preparation" links flagged + the us-ch fix applied (79 occurrences → static-HTML, independently fact-verifier re-verified; re-audit now 0 suspect / 170 good). The weekly link-auditor now also checks anchor-reach — a `#article` link that loads but whose section never renders (SPA shell) goes RED on SPA domains (fedlex-class regressions); france-visas added to manual-check (403s the bot, fine for users). Live run: 0 errors / 142 URLs. Plan-personalisation correctness: "Who's joining you?" companion multi-select (partner/children/"It's just me") replaces the children yes/no; family/dependant steps gated to who is actually coming; full-guide route labels; cross-corridor plan-correctness regression suite — ADR-0020. UI/UX "Trust & Authority" design system adopted — audit fixes 1–10: AA-contrast CTAs, 44px touch targets, readable legal text, EB Garamond + Lato self-hosted fonts, brand tokens, consent-overlap fix, home/wizard trust framing, plus polish 11–13 (SVG icons, consistent focus rings, tighter line-length); ADR-0019. Earlier: 8 corridors published + intake availability dots, ADR-0018; source-snapshot cache, ADR-0017; corridor production via agent teams in two runs, ADR-0016; all-routes intake + launch waitlist, ADR-0015; launch-readiness drafts, og:image, dormant consent+analytics, ADR-0013; us-ch founder approval, ADR-0014; go-live blocked on domain + lawyer review)
> **Current focus:** USA → Switzerland (`us-ch`) **only**, until it is perfected end-to-end.
> All other corridors are deferred (see DECISIONS.md **ADR-0006**). India → Germany (`in-de`)
diff --git a/src/components/ConsentBanner.tsx b/src/components/ConsentBanner.tsx
index 30f1860..2e270dd 100644
--- a/src/components/ConsentBanner.tsx
+++ b/src/components/ConsentBanner.tsx
@@ -98,20 +98,20 @@ export default function ConsentBanner() {
role="dialog"
aria-modal="false"
aria-labelledby="consent-title"
- className="mx-auto max-w-3xl rounded-xl border border-slate-300 bg-white p-5 shadow-xl"
+ className="mx-auto max-w-3xl rounded-card border border-separator bg-card p-5 shadow-xl"
>
-
+
Your privacy choices
{view === 'banner' ? (
<>
-
+
Your planner answers stay in your browser. We'd also like to measure usage to
improve the guidance. Privacy-friendly, cookieless analytics run by default;
optional cookie-based analytics and any future ads load only if you agree. See
our{' '}
-
+
Cookie policy
.
@@ -120,21 +120,21 @@ export default function ConsentBanner() {
@@ -142,7 +142,7 @@ export default function ConsentBanner() {
>
) : (
<>
-
+
Choose which optional technologies to allow. You can change this any time from
"Cookie settings" in the footer.
@@ -1526,8 +1518,8 @@ function Sidebar({
{cantonPanel}
-
-
Your journey
+
+
Your journey
{/* SIGNATURE: the connected, chapter-grouped visual PATH. Every node's
state, the per-node document meter and the why-locked prerequisite
are faithful projections of statusFor / docProgress / dependsOn —
@@ -1606,20 +1598,20 @@ function TaskCard({
{/* tabIndex={-1}: focus lands here when the active task changes, so
keyboard/screen-reader users hear the new task and never lose
focus to (e.g. when the Back button unmounts). */}
-
{task.title}
+
{task.title}
{locked ? (
) : (
-
+
)}
{done ? 'Completed' : locked ? 'Locked for now' : 'Ready to start'}
{docsTotal > 0 && (
-
+
{docsHandled}/{docsTotal} documents
)}
@@ -1628,9 +1620,9 @@ function TaskCard({
readable; this names the real prerequisite. Only Mark-done is gated
(see the footer). */}
{locked && prerequisiteTitle && (
-
+
You can read this step now. It unlocks once you finish{' '}
- {prerequisiteTitle}.
+ {prerequisiteTitle}.
)}
@@ -1641,12 +1633,12 @@ function TaskCard({
{/* (a) 1–2 sentence "what and why" (ADR-0012). Falls back to the verified
summary claim until the distilled tldr passes the content pipeline. */}
-
{(task.tldr ?? task.summary).text}
+
{(task.tldr ?? task.summary).text}
{/* Situational warning stays VISIBLE — it's specific to this step, not
boilerplate (it must not be folded away). */}
{task.warning && (
-
+
Note: {task.warning}
)}
@@ -1654,14 +1646,14 @@ function TaskCard({
{/* (b) The numbered "what you'll do" steps — the hero of the card. */}
{task.steps.length > 0 && (
-
What you'll do
+
What you'll do
{task.steps.map((s, i) => (
- {i + 1}
+ {i + 1}
-
{s.text}
- {s.tip &&
{s.tip}
}
+
{s.text}
+ {s.tip &&
{s.tip}
}
{/* Inline under a step we render ONLY a cantonOffice link —
an actionable destination ("Your canton — …"), not a legal
citation. Every other step link (statute / authority
@@ -1680,8 +1672,8 @@ function TaskCard({
const target = cantonOfficeClaim ?? link;
return (
{/* PER-TASK DOCUMENT METER (item 2): the same docProgress data as the
journey map, so the nearer-goal gradient is felt on the card too.
Skipped docs already count as handled upstream — never shown as
'missing'. Decorative bar (the count above is the AT label). */}
{docsTotal > 0 && (
-
{task.localCostTimeline === 'institution'
? 'Set by the educational institution, not at the federal level. Confirm the exact application fee and timing directly with the institution.'
: 'Set by your canton, not at the federal level — there is no single national figure, and it varies across Switzerland. Confirm the exact amount and timing with your cantonal authorities (see “Your canton”).'}
@@ -1777,8 +1769,8 @@ function TaskCard({
{/* The long authored prose (the former "Read the details"). */}
{(task.detail || task.tldr) && (
- {task.tldr &&
{task.summary.text}
}
- {task.detail &&
{task.detail}
}
+ {task.tldr &&
{task.summary.text}
}
+ {task.detail &&
{task.detail}
}
)}
@@ -1788,29 +1780,29 @@ function TaskCard({
{/* Source stays always-visible; the two boilerplate caveats are
consolidated into one collapsed "Sources & legal notes" disclosure —
present and findable, no longer triplicated. */}
-
{/* Per-step source/legal citation links, relocated here from the
@@ -1820,27 +1812,27 @@ function TaskCard({
cantonOffice links are excluded (they stay inline on the step). */}
{stepSourceLinks.length > 0 && (
General guidance only — not legal advice. Confirm with a licensed immigration professional or the relevant authority.
-
+
{DISCLAIMER_PROGRESS_NOTE}
@@ -1848,41 +1840,39 @@ function TaskCard({
-
+
{/* Mark-done is gated for a LOCKED step (item 5) — the content above stays
fully readable, but you can't tick a step done before its real
prerequisite. We name the prerequisite rather than greying out
silently. */}
{locked && (
-
+
{prerequisiteTitle
- ? <>This step unlocks once you finish {prerequisiteTitle}. You can read everything here in the meantime.>
+ ? <>This step unlocks once you finish {prerequisiteTitle}. You can read everything here in the meantime.>
: <>This step unlocks once you finish the steps it depends on. You can read everything here in the meantime.>}
)}
{/* Calmer gate: a helper near the checklist instead of a scolding line on
a greyed button. Only shows when documents are still outstanding. */}
{!done && !locked && docsRemaining > 0 && (
-
+
A few documents to go — check the ones you have, skip what doesn't apply, and you can
mark this step done.
We haven't built the {countryName(origin)} → {countryName(destination)} guide yet
-
+
Every route we publish is researched against official sources and independently
fact-checked before it goes live, so we add them one at a time. Yours isn't ready —
but leave your details and we'll tell you the moment it launches.
Note for moves from Russia: sanctions and banking restrictions can
heavily affect this route. When we publish it, those blockers will be flagged
prominently.
@@ -1982,9 +1972,9 @@ function WaitlistPanel({
)}
{done ? (
-
-
You're on the list ✓
-
+
+
You're on the list
+
We'll contact you when the {countryName(origin)} → {countryName(destination)} guide is
ready. You can close this page — your spot is saved on this device.
@@ -1992,7 +1982,7 @@ function WaitlistPanel({
) : (
@@ -2055,7 +2045,7 @@ function WaitlistPanel({
{/* Opaque-enough backdrop so the plan beneath is not readable. No onClick:
- clicking the backdrop must NOT dismiss the gate. */}
-
+ clicking the backdrop must NOT dismiss the gate. The scrim color is set
+ inline because the Apple tokens are hex CSS vars (not RGB channels), so a
+ Tailwind /opacity modifier on them would not compile to a valid color. */}
+
Before your plan — please read
-
+
{DISCLAIMER_LEAD} {DISCLAIMER_BODY}
-
+
{DISCLAIMER_PROGRESS_NOTE}
-
+
See our{' '}
-
+
Impressum
{' '}
for who runs this site.
@@ -2128,7 +2124,7 @@ function DisclaimerModal({ onAcknowledge }: { onAcknowledge: () => void }) {
ref={confirmRef}
type="button"
onClick={onAcknowledge}
- className="w-full rounded-xl bg-brand-600 py-3 font-medium text-white transition-colors hover:bg-brand-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500"
+ className="w-full rounded-pill bg-accent py-3 font-medium text-white transition-colors hover:bg-accent-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent"
>
I've read and understand
@@ -2165,13 +2161,13 @@ function MomentumToast({
return (
-
+
-
+
Step done — nice work.{' '}
{remaining > 0
? `${remaining} to go.`
@@ -2180,14 +2176,14 @@ function MomentumToast({
{/* PER-CHAPTER MILESTONE (item 6): finishing a chapter's last task. The
note describes the USER's action ("You have finished …") and never
implies an authority's decision (no "approved"/"ready"/"all set"). */}
- {chapterNote &&
{chapterNote}
}
- {milestone &&
{milestone}
}
+ {chapterNote &&
{chapterNote}
}
+ {milestone &&
{milestone}
}
@@ -2673,17 +2669,17 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
if (phase === 'wizard') {
return (
-
+
-
Relocation Guide
-
A few questions, then a plan made for your move — about 2 minutes.
+
Relocation Guide
+
A few questions, then a plan made for your move — about 2 minutes.
{currentIndex > 0 && (
- Start over
+ Start over
)}
-
+
{/* Phase-based progress: three STABLE named phases whose count never
grows when branch questions are inserted, so the bar only ever moves
forward. The current phase fills proportionally to honest position. */}
@@ -2707,8 +2703,8 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
if (pi < curPi) fill = 100;
else if (pi === curPi) fill = phaseProgressPct;
return (
-
-
+
+
);
})}
@@ -2722,52 +2718,52 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
stays a centered single column and the card internals are unchanged. */}
-
+
{/* Warm intro on EVERY breakpoint above the first country grid. On
lg+ the aside carries the warmth, so this in-card version only
shows below lg (where there is no aside). Shown on the very first
step only. */}
{currentStep.id === STEPS[0].id && (
-
Let's map out your move.
-
+
Let's map out your move.
+
Tell us a little about your situation and we'll build a step-by-step plan for your
exact route — every fact traced to an official source.
+
We'll focus your plan on the {motivationLabel(answers.motivation).toLowerCase()} route
{applicableTasks.length > 0 && (
@@ -2892,7 +2888,7 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
)}
{currentStep.id === 'motivation' && answers.motivation && !routeCovered && (
-
+
Heads up: we haven't verified the{' '}
{motivationLabel(answers.motivation).toLowerCase()} route for this corridor yet.
You can continue, but the current guide covers the {coveredLabel} route only —
@@ -2901,17 +2897,15 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
)}
-
+
{currentIndex > 0 && (
- ← Back
+ ← Back
)}
{currentIndex === visibleSteps.length - 1 ? 'Build my relocation plan' : 'Continue'}
@@ -2922,12 +2916,12 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
{/* Slim, calm reassurance line (replaces the old legal-heavy banner).
The full disclaimer lives in the footer + the post-intake modal gate;
the Impressum stays reachable here. */}
-
+
Your answers stay on this device{' '}
·{' '}
Informational only — not legal advice{' '}
·{' '}
- Impressum
+ Impressum
This route isn't live yet — join the launch waitlist
+
This route isn't live yet — join the launch waitlist
- ← Start over
+ ← Start over
{/* Slim, calm caveat line (replaces the old gold/amber banner, per the
founder's directive — the gold banner is gone everywhere). Mirrors the
intake slim line; the full disclaimer lives in the footer + modal gate. */}
-
-
+
+
Informational only — not legal advice{' '}
·{' '}
- Impressum
+ Impressum
-
+
-
-
+
+
-
You've completed every step
-
All {applicableTasks.length} tasks in your {corridorTitle} plan are marked done. You can revisit any step from your journey on the left.
-
+
You've completed every step
+
All {applicableTasks.length} tasks in your {corridorTitle} plan are marked done. You can revisit any step from your journey on the left.
+
This checklist tracks your progress only. Final decisions always rest with the
authorities — keep official confirmations for every step.
);
// Post-intake gate: show the blocking disclaimer modal the first time the plan
@@ -3072,26 +3066,26 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
// is the only thing the user can reach.
style={showDisclaimerGate ? { pointerEvents: 'none' } : undefined}
>
-
{routeCovered && (
-
+
Verified against official sources
)}
- ← Start over
+ ← Start over
{/* The persistent "not legal advice" banner that used to frame the plan is
@@ -3099,9 +3093,9 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
full disclaimer still lives in the site footer on every page. */}
{!routeCovered && answers.motivation && (
-
-
- Your route isn't covered yet.{' '}
+
+
+ Your route isn't covered yet.{' '}
Your answers point to the {motivationLabel(answers.motivation).toLowerCase()} route, but this
guide's verified content covers the {coveredLabel} route only. The steps below describe
the {coveredLabel} route and may not apply to your situation — treat them as background
@@ -3113,8 +3107,8 @@ export default function CorridorApp({ tasks, corridorTitle, originIso2, destinat
{isMobile ? (