@ponchia/ui 0.4.1 → 0.6.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 (153) hide show
  1. package/CHANGELOG.md +552 -8
  2. package/MIGRATIONS.json +106 -0
  3. package/README.md +34 -8
  4. package/annotations/index.d.ts +402 -0
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +792 -0
  7. package/behaviors/carousel.js +198 -0
  8. package/behaviors/combobox.js +226 -0
  9. package/behaviors/command.js +190 -0
  10. package/behaviors/connectors.js +95 -0
  11. package/behaviors/crosshair.js +57 -0
  12. package/behaviors/dialog.js +74 -0
  13. package/behaviors/disclosure.js +26 -0
  14. package/behaviors/dismissible.js +25 -0
  15. package/behaviors/forms.js +186 -0
  16. package/behaviors/glyph.js +108 -0
  17. package/behaviors/index.d.ts +79 -0
  18. package/behaviors/index.js +18 -1409
  19. package/behaviors/internal.js +97 -0
  20. package/behaviors/legend.js +67 -0
  21. package/behaviors/menu.js +47 -0
  22. package/behaviors/popover.js +179 -0
  23. package/behaviors/spotlight.js +52 -0
  24. package/behaviors/table.js +136 -0
  25. package/behaviors/tabs.js +103 -0
  26. package/behaviors/theme.js +84 -0
  27. package/behaviors/toast.js +164 -0
  28. package/classes/classes.json +1857 -0
  29. package/classes/index.d.ts +306 -13
  30. package/classes/index.js +339 -12
  31. package/classes/vscode.css-custom-data.json +12 -0
  32. package/connectors/index.d.ts +191 -0
  33. package/connectors/index.d.ts.map +1 -0
  34. package/connectors/index.js +275 -0
  35. package/css/analytical.css +21 -0
  36. package/css/annotations.css +292 -0
  37. package/css/app.css +43 -13
  38. package/css/base.css +15 -10
  39. package/css/command.css +97 -0
  40. package/css/connectors.css +110 -0
  41. package/css/content.css +7 -1
  42. package/css/crosshair.css +100 -0
  43. package/css/dataviz.css +5 -1
  44. package/css/disclosure.css +38 -6
  45. package/css/dots.css +57 -0
  46. package/css/feedback.css +111 -2
  47. package/css/fonts.css +11 -7
  48. package/css/forms.css +42 -1
  49. package/css/generated.css +117 -0
  50. package/css/legend.css +272 -0
  51. package/css/marks.css +174 -0
  52. package/css/motion.css +24 -44
  53. package/css/navigation.css +7 -0
  54. package/css/overlay.css +31 -1
  55. package/css/primitives.css +109 -5
  56. package/css/report.css +39 -81
  57. package/css/selection.css +46 -0
  58. package/css/site.css +16 -2
  59. package/css/sources.css +221 -0
  60. package/css/spotlight.css +104 -0
  61. package/css/state.css +121 -0
  62. package/css/tokens.css +60 -37
  63. package/css/workbench.css +83 -0
  64. package/dist/bronto.css +1 -1
  65. package/dist/css/analytical.css +1 -0
  66. package/dist/css/annotations.css +1 -0
  67. package/dist/css/app.css +1 -1
  68. package/dist/css/base.css +1 -1
  69. package/dist/css/command.css +1 -0
  70. package/dist/css/connectors.css +1 -0
  71. package/dist/css/content.css +1 -1
  72. package/dist/css/crosshair.css +1 -0
  73. package/dist/css/disclosure.css +1 -1
  74. package/dist/css/dots.css +1 -1
  75. package/dist/css/feedback.css +1 -1
  76. package/dist/css/fonts.css +1 -1
  77. package/dist/css/forms.css +1 -1
  78. package/dist/css/generated.css +1 -0
  79. package/dist/css/legend.css +1 -0
  80. package/dist/css/marks.css +1 -0
  81. package/dist/css/motion.css +1 -1
  82. package/dist/css/navigation.css +1 -1
  83. package/dist/css/overlay.css +1 -1
  84. package/dist/css/primitives.css +1 -1
  85. package/dist/css/report.css +1 -1
  86. package/dist/css/selection.css +1 -0
  87. package/dist/css/site.css +1 -1
  88. package/dist/css/sources.css +1 -0
  89. package/dist/css/spotlight.css +1 -0
  90. package/dist/css/state.css +1 -0
  91. package/dist/css/tokens.css +1 -1
  92. package/dist/css/workbench.css +1 -0
  93. package/docs/adr/0003-theme-model.md +7 -4
  94. package/docs/annotations.md +425 -0
  95. package/docs/architecture.md +246 -0
  96. package/docs/command.md +95 -0
  97. package/docs/connectors.md +91 -0
  98. package/docs/contrast.md +116 -92
  99. package/docs/crosshair.md +63 -0
  100. package/docs/d2.md +195 -0
  101. package/docs/generated.md +91 -0
  102. package/docs/legends.md +184 -0
  103. package/docs/marks.md +93 -0
  104. package/docs/mermaid.md +152 -0
  105. package/docs/reference.md +385 -23
  106. package/docs/reporting.md +436 -63
  107. package/docs/selection.md +40 -0
  108. package/docs/sources.md +137 -0
  109. package/docs/spotlight.md +78 -0
  110. package/docs/stability.md +24 -2
  111. package/docs/state.md +85 -0
  112. package/docs/usage.md +123 -4
  113. package/docs/vega.md +225 -0
  114. package/docs/workbench.md +78 -0
  115. package/fonts/doto-400.woff2 +0 -0
  116. package/fonts/doto-500.woff2 +0 -0
  117. package/fonts/doto-600.woff2 +0 -0
  118. package/fonts/doto-700.woff2 +0 -0
  119. package/fonts/doto-800.woff2 +0 -0
  120. package/fonts/doto-900.woff2 +0 -0
  121. package/glyphs/glyphs.js +6 -4
  122. package/llms.txt +362 -14
  123. package/package.json +115 -12
  124. package/qwik/index.d.ts +42 -54
  125. package/qwik/index.d.ts.map +1 -0
  126. package/qwik/index.js +75 -3
  127. package/react/index.d.ts +39 -56
  128. package/react/index.d.ts.map +1 -0
  129. package/react/index.js +67 -3
  130. package/solid/index.d.ts +64 -56
  131. package/solid/index.d.ts.map +1 -0
  132. package/solid/index.js +70 -3
  133. package/tokens/d2.d.ts +38 -0
  134. package/tokens/d2.js +71 -0
  135. package/tokens/d2.json +43 -0
  136. package/tokens/index.d.ts +5 -5
  137. package/tokens/index.js +23 -5
  138. package/tokens/index.json +9 -0
  139. package/tokens/mermaid.d.ts +23 -0
  140. package/tokens/mermaid.js +181 -0
  141. package/tokens/mermaid.json +163 -0
  142. package/tokens/resolved.json +45 -1
  143. package/tokens/skins.js +3 -2
  144. package/tokens/tokens.dtcg.json +26 -0
  145. package/tokens/vega.d.ts +34 -0
  146. package/tokens/vega.js +155 -0
  147. package/tokens/vega.json +179 -0
  148. package/fonts/doto-400.ttf +0 -0
  149. package/fonts/doto-500.ttf +0 -0
  150. package/fonts/doto-600.ttf +0 -0
  151. package/fonts/doto-700.ttf +0 -0
  152. package/fonts/doto-800.ttf +0 -0
  153. package/fonts/doto-900.ttf +0 -0
@@ -0,0 +1,46 @@
1
+ /* ==========================================================================
2
+ selection — opt-in, cross-cutting selection-emphasis vocabulary.
3
+
4
+ The carve-out from "brush/lasso": Bronto does NOT do region selection or
5
+ hit-testing (that needs the host's scales/geometry). It ships only the
6
+ *states* an item can be in once the host has decided — reusable on a chart
7
+ mark, a table row, a list item, a map region. The host adds/removes these
8
+ classes from its own brush/filter logic. Not imported by core.css.
9
+
10
+ in the selection → .ui-sel--on · excluded → .ui-sel--off
11
+ would-be-selected (live brush) → .ui-sel--maybe
12
+ ========================================================================== */
13
+
14
+ .ui-sel {
15
+ transition:
16
+ opacity 0.12s ease,
17
+ outline-color 0.12s ease;
18
+ }
19
+
20
+ @media (prefers-reduced-motion: reduce) {
21
+ .ui-sel {
22
+ transition: none;
23
+ }
24
+ }
25
+
26
+ .ui-sel--on {
27
+ outline: 2px solid var(--accent);
28
+ outline-offset: 1px;
29
+ }
30
+
31
+ .ui-sel--off {
32
+ /* opacity survives forced-colors, so an excluded item stays dimmer than the
33
+ selected/candidate items (which carry a solid/dashed outline). */
34
+ opacity: 0.35;
35
+ }
36
+
37
+ .ui-sel--maybe {
38
+ outline: 1px dashed var(--accent);
39
+ outline-offset: 1px;
40
+ }
41
+
42
+ @media (forced-colors: active) {
43
+ .ui-sel--on {
44
+ outline-color: Highlight;
45
+ }
46
+ }
package/css/site.css CHANGED
@@ -162,11 +162,11 @@
162
162
  transform var(--duration-fast) var(--ease-spring);
163
163
  }
164
164
 
165
- .ui-sitenav a[aria-current] {
165
+ .ui-sitenav a[aria-current]:not([aria-current='false']) {
166
166
  color: var(--accent-text);
167
167
  }
168
168
 
169
- .ui-sitenav a[aria-current]::before {
169
+ .ui-sitenav a[aria-current]:not([aria-current='false'])::before {
170
170
  opacity: 1;
171
171
  transform: scale(1);
172
172
  }
@@ -182,6 +182,13 @@
182
182
  }
183
183
  }
184
184
 
185
+ @media (pointer: coarse) {
186
+ .ui-sitenav a {
187
+ min-block-size: 2.9rem;
188
+ padding-inline: 0.9rem;
189
+ }
190
+ }
191
+
185
192
  /* --- Mobile menu — native <details>, no JS required --- */
186
193
 
187
194
  .ui-sitemenu {
@@ -247,6 +254,13 @@
247
254
  }
248
255
  }
249
256
 
257
+ @media (pointer: coarse) {
258
+ .ui-sitemenu > summary {
259
+ min-block-size: 2.9rem;
260
+ padding-inline: 0.9rem;
261
+ }
262
+ }
263
+
250
264
  /* --- Footer --- */
251
265
 
252
266
  .ui-sitefooter {
@@ -0,0 +1,221 @@
1
+ /* ==========================================================================
2
+ sources — opt-in source, citation & provenance grammar (the trust layer).
3
+
4
+ For generated reports, AI output, audits and docs that must answer "where
5
+ did this come from?". Bronto owns the visual grammar + the trust states; the
6
+ host owns fetching, citation numbering, and whether a source is trustworthy.
7
+ The state is carried by a rationed tone dot/border AND an author-written
8
+ label, so it never relies on colour alone (WCAG 1.4.1). Not imported by
9
+ core.css.
10
+
11
+ States (cross-cutting `.ui-src--*`, set the tone): verified · reviewed ·
12
+ generated · unverified · stale · conflict.
13
+ ========================================================================== */
14
+
15
+ /* One tone, shared by citation / source-card / provenance via `--src-tone`. */
16
+ .ui-citation,
17
+ .ui-source-card,
18
+ .ui-provenance {
19
+ --src-tone: var(--text-dim);
20
+ }
21
+
22
+ /* Standalone trust pill — wears a `.ui-src--*` tone on its own, for a bare
23
+ "verified" / "stale" label outside a citation or source card (the tone setters
24
+ below only paint a `--src-tone` custom property, so without this host a lone
25
+ `.ui-src--verified` validates against classes.json yet renders nothing). Tone
26
+ is a leading dot + a tinted border AND the author's written label, never colour
27
+ alone (WCAG 1.4.1). Declared before the `--*` setters so their tone wins. */
28
+ .ui-src {
29
+ --src-tone: var(--text-dim);
30
+
31
+ align-items: center;
32
+ background: var(--panel-soft);
33
+ border: 1px solid color-mix(in srgb, var(--src-tone) 45%, var(--line));
34
+ border-radius: var(--radius-pill);
35
+ color: var(--text-soft);
36
+ display: inline-flex;
37
+ font-size: var(--text-2xs);
38
+ gap: 0.35rem;
39
+ padding: 0.08rem 0.55rem;
40
+ vertical-align: baseline;
41
+ }
42
+
43
+ .ui-src::before {
44
+ background: var(--src-tone);
45
+ border-radius: 50%;
46
+ block-size: 0.45rem;
47
+ content: '';
48
+ flex: none;
49
+ inline-size: 0.45rem;
50
+ print-color-adjust: exact;
51
+ }
52
+
53
+ .ui-src--verified {
54
+ --src-tone: var(--success);
55
+ }
56
+
57
+ .ui-src--reviewed {
58
+ --src-tone: var(--accent);
59
+ }
60
+
61
+ .ui-src--generated {
62
+ --src-tone: var(--info);
63
+ }
64
+
65
+ .ui-src--unverified {
66
+ --src-tone: var(--text-dim);
67
+ }
68
+
69
+ .ui-src--stale {
70
+ --src-tone: var(--warning);
71
+ }
72
+
73
+ .ui-src--conflict {
74
+ --src-tone: var(--danger);
75
+ }
76
+
77
+ /* --- Inline citation — a reference marker on an <a> or <button>. --- */
78
+ .ui-citation {
79
+ color: var(--accent-text);
80
+ font-family: var(--mono);
81
+ font-size: 0.72em;
82
+ font-weight: 600;
83
+ text-decoration: none;
84
+ vertical-align: super;
85
+ }
86
+
87
+ .ui-citation:hover {
88
+ text-decoration: underline;
89
+ }
90
+
91
+ /* Named-source pill — full size, with a leading tone dot. */
92
+ .ui-citation--chip {
93
+ align-items: center;
94
+ background: var(--panel-soft);
95
+ border: 1px solid var(--line);
96
+ border-radius: var(--radius-pill);
97
+ color: var(--text-soft);
98
+ display: inline-flex;
99
+ font-size: var(--text-2xs);
100
+ gap: 0.35rem;
101
+ padding: 0.08rem 0.55rem;
102
+ vertical-align: baseline;
103
+ }
104
+
105
+ .ui-citation--chip::before {
106
+ background: var(--src-tone);
107
+ border-radius: 50%;
108
+ block-size: 0.45rem;
109
+ content: '';
110
+ inline-size: 0.45rem;
111
+ print-color-adjust: exact;
112
+ }
113
+
114
+ /* --- Source list — a references section. --- */
115
+ .ui-source-list {
116
+ display: grid;
117
+ gap: var(--space-sm);
118
+ list-style: none;
119
+ margin: 0;
120
+ padding: 0;
121
+ }
122
+
123
+ .ui-source-list__item {
124
+ margin: 0;
125
+ }
126
+
127
+ /* --- Source card — a single source preview. --- */
128
+ .ui-source-card {
129
+ background: var(--panel-soft);
130
+ border: 1px solid var(--line);
131
+ border-inline-start: 2px solid var(--src-tone);
132
+ border-radius: var(--radius-md);
133
+ display: grid;
134
+ gap: 0.3rem;
135
+ padding: 0.75rem 0.9rem;
136
+ print-color-adjust: exact;
137
+ }
138
+
139
+ .ui-source-card__title {
140
+ color: var(--text);
141
+ font-size: var(--text-sm);
142
+ font-weight: 600;
143
+ margin: 0;
144
+ }
145
+
146
+ .ui-source-card__origin {
147
+ color: var(--text-soft);
148
+ font-family: var(--mono);
149
+ font-size: var(--text-2xs);
150
+ letter-spacing: var(--tracking-wide);
151
+ }
152
+
153
+ .ui-source-card__time {
154
+ color: var(--text-dim);
155
+ font-family: var(--mono);
156
+ font-size: var(--text-2xs);
157
+ }
158
+
159
+ .ui-source-card__excerpt {
160
+ color: var(--text-soft);
161
+ margin: 0;
162
+ }
163
+
164
+ .ui-source-card__actions {
165
+ display: flex;
166
+ flex-wrap: wrap;
167
+ gap: 0.5rem;
168
+ margin-block-start: 0.2rem;
169
+ }
170
+
171
+ /* --- Provenance — compact metadata beside generated content. --- */
172
+ .ui-provenance {
173
+ align-items: center;
174
+ color: var(--text-dim);
175
+ display: inline-flex;
176
+ flex-wrap: wrap;
177
+ font-family: var(--mono);
178
+ font-size: var(--text-2xs);
179
+ gap: 0.3rem 0.75rem;
180
+ letter-spacing: var(--tracking-wide);
181
+ }
182
+
183
+ .ui-provenance__item {
184
+ align-items: center;
185
+ display: inline-flex;
186
+ gap: 0.35rem;
187
+ }
188
+
189
+ .ui-provenance__item::before {
190
+ background: var(--src-tone);
191
+ border-radius: 50%;
192
+ block-size: 0.45rem;
193
+ content: '';
194
+ inline-size: 0.45rem;
195
+ print-color-adjust: exact;
196
+ }
197
+
198
+ /* Forced colours: the tone dot/border collapses to a system colour, so the
199
+ author-written label is the surviving state channel (it already must be —
200
+ 1.4.1). Keep the marks visible as CanvasText rather than letting them vanish. */
201
+ @media (forced-colors: active) {
202
+ .ui-citation--chip::before,
203
+ .ui-provenance__item::before,
204
+ .ui-src::before {
205
+ background: CanvasText;
206
+ }
207
+
208
+ .ui-source-card {
209
+ border-inline-start-color: CanvasText;
210
+ }
211
+ }
212
+
213
+ /* Print: an inline citation marker points into the references list, so never
214
+ expand its href inline. base.css expands `.ui-prose a[href^="http"]` with a
215
+ trailing "(url)"; on a superscript marker that dumps a full URL mid-sentence.
216
+ !important + print-scoped because base's rule is more specific. */
217
+ @media print {
218
+ .ui-citation[href]::after {
219
+ content: none !important;
220
+ }
221
+ }
@@ -0,0 +1,104 @@
1
+ /* ==========================================================================
2
+ spotlight — opt-in guided-focus overlay (the visual language of a tour).
3
+
4
+ A dimming overlay with a cutout over a target element, an optional target
5
+ ring, and a callout note. Bronto owns the *look* and (via `initSpotlight`)
6
+ positions the cutout over a target; it is NOT a tour engine — step order,
7
+ advancing, and persistence are the host's. Not imported by core.css.
8
+
9
+ The cutout is a single box-shadow hole driven by JS-set custom properties
10
+ (`--spot-x/y/w/h`, viewport coordinates). The overlay is non-blocking
11
+ (`pointer-events: none`) — a visual highlight, not a modal trap.
12
+ ========================================================================== */
13
+
14
+ .ui-spotlight {
15
+ --spot-x: 50%;
16
+ --spot-y: 50%;
17
+ --spot-w: 0px;
18
+ --spot-h: 0px;
19
+ --spot-pad: 8px;
20
+ --spot-radius: var(--radius-md);
21
+ --spot-backdrop: color-mix(in srgb, #000 55%, transparent);
22
+
23
+ inset: 0;
24
+ pointer-events: none;
25
+ position: fixed;
26
+ z-index: var(--z-overlay, 1000);
27
+ }
28
+
29
+ .ui-spotlight__hole {
30
+ background: transparent;
31
+ block-size: calc(var(--spot-h) + var(--spot-pad) * 2);
32
+ border-radius: var(--spot-radius);
33
+ box-shadow: 0 0 0 100vmax var(--spot-backdrop);
34
+ inline-size: calc(var(--spot-w) + var(--spot-pad) * 2);
35
+ inset-block-start: 0;
36
+ inset-inline-start: 0;
37
+ position: absolute;
38
+ transform: translate(
39
+ calc(var(--spot-x) - var(--spot-pad)),
40
+ calc(var(--spot-y) - var(--spot-pad))
41
+ );
42
+ transition:
43
+ transform 0.2s ease,
44
+ inline-size 0.2s ease,
45
+ block-size 0.2s ease;
46
+ }
47
+
48
+ @media (prefers-reduced-motion: reduce) {
49
+ .ui-spotlight__hole {
50
+ transition: none;
51
+ }
52
+ }
53
+
54
+ .ui-spotlight--ring .ui-spotlight__hole {
55
+ outline: 2px solid var(--accent);
56
+ outline-offset: 0;
57
+ }
58
+
59
+ /* The callout. Place it near the target (the host positions it); it re-enables
60
+ pointer events so its controls work inside the non-interactive overlay. */
61
+ .ui-tour-note {
62
+ background: var(--panel);
63
+ border: 1px solid var(--line);
64
+ border-radius: var(--radius-md);
65
+ box-shadow: var(--shadow-raised);
66
+ color: var(--text);
67
+ display: grid;
68
+ gap: var(--space-sm);
69
+ max-inline-size: min(22rem, calc(100vw - 2rem));
70
+ padding: var(--space-md);
71
+ pointer-events: auto;
72
+ }
73
+
74
+ .ui-tour-note__step {
75
+ color: var(--text-dim);
76
+ font-family: var(--mono);
77
+ font-size: var(--text-2xs);
78
+ letter-spacing: 0;
79
+ text-transform: uppercase;
80
+ }
81
+
82
+ .ui-tour-note__title {
83
+ color: var(--text);
84
+ font-size: var(--text-lg);
85
+ font-weight: 600;
86
+ margin: 0;
87
+ }
88
+
89
+ .ui-tour-note__body {
90
+ color: var(--text-soft);
91
+ margin: 0;
92
+ }
93
+
94
+ .ui-tour-note__actions {
95
+ display: flex;
96
+ gap: var(--space-sm);
97
+ justify-content: flex-end;
98
+ }
99
+
100
+ @media (forced-colors: active) {
101
+ .ui-spotlight__hole {
102
+ outline: 2px solid CanvasText;
103
+ }
104
+ }
package/css/state.css ADDED
@@ -0,0 +1,121 @@
1
+ /* ==========================================================================
2
+ state — opt-in lifecycle / system-state vocabulary.
3
+
4
+ Serious apps spend a lot of time in states like saving, saved, queued,
5
+ offline, stale, conflicted, locked, and reviewed — usually improvised per
6
+ product, so even good apps feel inconsistent. This is the canonical set:
7
+ a labelled state object with a rationed tone, plus a page/document sync bar.
8
+
9
+ The state is carried by a tone dot AND an author-written label, never colour
10
+ alone (WCAG 1.4.1) — the label is the canonical wording (see docs/state.md).
11
+ Bronto ships the visual states; the host owns the state machine, retry
12
+ policy, persistence, and announcements. Persistent state gets persistent UI;
13
+ toasts are secondary. Not imported by core.css.
14
+ ========================================================================== */
15
+
16
+ .ui-state {
17
+ --state-tone: var(--text-dim);
18
+
19
+ align-items: center;
20
+ display: inline-flex;
21
+ font-size: var(--text-sm);
22
+ gap: 0.4rem;
23
+ }
24
+
25
+ /* Leading state indicator — a tone dot. `--busy` makes it pulse. */
26
+ .ui-state::before {
27
+ background: var(--state-tone);
28
+ border-radius: 50%;
29
+ block-size: 0.5rem;
30
+ content: '';
31
+ flex: none;
32
+ inline-size: 0.5rem;
33
+ print-color-adjust: exact;
34
+ }
35
+
36
+ .ui-state__label {
37
+ color: var(--text);
38
+ }
39
+
40
+ .ui-state__detail {
41
+ color: var(--text-dim);
42
+ font-size: var(--text-2xs);
43
+ }
44
+
45
+ /* In-progress states (saving / syncing / retrying): a pulsing indicator. */
46
+ .ui-state--busy::before {
47
+ animation: uiStatePulse 1.1s ease-in-out infinite;
48
+ }
49
+
50
+ @keyframes uiStatePulse {
51
+ 50% {
52
+ opacity: 0.3;
53
+ }
54
+ }
55
+
56
+ @media (prefers-reduced-motion: reduce) {
57
+ .ui-state--busy::before {
58
+ animation: none;
59
+ }
60
+ }
61
+
62
+ /* Canonical states — each bakes in the right rationed tone. */
63
+ .ui-state--saving {
64
+ --state-tone: var(--accent);
65
+ }
66
+
67
+ .ui-state--saved {
68
+ --state-tone: var(--success);
69
+ }
70
+
71
+ .ui-state--queued {
72
+ --state-tone: var(--text-dim);
73
+ }
74
+
75
+ .ui-state--offline {
76
+ --state-tone: var(--warning);
77
+ }
78
+
79
+ .ui-state--stale {
80
+ --state-tone: var(--warning);
81
+ }
82
+
83
+ .ui-state--conflict {
84
+ --state-tone: var(--danger);
85
+ }
86
+
87
+ .ui-state--error {
88
+ --state-tone: var(--danger);
89
+ }
90
+
91
+ .ui-state--locked {
92
+ --state-tone: var(--text-dim);
93
+ }
94
+
95
+ .ui-state--reviewed {
96
+ --state-tone: var(--success);
97
+ }
98
+
99
+ .ui-state--needs-review {
100
+ --state-tone: var(--warning);
101
+ }
102
+
103
+ /* Sync bar — a page/document-level save/sync status strip: a state on one side,
104
+ optional actions on the other. */
105
+ .ui-syncbar {
106
+ align-items: center;
107
+ border-block-end: 1px solid var(--line);
108
+ display: flex;
109
+ flex-wrap: wrap;
110
+ gap: var(--space-sm) var(--space-md);
111
+ justify-content: space-between;
112
+ padding-block: var(--space-xs);
113
+ }
114
+
115
+ /* Forced colours: the tone dot collapses to a system colour, so the
116
+ author-written label remains the state channel (it already must be). */
117
+ @media (forced-colors: active) {
118
+ .ui-state::before {
119
+ background: CanvasText;
120
+ }
121
+ }