* docs: host theme contract proposal (prevent features carving into one theme)
Charrette output after a plugin UI feature (note_detect results card) was built
against only the default skin and broke on the others — the colours adapted via
tokens but the visual *devices* (glow ring, gradient) did not, because themes are
design languages, not palettes, and nothing governs whether a theme does glow.
Proposes a host theme contract: always-present semantic role tokens (incl. the
missing on-accent + focus-ring), intent-named capability recipe slots where "off"
is legal (an EMPHASIS recipe + an ACCENT-TEXT recipe), a window.feedBack.theme
read/capability API + theme:changed event, a derive-surfaces-from-host
reconciliation rule, accessibility baked in, and a skin-matrix verification gate.
All additive + feature-detected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QbexxfTt8q2tAn436MqGWF
* docs(host-theme-contract): make the proposal normative (review fixes)
Address the review of #645 (manual + Codex) — the doc was a sound design
sketch but not yet the precise *contract* it claims to be:
- P1 Token contract pinned: one public namespace `--fb-*` written on :root by a
host-owned contract stylesheet (present themed-or-not); `--fbv-*` explicitly
demoted to internal Tailwind-override plumbing (plugins must not read it).
Added a normative role table + value grammar (colour roles = `r g b` triplets
consumed via `rgb(var(--fb-x))`; recipe slots = full CSS device values). The
§5 example now uses `--fb-*` throughout (was bare `--accent`/`--emph-*`).
- P1 Invisible-text bug removed from the spec: `--fb-acc-text-fill` is the one
slot where `none` is ILLEGAL (always a real paint, defaulting to the solid
accent); the example feature-detects `background-clip: text` and keeps a solid
`color` base, so the accuracy number can never render transparent — honouring
the DoD "a device stays legible when its slot resolves to none".
- P1 capabilities() booleans removed: they contradicted "never branch on
glowy?" and were too lossy for canvas. The JS API is now CSS/DOM-forbidden and
exposes RESOLVED token values (`get().tokens`) for canvas/WebGL renderers only.
- P1 Physical home decided: a static `theme-contract.css` (outside the prebuilt
Tailwind artifact, so no tailwind-fresh CI churn) holds the :root `--fb-*`
defaults + the single focus-visible + reduced-motion rules; existing v3.css
focus/motion rules are a tracked reconciliation, not day-one magic.
- P2 Full on-fill family (`--fb-on-accent/-good/-warn/-bad`) + good/warn/bad ↔
existing good/mid/low mapping; `theme:changed` lifecycle pinned (get() sync +
valid pre-apply, event after commit + once on hydration, plugins read on
mount); same-document-light-DOM scope + shadow/iframe bridge stated;
prefersReducedMotion() named the single JS motion gate.
Resolved open questions folded into the body; the two genuine ones (skins-as-
host-themes, component-recipe bundles) remain.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: byrongamatos <xasiklas@gmail.com>