docs(01-02): summarize PWA-04 safe-area utility gap closure
Closes the orphaned PWA-04 requirement flagged by 01-VERIFICATION.md. Single edit to app/styles/brand.css adds @utility pt-safe and @utility pb-safe; production build (load-bearing for Tailwind 4 @utility syntax) compiled successfully and emitted both classes into the production CSS bundle.
This commit is contained in:
parent
dff0264115
commit
a293a4f662
1 changed files with 174 additions and 0 deletions
174
.planning/phases/01-pwa-scaffolding/01-02-SUMMARY.md
Normal file
174
.planning/phases/01-pwa-scaffolding/01-02-SUMMARY.md
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
---
|
||||
phase: 01-pwa-scaffolding
|
||||
plan: 02
|
||||
subsystem: pwa-scaffolding
|
||||
gap_closure: true
|
||||
tags: [css, tailwind4, mobile, pwa, safe-area]
|
||||
requirements_satisfied: [PWA-04]
|
||||
roadmap_criteria_satisfied: ["Phase 1 SC #3 — safe-area utility available"]
|
||||
dependency_graph:
|
||||
requires: []
|
||||
provides:
|
||||
- "@utility pt-safe (padding-top: env(safe-area-inset-top))"
|
||||
- "@utility pb-safe (padding-bottom: env(safe-area-inset-bottom))"
|
||||
affects:
|
||||
- "Phase 2 (mobile shell) — sticky header (SHELL-05) and fixed bottom nav (SHELL-06) consume these utilities"
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "Tailwind 4 @utility blocks (already in use across brand.css)"
|
||||
- "CSS env(safe-area-inset-*) — browser-native, falls back to 0"
|
||||
key_files:
|
||||
created: []
|
||||
modified:
|
||||
- app/styles/brand.css
|
||||
decisions:
|
||||
- "Named utilities (pt-safe / pb-safe) over arbitrary values (pt-[env(safe-area-inset-top)]) — single source of truth, clearer JSX, easy future tweak if iOS rules change"
|
||||
- "brand.css over globals.css — co-located with all other named project utilities (num, metric-label, surface-brand, tagline, etc.); already imported by globals.css line 125"
|
||||
- "Top + bottom only (no pl-safe / pr-safe) — manifest pins orientation to portrait; left/right insets only matter in landscape on notched devices; speculative until a consumer asks"
|
||||
- "Plain env() (not max(env(), 0px)) — env() already returns 0 on devices without insets; max() wrapper is a no-op"
|
||||
metrics:
|
||||
duration: "~5 min"
|
||||
completed: 2026-05-03
|
||||
tasks_completed: 1
|
||||
files_modified: 1
|
||||
commits: 1
|
||||
---
|
||||
|
||||
# Phase 01 Plan 02: PWA-04 Safe-Area Utility Gap Closure Summary
|
||||
|
||||
**One-liner:** Adds shared `pt-safe` / `pb-safe` Tailwind 4 `@utility` blocks to `app/styles/brand.css`, closing the orphaned PWA-04 requirement so Phase 2's sticky header and fixed bottom nav can opt into iOS notch / Android home-indicator padding via `env(safe-area-inset-*)`.
|
||||
|
||||
## Requirements Satisfied
|
||||
|
||||
- **PWA-04** — Header and bottom tab bar respect `env(safe-area-inset-top/bottom)` (Tailwind arbitrary values or shared utility class). **Closed** by shipping `@utility pt-safe` and `@utility pb-safe` in `app/styles/brand.css`. This restores the orphaned-requirement state flagged by `01-VERIFICATION.md` (where 01-01 had declared `requirements: [PWA-01, PWA-02, PWA-03]` only and silently deferred PWA-04 to Phase 2).
|
||||
- **ROADMAP Phase 1 Success Criterion #3** — "Shared safe-area utility class available" — satisfied by the same two `@utility` blocks.
|
||||
|
||||
## What Changed
|
||||
|
||||
### Files Modified
|
||||
|
||||
- `app/styles/brand.css` — appended one section comment block + two `@utility` definitions between the existing `@utility tagline` (ends line 140) and the `/* === Wolf-mark watermark === */` section header (now line 165). Net: **+23 lines, 0 deletions.**
|
||||
|
||||
### Exact Diff (additive only)
|
||||
|
||||
```css
|
||||
/* === Safe-area insets =================================================
|
||||
*
|
||||
* Opt-in padding helpers for sticky top / fixed bottom bars on devices
|
||||
* with notches, dynamic islands, or gesture home indicators. Pair with
|
||||
* the viewport-fit=cover viewport meta (set in app/layout.tsx) — without
|
||||
* that, env(safe-area-inset-*) resolves to 0 and these utilities are
|
||||
* no-ops, which is the desired fallback on non-PWA / non-mobile contexts.
|
||||
*
|
||||
* Usage:
|
||||
* <header class="sticky top-0 pt-safe ..."> // header clears notch
|
||||
* <nav class="fixed bottom-0 pb-safe ..."> // bottom bar clears home bar
|
||||
*
|
||||
* Closes PWA-04 (REQUIREMENTS.md) and ROADMAP Phase 1 SC #3.
|
||||
* ==================================================================== */
|
||||
|
||||
@utility pt-safe {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
}
|
||||
|
||||
@utility pb-safe {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
```
|
||||
|
||||
### What Was NOT Changed
|
||||
|
||||
- `app/globals.css` — untouched. The existing `@import "./styles/brand.css";` on line 125 already pulls the new utilities into the global stylesheet.
|
||||
- All pre-existing `@utility` blocks in `brand.css` (`num`, `num-lg`, `num-xl`, `metric-label`, `surface-brand`, `surface-brand-ink`, `rule-brand`, `text-chrome`, `border-chrome`, `tagline`, `has-mark-watermark`) and the `.mark-watermark` plain rule — preserved verbatim.
|
||||
- The `:root` / `.dark` Wulf brand token sections — preserved verbatim.
|
||||
- No `tailwind.config.*` was created (Tailwind 4 + project convention forbids it).
|
||||
- No `next-pwa`, no service worker, no new dependencies introduced.
|
||||
|
||||
## Why These Choices
|
||||
|
||||
### `brand.css`, not `globals.css`
|
||||
|
||||
All named project utilities (`num`, `metric-label`, `surface-brand`, `tagline`, etc.) already live in `brand.css`. Co-locating safe-area utilities there means Phase 2 has one file to scan when looking for project helpers. `globals.css` is reserved for Tailwind imports, `@theme inline` token mapping, and `:root` / `.dark` variable definitions — adding utility classes there would muddy that separation. Plus `brand.css` is already imported by `globals.css` (line 125), so no new wiring is required.
|
||||
|
||||
### Named utilities, not arbitrary values
|
||||
|
||||
Phase 2 will use these classes in 2+ places (sticky header, bottom nav, drawer footer, possibly modals). A named utility is a single source of truth — if iOS rules ever change (e.g., `max(env(safe-area-inset-top), 0.5rem)` becomes desirable), it's a one-line edit to `brand.css` instead of multi-file find-and-replace. `pt-safe` / `pb-safe` also reads more clearly in JSX class lists than `pt-[env(safe-area-inset-top)]`. ROADMAP Phase 1 SC #3 explicitly accepts "shared utility class" as one valid form — picking that form removes ambiguity for Phase 2.
|
||||
|
||||
### Top + bottom only
|
||||
|
||||
The manifest pins orientation to `portrait` (per `01-01-SUMMARY.md`). Left/right safe-area insets (`safe-area-inset-left`, `safe-area-inset-right`) only matter in landscape on notched devices, which the app does not enter. Adding `pl-safe` / `pr-safe` now would be speculative; Phase 2 (or any future phase) can add them in 30 seconds if a real consumer appears.
|
||||
|
||||
### Plain `env(safe-area-inset-*)`, not `max(env(...), 0px)`
|
||||
|
||||
The CSS `env()` value already returns `0` when no inset is reported by the browser — wrapping it in `max(..., 0)` is a no-op and adds noise. Wrap it later if a real device misbehaves.
|
||||
|
||||
## Verification Results
|
||||
|
||||
All checks from the plan's `<verification>` section ran successfully:
|
||||
|
||||
| Check | Command | Result |
|
||||
|-------|---------|--------|
|
||||
| `pt-safe` utility present | `grep -E '@utility pt-safe' app/styles/brand.css` | match (1 line) |
|
||||
| `pb-safe` utility present | `grep -E '@utility pb-safe' app/styles/brand.css` | match (1 line) |
|
||||
| Top inset declaration correct | `grep -E 'padding-top:\s*env\(safe-area-inset-top\)' app/styles/brand.css` | match (1 line) |
|
||||
| Bottom inset declaration correct | `grep -E 'padding-bottom:\s*env\(safe-area-inset-bottom\)' app/styles/brand.css` | match (1 line) |
|
||||
| `tagline` utility unchanged | `grep -E '@utility tagline' app/styles/brand.css` | match |
|
||||
| `num` utility unchanged | `grep -E '@utility num \{' app/styles/brand.css` | match |
|
||||
| Wulf brand tokens intact | `grep -E '\-\-wulf-blue:' app/styles/brand.css` | match |
|
||||
| `.mark-watermark` intact | `grep -E '\.mark-watermark \{' app/styles/brand.css` | match |
|
||||
| globals.css import wiring intact | `grep -E '@import "\./styles/brand\.css";' app/globals.css` | match |
|
||||
| No `pl-safe` / `pr-safe` (out of scope) | `grep -E '@utility (pl-safe\|pr-safe)' app/styles/brand.css` | no match |
|
||||
| No `tailwind.config.*` created | `test ! -f tailwind.config.{ts,js,mjs}` | exit 0 |
|
||||
| No service worker shipped | `test ! -f public/{sw,service-worker}.js` | exit 0 |
|
||||
| `next-pwa` not added | `! grep '"next-pwa"' package.json` | not found |
|
||||
| Type check baseline preserved | `npx tsc --noEmit --pretty` | exit 0 (clean) |
|
||||
| **Production build (load-bearing — Tailwind 4 fails on malformed `@utility` syntax)** | `npm run build` | **`✓ Compiled successfully in 20.3s`** |
|
||||
|
||||
### Compiled CSS Confirmation
|
||||
|
||||
Inspected the production CSS chunk emitted by the build:
|
||||
|
||||
```
|
||||
$ grep -oE '\.pt-safe[^,{]*\{[^}]*\}|\.pb-safe[^,{]*\{[^}]*\}' .next/static/chunks/3c3ee60b60fe53db.css
|
||||
.pt-safe{padding-top:env(safe-area-inset-top)}
|
||||
.pb-safe{padding-bottom:env(safe-area-inset-bottom)}
|
||||
```
|
||||
|
||||
Both utilities compiled cleanly into the production bundle and are ready for Phase 2 to consume.
|
||||
|
||||
### Notes on Build-Time Runtime Errors (Pre-Existing, Out of Scope)
|
||||
|
||||
`npm run build` also surfaces unrelated runtime errors during static page generation: the auto-starting workers (sync-scheduler, analyzer worker, RMM worker) attempt to initialize against Postgres and Better Auth at import time, but no `.env` is present in this worktree, so they log SASL connection errors and a `BETTER_AUTH_SECRET` warning. **These are pre-existing and unrelated to this plan** — they appeared identically in the 01-01 build environment. The compile step (the load-bearing gate for this plan, which validates Tailwind 4 `@utility` syntax) reported `✓ Compiled successfully` and emitted the new classes into the CSS bundle. Logged to deferred-items if needed; not in scope for PWA-04.
|
||||
|
||||
## Pointer to Phase 2
|
||||
|
||||
The new utilities are ready for `app/mobile/layout.tsx`:
|
||||
|
||||
- **Sticky header** (SHELL-05): `<header class="sticky top-0 pt-safe ...">` — clears the iPhone notch / Dynamic Island and Android status bar.
|
||||
- **Fixed bottom nav** (SHELL-06): `<nav class="fixed bottom-0 pb-safe ...">` — clears the iOS home indicator and Android gesture bar.
|
||||
|
||||
No Phase 2 work is required to wire these in — they're already part of the global Tailwind class space the moment Phase 2's components mount.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written. Single-task plan, single edit, single commit.
|
||||
|
||||
## Threat Surface Scan
|
||||
|
||||
No new threat surface. CSS utilities are public client-side styles compiled into the (already-public) Tailwind CSS bundle. `env(safe-area-inset-*)` is a browser-native CSS environment variable resolved entirely client-side from the device viewport — no JavaScript, no user input, no data flow, no auth surface, no new endpoint. STRIDE assessment from the plan stands: only boundary is "browser ↔ static CSS bundle" (information-disclosure → accept; same risk profile as every other Tailwind class). ASVS-L1 baseline preserved.
|
||||
|
||||
## Commits
|
||||
|
||||
| Task | Commit | Files |
|
||||
|------|--------|-------|
|
||||
| 1: Append `pt-safe` / `pb-safe` `@utility` blocks | `dff0264` | `app/styles/brand.css` |
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- File modified exists and contains both new utilities — confirmed via grep.
|
||||
- Commit `dff0264` exists in current branch — confirmed via `git log`.
|
||||
- Compiled CSS bundle in `.next/static/chunks/` contains `.pt-safe` and `.pb-safe` rules — confirmed via grep.
|
||||
- `npm run build` exited successfully (`✓ Compiled successfully in 20.3s`).
|
||||
- `npx tsc --noEmit --pretty` exited 0.
|
||||
- PWA-04 explicitly claimed in this SUMMARY's `requirements_satisfied` frontmatter and "Requirements Satisfied" section — orphaned-requirement trail closed.
|
||||
Loading…
Add table
Add a link
Reference in a new issue