diff --git a/docs/superpowers/plans/2026-10-10-night-shift.md b/docs/superpowers/plans/2026-10-10-night-shift.md new file mode 100644 index 0000000..4b085a6 --- /dev/null +++ b/docs/superpowers/plans/2026-10-10-night-shift.md @@ -0,0 +1,55 @@ +# Night Shift Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans. Steps use checkbox syntax. + +**Goal:** Layer a cinematic, kinetic "Night Shift" identity onto the existing night-drive portfolio without breaking content, budgets or tests. + +**Architecture:** Additive. One pure helper module with tests, one pointer composable, two small Vue components, one stylesheet imported last in `App.vue`. All motion honors `prefers-reduced-motion` and the existing motion policy. + +**Tech Stack:** Vue 3, TypeScript, Vitest, CSS scroll-driven animations (progressive enhancement). + +**Spec:** `docs/redesign/direction.md` + +## Global Constraints +- No new runtime dependencies; no new font files (fonts budget 120 KB). +- Initial JS budget 120 KB; HTML+critical CSS 100 KB. +- Never alter content strings in `content/public/portfolio-content.json`. +- Overlay UI is `aria-hidden` or non-blocking; focus rings stay visible; text contrast >= 4.5:1. +- Reduced motion, forced colors, touch and webdriver (tests) show the plain site. + +## Review Focus +- Hydration mismatch from time-based text: render stable text on the server, fill on mount. +- Boot overlay trapping clicks/keys or hiding content from no-JS and crawlers. +- Pointer effects on touch devices. +- Uptime when clock is before the start date: clamp to zero. +- Repeat visits: boot shown once per session. + +### Task 1: Operations helpers +**Files:** Create `src/lib/operations.ts`; Test `tests/unit/operations.test.ts` +**Produces:** `uptimeSince(start: Date, now: Date): { months: number; days: number }`; `bucharestClock(now: Date): string` (HH:MM, 24h, Europe/Bucharest) +- [ ] Test: `uptimeSince(2025-08-01, 2025-08-01)` is 0 months 0 days; `2026-10-10` gives 14 months 9 days; a `now` before start clamps to zero. +- [ ] Test: `bucharestClock(new Date('2026-01-15T10:05:00Z'))` is `12:05`. +- [ ] Implement; run `npx vitest run tests/unit/operations.test.ts`; commit. + +### Task 2: Headlight + pointer composable +**Files:** Create `src/composables/useHeadlight.ts` +**Produces:** `useHeadlight(enabled: Ref): void` sets `--hx`/`--hy` on `document.documentElement` and `--mx`/`--my` (percent) on the hovered `.project-case-study, .project-card, .portfolio-section` ancestor, via one rAF-throttled passive `pointermove`; no-op unless `(pointer: fine)` and enabled. +- [ ] Implement, typecheck, commit. + +### Task 3: Operations strip +**Files:** Create `src/components/OperationsStrip.vue`; Modify `AppShell.vue` +Renders `Bucharest HH:MM · On shift 14 mo · Route NN%` after mount, static `Bucharest` text on the server. `aria-hidden`. Start date constant `2025-08-01` (Trupa lui Răzuș, from the content file). +- [ ] Implement, mount in AppShell beside JourneyHud, run unit tests, commit. + +### Task 4: Boot sequence +**Files:** Create `src/components/BootSequence.vue`; Modify `AppShell.vue` +Shown only after mount when motion allowed, not `navigator.webdriver`, not seen this session (sessionStorage guarded by try/catch). Lines use real facts. Auto-dismiss, any key/click/Escape skips, `pointer-events` only while visible, `aria-hidden`. +- [ ] Implement, commit. + +### Task 5: nightshift.css +**Files:** Create `src/styles/nightshift.css`; Modify `src/App.vue` (import last) +Kinetic hero weight, outlined chapter numerals via CSS counter, headlight layer, grain/vignette, card spotlight/tilt, scroll-driven reveals under `@supports (animation-timeline: view())`, all inside `prefers-reduced-motion: no-preference` and `(pointer: fine)` where relevant. +- [ ] Implement, commit. + +### Task 6: Verify +- [ ] `npm run typecheck`, `npm run test:unit`, `npm run build:preview`; browser check at 1440 and 390; run browser tests; code review pass.