@jabworks/condux 0.14.2 → 0.15.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jabworks/condux",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "OpenCode plugin for the condux workflow toolkit — bundles the condux skills and injects the specialist agents (coder, explorer, planner, researcher) plus an opt-in plan-review listener.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: blueprint
|
|
3
|
-
description: "Produce dependency-free visual clarity artifacts at design time —
|
|
3
|
+
description: "Produce dependency-free visual clarity artifacts at design time — HTML wireframes and full renders for UI screens and flows in the house design language (surface-kit tokens), and inline-SVG system diagrams (data models, flows, architecture, state machines) for backend work. During /discovery when the feature has a UI surface or a data model, from /draft-plan task cards, or standalone on \"mock this up\", \"wireframe this screen\", \"visualize the data model\", \"sketch the architecture\", \"diagram the flow\". Not for aesthetic or brand direction, editable design canvases or Figma, charts from real data, or generating code from a mockup."
|
|
4
4
|
argument-hint: "[surface or model to visualize — optional; defaults to the current design context]"
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,7 +8,9 @@ argument-hint: "[surface or model to visualize — optional; defaults to the cur
|
|
|
8
8
|
|
|
9
9
|
Make the design visible before it's built. Wireframes tell a frontend dev what
|
|
10
10
|
goes where and why; system diagrams tell a backend dev what talks to what.
|
|
11
|
-
Structure
|
|
11
|
+
Structure first — and everything speaks the house design language (the
|
|
12
|
+
surface-kit token core), so a mockup already looks like it belongs to the
|
|
13
|
+
product family.
|
|
12
14
|
|
|
13
15
|
## Usage
|
|
14
16
|
|
|
@@ -33,14 +35,19 @@ Structure, never style.
|
|
|
33
35
|
│ │
|
|
34
36
|
│ Step 2: PRODUCE │
|
|
35
37
|
│ One self-contained HTML file per screen / flow state / diagram. │
|
|
36
|
-
│ Wireframes follow references/wireframe-kit.md
|
|
37
|
-
│
|
|
38
|
-
│
|
|
38
|
+
│ Wireframes follow references/wireframe-kit.md — wireframe mode │
|
|
39
|
+
│ by default; render mode when structure is signed off or the │
|
|
40
|
+
│ user asks for fidelity. Diagrams follow references/ │
|
|
41
|
+
│ diagram-kit.md. All styling from references/token-core.css. │
|
|
42
|
+
│ No external assets, no CDN, no font files. │
|
|
39
43
|
│ │
|
|
40
44
|
│ Step 3: DELIVER │
|
|
41
45
|
│ Open in the browser (xdg-open / open). If neither works │
|
|
42
46
|
│ (headless, SSH), print the absolute paths and continue — │
|
|
43
|
-
│ never fail on delivery.
|
|
47
|
+
│ never fail on delivery. Always state which mode was produced │
|
|
48
|
+
│ and offer the flip: "wireframe mode — say 'promote to render' │
|
|
49
|
+
│ for the full house look" (or the reverse). The mode is never │
|
|
50
|
+
│ chosen silently. │
|
|
44
51
|
│ │
|
|
45
52
|
│ Step 4: LINK │
|
|
46
53
|
│ Reference the files from the design doc or task card that │
|
|
@@ -50,11 +57,15 @@ Structure, never style.
|
|
|
50
57
|
|
|
51
58
|
## The Two Families
|
|
52
59
|
|
|
53
|
-
**Wireframes (UI clarity).**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
**Wireframes and renders (UI clarity).** Two modes over one shared skeleton,
|
|
61
|
+
both in the house tokens. *Wireframe mode* (default) is schematic — dashed
|
|
62
|
+
grouping, neutral roles only, annotation callouts — and answers: what elements
|
|
63
|
+
exist, how they group, what order they read in, what happens on each state
|
|
64
|
+
(empty, loading, error, populated). *Render mode* unlocks the full language
|
|
65
|
+
(accent, semantic and categorical colour, elevation, motion) to show how the
|
|
66
|
+
settled structure will look; promotion is a style-block swap, the skeleton
|
|
67
|
+
never changes. Multiple states of one flow are separate files, named for the
|
|
68
|
+
state. The full discipline — hard rules plus copyable mode CSS blocks — is in
|
|
58
69
|
`references/wireframe-kit.md`.
|
|
59
70
|
|
|
60
71
|
**System diagrams (BE clarity).** Hand-authored inline SVG for four shapes:
|
|
@@ -94,8 +105,9 @@ mockup into the spec directory first and cite the committed copy.
|
|
|
94
105
|
## What Does NOT Happen
|
|
95
106
|
|
|
96
107
|
```
|
|
97
|
-
✗
|
|
98
|
-
|
|
108
|
+
✗ Palettes or typography outside the shared token core — the house language
|
|
109
|
+
is the ceiling, render mode included; blueprint is not a brand playground
|
|
110
|
+
✗ Chromatic colour in wireframe mode (neutral roles + the annotation accent)
|
|
99
111
|
✗ External dependencies — no Mermaid CDN, no image generation, no Figma
|
|
100
112
|
✗ Code generation from the mockup (that's implementation's job, later)
|
|
101
113
|
✗ Charts of real data (that's a dataviz concern, not a design mockup)
|
|
@@ -2,28 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
Reference for `/blueprint`. Hand-authored inline SVG — no Mermaid, no CDN, no
|
|
4
4
|
renderer dependency. Every diagram is a self-contained HTML file that renders
|
|
5
|
-
from `file://`.
|
|
5
|
+
from `file://`. Diagrams have one look — no wireframe/render split — and it is
|
|
6
|
+
the house language: paste `token-core.css` (sibling of this file) at the top
|
|
7
|
+
of the `<style>` block, verbatim.
|
|
6
8
|
|
|
7
9
|
## Shared Conventions
|
|
8
10
|
|
|
9
11
|
- Canvas: `<svg viewBox="0 0 W H" style="max-width:100%">` sized to content;
|
|
10
|
-
the page wraps it in the
|
|
11
|
-
- Palette
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
the page wraps it in the wireframe kit's `.frame` shell (either mode's).
|
|
13
|
+
- Palette is token roles, referenced with `var(--…)` (CSS variables work in
|
|
14
|
+
inline SVG attributes): fills `var(--card)` / `var(--muted)`, strokes
|
|
15
|
+
`var(--border)`, edges `var(--subtle)`, text `var(--foreground)`. The one
|
|
16
|
+
accent is the `--primary` family — for the one thing the diagram is about
|
|
17
|
+
(the new entity, the changed edge) — never more than one accent use.
|
|
18
|
+
- Text: `--sans` for titles, `--mono` for everything that is data — field
|
|
19
|
+
rows, cardinalities, edge labels (D2). 13–14px labels, 11px annotations
|
|
20
|
+
in `var(--muted-foreground)`. If a label doesn't fit its box, the box
|
|
21
|
+
grows — never shrink the font below 11px.
|
|
17
22
|
- Arrowheads via one shared `<marker>`:
|
|
18
23
|
|
|
19
24
|
```html
|
|
20
25
|
<defs>
|
|
21
26
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
|
|
22
27
|
markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
23
|
-
<path d="M0,0 L10,5 L0,10 z" fill="
|
|
28
|
+
<path d="M0,0 L10,5 L0,10 z" fill="var(--subtle)"/>
|
|
24
29
|
</marker>
|
|
25
30
|
</defs>
|
|
26
|
-
<!-- usage: <line ... stroke="
|
|
31
|
+
<!-- usage: <line ... stroke="var(--subtle)" marker-end="url(#arrow)"/> -->
|
|
27
32
|
```
|
|
28
33
|
|
|
29
34
|
- Every relationship line gets a label. An unlabeled arrow is a guess the
|
|
@@ -36,18 +41,22 @@ labels carry cardinality (`1..*`, `0..1`).
|
|
|
36
41
|
|
|
37
42
|
```html
|
|
38
43
|
<g transform="translate(40,40)">
|
|
39
|
-
<rect width="200" height="24" fill="
|
|
44
|
+
<rect width="200" height="24" fill="var(--muted)" stroke="var(--border)" rx="3"/>
|
|
40
45
|
<text x="100" y="17" text-anchor="middle" font-weight="600">orders</text>
|
|
41
|
-
<rect y="24" width="200" height="72" fill="
|
|
46
|
+
<rect y="24" width="200" height="72" fill="var(--card)" stroke="var(--border)"/>
|
|
42
47
|
<text x="8" y="41">id PK</text>
|
|
43
48
|
<text x="8" y="61">user_id FK</text>
|
|
44
49
|
<text x="8" y="81">status</text>
|
|
45
50
|
</g>
|
|
46
51
|
<!-- edge: users 1..* orders -->
|
|
47
|
-
<line x1="240" y1="80" x2="340" y2="80" stroke="
|
|
48
|
-
<text x="290" y="72" text-anchor="middle" font-size="11">1..*</text>
|
|
52
|
+
<line x1="240" y1="80" x2="340" y2="80" stroke="var(--subtle)" marker-end="url(#arrow)"/>
|
|
53
|
+
<text x="290" y="72" text-anchor="middle" font-size="11" fill="var(--muted-foreground)">1..*</text>
|
|
49
54
|
```
|
|
50
55
|
|
|
56
|
+
An accented entity (the diagram's one accent) swaps its title-bar fill to
|
|
57
|
+
`var(--primary-muted)`, its strokes to `var(--primary)`, and its title text to
|
|
58
|
+
`var(--primary-text)`.
|
|
59
|
+
|
|
51
60
|
## 2. Request / Data Flow
|
|
52
61
|
|
|
53
62
|
Actors and stores as boxes on one horizontal band; numbered edges show
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/* Shared design core — do not hand-edit; edit scripts/tokens/core.css. */
|
|
2
|
+
:root {
|
|
3
|
+
--background: #111110;
|
|
4
|
+
--card: #191918;
|
|
5
|
+
--card-foreground: #eeeeec;
|
|
6
|
+
--popover: #222221;
|
|
7
|
+
--foreground: #eeeeec;
|
|
8
|
+
--muted: #222221;
|
|
9
|
+
--muted-foreground: #b5b3ad;
|
|
10
|
+
--border: #3b3a37;
|
|
11
|
+
--input: #3b3a37;
|
|
12
|
+
--primary: #978365;
|
|
13
|
+
--primary-foreground: #ffffff;
|
|
14
|
+
--primary-hover: #a39073;
|
|
15
|
+
--primary-muted: #24231f;
|
|
16
|
+
--primary-text: #cbb99f;
|
|
17
|
+
--ring: #978365;
|
|
18
|
+
--accent: #2a2a28;
|
|
19
|
+
--success: #71d083;
|
|
20
|
+
--success-muted: #1b2a1e;
|
|
21
|
+
--success-border: #2d5736;
|
|
22
|
+
--warning: #ffca16;
|
|
23
|
+
--warning-muted: #302008;
|
|
24
|
+
--warning-border: #5c3d05;
|
|
25
|
+
--destructive: #ff977d;
|
|
26
|
+
--destructive-muted: #391714;
|
|
27
|
+
--destructive-border: #6e2920;
|
|
28
|
+
--info: #70b8ff;
|
|
29
|
+
--info-muted: #0d2847;
|
|
30
|
+
--info-border: #104d87;
|
|
31
|
+
/* categorical — series identity; neither the accent nor the semantics */
|
|
32
|
+
--cat-1: #cf686e;
|
|
33
|
+
--cat-2: #897ed6;
|
|
34
|
+
--cat-3: #41a265;
|
|
35
|
+
--cat-4: #3694d4;
|
|
36
|
+
--cat-5: #94911b;
|
|
37
|
+
--cat-6: #ba6cae;
|
|
38
|
+
--cat-7: #c37827;
|
|
39
|
+
--cat-8: #00a0a4;
|
|
40
|
+
--cat-other: #686560;
|
|
41
|
+
--outline: rgba(237, 237, 236, 0.08);
|
|
42
|
+
--subtle: #686560;
|
|
43
|
+
--shadow-sm: 0 1px 2px rgba(6, 6, 5, 0.5);
|
|
44
|
+
--shadow-md: 0 4px 14px rgba(6, 6, 5, 0.55);
|
|
45
|
+
--shadow-lg: 0 20px 60px rgba(6, 6, 5, 0.62);
|
|
46
|
+
--mono: "Geist Mono", "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Monaco, "Cascadia Code", monospace;
|
|
47
|
+
--sans: "Geist", "Inter Tight", ui-sans-serif, system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
48
|
+
--text-2xs: 0.6875rem;
|
|
49
|
+
--text-xs: 0.75rem;
|
|
50
|
+
--text-sm: 0.8125rem;
|
|
51
|
+
--text-base: 0.875rem;
|
|
52
|
+
--text-md: 1rem;
|
|
53
|
+
--text-lg: 1.125rem;
|
|
54
|
+
--text-xl: 1.375rem;
|
|
55
|
+
--text-2xl: 1.75rem;
|
|
56
|
+
--text-3xl: 2.5rem;
|
|
57
|
+
--text-4xl: 3.5rem;
|
|
58
|
+
--leading-tight: 1.15;
|
|
59
|
+
--leading-snug: 1.35;
|
|
60
|
+
--leading-normal: 1.55;
|
|
61
|
+
--leading-relaxed: 1.7;
|
|
62
|
+
--tracking-tight: -0.022em;
|
|
63
|
+
--tracking-normal: 0em;
|
|
64
|
+
--tracking-wide: 0.06em;
|
|
65
|
+
--space-1: 0.25rem;
|
|
66
|
+
--space-2: 0.5rem;
|
|
67
|
+
--space-3: 0.75rem;
|
|
68
|
+
--space-4: 1rem;
|
|
69
|
+
--space-5: 1.5rem;
|
|
70
|
+
--space-6: 2rem;
|
|
71
|
+
--space-8: 3rem;
|
|
72
|
+
--space-12: 4rem;
|
|
73
|
+
--radius-sm: 0.1875rem;
|
|
74
|
+
--radius: 0.25rem;
|
|
75
|
+
--radius-md: 0.5rem;
|
|
76
|
+
--radius-lg: 0.75rem;
|
|
77
|
+
--radius-full: 9999px;
|
|
78
|
+
--dur-fast: 120ms;
|
|
79
|
+
--dur: 200ms;
|
|
80
|
+
--dur-slow: 320ms;
|
|
81
|
+
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
|
82
|
+
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
83
|
+
}
|
|
84
|
+
@media (prefers-color-scheme: light) {
|
|
85
|
+
:root:not([data-theme="dark"]) {
|
|
86
|
+
--background: #f6f5ef;
|
|
87
|
+
--card: #fcfbf6;
|
|
88
|
+
--card-foreground: #36302a;
|
|
89
|
+
--popover: #fcfbf6;
|
|
90
|
+
--foreground: #36302a;
|
|
91
|
+
--muted: #f0efe3;
|
|
92
|
+
--muted-foreground: #726c5e;
|
|
93
|
+
--border: #ddd6c6;
|
|
94
|
+
--input: #ddd6c6;
|
|
95
|
+
--primary: #967e60;
|
|
96
|
+
--primary-foreground: #ffffff;
|
|
97
|
+
--primary-hover: #897254;
|
|
98
|
+
--primary-muted: #efece0;
|
|
99
|
+
--primary-text: #6f5e44;
|
|
100
|
+
--ring: #967e60;
|
|
101
|
+
--accent: #eae7da;
|
|
102
|
+
--success: #3f7a34;
|
|
103
|
+
--success-muted: #e6f5e2;
|
|
104
|
+
--success-border: #c2e1b3;
|
|
105
|
+
--warning: #93761d;
|
|
106
|
+
--warning-muted: #fbf4c4;
|
|
107
|
+
--warning-border: #ebd87f;
|
|
108
|
+
--destructive: #bf4f3b;
|
|
109
|
+
--destructive-muted: #fbe8e2;
|
|
110
|
+
--destructive-border: #f0c9ba;
|
|
111
|
+
--info: #3f6fa6;
|
|
112
|
+
--info-muted: #e6f1fc;
|
|
113
|
+
--info-border: #bed7ef;
|
|
114
|
+
--cat-1: #b04d54;
|
|
115
|
+
--cat-2: #6f63b8;
|
|
116
|
+
--cat-3: #1e874b;
|
|
117
|
+
--cat-4: #0a78b7;
|
|
118
|
+
--cat-5: #797600;
|
|
119
|
+
--cat-6: #9d5192;
|
|
120
|
+
--cat-7: #a45e00;
|
|
121
|
+
--cat-8: #008f93;
|
|
122
|
+
--cat-other: #a8a294;
|
|
123
|
+
--outline: rgba(54, 48, 42, 0.08);
|
|
124
|
+
--subtle: #a8a294;
|
|
125
|
+
--shadow-sm: 0 1px 2px rgba(54, 48, 42, 0.1);
|
|
126
|
+
--shadow-md: 0 4px 14px rgba(54, 48, 42, 0.13);
|
|
127
|
+
--shadow-lg: 0 20px 60px rgba(54, 48, 42, 0.18);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
:root[data-theme="light"] {
|
|
131
|
+
--background: #f6f5ef;
|
|
132
|
+
--card: #fcfbf6;
|
|
133
|
+
--card-foreground: #36302a;
|
|
134
|
+
--popover: #fcfbf6;
|
|
135
|
+
--foreground: #36302a;
|
|
136
|
+
--muted: #f0efe3;
|
|
137
|
+
--muted-foreground: #726c5e;
|
|
138
|
+
--border: #ddd6c6;
|
|
139
|
+
--input: #ddd6c6;
|
|
140
|
+
--primary: #967e60;
|
|
141
|
+
--primary-foreground: #ffffff;
|
|
142
|
+
--primary-hover: #897254;
|
|
143
|
+
--primary-muted: #efece0;
|
|
144
|
+
--primary-text: #6f5e44;
|
|
145
|
+
--ring: #967e60;
|
|
146
|
+
--accent: #eae7da;
|
|
147
|
+
--success: #3f7a34;
|
|
148
|
+
--success-muted: #e6f5e2;
|
|
149
|
+
--success-border: #c2e1b3;
|
|
150
|
+
--warning: #93761d;
|
|
151
|
+
--warning-muted: #fbf4c4;
|
|
152
|
+
--warning-border: #ebd87f;
|
|
153
|
+
--destructive: #bf4f3b;
|
|
154
|
+
--destructive-muted: #fbe8e2;
|
|
155
|
+
--destructive-border: #f0c9ba;
|
|
156
|
+
--info: #3f6fa6;
|
|
157
|
+
--info-muted: #e6f1fc;
|
|
158
|
+
--info-border: #bed7ef;
|
|
159
|
+
--cat-1: #b04d54;
|
|
160
|
+
--cat-2: #6f63b8;
|
|
161
|
+
--cat-3: #1e874b;
|
|
162
|
+
--cat-4: #0a78b7;
|
|
163
|
+
--cat-5: #797600;
|
|
164
|
+
--cat-6: #9d5192;
|
|
165
|
+
--cat-7: #a45e00;
|
|
166
|
+
--cat-8: #008f93;
|
|
167
|
+
--cat-other: #a8a294;
|
|
168
|
+
--outline: rgba(54, 48, 42, 0.08);
|
|
169
|
+
--subtle: #a8a294;
|
|
170
|
+
--shadow-sm: 0 1px 2px rgba(54, 48, 42, 0.1);
|
|
171
|
+
--shadow-md: 0 4px 14px rgba(54, 48, 42, 0.13);
|
|
172
|
+
--shadow-lg: 0 20px 60px rgba(54, 48, 42, 0.18);
|
|
173
|
+
}
|
|
@@ -1,88 +1,299 @@
|
|
|
1
1
|
# Wireframe Kit
|
|
2
2
|
|
|
3
|
-
Reference for `/blueprint`.
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Reference for `/blueprint`. Every mockup speaks the house design language —
|
|
4
|
+
the surface-kit token core in `token-core.css` beside this file — in one of
|
|
5
|
+
two modes. The discipline is what keeps a mockup unambiguous: in wireframe
|
|
6
|
+
mode the schematic look keeps reviewers debating structure instead of taste;
|
|
7
|
+
in render mode the full language shows how the approved structure will
|
|
8
|
+
actually look.
|
|
9
|
+
|
|
10
|
+
## The Two Modes
|
|
11
|
+
|
|
12
|
+
| | `wireframe` | `render` |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| When | design time — structure is the open question | sign-off / presentation — structure is settled |
|
|
15
|
+
| Colour roles | neutrals only; semantics stay silent | full palette: accent, semantic, categorical |
|
|
16
|
+
| Grouping | dashed borders, flat corners | solid borders, radius + elevation |
|
|
17
|
+
| Buttons | transparent outlines, emphasis by border weight | filled `--primary`, hover, motion |
|
|
18
|
+
| Overall read | "schematic under discussion" | "this is how it'll look" |
|
|
19
|
+
|
|
20
|
+
**Same skeleton, two skins.** Both modes share identical HTML structure and
|
|
21
|
+
class names; only the component CSS block differs. Promoting a signed-off
|
|
22
|
+
wireframe to a render is a style-block swap — nothing may move. Declare the
|
|
23
|
+
mode on the body: `<body data-blueprint-mode="wireframe">` (or `"render"`).
|
|
24
|
+
|
|
25
|
+
Default to wireframe mode. Produce a render when the structure is already
|
|
26
|
+
signed off, when the user asks for fidelity ("make it look real", "mock this
|
|
27
|
+
up properly"), or when discovery offers promotion at sign-off. Whichever mode
|
|
28
|
+
you produce, say so at delivery and offer the other in one line — "wireframe
|
|
29
|
+
mode; say 'promote to render' for the full look" — so the default is visible
|
|
30
|
+
and reversible, never silent. Ask upfront only when the request genuinely
|
|
31
|
+
mixes both signals.
|
|
6
32
|
|
|
7
33
|
## Hard Rules
|
|
8
34
|
|
|
9
|
-
1. **
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
35
|
+
1. **Tokens only.** Every colour, size, radius, and duration comes from a
|
|
36
|
+
`var(--…)` defined in the token core. No raw hex, no ad-hoc px values
|
|
37
|
+
where a ramp token exists. Paste `token-core.css` (sibling of this file)
|
|
38
|
+
at the top of every `<style>` block, verbatim.
|
|
39
|
+
2. **Wireframe mode is neutral.** Its component CSS may reference only:
|
|
40
|
+
`--background`, `--card`, `--foreground`, `--muted`, `--muted-foreground`,
|
|
41
|
+
`--border`, `--input`, `--accent`, `--subtle`, the `--primary*` family
|
|
42
|
+
(annotation callouts only), and every type / space / radius / motion /
|
|
43
|
+
font token. Semantic (`--success*`, `--warning*`, `--destructive*`,
|
|
44
|
+
`--info*`), categorical (`--cat-*`), and elevation (`--shadow-*`) tokens
|
|
45
|
+
are render-mode vocabulary.
|
|
46
|
+
3. **Fonts per D2.** `--sans` for the UI's own copy; `--mono` for everything
|
|
47
|
+
meta — labels, badges, annotations, data. The stacks are fallbacks; never
|
|
48
|
+
load font files.
|
|
49
|
+
4. **No imagery.** Photos and illustrations render as a crossed box with a
|
|
15
50
|
label (`.img-box`). Icons render as their name in brackets, e.g. `[gear]`.
|
|
16
|
-
|
|
51
|
+
5. **Real hierarchy, placeholder content.** Headings, labels, and CTAs carry
|
|
17
52
|
their actual intended text; body copy may be greeked with `▓▓▓` bars.
|
|
18
|
-
|
|
53
|
+
6. **Annotate decisions, not furniture.** A callout explains *why this is
|
|
19
54
|
here* or *what happens on interaction* — not "this is a button".
|
|
20
|
-
|
|
55
|
+
7. **One file per screen or flow state.** Empty, loading, error, and populated
|
|
21
56
|
are different files named for the state:
|
|
22
57
|
`settings-page.html`, `settings-page-empty.html`, `settings-page-error.html`.
|
|
23
|
-
|
|
58
|
+
8. **Self-contained.** All CSS inline in a `<style>` block. No external
|
|
24
59
|
requests of any kind. The file must render identically from `file://`.
|
|
60
|
+
The token core carries dark and light themes; the page follows the OS.
|
|
25
61
|
|
|
26
|
-
##
|
|
62
|
+
## Page Skeleton
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<title>settings-page — wireframe</title>
|
|
66
|
+
<style>
|
|
67
|
+
/* 1. token-core.css pasted verbatim */
|
|
68
|
+
/* 2. ONE mode block from below */
|
|
69
|
+
</style>
|
|
70
|
+
<body data-blueprint-mode="wireframe">
|
|
71
|
+
<div class="frame">
|
|
72
|
+
<div class="box"><strong>Header</strong> · [logo] · nav: Account / Billing / Team</div>
|
|
73
|
+
<div class="row">
|
|
74
|
+
<div class="box"><!-- sidebar --></div>
|
|
75
|
+
<div class="box" style="flex:3"><!-- main content --></div>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="note">Sidebar collapses below 768px — Billing moves into the header nav.</div>
|
|
78
|
+
</div>
|
|
79
|
+
</body>
|
|
80
|
+
```
|
|
27
81
|
|
|
28
|
-
|
|
82
|
+
## Wireframe Mode CSS
|
|
29
83
|
|
|
30
84
|
```css
|
|
85
|
+
/* wireframe mode — surface-kit neutrals only, schematic look.
|
|
86
|
+
Emphasis by value and weight, never hue. */
|
|
31
87
|
* { margin: 0; box-sizing: border-box; }
|
|
32
88
|
body {
|
|
33
|
-
font-family:
|
|
34
|
-
|
|
89
|
+
font-family: var(--sans);
|
|
90
|
+
font-size: var(--text-base);
|
|
91
|
+
line-height: var(--leading-normal);
|
|
92
|
+
background: var(--background);
|
|
93
|
+
color: var(--foreground);
|
|
94
|
+
padding: var(--space-6);
|
|
35
95
|
}
|
|
36
|
-
.frame {
|
|
37
|
-
background:
|
|
38
|
-
|
|
96
|
+
.frame {
|
|
97
|
+
background: var(--card);
|
|
98
|
+
border: 1px dashed var(--muted-foreground);
|
|
99
|
+
border-radius: var(--radius-sm);
|
|
100
|
+
max-width: 1100px; margin: 0 auto; padding: var(--space-6);
|
|
39
101
|
}
|
|
40
|
-
.
|
|
41
|
-
|
|
42
|
-
padding:
|
|
102
|
+
.topbar {
|
|
103
|
+
display: flex; justify-content: space-between; align-items: baseline;
|
|
104
|
+
padding-bottom: var(--space-4); border-bottom: 1px solid var(--border);
|
|
105
|
+
margin-bottom: var(--space-5);
|
|
43
106
|
}
|
|
44
|
-
.
|
|
107
|
+
.nav { display: flex; gap: var(--space-4); font-size: var(--text-sm); }
|
|
108
|
+
.nav a { color: var(--muted-foreground); }
|
|
109
|
+
.nav a.active { color: var(--foreground); border-bottom: 2px solid var(--foreground); padding-bottom: 2px; }
|
|
110
|
+
.row { display: flex; gap: var(--space-4); }
|
|
45
111
|
.row > * { flex: 1; }
|
|
46
|
-
.
|
|
47
|
-
border: 1px
|
|
48
|
-
|
|
49
|
-
|
|
112
|
+
.box {
|
|
113
|
+
background: var(--card); border: 1px dashed var(--border);
|
|
114
|
+
border-radius: var(--radius-sm); padding: var(--space-4); margin-bottom: var(--space-4);
|
|
115
|
+
}
|
|
116
|
+
h2 { font-size: var(--text-md); letter-spacing: var(--tracking-tight); margin-bottom: var(--space-3); }
|
|
117
|
+
.side-item {
|
|
118
|
+
padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
|
|
119
|
+
color: var(--muted-foreground); font-size: var(--text-sm);
|
|
120
|
+
}
|
|
121
|
+
.side-item.active { background: var(--accent); color: var(--foreground); }
|
|
122
|
+
.field { margin-bottom: var(--space-3); }
|
|
123
|
+
label {
|
|
124
|
+
display: block; font-family: var(--mono); font-size: var(--text-2xs);
|
|
125
|
+
text-transform: uppercase; letter-spacing: var(--tracking-wide);
|
|
126
|
+
color: var(--muted-foreground); margin-bottom: var(--space-1);
|
|
127
|
+
}
|
|
128
|
+
input {
|
|
129
|
+
width: 100%; background: transparent; color: var(--foreground);
|
|
130
|
+
border: 1px solid var(--input); border-radius: var(--radius);
|
|
131
|
+
padding: var(--space-2) var(--space-3); font: inherit; font-size: var(--text-sm);
|
|
132
|
+
}
|
|
133
|
+
.btn {
|
|
134
|
+
display: inline-block; border: 1px solid var(--muted-foreground); border-radius: var(--radius-sm);
|
|
135
|
+
padding: var(--space-2) var(--space-4); background: transparent;
|
|
136
|
+
color: var(--foreground); font-size: var(--text-sm);
|
|
137
|
+
}
|
|
138
|
+
.btn.primary { border-width: 2px; font-weight: 600; }
|
|
139
|
+
.btn.danger { color: var(--muted-foreground); } /* semantics stay silent in wireframe */
|
|
140
|
+
.greek { color: var(--border); letter-spacing: 2px; overflow: hidden; white-space: nowrap; }
|
|
141
|
+
.img-box {
|
|
142
|
+
border: 1px solid var(--border); background:
|
|
143
|
+
linear-gradient(45deg, transparent 49.5%, var(--border) 49.5%, var(--border) 50.5%, transparent 50.5%),
|
|
144
|
+
linear-gradient(-45deg, transparent 49.5%, var(--border) 49.5%, var(--border) 50.5%, transparent 50.5%)
|
|
145
|
+
var(--muted);
|
|
50
146
|
display: flex; align-items: center; justify-content: center;
|
|
51
|
-
color:
|
|
147
|
+
color: var(--muted-foreground); font-family: var(--mono); font-size: var(--text-xs);
|
|
148
|
+
min-height: 120px; border-radius: var(--radius);
|
|
52
149
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
150
|
+
table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
|
|
151
|
+
th {
|
|
152
|
+
font-family: var(--mono); font-size: var(--text-2xs); text-transform: uppercase;
|
|
153
|
+
letter-spacing: var(--tracking-wide); color: var(--muted-foreground);
|
|
154
|
+
text-align: left; padding: var(--space-2); border-bottom: 1px solid var(--border);
|
|
56
155
|
}
|
|
57
|
-
|
|
58
|
-
|
|
156
|
+
td { padding: var(--space-2); border-bottom: 1px solid var(--border); }
|
|
157
|
+
.badge {
|
|
158
|
+
display: inline-block; font-family: var(--mono); font-size: var(--text-2xs);
|
|
159
|
+
padding: 2px var(--space-2); border-radius: var(--radius-full);
|
|
160
|
+
border: 1px solid var(--border); color: var(--muted-foreground);
|
|
59
161
|
}
|
|
60
|
-
.note {
|
|
61
|
-
|
|
62
|
-
|
|
162
|
+
.note::before { content: "\25B8 note "; font-weight: 600; letter-spacing: var(--tracking-wide); }
|
|
163
|
+
.note {
|
|
164
|
+
border-left: 3px solid var(--primary); background: var(--primary-muted);
|
|
165
|
+
color: var(--primary-text); border-radius: 0 var(--radius) var(--radius) 0;
|
|
166
|
+
padding: var(--space-2) var(--space-3); margin: var(--space-3) 0;
|
|
167
|
+
font-family: var(--mono); font-size: var(--text-xs); line-height: var(--leading-snug);
|
|
63
168
|
}
|
|
169
|
+
.actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
|
|
170
|
+
.choice { display: flex; gap: var(--space-2); }
|
|
171
|
+
.empty { text-align: center; padding: var(--space-8); border-style: dashed; }
|
|
172
|
+
.muted { color: var(--muted-foreground); }
|
|
64
173
|
```
|
|
65
174
|
|
|
66
175
|
Greeked copy: `<div class="greek">▓▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓</div>` at whatever
|
|
67
176
|
width the real copy would occupy.
|
|
68
177
|
|
|
69
|
-
##
|
|
178
|
+
## Render Mode CSS
|
|
70
179
|
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
180
|
+
```css
|
|
181
|
+
/* render mode — the full house language. Same skeleton, colour unlocked:
|
|
182
|
+
accent on primary actions, semantic status colours, categorical chips,
|
|
183
|
+
elevation, motion. */
|
|
184
|
+
* { margin: 0; box-sizing: border-box; }
|
|
185
|
+
body {
|
|
186
|
+
font-family: var(--sans);
|
|
187
|
+
font-size: var(--text-base);
|
|
188
|
+
line-height: var(--leading-normal);
|
|
189
|
+
background: var(--background);
|
|
190
|
+
color: var(--foreground);
|
|
191
|
+
padding: var(--space-6);
|
|
192
|
+
}
|
|
193
|
+
.frame {
|
|
194
|
+
background: var(--card);
|
|
195
|
+
border: 1px solid var(--border);
|
|
196
|
+
border-radius: var(--radius-lg);
|
|
197
|
+
box-shadow: var(--shadow-md);
|
|
198
|
+
max-width: 1100px; margin: 0 auto; padding: var(--space-6);
|
|
199
|
+
}
|
|
200
|
+
.topbar {
|
|
201
|
+
display: flex; justify-content: space-between; align-items: baseline;
|
|
202
|
+
padding-bottom: var(--space-4); border-bottom: 1px solid var(--border);
|
|
203
|
+
margin-bottom: var(--space-5);
|
|
204
|
+
}
|
|
205
|
+
.topbar strong { font-size: var(--text-lg); letter-spacing: var(--tracking-tight); }
|
|
206
|
+
.nav { display: flex; gap: var(--space-4); font-size: var(--text-sm); }
|
|
207
|
+
.nav a { color: var(--muted-foreground); transition: color var(--dur-fast) var(--ease-out); }
|
|
208
|
+
.nav a.active { color: var(--primary-text); border-bottom: 2px solid var(--primary); padding-bottom: 2px; }
|
|
209
|
+
.row { display: flex; gap: var(--space-4); }
|
|
210
|
+
.row > * { flex: 1; }
|
|
211
|
+
.box {
|
|
212
|
+
background: var(--card); border: 1px solid var(--border);
|
|
213
|
+
border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-4);
|
|
214
|
+
box-shadow: var(--shadow-sm);
|
|
215
|
+
}
|
|
216
|
+
h2 { font-size: var(--text-md); letter-spacing: var(--tracking-tight); margin-bottom: var(--space-3); }
|
|
217
|
+
.side-item {
|
|
218
|
+
padding: var(--space-2) var(--space-3); border-radius: var(--radius);
|
|
219
|
+
color: var(--muted-foreground); font-size: var(--text-sm);
|
|
220
|
+
transition: background var(--dur-fast) var(--ease-out);
|
|
221
|
+
}
|
|
222
|
+
.side-item.active { background: var(--primary-muted); color: var(--primary-text); }
|
|
223
|
+
.field { margin-bottom: var(--space-3); }
|
|
224
|
+
label {
|
|
225
|
+
display: block; font-family: var(--mono); font-size: var(--text-2xs);
|
|
226
|
+
text-transform: uppercase; letter-spacing: var(--tracking-wide);
|
|
227
|
+
color: var(--muted-foreground); margin-bottom: var(--space-1);
|
|
228
|
+
}
|
|
229
|
+
input {
|
|
230
|
+
width: 100%; background: var(--muted); color: var(--foreground);
|
|
231
|
+
border: 1px solid var(--input); border-radius: var(--radius);
|
|
232
|
+
padding: var(--space-2) var(--space-3); font: inherit; font-size: var(--text-sm);
|
|
233
|
+
transition: border-color var(--dur-fast) var(--ease-out);
|
|
234
|
+
}
|
|
235
|
+
input:focus { outline: none; border-color: var(--ring); }
|
|
236
|
+
.btn {
|
|
237
|
+
display: inline-block; border: 1px solid var(--border); border-radius: var(--radius);
|
|
238
|
+
padding: var(--space-2) var(--space-4); background: var(--accent);
|
|
239
|
+
color: var(--foreground); font-size: var(--text-sm); cursor: pointer;
|
|
240
|
+
transition: background var(--dur-fast) var(--ease-out);
|
|
241
|
+
}
|
|
242
|
+
.btn.primary { background: var(--primary); color: var(--primary-foreground); border-color: transparent; }
|
|
243
|
+
.btn.primary:hover { background: var(--primary-hover); }
|
|
244
|
+
.btn.danger {
|
|
245
|
+
background: var(--destructive-muted); color: var(--destructive);
|
|
246
|
+
border-color: var(--destructive-border);
|
|
247
|
+
}
|
|
248
|
+
.greek { color: var(--border); letter-spacing: 2px; overflow: hidden; white-space: nowrap; }
|
|
249
|
+
.img-box {
|
|
250
|
+
border: 1px solid var(--border); background:
|
|
251
|
+
linear-gradient(45deg, transparent 49.5%, var(--border) 49.5%, var(--border) 50.5%, transparent 50.5%),
|
|
252
|
+
linear-gradient(-45deg, transparent 49.5%, var(--border) 49.5%, var(--border) 50.5%, transparent 50.5%)
|
|
253
|
+
var(--muted);
|
|
254
|
+
display: flex; align-items: center; justify-content: center;
|
|
255
|
+
color: var(--muted-foreground); font-family: var(--mono); font-size: var(--text-xs);
|
|
256
|
+
min-height: 120px; border-radius: var(--radius);
|
|
257
|
+
}
|
|
258
|
+
table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
|
|
259
|
+
th {
|
|
260
|
+
font-family: var(--mono); font-size: var(--text-2xs); text-transform: uppercase;
|
|
261
|
+
letter-spacing: var(--tracking-wide); color: var(--muted-foreground);
|
|
262
|
+
text-align: left; padding: var(--space-2); border-bottom: 1px solid var(--border);
|
|
263
|
+
}
|
|
264
|
+
td { padding: var(--space-2); border-bottom: 1px solid var(--border); }
|
|
265
|
+
.badge {
|
|
266
|
+
display: inline-block; font-family: var(--mono); font-size: var(--text-2xs);
|
|
267
|
+
padding: 2px var(--space-2); border-radius: var(--radius-full);
|
|
268
|
+
border: 1px solid var(--border); color: var(--muted-foreground);
|
|
269
|
+
}
|
|
270
|
+
.badge.ok { color: var(--success); background: var(--success-muted); border-color: var(--success-border); }
|
|
271
|
+
.badge.warn { color: var(--warning); background: var(--warning-muted); border-color: var(--warning-border); }
|
|
272
|
+
.badge.err { color: var(--destructive); background: var(--destructive-muted); border-color: var(--destructive-border); }
|
|
273
|
+
.badge.role-1 { color: var(--cat-2); border-color: var(--cat-2); background: transparent; }
|
|
274
|
+
.badge.role-2 { color: var(--cat-4); border-color: var(--cat-4); background: transparent; }
|
|
275
|
+
.badge.role-3 { color: var(--cat-other); border-color: var(--cat-other); background: transparent; }
|
|
276
|
+
.note {
|
|
277
|
+
border-left: 3px solid var(--primary); background: var(--primary-muted);
|
|
278
|
+
color: var(--primary-text); border-radius: 0 var(--radius) var(--radius) 0;
|
|
279
|
+
padding: var(--space-2) var(--space-3); margin: var(--space-3) 0;
|
|
280
|
+
font-family: var(--mono); font-size: var(--text-xs); line-height: var(--leading-snug);
|
|
281
|
+
}
|
|
282
|
+
.actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }
|
|
283
|
+
.choice { display: flex; gap: var(--space-2); }
|
|
284
|
+
.empty { text-align: center; padding: var(--space-8); border-style: dashed; box-shadow: none; }
|
|
285
|
+
.muted { color: var(--muted-foreground); }
|
|
82
286
|
```
|
|
83
287
|
|
|
288
|
+
The `.badge.role-*` classes are categorical-colour examples — rename them for
|
|
289
|
+
the domain at hand (`.badge.plan-pro`, `.badge.env-staging`, …); the pattern
|
|
290
|
+
to keep is one `--cat-N` per identity, `--cat-other` for the long tail.
|
|
291
|
+
|
|
84
292
|
## Review Posture
|
|
85
293
|
|
|
86
294
|
Present a wireframe as a question, not an answer: "this is the structure I
|
|
87
295
|
understood — what's wrong with it?" When two structures genuinely compete,
|
|
88
|
-
produce both files and let discovery's mockup-picker run the choice.
|
|
296
|
+
produce both files and let discovery's mockup-picker run the choice. A render
|
|
297
|
+
is the opposite posture — it presents the settled structure in the house
|
|
298
|
+
language, so changes at render stage should be taste-level, not structural;
|
|
299
|
+
structural feedback at that point reopens the wireframe.
|
|
@@ -171,10 +171,12 @@ design that lives only in conversation doesn't count as signed off.
|
|
|
171
171
|
ignored — see the bootstrap step there. Honour an `AGENTS.md` path override
|
|
172
172
|
if the project defines one.
|
|
173
173
|
|
|
174
|
-
For full design mockups —
|
|
175
|
-
architecture diagrams — load the `blueprint`
|
|
176
|
-
files it produces.
|
|
177
|
-
|
|
174
|
+
For full design mockups — UI wireframes and renders in the house token
|
|
175
|
+
language, data-model / flow / architecture diagrams — load the `blueprint`
|
|
176
|
+
skill; the design doc links the files it produces. At sign-off, offer to
|
|
177
|
+
promote the chosen wireframes to render mode (a style-block swap). For
|
|
178
|
+
*picking between* side-by-side options in the browser, see
|
|
179
|
+
`references/mockup-picker.md` (it can point at blueprint's files).
|
|
178
180
|
|
|
179
181
|
## Design Review Loop
|
|
180
182
|
|