Wrap any HTML artifact with a side panel of live controls that rewrite
CSS custom properties in real time and persist to localStorage.
Inspired by the huashu-design tweak pattern.
A single self-contained HTML file with two layers:
--accent, --scale, --density, --mode, --motion.localStorage keyed
by the artifact identifier.The user can:
Pick a subset that suits the artifact. Don't ship all 5 if only 2 matter — clutter is a regression.
--accent — Accent colorA select with 5–8 curated swatches (don't ship a free color picker — the user will pick a bad color and blame you).
const ACCENT_PRESETS = [
{ id: 'rust', val: '#c96442', label: 'Rust' },
{ id: 'cobalt', val: '#2c4d8e', label: 'Cobalt' },
{ id: 'sage', val: '#4a7a3f', label: 'Sage' },
{ id: 'plum', val: '#7a3f6a', label: 'Plum' },
{ id: 'graphite',val: '#3a3a3a', label: 'Graphite' },
];
The artifact uses var(--accent) everywhere it had a hard-coded
accent before. Border / link / pull-quote rule / CTA all flip
together.
--scale — Type scale (0.85 / 1.0 / 1.15)Three settings: Compact (0.85), Normal (1.0), Generous (1.15).
All font-size declarations multiply by var(--scale) via
calc(... * var(--scale)).
Don't go beyond ±15% — beyond that the layout breaks (column flow, breakpoints, line counts).
--density — Layout density (Tight / Normal / Roomy)Three settings that swap the spacing scale: Tight (0.75) /
Normal (1.0) / Roomy (1.4). All padding / gap / margin
declarations multiply by var(--density).
This is the highest-impact knob — it's also the most fragile, so every layout-critical container must declare its base spacing in custom properties before you wrap.
--mode — Light / DarkA 2-state toggle. Sets data-mode="light" vs "dark" on the
<html> element and the artifact's :root selector responds with
two color sets.
If the artifact already has a media-query-based dark mode, replace it with the data-attr version — the user's choice should win over their OS.
--motion — Off / Subtle / LivelyThree settings. Maps to a CSS variable --motion-mult that scales
all transition-duration / animation-duration declarations:
0s (also disables WebGL canvases / decorative animation).1.0 (the artifact's authored timing).1.6 (slower transitions, more visible motion).Respect prefers-reduced-motion: default to Off if the user has
that set, regardless of stored preference.
Read assets/wrap.html — it ships the panel + bridge as an
inert template. Your job is to:
#hex / Npx / Nrem and convert).wrap.html.assets/wrap.html's KNOBS array to keep only the knobs
you decided are relevant to this artifact. Don't ship 5 if 2
matter.STORAGE_KEY to a unique slug (tweaks-<artifact-slug>).The bridge in wrap.html:
localStorage[STORAGE_KEY] JSON on first paint.document.documentElement.style.setProperty('--accent', ...).change event and writes back.Same options as the critique skill:
index.html in the project folder).Read the artifact's CSS first. For each knob, decide yes / no:
--accent — yes if the artifact has 1 accent color used ≥ 3 times.--scale — yes if the artifact is type-driven (article, deck,
pricing page).--density — yes if the artifact has consistent gap / padding
rhythm (deck, dashboard, landing). No for runbooks (already dense).--mode — yes if the artifact has authored dark mode tokens, or
you're willing to derive them.--motion — yes if the artifact has any transition / animation
worth scaling. No for static reports / critique reports.Default: 3 knobs is the sweet spot. Five is too busy, one is not worth a panel.
Open assets/wrap.html's <style> block — copy its custom-property
naming scheme (--accent, --scale, etc.). In the user's artifact,
find every place those concerns live and rewrite:
color: #c96442 → color: var(--accent)
font-size: 18px → font-size: calc(18px * var(--scale))
padding: 24px 32px → padding: calc(24px * var(--density)) calc(32px * var(--density))
transition: opacity 200ms → transition: opacity calc(200ms * var(--motion-mult))
If the artifact uses clamp() or vw already, multiply the
outer value by the custom property — don't tear apart clamp(...).
Copy the artifact's <style> and <body> into the marked regions
of wrap.html. Keep the panel + bridge intact.
Open the result, click each knob at least once, refresh the page, confirm the choice persists. If a knob breaks the layout — remove it, don't ship it.
<artifact identifier="tweaks-<artifact-slug>" type="text/html" title="<Artifact Title> · Tweaks">
<!doctype html>
<html>...</html>
</artifact>
One sentence before the artifact ("Wrapped X with a 3-knob tweak
panel — accent / scale / mode."). Stop after </artifact>.
tweaks-<slug>, not a global
key. Two artifacts open in two tabs must not share state.prefers-reduced-motion — default to Off for motion
if the user has that set, override only on explicit click.