docs: add Night Shift implementation plan
This commit is contained in:
55
docs/superpowers/plans/2026-10-10-night-shift.md
Normal file
55
docs/superpowers/plans/2026-10-10-night-shift.md
Normal file
@@ -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<boolean>): 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.
|
||||||
Reference in New Issue
Block a user