@plannotator/pi-extension 0.19.13 → 0.19.14

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.
@@ -0,0 +1,560 @@
1
+ # Design System Reference
2
+
3
+ Plan documents use Plannotator's semantic theme tokens. This makes them theme-aware: standalone files render with bundled defaults; embedded in the Plannotator UI, they inherit whatever theme is active (30+ themes, light and dark variants).
4
+
5
+ ## Standalone defaults
6
+
7
+ Include this `:root` block so the plan works when opened directly in a browser. These are the Plannotator light theme values — they get overridden when embedded.
8
+
9
+ ```css
10
+ :root {
11
+ --background: oklch(0.97 0.005 260);
12
+ --foreground: oklch(0.18 0.02 260);
13
+ --card: oklch(1 0 0);
14
+ --card-foreground: oklch(0.18 0.02 260);
15
+ --primary: oklch(0.50 0.25 280);
16
+ --primary-foreground: oklch(1 0 0);
17
+ --secondary: oklch(0.50 0.18 180);
18
+ --secondary-foreground: oklch(1 0 0);
19
+ --muted: oklch(0.92 0.01 260);
20
+ --muted-foreground: oklch(0.40 0.02 260);
21
+ --accent: oklch(0.60 0.22 50);
22
+ --accent-foreground: oklch(0.18 0.02 260);
23
+ --destructive: oklch(0.50 0.25 25);
24
+ --destructive-foreground: oklch(1 0 0);
25
+ --success: oklch(0.45 0.20 150);
26
+ --success-foreground: oklch(1 0 0);
27
+ --warning: oklch(0.55 0.18 85);
28
+ --warning-foreground: oklch(0.18 0.02 260);
29
+ --border: oklch(0.88 0.01 260);
30
+ --input: oklch(0.92 0.01 260);
31
+ --ring: oklch(0.50 0.25 280);
32
+ --code-bg: oklch(0.92 0.01 260);
33
+
34
+ --font-sans: 'Inter', system-ui, -apple-system, sans-serif;
35
+ --font-mono: 'JetBrains Mono', 'Fira Code', ui-monospace, monospace;
36
+ --font-display: ui-serif, Georgia, 'Times New Roman', serif;
37
+ --radius: 0.625rem;
38
+ }
39
+ ```
40
+
41
+ `--font-display` is plan-specific — used for headings and titles to create visual contrast with the body. It's not part of the core Plannotator theme, so it won't be overridden when embedded (which is the desired behavior).
42
+
43
+ ## Token usage map
44
+
45
+ | Role | Token | SVG equivalent |
46
+ |------|-------|----------------|
47
+ | Page background | `--background` | — |
48
+ | Primary text | `--foreground` | `fill` on text |
49
+ | Card / panel background | `--card` | `fill` on rects |
50
+ | Subdued text, labels, captions | `--muted-foreground` | `fill` on labels |
51
+ | Soft backgrounds, secondary fills | `--muted` | `fill` on secondary rects |
52
+ | Primary accent (CTA, attention, keywords) | `--primary` | `stroke` / `fill` on highlighted elements |
53
+ | Warm accent | `--accent` | — |
54
+ | Positive / success | `--success` | `stroke` / `fill` on success paths |
55
+ | Caution | `--warning` | `fill` on warning badges |
56
+ | Error / destructive | `--destructive` | `stroke` / `fill` on error paths |
57
+ | Borders, dividers | `--border` | `stroke` on box outlines |
58
+ | Arrow strokes, diagram lines | `--muted-foreground` | `stroke` on connectors |
59
+ | Code block background | `--code-bg` | — |
60
+ | Body font | `--font-sans` | `font-family` on SVG body text |
61
+ | Code / labels font | `--font-mono` | `font-family` on SVG labels |
62
+ | Display / heading font | `--font-display` | `font-family` on SVG titles |
63
+
64
+ ## Base styles
65
+
66
+ ```css
67
+ *, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
68
+
69
+ body {
70
+ font-family: var(--font-sans);
71
+ background: var(--background);
72
+ color: var(--foreground);
73
+ line-height: 1.65;
74
+ font-size: 15px;
75
+ -webkit-font-smoothing: antialiased;
76
+ }
77
+
78
+ .container {
79
+ max-width: 1080px;
80
+ margin: 0 auto;
81
+ padding: 64px 24px;
82
+ }
83
+ ```
84
+
85
+ ## Typography
86
+
87
+ **Headings** — `var(--font-display)`, weight 500, `var(--foreground)`.
88
+ - H1: `2rem` page title
89
+ - H2: `1.4rem` section headers
90
+ - H3: `1.15rem` subsection headers
91
+
92
+ **Body** — `var(--font-sans)`, weight 400, `0.95rem`, line-height `1.65`. Max paragraph width `65ch`.
93
+
94
+ **Labels & metadata** — `var(--font-mono)`, `0.7–0.8rem`, weight 500, uppercase, letter-spacing `0.06em`, `var(--muted-foreground)`.
95
+
96
+ **Code** — `var(--font-mono)`, `0.85rem`, line-height `1.55`.
97
+
98
+ ## Component patterns
99
+
100
+ ### Page header
101
+
102
+ ```html
103
+ <header>
104
+ <span class="eyebrow">Implementation plan · Project name</span>
105
+ <h1>Plan Title Goes Here</h1>
106
+ <div class="prompt-box">
107
+ <span class="prompt-label">Brief</span>
108
+ <p>The original task or problem statement that motivated this plan.</p>
109
+ </div>
110
+ </header>
111
+ ```
112
+
113
+ ```css
114
+ .eyebrow {
115
+ font-family: var(--font-mono);
116
+ font-size: 0.72rem;
117
+ font-weight: 500;
118
+ text-transform: uppercase;
119
+ letter-spacing: 0.06em;
120
+ color: var(--muted-foreground);
121
+ }
122
+
123
+ header h1 {
124
+ font-family: var(--font-display);
125
+ font-size: 2rem;
126
+ font-weight: 500;
127
+ margin: 8px 0 24px;
128
+ line-height: 1.2;
129
+ }
130
+
131
+ .prompt-box {
132
+ background: var(--muted);
133
+ border: 1.5px solid var(--border);
134
+ border-radius: var(--radius);
135
+ padding: 16px 24px;
136
+ }
137
+
138
+ .prompt-label {
139
+ font-family: var(--font-mono);
140
+ font-size: 0.7rem;
141
+ font-weight: 600;
142
+ text-transform: uppercase;
143
+ letter-spacing: 0.06em;
144
+ color: var(--muted-foreground);
145
+ display: block;
146
+ margin-bottom: 4px;
147
+ }
148
+
149
+ .prompt-box p {
150
+ font-size: 0.92rem;
151
+ color: var(--muted-foreground);
152
+ line-height: 1.55;
153
+ }
154
+ ```
155
+
156
+ ### Summary strip (stat cards)
157
+
158
+ ```html
159
+ <div class="summary-strip">
160
+ <div class="stat-card">
161
+ <span class="stat-value">4</span>
162
+ <span class="stat-label">Components</span>
163
+ </div>
164
+ <!-- more cards -->
165
+ </div>
166
+ ```
167
+
168
+ ```css
169
+ .summary-strip {
170
+ display: grid;
171
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
172
+ gap: 16px;
173
+ margin: 32px 0;
174
+ }
175
+
176
+ .stat-card {
177
+ border: 1.5px solid var(--border);
178
+ border-radius: var(--radius);
179
+ padding: 16px 24px;
180
+ text-align: center;
181
+ background: var(--card);
182
+ }
183
+
184
+ .stat-value {
185
+ font-family: var(--font-display);
186
+ font-size: 1.8rem;
187
+ font-weight: 500;
188
+ display: block;
189
+ color: var(--foreground);
190
+ }
191
+
192
+ .stat-label {
193
+ font-family: var(--font-mono);
194
+ font-size: 0.7rem;
195
+ font-weight: 500;
196
+ text-transform: uppercase;
197
+ letter-spacing: 0.06em;
198
+ color: var(--muted-foreground);
199
+ margin-top: 4px;
200
+ display: block;
201
+ }
202
+ ```
203
+
204
+ ### Section header
205
+
206
+ ```html
207
+ <section>
208
+ <div class="section-header">
209
+ <span class="section-number">01</span>
210
+ <h2>Solution Overview</h2>
211
+ </div>
212
+ <!-- content -->
213
+ </section>
214
+ ```
215
+
216
+ ```css
217
+ section { margin-top: 64px; }
218
+
219
+ .section-header {
220
+ display: flex;
221
+ align-items: baseline;
222
+ gap: 16px;
223
+ margin-bottom: 24px;
224
+ padding-bottom: 8px;
225
+ border-bottom: 1.5px solid var(--border);
226
+ }
227
+
228
+ .section-number {
229
+ font-family: var(--font-mono);
230
+ font-size: 0.75rem;
231
+ font-weight: 600;
232
+ color: var(--primary);
233
+ }
234
+
235
+ .section-header h2 {
236
+ font-family: var(--font-display);
237
+ font-size: 1.4rem;
238
+ font-weight: 500;
239
+ }
240
+ ```
241
+
242
+ ### Code block (dark theme)
243
+
244
+ ```html
245
+ <div class="code-panel">
246
+ <span class="code-label">src/api/handler.ts</span>
247
+ <pre><code><span class="kw">interface</span> <span class="fn">PlanRequest</span> {
248
+ <span class="fn">title</span>: <span class="kw">string</span>;
249
+ <span class="fn">sections</span>: <span class="fn">Section</span>[];
250
+ }</code></pre>
251
+ </div>
252
+ ```
253
+
254
+ ```css
255
+ .code-panel {
256
+ background: var(--code-bg);
257
+ border-radius: var(--radius);
258
+ padding: 24px;
259
+ overflow-x: auto;
260
+ margin: 16px 0;
261
+ border: 1.5px solid var(--border);
262
+ }
263
+
264
+ .code-label {
265
+ font-family: var(--font-mono);
266
+ font-size: 0.7rem;
267
+ color: var(--muted-foreground);
268
+ display: block;
269
+ margin-bottom: 8px;
270
+ }
271
+
272
+ .code-panel pre {
273
+ margin: 0;
274
+ font-family: var(--font-mono);
275
+ font-size: 0.85rem;
276
+ line-height: 1.55;
277
+ color: var(--foreground);
278
+ }
279
+
280
+ /* Syntax tokens — these use semantic roles, not fixed colors */
281
+ .code-panel .kw { color: var(--primary); } /* keywords */
282
+ .code-panel .fn { color: var(--accent); } /* identifiers, types */
283
+ .code-panel .str { color: var(--success); } /* strings */
284
+ .code-panel .cm { color: var(--muted-foreground); font-style: italic; } /* comments */
285
+ .code-panel .num { color: var(--warning); } /* numbers */
286
+ ```
287
+
288
+ ### Risk table
289
+
290
+ ```html
291
+ <div class="risk-grid">
292
+ <div class="risk-row">
293
+ <div class="risk-name">Database migration on large table</div>
294
+ <div><span class="badge high">HIGH</span></div>
295
+ <div class="risk-mitigation">Run during off-peak with online DDL</div>
296
+ </div>
297
+ <!-- more rows -->
298
+ </div>
299
+ ```
300
+
301
+ ```css
302
+ .risk-grid {
303
+ border: 1.5px solid var(--border);
304
+ border-radius: var(--radius);
305
+ overflow: hidden;
306
+ }
307
+
308
+ .risk-row {
309
+ display: grid;
310
+ grid-template-columns: 1fr auto 1.5fr;
311
+ gap: 24px;
312
+ padding: 16px 24px;
313
+ align-items: center;
314
+ border-bottom: 1px solid var(--border);
315
+ }
316
+
317
+ .risk-row:last-child { border-bottom: none; }
318
+ .risk-name { font-weight: 500; }
319
+ .risk-mitigation { font-size: 0.9rem; color: var(--muted-foreground); }
320
+
321
+ .badge {
322
+ font-family: var(--font-mono);
323
+ font-size: 0.68rem;
324
+ font-weight: 600;
325
+ padding: 2px 8px;
326
+ border-radius: calc(var(--radius) - 4px);
327
+ text-transform: uppercase;
328
+ letter-spacing: 0.04em;
329
+ }
330
+
331
+ .badge.high {
332
+ background: color-mix(in oklab, var(--destructive) 15%, transparent);
333
+ color: var(--destructive);
334
+ }
335
+ .badge.med {
336
+ background: color-mix(in oklab, var(--warning) 15%, transparent);
337
+ color: var(--warning);
338
+ }
339
+ .badge.low {
340
+ background: color-mix(in oklab, var(--success) 15%, transparent);
341
+ color: var(--success);
342
+ }
343
+ ```
344
+
345
+ ### Callout / open question
346
+
347
+ ```html
348
+ <div class="callout">
349
+ <h3>Should we use WebSockets or SSE?</h3>
350
+ <p>SSE is simpler but unidirectional. WebSockets add infrastructure complexity.</p>
351
+ <span class="decide-with">Decide with: infrastructure team</span>
352
+ </div>
353
+ ```
354
+
355
+ ```css
356
+ .callout {
357
+ border-left: 3px solid var(--primary);
358
+ padding: 16px 24px;
359
+ margin: 16px 0;
360
+ background: var(--card);
361
+ border-radius: 0 var(--radius) var(--radius) 0;
362
+ }
363
+
364
+ .callout h3 {
365
+ font-family: var(--font-display);
366
+ font-size: 1.05rem;
367
+ font-weight: 500;
368
+ margin-bottom: 4px;
369
+ }
370
+
371
+ .callout p {
372
+ font-size: 0.9rem;
373
+ color: var(--muted-foreground);
374
+ line-height: 1.55;
375
+ }
376
+
377
+ .decide-with {
378
+ font-family: var(--font-mono);
379
+ font-size: 0.72rem;
380
+ color: var(--primary);
381
+ font-weight: 500;
382
+ display: block;
383
+ margin-top: 8px;
384
+ }
385
+ ```
386
+
387
+ ### Tag chips
388
+
389
+ ```html
390
+ <div class="tags">
391
+ <span class="tag">packages/server</span>
392
+ <span class="tag highlight">new endpoint</span>
393
+ </div>
394
+ ```
395
+
396
+ ```css
397
+ .tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }
398
+
399
+ .tag {
400
+ font-family: var(--font-mono);
401
+ font-size: 0.68rem;
402
+ padding: 2px 8px;
403
+ border-radius: calc(var(--radius) - 4px);
404
+ background: var(--muted);
405
+ color: var(--muted-foreground);
406
+ }
407
+
408
+ .tag.highlight {
409
+ background: color-mix(in oklab, var(--primary) 12%, transparent);
410
+ color: var(--primary);
411
+ }
412
+ ```
413
+
414
+ ### Diagram panel
415
+
416
+ Wraps SVG diagrams in a bordered container:
417
+
418
+ ```html
419
+ <div class="diagram-panel">
420
+ <svg viewBox="0 0 720 280" xmlns="http://www.w3.org/2000/svg" style="width:100%">
421
+ <!-- diagram content -->
422
+ </svg>
423
+ <span class="diagram-caption">Request flow through the API gateway</span>
424
+ </div>
425
+ ```
426
+
427
+ ```css
428
+ .diagram-panel {
429
+ border: 1.5px solid var(--border);
430
+ border-radius: var(--radius);
431
+ padding: 24px;
432
+ margin: 24px 0;
433
+ background: var(--card);
434
+ }
435
+
436
+ .diagram-caption {
437
+ font-family: var(--font-mono);
438
+ font-size: 0.72rem;
439
+ color: var(--muted-foreground);
440
+ display: block;
441
+ margin-top: 8px;
442
+ text-align: center;
443
+ }
444
+ ```
445
+
446
+ ### Two-column grid
447
+
448
+ ```css
449
+ .two-col {
450
+ display: grid;
451
+ grid-template-columns: 1fr 1fr;
452
+ gap: 24px;
453
+ }
454
+
455
+ @media (max-width: 720px) {
456
+ .two-col { grid-template-columns: 1fr; }
457
+ }
458
+ ```
459
+
460
+ ### Collapsible details
461
+
462
+ ```html
463
+ <details>
464
+ <summary>Implementation details</summary>
465
+ <div class="details-body"><!-- content --></div>
466
+ </details>
467
+ ```
468
+
469
+ ```css
470
+ details {
471
+ border: 1.5px solid var(--border);
472
+ border-radius: var(--radius);
473
+ margin: 16px 0;
474
+ }
475
+
476
+ summary {
477
+ font-family: var(--font-sans);
478
+ font-weight: 500;
479
+ padding: 16px 24px;
480
+ cursor: pointer;
481
+ list-style: none;
482
+ }
483
+
484
+ summary::before {
485
+ content: '▸';
486
+ display: inline-block;
487
+ margin-right: 8px;
488
+ transition: transform 0.2s;
489
+ }
490
+
491
+ details[open] summary::before { transform: rotate(90deg); }
492
+
493
+ .details-body { padding: 0 24px 24px; }
494
+ ```
495
+
496
+ ### Milestone timeline
497
+
498
+ Vertical timeline showing phases without time estimates.
499
+
500
+ ```html
501
+ <div class="milestones">
502
+ <div class="milestone">
503
+ <div class="when">Phase 1</div>
504
+ <div class="dot-col"><span class="dot done"></span><span class="line"></span></div>
505
+ <div class="body">
506
+ <h3>Foundation</h3>
507
+ <p>Set up core infrastructure and initial integrations.</p>
508
+ <div class="tags"><span class="tag">packages/server</span></div>
509
+ </div>
510
+ </div>
511
+ </div>
512
+ ```
513
+
514
+ ```css
515
+ .milestones { display: flex; flex-direction: column; gap: 0; }
516
+
517
+ .milestone {
518
+ display: grid;
519
+ grid-template-columns: 120px 28px 1fr;
520
+ gap: 0 18px;
521
+ }
522
+
523
+ .milestone .when {
524
+ text-align: right;
525
+ font-family: var(--font-mono);
526
+ font-size: 0.75rem;
527
+ color: var(--muted-foreground);
528
+ padding-top: 4px;
529
+ }
530
+
531
+ .milestone .dot-col { display: flex; flex-direction: column; align-items: center; }
532
+
533
+ .milestone .dot {
534
+ width: 14px; height: 14px; border-radius: 50%;
535
+ background: var(--card);
536
+ border: 3px solid var(--primary);
537
+ flex-shrink: 0;
538
+ }
539
+
540
+ .milestone .dot.done { background: var(--success); border-color: var(--success); }
541
+
542
+ .milestone .line { width: 2px; flex: 1; background: var(--border); margin: 4px 0; }
543
+ .milestone:last-child .line { display: none; }
544
+
545
+ .milestone .body { padding-bottom: 36px; }
546
+
547
+ .milestone .body h3 {
548
+ font-family: var(--font-display);
549
+ font-size: 1.15rem;
550
+ font-weight: 500;
551
+ margin-bottom: 4px;
552
+ }
553
+
554
+ .milestone .body p {
555
+ font-size: 0.88rem;
556
+ color: var(--muted-foreground);
557
+ max-width: 620px;
558
+ margin-bottom: 10px;
559
+ }
560
+ ```