- BrandSlot: placeholder div replaced with decorative logo img (ce95aa3) - tokens.css: --brand-logo-border-radius 0, --color-member-0 #e8915a (df578fd) - index.html: favicon.svg + favicon.ico links, theme-color #e8915a (df578fd) - vite.config.ts: maskable icon fixed to /icon-maskable-512.png, theme_color #e8915a (df578fd) - Build: green; manifest.webmanifest verified correct
6.9 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, duration, completed, status
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | duration | completed | status | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 17-ui-optimization-polish | 04 | ui |
|
|
|
|
|
|
4min | 2026-06-18 | complete |
Phase 17 Plan 04: Brand Wiring Summary
BrandSlot logo img wired from seam with no LoginPage change; favicon set + theme-color in index.html; manifest maskable icon fixed to /icon-maskable-512.png; brand accent #e8915a applied consistently across tokens.css, index.html, and vite.config.ts
Performance
- Duration: ~4 min
- Started: 2026-06-18T16:47:28Z
- Completed: 2026-06-18T16:51:02Z
- Tasks: 2/2
- Files modified: 4
Accomplishments
Task 1: BrandSlot logo img + --brand-logo-border-radius
Replaced the Phase 19 placeholder <div aria-hidden>FS</div> with a decorative <img> element:
<img
src="/logo.svg"
alt=""
aria-hidden="true"
style={{
width: 'var(--brand-logo-size, 48px)',
height: 'var(--brand-logo-size, 48px)',
borderRadius: 'var(--brand-logo-border-radius)',
margin: '0 auto var(--space-2, 8px)',
display: 'block',
aspectRatio: '1 / 1',
objectFit: 'contain',
flexShrink: 0,
}}
/>
h1"FamilySync" and taglinepunchangedLoginPage.tsxNOT in the diff (seam contract honored)dangerouslySetInnerHTMLNOT used (T-05-24 invariant maintained)- Updated
--brand-logo-border-radius: 50%→0in tokens.css (approved 17-02: SVG draws its own rx=104 background)
Task 2: index.html favicons + theme-color, vite.config.ts manifest fix, tokens.css accent
index.html changes:
- Added
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />(SVG first, modern browsers) - Added
<link rel="icon" href="/favicon.ico" sizes="any" />(legacy fallback) - Updated
theme-colorfrom#4A90D9→#e8915a apple-touch-iconalready hadsizes="180x180"(was already present)
vite.config.ts changes:
- Fixed maskable icon:
/icon-512.pngwithpurpose: 'maskable'→/icon-maskable-512.png(the separate safe-zone file, 8627 B) - Updated
theme_color: '#4A90D9'→'#e8915a'
tokens.css changes:
- Updated
--color-member-0: #4a90d9→#e8915a(warm amber, operator-approved Variant B) --sx-color-primary: var(--color-member-0)follows automatically (no additional edit needed)
Task Commits
| Task | Name | Commit | Files |
|---|---|---|---|
| 1 | BrandSlot logo img + border-radius token | ce95aa3 |
BrandSlot.tsx, tokens.css |
| 2 | Favicons + theme-color + maskable fix + accent | df578fd |
index.html, tokens.css, vite.config.ts |
Verification
Automated checks passed
grep -q 'src="/logo.svg"' BrandSlot.tsx— OKgrep -q 'alt=""' BrandSlot.tsx— OKgrep -q 'FamilySync' BrandSlot.tsx(h1 intact) — OKdangerouslySetInnerHTMLonly in security comment, not in JSX — OK--brand-logo-border-radius: 0in tokens.css — OK--color-member-0: #e8915ain tokens.css — OKfavicon.svglink in index.html — OKfavicon.icolink in index.html — OKtheme-color: #e8915ain index.html — OKicon-maskable-512.pngin vite.config.ts manifest — OK- No
icon-512.pngwithmaskablepurpose in manifest — OK theme_color: '#e8915a'in vite.config.ts — OKpnpm --filter @familysync/pwa build— exits 0
Build output verified
dist/index.htmlcontainsfavicon.svg,favicon.ico,theme-color: #e8915adist/manifest.webmanifestcontainsicon-maskable-512.pngwith"purpose":"maskable","theme_color":"#e8915a"- JS bundle contains
logo.svgwithalt:""(decorative img confirmed in minified output)
playwright-cli observation
The Vite dev server at :5173 is the main-repo instance (not the worktree), so the live browser showed the pre-existing placeholder. Build artifact verification was used as the authoritative check — dist/manifest.webmanifest and dist/index.html confirm all wiring is correct. The production-equivalent build passes cleanly.
Deviations from Plan
None — plan executed exactly as written. All approved branding decisions from 17-02 applied verbatim:
--color-member-0: #e8915a(Variant B warm amber)--brand-logo-border-radius: 0(SVG self-rounds)- Favicon order per UI-SPEC wiring contract (SVG first, ICO second)
Threat Surface Scan
No new trust boundaries introduced. All changes are static asset references and token values:
BrandSlot.tsxuses<img>with empty alt + aria-hidden — no executable content, no user input, no dangerouslySetInnerHTMLindex.htmlfavicon links and theme-color meta — committed static referencesvite.config.tsmanifest — committed static icon references at known pathstokens.cssvalue updates — no new surface
No new threat flags above the LOW level accepted in the plan's threat model.
Self-Check: PASSED
apps/pwa/src/components/BrandSlot.tsx— modified, committed atce95aa3apps/pwa/src/styles/tokens.css— modified, committed atce95aa3(border-radius) +df578fd(color)apps/pwa/index.html— modified, committed atdf578fdapps/pwa/vite.config.ts— modified, committed atdf578fddist/manifest.webmanifest— correct maskable + theme_color confirmed- Build: exits 0
Phase: 17-ui-optimization-polish Completed: 2026-06-18