HaTchi-MaXchi — the Dazzle House Aesthetic¶
Canonical, agent-readable definition of Dazzle's visual taste — the HaTchi-MaXchi style (pronounced "hachi machi"; the capitals spell its HTMX substrate). Consumed by: framework CSS/token authors (now), the authoring agent and the improve loop (follow-ons).
Enforced by: the blind taste panel (dazzle qa taste-panel — scriptable
exit code, the Phase 2–4 convergence gate), the opt-in composition analyze
taste focus (focus=["taste"]), and the per-rule gates listed below.
- Spec:
docs/superpowers/specs/2026-07-02-taste-house-aesthetic-design.md - Baseline:
dev_docs/taste/baseline-2026-07-02.md(all six dimensions FAIL; fleet 2.4–3.2 vs references 5.1–5.8 on a 10-point scale) - Rubric source of truth:
src/dazzle/core/taste_rubric.py(this document is drift-gated against it bytests/unit/test_taste_doc_drift.py)
Parity target, not mimicry. HaTchi-MaXchi competes with the
shadcn/Tailwind/Vercel dialect on perceived quality, never on mechanism:
semantic root classes + data-dz-* modifiers + design tokens, no
utility-class proliferation, no client-state framework. The judged rubric is
deliberately dialect-neutral (Goodhart guard).
Principles¶
-
Semantic surface, expressive result. One root class per component +
data-dz-*modifiers; tokens carry the aesthetic. Agent-hostile class soup is a rule violation, not a style choice. -
Type does the hierarchy. A disciplined scale and weight system carries visual importance — headings, labels, values and captions each have a recognisable role. Boxes and chrome never substitute for type.
-
One accent; neutrals do the work. Color appears when it means something. Neutral ramps carry structure; the accent marks the primary action or focus; semantic tones (success/warning/danger) are reserved for meaning.
-
Depth is information. Elevation encodes layering and interactivity — never decoration. Shadows are stacked, low-alpha, and consistent per elevation level.
-
Motion confirms, never entertains. 100–200ms, derived from the request lifecycle, honoring
prefers-reduced-motioneverywhere. -
Dark is a material, not an inversion. A designed dark neutral ramp; elevation reads through lightness; accents and semantic tones are recalibrated for the dark context.
-
Density with rhythm. Data-dense, but every gap sits on the spacing scale; related items cluster, unrelated items separate.
-
Every state is designed. Hover, focus, active, disabled, loading, empty, error — no browser defaults showing through, no accidental empty regions.
-
The structure is the style. The HaTchi-MaXchi signature: HTMX4 anatomy is expressed, not hidden. Swap targets read as coherent surfaces,
hx-indicatorand the htmx request-lifecycle classes drive the loading/motion language (skeleton shimmer, settle transitions), boosted navigation feels like part of the material. The design language and the transport share one skeleton — a differentiator no client-state dialect can copy honestly.
Rules¶
Each rule states its motivating baseline evidence and its enforcement. Rules marked advisory become gated as Phases 2–3 land the machinery.
-
TASTE-1 — Every interactive element gets a designed focus ring: 2px accent at ~40% alpha, 2px offset, on
:focus-visible. (Principle 8; evidence: state_completeness gap 2.46 — judges saw browser-default focus/affordances. Enforcement: token + component CSS in Phase 2; panel dimensionstate_completeness.) -
TASTE-2 — Shadows are stacked low-alpha pairs bound to elevation tokens; never a single hard drop-shadow, never ad-hoc values. (Principle 4; evidence: perceived_craft gap 3.24, the widest and most judge-agreed gap. Enforcement: shadow tokens in Phase 2; panel
perceived_craft.) -
TASTE-3 — One accent hue per app, applied to the primary action and active states only; all other structure comes from the neutral ramp; semantic tones only where they carry meaning. (Principle 3; evidence: color_discipline gap 2.59 — accent exists but semantics muddy. Enforcement: token sheet v2 ramps; panel
color_discipline.) -
TASTE-4 — Every gap, padding and margin sits on the spacing scale; no off-scale one-off values in component CSS. (Principle 7; evidence: spatial_rhythm gap 2.75. Enforcement: advisory until the Phase 3 component pass; panel
spatial_rhythm.) -
TASTE-5 — Text roles are typographically distinct: page title, section heading, label, value, caption each differ in at least two of size/weight/color-step. Tabular numerals in data tables. (Principle 2; evidence: typographic_hierarchy gap 2.44 — "near-uniform text sizes". Enforcement: type-scale tokens + Geist in Phase 2; panel
typographic_hierarchy.) -
TASTE-6 — Icons come only from the vendored Lucide registry via the
Iconfragment primitive — inline SVG, sized on the type scale, never icon fonts, emoji-as-UI, or ad-hoc SVGs. (Principle 1/8; evidence: perceived_craft — "no icon language" was a recurring judge note. Enforcement: icon registry drift gate, Phase 2.) -
TASTE-7 — Dark mode uses the designed dark ramp: surfaces lighten with elevation, borders replace shadows where shadows die, accents and semantic tones are dark-recalibrated. Never a naive inversion. (Principle 6; evidence: dark_mode_integrity 3.13 — "inverted-looking". Enforcement: dark ramp tokens + WCAG pair test, Phase 2; panel
dark_mode_integrity.) -
TASTE-8 — Empty states are designed: an icon, one sentence, and the primary action — never a bare "No X yet" line in an otherwise blank card, and never an unexplained blank region. (Principle 8; evidence: worst-scoring screens were empty/denied workspaces, down to 1.27. Enforcement: advisory until Phase 3; panel
state_completeness.) -
TASTE-9 — Loading and settling states derive from the htmx request lifecycle (
hx-indicator, request/settle classes → skeleton shimmer, 100–200ms settle transitions), withprefers-reduced-motionhonored. (Principle 9/5; evidence: not judgeable from stills — enforced by the interaction walks, not the panel. Advisory until Phase 2 motion tokens.) -
TASTE-10 — Corner radii come from the radius scale and are consistent per component family (inputs and buttons share a radius; cards share a larger one). (Principle 1/4; evidence: perceived_craft — "inconsistent radii/borders". Enforcement: token sheet v2; panel
perceived_craft.) -
TASTE-11 — Text contrast meets WCAG AA against its actual surface token in both themes; the token sheet is the unit under test. (Principle 6/3. Enforcement: contrast unit test over token pairs, Phase 2 — closes a named gap: no machine contrast gate exists today.)
-
TASTE-12 — No utility-class accretion: components keep one semantic root class +
data-dz-*modifiers; new visual variation goes through tokens or a modifier, never a class pile. (Principle 1. Enforcement: existing card-safety/contract scanners keep the floor; advisory beyond that.)
Rubric¶
The judged dimensions live in src/dazzle/core/taste_rubric.py (single
source of truth; this table is drift-gated).
| Key | Title | Applies to |
|---|---|---|
typographic_hierarchy |
Typographic hierarchy | both |
spatial_rhythm |
Spatial rhythm | both |
color_discipline |
Color discipline | both |
state_completeness |
State completeness | both |
dark_mode_integrity |
Dark-mode integrity | dark |
perceived_craft |
Perceived craft | both |
Composition note: composition analyze focus=["taste"] runs the
theme-agnostic five; dark_mode_integrity must be requested by name
against known-dark captures (composition captures carry no theme info).
The parity gate¶
# capture references (third-party pixels stay gitignored)
python scripts/taste/capture_references.py
# capture the fleet, per app (above-fold + dark are REQUIRED for parity)
dazzle qa capture --app <app> --url <URL> --above-fold --manifest fleet.json
dazzle qa capture --app <app> --url <URL> --above-fold --dark --manifest fleet-dark.json
# run the blind panel (exit 0 = parity on every dimension)
dazzle qa taste-panel --manifest fleet-merged.json --judges 3 --noise-runs 2
The panel top-crops every image to the reference frame
(normalize_pool_frames), interleaves sources blindly, and applies
per-dimension margins locked by the 2026-07-02 baseline:
margin = max(0.5, 2 × judge noise SD) —
| Dimension | Locked margin | Baseline gap |
|---|---|---|
| perceived_craft | 0.50 | 3.24 |
| spatial_rhythm | 0.82 | 2.75 |
| color_discipline | 1.63 | 2.59 |
| state_completeness | 0.58 | 2.46 |
| typographic_hierarchy | 1.15 | 2.44 |
| dark_mode_integrity | 1.15 | 1.97 |
Phases 2–4 (foundations → component pass → example convergence) end when
the fleet clears every margin. Protocol invariants for re-judging: same
frame, same rubric, unseeded apps, persona-matched workspace sampling
(fixing the _platform_admin over-selection noted in the baseline).