@ponchia/ui 0.11.0 → 0.13.0

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 (76) hide show
  1. package/CHANGELOG.md +98 -0
  2. package/MIGRATIONS.json +24 -0
  3. package/README.md +5 -5
  4. package/behaviors/forms.d.ts +1 -1
  5. package/behaviors/internal.d.ts +1 -1
  6. package/classes/classes.json +3 -1
  7. package/classes/index.d.ts +2 -0
  8. package/classes/index.js +3 -1
  9. package/classes/vscode.css-custom-data.json +64 -0
  10. package/css/base.css +2 -2
  11. package/css/blocknote.css +61 -0
  12. package/css/clamp.css +2 -2
  13. package/css/content.css +126 -0
  14. package/css/dataviz.css +117 -64
  15. package/css/disclosure.css +10 -10
  16. package/css/forms.css +8 -8
  17. package/css/legend.css +1 -2
  18. package/css/primitives.css +5 -6
  19. package/css/row.css +2 -2
  20. package/css/term.css +2 -2
  21. package/css/textref.css +2 -2
  22. package/css/toc.css +2 -2
  23. package/css/tokens.css +43 -0
  24. package/css/workbench.css +2 -2
  25. package/dist/bronto.css +1 -1
  26. package/dist/css/analytical.css +1 -1
  27. package/dist/css/base.css +1 -1
  28. package/dist/css/blocknote.css +1 -0
  29. package/dist/css/clamp.css +1 -1
  30. package/dist/css/content.css +1 -1
  31. package/dist/css/dataviz.css +1 -1
  32. package/dist/css/disclosure.css +1 -1
  33. package/dist/css/forms.css +1 -1
  34. package/dist/css/legend.css +1 -1
  35. package/dist/css/report-kit.css +1 -1
  36. package/dist/css/row.css +1 -1
  37. package/dist/css/term.css +1 -1
  38. package/dist/css/textref.css +1 -1
  39. package/dist/css/toc.css +1 -1
  40. package/dist/css/tokens.css +1 -1
  41. package/dist/css/workbench.css +1 -1
  42. package/docs/adr/0001-color-system.md +29 -0
  43. package/docs/architecture.md +1 -1
  44. package/docs/compositions.md +2 -2
  45. package/docs/contrast.md +24 -24
  46. package/docs/frontier-primitives.md +5 -0
  47. package/docs/interop/blocknote.md +60 -0
  48. package/docs/mermaid.md +1 -1
  49. package/docs/migrations/0.11-to-0.12.md +47 -0
  50. package/docs/package-contract.md +12 -2
  51. package/docs/reference.md +18 -1
  52. package/docs/renderer.md +100 -0
  53. package/docs/reporting.md +9 -9
  54. package/docs/stability.md +4 -2
  55. package/docs/theming.md +77 -20
  56. package/docs/usage.md +12 -8
  57. package/docs/vega.md +24 -23
  58. package/llms.txt +8 -4
  59. package/package.json +24 -12
  60. package/renderer/index.d.ts +203 -0
  61. package/renderer/index.d.ts.map +1 -0
  62. package/renderer/index.js +650 -0
  63. package/tokens/charts.d.ts +16 -10
  64. package/tokens/charts.js +65 -49
  65. package/tokens/charts.json +77 -29
  66. package/tokens/figma.variables.json +240 -0
  67. package/tokens/index.d.ts +2 -2
  68. package/tokens/index.js +30 -2
  69. package/tokens/index.json +32 -0
  70. package/tokens/mermaid.js +56 -56
  71. package/tokens/mermaid.json +56 -56
  72. package/tokens/resolved.json +17 -1
  73. package/tokens/tokens.dtcg.json +190 -0
  74. package/tokens/vega.d.ts +3 -3
  75. package/tokens/vega.js +111 -72
  76. package/tokens/vega.json +198 -126
package/css/dataviz.css CHANGED
@@ -1,27 +1,39 @@
1
1
  /* @ponchia/ui — GENERATED from tokens/charts.js by scripts/gen-charts.mjs.
2
2
  * Do not edit by hand; run `npm run charts:build`. Drift-checked in CI.
3
3
  *
4
- * Tier-4 data-viz palette (ADR-0001). OPT-IN: import `@ponchia/ui/css/dataviz.css`
5
- * on demand; never in the default bundle, never UI chrome. --chart-1 is the live
6
- * accent (series 1 = brand). Pair colour N with pattern N (a 2nd, non-colour
7
- * channel): background: var(--chart-3); background-image: var(--chart-pattern-3);
4
+ * Tier-4 categorical + data-viz palette (ADR-0001). OPT-IN: import
5
+ * `@ponchia/ui/css/dataviz.css` on demand; never in the default bundle, never
6
+ * UI chrome. Eight fixed hues (blue, orange, aqua, yellow, magenta, green,
7
+ * violet, red) in two namespaces:
8
+ * --cat-N / --cat-N-tint / --cat-N-ink categorical identity (a tag, a
9
+ * participant, a user-chosen tint): ink holds 4.5:1 on the panel and tint.
10
+ * --chart-N, --chart-seq-*, --chart-div-* data-viz series and ramps.
11
+ * Pair colour N with pattern N (a 2nd, non-colour channel):
12
+ * background: var(--chart-3); background-image: var(--chart-pattern-3);
8
13
  * background-size: var(--chart-pattern-size); --chart-pattern-ink: <contrast>. */
9
14
 
10
15
  :root {
11
- --chart-1: var(--accent);
12
- --chart-2: #e69f00;
13
- --chart-3: #56b4e9;
14
- --chart-4: #009e73;
15
- --chart-5: #f0e442;
16
- --chart-6: #0072b2;
17
- --chart-7: #cc79a7;
18
- --chart-8: #4d5358;
19
- --chart-seq-1: oklch(94% 0.03 25deg);
20
- --chart-seq-2: oklch(85% 0.07 25deg);
21
- --chart-seq-3: oklch(74% 0.12 25deg);
22
- --chart-seq-4: oklch(62% 0.16 25deg);
23
- --chart-seq-5: oklch(50% 0.16 25deg);
24
- --chart-seq-6: oklch(38% 0.13 25deg);
16
+ --cat-1: #2a78d6;
17
+ --cat-2: #eb6834;
18
+ --cat-3: #1baf7a;
19
+ --cat-4: #eda100;
20
+ --cat-5: #e87ba4;
21
+ --cat-6: #008300;
22
+ --cat-7: #4a3aa7;
23
+ --cat-8: #e34948;
24
+ --cat-1-ink: #1467c3;
25
+ --cat-2-ink: #bf3f00;
26
+ --cat-3-ink: #007d4c;
27
+ --cat-4-ink: #a45d00;
28
+ --cat-5-ink: #b04972;
29
+ --cat-6-ink: #007800;
30
+ --cat-7-ink: #4a3aa7;
31
+ --cat-8-ink: #c62b30;
32
+ --chart-seq-1: #80b0e8;
33
+ --chart-seq-2: #5598e7;
34
+ --chart-seq-3: #2a78d6;
35
+ --chart-seq-4: #1c5cab;
36
+ --chart-seq-5: #104281;
25
37
  --chart-div-1: oklch(45% 0.14 255deg);
26
38
  --chart-div-2: oklch(62% 0.1 250deg);
27
39
  --chart-div-3: oklch(82% 0.05 245deg);
@@ -30,11 +42,31 @@
30
42
  --chart-div-6: oklch(66% 0.13 55deg);
31
43
  --chart-div-7: oklch(56% 0.15 45deg);
32
44
 
45
+ /* Theme-independent: each series and tint follows its slot, and the tint
46
+ follows whichever --panel the page, a skin or the OLED preset set. */
47
+ --cat-1-tint: color-mix(in oklch, var(--cat-1) 16%, var(--panel));
48
+ --cat-2-tint: color-mix(in oklch, var(--cat-2) 16%, var(--panel));
49
+ --cat-3-tint: color-mix(in oklch, var(--cat-3) 16%, var(--panel));
50
+ --cat-4-tint: color-mix(in oklch, var(--cat-4) 16%, var(--panel));
51
+ --cat-5-tint: color-mix(in oklch, var(--cat-5) 16%, var(--panel));
52
+ --cat-6-tint: color-mix(in oklch, var(--cat-6) 16%, var(--panel));
53
+ --cat-7-tint: color-mix(in oklch, var(--cat-7) 16%, var(--panel));
54
+ --cat-8-tint: color-mix(in oklch, var(--cat-8) 16%, var(--panel));
55
+ --chart-1: var(--cat-1);
56
+ --chart-2: var(--cat-2);
57
+ --chart-3: var(--cat-3);
58
+ --chart-4: var(--cat-4);
59
+ --chart-5: var(--cat-5);
60
+ --chart-6: var(--cat-6);
61
+ --chart-7: var(--cat-7);
62
+ --chart-8: var(--cat-8);
63
+
33
64
  /* Dot-matrix pattern fills — pair with the matching colour (WCAG 1.4.1).
34
- Series 1 (the accent) is intentionally `none`: absence-of-pattern IS its
35
- redundant channel. The colour palette is CVD-safe on its own (gated by
36
- check:charts), so a colour+pattern chart stays distinguishable; a
37
- pattern-ONLY chart must still give series 1 a fill or a labelled legend. */
65
+ Series 1 is intentionally `none`: absence-of-pattern IS its redundant
66
+ channel. Adjacent series are separated under simulated colour-vision
67
+ deficiency (gated by check:charts), so a colour+pattern chart stays
68
+ distinguishable; a pattern-ONLY chart must still give series 1 a fill or
69
+ a labelled legend. */
38
70
  --chart-pattern-size: 8px;
39
71
  --chart-pattern-ink: rgb(0 0 0 / 0.34);
40
72
  --chart-pattern-1: none;
@@ -49,20 +81,27 @@
49
81
 
50
82
  @media (prefers-color-scheme: dark) {
51
83
  :root:not([data-theme='light']) {
52
- --chart-1: var(--accent);
53
- --chart-2: #e69f00;
54
- --chart-3: #56b4e9;
55
- --chart-4: #009e73;
56
- --chart-5: #f0e442;
57
- --chart-6: #0072b2;
58
- --chart-7: #cc79a7;
59
- --chart-8: #4d5358;
60
- --chart-seq-1: oklch(30% 0.1 25deg);
61
- --chart-seq-2: oklch(42% 0.15 25deg);
62
- --chart-seq-3: oklch(55% 0.17 25deg);
63
- --chart-seq-4: oklch(68% 0.15 25deg);
64
- --chart-seq-5: oklch(80% 0.1 25deg);
65
- --chart-seq-6: oklch(90% 0.05 25deg);
84
+ --cat-1: #3987e5;
85
+ --cat-2: #d95926;
86
+ --cat-3: #199e70;
87
+ --cat-4: #c98500;
88
+ --cat-5: #d55181;
89
+ --cat-6: #008300;
90
+ --cat-7: #9085e9;
91
+ --cat-8: #e66767;
92
+ --cat-1-ink: #4694f3;
93
+ --cat-2-ink: #e86f42;
94
+ --cat-3-ink: #27a677;
95
+ --cat-4-ink: #cb8705;
96
+ --cat-5-ink: #e46792;
97
+ --cat-6-ink: #38a433;
98
+ --cat-7-ink: #9187eb;
99
+ --cat-8-ink: #eb6c6c;
100
+ --chart-seq-1: #1b5298;
101
+ --chart-seq-2: #256abf;
102
+ --chart-seq-3: #3987e5;
103
+ --chart-seq-4: #6da7ec;
104
+ --chart-seq-5: #9ec5f4;
66
105
  --chart-div-1: oklch(70% 0.13 250deg);
67
106
  --chart-div-2: oklch(60% 0.12 252deg);
68
107
  --chart-div-3: oklch(48% 0.08 255deg);
@@ -75,20 +114,27 @@
75
114
  }
76
115
 
77
116
  :root[data-theme='dark'] {
78
- --chart-1: var(--accent);
79
- --chart-2: #e69f00;
80
- --chart-3: #56b4e9;
81
- --chart-4: #009e73;
82
- --chart-5: #f0e442;
83
- --chart-6: #0072b2;
84
- --chart-7: #cc79a7;
85
- --chart-8: #4d5358;
86
- --chart-seq-1: oklch(30% 0.1 25deg);
87
- --chart-seq-2: oklch(42% 0.15 25deg);
88
- --chart-seq-3: oklch(55% 0.17 25deg);
89
- --chart-seq-4: oklch(68% 0.15 25deg);
90
- --chart-seq-5: oklch(80% 0.1 25deg);
91
- --chart-seq-6: oklch(90% 0.05 25deg);
117
+ --cat-1: #3987e5;
118
+ --cat-2: #d95926;
119
+ --cat-3: #199e70;
120
+ --cat-4: #c98500;
121
+ --cat-5: #d55181;
122
+ --cat-6: #008300;
123
+ --cat-7: #9085e9;
124
+ --cat-8: #e66767;
125
+ --cat-1-ink: #4694f3;
126
+ --cat-2-ink: #e86f42;
127
+ --cat-3-ink: #27a677;
128
+ --cat-4-ink: #cb8705;
129
+ --cat-5-ink: #e46792;
130
+ --cat-6-ink: #38a433;
131
+ --cat-7-ink: #9187eb;
132
+ --cat-8-ink: #eb6c6c;
133
+ --chart-seq-1: #1b5298;
134
+ --chart-seq-2: #256abf;
135
+ --chart-seq-3: #3987e5;
136
+ --chart-seq-4: #6da7ec;
137
+ --chart-seq-5: #9ec5f4;
92
138
  --chart-div-1: oklch(70% 0.13 250deg);
93
139
  --chart-div-2: oklch(60% 0.12 252deg);
94
140
  --chart-div-3: oklch(48% 0.08 255deg);
@@ -101,20 +147,27 @@
101
147
 
102
148
  @media print {
103
149
  :root:not([data-theme='light']) {
104
- --chart-1: var(--accent);
105
- --chart-2: #e69f00;
106
- --chart-3: #56b4e9;
107
- --chart-4: #009e73;
108
- --chart-5: #f0e442;
109
- --chart-6: #0072b2;
110
- --chart-7: #cc79a7;
111
- --chart-8: #4d5358;
112
- --chart-seq-1: oklch(94% 0.03 25deg);
113
- --chart-seq-2: oklch(85% 0.07 25deg);
114
- --chart-seq-3: oklch(74% 0.12 25deg);
115
- --chart-seq-4: oklch(62% 0.16 25deg);
116
- --chart-seq-5: oklch(50% 0.16 25deg);
117
- --chart-seq-6: oklch(38% 0.13 25deg);
150
+ --cat-1: #2a78d6;
151
+ --cat-2: #eb6834;
152
+ --cat-3: #1baf7a;
153
+ --cat-4: #eda100;
154
+ --cat-5: #e87ba4;
155
+ --cat-6: #008300;
156
+ --cat-7: #4a3aa7;
157
+ --cat-8: #e34948;
158
+ --cat-1-ink: #1467c3;
159
+ --cat-2-ink: #bf3f00;
160
+ --cat-3-ink: #007d4c;
161
+ --cat-4-ink: #a45d00;
162
+ --cat-5-ink: #b04972;
163
+ --cat-6-ink: #007800;
164
+ --cat-7-ink: #4a3aa7;
165
+ --cat-8-ink: #c62b30;
166
+ --chart-seq-1: #80b0e8;
167
+ --chart-seq-2: #5598e7;
168
+ --chart-seq-3: #2a78d6;
169
+ --chart-seq-4: #1c5cab;
170
+ --chart-seq-5: #104281;
118
171
  --chart-div-1: oklch(45% 0.14 255deg);
119
172
  --chart-div-2: oklch(62% 0.1 250deg);
120
173
  --chart-div-3: oklch(82% 0.05 245deg);
@@ -75,8 +75,8 @@
75
75
  distinction — colour stays the solid accent used by every other
76
76
  control's ring (the --focus-ring token wiring is decided globally,
77
77
  not per-component). */
78
- outline: 2px solid var(--focus-ring);
79
- outline-offset: -3px;
78
+ outline: var(--focus-ring-width) solid var(--focus-ring);
79
+ outline-offset: calc(-1.5 * var(--focus-ring-offset));
80
80
  }
81
81
 
82
82
  .ui-tabs__panel[hidden] {
@@ -216,8 +216,8 @@
216
216
  }
217
217
 
218
218
  .ui-segmented__option:has(input:focus-visible) {
219
- outline: 2px solid var(--focus-ring);
220
- outline-offset: -2px;
219
+ outline: var(--focus-ring-width) solid var(--focus-ring);
220
+ outline-offset: calc(-1 * var(--focus-ring-offset));
221
221
  }
222
222
 
223
223
  @media (hover: hover) {
@@ -439,8 +439,8 @@
439
439
  }
440
440
 
441
441
  .ui-carousel__viewport:focus-visible {
442
- outline: 2px solid var(--focus-ring);
443
- outline-offset: -2px;
442
+ outline: var(--focus-ring-width) solid var(--focus-ring);
443
+ outline-offset: calc(-1 * var(--focus-ring-offset));
444
444
  }
445
445
 
446
446
  .ui-carousel__slide {
@@ -519,8 +519,8 @@
519
519
 
520
520
  .ui-carousel__prev:focus-visible,
521
521
  .ui-carousel__next:focus-visible {
522
- outline: 2px solid var(--focus-ring);
523
- outline-offset: 2px;
522
+ outline: var(--focus-ring-width) solid var(--focus-ring);
523
+ outline-offset: var(--focus-ring-offset);
524
524
  }
525
525
 
526
526
  /* Position counter ("3 / 12") — initCarousel fills the text; aria-live. */
@@ -584,8 +584,8 @@
584
584
  }
585
585
 
586
586
  .ui-carousel__thumb:focus-visible {
587
- outline: 2px solid var(--focus-ring);
588
- outline-offset: 2px;
587
+ outline: var(--focus-ring-width) solid var(--focus-ring);
588
+ outline-offset: var(--focus-ring-offset);
589
589
  }
590
590
 
591
591
  @media (prefers-reduced-motion: reduce) {
package/css/forms.css CHANGED
@@ -66,8 +66,8 @@
66
66
  .ui-input:focus-visible,
67
67
  .ui-select:focus-visible,
68
68
  .ui-textarea:focus-visible {
69
- outline: 2px solid var(--focus-ring);
70
- outline-offset: 1px;
69
+ outline: var(--focus-ring-width) solid var(--focus-ring);
70
+ outline-offset: calc(var(--focus-ring-offset) / 2);
71
71
  }
72
72
 
73
73
  .ui-input:disabled,
@@ -292,8 +292,8 @@
292
292
  }
293
293
 
294
294
  .ui-range:focus-visible {
295
- outline: 2px solid var(--focus-ring);
296
- outline-offset: 4px;
295
+ outline: var(--focus-ring-width) solid var(--focus-ring);
296
+ outline-offset: calc(2 * var(--focus-ring-offset));
297
297
  }
298
298
 
299
299
  /* --- Error summary: one focusable, assertive list of form errors --- */
@@ -358,8 +358,8 @@
358
358
  border-colour shift alone read markedly fainter on this one control. Keyed to
359
359
  :focus-visible on the inner input so it stays keyboard-only. */
360
360
  .ui-search:has(input:focus-visible) {
361
- outline: 2px solid var(--focus-ring);
362
- outline-offset: 1px;
361
+ outline: var(--focus-ring-width) solid var(--focus-ring);
362
+ outline-offset: calc(var(--focus-ring-offset) / 2);
363
363
  }
364
364
 
365
365
  .ui-search:focus-within::before {
@@ -429,8 +429,8 @@
429
429
  }
430
430
 
431
431
  .ui-switch input:focus-visible + .ui-switch__track {
432
- outline: 2px solid var(--focus-ring);
433
- outline-offset: 2px;
432
+ outline: var(--focus-ring-width) solid var(--focus-ring);
433
+ outline-offset: var(--focus-ring-offset);
434
434
  }
435
435
 
436
436
  /* ARIA contract: `.ui-switch` is a visually-styled checkbox. Author
package/css/legend.css CHANGED
@@ -158,8 +158,7 @@
158
158
  var(--chart-seq-2),
159
159
  var(--chart-seq-3),
160
160
  var(--chart-seq-4),
161
- var(--chart-seq-5),
162
- var(--chart-seq-6)
161
+ var(--chart-seq-5)
163
162
  );
164
163
  block-size: 0.7rem;
165
164
  border: 1px solid var(--line);
@@ -812,12 +812,11 @@
812
812
 
813
813
  /* --- Touch: comfortable hit targets on coarse pointers.
814
814
 
815
- The floor is `--tap-target`, not a bare rem. Bronto's own base sets
816
- `html { font-size: 0.9375rem }`, so the 2.9rem this family used to carry
817
- resolved to 43.5px — half a pixel under the 44px WCAG 2.5.5 / platform-HIG
818
- target, and under any host that shrinks the root further it drifted further
819
- still. The token clamps in px against the rem so the standard holds however
820
- the root is re-pointed. --- */
815
+ The floor is `--tap-target`, not a bare rem. Under a 15px root the 2.9rem
816
+ this family used to carry resolved to 43.5px — half a pixel under the 44px
817
+ WCAG 2.5.5 / platform-HIG target, and under any host that shrinks the root
818
+ further it drifted further still. The token clamps in px against the rem so
819
+ the standard holds however the root is re-pointed. --- */
821
820
 
822
821
  @media (pointer: coarse) {
823
822
  .ui-button {
package/css/row.css CHANGED
@@ -126,8 +126,8 @@
126
126
  .ui-row:focus-visible {
127
127
  background: var(--bg-accent);
128
128
  color: var(--text);
129
- outline: 2px solid var(--focus-ring);
130
- outline-offset: -2px;
129
+ outline: var(--focus-ring-width) solid var(--focus-ring);
130
+ outline-offset: calc(-1 * var(--focus-ring-offset));
131
131
  }
132
132
 
133
133
  /* Touch: a row is a primary target in a list, so it floats to the full
package/css/term.css CHANGED
@@ -39,8 +39,8 @@
39
39
  }
40
40
 
41
41
  .ui-term:focus-visible {
42
- outline: 2px solid var(--focus-ring);
43
- outline-offset: 2px;
42
+ outline: var(--focus-ring-width) solid var(--focus-ring);
43
+ outline-offset: var(--focus-ring-offset);
44
44
  }
45
45
 
46
46
  /* The definition — a native popover. Reset the UA popover chrome to the Bronto
package/css/textref.css CHANGED
@@ -39,8 +39,8 @@
39
39
  }
40
40
 
41
41
  .ui-textref:focus-visible {
42
- outline: 2px solid var(--focus-ring);
43
- outline-offset: 2px;
42
+ outline: var(--focus-ring-width) solid var(--focus-ring);
43
+ outline-offset: var(--focus-ring-offset);
44
44
  }
45
45
 
46
46
  /* The browser-painted highlight on the matched fragment. Scoped to the page
package/css/toc.css CHANGED
@@ -64,8 +64,8 @@
64
64
  }
65
65
 
66
66
  .ui-toc__link:focus-visible {
67
- outline: 2px solid var(--focus-ring);
68
- outline-offset: -2px;
67
+ outline: var(--focus-ring-width) solid var(--focus-ring);
68
+ outline-offset: calc(-1 * var(--focus-ring-offset));
69
69
  }
70
70
 
71
71
  @media (hover: hover) {
package/css/tokens.css CHANGED
@@ -25,6 +25,10 @@
25
25
  --space-lg: 1.35rem;
26
26
  --space-xl: 1.75rem;
27
27
  --space-2xl: 2.5rem;
28
+ --space-0-5: 0.125rem;
29
+ --space-0-75: 0.1875rem;
30
+ --space-1-5: 0.375rem;
31
+ --space-2-5: 0.625rem;
28
32
  --tap-target: max(44px, 2.9rem);
29
33
  --tap-target-min: max(24px, 1.6rem);
30
34
  --safe-area-top: env(safe-area-inset-top, 0px);
@@ -68,6 +72,22 @@
68
72
  --z-popover: 50;
69
73
  --z-toast: 60;
70
74
 
75
+ /* Workspace layers over a canvas, aliased to the page layer where they mean the same. */
76
+ --z-canvas: var(--z-base);
77
+ --z-chrome: var(--z-sticky);
78
+ --z-panel: 25;
79
+ --z-modal: var(--z-overlay);
80
+ --z-menu: var(--z-popover);
81
+ --z-tooltip: 70;
82
+ --z-navigation: 80;
83
+
84
+ /* Zoom — --ui-px is one screen pixel; [data-ui-zoom] re-declares it for a scaled surface. */
85
+ --ui-zoom: 1;
86
+ --ui-px: 1px;
87
+ --hairline: 1px;
88
+ --focus-ring-width: 2px;
89
+ --focus-ring-offset: 2px;
90
+
71
91
  /* Accent ramp — a stepped family for charts / data-viz, derived from the single --accent knob via OKLCH color-mix against a per-theme white/black endpoint. */
72
92
  --accent-1: color-mix(in oklch, var(--accent) 8%, var(--accent-ramp-end));
73
93
  --accent-2: color-mix(in oklch, var(--accent) 16%, var(--accent-ramp-end));
@@ -259,6 +279,10 @@
259
279
  -------------------------------------------------------------------------- */
260
280
 
261
281
  [data-density='compact'] {
282
+ --space-0-5: 0.1rem;
283
+ --space-0-75: 0.15rem;
284
+ --space-1-5: 0.3rem;
285
+ --space-2-5: 0.5rem;
262
286
  --space-2xs: 0.2rem;
263
287
  --space-xs: 0.4rem;
264
288
  --space-sm: 0.6rem;
@@ -269,6 +293,10 @@
269
293
  }
270
294
 
271
295
  [data-density='comfortable'] {
296
+ --space-0-5: 0.15rem;
297
+ --space-0-75: 0.225rem;
298
+ --space-1-5: 0.45rem;
299
+ --space-2-5: 0.75rem;
272
300
  --space-2xs: 0.3rem;
273
301
  --space-xs: 0.6rem;
274
302
  --space-sm: 0.95rem;
@@ -278,6 +306,21 @@
278
306
  --space-2xl: 3.1rem;
279
307
  }
280
308
 
309
+ /* Zoom — a host that draws bronto UI inside a scaled surface (a zoomable
310
+ canvas) marks the scaled element [data-ui-zoom] and sets --ui-zoom to its
311
+ scale there. Inside it --ui-px is one SCREEN pixel, so hairlines, focus rings
312
+ and anything the host sizes in --ui-px keep their on-screen size at any zoom.
313
+ Re-declared here, not inherited, because a custom property that reads
314
+ --ui-zoom resolves where it is declared: the :root values cannot follow a
315
+ zoomed subtree. The 0.15 floor stops a far-out zoom inflating a ring past
316
+ the thing it rings. */
317
+ [data-ui-zoom] {
318
+ --ui-px: calc(1px / max(var(--ui-zoom, 1), 0.15));
319
+ --hairline: var(--ui-px);
320
+ --focus-ring-width: calc(2 * var(--ui-px));
321
+ --focus-ring-offset: calc(2 * var(--ui-px));
322
+ }
323
+
281
324
  /* High contrast — manual opt-in and the OS `prefers-contrast` signal.
282
325
  Both collapse the soft greys toward the strong end; theme-agnostic
283
326
  because they reference the per-theme *-strong / -soft tokens. */
package/css/workbench.css CHANGED
@@ -432,8 +432,8 @@
432
432
  }
433
433
 
434
434
  .ui-splitter__handle:focus-visible {
435
- outline: 2px solid var(--focus-ring);
436
- outline-offset: -2px;
435
+ outline: var(--focus-ring-width) solid var(--focus-ring);
436
+ outline-offset: calc(-1 * var(--focus-ring-offset));
437
437
  }
438
438
 
439
439
  .ui-splitter--horizontal .ui-splitter__handle {