@ponchia/ui 0.5.0 → 0.6.3

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 (196) hide show
  1. package/CHANGELOG.md +386 -4
  2. package/MIGRATIONS.json +14 -0
  3. package/README.md +29 -6
  4. package/annotations/index.d.ts +398 -276
  5. package/annotations/index.d.ts.map +1 -0
  6. package/annotations/index.js +350 -77
  7. package/behaviors/carousel.d.ts +28 -0
  8. package/behaviors/carousel.d.ts.map +1 -0
  9. package/behaviors/carousel.js +20 -16
  10. package/behaviors/combobox.d.ts +40 -0
  11. package/behaviors/combobox.d.ts.map +1 -0
  12. package/behaviors/combobox.js +111 -29
  13. package/behaviors/command.d.ts +41 -0
  14. package/behaviors/command.d.ts.map +1 -0
  15. package/behaviors/command.js +27 -15
  16. package/behaviors/connectors.d.ts +17 -0
  17. package/behaviors/connectors.d.ts.map +1 -0
  18. package/behaviors/connectors.js +7 -5
  19. package/behaviors/crosshair.d.ts +42 -0
  20. package/behaviors/crosshair.d.ts.map +1 -0
  21. package/behaviors/crosshair.js +23 -6
  22. package/behaviors/dialog.d.ts +20 -0
  23. package/behaviors/dialog.d.ts.map +1 -0
  24. package/behaviors/dialog.js +6 -2
  25. package/behaviors/disclosure.d.ts +10 -0
  26. package/behaviors/disclosure.d.ts.map +1 -0
  27. package/behaviors/disclosure.js +6 -2
  28. package/behaviors/dismissible.d.ts +10 -0
  29. package/behaviors/dismissible.d.ts.map +1 -0
  30. package/behaviors/dismissible.js +6 -2
  31. package/behaviors/forms.d.ts +27 -0
  32. package/behaviors/forms.d.ts.map +1 -0
  33. package/behaviors/forms.js +54 -13
  34. package/behaviors/glyph.d.ts +14 -0
  35. package/behaviors/glyph.d.ts.map +1 -0
  36. package/behaviors/glyph.js +28 -5
  37. package/behaviors/index.d.ts +31 -237
  38. package/behaviors/index.d.ts.map +1 -0
  39. package/behaviors/index.js +17 -0
  40. package/behaviors/inert.d.ts +20 -0
  41. package/behaviors/inert.d.ts.map +1 -0
  42. package/behaviors/inert.js +46 -0
  43. package/behaviors/internal.d.ts +25 -0
  44. package/behaviors/internal.d.ts.map +1 -0
  45. package/behaviors/internal.js +77 -1
  46. package/behaviors/legend.d.ts +35 -0
  47. package/behaviors/legend.d.ts.map +1 -0
  48. package/behaviors/legend.js +32 -2
  49. package/behaviors/menu.d.ts +16 -0
  50. package/behaviors/menu.d.ts.map +1 -0
  51. package/behaviors/menu.js +6 -2
  52. package/behaviors/modal.d.ts +41 -0
  53. package/behaviors/modal.d.ts.map +1 -0
  54. package/behaviors/modal.js +124 -0
  55. package/behaviors/popover.d.ts +28 -0
  56. package/behaviors/popover.d.ts.map +1 -0
  57. package/behaviors/popover.js +78 -7
  58. package/behaviors/spotlight.d.ts +17 -0
  59. package/behaviors/spotlight.d.ts.map +1 -0
  60. package/behaviors/spotlight.js +7 -5
  61. package/behaviors/table.d.ts +36 -0
  62. package/behaviors/table.d.ts.map +1 -0
  63. package/behaviors/table.js +84 -17
  64. package/behaviors/tabs.d.ts +20 -0
  65. package/behaviors/tabs.d.ts.map +1 -0
  66. package/behaviors/tabs.js +17 -14
  67. package/behaviors/theme.d.ts +54 -0
  68. package/behaviors/theme.d.ts.map +1 -0
  69. package/behaviors/theme.js +22 -3
  70. package/behaviors/toast.d.ts +49 -0
  71. package/behaviors/toast.d.ts.map +1 -0
  72. package/behaviors/toast.js +47 -3
  73. package/classes/classes.json +2527 -0
  74. package/classes/index.d.ts +134 -15
  75. package/classes/index.js +280 -80
  76. package/classes/vscode.css-custom-data.json +12 -0
  77. package/connectors/index.d.ts +201 -69
  78. package/connectors/index.d.ts.map +1 -0
  79. package/connectors/index.js +142 -25
  80. package/css/app.css +69 -13
  81. package/css/base.css +15 -10
  82. package/css/bullet.css +108 -0
  83. package/css/code.css +98 -0
  84. package/css/connectors.css +17 -0
  85. package/css/content.css +22 -3
  86. package/css/crosshair.css +7 -7
  87. package/css/dataviz.css +5 -1
  88. package/css/diff.css +153 -0
  89. package/css/disclosure.css +53 -7
  90. package/css/dots.css +94 -7
  91. package/css/feedback.css +97 -7
  92. package/css/forms.css +113 -4
  93. package/css/legend.css +16 -9
  94. package/css/marks.css +38 -8
  95. package/css/motion.css +98 -53
  96. package/css/navigation.css +7 -0
  97. package/css/overlay.css +90 -3
  98. package/css/primitives.css +158 -13
  99. package/css/report.css +73 -56
  100. package/css/sidenote.css +67 -0
  101. package/css/site.css +16 -2
  102. package/css/sources.css +43 -1
  103. package/css/spark.css +62 -0
  104. package/css/spotlight.css +1 -1
  105. package/css/table.css +9 -2
  106. package/css/term.css +110 -0
  107. package/css/textref.css +63 -0
  108. package/css/toc.css +91 -0
  109. package/css/tokens.css +49 -1
  110. package/css/tree.css +134 -0
  111. package/css/workbench.css +1 -1
  112. package/dist/bronto.css +1 -1
  113. package/dist/css/analytical.css +1 -1
  114. package/dist/css/app.css +1 -1
  115. package/dist/css/base.css +1 -1
  116. package/dist/css/bullet.css +1 -0
  117. package/dist/css/code.css +1 -0
  118. package/dist/css/connectors.css +1 -1
  119. package/dist/css/content.css +1 -1
  120. package/dist/css/crosshair.css +1 -1
  121. package/dist/css/diff.css +1 -0
  122. package/dist/css/disclosure.css +1 -1
  123. package/dist/css/dots.css +1 -1
  124. package/dist/css/feedback.css +1 -1
  125. package/dist/css/forms.css +1 -1
  126. package/dist/css/legend.css +1 -1
  127. package/dist/css/marks.css +1 -1
  128. package/dist/css/motion.css +1 -1
  129. package/dist/css/navigation.css +1 -1
  130. package/dist/css/overlay.css +1 -1
  131. package/dist/css/primitives.css +1 -1
  132. package/dist/css/report.css +1 -1
  133. package/dist/css/sidenote.css +1 -0
  134. package/dist/css/site.css +1 -1
  135. package/dist/css/sources.css +1 -1
  136. package/dist/css/spark.css +1 -0
  137. package/dist/css/spotlight.css +1 -1
  138. package/dist/css/table.css +1 -1
  139. package/dist/css/term.css +1 -0
  140. package/dist/css/textref.css +1 -0
  141. package/dist/css/toc.css +1 -0
  142. package/dist/css/tokens.css +1 -1
  143. package/dist/css/tree.css +1 -0
  144. package/dist/css/workbench.css +1 -1
  145. package/docs/adr/0003-theme-model.md +1 -1
  146. package/docs/annotations.md +133 -14
  147. package/docs/architecture.md +49 -6
  148. package/docs/bullet.md +78 -0
  149. package/docs/code.md +76 -0
  150. package/docs/contrast.md +116 -92
  151. package/docs/d2.md +196 -0
  152. package/docs/diff.md +146 -0
  153. package/docs/legends.md +23 -3
  154. package/docs/marks.md +9 -2
  155. package/docs/mermaid.md +169 -0
  156. package/docs/reference.md +201 -26
  157. package/docs/reporting.md +416 -57
  158. package/docs/sidenote.md +64 -0
  159. package/docs/sources.md +27 -0
  160. package/docs/spark.md +78 -0
  161. package/docs/stability.md +10 -2
  162. package/docs/term.md +81 -0
  163. package/docs/textref.md +78 -0
  164. package/docs/theming.md +44 -5
  165. package/docs/toc.md +83 -0
  166. package/docs/tree.md +74 -0
  167. package/docs/usage.md +354 -16
  168. package/docs/vega.md +244 -0
  169. package/docs/workbench.md +7 -1
  170. package/glyphs/glyphs.js +13 -5
  171. package/llms.txt +285 -14
  172. package/package.json +95 -17
  173. package/qwik/index.d.ts +44 -59
  174. package/qwik/index.d.ts.map +1 -0
  175. package/qwik/index.js +65 -3
  176. package/react/index.d.ts +41 -61
  177. package/react/index.d.ts.map +1 -0
  178. package/react/index.js +63 -3
  179. package/solid/index.d.ts +68 -61
  180. package/solid/index.d.ts.map +1 -0
  181. package/solid/index.js +66 -3
  182. package/tokens/d2.d.ts +38 -0
  183. package/tokens/d2.js +71 -0
  184. package/tokens/d2.json +43 -0
  185. package/tokens/index.d.ts +5 -5
  186. package/tokens/index.js +15 -1
  187. package/tokens/index.json +9 -0
  188. package/tokens/mermaid.d.ts +23 -0
  189. package/tokens/mermaid.js +181 -0
  190. package/tokens/mermaid.json +163 -0
  191. package/tokens/resolved.json +45 -1
  192. package/tokens/skins.js +3 -2
  193. package/tokens/tokens.dtcg.json +26 -0
  194. package/tokens/vega.d.ts +34 -0
  195. package/tokens/vega.js +155 -0
  196. package/tokens/vega.json +179 -0
package/docs/legends.md CHANGED
@@ -13,8 +13,9 @@ drifts from the series it describes.
13
13
  ```
14
14
 
15
15
  Bronto **paints and positions** the key; it owns no scales, no data→pixel
16
- mapping, and no series state. Pair it with Bronto's own `.ui-chart` bars, an
17
- SVG/canvas figure, or any external chart engine — the host owns the chart.
16
+ mapping, and no series state. Pair it with any chart — a token-themed inline
17
+ SVG, or an external engine like [Vega-Lite](./vega.md) — the host owns the
18
+ chart.
18
19
 
19
20
  ## What it is not
20
21
 
@@ -47,7 +48,7 @@ Recommended structure: wrap the figure and its key in a `<figure>` with a
47
48
  <li class="ui-legend__item">
48
49
  <span
49
50
  class="ui-legend__swatch"
50
- style="--chart-color: var(--chart-1); --chart-pattern: var(--chart-pattern-1)"
51
+ style="--chart-color: var(--chart-3); --chart-pattern: var(--chart-pattern-3)"
51
52
  aria-hidden="true"
52
53
  ></span>
53
54
  <span class="ui-legend__label">Research</span>
@@ -89,6 +90,25 @@ chart mark uses, or with a `--N` index helper for the categorical palette.
89
90
  `ui-legend__swatch--circle` and `ui-legend__swatch--line` change the chip shape
90
91
  (dot series, line series).
91
92
 
93
+ A `ui-legend__symbol` chip is an `.ui-icon` mask — it needs a `--icon-mask` or it
94
+ paints a solid square, like any [icon](./reference.md). There is **no `--glyph-*`
95
+ token**: build the mask value with
96
+ [`renderGlyph(name, { render: 'mask' })`](./reference.md) from `@ponchia/ui/glyphs`,
97
+ e.g. `el.style.setProperty('--icon-mask', renderGlyph('circle', { render: 'mask' }).match(/--icon-mask:([^"]+)/)[1])`,
98
+ or render the whole chip with `renderGlyph('circle', { render: 'mask', label })` and
99
+ add the `ui-legend__symbol` class to it. And an **interactive** legend entry must be a real
100
+ `<button>` (as in the example below) — a non-button `ui-legend__item` carrying
101
+ `data-series` is not keyboard-reachable.
102
+
103
+ **Keying the de-emphasised series.** In an accent-rationed chart — one mark
104
+ painted with [`brontoVegaAccent`](./vega.md#spending-the-accent), the rest left
105
+ quiet with `brontoVegaNeutral` — the quiet neutral **is** the last categorical
106
+ series, `--chart-8` (`#4d5358`). So a legend that honestly mirrors that chart
107
+ uses `ui-legend__swatch--1` for the highlighted entry and
108
+ `ui-legend__swatch--8` for the "everything else" entry — both are real palette
109
+ tokens, so the key never drifts from the marks and `check:legend` stays happy.
110
+ Don't hand-roll a grey: `--chart-8` is the neutral by construction.
111
+
92
112
  ## Variants
93
113
 
94
114
  | Modifier | Effect |
package/docs/marks.md CHANGED
@@ -44,6 +44,13 @@ Put `.ui-mark` on a `<mark>` so the emphasis is semantic, not just visual.
44
44
  `prefers-reduced-motion` (reduced motion shows the resting full highlight). It
45
45
  applies to the highlight fill, so pair it with the default (no style modifier).
46
46
 
47
+ > **A mark is a behind-text highlight, not a filled chip.** The fill is a
48
+ > low-alpha gradient *behind* the running text, so the text keeps its normal ink
49
+ > and the contrast stays text-on-background — even `ui-mark--accent` is
50
+ > contrast-safe by construction. Don't reach for `--on-accent` here (that ink is
51
+ > for a *solid* accent fill, like a button or a D2 node); a `<mark>` never needs
52
+ > it.
53
+
47
54
  ## Passage bracket — `.ui-bracket-note`
48
55
 
49
56
  Brackets a whole block and optionally labels it — the prose analogue of
@@ -56,8 +63,8 @@ Brackets a whole block and optionally labels it — the prose analogue of
56
63
  </blockquote>
57
64
  ```
58
65
 
59
- Tones: `--accent` (the rationed accent), `--warning`, `--danger`, `--info`. The
60
- default is a neutral bracket.
66
+ Tones: `--accent` (the rationed accent), `--success`, `--warning`, `--danger`,
67
+ `--info`. The default is a neutral bracket.
61
68
 
62
69
  ## Recipes
63
70
 
@@ -0,0 +1,169 @@
1
+ # Mermaid
2
+
3
+ [Mermaid](https://mermaid.js.org) renders diagrams (flowcharts, sequence, pie,
4
+ git, gantt…) from text to **SVG**. `@ponchia/ui` does not render diagrams — it
5
+ **themes** the ones you already have and lets you **annotate** them, the same way
6
+ it dresses any other SVG figure in a report. Two things ship:
7
+
8
+ - `@ponchia/ui/mermaid` — a resolved Mermaid `base` theme, per bronto theme.
9
+ - `@ponchia/ui/mermaid.json` — the same data as plain JSON, for any consumer.
10
+
11
+ Mermaid stays the consumer's renderer. This is config only: bronto never imports
12
+ or runs Mermaid, and Mermaid is **not** a dependency.
13
+
14
+ ## Theme a diagram
15
+
16
+ Mermaid's `base` theme is the only one meant to be customized. Hand it the
17
+ bronto theme variables:
18
+
19
+ ```js
20
+ import mermaid from 'mermaid';
21
+ import { brontoMermaidTheme } from '@ponchia/ui/mermaid';
22
+
23
+ mermaid.initialize(brontoMermaidTheme()); // light
24
+ await mermaid.run();
25
+ ```
26
+
27
+ `brontoMermaidTheme(theme)` returns `{ theme: 'base', themeVariables }` ready to
28
+ spread into `initialize`. Pass `'dark'` for the dark palette, or read the active
29
+ bronto theme:
30
+
31
+ ```js
32
+ const theme = document.documentElement.dataset.theme === 'dark' ? 'dark' : 'light';
33
+ mermaid.initialize(brontoMermaidTheme(theme));
34
+ ```
35
+
36
+ You can also splice the variables into a single diagram via an init directive,
37
+ or read the raw maps (`import { mermaid } from '@ponchia/ui/mermaid'` →
38
+ `{ light, dark }`). For a build step or non-JS host, read
39
+ `@ponchia/ui/mermaid.json` directly.
40
+
41
+ **Over `http(s)`, import the helper from a CDN as an ES module** — no bundler.
42
+ `tokens/mermaid.js` (the `@ponchia/ui/mermaid` entry) has **zero dependencies**,
43
+ so it loads directly as a browser ES module; you get `brontoMermaidTheme(theme)`
44
+ itself, not a frozen object to keep in sync. Pin the package version; this needs
45
+ a real origin (not `file://` — inline or pre-render to SVG there, per the note
46
+ below):
47
+
48
+ ```html
49
+ <script type="module">
50
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
51
+ import { brontoMermaidTheme } from 'https://cdn.jsdelivr.net/npm/@ponchia/ui@VERSION/tokens/mermaid.js';
52
+ mermaid.initialize(brontoMermaidTheme('light'));
53
+ await mermaid.run();
54
+ </script>
55
+ ```
56
+
57
+ > **file:// portability.** A report opened straight from disk (`file://`) cannot
58
+ > `import` the `@ponchia/ui/mermaid` module **nor** `fetch('…/mermaid.json')` —
59
+ > the browser blocks both across the `null`/file origin (CORS), exactly as with
60
+ > [Vega](./vega.md#from-a-cdn-no-bundler). So for a double-clickable or PDF-bound
61
+ > report either **inline the theme variables** (generate the paste-ready literal
62
+ > with `npm run emit:theme mermaid light` / `dark` — guard it from token drift
63
+ > with `npm run emit:theme:check <file>`) or, better, **pre-render to a frozen
64
+ > SVG** with the Mermaid CLI (`mmdc`, below) so there is no runtime at all. Over
65
+ > an `http(s)` origin the `import`/`fetch` forms both work.
66
+
67
+ The result is monochrome surfaces and lines with the rationed accent reserved
68
+ for notes — a diagram that looks like the rest of a bronto surface and
69
+ **re-skins for free** when you change `--accent`, exactly like the chart palette.
70
+
71
+ ### Why resolved colours, not `var(--x)`
72
+
73
+ Mermaid's theming engine derives shades (lighten/darken) from your seed colours,
74
+ so it only understands real colours — a `var(--accent)` string breaks
75
+ derivation. The theme map therefore ships **resolved hex/rgba per theme**,
76
+ projected from the same token source that feeds
77
+ [`tokens/resolved.json`](./architecture.md) and `charts.json`. That projection
78
+ is the bridge a CSS-first system needs until Mermaid can read CSS variables
79
+ directly. It also means the theme is **static per theme**: on a light/dark
80
+ switch, re-`initialize` with the other palette and re-render.
81
+
82
+ ### Which diagrams get the palette
83
+
84
+ - **Chart-like** diagrams carry a categorical series palette — **pie**
85
+ (`pie1`…`pie12`), **git** (`git0`…`git7`), and **user-journey**
86
+ (`fillType0`…`fillType7`) are wired to the CVD-safe
87
+ [charts palette](./legends.md) (series 1 = the live accent).
88
+ - **Structural** diagrams — flowchart, sequence, class, ER, state — use the
89
+ monochrome node/edge/cluster grammar and spend the accent only on notes.
90
+ - **Not themed: `gantt` and `timeline`.** Their colours come from
91
+ diagram-specific slots (`taskBkgColor`, `sectionBkgColor*`, `gridColor`,
92
+ `todayLineColor`, …) that the base `themeVariables` map does **not** set, so a
93
+ gantt/timeline renders with Mermaid's own off-brand defaults (red/grey bars),
94
+ not the bronto palette. For a **report timeline**, prefer the native,
95
+ fully-themed [`ui-timeline`](./reporting.md) primitive (it also prints and
96
+ needs no renderer); reach for a Mermaid gantt only when you specifically need
97
+ its scheduling layout, and accept its default colours.
98
+
99
+ Pie wedge labels (`pieSectionTextColor`) sit on arbitrary palette colours; if a
100
+ label is hard to read on a given wedge, prefer a legend or direct labels over
101
+ recolouring.
102
+
103
+ ### Fit to small screens
104
+
105
+ The theme map sets colours, not size — sizing stays Mermaid's. Keep `useMaxWidth`
106
+ on (the default for most diagram types) so each SVG scales to its container
107
+ instead of forcing page-wide horizontal scroll:
108
+
109
+ ```js
110
+ mermaid.initialize({
111
+ ...brontoMermaidTheme(theme),
112
+ flowchart: { useMaxWidth: true },
113
+ sequence: { useMaxWidth: true },
114
+ });
115
+ ```
116
+
117
+ A genuinely wide diagram (a long flowchart, a big ER) can still be unreadable
118
+ once squeezed onto a phone. Rather than let it overflow the page, wrap the render
119
+ in a scroll container so the *diagram* scrolls, not the document — the same
120
+ pattern the report layer uses for wide figures and tables:
121
+
122
+ ```css
123
+ .diagram-scroll {
124
+ overflow-x: auto;
125
+ }
126
+ ```
127
+
128
+ ## Annotate a diagram
129
+
130
+ Mermaid output is SVG, and the [annotation layer](./annotations.md) is
131
+ renderer-agnostic SVG — so a `<g class="ui-annotation">` callout composes onto a
132
+ rendered diagram the same as onto any figure. bronto supplies the geometry and
133
+ the styling; **placing a callout on a specific node is yours**, because that
134
+ means reading Mermaid's laid-out coordinates, which bronto deliberately does not
135
+ own (no scales, no DOM, no hit-testing — see [annotations.md](./annotations.md)).
136
+
137
+ The robust path is **build-time**, mirroring the
138
+ [static-report recipe](./annotations.md#using-the-helpers-in-a-static-no-js-report):
139
+
140
+ 1. Pre-render the diagram to a frozen SVG with the Mermaid CLI
141
+ (`mmdc -t base -i diagram.mmd -o diagram.svg`, feeding the same
142
+ `themeVariables`).
143
+ 2. From that SVG, read the target node's box (`getBBox()` / the node's
144
+ `transform`), accounting for the diagram's root `<g>` translate and the
145
+ `viewBox`.
146
+ 3. Compute the callout strings with `@ponchia/ui/annotations` and paste a
147
+ `<g class="ui-annotation …">` into the SVG at those coordinates.
148
+
149
+ The output is a static, on-brand, annotated SVG with no runtime — ideal for the
150
+ [report layer](./reporting.md).
151
+
152
+ To annotate a **live** client render instead, run the same measure-and-inject
153
+ pass on the SVG returned by `mermaid.render()`, after it is in the DOM. Two
154
+ honest caveats, both inherent to overlaying a foreign renderer (not bronto
155
+ limitations):
156
+
157
+ - **Mermaid's internal SVG structure is not a public contract.** Node ids and
158
+ classes are undocumented and have changed across major versions. Match nodes
159
+ by your own author-supplied id substring, measure positions rather than
160
+ hard-coding them, and **pin your Mermaid version**.
161
+ - **Every re-render replaces the SVG**, discarding injected overlays. Re-apply
162
+ the annotation pass after each `render()` / theme switch / resize.
163
+
164
+ ## Scope
165
+
166
+ bronto owns the theme map (gated: every value resolves to a colour, both themes,
167
+ no `var()` leaks) and the annotation geometry. It does **not** own Mermaid's
168
+ rendering, its internal DOM, or its re-render lifecycle — those stay Mermaid's,
169
+ and the overlay above is a documented composition, not a shipped runtime binding.
package/docs/reference.md CHANGED
@@ -9,8 +9,11 @@ rendering of every class is the kitchen-sink demo:
9
9
  **<https://ponchia.github.io/bronto-ui/>**. Theming knobs and the token
10
10
  contract: [docs/theming.md](theming.md).
11
11
 
12
- - 474 classes across 148 component groups
12
+ - 529 classes across 161 component groups
13
13
  - Import the typed registry: `import { cls, ui, cx } from '@ponchia/ui/classes'`
14
+ - Validate markup as data (no JS/TS): `@ponchia/ui/classes.json` — the same
15
+ vocabulary as language-neutral JSON (`groups`, `classes`, `states`,
16
+ `customProperties`), for an external linter or non-JS host
14
17
  - Tokens as data: `import { cssVars, tokens, themeColor } from '@ponchia/ui/tokens'`
15
18
 
16
19
  ## Classes
@@ -34,7 +37,7 @@ each one matches a real selector in the stylesheet.
34
37
  | --- | --- | --- |
35
38
  | `cls.alert` | `ui-alert` | base |
36
39
  | `cls.alertBody` | `ui-alert__body` | part |
37
- | `cls.alertDismiss` | `ui-alert__dismiss` | part |
40
+ | `cls.alertClose` | `ui-alert__close` | part |
38
41
  | `cls.alertTitle` | `ui-alert__title` | part |
39
42
  | `cls.alertAccent` | `ui-alert--accent` | modifier |
40
43
  | `cls.alertDanger` | `ui-alert--danger` | modifier |
@@ -162,7 +165,6 @@ each one matches a real selector in the stylesheet.
162
165
  | `cls.appRailAccount` | `ui-app-rail__account` | part |
163
166
  | `cls.appRailBrand` | `ui-app-rail__brand` | part |
164
167
  | `cls.appRailFoot` | `ui-app-rail__foot` | part |
165
- | `cls.appRailToggle` | `ui-app-rail__toggle` | part |
166
168
 
167
169
  ### `.ui-app-shell`
168
170
 
@@ -221,6 +223,7 @@ each one matches a real selector in the stylesheet.
221
223
  | `cls.bracketNoteAccent` | `ui-bracket-note--accent` | modifier |
222
224
  | `cls.bracketNoteDanger` | `ui-bracket-note--danger` | modifier |
223
225
  | `cls.bracketNoteInfo` | `ui-bracket-note--info` | modifier |
226
+ | `cls.bracketNoteSuccess` | `ui-bracket-note--success` | modifier |
224
227
  | `cls.bracketNoteWarning` | `ui-bracket-note--warning` | modifier |
225
228
 
226
229
  ### `.ui-breadcrumb`
@@ -242,6 +245,18 @@ each one matches a real selector in the stylesheet.
242
245
  | --- | --- | --- |
243
246
  | `cls.breakBefore` | `ui-break-before` | base |
244
247
 
248
+ ### `.ui-bullet`
249
+
250
+ | Registry key | Class | Kind |
251
+ | --- | --- | --- |
252
+ | `cls.bullet` | `ui-bullet` | base |
253
+ | `cls.bulletLabel` | `ui-bullet__label` | part |
254
+ | `cls.bulletMeasure` | `ui-bullet__measure` | part |
255
+ | `cls.bulletMeasureAccent` | `ui-bullet__measure--accent` | modifier |
256
+ | `cls.bulletMeasureNeg` | `ui-bullet__measure--neg` | modifier |
257
+ | `cls.bulletMeasurePos` | `ui-bullet__measure--pos` | modifier |
258
+ | `cls.bulletTarget` | `ui-bullet__target` | part |
259
+
245
260
  ### `.ui-button`
246
261
 
247
262
  | Registry key | Class | Kind |
@@ -289,19 +304,6 @@ each one matches a real selector in the stylesheet.
289
304
  | --- | --- | --- |
290
305
  | `cls.center` | `ui-center` | base |
291
306
 
292
- ### `.ui-chart`
293
-
294
- | Registry key | Class | Kind |
295
- | --- | --- | --- |
296
- | `cls.chart` | `ui-chart` | base |
297
- | `cls.chartBar` | `ui-chart__bar` | part |
298
- | `cls.chartCaption` | `ui-chart__caption` | part |
299
- | `cls.chartFallback` | `ui-chart__fallback` | part |
300
- | `cls.chartFill` | `ui-chart__fill` | part |
301
- | `cls.chartLabel` | `ui-chart__label` | part |
302
- | `cls.chartPlot` | `ui-chart__plot` | part |
303
- | `cls.chartTrack` | `ui-chart__track` | part |
304
-
305
307
  ### `.ui-check`
306
308
 
307
309
  | Registry key | Class | Kind |
@@ -329,6 +331,19 @@ each one matches a real selector in the stylesheet.
329
331
  | `cls.cluster` | `ui-cluster` | base |
330
332
  | `cls.clusterBetween` | `ui-cluster--between` | modifier |
331
333
 
334
+ ### `.ui-code`
335
+
336
+ | Registry key | Class | Kind |
337
+ | --- | --- | --- |
338
+ | `cls.code` | `ui-code` | base |
339
+ | `cls.codeBody` | `ui-code__body` | part |
340
+ | `cls.codeHead` | `ui-code__head` | part |
341
+ | `cls.codeLine` | `ui-code__line` | part |
342
+ | `cls.codeLineAdd` | `ui-code__line--add` | modifier |
343
+ | `cls.codeLineHl` | `ui-code__line--hl` | modifier |
344
+ | `cls.codeLineRemove` | `ui-code__line--remove` | modifier |
345
+ | `cls.codeNumbered` | `ui-code--numbered` | modifier |
346
+
332
347
  ### `.ui-combobox`
333
348
 
334
349
  | Registry key | Class | Kind |
@@ -352,6 +367,15 @@ each one matches a real selector in the stylesheet.
352
367
  | `cls.commandMeta` | `ui-command__meta` | part |
353
368
  | `cls.commandShortcut` | `ui-command__shortcut` | part |
354
369
 
370
+ ### `.ui-compare`
371
+
372
+ | Registry key | Class | Kind |
373
+ | --- | --- | --- |
374
+ | `cls.compare` | `ui-compare` | base |
375
+ | `cls.compareCol` | `ui-compare__col` | part |
376
+ | `cls.compareHead` | `ui-compare__head` | part |
377
+ | `cls.compare2up` | `ui-compare--2up` | modifier |
378
+
355
379
  ### `.ui-connector`
356
380
 
357
381
  | Registry key | Class | Kind |
@@ -393,6 +417,38 @@ each one matches a real selector in the stylesheet.
393
417
  | `cls.crosshairLineY` | `ui-crosshair__line--y` | modifier |
394
418
  | `cls.crosshairMuted` | `ui-crosshair--muted` | modifier |
395
419
 
420
+ ### `.ui-def`
421
+
422
+ | Registry key | Class | Kind |
423
+ | --- | --- | --- |
424
+ | `cls.def` | `ui-def` | base |
425
+
426
+ ### `.ui-delta`
427
+
428
+ | Registry key | Class | Kind |
429
+ | --- | --- | --- |
430
+ | `cls.delta` | `ui-delta` | base |
431
+ | `cls.deltaDown` | `ui-delta--down` | modifier |
432
+ | `cls.deltaFlat` | `ui-delta--flat` | modifier |
433
+ | `cls.deltaInvert` | `ui-delta--invert` | modifier |
434
+ | `cls.deltaUp` | `ui-delta--up` | modifier |
435
+
436
+ ### `.ui-diff`
437
+
438
+ | Registry key | Class | Kind |
439
+ | --- | --- | --- |
440
+ | `cls.diff` | `ui-diff` | base |
441
+ | `cls.diffCode` | `ui-diff__code` | part |
442
+ | `cls.diffHead` | `ui-diff__head` | part |
443
+ | `cls.diffHunk` | `ui-diff__hunk` | part |
444
+ | `cls.diffLn` | `ui-diff__ln` | part |
445
+ | `cls.diffPane` | `ui-diff__pane` | part |
446
+ | `cls.diffRow` | `ui-diff__row` | part |
447
+ | `cls.diffRowAdd` | `ui-diff__row--add` | modifier |
448
+ | `cls.diffRowContext` | `ui-diff__row--context` | modifier |
449
+ | `cls.diffRowRemove` | `ui-diff__row--remove` | modifier |
450
+ | `cls.diffSplit` | `ui-diff--split` | modifier |
451
+
396
452
  ### `.ui-display`
397
453
 
398
454
  | Registry key | Class | Kind |
@@ -510,6 +566,14 @@ each one matches a real selector in the stylesheet.
510
566
  | `cls.generated` | `ui-generated` | base |
511
567
  | `cls.generatedLabel` | `ui-generated__label` | part |
512
568
 
569
+ ### `.ui-glossary`
570
+
571
+ | Registry key | Class | Kind |
572
+ | --- | --- | --- |
573
+ | `cls.glossary` | `ui-glossary` | base |
574
+ | `cls.glossaryDef` | `ui-glossary__def` | part |
575
+ | `cls.glossaryTerm` | `ui-glossary__term` | part |
576
+
513
577
  ### `.ui-grid`
514
578
 
515
579
  | Registry key | Class | Kind |
@@ -556,7 +620,7 @@ each one matches a real selector in the stylesheet.
556
620
  | --- | --- | --- |
557
621
  | `cls.inspector` | `ui-inspector` | base |
558
622
  | `cls.inspectorBody` | `ui-inspector__body` | part |
559
- | `cls.inspectorHeader` | `ui-inspector__header` | part |
623
+ | `cls.inspectorHead` | `ui-inspector__head` | part |
560
624
 
561
625
  ### `.ui-kbd`
562
626
 
@@ -630,6 +694,12 @@ each one matches a real selector in the stylesheet.
630
694
  | `cls.linkArrow` | `ui-link--arrow` | modifier |
631
695
  | `cls.linkCta` | `ui-link--cta` | modifier |
632
696
 
697
+ ### `.ui-marginnote`
698
+
699
+ | Registry key | Class | Kind |
700
+ | --- | --- | --- |
701
+ | `cls.marginnote` | `ui-marginnote` | base |
702
+
633
703
  ### `.ui-mark`
634
704
 
635
705
  | Registry key | Class | Kind |
@@ -680,8 +750,12 @@ each one matches a real selector in the stylesheet.
680
750
  | --- | --- | --- |
681
751
  | `cls.meter` | `ui-meter` | base |
682
752
  | `cls.meterFill` | `ui-meter__fill` | part |
753
+ | `cls.meterLabel` | `ui-meter__label` | part |
754
+ | `cls.meterRow` | `ui-meter__row` | part |
755
+ | `cls.meterValue` | `ui-meter__value` | part |
683
756
  | `cls.meterAccent` | `ui-meter--accent` | modifier |
684
757
  | `cls.meterDanger` | `ui-meter--danger` | modifier |
758
+ | `cls.meterInfo` | `ui-meter--info` | modifier |
685
759
  | `cls.meterSuccess` | `ui-meter--success` | modifier |
686
760
  | `cls.meterWarning` | `ui-meter--warning` | modifier |
687
761
 
@@ -840,7 +914,7 @@ each one matches a real selector in the stylesheet.
840
914
  | `cls.reportFigure` | `ui-report__figure` | part |
841
915
  | `cls.reportFinding` | `ui-report__finding` | part |
842
916
  | `cls.reportFootnotes` | `ui-report__footnotes` | part |
843
- | `cls.reportHeader` | `ui-report__header` | part |
917
+ | `cls.reportHead` | `ui-report__head` | part |
844
918
  | `cls.reportMeta` | `ui-report__meta` | part |
845
919
  | `cls.reportSection` | `ui-report__section` | part |
846
920
  | `cls.reportSectionUnnumbered` | `ui-report__section--unnumbered` | modifier |
@@ -926,6 +1000,13 @@ each one matches a real selector in the stylesheet.
926
1000
  | --- | --- | --- |
927
1001
  | `cls.sidebar` | `ui-sidebar` | base |
928
1002
 
1003
+ ### `.ui-sidenote`
1004
+
1005
+ | Registry key | Class | Kind |
1006
+ | --- | --- | --- |
1007
+ | `cls.sidenote` | `ui-sidenote` | base |
1008
+ | `cls.sidenoteRef` | `ui-sidenote__ref` | part |
1009
+
929
1010
  ### `.ui-sitefooter`
930
1011
 
931
1012
  | Registry key | Class | Kind |
@@ -985,6 +1066,16 @@ each one matches a real selector in the stylesheet.
985
1066
  | `cls.sourceList` | `ui-source-list` | base |
986
1067
  | `cls.sourceListItem` | `ui-source-list__item` | part |
987
1068
 
1069
+ ### `.ui-spark`
1070
+
1071
+ | Registry key | Class | Kind |
1072
+ | --- | --- | --- |
1073
+ | `cls.spark` | `ui-spark` | base |
1074
+ | `cls.sparkBar` | `ui-spark__bar` | part |
1075
+ | `cls.sparkBarAccent` | `ui-spark__bar--accent` | modifier |
1076
+ | `cls.sparkBarNeg` | `ui-spark__bar--neg` | modifier |
1077
+ | `cls.sparkBarPos` | `ui-spark__bar--pos` | modifier |
1078
+
988
1079
  ### `.ui-spinner`
989
1080
 
990
1081
  | Registry key | Class | Kind |
@@ -1003,6 +1094,7 @@ each one matches a real selector in the stylesheet.
1003
1094
 
1004
1095
  | Registry key | Class | Kind |
1005
1096
  | --- | --- | --- |
1097
+ | `cls.src` | `ui-src` | base |
1006
1098
  | `cls.srcConflict` | `ui-src--conflict` | modifier |
1007
1099
  | `cls.srcGenerated` | `ui-src--generated` | modifier |
1008
1100
  | `cls.srcReviewed` | `ui-src--reviewed` | modifier |
@@ -1115,7 +1207,6 @@ each one matches a real selector in the stylesheet.
1115
1207
  | `cls.tableComfortable` | `ui-table--comfortable` | modifier |
1116
1208
  | `cls.tableDense` | `ui-table--dense` | modifier |
1117
1209
  | `cls.tableLined` | `ui-table--lined` | modifier |
1118
- | `cls.tableLoading` | `ui-table--loading` | modifier |
1119
1210
  | `cls.tableSelectable` | `ui-table--selectable` | modifier |
1120
1211
 
1121
1212
  ### `.ui-table-wrap`
@@ -1123,6 +1214,7 @@ each one matches a real selector in the stylesheet.
1123
1214
  | Registry key | Class | Kind |
1124
1215
  | --- | --- | --- |
1125
1216
  | `cls.tableWrap` | `ui-table-wrap` | base |
1217
+ | `cls.tableLoading` | `ui-table-wrap--loading` | modifier |
1126
1218
 
1127
1219
  ### `.ui-tabs`
1128
1220
 
@@ -1145,12 +1237,24 @@ each one matches a real selector in the stylesheet.
1145
1237
  | --- | --- | --- |
1146
1238
  | `cls.tags` | `ui-tags` | base |
1147
1239
 
1240
+ ### `.ui-term`
1241
+
1242
+ | Registry key | Class | Kind |
1243
+ | --- | --- | --- |
1244
+ | `cls.term` | `ui-term` | base |
1245
+
1148
1246
  ### `.ui-textarea`
1149
1247
 
1150
1248
  | Registry key | Class | Kind |
1151
1249
  | --- | --- | --- |
1152
1250
  | `cls.textarea` | `ui-textarea` | base |
1153
1251
 
1252
+ ### `.ui-textref`
1253
+
1254
+ | Registry key | Class | Kind |
1255
+ | --- | --- | --- |
1256
+ | `cls.textref` | `ui-textref` | base |
1257
+
1154
1258
  ### `.ui-themetoggle`
1155
1259
 
1156
1260
  | Registry key | Class | Kind |
@@ -1189,6 +1293,15 @@ each one matches a real selector in the stylesheet.
1189
1293
  | `cls.toastStack` | `ui-toast-stack` | base |
1190
1294
  | `cls.toastStackAssertive` | `ui-toast-stack--assertive` | modifier |
1191
1295
 
1296
+ ### `.ui-toc`
1297
+
1298
+ | Registry key | Class | Kind |
1299
+ | --- | --- | --- |
1300
+ | `cls.toc` | `ui-toc` | base |
1301
+ | `cls.tocLink` | `ui-toc__link` | part |
1302
+ | `cls.tocList` | `ui-toc__list` | part |
1303
+ | `cls.tocTitle` | `ui-toc__title` | part |
1304
+
1192
1305
  ### `.ui-tool-call`
1193
1306
 
1194
1307
  | Registry key | Class | Kind |
@@ -1221,6 +1334,16 @@ each one matches a real selector in the stylesheet.
1221
1334
  | `cls.tourNoteStep` | `ui-tour-note__step` | part |
1222
1335
  | `cls.tourNoteTitle` | `ui-tour-note__title` | part |
1223
1336
 
1337
+ ### `.ui-tree`
1338
+
1339
+ | Registry key | Class | Kind |
1340
+ | --- | --- | --- |
1341
+ | `cls.tree` | `ui-tree` | base |
1342
+ | `cls.treeBranch` | `ui-tree__branch` | part |
1343
+ | `cls.treeLabel` | `ui-tree__label` | part |
1344
+ | `cls.treeLeaf` | `ui-tree__leaf` | part |
1345
+ | `cls.treeSummary` | `ui-tree__summary` | part |
1346
+
1224
1347
  ### `.ui-visually-hidden`
1225
1348
 
1226
1349
  | Registry key | Class | Kind |
@@ -1244,11 +1367,19 @@ registry consumer should reach for these instead of re-implementing
1244
1367
  | Class | Where | Effect |
1245
1368
  | --- | --- | --- |
1246
1369
  | `.ui-table .is-num` | numeric `<td>`/`<th>` | tabular figures + end-aligned (the canonical numeric cell) |
1247
- | `.ui-table .is-pos` | numeric `<td>` | positive-delta tone |
1248
- | `.ui-table .is-neg` | numeric `<td>` | negative-delta tone |
1370
+ | `.ui-table .is-pos` | numeric `<td>`, `.ui-stat__delta` | positive-delta tone |
1371
+ | `.ui-table .is-neg` | numeric `<td>`, `.ui-stat__delta` | negative-delta tone |
1372
+ | `.ui-table .is-key` | `<td>`/`<th>` | emphasised key column |
1249
1373
 
1250
1374
  For numeric text *outside* a table, use the `ui-num` primitive
1251
- (`ui.num({ tone })`), which carries the same tabular/aligned/tone intent.
1375
+ (`ui.num({ tone })`), which carries the same tabular/aligned/tone intent; for
1376
+ a trend figure use `ui-delta` (`ui.delta({ dir, invert })`). The full,
1377
+ machine-readable list of these `is-*` state hooks — and the author-set inline
1378
+ custom properties (`--chart-color`, `--chart-pattern`, `--value`, and the
1379
+ **required** `--icon-mask` on `.ui-icon` and `--ui-vt-name` on `.ui-vt` —
1380
+ without which those classes render a solid square / do nothing) — is in
1381
+ [`@ponchia/ui/classes.json`](../classes/classes.json)
1382
+ (`states` / `customProperties`).
1252
1383
 
1253
1384
  ## Composition & state (read before re-implementing glue)
1254
1385
 
@@ -1264,18 +1395,58 @@ works in any framework without a binding layer:
1264
1395
  - **Button loading** — set `aria-busy="true"` (and `disabled`) on
1265
1396
  `ui-button`; the leading spinner is injected by CSS with no extra
1266
1397
  markup or class. `ui-button--sm`/`--lg` size it.
1267
- - **Badge tone** — `ui.badge({ tone })` emits the framework tone
1268
- (`accent|success|warning|danger|info|muted`). Mapping an app's own variant
1398
+ - **Badge tone** — `ui.badge({ tone })` emits the badge tone
1399
+ (`accent|success|warning|danger|info|muted`). The set is badge-specific, not a
1400
+ universal vocabulary — `muted` is a badge/neutral tone, absent from the status
1401
+ families (`ui-alert`/`ui-toast`/`ui-meter`/`ui-dot`); the builders warn on an
1402
+ out-of-set tone (see usage.md). Mapping an app's own variant
1269
1403
  vocabulary onto a tone is application logic, not a framework class.
1270
1404
  - **Modal** — native `<dialog>` gets backdrop + top-layer + focus-trap
1271
1405
  free. For a controlled/portal modal, add `is-open`
1272
1406
  (`ui.modal({ open: true })`) for the same skin/layout; the
1273
- backdrop and focus-trap are then yours.
1407
+ backdrop, top-layer stacking AND focus-trap are then yours (`.is-open`
1408
+ is a bare grid — it does not float or stack on its own).
1409
+ - **Current page** — mark the active link with `aria-current="page"`; it is
1410
+ the programmatic cue the navs honour (`ui-sitenav`, `ui-app-nav`). The
1411
+ `.is-active` class is the visual-only equivalent on `ui-app-nav`/`ui-tab`;
1412
+ prefer `aria-current` so assistive tech announces the current page.
1413
+ - **Form validation wiring** — `initFormValidation` (`@ponchia/ui/behaviors`)
1414
+ reads these attributes; they ARE the contract, not styling. Markup that omits
1415
+ them renders but the behavior silently no-ops: `data-bronto-validate` on the
1416
+ `<form>`; an optional empty `[data-bronto-error]` node per field (it falls
1417
+ back to the field's `.ui-hint`, restoring the help text when valid again); a
1418
+ `[data-bronto-error-summary]` (`.ui-error-summary`) block. The combobox
1419
+ reads `[data-bronto-combobox]` + per-option `data-value` and emits
1420
+ `bronto:change` (`{ detail: { value, label } }`) on selection — `label` is the
1421
+ chosen option's text, so a live region can announce it without re-reading the DOM;
1422
+ the interactive
1423
+ legend emits `bronto:legend:toggle` (`{ detail: { series, active } }`).
1424
+ - **Status indicator** — `ui-status` carries no dot of its own: compose it with
1425
+ a `.ui-dot` child + a text label, e.g.
1426
+ `<span class="ui-status"><span class="ui-dot ui-dot--success"></span> Live</span>`.
1427
+ (`ui-state` instead bakes in its own dot + the full tone vocabulary — pick
1428
+ one.) A semantic `ui-dot--success|warning|danger|info` is colour-only outside
1429
+ forced-colors, so it ALWAYS needs an adjacent text/aria label — never ship a
1430
+ bare coloured dot as the sole signal.
1431
+ - **Opt-in component CSS** — a few classes are not in the core bundle and need
1432
+ their leaf imported, or they render unstyled: `ui-property`/`ui-readout` →
1433
+ `@ponchia/ui/css/workbench.css`; `ui-mark`/`ui-bracket-note` →
1434
+ `@ponchia/ui/css/marks.css`; the analytical leaves (`ui-annotations`,
1435
+ `ui-crosshair`, `ui-spotlight`, …) → their matching leaf.
1436
+ - **Loaders need their children** — `ui-dotspinner` requires exactly eight
1437
+ `<i>` children, `ui-dotloader` three `<span>`, and a static `ui-dotbar`
1438
+ lights a segment with `<i class="is-on">`. A childless
1439
+ `<span class="ui-dotspinner">` renders nothing.
1440
+ - **`ui-caret` is a typing cursor**, not a dropdown chevron — a blinking block
1441
+ caret. It is **pure CSS** (a `uiBlink` keyframe on `::after`); it needs no
1442
+ behavior — do NOT call `initDotGlyph` to animate it — and it is decorative, so
1443
+ keep it out of the a11y tree (`aria-hidden`). For a disclosure/affordance arrow
1444
+ use `ui-link--arrow` (`ui.link({ arrow: true })`).
1274
1445
 
1275
1446
  ## Tokens
1276
1447
 
1277
1448
  Exact mirror of the `:root` blocks in `css/tokens.css`
1278
- (`check-tokens` enforces parity). DTCG export:
1449
+ (`check-fresh` enforces parity). DTCG export:
1279
1450
  [`@ponchia/ui/tokens.dtcg.json`](../tokens/tokens.dtcg.json).
1280
1451
 
1281
1452
  ### Global (scales — shared by both themes)
@@ -1298,6 +1469,8 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
1298
1469
  | `--sans` | `'Inter', 'SF Pro Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif` |
1299
1470
  | `--dot-font` | `'Doto', var(--mono)` |
1300
1471
  | `--display` | `var(--dot-font)` |
1472
+ | `--display-weight` | `700` |
1473
+ | `--display-weight-strong` | `800` |
1301
1474
  | `--text-2xs` | `0.68rem` |
1302
1475
  | `--text-xs` | `0.76rem` |
1303
1476
  | `--text-sm` | `0.86rem` |
@@ -1371,6 +1544,7 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
1371
1544
  | `--accent-ramp-end` | `#ffffff` |
1372
1545
  | `--accent-strong` | `color-mix(in srgb, var(--accent) 83%, #000)` |
1373
1546
  | `--accent-text` | `var(--accent-strong)` |
1547
+ | `--on-accent` | `var(--button-text)` |
1374
1548
  | `--accent-soft` | `color-mix(in srgb, var(--accent) 10%, transparent)` |
1375
1549
  | `--success` | `#2f7d4f` |
1376
1550
  | `--success-soft` | `rgb(47, 125, 79, 0.12)` |
@@ -1408,6 +1582,7 @@ Exact mirror of the `:root` blocks in `css/tokens.css`
1408
1582
  | `--accent-ramp-end` | `#000000` |
1409
1583
  | `--accent-strong` | `color-mix(in srgb, var(--accent) 84%, #fff)` |
1410
1584
  | `--accent-text` | `var(--accent-strong)` |
1585
+ | `--on-accent` | `var(--button-text)` |
1411
1586
  | `--accent-soft` | `color-mix(in srgb, var(--accent) 14%, transparent)` |
1412
1587
  | `--success` | `#4ec27e` |
1413
1588
  | `--success-soft` | `rgb(78, 194, 126, 0.14)` |