feat: public landing page with magic login, brand palette and demo build flag

Adds a public funnel landing at `/` and moves the login to `/login`, rebuilt
around the panel's own colors instead of an invented palette.

Landing (`src/components/landing/`, one section per file, no props):
- Seven funnel sections composed by `LandingPage`. The hero's eight swatches are
  literally `PIE_COLORS` from `DashboardPage`, the same hex values the seed hands
  to avatars and services, so "your colors become your numbers" is literal.
- `BrandMark` becomes the single source for the logo, replicating
  `public/favicon.svg`. Blue is the action surface, orange only ever marks.
- `NotebookVisual` is the one deliberate exception to the palette: it is what the
  product replaces.
- Copy drops all system vocabulary; motion comes from `src/lib/motion.ts` with a
  single easing, and reduced-motion resolves `initial` to the final state so a
  never-firing `whileInView` cannot leave a section invisible forever.

Routing and bundle:
- `homePathFor` is the single definition of each role's destination.
- Landing, login, dashboard and calendar load lazily. Eager, the login dragged
  framer-motion (~40 KB gz) into every panel load and the landing downloaded
  recharts + FullCalendar (~187 KB gz) without charting anything. `clsx` is
  pinned to the `react` chunk because Rollup otherwise assigns it to `charts`,
  making the entry import 111 KB gz for a 200-byte utility.

Responsiveness (iPhone/iPad), verified with `npm run audit:responsive`:
- No touch form field below 16px, `dvh` height utilities, safe-area insets, and
  40px touch targets keyed off `pointer: coarse` rather than `sm:`.
- New `.ld-gutter`: `.safe-x` lives outside `@layer` and beats Tailwind's `px-*`,
  so it left the login's side padding at 0 on anything but an iPhone in
  landscape. No overflow check could see it — there was no overflow, just zero
  margin. The audit now guards it with a `gutter` check.
- `shell-height` no longer fires on pages that legitimately scroll; the static
  `raw-viewport-unit` scan covers those instead.

Production build:
- The Dockerfile now sets `VITE_DEMO_UI=1` as a build arg. `DEMO` is a build-time
  constant, so without it Vite eliminated the magic login and the "Ver como…"
  switcher: the deployed landing promised "no registration" and led to an empty
  form. Verified by building both ways and diffing the bundle.
- Service worker cache bumped to v2 so the orphaned pre-landing chunks get purged
  from returning visitors' caches.

Verified: typecheck clean; unit 39/39, e2e 33/33, admin 17/17, booking 12/12,
landing 13/13 (WebKit), PWA passed against the real production build.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
AgendaPro Dev
2026-07-28 14:25:58 -06:00
co-authored by Claude Opus 5
parent 0b466f33f3
commit 4c19244df9
53 changed files with 7310 additions and 525 deletions
+26 -63
View File
@@ -1,74 +1,37 @@
# Task 1 Report - AgendaMax demo access references
# Task 1 Implementation Report
## Status
## Scope
Complete for the source and documentation layer. Local and production SQLite data were not touched.
Implemented only the static AgendaMax PWA contract from Task 1. Existing worktree changes and graphify outputs were not modified.
## Changed files
## Changed Files
Implementation commit `6355d18a07b5bef6fd3515b80a0f768b0ae1050b` (`docs: standardize AgendaMax demo access`) changed:
- `scripts/generate-pwa-icons.mjs`: reproducible Playwright generator using the existing `public/favicon.svg` as a base64 data URL.
- `public/icon-192.png`: generated 192x192 PNG install icon.
- `public/icon-512.png`: generated 512x512 PNG install icon.
- `public/manifest.webmanifest`: exact AgendaMax manifest metadata and icon declarations.
- `index.html`: manifest link, Apple install metadata, and `viewport-fit=cover`; existing favicon, theme, and description preserved.
- `package.json`: added `generate:pwa-icons` and `test:pwa` scripts.
- `README.md` - added an explicit `Contraseña` column with `demo1234` for all eight demo accounts; changed only Admin and Dueño to `@agendamax.demo`.
- `server/index.ts` - changed the fresh default owner email.
- `server/scripts/seed.ts` - changed fresh admin and owner emails; retained `demo1234`.
- `src/pages/LoginPage.tsx` - changed only the development default owner email.
- `admin-test.mjs`, `e2e-test.mjs`, `e2e-full.mjs`, `server/scripts/booking-e2e.mjs`, `visual-audit.mjs` - aligned active platform login fixtures and assertions.
- `docs/superpowers/plans/2026-07-26-auto-assign-specialist-booking-redesign.md` - aligned its copy-pasteable booking login example.
## Verification
The current untracked Task 1 brief, design, and migration plan were not modified or staged. The completed Task 5 report was classified as historical and was not modified. No employee email domain or password was changed.
- `node scripts/generate-pwa-icons.mjs`: exit 0, no output.
- PNG signature/dimensions Node check: passed; `public/icon-192.png` is PNG 192x192 and `public/icon-512.png` is PNG 512x512.
- Reproducibility check: passed. SHA256 values remained stable across regeneration:
- 192 icon: `A5073D1EA7662F7E90D4E8E1DF12FF563A6DCC161FFCF6C4591D7C5F2695F6FE`
- 512 icon: `19914C9D4C3F626782C85920DAD9E16B069809B5D876A903BF88695E1F9F045F`
- `npm.cmd run typecheck`: exit 0.
- `npm.cmd run build`: exit 0; Vite transformed 2463 modules and emitted the production bundle.
- Dist asset/manifest check: passed; `dist/manifest.webmanifest`, `dist/icon-192.png`, and `dist/icon-512.png` exist and the manifest contract is valid.
- `git diff --check`: no whitespace errors. Git emitted only existing line-ending normalization warnings.
## TDD evidence
## Self-Review
### RED
The five executable login fixtures were updated before the source constants. A read-only source assertion was then run against `server/index.ts`, `server/scripts/seed.ts`, and `src/pages/LoginPage.tsx`. It failed as expected with `AssertionError` because `owner@agendamax.demo` and `[email protected]` were not yet present while the old source constants remained.
The focused runtime visual check was also attempted before source changes:
```text
npm run audit:visual
page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/
```
This did not reach the application and did not touch the database.
### GREEN
After the minimal source and README edits, the corrected read-only assertion passed:
```text
source and active login fixtures: PASS
```
The final active-reference and README credential assertion also passed:
```text
active references and README credentials: PASS
```
## Tests and outputs
- `npm run typecheck` - passed, exit code 0; `tsc -b --noEmit` reported no errors.
- `npm run build` - passed, exit code 0; Vite transformed 2463 modules and built in 5.63s.
- `npm run test:unit` - passed: 39 tests, 39 pass, 0 fail.
- `npm run audit:visual` - unavailable: no server was listening on `localhost:5173` (`ERR_CONNECTION_REFUSED`).
- `npm run lint` - unavailable: ESLint 9.39.5 could not find `eslint.config.js`, `eslint.config.mjs`, or `eslint.config.cjs`.
- `rg -n ...` - unavailable because `rg` is not installed/on PATH in this environment. The equivalent scoped repository search found no old domain in active application, README, fixture, or executable plan references.
- `git diff --cached --check` - passed before the implementation commit.
The database-mutating API suites (`test:e2e`, `test:admin`, and `test:booking`) were not run because this task explicitly forbids touching the ignored local database. They remain for the post-migration verification task.
## Self-review
- The quick-login behavior is unchanged: `LoginPage` still loads `/api/auth/demo-users`, and the existing password and account-switching logic remain intact.
- Only platform-owned Admin and Dueño domains changed to `@agendamax.demo`; all employee domains remain on their existing business domains.
- All documented demo rows explicitly show `demo1234`, including every employee row.
- No migration, abstraction, production command, local database command, `.env.local.ps1`, or `data/` file was added or changed.
- The implementation commit contains exactly the ten intended Task 1 files and excludes the supplied untracked design/plan files.
- Remaining `@agendapro.demo` matches are intentional migration/history references in the new migration plan/spec and the completed Task 5 report.
- The browser-tab icon remains `/favicon.svg`.
- The manifest uses `/` for both `start_url` and `scope`, standalone display, portrait-primary orientation, the requested colors, and PNG icon declarations.
- The generator resolves paths from its own module location, closes pages and the browser, and produces deterministic 1x screenshots.
- No unrelated tracked or untracked worktree files were staged.
## Concerns
- Live/API and visual login verification is pending a running dev server and the later SQLite migration; those prerequisites were intentionally not started in this task.
- Lint remains unavailable until the repository ESLint 9 configuration is supplied or the project pins a compatible ESLint setup.
- The exact `rg` inventory command cannot be reproduced until ripgrep is installed/on PATH.
- `npm.cmd run test:pwa` was not run because `pwa-e2e.mjs` is intentionally a Task 4 deliverable and does not exist at this task boundary. The script is present as required for the later task.