diff --git a/DECISIONS.md b/DECISIONS.md index 7356f53c..591b1311 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -236,3 +236,4 @@ One line per decision: `[YYYY-MM-DD] : `. Appended by agents and [2026-07-20] MCP gnubok_book_salary_run walks the whole review->approved->paid->booked chain in ONE staged op instead of mirroring the dashboard's four separate clicks: the human approval of the pending operation (high-risk, confirmed=true) IS the authorization act, and a four-op chain over MCP would just be approval theater. Missing bank details downgrade from overridable block to warnings (dashboard force-approve semantics): the payment-file generators hard-block on them where it matters. [2026-07-20] No gnubok_archive_employee tool: gnubok_update_employee already takes is_active=false (soft-archive, BFL retention) and the v1 REST surface has the DELETE verb; a dedicated tool would only bloat the tools/list budget. [2026-07-20] Booking core extracted to lib/salary/book-run.ts and shared by the dashboard route + book_salary_run executor; the v1 book route intentionally keeps its own strict-mode mirror (optimistic locking, period pre-check, its own envelope) rather than being folded in. +[2026-07-20] Onboarding backdrop reuses marketing-site halftone webp assets copied into public/illustrations/ (not hotlinked, not regenerated): keeps app self-contained and signup->app visually continuous; decorative art uses plain (physics sizes by %, next/image adds nothing for 1-35KB webp). diff --git a/app/(onboarding)/layout.tsx b/app/(onboarding)/layout.tsx index a527be76..cea9313a 100644 --- a/app/(onboarding)/layout.tsx +++ b/app/(onboarding)/layout.tsx @@ -1,6 +1,7 @@ import Link from 'next/link' import { Settings } from 'lucide-react' import { createClient, createServiceClient } from '@/lib/supabase/server' +import OnboardingBackdrop from '@/components/onboarding/OnboardingBackdrop' export default async function OnboardingLayout({ children, @@ -34,7 +35,9 @@ export default async function OnboardingLayout({ return (
-
+ + +
{children}
diff --git a/components/dashboard/WelcomeOnboarding.tsx b/components/dashboard/WelcomeOnboarding.tsx index 52ecb442..7cc7d688 100644 --- a/components/dashboard/WelcomeOnboarding.tsx +++ b/components/dashboard/WelcomeOnboarding.tsx @@ -19,6 +19,22 @@ import Step1EntityType from '@/components/onboarding/Step1EntityType' import Step2CompanyDetails from '@/components/onboarding/Step2CompanyDetails' import Step3TaxRegistration from '@/components/onboarding/Step3TaxRegistration' import Step4VatAccounting from '@/components/onboarding/Step4VatAccounting' +import { + ILLUSTRATIONS, + illustrationSrc, + type IllustrationName, +} from '@/components/onboarding/onboarding-illustrations' + +// One halftone instrument per step, ghosted in white ink on the dark card +// header. The tools get more computational as the steps get more fiscal: +// pencil (choose form) -> notebook (company details) -> adding machine +// (tax registration) -> calculator (VAT & method). +const STEP_ART: { name: IllustrationName; className: string }[] = [ + { name: 'pencil', className: 'w-28 -rotate-12 right-5 -bottom-6' }, + { name: 'notebook', className: 'w-28 rotate-3 right-4 -bottom-3' }, + { name: 'key-adding-machine', className: 'w-32 -rotate-3 right-2 -bottom-10' }, + { name: 'calculator', className: 'w-28 rotate-3 right-4 -bottom-8' }, +] type TFn = (key: string, values?: Record) => string @@ -289,6 +305,29 @@ export default function WelcomeOnboarding({ background: 'radial-gradient(ellipse at 30% -20%, rgba(255,255,255,0.04) 0%, transparent 50%)', }} /> + {/* Step instrument, ghosted in white ink. Keyed by step so it + crossfades together with the form below. */} + {(() => { + const art = STEP_ART[currentStep - 1] + const dims = ILLUSTRATIONS[art.name] + return ( +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
+ ) + })()}
diff --git a/components/onboarding/OnboardingBackdrop.tsx b/components/onboarding/OnboardingBackdrop.tsx new file mode 100644 index 00000000..4c0c46db --- /dev/null +++ b/components/onboarding/OnboardingBackdrop.tsx @@ -0,0 +1,35 @@ +import { ILLUSTRATIONS, illustrationSrc } from './onboarding-illustrations' + +// Ambient scene behind the onboarding flow, built from the marketing site's +// halftone illustration set so signup -> app feels like one product: the +// Stockholm skyline dissolving into the bottom edge. Purely decorative +// (aria-hidden, pointer-events-none); the content column sits above it on +// z-10. +export default function OnboardingBackdrop() { + const skyline = ILLUSTRATIONS['about-stockholm'] + + return ( +
+ {/* Stadshuset skyline anchored to the bottom: translated down so its + water reflection falls below the fold and only the silhouette hugs + the edge, masked so it dissolves upward into the page. min-width + keeps the towers readable on narrow viewports (crops at the sides). */} +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + +
+
+ ) +} diff --git a/components/onboarding/onboarding-illustrations.ts b/components/onboarding/onboarding-illustrations.ts new file mode 100644 index 00000000..6705c0c9 --- /dev/null +++ b/components/onboarding/onboarding-illustrations.ts @@ -0,0 +1,17 @@ +// Halftone line-art illustrations shared with the marketing site +// (gnubok-website public/illustrations/). Intrinsic dimensions are declared +// up front so layers get width/height and avoid layout shift. If you +// copy more pieces from the website repo, add their manifest.json entry here. +export const ILLUSTRATIONS = { + 'about-stockholm': { w: 2648, h: 1318 }, + calculator: { w: 745, h: 525 }, + 'key-adding-machine': { w: 1650, h: 1318 }, + notebook: { w: 636, h: 525 }, + pencil: { w: 542, h: 525 }, +} as const + +export type IllustrationName = keyof typeof ILLUSTRATIONS + +export function illustrationSrc(name: IllustrationName): string { + return `/illustrations/${name}.webp` +} diff --git a/public/illustrations/about-stockholm.webp b/public/illustrations/about-stockholm.webp new file mode 100644 index 00000000..ff833123 Binary files /dev/null and b/public/illustrations/about-stockholm.webp differ diff --git a/public/illustrations/calculator.webp b/public/illustrations/calculator.webp new file mode 100644 index 00000000..ddce88ab Binary files /dev/null and b/public/illustrations/calculator.webp differ diff --git a/public/illustrations/key-adding-machine.webp b/public/illustrations/key-adding-machine.webp new file mode 100644 index 00000000..d45e7b23 Binary files /dev/null and b/public/illustrations/key-adding-machine.webp differ diff --git a/public/illustrations/notebook.webp b/public/illustrations/notebook.webp new file mode 100644 index 00000000..f5e164d4 Binary files /dev/null and b/public/illustrations/notebook.webp differ diff --git a/public/illustrations/pencil.webp b/public/illustrations/pencil.webp new file mode 100644 index 00000000..0136bce7 Binary files /dev/null and b/public/illustrations/pencil.webp differ