@wenaixi/dsh-superpower 7.2.1 → 7.4.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/README.md +16 -12
- package/lib/catalog.d.ts +25 -2
- package/lib/catalog.d.ts.map +1 -1
- package/lib/catalog.js +135 -8
- package/lib/catalog.js.map +1 -1
- package/lib/client.js +56 -58
- package/lib/document.d.ts.map +1 -1
- package/lib/document.js +7 -0
- package/lib/document.js.map +1 -1
- package/lib/superpowers.d.ts +5 -1
- package/lib/superpowers.d.ts.map +1 -1
- package/lib/superpowers.js +18 -3
- package/lib/superpowers.js.map +1 -1
- package/lib/switches.d.ts +21 -14
- package/lib/switches.d.ts.map +1 -1
- package/lib/switches.js +54 -31
- package/lib/switches.js.map +1 -1
- package/package.json +1 -1
- package/skills/brainstorming/SKILL.md +2 -2
- package/skills/brainstorming/visual-companion.md +70 -213
- package/skills/brainstorming/scripts/frame-template.html +0 -213
- package/skills/brainstorming/scripts/helper.js +0 -167
- package/skills/brainstorming/scripts/server.cjs +0 -715
- package/skills/brainstorming/scripts/start-server.sh +0 -204
- package/skills/brainstorming/scripts/stop-server.sh +0 -120
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# 可视化辅助指南
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
基于 DSH 官方文档预览的头脑风暴辅助工具,用于展示原型、图表和选项。
|
|
4
4
|
|
|
5
5
|
## 何时使用
|
|
6
6
|
|
|
7
7
|
按问题逐个判断,而非按会话判断。判断标准:**用户看图是否比看文字更易理解?**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**内容本身是可视化的场景,适合用浏览器预览:**
|
|
10
10
|
|
|
11
11
|
- **界面原型** — 线框图、布局、导航结构、组件设计
|
|
12
12
|
- **架构图** — 系统组件、数据流、关系图谱
|
|
@@ -16,252 +16,109 @@
|
|
|
16
16
|
|
|
17
17
|
**内容为文本或表格的场景,适合使用终端:**
|
|
18
18
|
|
|
19
|
-
- **需求与范围问题** —
|
|
19
|
+
- **需求与范围问题** — 「这是什么意思?」,「哪些功能在范围内?」
|
|
20
20
|
- **概念性的 A/B/C 选择** — 在文字描述的方案之间做选择
|
|
21
21
|
- **权衡清单** — 优缺点、对比表格
|
|
22
22
|
- **技术决策** — API 设计、数据建模、架构方案选型
|
|
23
23
|
- **澄清性问题** — 任何答案是文字而非视觉偏好的问题
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
一个*关于*界面主题的问题并不自动等同于可视化问题。「你想要哪种向导?」是概念性问题——使用终端。「这些向导布局中哪一个更合适?」是可视化问题——使用浏览器预览。
|
|
26
26
|
|
|
27
27
|
## 工作原理
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
你把 HTML 写入工作区的一个约定目录,DSH 的文档预览面板读取并渲染它。用户在浏览器侧的文档栏打开该文件即见画面。
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
**选择结果不会自动回传给你。** 预览是一个隔离的 iframe 文档,它无法把你的选择送达会话。所以:让用户在终端里回答。绝不要声称读到了用户在预览里的点击。
|
|
32
32
|
|
|
33
|
-
##
|
|
33
|
+
## 写文件
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
# 在用户批准 companion 后启动。--open 会在首屏自动打开其浏览器;
|
|
37
|
-
# --project-dir 持久化原型并支持同端口重启。
|
|
38
|
-
bash scripts/start-server.sh --project-dir /path/to/project --open
|
|
35
|
+
把每一页 HTML 写成一个自包含的完整文档。三条硬要求:
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
保存响应中的 `screen_dir` 和 `state_dir`。使用 `--open` 时,浏览器会在你推送首屏时自动打开——你无需让用户手动打开,但仍需分享 URL 作为备用方案(无头/远程环境无法自动打开)。
|
|
47
|
-
|
|
48
|
-
**URL 中包含会话密钥(`?key=…`)。** 服务器会拒绝任何不带该密钥的请求,因此务必向用户提供 `url` 字段中的**完整** URL——不要去除查询字符串,也不要只给裸的 `http://host:port`。该密钥用于控制 HTTP 和 WebSocket 访问,防止随意的浏览器标签页或同一网络中的其他机器读取页面或注入事件。首次加载后,浏览器会通过 Cookie 记住该密钥,因此重新加载和访问 `/files/*` 资源时无需重复携带。
|
|
49
|
-
|
|
50
|
-
**查找连接信息:** 服务器会将启动时的 JSON 写入 `$STATE_DIR/server-info`。如果你在后台启动了服务器且未捕获标准输出,可读取该文件以获取 URL 和端口。使用 `--project-dir` 时,请在 `<project>/.superpowers/brainstorm/` 下查找会话目录。
|
|
51
|
-
|
|
52
|
-
**注意:** 将项目根目录作为 `--project-dir` 传入,这样原型会持久化到 `.superpowers/brainstorm/` 并在服务器重启后依然保留。若不传,文件会写入 `/tmp` 并被清理。如果 `.gitignore` 中尚未包含 `.superpowers/`,请提醒用户添加。
|
|
53
|
-
|
|
54
|
-
**在 DSH 中启动服务器:**
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# 在 DSH 中使用 pwsh(Windows 首选)或 bash 工具,传入 run_in_background: true
|
|
58
|
-
bash scripts/start-server.sh --project-dir /path/to/project --open --foreground
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
服务器必须在后台持续运行并跨越 turn。在 DSH 工具调用中使用 `run_in_background: true`,然后在下一轮读取 `$STATE_DIR/server-info` 以获取 URL 和端口。
|
|
62
|
-
|
|
63
|
-
如果 URL 在你的浏览器中无法访问(在远程/容器化环境中很常见),请绑定非回环地址:
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
bash scripts/start-server.sh \
|
|
67
|
-
--project-dir /path/to/project \
|
|
68
|
-
--host 0.0.0.0 \
|
|
69
|
-
--url-host localhost
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
使用 `--url-host` 控制返回的 URL JSON 中显示的主机名。
|
|
73
|
-
|
|
74
|
-
## 循环流程
|
|
75
|
-
|
|
76
|
-
1. **检查服务器是否存活**,然后**向 `screen_dir` 写入 HTML 新文件**:
|
|
77
|
-
- **必须:在引用 URL 或推送页面前确认服务器存活。** 检查 `$STATE_DIR/server-info` 是否存在且 `$STATE_DIR/server-stopped` 是否不存在。如果已关闭,请使用**相同的 `--project-dir`** 通过 `start-server.sh` 重启——它会复用同一端口,用户的已打开标签页会自动重连(服务器宕机期间会显示“已暂停”遮罩),无需发送新 URL。服务器在空闲 4 小时后自动退出(可通过 `--idle-timeout-minutes` 配置)。
|
|
78
|
-
- 使用语义化文件名:`platform.html`、`visual-style.html`、`layout.html`
|
|
79
|
-
- **不要复用文件名**——每个页面都使用全新文件
|
|
80
|
-
- 使用你的文件创建工具——**不要使用 cat/heredoc**(会在终端产生大量噪音)
|
|
81
|
-
- 服务器自动提供最新的文件
|
|
82
|
-
|
|
83
|
-
2. **告知用户预期内容并结束本轮:**
|
|
84
|
-
- 提醒他们 URL(每一步都要,不只是第一步)
|
|
85
|
-
- 简要文字概括屏幕内容(例如:“正在展示首页的 3 种布局方案”)
|
|
86
|
-
- 请他们在终端中回应:“请查看后告诉我你的想法。如果愿意,可以点击选择一个选项。”
|
|
87
|
-
|
|
88
|
-
3. **在你的下一轮**——用户在终端回应后:
|
|
89
|
-
- 如果存在,读取 `$STATE_DIR/events`——其中包含用户在浏览器中的交互(点击、选择),以 JSON 行格式记录
|
|
90
|
-
- 将其与用户的终端文本合并,以获得完整信息
|
|
91
|
-
- 终端消息是主要反馈;`state_dir/events` 提供结构化的交互数据
|
|
37
|
+
1. **完整文档。** 官方预览不做内容包裹,不提供任何现成 CSS 类。
|
|
38
|
+
`<div class="options">` 在这里没有任何含义,页面上什么都不会出现。
|
|
39
|
+
2. **自包含。** 不引用外部相对路径的 CSS 或脚本——相对依赖只在交互预览
|
|
40
|
+
开关打开时才被打包。写单文件最稳。
|
|
41
|
+
3. **不依赖 iframe 外的能力。** 预览文档与宿主页面不共享上下文,
|
|
42
|
+
`window.parent` 拿不到任何东西。
|
|
92
43
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
5. **回到终端时卸载**——当下一步不需要浏览器时(例如澄清问题、权衡讨论),推送一个等待页面以清除过时内容:
|
|
96
|
-
|
|
97
|
-
```html
|
|
98
|
-
<!-- filename: waiting.html (or waiting-2.html, etc.) -->
|
|
99
|
-
<div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
|
|
100
|
-
<p class="subtitle">Continuing in terminal...</p>
|
|
101
|
-
</div>
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
这样可避免用户在对话已推进后仍盯着已解决的选择。当下一个可视化问题出现时,像往常一样推送新的内容文件即可。
|
|
105
|
-
|
|
106
|
-
6. 重复上述流程直至完成。
|
|
107
|
-
|
|
108
|
-
## 编写内容片段
|
|
109
|
-
|
|
110
|
-
只需编写页面内部的内容。服务器会自动将其包裹到框架模板中(页头、主题 CSS、连接状态及所有交互基础设施)。
|
|
111
|
-
|
|
112
|
-
**最小示例:**
|
|
44
|
+
### 最小示例
|
|
113
45
|
|
|
114
46
|
```html
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
47
|
+
<!DOCTYPE html>
|
|
48
|
+
<html lang="zh">
|
|
49
|
+
<head>
|
|
50
|
+
<meta charset="utf-8">
|
|
51
|
+
<title>布局方案</title>
|
|
52
|
+
<style>
|
|
53
|
+
body { font: 15px/1.7 system-ui, sans-serif; margin: 0; padding: 40px; }
|
|
54
|
+
h1 { font-size: 20px; margin: 0 0 6px; }
|
|
55
|
+
.subtitle { margin: 0 0 32px; color: #5b616e; }
|
|
56
|
+
.cards { display: flex; gap: 20px; flex-wrap: wrap; }
|
|
57
|
+
.card { flex: 1 1 280px; border: 1px solid #dfe2e8; border-radius: 10px; padding: 20px; }
|
|
58
|
+
.card h3 { margin: 0 0 8px; font-size: 16px; }
|
|
59
|
+
.card p { margin: 0; color: #5b616e; }
|
|
60
|
+
</style>
|
|
61
|
+
</head>
|
|
62
|
+
<body>
|
|
63
|
+
<h1>哪种布局更合适?</h1>
|
|
64
|
+
<p class="subtitle">请考虑可读性与视觉层级</p>
|
|
65
|
+
<div class="cards">
|
|
66
|
+
<div class="card">
|
|
67
|
+
<h3>A 单列</h3>
|
|
68
|
+
<p>阅读体验最好,信息密度最低</p>
|
|
124
69
|
</div>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<div class="content">
|
|
129
|
-
<h3>Two Column</h3>
|
|
130
|
-
<p>Sidebar navigation with main content</p>
|
|
70
|
+
<div class="card">
|
|
71
|
+
<h3>B 两列</h3>
|
|
72
|
+
<p>空间利用率高,需要额外样式约束</p>
|
|
131
73
|
</div>
|
|
132
74
|
</div>
|
|
133
|
-
</
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
|
134
77
|
```
|
|
135
78
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
## 可用 CSS 类
|
|
139
|
-
|
|
140
|
-
框架模板为你的内容提供以下 CSS 类:
|
|
141
|
-
|
|
142
|
-
### 选项(A/B/C 选择)
|
|
79
|
+
深色环境下把配色换成跟随 `prefers-color-scheme`,或直接用中性灰阶。
|
|
143
80
|
|
|
144
|
-
|
|
145
|
-
<div class="options">
|
|
146
|
-
<div class="option" data-choice="a" onclick="toggleSelect(this)">
|
|
147
|
-
<div class="letter">A</div>
|
|
148
|
-
<div class="content">
|
|
149
|
-
<h3>Title</h3>
|
|
150
|
-
<p>Description</p>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
```
|
|
81
|
+
## 目录与命名
|
|
155
82
|
|
|
156
|
-
|
|
83
|
+
约定目录:项目根下的 `.superpowers/brainstorm/`。会话结束后由你自行删除。
|
|
157
84
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
</div>
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### 卡片(视觉设计)
|
|
165
|
-
|
|
166
|
-
```html
|
|
167
|
-
<div class="cards">
|
|
168
|
-
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
|
|
169
|
-
<div class="card-image"><!-- mockup content --></div>
|
|
170
|
-
<div class="card-body">
|
|
171
|
-
<h3>Name</h3>
|
|
172
|
-
<p>Description</p>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### 原型容器
|
|
179
|
-
|
|
180
|
-
```html
|
|
181
|
-
<div class="mockup">
|
|
182
|
-
<div class="mockup-header">Preview: Dashboard Layout</div>
|
|
183
|
-
<div class="mockup-body"><!-- your mockup HTML --></div>
|
|
184
|
-
</div>
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### 分栏视图(并排)
|
|
188
|
-
|
|
189
|
-
```html
|
|
190
|
-
<div class="split">
|
|
191
|
-
<div class="mockup"><!-- left --></div>
|
|
192
|
-
<div class="mockup"><!-- right --></div>
|
|
193
|
-
</div>
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 优缺点
|
|
197
|
-
|
|
198
|
-
```html
|
|
199
|
-
<div class="pros-cons">
|
|
200
|
-
<div class="pros"><h4>Pros</h4><ul><li>Benefit</li></ul></div>
|
|
201
|
-
<div class="cons"><h4>Cons</h4><ul><li>Drawback</li></ul></div>
|
|
202
|
-
</div>
|
|
203
|
-
```
|
|
85
|
+
- 使用语义化名称:`platform.html`、`visual-style.html`、`layout.html`
|
|
86
|
+
- 不要复用文件名——每次迭代写一个新文件,`layout-v2.html`、`layout-v3.html`
|
|
87
|
+
- 用户打开的是他指定的那一个文件;改完告诉他新文件名
|
|
204
88
|
|
|
205
|
-
|
|
89
|
+
若项目的 `.gitignore` 尚未包含 `.superpowers/`,提醒用户添加。
|
|
206
90
|
|
|
207
|
-
|
|
208
|
-
<div class="mock-nav">Logo | Home | About | Contact</div>
|
|
209
|
-
<div style="display: flex;">
|
|
210
|
-
<div class="mock-sidebar">Navigation</div>
|
|
211
|
-
<div class="mock-content">Main content area</div>
|
|
212
|
-
</div>
|
|
213
|
-
<button class="mock-button">Action Button</button>
|
|
214
|
-
<input class="mock-input" placeholder="Input field">
|
|
215
|
-
<div class="placeholder">Placeholder area</div>
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### 排版与区块
|
|
91
|
+
## 循环流程
|
|
219
92
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
-
-
|
|
93
|
+
1. **写入 HTML** 到约定目录,用文件工具创建,不要用 `cat`/heredoc(会在终端产生大量噪音)。
|
|
94
|
+
2. **告知用户预期内容并结束本轮**:
|
|
95
|
+
- 提醒文件路径,以及如何在右侧文档栏打开它;
|
|
96
|
+
- 简要文字概括这一页在展示什么(例如「正在展示首页的 3 种布局方案」);
|
|
97
|
+
- 请他们在终端里回答。措辞要让人知道在哪里回答。
|
|
98
|
+
3. **读用户的终端回复**。这是唯一的选择回传通道。
|
|
99
|
+
4. **迭代或推进** —— 若反馈改变了当前页面,写一个新版本文件。
|
|
100
|
+
5. **回到终端时清场** —— 下一步不需要预览时,删除不再需要的 HTML 文件,
|
|
101
|
+
避免用户在文档栏看到早已解决的问题。
|
|
102
|
+
6. 重复直至完成。
|
|
225
103
|
|
|
226
|
-
##
|
|
104
|
+
## 逐题决策
|
|
227
105
|
|
|
228
|
-
|
|
106
|
+
即使用户已接受预览,仍需针对每个问题决定是否值得画出来:
|
|
229
107
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
{"type":"click","choice":"c","text":"Option C - Complex Grid","timestamp":1706000108}
|
|
233
|
-
{"type":"click","choice":"b","text":"Option B - Hybrid","timestamp":1706000115}
|
|
234
|
-
```
|
|
108
|
+
- **使用预览** 处理视觉内容——原型、线框、布局对比、架构图、并排视觉设计
|
|
109
|
+
- **使用终端** 处理文本内容——需求问题、概念抉择、权衡清单、A/B/C/D 文本选项、范围决策
|
|
235
110
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
如果 `$STATE_DIR/events` 不存在,说明用户未与浏览器交互——仅使用其终端文本即可。
|
|
111
|
+
涉及 UI 话题的问题不一定是视觉问题。「在此上下文中 personality 指什么?」是概念问题——使用终端。「哪种向导布局更合适?」是视觉问题——使用预览。
|
|
239
112
|
|
|
240
113
|
## 设计建议
|
|
241
114
|
|
|
242
|
-
-
|
|
243
|
-
-
|
|
244
|
-
-
|
|
115
|
+
- **按问题匹配保真度**——布局问题用线框图,视觉打磨问题再做精细化
|
|
116
|
+
- **在每页上说明问题**——「哪种看起来更专业?」而非仅仅「选一个」
|
|
117
|
+
- **先迭代再推进**——若反馈改变了当前页面,先写一个新版本
|
|
245
118
|
- **每屏最多 2-4 个选项**
|
|
246
|
-
-
|
|
119
|
+
- **在重要场景使用真实内容**——真实文案与真实配色比占位文本更能暴露问题
|
|
247
120
|
- **保持原型简洁**——聚焦布局与结构,而非像素级完美
|
|
248
121
|
|
|
249
|
-
## 文件命名
|
|
250
|
-
|
|
251
|
-
- 使用语义化名称:`platform.html`、`visual-style.html`、`layout.html`
|
|
252
|
-
- 不要复用文件名——每个页面必须是新文件
|
|
253
|
-
- 迭代时:追加版本后缀,如 `layout-v2.html`、`layout-v3.html`
|
|
254
|
-
- 服务器按修改时间提供最新的文件
|
|
255
|
-
|
|
256
122
|
## 清理
|
|
257
123
|
|
|
258
|
-
|
|
259
|
-
bash scripts/stop-server.sh $SESSION_DIR
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
如果会话使用了 `--project-dir`,原型文件会保留在 `.superpowers/brainstorm/` 中以便后续查阅。仅 `/tmp` 会话在停止时会被删除。
|
|
263
|
-
|
|
264
|
-
## 参考
|
|
265
|
-
|
|
266
|
-
- 框架模板(CSS 参考):`scripts/frame-template.html`
|
|
267
|
-
- 辅助脚本(客户端):`scripts/helper.js`
|
|
124
|
+
删除本次会话写下的所有 HTML 文件。若用了项目目录,提醒用户该目录已在 `.gitignore` 中。
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html>
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<title>Superpowers Brainstorming</title>
|
|
6
|
-
<style>
|
|
7
|
-
/*
|
|
8
|
-
* BRAINSTORM COMPANION FRAME TEMPLATE
|
|
9
|
-
*
|
|
10
|
-
* This template provides a consistent frame with:
|
|
11
|
-
* - OS-aware light/dark theming
|
|
12
|
-
* - Header branding and connection status
|
|
13
|
-
* - Scrollable main content area
|
|
14
|
-
* - CSS helpers for common UI patterns
|
|
15
|
-
*
|
|
16
|
-
* Content is injected via placeholder comment in #frame-content.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
20
|
-
html, body { height: 100%; overflow: hidden; }
|
|
21
|
-
|
|
22
|
-
/* ===== THEME VARIABLES ===== */
|
|
23
|
-
:root {
|
|
24
|
-
--bg-primary: #f5f5f7;
|
|
25
|
-
--bg-secondary: #ffffff;
|
|
26
|
-
--bg-tertiary: #e5e5e7;
|
|
27
|
-
--border: #d1d1d6;
|
|
28
|
-
--text-primary: #1d1d1f;
|
|
29
|
-
--text-secondary: #86868b;
|
|
30
|
-
--text-tertiary: #aeaeb2;
|
|
31
|
-
--accent: #0071e3;
|
|
32
|
-
--accent-hover: #0077ed;
|
|
33
|
-
--success: #34c759;
|
|
34
|
-
--warning: #ff9f0a;
|
|
35
|
-
--error: #ff3b30;
|
|
36
|
-
--selected-bg: #e8f4fd;
|
|
37
|
-
--selected-border: #0071e3;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@media (prefers-color-scheme: dark) {
|
|
41
|
-
:root {
|
|
42
|
-
--bg-primary: #1d1d1f;
|
|
43
|
-
--bg-secondary: #2d2d2f;
|
|
44
|
-
--bg-tertiary: #3d3d3f;
|
|
45
|
-
--border: #424245;
|
|
46
|
-
--text-primary: #f5f5f7;
|
|
47
|
-
--text-secondary: #86868b;
|
|
48
|
-
--text-tertiary: #636366;
|
|
49
|
-
--accent: #0a84ff;
|
|
50
|
-
--accent-hover: #409cff;
|
|
51
|
-
--selected-bg: rgba(10, 132, 255, 0.15);
|
|
52
|
-
--selected-border: #0a84ff;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
body {
|
|
57
|
-
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
58
|
-
background: var(--bg-primary);
|
|
59
|
-
color: var(--text-primary);
|
|
60
|
-
display: flex;
|
|
61
|
-
flex-direction: column;
|
|
62
|
-
line-height: 1.5;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/* ===== FRAME STRUCTURE ===== */
|
|
66
|
-
.brand { display: flex; align-items: center; min-width: 0; overflow: hidden; color: var(--text-secondary); line-height: 1; }
|
|
67
|
-
.brand a { color: inherit; text-decoration: none; display: flex; align-items: center; gap: 0.5rem; min-width: 0; max-width: 100%; line-height: 1; }
|
|
68
|
-
.brand-copy { display: block; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1; transform: translateY(-1px); }
|
|
69
|
-
.brand-logo { display: block; height: 1em; width: auto; max-width: 180px; flex-shrink: 0; filter: invert(1); }
|
|
70
|
-
@media (prefers-color-scheme: dark) {
|
|
71
|
-
.brand-logo { filter: none; }
|
|
72
|
-
}
|
|
73
|
-
.status { font-size: 0.7rem; color: var(--status-color, var(--success)); display: flex; align-items: center; gap: 0.4rem; justify-self: end; white-space: nowrap; line-height: 1; }
|
|
74
|
-
.status::before { content: ''; width: 6px; height: 6px; background: var(--status-color, var(--success)); border-radius: 50%; }
|
|
75
|
-
|
|
76
|
-
.main { flex: 1; overflow-y: auto; }
|
|
77
|
-
#frame-content { padding: 2rem; min-height: 100%; }
|
|
78
|
-
|
|
79
|
-
.header {
|
|
80
|
-
background: var(--bg-secondary);
|
|
81
|
-
border-bottom: 1px solid var(--border);
|
|
82
|
-
padding: 0.5rem 1.5rem;
|
|
83
|
-
flex-shrink: 0;
|
|
84
|
-
display: grid;
|
|
85
|
-
grid-template-columns: minmax(0, 1fr) auto;
|
|
86
|
-
align-items: center;
|
|
87
|
-
gap: 1rem;
|
|
88
|
-
min-height: 42px;
|
|
89
|
-
}
|
|
90
|
-
.header .brand { justify-self: start; width: 100%; font-size: 0.75rem; line-height: 1; }
|
|
91
|
-
.header .status { grid-column: 2; line-height: 1; }
|
|
92
|
-
.header span {
|
|
93
|
-
font-size: 0.75rem;
|
|
94
|
-
color: var(--text-secondary);
|
|
95
|
-
}
|
|
96
|
-
.header .selected-text {
|
|
97
|
-
color: var(--accent);
|
|
98
|
-
font-weight: 500;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/* ===== TYPOGRAPHY ===== */
|
|
102
|
-
h2 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
103
|
-
h3 { font-size: 1.1rem; font-weight: 600; margin-bottom: 0.25rem; }
|
|
104
|
-
.subtitle { color: var(--text-secondary); margin-bottom: 1.5rem; }
|
|
105
|
-
.section { margin-bottom: 2rem; }
|
|
106
|
-
.label { font-size: 0.7rem; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 0.5rem; }
|
|
107
|
-
|
|
108
|
-
/* ===== OPTIONS (for A/B/C choices) ===== */
|
|
109
|
-
.options { display: flex; flex-direction: column; gap: 0.75rem; }
|
|
110
|
-
.option {
|
|
111
|
-
background: var(--bg-secondary);
|
|
112
|
-
border: 2px solid var(--border);
|
|
113
|
-
border-radius: 12px;
|
|
114
|
-
padding: 1rem 1.25rem;
|
|
115
|
-
cursor: pointer;
|
|
116
|
-
transition: all 0.15s ease;
|
|
117
|
-
display: flex;
|
|
118
|
-
align-items: flex-start;
|
|
119
|
-
gap: 1rem;
|
|
120
|
-
}
|
|
121
|
-
.option:hover { border-color: var(--accent); }
|
|
122
|
-
.option.selected { background: var(--selected-bg); border-color: var(--selected-border); }
|
|
123
|
-
.option .letter {
|
|
124
|
-
background: var(--bg-tertiary);
|
|
125
|
-
color: var(--text-secondary);
|
|
126
|
-
width: 1.75rem; height: 1.75rem;
|
|
127
|
-
border-radius: 6px;
|
|
128
|
-
display: flex; align-items: center; justify-content: center;
|
|
129
|
-
font-weight: 600; font-size: 0.85rem; flex-shrink: 0;
|
|
130
|
-
}
|
|
131
|
-
.option.selected .letter { background: var(--accent); color: white; }
|
|
132
|
-
.option .content { flex: 1; }
|
|
133
|
-
.option .content h3 { font-size: 0.95rem; margin-bottom: 0.15rem; }
|
|
134
|
-
.option .content p { color: var(--text-secondary); font-size: 0.85rem; margin: 0; }
|
|
135
|
-
|
|
136
|
-
/* ===== CARDS (for showing designs/mockups) ===== */
|
|
137
|
-
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1rem; }
|
|
138
|
-
.card {
|
|
139
|
-
background: var(--bg-secondary);
|
|
140
|
-
border: 1px solid var(--border);
|
|
141
|
-
border-radius: 12px;
|
|
142
|
-
overflow: hidden;
|
|
143
|
-
cursor: pointer;
|
|
144
|
-
transition: all 0.15s ease;
|
|
145
|
-
}
|
|
146
|
-
.card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
|
|
147
|
-
.card.selected { border-color: var(--selected-border); border-width: 2px; }
|
|
148
|
-
.card-image { background: var(--bg-tertiary); aspect-ratio: 16/10; display: flex; align-items: center; justify-content: center; }
|
|
149
|
-
.card-body { padding: 1rem; }
|
|
150
|
-
.card-body h3 { margin-bottom: 0.25rem; }
|
|
151
|
-
.card-body p { color: var(--text-secondary); font-size: 0.85rem; }
|
|
152
|
-
|
|
153
|
-
/* ===== MOCKUP CONTAINER ===== */
|
|
154
|
-
.mockup {
|
|
155
|
-
background: var(--bg-secondary);
|
|
156
|
-
border: 1px solid var(--border);
|
|
157
|
-
border-radius: 12px;
|
|
158
|
-
overflow: hidden;
|
|
159
|
-
margin-bottom: 1.5rem;
|
|
160
|
-
}
|
|
161
|
-
.mockup-header {
|
|
162
|
-
background: var(--bg-tertiary);
|
|
163
|
-
padding: 0.5rem 1rem;
|
|
164
|
-
font-size: 0.75rem;
|
|
165
|
-
color: var(--text-secondary);
|
|
166
|
-
border-bottom: 1px solid var(--border);
|
|
167
|
-
}
|
|
168
|
-
.mockup-body { padding: 1.5rem; }
|
|
169
|
-
|
|
170
|
-
/* ===== SPLIT VIEW (side-by-side comparison) ===== */
|
|
171
|
-
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
|
|
172
|
-
@media (max-width: 700px) { .split { grid-template-columns: 1fr; } }
|
|
173
|
-
|
|
174
|
-
/* ===== PROS/CONS ===== */
|
|
175
|
-
.pros-cons { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1rem 0; }
|
|
176
|
-
.pros, .cons { background: var(--bg-secondary); border-radius: 8px; padding: 1rem; }
|
|
177
|
-
.pros h4 { color: var(--success); font-size: 0.85rem; margin-bottom: 0.5rem; }
|
|
178
|
-
.cons h4 { color: var(--error); font-size: 0.85rem; margin-bottom: 0.5rem; }
|
|
179
|
-
.pros ul, .cons ul { margin-left: 1.25rem; font-size: 0.85rem; color: var(--text-secondary); }
|
|
180
|
-
.pros li, .cons li { margin-bottom: 0.25rem; }
|
|
181
|
-
|
|
182
|
-
/* ===== PLACEHOLDER (for mockup areas) ===== */
|
|
183
|
-
.placeholder {
|
|
184
|
-
background: var(--bg-tertiary);
|
|
185
|
-
border: 2px dashed var(--border);
|
|
186
|
-
border-radius: 8px;
|
|
187
|
-
padding: 2rem;
|
|
188
|
-
text-align: center;
|
|
189
|
-
color: var(--text-tertiary);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/* ===== INLINE MOCKUP ELEMENTS ===== */
|
|
193
|
-
.mock-nav { background: var(--accent); color: white; padding: 0.75rem 1rem; display: flex; gap: 1.5rem; font-size: 0.9rem; }
|
|
194
|
-
.mock-sidebar { background: var(--bg-tertiary); padding: 1rem; min-width: 180px; }
|
|
195
|
-
.mock-content { padding: 1.5rem; flex: 1; }
|
|
196
|
-
.mock-button { background: var(--accent); color: white; border: none; padding: 0.5rem 1rem; border-radius: 6px; font-size: 0.85rem; }
|
|
197
|
-
.mock-input { background: var(--bg-primary); border: 1px solid var(--border); border-radius: 6px; padding: 0.5rem; width: 100%; }
|
|
198
|
-
</style>
|
|
199
|
-
</head>
|
|
200
|
-
<body>
|
|
201
|
-
<div class="header">
|
|
202
|
-
<!-- BRANDING -->
|
|
203
|
-
<div class="status">Connecting…</div>
|
|
204
|
-
</div>
|
|
205
|
-
|
|
206
|
-
<div class="main">
|
|
207
|
-
<div id="frame-content">
|
|
208
|
-
<!-- CONTENT -->
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
|
|
212
|
-
</body>
|
|
213
|
-
</html>
|