@namewta/speculo 0.8.6 → 0.8.7

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.
Files changed (74) hide show
  1. package/package.json +1 -1
  2. package/template/canonical/canonical-specdev-goal-plan.md +14 -14
  3. package/template/canonical/canonical-specdev-grill-with-docs.md +9 -7
  4. package/template/canonical/canonical-specdev-spec.md +9 -7
  5. package/template/canonical/canonical-specdev-tickets.md +13 -13
  6. package/template/canonical/canonical-specdev-wayfinder.md +7 -7
  7. package/template/workflows/specdev/I-init-setup/I-init-setup.md +1 -1
  8. package/template/workflows/specdev/I-init-setup/config-template.json +2 -2
  9. package/template/workflows/specdev/P-goal-plan/planning-modes.md +1 -1
  10. package/template/workflows/specdev/P-prototype/P-prototype.md +30 -26
  11. package/template/workflows/specdev/P-prototype/design-library/INDEX.md +43 -0
  12. package/template/workflows/specdev/P-prototype/design-library/color-and-theme.md +65 -0
  13. package/template/workflows/specdev/P-prototype/design-library/foundations.md +66 -0
  14. package/template/workflows/specdev/P-prototype/design-library/interaction-patterns.md +61 -0
  15. package/template/workflows/specdev/P-prototype/design-library/product-pattern-index.md +73 -0
  16. package/template/workflows/specdev/P-prototype/design-library/research-provenance.md +54 -0
  17. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/METHODOLOGY.md +90 -0
  18. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/README.md +31 -0
  19. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/data/extended-projects.json +241 -0
  20. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/data/projects.json +253 -0
  21. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/reference/USAGE.md +40 -0
  22. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/reference/design-tokens.css +145 -0
  23. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/report/OPEN_SOURCE_UI_RESEARCH_2026.md +519 -0
  24. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/PROJECT_TEMPLATE.md +29 -0
  25. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/README.md +9 -0
  26. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/claude-code-modern-clients.md +407 -0
  27. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/creative-ai-communication.md +574 -0
  28. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/data-dev-tools.md +432 -0
  29. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/personal-multiplatform-apps.md +185 -0
  30. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/research/productivity-collaboration.md +398 -0
  31. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/01-dense-ide.html +68 -0
  32. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/02-monochrome-console.html +18 -0
  33. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/03-soft-personal-ai.html +17 -0
  34. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/04-responsive-web.html +14 -0
  35. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/05-mobile-supervisor.html +16 -0
  36. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/06-cross-platform-workspace.html +17 -0
  37. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/07-local-first-content.html +9 -0
  38. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/08-media-first.html +17 -0
  39. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/README.md +49 -0
  40. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/assets/ATTRIBUTION.md +9 -0
  41. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/assets/landscape.jpg +0 -0
  42. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/assets/lucide.js +20494 -0
  43. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/assets/mountain.jpg +0 -0
  44. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/assets/workspace.jpg +0 -0
  45. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/index.html +70 -0
  46. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/package-lock.json +78 -0
  47. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/package.json +12 -0
  48. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/screenshots/index-desktop.png +0 -0
  49. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/scripts/gallery.js +134 -0
  50. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/styles/base.css +795 -0
  51. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/styles/pages.css +533 -0
  52. package/template/workflows/specdev/P-prototype/design-library/research-snapshot/ui-gallery/tests/gallery.spec.js +56 -0
  53. package/template/workflows/specdev/P-prototype/design-library/responsive-and-platforms.md +53 -0
  54. package/template/workflows/specdev/P-prototype/design-library/style-index.md +32 -0
  55. package/template/workflows/specdev/P-prototype/design-package.schema.json +70 -0
  56. package/template/workflows/specdev/P-prototype/design-system-template.md +366 -0
  57. package/template/workflows/specdev/P-prototype/detect-existing-style.md +53 -0
  58. package/template/workflows/specdev/P-prototype/generate-design-package.md +50 -0
  59. package/template/workflows/specdev/P-prototype/style-selection-protocol.md +41 -0
  60. package/template/workflows/specdev/P-prototype/tools/materialize-prototype.mjs +126 -0
  61. package/template/workflows/specdev/P-prototype/tools/validate-design-package.mjs +155 -0
  62. package/template/workflows/specdev/README.md +11 -5
  63. package/template/workflows/specdev/T-triage/T-triage.md +1 -1
  64. package/template/workflows/specdev/W-wayfinder/W-wayfinder.md +1 -1
  65. package/template/workflows/specdev/common/README.md +2 -2
  66. package/template/workflows/specdev/common/rules/artifact-contract.md +3 -1
  67. package/template/workflows/specdev/common/schemas/config.schema.json +4 -4
  68. package/template/workflows/specdev/common/skills/dev-worktree/SKILL.md +4 -4
  69. package/template/workflows/specdev/common/skills/dev-worktree/references/create.md +1 -3
  70. package/template/workflows/specdev/common/tools/validate-specdev.mjs +88 -29
  71. package/template/workflows/specdev/P-prototype/logic-prototype.md +0 -24
  72. package/template/workflows/specdev/P-prototype/prototype-record-template.md +0 -46
  73. package/template/workflows/specdev/P-prototype/ui-prototype.md +0 -21
  74. package/template/workflows/specdev/common/schemas/prototype-record.schema.json +0 -24
@@ -0,0 +1,533 @@
1
+ /* Gallery index */
2
+ .gallery-page {
3
+ overflow: auto;
4
+ background: #f3f4f5;
5
+ color: #16181b;
6
+ --surface: #ffffff;
7
+ --text: #16181b;
8
+ --text-2: #5f6670;
9
+ --text-3: #8a929d;
10
+ --border: #dde1e6;
11
+ }
12
+
13
+ .gallery-shell {
14
+ min-height: 100%;
15
+ }
16
+
17
+ .gallery-topbar {
18
+ position: sticky;
19
+ z-index: 20;
20
+ top: 0;
21
+ display: flex;
22
+ height: 52px;
23
+ align-items: center;
24
+ gap: 10px;
25
+ padding: 0 20px;
26
+ border-bottom: 1px solid #dde1e6;
27
+ background: rgba(255, 255, 255, 0.92);
28
+ backdrop-filter: blur(18px);
29
+ }
30
+
31
+ .gallery-topbar strong {
32
+ font-size: 14px;
33
+ }
34
+
35
+ .gallery-topbar span {
36
+ color: #818995;
37
+ font-size: 12px;
38
+ }
39
+
40
+ .gallery-main {
41
+ width: min(1480px, 100%);
42
+ margin: 0 auto;
43
+ padding: 24px;
44
+ }
45
+
46
+ .gallery-summary {
47
+ display: grid;
48
+ grid-template-columns: minmax(0, 1fr) auto;
49
+ align-items: end;
50
+ gap: 24px;
51
+ margin-bottom: 20px;
52
+ }
53
+
54
+ .gallery-summary h1 {
55
+ max-width: 720px;
56
+ margin: 0 0 8px;
57
+ font-size: 25px;
58
+ line-height: 1.25;
59
+ }
60
+
61
+ .gallery-summary p {
62
+ max-width: 760px;
63
+ margin: 0;
64
+ color: #626a74;
65
+ font-size: 14px;
66
+ line-height: 1.65;
67
+ }
68
+
69
+ .gallery-metrics {
70
+ display: flex;
71
+ gap: 18px;
72
+ }
73
+
74
+ .metric {
75
+ min-width: 74px;
76
+ }
77
+
78
+ .metric b {
79
+ display: block;
80
+ font-size: 24px;
81
+ }
82
+
83
+ .metric span {
84
+ color: #818995;
85
+ font-size: 11px;
86
+ }
87
+
88
+ .style-grid {
89
+ display: grid;
90
+ grid-template-columns: repeat(4, minmax(0, 1fr));
91
+ gap: 14px;
92
+ }
93
+
94
+ .style-card {
95
+ display: flex;
96
+ min-width: 0;
97
+ min-height: 300px;
98
+ flex-direction: column;
99
+ overflow: hidden;
100
+ border: 1px solid #dde1e6;
101
+ border-radius: 8px;
102
+ background: #fff;
103
+ transition: border-color 160ms ease, transform 160ms ease, box-shadow 160ms ease;
104
+ }
105
+
106
+ .style-card:hover {
107
+ border-color: #afb6c0;
108
+ box-shadow: 0 12px 28px rgba(18, 25, 36, 0.08);
109
+ transform: translateY(-2px);
110
+ }
111
+
112
+ .style-preview {
113
+ position: relative;
114
+ height: 186px;
115
+ flex: 0 0 auto;
116
+ overflow: hidden;
117
+ border-bottom: 1px solid #e6e9ed;
118
+ background: var(--preview-bg, #f5f6f7);
119
+ }
120
+
121
+ .mini-app {
122
+ position: absolute;
123
+ inset: 12px;
124
+ display: grid;
125
+ grid-template-columns: 17% 28% 1fr 25%;
126
+ grid-template-rows: 16px 1fr 12px;
127
+ overflow: hidden;
128
+ border: 1px solid var(--p-border, #d9dde2);
129
+ border-radius: var(--p-radius, 4px);
130
+ background: var(--p-surface, #fff);
131
+ box-shadow: 0 8px 24px rgba(18, 24, 32, 0.1);
132
+ }
133
+
134
+ .mini-top { grid-column: 1 / -1; background: var(--p-top, #eceff2); border-bottom: 1px solid var(--p-border, #d9dde2); }
135
+ .mini-rail { grid-row: 2; background: var(--p-rail, #202327); }
136
+ .mini-side { grid-row: 2; background: var(--p-side, #f0f2f4); border-right: 1px solid var(--p-border, #d9dde2); }
137
+ .mini-main { position: relative; grid-row: 2; background: var(--p-main, #fff); }
138
+ .mini-right { grid-row: 2; background: var(--p-right, #f7f8f9); border-left: 1px solid var(--p-border, #d9dde2); }
139
+ .mini-status { grid-column: 1 / -1; background: var(--p-accent, #2563eb); }
140
+
141
+ .mini-main::before,
142
+ .mini-main::after,
143
+ .mini-side::before,
144
+ .mini-right::before {
145
+ position: absolute;
146
+ display: block;
147
+ border-radius: 3px;
148
+ background: var(--p-line, #cbd0d7);
149
+ content: "";
150
+ }
151
+
152
+ .mini-main::before { top: 24%; right: 13%; left: 13%; height: 8%; box-shadow: 0 18px 0 var(--p-line, #cbd0d7), 0 36px 0 var(--p-line, #cbd0d7); }
153
+ .mini-main::after { right: 12%; bottom: 10%; left: 12%; height: 17%; border: 1px solid var(--p-border, #d9dde2); background: var(--p-input, #f7f8fa); }
154
+ .mini-side::before { top: 16%; right: 14%; left: 14%; height: 7%; box-shadow: 0 16px 0 var(--p-line, #cbd0d7), 0 32px 0 var(--p-active, #fff), 0 48px 0 var(--p-line, #cbd0d7); }
155
+ .mini-right::before { top: 14%; right: 15%; left: 15%; height: 9%; box-shadow: 0 20px 0 var(--p-line, #cbd0d7), 0 40px 0 var(--p-line, #cbd0d7), 0 60px 0 var(--p-line, #cbd0d7); }
156
+
157
+ .preview-ide { --preview-bg:#e8e9eb; --p-surface:#fff; --p-side:#ededee; --p-rail:#111; --p-right:#f4f4f4; --p-top:#f5f5f5; --p-accent:#d96b27; --p-radius:2px; }
158
+ .preview-console { --preview-bg:#101214; --p-surface:#181b1e; --p-side:#202428; --p-rail:#0d0f11; --p-right:#15181b; --p-top:#15181b; --p-line:#343a40; --p-border:#2b3035; --p-input:#202428; --p-accent:#e9ecef; --p-radius:8px; }
159
+ .preview-soft { --preview-bg:#e9e8e5; --p-surface:#fff; --p-side:#f4f3f0; --p-rail:#ecebe7; --p-right:#faf9f7; --p-top:#fbfaf8; --p-line:#dedbd5; --p-border:#e4e0d9; --p-active:#e6e2db; --p-accent:#262626; --p-radius:12px; }
160
+ .preview-web { --preview-bg:#eef1f4; --p-surface:#fff; --p-side:#f4f2ed; --p-rail:#f0eee8; --p-right:#f8f7f3; --p-top:#fff; --p-accent:#3979e8; --p-radius:7px; }
161
+ .preview-mobile .mini-app { inset: 10px 30%; grid-template-columns: 1fr; grid-template-rows: 15px 1fr 20px; border-radius: 18px; }
162
+ .preview-mobile .mini-top { grid-column: 1; }
163
+ .preview-mobile .mini-rail,.preview-mobile .mini-side,.preview-mobile .mini-right { display:none; }
164
+ .preview-mobile .mini-main { grid-row:2; }
165
+ .preview-mobile .mini-status { grid-column:1; border-radius:10px 10px 0 0; background:#5e52a7; }
166
+ .preview-mobile { --preview-bg:#eeedf3; --p-surface:#fffbff; --p-top:#f3eff8; --p-line:#ded7ee; --p-border:#cfc7df; --p-input:#e5deff; }
167
+ .preview-paseo { --preview-bg:#e8eeeb; --p-surface:#fff; --p-side:#f4f4f5; --p-rail:#eef2ef; --p-right:#fafafa; --p-top:#fff; --p-accent:#20744a; --p-radius:6px; }
168
+ .preview-content { --preview-bg:#efeee9; --p-surface:#fffefb; --p-side:#f4f2ec; --p-rail:#e9e5da; --p-right:#fffefb; --p-top:#fffefb; --p-accent:#b05e3c; --p-radius:6px; }
169
+ .preview-media { --preview-bg:#17191c; --p-surface:#1f2226; --p-side:#191b1e; --p-rail:#101214; --p-right:#24272c; --p-top:#181a1d; --p-line:#393d44; --p-border:#30343a; --p-input:#2a2e33; --p-accent:#62a7ff; --p-radius:8px; }
170
+
171
+ .style-card-body {
172
+ display: flex;
173
+ flex: 1;
174
+ flex-direction: column;
175
+ padding: 14px;
176
+ }
177
+
178
+ .style-number {
179
+ color: #939aa3;
180
+ font: 10px var(--font-mono);
181
+ }
182
+
183
+ .style-card h2 {
184
+ margin: 6px 0 5px;
185
+ font-size: 15px;
186
+ }
187
+
188
+ .style-card p {
189
+ margin: 0;
190
+ color: #686f79;
191
+ font-size: 12px;
192
+ line-height: 1.55;
193
+ }
194
+
195
+ .style-tags {
196
+ display: flex;
197
+ flex-wrap: wrap;
198
+ gap: 5px;
199
+ margin-top: auto;
200
+ padding-top: 12px;
201
+ }
202
+
203
+ .style-tags span {
204
+ padding: 3px 6px;
205
+ border-radius: 3px;
206
+ background: #f0f2f4;
207
+ color: #626a74;
208
+ font-size: 10px;
209
+ }
210
+
211
+ /* 01 Dense IDE */
212
+ .theme-ide {
213
+ --bg: #eceeef;
214
+ --surface: #ffffff;
215
+ --surface-2: #f2f3f4;
216
+ --surface-3: #e1e4e7;
217
+ --text: #151719;
218
+ --text-2: #5f646a;
219
+ --text-3: #858b92;
220
+ --border: #d6d9dd;
221
+ --accent: #d96b27;
222
+ --accent-soft: #fff0e6;
223
+ --accent-fg: #ffffff;
224
+ --radius-sm: 2px;
225
+ --radius-md: 3px;
226
+ --radius-lg: 4px;
227
+ --font-ui: "IBM Plex Sans", Inter, ui-sans-serif, system-ui, "PingFang SC", sans-serif;
228
+ --control-h: 30px;
229
+ --sidebar: 230px;
230
+ --right-panel: 330px;
231
+ --ui-size: 13px;
232
+ }
233
+
234
+ html.dark .theme-ide,
235
+ html.dark body.theme-ide {
236
+ --bg: #0b0c0d;
237
+ --surface: #111315;
238
+ --surface-2: #181b1e;
239
+ --surface-3: #22262a;
240
+ --text: #f3f4f5;
241
+ --text-2: #b0b5bb;
242
+ --text-3: #727980;
243
+ --border: #2b3035;
244
+ --accent: #e47c38;
245
+ }
246
+
247
+ .ide-rail {
248
+ display: flex;
249
+ width: 48px;
250
+ flex: 0 0 48px;
251
+ flex-direction: column;
252
+ align-items: center;
253
+ gap: 3px;
254
+ padding: 7px 0;
255
+ border-right: 1px solid var(--border);
256
+ background: #111315;
257
+ color: #9ba1a8;
258
+ }
259
+
260
+ .ide-rail .tool-btn:hover,
261
+ .ide-rail .tool-btn.active { background: #292d31; color: #fff; }
262
+ .ide-rail .tool-btn.active::before { position:absolute; left:0; width:2px; height:20px; background:var(--accent); content:""; }
263
+ .ide-rail .tool-btn { position: relative; border-radius: 2px; }
264
+ .ide-rail-spacer { flex: 1; }
265
+
266
+ .ide-explorer { display:flex; flex-direction:column; width:var(--sidebar); flex:0 0 var(--sidebar); border-right:1px solid var(--border); background:var(--surface-2); }
267
+ .ide-tree { padding: 5px 0; font: 12px/1.7 var(--font-mono); }
268
+ .tree-row { display:flex; min-height:24px; align-items:center; gap:5px; padding:0 8px; color:var(--text-2); white-space:nowrap; }
269
+ .tree-row:hover,.tree-row.active { background:var(--surface-3); color:var(--text); }
270
+ .tree-row .indent { width:12px; flex:0 0 12px; }
271
+ .tree-row svg { width:14px; height:14px; }
272
+ .file-ts { color:#3f88c5; } .file-css { color:#a06bc8; } .file-md { color:#6d8a9c; }
273
+
274
+ .ide-center { position:relative; display:flex; min-width:0; flex:1; flex-direction:column; background:var(--surface); }
275
+ .ide-tabbar { display:flex; min-height:34px; border-bottom:1px solid var(--border); background:var(--surface-2); }
276
+ .ide-tab { display:flex; min-width:130px; align-items:center; gap:6px; padding:0 10px; border-right:1px solid var(--border); color:var(--text-2); font-size:12px; }
277
+ .ide-tab.active { border-top:2px solid var(--accent); background:var(--surface); color:var(--text); }
278
+ .ide-editor { display:grid; grid-template-columns:1fr 1fr; min-height:0; flex:1; }
279
+ .editor-pane { min-width:0; overflow:auto; border-right:1px solid var(--border); }
280
+ .editor-pane:last-child { border-right:0; }
281
+ .editor-title { display:flex; height:30px; align-items:center; padding:0 10px; border-bottom:1px solid var(--border); color:var(--text-2); font-size:11px; }
282
+ .ide-code { padding:8px 0; background:var(--surface); font:12px/1.75 var(--font-mono); }
283
+ .ide-code .code-line { padding:0 12px; }
284
+ .ide-code .code-line.active { background:color-mix(in srgb,var(--accent) 8%,transparent); }
285
+ .ide-terminal { height:180px; flex:0 0 180px; border-top:1px solid var(--border); background:#101214; color:#d5d9de; }
286
+ .terminal-head { display:flex; height:34px; align-items:center; gap:14px; padding:0 10px; border-bottom:1px solid #272b30; color:#8c949d; font-size:11px; }
287
+ .terminal-head .active { color:#fff; }
288
+ .terminal-body { padding:10px 12px; font:11px/1.65 var(--font-mono); }
289
+ .prompt { color:#71c18c; }
290
+ .ide-review { display:flex; width:var(--right-panel); flex:0 0 var(--right-panel); flex-direction:column; border-left:1px solid var(--border); background:var(--surface); }
291
+ .change-group { padding:9px 10px; border-bottom:1px solid var(--border); }
292
+ .change-title { display:flex; align-items:center; gap:7px; font-size:12px; font-weight:650; }
293
+ .change-stats { margin-left:auto; font:10px var(--font-mono); }
294
+ .plus { color:var(--success); } .minus { color:var(--danger); }
295
+ .ide-statusbar { display:flex; min-height:23px; align-items:center; gap:14px; padding:0 8px; background:var(--accent); color:#fff; font-size:10px; }
296
+ .ide-statusbar .push { margin-left:auto; }
297
+
298
+ /* 02 Monochrome desktop control center */
299
+ .theme-console {
300
+ --bg:#0e1012; --surface:#15181b; --surface-2:#1b1f23; --surface-3:#24292e; --text:#f1f3f5; --text-2:#a9b0b7; --text-3:#6f7881; --border:#2a3036;
301
+ --accent:#eef0f2; --accent-soft:#2a2f34; --accent-fg:#151719; --radius-sm:4px; --radius-md:8px; --radius-lg:12px;
302
+ --font-ui:Inter,system-ui,"PingFang SC",sans-serif; --control-h:34px; --sidebar:252px; --right-panel:320px;
303
+ }
304
+ .theme-console .utility-mark { background:#f0f2f4; color:#151719; }
305
+ .console-sidebar { display:flex; width:var(--sidebar); flex:0 0 var(--sidebar); flex-direction:column; border-right:1px solid var(--border); background:#121416; }
306
+ .console-logo { display:flex; height:54px; align-items:center; gap:10px; padding:0 14px; border-bottom:1px solid var(--border); font-weight:700; }
307
+ .console-logo .logo-glyph { display:grid; width:28px; height:28px; place-items:center; border:1px solid #3a4046; border-radius:8px; background:#202429; }
308
+ .console-main { display:flex; min-width:0; flex:1; flex-direction:column; }
309
+ .console-overview { display:grid; grid-template-columns:repeat(4,minmax(130px,1fr)); gap:1px; border-bottom:1px solid var(--border); background:var(--border); }
310
+ .console-stat { min-height:92px; padding:16px; background:var(--surface); }
311
+ .console-stat span { color:var(--text-3); font-size:11px; }
312
+ .console-stat b { display:block; margin-top:8px; font-size:24px; font-weight:600; }
313
+ .console-stat small { color:var(--success); font-size:10px; }
314
+ .console-content { display:grid; grid-template-columns:minmax(420px,1.55fr) minmax(280px,0.8fr); min-height:0; flex:1; }
315
+ .session-column { min-width:0; border-right:1px solid var(--border); }
316
+ .session-row { display:grid; grid-template-columns:32px 1fr auto; gap:10px; padding:12px 14px; border-bottom:1px solid var(--border); }
317
+ .session-row:hover { background:var(--surface-2); }
318
+ .session-copy { min-width:0; }
319
+ .session-copy strong { display:block; overflow:hidden; font-size:13px; text-overflow:ellipsis; white-space:nowrap; }
320
+ .session-copy p { margin:4px 0 0; overflow:hidden; color:var(--text-3); font-size:11px; text-overflow:ellipsis; white-space:nowrap; }
321
+ .analytics-column { min-width:0; padding:14px; overflow:auto; }
322
+ .chart-shell { height:170px; padding:12px; border:1px solid var(--border); border-radius:10px; background:var(--surface-2); }
323
+ .bar-chart { display:flex; height:115px; align-items:end; gap:8px; padding-top:10px; }
324
+ .bar-chart i { flex:1; min-width:8px; border-radius:3px 3px 0 0; background:linear-gradient(to top,#3a4046,#e2e5e8); }
325
+ .bar-chart i:nth-child(1){height:38%}.bar-chart i:nth-child(2){height:62%}.bar-chart i:nth-child(3){height:49%}.bar-chart i:nth-child(4){height:78%}.bar-chart i:nth-child(5){height:56%}.bar-chart i:nth-child(6){height:91%}.bar-chart i:nth-child(7){height:70%}
326
+ .agent-card { margin-top:12px; padding:12px; border:1px solid var(--border); border-radius:10px; background:var(--surface); }
327
+ .agent-card-head { display:flex; align-items:center; gap:8px; }
328
+ .agent-card p { margin:8px 0 0; color:var(--text-2); font-size:11px; line-height:1.55; }
329
+
330
+ /* 03 Soft personal AI desktop */
331
+ .theme-soft {
332
+ --bg:#efeeeb; --surface:#fff; --surface-2:#f5f4f1; --surface-3:#e8e5df; --text:#242424; --text-2:#66625d; --text-3:#969089; --border:#e2ded7;
333
+ --accent:#262626; --accent-soft:#ece9e3; --accent-fg:#fff; --radius-sm:8px; --radius-md:12px; --radius-lg:16px; --control-h:36px; --sidebar:264px; --right-panel:360px;
334
+ }
335
+ html.dark .theme-soft,html.dark body.theme-soft { --bg:#161513; --surface:#1d1c1a; --surface-2:#272522; --surface-3:#34312c; --text:#f3f0ea; --text-2:#b8b1a8; --text-3:#7f7971; --border:#34312d; --accent:#f3f0ea; --accent-fg:#24211e; }
336
+ .soft-shell { gap:8px; padding:8px; }
337
+ .soft-sidebar { display:flex; width:var(--sidebar); flex:0 0 var(--sidebar); flex-direction:column; overflow:hidden; border:1px solid var(--border); border-radius:16px; background:color-mix(in srgb,var(--surface-2) 86%,transparent); }
338
+ .soft-main { position:relative; display:flex; min-width:0; flex:1; flex-direction:column; overflow:hidden; border:1px solid var(--border); border-radius:16px; background:var(--surface); }
339
+ .soft-right { display:flex; width:var(--right-panel); flex:0 0 var(--right-panel); flex-direction:column; overflow:hidden; border:1px solid var(--border); border-radius:16px; background:var(--surface); }
340
+ .soft-greeting { padding:18px 16px 10px; }
341
+ .soft-greeting strong { display:block; font-size:15px; }
342
+ .soft-greeting span { color:var(--text-3); font-size:11px; }
343
+ .soft-project { margin:4px 9px; padding:10px; border-radius:11px; }
344
+ .soft-project.active { background:var(--surface); box-shadow:0 2px 10px rgba(35,31,25,.06); }
345
+ .soft-project-head { display:flex; align-items:center; gap:8px; font-size:12px; font-weight:650; }
346
+ .soft-project p { margin:5px 0 0 28px; color:var(--text-3); font-size:10px; }
347
+ .soft-main .message-list { padding-top:28px; }
348
+ .soft-main .composer { border-radius:16px; box-shadow:0 12px 40px -8px rgba(35,30,25,.15),0 4px 12px -4px rgba(35,30,25,.06); }
349
+ .soft-main .message.user .message-body { border-radius:15px 15px 4px 15px; background:var(--text); color:var(--surface); }
350
+ .context-ring { position:relative; display:grid; width:70px; height:70px; margin:18px auto 10px; place-items:center; border-radius:50%; background:conic-gradient(var(--accent) 0 72%,var(--surface-3) 72%); }
351
+ .context-ring::after { position:absolute; inset:6px; border-radius:50%; background:var(--surface); content:""; }
352
+ .context-ring b { position:relative; z-index:1; font-size:15px; }
353
+ .context-list { display:grid; gap:1px; margin:0 12px; overflow:hidden; border:1px solid var(--border); border-radius:11px; background:var(--border); }
354
+ .context-row { display:grid; grid-template-columns:8px 1fr auto; align-items:center; gap:8px; padding:9px 10px; background:var(--surface); font-size:11px; }
355
+ .context-row i { width:7px; height:7px; border-radius:50%; background:var(--dot); }
356
+ .soft-banner { margin:12px; padding:11px; border-radius:12px; background:var(--surface-2); color:var(--text-2); font-size:11px; line-height:1.55; }
357
+
358
+ /* 04 Responsive web */
359
+ .theme-web {
360
+ --bg:#f4f2ed; --surface:#fff; --surface-2:#f3f1eb; --surface-3:#e8e5dd; --text:#171613; --text-2:#65615a; --text-3:#918b82; --border:#dedad1;
361
+ --accent:#3978e6; --accent-soft:#eaf1ff; --accent-fg:#fff; --radius-sm:4px; --radius-md:6px; --radius-lg:8px; --sidebar:260px; --right-panel:350px;
362
+ }
363
+ html.dark .theme-web,html.dark body.theme-web { --bg:#121212; --surface:#1b1b1b; --surface-2:#252525; --surface-3:#303030; --text:#f0efec; --text-2:#aaa6a0; --text-3:#77736d; --border:#2e2e2e; --accent:#5a94f4; }
364
+ .web-sidebar { display:flex; flex-direction:column; }
365
+ .search-box { display:flex; min-height:34px; align-items:center; gap:7px; margin:8px; padding:0 9px; border:1px solid var(--border); border-radius:var(--radius-md); background:color-mix(in srgb,var(--surface) 65%,transparent); color:var(--text-3); font-size:11px; }
366
+ .web-main { position:relative; display:flex; min-width:0; flex:1; flex-direction:column; }
367
+ .web-right { display:flex; width:var(--right-panel); flex:0 0 var(--right-panel); flex-direction:column; border-left:1px solid var(--border); background:var(--surface); }
368
+ .web-bottom-nav { position:absolute; z-index:25; right:12px; bottom:calc(8px + env(safe-area-inset-bottom)); left:12px; display:none; height:52px; align-items:center; justify-content:space-around; border:1px solid var(--border); border-radius:16px; background:color-mix(in srgb,var(--surface) 88%,transparent); box-shadow:0 12px 30px rgba(20,25,32,.16); backdrop-filter:blur(20px) saturate(1.4); }
369
+ .web-bottom-nav button { display:grid; width:44px; height:40px; place-items:center; border-radius:12px; background:transparent; color:var(--text-3); }
370
+ .web-bottom-nav button.active { background:var(--accent-soft); color:var(--accent); }
371
+ .plan-list { display:grid; gap:8px; padding:12px; }
372
+ .plan-step { display:grid; grid-template-columns:20px 1fr; gap:8px; color:var(--text-2); font-size:11px; line-height:1.45; }
373
+ .plan-step i { display:grid; width:19px; height:19px; place-items:center; border-radius:50%; background:var(--surface-2); color:var(--text-3); font-style:normal; font-size:9px; }
374
+ .plan-step.done i { background:color-mix(in srgb,var(--success) 14%,transparent); color:var(--success); }
375
+ .preview-frame { margin:12px; overflow:hidden; border:1px solid var(--border); border-radius:8px; }
376
+ .preview-address { display:flex; height:28px; align-items:center; gap:5px; padding:0 8px; border-bottom:1px solid var(--border); background:var(--surface-2); }
377
+ .preview-dot { width:6px; height:6px; border-radius:50%; background:var(--surface-3); }
378
+ .preview-content { display:grid; height:160px; place-items:center; background:var(--surface); }
379
+ .preview-content img { width:100%; height:100%; object-fit:cover; }
380
+
381
+ /* 05 Mobile supervisor */
382
+ .theme-mobile { --bg:#e9e7ed; --surface:#fffbff; --surface-2:#f3eef7; --surface-3:#e5deed; --text:#1c1b1f; --text-2:#5f5b66; --text-3:#8d8794; --border:#d7d0df; --accent:#5e52a7; --accent-soft:#e5deff; --accent-fg:#fff; --radius-sm:12px; --radius-md:18px; --radius-lg:22px; --ui-size:15px; }
383
+ html.dark .theme-mobile,html.dark body.theme-mobile { --bg:#111013; --surface:#1c1b1f; --surface-2:#28252d; --surface-3:#48454f; --text:#e5e1e6; --text-2:#c9c5d0; --text-3:#928f99; --border:#48454f; --accent:#c8bfff; --accent-soft:#463a8d; --accent-fg:#2f2176; }
384
+ .mobile-stage { display:grid; min-height:0; flex:1; grid-template-columns:minmax(220px,340px) minmax(320px,430px); justify-content:center; gap:28px; padding:22px; overflow:auto; background:var(--bg); }
385
+ .phone-frame { display:flex; width:100%; max-width:390px; height:min(760px,calc(100vh - 104px)); min-height:580px; flex-direction:column; overflow:hidden; border:1px solid var(--border); border-radius:32px; background:var(--surface); box-shadow:0 26px 70px rgba(39,29,53,.2); }
386
+ .phone-status { display:flex; height:30px; align-items:center; justify-content:space-between; padding:0 18px; font-size:10px; font-weight:700; }
387
+ .phone-header { display:flex; min-height:52px; align-items:center; gap:10px; padding:0 14px; }
388
+ .phone-header strong { font-size:17px; }
389
+ .phone-header .icon-btn { width:38px; height:38px; border-radius:50%; }
390
+ .session-cards { display:grid; gap:10px; padding:8px 12px 100px; overflow:auto; }
391
+ .mobile-session { padding:14px; border:1px solid var(--border); border-radius:18px; background:var(--surface); }
392
+ .mobile-session.active { border-color:color-mix(in srgb,var(--accent) 38%,var(--border)); background:var(--accent-soft); }
393
+ .mobile-session-head { display:flex; align-items:center; gap:10px; }
394
+ .mobile-session-head strong { min-width:0; flex:1; overflow:hidden; font-size:14px; text-overflow:ellipsis; white-space:nowrap; }
395
+ .mobile-session p { margin:10px 0 0; color:var(--text-2); font-size:13px; line-height:1.45; }
396
+ .mobile-session-meta { display:flex; align-items:center; gap:7px; margin-top:11px; color:var(--text-3); font-size:11px; }
397
+ .mobile-tabbar { display:flex; height:66px; margin-top:auto; align-items:center; justify-content:space-around; border-top:1px solid var(--border); background:var(--surface); padding-bottom:env(safe-area-inset-bottom); }
398
+ .mobile-tabbar button { display:grid; width:50px; height:48px; place-items:center; border-radius:16px; background:transparent; color:var(--text-3); }
399
+ .mobile-tabbar button.active { background:var(--accent-soft); color:var(--accent); }
400
+ .approval-card { align-self:center; margin:auto 14px; overflow:hidden; border:1px solid var(--border); border-radius:20px; background:var(--surface); }
401
+ .approval-hero { display:flex; min-height:64px; align-items:center; gap:11px; padding:12px 14px; background:var(--surface-2); }
402
+ .approval-hero .avatar { width:38px; height:38px; }
403
+ .approval-hero strong { display:block; font-size:14px; }
404
+ .approval-hero span { color:var(--text-3); font-size:11px; }
405
+ .approval-command { margin:14px; padding:11px; border-radius:12px; background:#17181b; color:#dde1e6; font:11px/1.6 var(--font-mono); }
406
+ .approval-scope { display:grid; gap:8px; padding:0 14px 14px; }
407
+ .scope-row { display:flex; align-items:center; gap:8px; color:var(--text-2); font-size:12px; }
408
+ .approval-actions { display:grid; grid-template-columns:1fr 1fr; gap:8px; padding:12px 14px 14px; border-top:1px solid var(--border); }
409
+ .approval-actions .btn { min-height:44px; border-radius:14px; }
410
+ .approval-result { margin:0 14px 14px; padding:11px; border-radius:12px; text-align:center; font-size:12px; font-weight:650; }
411
+ .approval-result.allow { background:color-mix(in srgb,var(--success) 14%,transparent); color:var(--success); }
412
+ .approval-result.deny { background:color-mix(in srgb,var(--danger) 14%,transparent); color:var(--danger); }
413
+
414
+ /* 06 Cross-platform workspace */
415
+ .theme-paseo { --bg:#f2f4f2; --surface:#fff; --surface-2:#f4f4f5; --surface-3:#e4e4e7; --text:#1a1a1e; --text-2:#71717a; --text-3:#a1a1aa; --border:#e4e4e7; --accent:#20744a; --accent-soft:#e6f1eb; --accent-fg:#fff; --radius-sm:4px; --radius-md:6px; --radius-lg:8px; --control-h:32px; --sidebar:250px; --right-panel:330px; --ui-size:14px; --meta-size:12px; }
416
+ html.dark .theme-paseo,html.dark body.theme-paseo { --bg:#121214; --surface:#18181b; --surface-2:#202024; --surface-3:#303036; --text:#fafafa; --text-2:#b7b7c0; --text-3:#73737d; --border:#303036; --accent:#6cb17b; --accent-soft:#21382a; --accent-fg:#101512; }
417
+ .paseo-rail { display:flex; width:54px; flex:0 0 54px; flex-direction:column; align-items:center; gap:4px; padding:8px 0; border-right:1px solid var(--border); background:var(--surface); }
418
+ .paseo-rail .tool-btn.active { background:var(--accent-soft); color:var(--accent); }
419
+ .paseo-sidebar { display:flex; flex-direction:column; }
420
+ .workspace-row { margin:1px 7px; padding:8px; border-radius:7px; }
421
+ .workspace-row.active { background:var(--surface); box-shadow:inset 0 0 0 1px var(--border); }
422
+ .workspace-row-head { display:grid; grid-template-columns:8px 1fr auto; align-items:center; gap:8px; font-size:12px; }
423
+ .workspace-row p { margin:4px 0 0 16px; color:var(--text-3); font-size:10px; }
424
+ .paseo-center { position:relative; display:flex; min-width:0; flex:1; flex-direction:column; }
425
+ .workspace-tabs { display:flex; min-height:39px; align-items:end; border-bottom:1px solid var(--border); background:var(--surface-2); }
426
+ .workspace-tab { display:flex; min-width:150px; height:34px; align-items:center; gap:7px; padding:0 10px; border-right:1px solid var(--border); color:var(--text-2); font-size:11px; }
427
+ .workspace-tab.active { background:var(--surface); color:var(--text); }
428
+ .paseo-right { display:flex; width:var(--right-panel); flex:0 0 var(--right-panel); flex-direction:column; border-left:1px solid var(--border); background:var(--surface); }
429
+ .attention-strip { display:flex; min-height:34px; align-items:center; gap:8px; padding:0 12px; border-bottom:1px solid color-mix(in srgb,var(--warning) 25%,var(--border)); background:color-mix(in srgb,var(--warning) 8%,var(--surface)); color:var(--warning); font-size:11px; }
430
+ .file-change { display:flex; min-height:31px; align-items:center; gap:7px; padding:0 10px; border-bottom:1px solid var(--border); font:11px var(--font-mono); }
431
+ .file-change .stat { margin-left:auto; }
432
+ .paseo-mobile-chip { display:none; }
433
+
434
+ /* 07 Local-first content */
435
+ .theme-content { --bg:#f2f0e9; --surface:#fffefb; --surface-2:#f4f1e9; --surface-3:#e8e3d7; --text:#292722; --text-2:#6c675d; --text-3:#9a9387; --border:#e2ddd1; --accent:#a65235; --accent-soft:#f5e7df; --accent-fg:#fff; --radius-sm:4px; --radius-md:6px; --radius-lg:8px; --sidebar:214px; --ui-size:14px; }
436
+ html.dark .theme-content,html.dark body.theme-content { --bg:#171612; --surface:#1e1d19; --surface-2:#27251f; --surface-3:#353128; --text:#f0ede5; --text-2:#b9b3a7; --text-3:#7f796f; --border:#38342c; --accent:#d68362; --accent-soft:#3e2a22; }
437
+ .content-global { display:flex; width:var(--sidebar); flex:0 0 var(--sidebar); flex-direction:column; border-right:1px solid var(--border); background:var(--surface-2); }
438
+ .content-list { display:flex; width:300px; flex:0 0 300px; flex-direction:column; border-right:1px solid var(--border); background:var(--surface); }
439
+ .note-row { padding:11px 12px; border-bottom:1px solid var(--border); }
440
+ .note-row:hover,.note-row.active { background:var(--surface-2); }
441
+ .note-row strong { display:block; overflow:hidden; font-size:13px; text-overflow:ellipsis; white-space:nowrap; }
442
+ .note-row p { display:-webkit-box; margin:5px 0 0; overflow:hidden; color:var(--text-3); font-size:11px; line-height:1.45; -webkit-box-orient:vertical; -webkit-line-clamp:2; }
443
+ .note-row time { display:block; margin-top:7px; color:var(--text-3); font-size:10px; }
444
+ .editor-page { display:flex; min-width:0; flex:1; flex-direction:column; background:var(--surface); }
445
+ .editor-document { width:min(760px,calc(100% - 40px)); margin:0 auto; padding:58px 0 120px; overflow:auto; }
446
+ .editor-document .eyebrow { color:var(--accent); font-size:11px; font-weight:700; text-transform:uppercase; }
447
+ .editor-document h1 { margin:14px 0 10px; font-family:Georgia,"Songti SC",serif; font-size:34px; line-height:1.2; }
448
+ .editor-document .byline { color:var(--text-3); font-size:12px; }
449
+ .editor-document p { margin:22px 0 0; font-family:Georgia,"Songti SC",serif; font-size:17px; line-height:1.78; }
450
+ .editor-document blockquote { margin:28px 0; padding:2px 0 2px 18px; border-left:3px solid var(--accent); color:var(--text-2); font-family:Georgia,"Songti SC",serif; font-size:19px; line-height:1.55; }
451
+ .editor-image { width:100%; height:260px; margin:26px 0 6px; border-radius:8px; object-fit:cover; }
452
+ .sync-state { display:flex; align-items:center; gap:6px; margin-left:auto; color:var(--success); font-size:11px; }
453
+
454
+ /* 08 Media first */
455
+ .theme-media { --bg:#101214; --surface:#181b1e; --surface-2:#202429; --surface-3:#2b3036; --text:#f2f4f6; --text-2:#b0b6bd; --text-3:#747d86; --border:#2b3036; --accent:#62a7ff; --accent-soft:#19344f; --accent-fg:#07111d; --radius-sm:4px; --radius-md:8px; --radius-lg:10px; --sidebar:224px; --ui-size:14px; }
456
+ html:not(.dark) .theme-media,html:not(.dark) body.theme-media { color-scheme:dark; }
457
+ .media-sidebar { display:flex; width:var(--sidebar); flex:0 0 var(--sidebar); flex-direction:column; border-right:1px solid var(--border); background:#111315; }
458
+ .media-main { display:flex; min-width:0; flex:1; flex-direction:column; background:var(--bg); }
459
+ .media-toolbar { display:flex; min-height:52px; align-items:center; gap:8px; padding:0 14px; border-bottom:1px solid var(--border); }
460
+ .media-toolbar h1 { margin:0; font-size:16px; }
461
+ .media-grid { display:grid; grid-template-columns:repeat(4,minmax(150px,1fr)); gap:6px; padding:12px; overflow:auto; }
462
+ .media-day { grid-column:1/-1; display:flex; align-items:center; gap:9px; padding:10px 2px 3px; }
463
+ .media-day strong { font-size:13px; }
464
+ .media-day span { color:var(--text-3); font-size:11px; }
465
+ .photo-tile { position:relative; min-height:170px; overflow:hidden; border-radius:6px; background:var(--surface-2); }
466
+ .photo-tile.tall { grid-row:span 2; min-height:346px; }
467
+ .photo-tile.wide { grid-column:span 2; }
468
+ .photo-tile img { width:100%; height:100%; object-fit:cover; transition:transform 260ms ease,filter 180ms ease; }
469
+ .photo-tile:hover img { transform:scale(1.025); filter:brightness(.88); }
470
+ .photo-meta { position:absolute; right:0; bottom:0; left:0; display:flex; align-items:end; min-height:54px; padding:10px; background:linear-gradient(transparent,rgba(0,0,0,.7)); opacity:0; transition:opacity 160ms ease; }
471
+ .photo-tile:hover .photo-meta { opacity:1; }
472
+ .photo-meta span { color:#fff; font-size:11px; }
473
+ .photo-meta button { margin-left:auto; background:transparent; color:#fff; }
474
+ .upload-card { margin:auto 10px 10px; padding:11px; border:1px solid var(--border); border-radius:8px; background:var(--surface); }
475
+ .upload-head { display:flex; align-items:center; gap:8px; font-size:11px; }
476
+ .upload-progress { height:4px; margin-top:9px; overflow:hidden; border-radius:4px; background:var(--surface-3); }
477
+ .upload-progress i { display:block; width:72%; height:100%; background:var(--accent); }
478
+
479
+ @media (max-width: 1180px) {
480
+ .style-grid { grid-template-columns: repeat(3,minmax(0,1fr)); }
481
+ .soft-right,.web-right,.paseo-right,.ide-review { display:none; }
482
+ .console-content { grid-template-columns:1fr; }
483
+ .analytics-column { display:none; }
484
+ .media-grid { grid-template-columns:repeat(3,minmax(140px,1fr)); }
485
+ }
486
+
487
+ @media (max-width: 900px) {
488
+ .style-grid { grid-template-columns:repeat(2,minmax(0,1fr)); }
489
+ .gallery-summary { grid-template-columns:1fr; }
490
+ .gallery-metrics { display:none; }
491
+ .ide-explorer,.content-global { display:none; }
492
+ .content-list { width:250px; flex-basis:250px; }
493
+ .mobile-stage { grid-template-columns:minmax(300px,420px); }
494
+ .mobile-stage .phone-frame:first-child { display:none; }
495
+ .media-grid { grid-template-columns:repeat(2,minmax(140px,1fr)); }
496
+ }
497
+
498
+ @media (max-width: 760px) {
499
+ .gallery-main { padding:16px 12px; }
500
+ .gallery-topbar { padding:0 12px; }
501
+ .gallery-topbar span { display:none; }
502
+ .gallery-summary h1 { font-size:21px; }
503
+ .style-grid { grid-template-columns:1fr; }
504
+ .style-card { min-height:0; }
505
+ .style-preview { height:176px; }
506
+ .ide-rail,.paseo-rail { display:none; }
507
+ .ide-editor { grid-template-columns:1fr; }
508
+ .editor-pane:last-child { display:none; }
509
+ .ide-terminal { height:160px; flex-basis:160px; }
510
+ .console-sidebar { position:absolute; z-index:30; top:0; bottom:0; transform:translateX(-102%); }
511
+ .console-overview { grid-template-columns:repeat(2,1fr); }
512
+ .console-stat { min-height:72px; padding:11px; }
513
+ .console-stat b { font-size:19px; }
514
+ .soft-shell { padding:0; }
515
+ .soft-sidebar { position:absolute; z-index:30; inset:0 auto 0 0; transform:translateX(-102%); }
516
+ .soft-main { border:0; border-radius:0; }
517
+ .web-bottom-nav { display:flex; }
518
+ .theme-web .composer-wrap { bottom:58px; }
519
+ .mobile-stage { display:block; padding:0; }
520
+ .phone-frame { max-width:none; height:100%; min-height:0; border:0; border-radius:0; box-shadow:none; }
521
+ .paseo-sidebar { position:absolute; z-index:30; inset:0 auto 0 0; transform:translateX(-102%); }
522
+ .paseo-mobile-chip { display:inline-flex; }
523
+ .content-list { position:absolute; z-index:30; inset:0 auto 0 0; transform:translateX(-102%); }
524
+ .editor-document { width:calc(100% - 30px); padding-top:34px; }
525
+ .editor-document h1 { font-size:27px; }
526
+ .editor-document p { font-size:16px; }
527
+ .editor-image { height:210px; }
528
+ .media-sidebar { position:absolute; z-index:30; inset:0 auto 0 0; transform:translateX(-102%); }
529
+ .media-grid { grid-template-columns:repeat(2,minmax(110px,1fr)); padding:7px; }
530
+ .photo-tile { min-height:130px; }
531
+ .photo-tile.tall { min-height:266px; }
532
+ .photo-meta { opacity:1; }
533
+ }
@@ -0,0 +1,56 @@
1
+ const { test, expect } = require("@playwright/test");
2
+ const path = require("node:path");
3
+ const { pathToFileURL } = require("node:url");
4
+
5
+ const galleryRoot = path.resolve(__dirname, "..");
6
+ const pages = [
7
+ "index.html",
8
+ "01-dense-ide.html",
9
+ "02-monochrome-console.html",
10
+ "03-soft-personal-ai.html",
11
+ "04-responsive-web.html",
12
+ "05-mobile-supervisor.html",
13
+ "06-cross-platform-workspace.html",
14
+ "07-local-first-content.html",
15
+ "08-media-first.html",
16
+ ];
17
+
18
+ for (const filename of pages) {
19
+ test(`${filename} renders without viewport overflow`, async ({ page }) => {
20
+ await page.setViewportSize({ width: 390, height: 844 });
21
+ await page.goto(pathToFileURL(path.join(galleryRoot, filename)).href);
22
+
23
+ await expect(page.locator("body")).toBeVisible();
24
+ expect(await page.locator("svg").count()).toBeGreaterThan(0);
25
+
26
+ const layout = await page.evaluate(() => ({
27
+ viewport: window.innerWidth,
28
+ documentWidth: document.documentElement.scrollWidth,
29
+ bodyWidth: document.body.scrollWidth,
30
+ }));
31
+ expect(layout.documentWidth).toBeLessThanOrEqual(layout.viewport + 1);
32
+ expect(layout.bodyWidth).toBeLessThanOrEqual(layout.viewport + 1);
33
+
34
+ const brokenImages = await page.locator("img").evaluateAll((images) =>
35
+ images.filter((image) => !image.complete || image.naturalWidth === 0).map((image) => image.src),
36
+ );
37
+ expect(brokenImages).toEqual([]);
38
+ });
39
+ }
40
+
41
+ test("theme and token controls respond", async ({ page }) => {
42
+ await page.goto(pathToFileURL(path.join(galleryRoot, "03-soft-personal-ai.html")).href);
43
+ await page.locator("[data-theme-toggle]").click();
44
+ await expect(page.locator("html")).toHaveClass(/dark/);
45
+ await page.locator("[data-token-toggle]").click();
46
+ await expect(page.locator(".token-drawer")).toHaveClass(/open/);
47
+ await page.locator("[data-token-close]").click();
48
+ await expect(page.locator(".token-drawer")).not.toHaveClass(/open/);
49
+ });
50
+
51
+ test("mobile approval returns a visible decision", async ({ page }) => {
52
+ await page.setViewportSize({ width: 390, height: 844 });
53
+ await page.goto(pathToFileURL(path.join(galleryRoot, "05-mobile-supervisor.html")).href);
54
+ await page.locator('[data-approval="allow"]').click();
55
+ await expect(page.locator(".approval-result.allow")).toContainText("已允许本次操作");
56
+ });
@@ -0,0 +1,53 @@
1
+ # 响应式与平台职责
2
+
3
+ 响应式设计改变任务流,不只是 CSS 宽度。桌面适合并行、比较、快捷键和可调面板;Web 适合易部署与跨设备访问;移动端适合通知、监督、拍摄、语音、审批和即时 follow-up。跨端一致性落在对象、状态和核心流程,不要求像素一致。
4
+
5
+ ## 桌面到窄屏的任务重排
6
+
7
+ | 桌面结构 | 窄屏替代 |
8
+ |---|---|
9
+ | 固定侧栏 | off-canvas drawer 或单层导航 |
10
+ | 右侧检查器 | bottom sheet 或 full-screen detail |
11
+ | 三栏主从 | 列表页 -> 详情页,并提供明确返回路径 |
12
+ | 宽表格 | 关键列 + 横向滚动 + 行详情 |
13
+ | 常驻工具栏 | 主要动作 + overflow menu |
14
+ | hover 工具 | 可点击菜单或显式按钮 |
15
+ | 多 pane 代码工作区 | tabs、全屏工具 route 或按任务切换的单 pane |
16
+
17
+ 每个 breakpoint 写出主要任务如何开始、继续、返回和恢复,不以“元素能换行”为完成。移动端触控目标建议至少 44px;桌面紧凑视觉控件可以更小,但命中区可保持更大。
18
+
19
+ ## 平台职责
20
+
21
+ | 平台 | 优先任务 | 避免 |
22
+ |---|---|---|
23
+ | 桌面 | 多对象比较、精细编辑、键盘命令、diff/terminal/preview 并行 | 把每个区域做成浮卡,或用大标题浪费工作区 |
24
+ | Web/PWA | 跨设备访问、分享 URL、自托管、响应式工作区 | 将桌面三栏直接压窄;依赖 hover 才能完成关键动作 |
25
+ | 移动 | 状态摘要、通知、权限审批、阅读 diff 摘要、短 follow-up、拍摄/上传 | 完整复刻 IDE、密集小控件、无返回路径的多栏 |
26
+ | 原生壳 | 文件、通知、相机、系统凭据、后台任务等平台能力 | 为像素一致牺牲系统语义和原生可达性 |
27
+
28
+ ## 四种跨端实现模型
29
+
30
+ 1. 同一 Web UI + Electron/Tauri/native WebView,例如 Actual Budget。共享率高,但 Web 语义、shell 能力和窄屏任务流要分别治理。
31
+ 2. React Web 与 React Native 双壳,共享领域层,例如 Notesnook、Standard Notes、Joplin。共享对象和状态,不强求视图代码一致。
32
+ 3. Flutter/React Native 单一 UI 覆盖多端,例如 LocalSend、RustDesk。渲染一致,但 Web 语义和平台细节仍需单独验证。
33
+ 4. 共享协议、SDK 和设计语言,SwiftUI/Compose/React 分别实现,例如 Element X、Bitwarden。平台体验最好,设计系统和行为一致性需要明确合同。
34
+
35
+ Immich 展示另一种常见取舍:共享 API 与领域词汇,Web 使用 SvelteKit、移动使用 Flutter,让媒体浏览和拍摄/上传分别贴近平台。
36
+
37
+ ## Agent 工作区专项
38
+
39
+ - 桌面通常收敛为“会话侧栏 + 对话/工具时间线 + Plan/Files/Diff/Preview”,通过可调 pane 或分屏支持验证。
40
+ - Web 窄屏将 sidebar 变 drawer,将工具区变 full-screen route 或 bottom sheet,将 composer 固定在 safe area 上方。
41
+ - 移动端第一任务是状态、审批、摘要/diff 和 follow-up,不是完整开发环境。
42
+ - 会话状态、工具执行、权限边界、代码变更和跨设备控制是核心对象;聊天气泡只是呈现层。
43
+
44
+ 对应样板分别是 responsive Web、mobile supervisor 和 cross-platform workspace,见 `<Path>{roots.workflows}/specdev/P-prototype/design-library/style-index.md</Path>`。
45
+
46
+ ## 可访问与设备检查
47
+
48
+ - 全部功能可用键盘到达,Tab 顺序与视觉顺序一致,`:focus-visible` 清晰可见;
49
+ - dialog/menu/listbox/combobox 使用正确语义和焦点管理;
50
+ - 图标按钮有可访问名称,tooltip 不是唯一说明;
51
+ - 测试 200% 缩放、reduced motion、屏幕阅读器、长文本、CJK 与 RTL;
52
+ - 使用 safe-area inset,移动 composer、审批动作和底部导航不被系统 UI 遮挡;
53
+ - 图片有有效替代文本;媒体本身可检查,不用暗化、模糊或装饰性裁切掩盖内容。