@hegemonart/get-design-done 1.27.7 → 1.28.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +2 -2
- package/CHANGELOG.md +142 -0
- package/SKILL.md +1 -1
- package/agents/design-verifier.md +17 -0
- package/hooks/gdd-decision-injector.js +149 -3
- package/package.json +1 -1
- package/reference/accessibility.md +4 -0
- package/reference/adr-format.md +96 -0
- package/reference/apply-reflections-procedure.md +68 -0
- package/reference/architecture-vocabulary.md +102 -0
- package/reference/audit-scoring.md +14 -0
- package/reference/cache-policy.md +126 -0
- package/reference/color-theory.md +279 -0
- package/reference/compare-rubric.md +171 -0
- package/reference/composition.md +349 -0
- package/reference/connections-onboarding.md +417 -0
- package/reference/context-md-format.md +106 -0
- package/reference/contrast-advanced.md +205 -0
- package/reference/darkmode-audit-procedure.md +258 -0
- package/reference/debug-feedback-loops.md +119 -0
- package/reference/design-procedure.md +304 -0
- package/reference/design-system-guidance.md +2 -0
- package/reference/discover-procedure.md +204 -0
- package/reference/explore-procedure.md +267 -0
- package/reference/form-patterns.md +2 -0
- package/reference/health-mcp-detection.md +44 -0
- package/reference/health-skill-length-report.md +69 -0
- package/reference/heuristics.md +84 -0
- package/reference/i18n.md +554 -0
- package/reference/iconography.md +2 -0
- package/reference/milestone-completeness-rubric.md +87 -0
- package/reference/motion-interpolate.md +1 -0
- package/reference/palette-catalog.md +2 -0
- package/reference/peer-cli-protocol.md +161 -0
- package/reference/plan-procedure.md +278 -0
- package/reference/proportion-systems.md +267 -0
- package/reference/registry.json +204 -1
- package/reference/registry.schema.json +1 -1
- package/reference/router-rules.md +84 -0
- package/reference/rtl-cjk-cultural.md +2 -0
- package/reference/scan-procedure.md +731 -0
- package/reference/shared-preamble.md +78 -6
- package/reference/skill-authoring-contract.md +128 -0
- package/reference/start-procedure.md +115 -0
- package/reference/style-doc-procedure.md +150 -0
- package/reference/style-vocabulary.md +2 -0
- package/reference/threat-modeling.md +101 -0
- package/reference/typography.md +4 -0
- package/reference/verify-procedure.md +512 -0
- package/reference/visual-hierarchy-layout.md +4 -0
- package/scripts/validate-skill-length.cjs +283 -0
- package/skills/add-backlog/SKILL.md +1 -0
- package/skills/analyze-dependencies/SKILL.md +33 -122
- package/skills/apply-reflections/SKILL.md +1 -40
- package/skills/audit/SKILL.md +3 -1
- package/skills/bandit-status/SKILL.md +31 -66
- package/skills/benchmark/SKILL.md +15 -55
- package/skills/brief/SKILL.md +12 -1
- package/skills/cache-manager/SKILL.md +3 -57
- package/skills/check-update/SKILL.md +38 -75
- package/skills/compare/SKILL.md +29 -269
- package/skills/complete-cycle/SKILL.md +1 -1
- package/skills/connections/SKILL.md +21 -427
- package/skills/continue/SKILL.md +1 -0
- package/skills/darkmode/SKILL.md +32 -287
- package/skills/debug/SKILL.md +11 -8
- package/skills/design/SKILL.md +27 -245
- package/skills/discover/SKILL.md +26 -133
- package/skills/discuss/SKILL.md +18 -2
- package/skills/explore/SKILL.md +42 -176
- package/skills/fast/SKILL.md +1 -0
- package/skills/figma-write/SKILL.md +2 -2
- package/skills/health/SKILL.md +11 -33
- package/skills/help/SKILL.md +1 -0
- package/skills/list-assumptions/SKILL.md +1 -0
- package/skills/map/SKILL.md +8 -31
- package/skills/new-cycle/SKILL.md +3 -1
- package/skills/next/SKILL.md +1 -0
- package/skills/note/SKILL.md +1 -0
- package/skills/optimize/SKILL.md +21 -44
- package/skills/pause/SKILL.md +1 -0
- package/skills/peer-cli-add/SKILL.md +26 -108
- package/skills/peer-cli-customize/SKILL.md +22 -42
- package/skills/peers/SKILL.md +33 -57
- package/skills/plan/SKILL.md +33 -220
- package/skills/plant-seed/SKILL.md +1 -0
- package/skills/pr-branch/SKILL.md +1 -0
- package/skills/progress/SKILL.md +1 -7
- package/skills/quality-gate/SKILL.md +34 -166
- package/skills/quick/SKILL.md +1 -0
- package/skills/reapply-patches/SKILL.md +1 -0
- package/skills/recall/SKILL.md +1 -0
- package/skills/resume/SKILL.md +1 -0
- package/skills/review-backlog/SKILL.md +1 -0
- package/skills/router/SKILL.md +3 -59
- package/skills/scan/SKILL.md +36 -675
- package/skills/settings/SKILL.md +1 -0
- package/skills/ship/SKILL.md +1 -0
- package/skills/sketch/SKILL.md +1 -1
- package/skills/sketch-wrap-up/SKILL.md +13 -54
- package/skills/spike/SKILL.md +1 -1
- package/skills/spike-wrap-up/SKILL.md +12 -46
- package/skills/start/SKILL.md +13 -112
- package/skills/stats/SKILL.md +1 -0
- package/skills/style/SKILL.md +18 -140
- package/skills/synthesize/SKILL.md +1 -0
- package/skills/timeline/SKILL.md +1 -0
- package/skills/todo/SKILL.md +1 -0
- package/skills/turn-closeout/SKILL.md +36 -56
- package/skills/undo/SKILL.md +1 -0
- package/skills/update/SKILL.md +1 -0
- package/skills/verify/SKILL.md +42 -457
- package/skills/warm-cache/SKILL.md +3 -35
- package/skills/zoom-out/SKILL.md +26 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compare-rubric
|
|
3
|
+
type: heuristic
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
phase: 28.5
|
|
6
|
+
tags: [compare, delta, drift, scoring, rubric, extracted]
|
|
7
|
+
last_updated: 2026-05-18
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Source: extracted from `skills/compare/SKILL.md` (Phase 28.5 rework — D-10 extract-then-link).
|
|
11
|
+
The skill's load-bearing workflow stays in `../skills/compare/SKILL.md`; this file holds the
|
|
12
|
+
delta-computation methodology, anti-pattern set arithmetic, drift-detection coverage map,
|
|
13
|
+
and the `COMPARE-REPORT.md` template the skill writes.
|
|
14
|
+
|
|
15
|
+
# Compare Rubric — Baseline vs Result Delta Methodology
|
|
16
|
+
|
|
17
|
+
Detailed methodology for the `get-design-done:compare` standalone command — companion to
|
|
18
|
+
`../skills/compare/SKILL.md`. Read this file when executing a specific compare step (score
|
|
19
|
+
delta math, anti-pattern set arithmetic, drift coverage map, report layout). The SKILL.md
|
|
20
|
+
keeps the load-bearing pre-flight checks + step routing; this file holds the deep methodology.
|
|
21
|
+
|
|
22
|
+
See `./shared-preamble.md#output-contract-reminders` for the per-skill output discipline and
|
|
23
|
+
`./audit-scoring.md` for the 0–10 category-scoring rubric the delta is computed against.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step 1 — Parse Category Scores
|
|
28
|
+
|
|
29
|
+
**Extract baseline scores from `.design/DESIGN.md`:** locate the category score table (rows like `| Accessibility | 6/10 | ... |`). Parse each row: extract category name + numeric score. Store as `baseline_scores` map.
|
|
30
|
+
|
|
31
|
+
**Extract result scores from `.design/DESIGN-VERIFICATION.md`:** locate the same table in the Phase 1 output section. Store as `result_scores` map.
|
|
32
|
+
|
|
33
|
+
**Normalize category names:**
|
|
34
|
+
- Strip leading/trailing whitespace.
|
|
35
|
+
- Apply title-case normalization (e.g., `anti-patterns` → `Anti-Patterns`).
|
|
36
|
+
- Match categories case-insensitively between the two tables.
|
|
37
|
+
|
|
38
|
+
**Unmatched categories:**
|
|
39
|
+
- Baseline-only → flag `[UNMATCHED-BASELINE]`, exclude from score delta.
|
|
40
|
+
- Result-only → flag `[UNMATCHED-RESULT]`, exclude from score delta.
|
|
41
|
+
- Report all unmatched categories in the Notes section. Do NOT silently paper over mismatches.
|
|
42
|
+
|
|
43
|
+
## Step 2 — Compute Score Delta (COMP-03)
|
|
44
|
+
|
|
45
|
+
For each matched category: `delta = result_scores[category] - baseline_scores[category]`.
|
|
46
|
+
|
|
47
|
+
Classify:
|
|
48
|
+
- `improvement` — delta > 0
|
|
49
|
+
- `no_change` — delta == 0
|
|
50
|
+
- `regression` — delta < 0
|
|
51
|
+
|
|
52
|
+
Record per category: name, baseline score, result score, signed delta, classification. Collect regressed categories for drift detection in Step 5.
|
|
53
|
+
|
|
54
|
+
## Step 3 — Anti-Pattern Delta
|
|
55
|
+
|
|
56
|
+
Enumerate anti-patterns in both files (entries identified by BAN-*, SLOP-*, or labeled as anti-patterns). Collect identifiers or descriptions as sets.
|
|
57
|
+
|
|
58
|
+
Compute set arithmetic:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
resolved = baseline_anti_patterns - result_anti_patterns
|
|
62
|
+
(present in baseline, absent in result — fixed)
|
|
63
|
+
|
|
64
|
+
new = result_anti_patterns - baseline_anti_patterns
|
|
65
|
+
(absent in baseline, present in result — introduced)
|
|
66
|
+
|
|
67
|
+
unchanged = intersection of both sets
|
|
68
|
+
(still present in both)
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Report all three groups in the output report.
|
|
72
|
+
|
|
73
|
+
## Step 4 — Must-Have Pass/Fail Change
|
|
74
|
+
|
|
75
|
+
**Skip condition:** if `.design/DESIGN-CONTEXT.md` is absent → emit note and skip this section.
|
|
76
|
+
|
|
77
|
+
Read `<must_haves>` from `DESIGN-CONTEXT.md` (each must-have has ID + description). Read pass/fail status from `DESIGN-VERIFICATION.md` (must-have status table). For each must-have: record `pass`, `fail`, or `not-evaluated`. If `DESIGN.md` contained a prior must-have status section, compute the change (`pass→fail`, `fail→pass`); otherwise report current status only.
|
|
78
|
+
|
|
79
|
+
## Step 5 — Design Drift Detection (COMP-04)
|
|
80
|
+
|
|
81
|
+
**Skip condition:** if `.design/DESIGN-PLAN.md` is absent → emit `"Drift detection skipped: DESIGN-PLAN.md not found."` in the Drift section.
|
|
82
|
+
|
|
83
|
+
**Coverage map:** read `DESIGN-PLAN.md` and extract the `Type:` field from each task. Build a map of which design categories have at least one task of matching Type:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Type: accessibility → covers "Accessibility" category
|
|
87
|
+
Type: color → covers "Color" category
|
|
88
|
+
Type: typography → covers "Typography" category
|
|
89
|
+
Type: visual-hierarchy → covers "Visual Hierarchy" category
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Category-to-Type matching is case-insensitive and normalized.
|
|
93
|
+
|
|
94
|
+
**Drift check:** for each category classified as `regression` in Step 2: if category NOT in coverage_map → emit `DRIFT: [category] regressed from <baseline> to <result> without a design task of Type:<category>`.
|
|
95
|
+
|
|
96
|
+
Emit `"No drift detected. All regressed categories are covered by tasks in DESIGN-PLAN.md."` if all regressed categories are covered. Emit `"No drift detected. No score regressions found."` if no regressions in Step 2.
|
|
97
|
+
|
|
98
|
+
## Step 5B — Screenshot Delta (when preview: available)
|
|
99
|
+
|
|
100
|
+
Check `preview` status from `.design/STATE.md <connections>` (written by the probe at stage entry — see `./shared-preamble.md#connection-handshake-summary`).
|
|
101
|
+
|
|
102
|
+
**If `preview: available`:**
|
|
103
|
+
|
|
104
|
+
1. `preview_start` if no session is already running.
|
|
105
|
+
2. For each route inferred from `DESIGN-PLAN.md` tasks or `src/app/` / `src/pages/` file structure:
|
|
106
|
+
a. `preview_navigate` to route URL (e.g., `http://localhost:3000/<route>`).
|
|
107
|
+
b. `preview_screenshot` → save to `.design/screenshots/before/<route>.png` (only if a prior baseline exists at this path) and `.design/screenshots/after/<route>.png` (current render).
|
|
108
|
+
c. Record reference paths (NOT base64) for embedding in the `## Screenshot Delta` section.
|
|
109
|
+
3. `preview_stop` when all routes are captured.
|
|
110
|
+
|
|
111
|
+
**If `preview: unavailable` or `preview: not_configured`:** emit exactly `Screenshot delta skipped — preview not configured.`
|
|
112
|
+
|
|
113
|
+
## Step 6 — COMPARE-REPORT.md Template
|
|
114
|
+
|
|
115
|
+
Output path: `.design/COMPARE-REPORT.md`. This file MUST NOT be written to any pipeline-reserved path.
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
# Compare Report: Baseline vs Result
|
|
119
|
+
|
|
120
|
+
**Generated:** <ISO 8601 date>
|
|
121
|
+
**Baseline:** .design/DESIGN.md
|
|
122
|
+
**Result:** .design/DESIGN-VERIFICATION.md
|
|
123
|
+
|
|
124
|
+
## Score Delta by Category
|
|
125
|
+
|
|
126
|
+
| Category | Baseline | Result | Delta | Status |
|
|
127
|
+
|----------|----------|--------|-------|--------|
|
|
128
|
+
| Accessibility | 6 | 8 | +2 | improvement |
|
|
129
|
+
| Visual Hierarchy | 5 | 5 | 0 | no_change |
|
|
130
|
+
| Anti-Patterns | 4 | 3 | -1 | regression |
|
|
131
|
+
|
|
132
|
+
## Anti-Pattern Delta
|
|
133
|
+
|
|
134
|
+
**Resolved** (present in baseline, absent in result):
|
|
135
|
+
- <anti-pattern id or description>
|
|
136
|
+
|
|
137
|
+
**New** (absent in baseline, present in result):
|
|
138
|
+
- <anti-pattern id or description>
|
|
139
|
+
|
|
140
|
+
**Unchanged:**
|
|
141
|
+
- <anti-pattern id or description>
|
|
142
|
+
|
|
143
|
+
## Must-Have Status
|
|
144
|
+
|
|
145
|
+
| Must-Have | Status |
|
|
146
|
+
|-----------|--------|
|
|
147
|
+
| <id / description> | pass |
|
|
148
|
+
| <id / description> | fail |
|
|
149
|
+
| <id / description> | not-evaluated |
|
|
150
|
+
|
|
151
|
+
## Design Drift
|
|
152
|
+
|
|
153
|
+
<One of: "No drift detected. ..." | "DRIFT: [Category] regressed ..." | "Drift detection skipped: DESIGN-PLAN.md not found.">
|
|
154
|
+
|
|
155
|
+
## Screenshot Delta
|
|
156
|
+
|
|
157
|
+
<Per-route screenshot pairs OR "Screenshot delta skipped — preview not configured.">
|
|
158
|
+
|
|
159
|
+
## Notes
|
|
160
|
+
|
|
161
|
+
Scope: delta between two existing artifacts (.design/DESIGN.md → .design/DESIGN-VERIFICATION.md).
|
|
162
|
+
No snapshot mechanism — multi-snapshot compare deferred to V2-06.
|
|
163
|
+
This report does not modify DESIGN.md, DESIGN-VERIFICATION.md, or any other pipeline artifact.
|
|
164
|
+
<List any UNMATCHED-BASELINE or UNMATCHED-RESULT categories here, if any.>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
If a section has no items (e.g., no anti-patterns in baseline), write "None."
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
*Imported by: `../skills/compare/SKILL.md`. Maintained as part of Phase 28.5 (Bucket 2 rework — D-10).*
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: composition
|
|
3
|
+
type: layout
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
phase: 28
|
|
6
|
+
tags: [composition, golden-ratio, fibonacci, focal-point, eye-flow]
|
|
7
|
+
last_updated: 2026-05-18
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Composition — Pre-Gestalt Layout Fundamentals
|
|
11
|
+
|
|
12
|
+
The existing [visual hierarchy and layout reference](./visual-hierarchy-layout.md) covers shadow, z-index, whitespace, asymmetry, and the 12-column grid — the *applied* surface of layout. This file gives the upstream foundation those rules silently assume: rule of thirds, the golden ratio and root rectangles, Fibonacci, focal-point construction, visual-weight calculus, optical-vs-mathematical centering, and the Z / F / Gutenberg eye-flow patterns. Where `visual-hierarchy-layout.md` says "place the CTA where the eye lands", this file replaces that hand-wave with explicit grids, ratios, weight formulas, and detection signatures an audit can grep for.
|
|
13
|
+
|
|
14
|
+
This is the file an agent should consult any time it is *constructing* a layout — choosing a grid, placing a focal point, balancing two halves of a composition, centering a glyph next to text, or deciding which eye-flow archetype a page should follow.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Rule of Thirds
|
|
19
|
+
|
|
20
|
+
The rule of thirds divides any canvas into a 3×3 grid with two horizontal and two vertical lines at the 33% and 67% marks. The four intersections of those lines are the *power points* — the locations the eye lands when scanning a composition. Placing a focal element exactly on a power point produces a layout that reads as deliberate and balanced; placing it at dead-center produces a layout that reads as static and posed. The rule is not a law; it is a default that holds until a stronger compositional intent overrides it (centered hero, symmetric mirror, single-axis radial).
|
|
21
|
+
|
|
22
|
+
**Audit detection signature.** Grep for grid declarations using third-fractions, then check whether a focal element (large heading, primary CTA, hero image) sits near one of the four intersections:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Find grids using third-fractions
|
|
26
|
+
grep -rE "grid-template-columns:\s*1fr\s+1fr\s+1fr|33%|66%|33\.33%|66\.66%" src/
|
|
27
|
+
|
|
28
|
+
# Then inspect: does a [data-focal], a primary CTA, or an h1 land near one of those gridlines?
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<!-- Hero layout — CTA placed at the lower-right power point -->
|
|
33
|
+
<section class="hero">
|
|
34
|
+
<div class="hero__copy">
|
|
35
|
+
<h1>Build it once. Ship it everywhere.</h1>
|
|
36
|
+
<p>Lead with the value, not the brand.</p>
|
|
37
|
+
</div>
|
|
38
|
+
<div class="hero__cta">
|
|
39
|
+
<button>Get Started</button>
|
|
40
|
+
</div>
|
|
41
|
+
</section>
|
|
42
|
+
|
|
43
|
+
<style>
|
|
44
|
+
.hero {
|
|
45
|
+
display: grid;
|
|
46
|
+
grid-template-columns: 1fr 1fr 1fr; /* thirds — vertical gridlines at 33% / 67% */
|
|
47
|
+
grid-template-rows: 1fr 1fr 1fr; /* thirds — horizontal gridlines at 33% / 67% */
|
|
48
|
+
min-height: 80vh;
|
|
49
|
+
}
|
|
50
|
+
.hero__copy {
|
|
51
|
+
grid-column: 1 / 3; /* fills the left two-thirds */
|
|
52
|
+
grid-row: 2 / 3; /* sits on the upper-third horizontal line */
|
|
53
|
+
align-self: center;
|
|
54
|
+
}
|
|
55
|
+
.hero__cta {
|
|
56
|
+
grid-column: 3 / 4; /* rightmost third */
|
|
57
|
+
grid-row: 3 / 4; /* lower-third row */
|
|
58
|
+
align-self: end;
|
|
59
|
+
justify-self: end; /* lower-right power point (67%, 67%) */
|
|
60
|
+
}
|
|
61
|
+
</style>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The CTA sits at the lower-right intersection — the natural Z-pattern terminus (see [§Eye-Flow Patterns](#eye-flow-patterns)). The headline anchors the upper-left third where reading begins.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Golden Ratio and Root Rectangles
|
|
69
|
+
|
|
70
|
+
Beyond thirds, four irrational ratios govern compositions that need to feel *proportional* rather than *gridded*: φ (the golden ratio), √2, √3, and √5. Each rectangle has a different subdivision behavior — when you remove the largest possible square from inside it, the remainder has a specific relationship to the original. φ produces another φ-rectangle (infinitely self-similar — the source of the golden spiral). √2 produces a rectangle that, when folded in half, is still √2 (the math behind A0 / A1 / A2 paper). √3 produces a √3 / 2 rectangle. √5 produces two squares plus a φ-rectangle and is the bridge from integer roots back to φ via the identity `φ = (1 + √5) / 2`.
|
|
71
|
+
|
|
72
|
+
### φ-Grid (Golden Ratio)
|
|
73
|
+
|
|
74
|
+
φ ≈ 1.618. A φ-rectangle has its short side to long side in ratio `1 : 1.618`. When the same ratio governs the relationship between a sidebar and main content, an image and its caption block, or a heading and its body text, the layout reads as *naturally weighted* — neither cramped nor empty. The catch is that φ is opinionated: it pulls compositions toward warmth and editorial feel, away from grid-locked rigidity. Use it where the design wants to feel hand-tuned, not where it must align to a strict baseline grid.
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
/* φ-grid — sidebar:content ratio of 1:1.618 */
|
|
78
|
+
.layout {
|
|
79
|
+
display: grid;
|
|
80
|
+
grid-template-columns: 1fr 1.618fr; /* φ */
|
|
81
|
+
gap: var(--space-6);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Image card with φ-proportioned caption block */
|
|
85
|
+
.card {
|
|
86
|
+
display: grid;
|
|
87
|
+
grid-template-rows: 1.618fr 1fr; /* image : caption = φ : 1 */
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Root Rectangles — √2, √3, √5
|
|
92
|
+
|
|
93
|
+
| Ratio | Value | Subdivision property | UI fit |
|
|
94
|
+
| ----- | ------ | ------------------------------------------------------- | --------------------------------------------------------------- |
|
|
95
|
+
| √2 | 1.414 | Halving produces another √2 rectangle (ISO paper sizes) | Editorial / print-adjacent UI; documents, articles, long-reads |
|
|
96
|
+
| √3 | 1.732 | Subdivides into three √3 / 2 rectangles | Music, data, spreadsheet-adjacent surfaces with triadic rhythm |
|
|
97
|
+
| √5 | 2.236 | Decomposes into 2 squares + a φ-rectangle | Bridge to φ; very wide hero panels, marquee bands |
|
|
98
|
+
| φ | 1.618 | Removing the largest square leaves another φ-rectangle | Editorial, naturalistic, "hand-tuned" feel |
|
|
99
|
+
|
|
100
|
+
```css
|
|
101
|
+
/* √2 rectangle — print-adjacent article card */
|
|
102
|
+
.article-card {
|
|
103
|
+
aspect-ratio: 1 / 1.414; /* √2 — same proportion as A4 paper */
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* √3 rectangle — triadic data tile */
|
|
107
|
+
.data-tile {
|
|
108
|
+
aspect-ratio: 1 / 1.732;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Dynamic Symmetry
|
|
113
|
+
|
|
114
|
+
Dynamic symmetry (Jay Hambidge, 1920) draws *armatures* inside root rectangles: the diagonal of the whole rectangle plus perpendiculars dropped from each corner to that diagonal. The intersections form anchor points for focal elements. The technique is older than the rule of thirds, more flexible, and produces compositions that hold together at different sizes (responsive layouts) because the armature is ratio-based, not pixel-based. In UI, dynamic symmetry shows up implicitly any time a hero image and its caption follow the diagonal of a φ or √2 rectangle.
|
|
115
|
+
|
|
116
|
+
### Fibonacci
|
|
117
|
+
|
|
118
|
+
The Fibonacci sequence — `1, 1, 2, 3, 5, 8, 13, 21, 34, 55, …` — approaches φ as the ratio between consecutive terms (8 / 5 = 1.6; 13 / 8 = 1.625; 21 / 13 = 1.615). The square-rectangle subdivision pattern uses Fibonacci numbers as side lengths: a 1×1 square next to a 1×1 square forms a 1×2, append a 2×2 to make a 3×2, append a 3×3 to make a 5×3, and so on — each new square's side is the previous two added together. The diagonal through these squares traces the golden spiral.
|
|
119
|
+
|
|
120
|
+
In UI, Fibonacci numbers show up in two places: (a) spacing scales — `4 8 12 20 32 52 84` is a Fibonacci-flavored scale (and see [./visual-hierarchy-layout.md §Whitespace as Design Element](./visual-hierarchy-layout.md) for the applied scale); (b) content sizing where natural proportion matters more than strict alignment (a 5-column / 3-column / 2-column nested layout reads as proportional because consecutive Fibonacci pairs approach φ). Fibonacci is the *integer-friendly approximation of φ* — use it when you want φ's feel but need round numbers for token systems.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Focal-Point Construction
|
|
125
|
+
|
|
126
|
+
Every composition declares 0, 1, or 2+ focal points. A composition with 0 focal points reads as a pattern or texture — fine for backgrounds, wrong for content. A composition with too many focal points reads as noisy and unfocused. Choosing the right count is the first compositional decision; placing them on a power point or armature anchor is the second.
|
|
127
|
+
|
|
128
|
+
### Single-Focal
|
|
129
|
+
|
|
130
|
+
One element dominates — significantly larger, higher contrast, more isolated, or more saturated than every sibling. The eye lands once and stays. Fits archetypes where there is exactly one decision to make or one piece of information to absorb.
|
|
131
|
+
|
|
132
|
+
- **UI archetypes:** landing hero, empty state, error page, sign-in / sign-up form, paywall, confirmation modal, onboarding step.
|
|
133
|
+
- **Audit detection:** one element scores ≥ 1.5× the visual weight of every other element on the page (see [§Visual-Weight Calculus](#visual-weight-calculus)).
|
|
134
|
+
- **Common failure:** decorative imagery competing with the primary CTA — image and CTA weight scores within 10%, eye bounces between them.
|
|
135
|
+
|
|
136
|
+
### Dual-Focal
|
|
137
|
+
|
|
138
|
+
Two elements compete intentionally — same weight, placed at opposite power points or mirrored across an axis. The eye is invited to compare. Fits archetypes where the user is choosing between exactly two paths.
|
|
139
|
+
|
|
140
|
+
- **UI archetypes:** pricing compare view (basic vs. pro), before/after slider, plan-A vs. plan-B, A/B testimonial pair, fork-in-the-road CTA (Login | Sign Up).
|
|
141
|
+
- **Audit detection:** exactly two elements with visual weights within 10% of each other and weights ≥ 2× the third-heaviest element; they sit on opposing thirds-power-points or mirror axes.
|
|
142
|
+
- **Common failure:** the two focal elements drift in weight as one gets a "recommended" badge — what was dual-focal becomes single-focal with a decorative competitor.
|
|
143
|
+
|
|
144
|
+
### Distributed
|
|
145
|
+
|
|
146
|
+
Three or more elements share weight — none dominates, all are roughly equal. The eye scans rather than locks on. Fits archetypes built around browse-and-select rather than read-and-act.
|
|
147
|
+
|
|
148
|
+
- **UI archetypes:** dashboard (multiple cards / KPIs / charts), gallery, product grid, settings index, file browser, kanban board.
|
|
149
|
+
- **Audit detection:** ≥ 3 elements with visual weights all within 25% of each other; total visual weight is high but no single element exceeds 1.3× the median.
|
|
150
|
+
- **Common failure:** one card accidentally gains a colored background and becomes a de facto focal point; the layout's "grid of equals" reads as "one promoted item plus its supporting cast".
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Visual-Weight Calculus
|
|
155
|
+
|
|
156
|
+
Visual weight is the *perceived heaviness* of an element — how strongly the eye is pulled to it relative to neighbors. It is the product of four factors, each normalized to 0..1:
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
weight = size × contrast × isolation × complexity
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- **Size** (0..1): the element's area normalized against the largest element on the page. A hero headline at full container width might be 1.0; a footer link at 12px might be 0.05.
|
|
163
|
+
- **Contrast** (0..1): luminance contrast against the immediate background, normalized against the page's maximum contrast pair. Black on white is 1.0; mid-gray on light-gray might be 0.2.
|
|
164
|
+
- **Isolation** (0..1): empty-space margin around the element, normalized against the largest margin on the page. Generous whitespace lifts the score; cramped neighbors lower it.
|
|
165
|
+
- **Complexity** (0..1): internal structure — an image with detail scores higher than a flat color block of the same size; a button with an icon plus a label plus a chevron scores higher than a plain text link.
|
|
166
|
+
|
|
167
|
+
The formula is multiplicative because each factor is necessary — an element with massive size but zero contrast (white text on white) has zero visual weight, regardless of isolation or complexity.
|
|
168
|
+
|
|
169
|
+
### Worked Example — 3 elements in a landing hero
|
|
170
|
+
|
|
171
|
+
Suppose a hero contains a headline, a primary CTA, and a secondary text link.
|
|
172
|
+
|
|
173
|
+
| Element | Size | Contrast | Isolation | Complexity | Weight |
|
|
174
|
+
| ---------------------- | ----- | -------- | --------- | ---------- | ----------------------------- |
|
|
175
|
+
| Headline (H1, 64px) | 0.90 | 0.95 | 0.80 | 0.30 | `0.90 × 0.95 × 0.80 × 0.30` = **0.205** |
|
|
176
|
+
| Primary CTA (button) | 0.25 | 0.90 | 0.70 | 0.60 | `0.25 × 0.90 × 0.70 × 0.60` = **0.095** |
|
|
177
|
+
| Secondary text link | 0.10 | 0.40 | 0.30 | 0.20 | `0.10 × 0.40 × 0.30 × 0.20` = **0.002** |
|
|
178
|
+
|
|
179
|
+
The headline dominates (weight ≈ 0.2), the CTA is secondary (≈ 0.1, half the headline), the text link is near-invisible (≈ 0.002, two orders of magnitude lighter). This is correct for a hero that wants the user to read the headline, then act on the CTA, with the text link as a low-stakes escape hatch.
|
|
180
|
+
|
|
181
|
+
### "Balanced" — defined numerically
|
|
182
|
+
|
|
183
|
+
A two-sided composition is **balanced** when the sum of visual weights on each side of the optical center is within ~20% of the other. Three or more elements distributed are balanced when no single element exceeds 1.3× the median weight (see distributed-focal detection above).
|
|
184
|
+
|
|
185
|
+
### Audit detection signature for imbalance
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
# Pseudo-procedure for a layout auditor:
|
|
189
|
+
# 1. Identify every visible element ≥ 16px tall / 16px wide.
|
|
190
|
+
# 2. Score each on the four axes (size, contrast, isolation, complexity).
|
|
191
|
+
# 3. Multiply to get weight.
|
|
192
|
+
# 4. Sum weights on the left and right of the optical center.
|
|
193
|
+
# 5. If left_sum > 1.5 × right_sum (or right > 1.5 × left), flag IMBALANCED.
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The 1.5× threshold catches obvious imbalance; the 20%-of-each-other rule is the *target* a balanced composition aims for. The gap between 20% and 50% is where a human designer's eye is needed — the formula declares "not obviously broken", not "definitively good".
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Optical vs. Mathematical Centering
|
|
201
|
+
|
|
202
|
+
The pixel center of a bounding box is rarely the visual center of the *thing inside the box*. Glyphs have asymmetric ink distribution; icons have asymmetric stroke weight; characters have descenders, ascenders, cap-height, and x-height that do not all line up with the box edges. Mathematical centering — `display: flex; align-items: center; justify-content: center;` — produces a result that *looks* off-center to the eye in three common cases:
|
|
203
|
+
|
|
204
|
+
- An icon glyph with directional weight (a play triangle pointing right has more ink on the left half of its bounding box and reads as shifted-left when math-centered).
|
|
205
|
+
- A button label aligned next to an icon — the label's x-height pulls the label's optical center *below* the icon's optical center.
|
|
206
|
+
- Mixed cap-height + x-height text aligned to a baseline — capitals look "too high" because their cap-height extends above the x-height where the eye expects the line to live.
|
|
207
|
+
|
|
208
|
+
### Asymmetric Glyph Weight — the −1px nudge
|
|
209
|
+
|
|
210
|
+
A right-pointing play triangle visually balances when its bounding box is shifted ~1 px (or 1.5–2 px at larger sizes) to the *right* of the mathematical center. The shift accounts for the empty wedge on the triangle's right side.
|
|
211
|
+
|
|
212
|
+
```css
|
|
213
|
+
/* Mathematically centered play button — looks shifted-LEFT to the eye */
|
|
214
|
+
.btn-play .icon-play { transform: translateX(0); }
|
|
215
|
+
|
|
216
|
+
/* Optically centered — −1px to nudge the visually-heavy edge toward the center */
|
|
217
|
+
.btn-play .icon-play {
|
|
218
|
+
transform: translateX(1px); /* compensate the empty wedge on the right */
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* At larger glyph sizes the nudge scales — roughly 2–3% of the glyph width */
|
|
222
|
+
.btn-play-lg .icon-play {
|
|
223
|
+
transform: translateX(2px);
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
See [./iconography.md](./iconography.md) §1 "Optical Sizing & Stroke Weight" for the broader rules governing stroke-weight optics. The play-triangle case is the prototypical example; the same logic applies to chevrons, asymmetric arrows, and any glyph with a directional point.
|
|
228
|
+
|
|
229
|
+
### Cap-Height vs. X-Height Alignment
|
|
230
|
+
|
|
231
|
+
When a label sits next to an icon, the icon should align to the **cap-height** of capital letters in the label — not the x-height of lowercase, not the baseline. The eye reads the icon's center against the strongest vertical anchor in the type, and cap-height is that anchor. Aligning to x-height makes the icon look "low"; aligning to baseline makes it look "too low".
|
|
232
|
+
|
|
233
|
+
```css
|
|
234
|
+
/* Button with leading icon — align icon to cap-height of label */
|
|
235
|
+
.btn {
|
|
236
|
+
display: inline-flex;
|
|
237
|
+
align-items: center; /* approximate cap-height center */
|
|
238
|
+
gap: 0.5em;
|
|
239
|
+
line-height: 1; /* tighten so cap-height ≈ box-center */
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.btn__icon {
|
|
243
|
+
width: 1em; /* match cap-height, not x-height */
|
|
244
|
+
height: 1em;
|
|
245
|
+
display: inline-block;
|
|
246
|
+
vertical-align: -0.1em; /* fine-tune — icon-by-icon optical nudge */
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* For icon-plus-text where the type has a large x-height ratio (Inter, IBM Plex):
|
|
250
|
+
align-items: baseline is wrong (sinks the icon).
|
|
251
|
+
align-items: center with line-height: 1 keeps the icon at cap-center. */
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The cap-height anchor logic is one half of the story; the other half — modular scale, x-height ratios per typeface — lives in [./typography.md](./typography.md) §Type Scale Systems and §Modular Scale.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Eye-Flow Patterns
|
|
259
|
+
|
|
260
|
+
A page is not read pixel-by-pixel. The eye follows one of three default patterns shaped by reading direction (LTR Western languages assumed; RTL mirrors these horizontally), content density, and the kind of decision the user is making. Designing *against* the dominant pattern produces friction; designing *with* it produces effortless scanning.
|
|
261
|
+
|
|
262
|
+
### Z-Pattern — landing pages, conversion flows
|
|
263
|
+
|
|
264
|
+
The Z-pattern fits sparse, hero-led pages with a clear call to action. The eye lands top-left (logo / brand), sweeps top-right (secondary nav / brand CTA), diagonals down-left (hero headline / body), then sweeps bottom-right (primary CTA terminus). Each anchor of the Z gets one element; the diagonal is the "story" connecting them.
|
|
265
|
+
|
|
266
|
+
```txt
|
|
267
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
268
|
+
│ [Logo] ─────────────────────────────────→ [Nav | Login] │ 1. top-left → top-right
|
|
269
|
+
│ │
|
|
270
|
+
│ │
|
|
271
|
+
│ ╲ │
|
|
272
|
+
│ ╲ │ 2. diagonal sweep
|
|
273
|
+
│ ╲ │
|
|
274
|
+
│ ╲ │
|
|
275
|
+
│ │
|
|
276
|
+
│ [Headline] │ 3. bottom-left
|
|
277
|
+
│ [Body] │
|
|
278
|
+
│ Lorem ipsum dolor sit amet ────────────→ [ Get Started ] │ 4. bottom-right CTA
|
|
279
|
+
└──────────────────────────────────────────────────────────────┘
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Pair with single-focal-point construction (the CTA at the lower-right power point — same coordinate as the rule-of-thirds example above).
|
|
283
|
+
|
|
284
|
+
### F-Pattern — content-heavy, scanning surfaces
|
|
285
|
+
|
|
286
|
+
The F-pattern fits dense pages a user scans rather than reads — search results, news feeds, documentation, settings pages, listings. The eye sweeps horizontally across the top, drops to a shorter horizontal sweep mid-page, then runs vertically down the left edge sampling row-openers. Headings, leading icons, and the first 2–3 words of each row do the heaviest signaling work; deep right-side content gets skipped.
|
|
287
|
+
|
|
288
|
+
```txt
|
|
289
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
290
|
+
│ ════════════════════════════════════════════════════════ │ 1. top sweep (full width)
|
|
291
|
+
│ ─ list item 1 ─ ── ── ── ── ── ── ── ── ── ── ── ── ── ── │
|
|
292
|
+
│ ──── ─── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── │
|
|
293
|
+
│ ══════════════════════════════ ─── ── ── ── ── ── │ 2. mid sweep (partial)
|
|
294
|
+
│ ─ list item 2 │
|
|
295
|
+
│ ──── ─── ── ── ── ── ── ── ── ── │
|
|
296
|
+
│ ─ list item 3 │
|
|
297
|
+
│ ─── ── ── ── ── ── ── ── ── ── ── │
|
|
298
|
+
│ ─ list item 4 │ 3. left-edge sample
|
|
299
|
+
│ ─ list item 5 │
|
|
300
|
+
│ ─ list item 6 │
|
|
301
|
+
└──────────────────────────────────────────────────────────────┘
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Pair with distributed-focal-point construction. Front-load row-openers (titles, leading icons, status indicators) on the left edge. Avoid burying critical information on the right side of rows; the eye does not look there.
|
|
305
|
+
|
|
306
|
+
### Gutenberg Diagram — editorial, reading-heavy
|
|
307
|
+
|
|
308
|
+
The Gutenberg diagram applies to text-dense reading surfaces — long-form articles, blog posts, terms-of-service pages, documentation prose. The eye follows a *reading gravity* from the top-left (primary optical area) diagonally to the bottom-right (terminal area), and the two off-diagonal quadrants — top-right (strong fallow area) and bottom-left (weak fallow area) — receive much less attention. Placing critical information in the fallow areas guarantees it goes unread.
|
|
309
|
+
|
|
310
|
+
```txt
|
|
311
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
312
|
+
│ ★ Primary Optical Area │ ✕ Strong Fallow Area │
|
|
313
|
+
│ (eye lands here first) │ (skipped on first scan) │
|
|
314
|
+
│ │ │
|
|
315
|
+
│ Heading │ side note / decorative │
|
|
316
|
+
│ Lead paragraph... │ │
|
|
317
|
+
│ ────────────────────────────────────────────── │
|
|
318
|
+
│ │ │
|
|
319
|
+
│ ✕ Weak Fallow Area │ ★ Terminal Area │
|
|
320
|
+
│ (rarely returned to) │ (eye comes to rest here) │
|
|
321
|
+
│ │ │
|
|
322
|
+
│ │ Conclusion / CTA │
|
|
323
|
+
└──────────────────────────────────────────────────────────────┘
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Pair with single-focal-point construction. The terminal area is the natural home for a "next" action — a Read More link, a Subscribe CTA, a tip-jar button. Critical content does NOT go in either fallow area.
|
|
327
|
+
|
|
328
|
+
### Choosing the pattern
|
|
329
|
+
|
|
330
|
+
| UI archetype | Eye-flow pattern | Focal-point construction |
|
|
331
|
+
| ----------------------------------------------------- | ----------------- | ------------------------ |
|
|
332
|
+
| Landing page, sign-up, hero-led marketing | Z | Single |
|
|
333
|
+
| Pricing compare, before/after, plan-A vs plan-B | Z (mirrored) | Dual |
|
|
334
|
+
| Search results, news feed, settings index, dashboard | F | Distributed |
|
|
335
|
+
| Documentation, listing, kanban, gallery | F | Distributed |
|
|
336
|
+
| Long-form article, blog post, terms of service | Gutenberg | Single (terminal CTA) |
|
|
337
|
+
| Email newsletter, editorial layout | Gutenberg | Single or dual |
|
|
338
|
+
|
|
339
|
+
For RTL languages (Arabic, Hebrew, Urdu, Farsi) the Z-pattern and Gutenberg diagram mirror horizontally; the F-pattern's left-edge becomes a right-edge sample. See [./visual-hierarchy-layout.md §Asymmetry and Rhythm](./visual-hierarchy-layout.md) for the applied rhythm rules that pair with each pattern.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Cross-References
|
|
344
|
+
|
|
345
|
+
- [./visual-hierarchy-layout.md](./visual-hierarchy-layout.md) — §Compositional Grids (responsive column + baseline grid) and §Asymmetry and Rhythm; composition is the upstream foundation that file assumes.
|
|
346
|
+
- [./iconography.md](./iconography.md) — §1 Optical Sizing & Stroke Weight; the optical-centering rules in this file apply directly to icon glyphs.
|
|
347
|
+
- [./typography.md](./typography.md) — §Type Scale Systems and §Modular Scale; the cap-height vs. x-height alignment rule depends on those scale relationships.
|
|
348
|
+
|
|
349
|
+
Reciprocal inbound cross-links land in Phase 28-06 (additive-only, D-06).
|