@kerfjs/ui 5.0.0-beta.29 → 5.0.0-beta.30

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 (224) hide show
  1. package/README.md +43 -8
  2. package/ai/application-ui-diagnostic-ids-v1.json +5 -0
  3. package/ai/compile-time-contracts-v1.json +37 -0
  4. package/ai/compile-time-contracts-v1.schema.json +3 -1
  5. package/ai/component-catalog-v2-overrides.json +198 -1
  6. package/ai/component-catalog-v2.d.ts +22 -0
  7. package/ai/component-catalog-v2.json +488 -32
  8. package/ai/component-catalog-v2.schema.json +51 -0
  9. package/ai/component-catalog.json +251 -36
  10. package/ai/component-catalog.schema.json +23 -0
  11. package/ai/public-api-signatures-v1.md +231 -84
  12. package/ai/skill.md +32 -10
  13. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  14. package/analyzer/index.mjs +247 -5
  15. package/dist/app-tab.d.ts +3 -2
  16. package/dist/app-tab.js +2 -1
  17. package/dist/catalog-resources.d.ts +1 -0
  18. package/dist/catalog.d.ts +7 -6
  19. package/dist/catalog.js +8 -7
  20. package/dist/catalog.js.map +1 -1
  21. package/dist/{chunk-PX3YSS5C.js → chunk-6NDBE2OK.js} +1 -1
  22. package/dist/chunk-6NDBE2OK.js.map +1 -0
  23. package/dist/{chunk-B3A3IVO5.js → chunk-AQFWBG23.js} +3 -3
  24. package/dist/chunk-AQFWBG23.js.map +1 -0
  25. package/dist/{chunk-WNWD54GR.js → chunk-B6JYRX3P.js} +4 -2
  26. package/dist/chunk-B6JYRX3P.js.map +1 -0
  27. package/dist/{chunk-HP2B2L26.js → chunk-CAB6NQ2T.js} +1 -1
  28. package/dist/chunk-CAB6NQ2T.js.map +1 -0
  29. package/dist/{chunk-2NMQW7FX.js → chunk-CK6P5AUK.js} +4 -3
  30. package/dist/chunk-CK6P5AUK.js.map +1 -0
  31. package/dist/{chunk-VCE4MPVE.js → chunk-DAO2VFTT.js} +5 -6
  32. package/dist/chunk-DAO2VFTT.js.map +1 -0
  33. package/dist/{chunk-LPOMRC4C.js → chunk-DYBPI5O2.js} +1 -1
  34. package/dist/chunk-DYBPI5O2.js.map +1 -0
  35. package/dist/{chunk-IJBSZ4NX.js → chunk-E34TE2ZI.js} +4 -3
  36. package/dist/chunk-E34TE2ZI.js.map +1 -0
  37. package/dist/{chunk-4EF2CMYS.js → chunk-I45QO2IZ.js} +8 -7
  38. package/dist/chunk-I45QO2IZ.js.map +1 -0
  39. package/dist/{chunk-JRKSK2HX.js → chunk-I4V3UDSA.js} +1 -1
  40. package/dist/chunk-I4V3UDSA.js.map +1 -0
  41. package/dist/{chunk-FEY65TBV.js → chunk-KFUUFNTS.js} +1 -1
  42. package/dist/chunk-KFUUFNTS.js.map +1 -0
  43. package/dist/{chunk-QO55FN2Y.js → chunk-MFR2IIFG.js} +1 -1
  44. package/dist/chunk-MFR2IIFG.js.map +1 -0
  45. package/dist/{chunk-GWEAPEZI.js → chunk-OC275HHS.js} +4 -3
  46. package/dist/chunk-OC275HHS.js.map +1 -0
  47. package/dist/chunk-OL4TC3U2.js +156 -0
  48. package/dist/chunk-OL4TC3U2.js.map +1 -0
  49. package/dist/{chunk-OT6RPYAP.js → chunk-OMSRSL3B.js} +4 -3
  50. package/dist/chunk-OMSRSL3B.js.map +1 -0
  51. package/dist/{chunk-J5BFYY7Q.js → chunk-RL6COPKF.js} +12 -3
  52. package/dist/chunk-RL6COPKF.js.map +1 -0
  53. package/dist/{chunk-TB6DY7H5.js → chunk-SOK5EUF7.js} +1 -1
  54. package/dist/chunk-SOK5EUF7.js.map +1 -0
  55. package/dist/{chunk-RKVQEH4J.js → chunk-T7DOWS6T.js} +3 -3
  56. package/dist/chunk-T7DOWS6T.js.map +1 -0
  57. package/dist/{chunk-7KEUJIIC.js → chunk-TIGSG6BX.js} +1 -1
  58. package/dist/chunk-TIGSG6BX.js.map +1 -0
  59. package/dist/{chunk-W5L2JSBY.js → chunk-UDHHKZWO.js} +6 -5
  60. package/dist/chunk-UDHHKZWO.js.map +1 -0
  61. package/dist/{chunk-R7ZWUN64.js → chunk-V6GQKOX2.js} +4 -3
  62. package/dist/chunk-V6GQKOX2.js.map +1 -0
  63. package/dist/{chunk-KWWR5VMS.js → chunk-V6HCTCVD.js} +4 -3
  64. package/dist/chunk-V6HCTCVD.js.map +1 -0
  65. package/dist/{chunk-JFGXQBIP.js → chunk-VDUJZF5G.js} +76 -13
  66. package/dist/chunk-VDUJZF5G.js.map +1 -0
  67. package/dist/{chunk-SYDMYBPG.js → chunk-VXFGMDA7.js} +1 -1
  68. package/dist/chunk-VXFGMDA7.js.map +1 -0
  69. package/dist/{chunk-YMKH5XTF.js → chunk-WN52USHV.js} +2 -2
  70. package/dist/{chunk-YMKH5XTF.js.map → chunk-WN52USHV.js.map} +1 -1
  71. package/dist/{chunk-OBLTAKSX.js → chunk-WSXUPSID.js} +1 -1
  72. package/dist/chunk-WSXUPSID.js.map +1 -0
  73. package/dist/{chunk-X2U3QJCJ.js → chunk-ZPWZIVI6.js} +1 -1
  74. package/dist/chunk-ZPWZIVI6.js.map +1 -0
  75. package/dist/collapsible-panel.d.ts +5 -2
  76. package/dist/collapsible-panel.js.map +1 -1
  77. package/dist/css-values.d.ts +75 -0
  78. package/dist/css-values.js +3 -0
  79. package/dist/css-values.js.map +1 -0
  80. package/dist/empty-state.d.ts +2 -1
  81. package/dist/empty-state.js +1 -1
  82. package/dist/floating-toolbar.d.ts +4 -3
  83. package/dist/floating-toolbar.js +1 -1
  84. package/dist/index.d.ts +2 -0
  85. package/dist/index.js +26 -25
  86. package/dist/list-action-row.d.ts +1 -2
  87. package/dist/list-action-row.js +2 -1
  88. package/dist/list-header.d.ts +1 -1
  89. package/dist/list-header.js +2 -1
  90. package/dist/list-inset-control.d.ts +4 -3
  91. package/dist/list-inset-control.js +1 -1
  92. package/dist/list-inset-text.d.ts +4 -3
  93. package/dist/list-inset-text.js +1 -1
  94. package/dist/list-item.d.ts +4 -3
  95. package/dist/list-item.js +2 -1
  96. package/dist/list.d.ts +10 -8
  97. package/dist/list.js +2 -1
  98. package/dist/nav-stack.d.ts +9 -6
  99. package/dist/nav-stack.js +2 -1
  100. package/dist/pane.d.ts +6 -5
  101. package/dist/pane.js +1 -1
  102. package/dist/resizable-region.d.ts +2 -1
  103. package/dist/resizable-region.js +1 -1
  104. package/dist/segmented-control.d.ts +4 -3
  105. package/dist/segmented-control.js +2 -1
  106. package/dist/select.d.ts +3 -1
  107. package/dist/select.js +2 -1
  108. package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
  109. package/dist/skeleton.d.ts +7 -6
  110. package/dist/skeleton.js +2 -1
  111. package/dist/split-view.d.ts +5 -4
  112. package/dist/split-view.js +3 -2
  113. package/dist/split-view.js.map +1 -1
  114. package/dist/state-banner.d.ts +3 -2
  115. package/dist/state-banner.js +2 -1
  116. package/dist/styles/catalog.css +8 -1
  117. package/dist/styles/collapsible-panel.css +6 -2
  118. package/dist/styles/foundation.css +44 -0
  119. package/dist/styles/list-header.css +6 -0
  120. package/dist/styles/list-item.css +9 -0
  121. package/dist/styles/nav-stack.css +32 -2
  122. package/dist/styles/segmented-control.css +8 -1
  123. package/dist/styles/select.css +2 -1
  124. package/dist/styles/state-banner.css +14 -0
  125. package/dist/styles/tab-scaffold.css +1 -0
  126. package/dist/styles/token-search-field.css +4 -0
  127. package/dist/styles/toolbar-control-group.css +98 -16
  128. package/dist/styles/webawesome.css +22 -0
  129. package/dist/styles/workbench.css +4 -0
  130. package/dist/sunken-panel.d.ts +4 -3
  131. package/dist/sunken-panel.js +1 -1
  132. package/dist/surface-scaffold.d.ts +6 -5
  133. package/dist/surface-scaffold.js +1 -1
  134. package/dist/tab-bar.d.ts +6 -5
  135. package/dist/tab-bar.js +1 -1
  136. package/dist/tab-scaffold.d.ts +2 -1
  137. package/dist/tab-scaffold.js.map +1 -1
  138. package/dist/token-search-field.d.ts +5 -4
  139. package/dist/token-search-field.js +1 -1
  140. package/dist/toolbar-control-group.d.ts +10 -4
  141. package/dist/toolbar-control-group.js +1 -1
  142. package/dist/toolbar-text.js +2 -1
  143. package/dist/toolbar.d.ts +6 -5
  144. package/dist/toolbar.js +1 -1
  145. package/dist/value-table.d.ts +4 -2
  146. package/dist/value-table.js +2 -1
  147. package/dist/wire-nav-stack.d.ts +4 -1
  148. package/dist/wire-nav-stack.js +125 -0
  149. package/dist/wire-nav-stack.js.map +1 -1
  150. package/dist/wire-resizable-regions.js +1 -1
  151. package/dist/wire-tab-bars.d.ts +1 -0
  152. package/dist/wire-token-search-fields.js +1 -1
  153. package/dist/workbench.d.ts +7 -4
  154. package/dist/workbench.js.map +1 -1
  155. package/docs/accessibility.md +9 -3
  156. package/docs/collapsible-panel.md +4 -1
  157. package/docs/component-contract.md +56 -8
  158. package/docs/component-selection.md +45 -8
  159. package/docs/design/templates/list/compact-dark.svg +1 -1
  160. package/docs/design/templates/list/compact.svg +1 -1
  161. package/docs/design/templates/list/stack-dark.svg +1 -1
  162. package/docs/design/templates/list/stack.svg +1 -1
  163. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  164. package/docs/design/templates/list-action-row/default.svg +1 -1
  165. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  166. package/docs/design/templates/list-action-row/selected.svg +1 -1
  167. package/docs/design/templates/list-action-row-dark.svg +1 -1
  168. package/docs/design/templates/list-action-row.svg +1 -1
  169. package/docs/design/templates/list-dark.svg +1 -1
  170. package/docs/design/templates/list-item/default-dark.svg +1 -1
  171. package/docs/design/templates/list-item/default.svg +1 -1
  172. package/docs/design/templates/list-item/multiline-dark.svg +1 -1
  173. package/docs/design/templates/list-item/multiline.svg +1 -1
  174. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  175. package/docs/design/templates/list-item/selected.svg +1 -1
  176. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  177. package/docs/design/templates/list-item/trailing.svg +1 -1
  178. package/docs/design/templates/list-item-dark.svg +1 -1
  179. package/docs/design/templates/list-item.svg +1 -1
  180. package/docs/design/templates/list.svg +1 -1
  181. package/docs/design-philosophy.md +4 -2
  182. package/docs/examples/component-catalog-extension-v2.json +2 -0
  183. package/docs/layout.md +12 -4
  184. package/docs/nav-stack.md +29 -8
  185. package/docs/recipes.md +8 -4
  186. package/docs/split-view.md +6 -0
  187. package/docs/surface-scaffold.md +8 -0
  188. package/docs/tab-scaffold.md +3 -1
  189. package/docs/type-contracts.md +39 -12
  190. package/docs/ui-analyzer.md +17 -3
  191. package/docs/ui-doctor.md +7 -0
  192. package/docs/ux-demo.md +10 -4
  193. package/docs/webawesome-theme.md +6 -0
  194. package/docs/workbench.md +6 -4
  195. package/llms.txt +46 -6
  196. package/package.json +5 -1
  197. package/ux-demo/recipes/compact-toolbar.tsx +10 -9
  198. package/ux-demo/recipes/composer-form.tsx +6 -3
  199. package/ux-demo/recipes/loading-inspector.tsx +2 -1
  200. package/dist/chunk-2NMQW7FX.js.map +0 -1
  201. package/dist/chunk-4EF2CMYS.js.map +0 -1
  202. package/dist/chunk-7KEUJIIC.js.map +0 -1
  203. package/dist/chunk-B3A3IVO5.js.map +0 -1
  204. package/dist/chunk-FEY65TBV.js.map +0 -1
  205. package/dist/chunk-GWEAPEZI.js.map +0 -1
  206. package/dist/chunk-HP2B2L26.js.map +0 -1
  207. package/dist/chunk-IJBSZ4NX.js.map +0 -1
  208. package/dist/chunk-J5BFYY7Q.js.map +0 -1
  209. package/dist/chunk-JFGXQBIP.js.map +0 -1
  210. package/dist/chunk-JRKSK2HX.js.map +0 -1
  211. package/dist/chunk-KWWR5VMS.js.map +0 -1
  212. package/dist/chunk-LPOMRC4C.js.map +0 -1
  213. package/dist/chunk-OBLTAKSX.js.map +0 -1
  214. package/dist/chunk-OT6RPYAP.js.map +0 -1
  215. package/dist/chunk-PX3YSS5C.js.map +0 -1
  216. package/dist/chunk-QO55FN2Y.js.map +0 -1
  217. package/dist/chunk-R7ZWUN64.js.map +0 -1
  218. package/dist/chunk-RKVQEH4J.js.map +0 -1
  219. package/dist/chunk-SYDMYBPG.js.map +0 -1
  220. package/dist/chunk-TB6DY7H5.js.map +0 -1
  221. package/dist/chunk-VCE4MPVE.js.map +0 -1
  222. package/dist/chunk-W5L2JSBY.js.map +0 -1
  223. package/dist/chunk-WNWD54GR.js.map +0 -1
  224. package/dist/chunk-X2U3QJCJ.js.map +0 -1
@@ -24,10 +24,18 @@ remains authored rather than generated.
24
24
  machine-evaluable composition layer without changing the v1 selection and
25
25
  delivery contract. Every v1 entry projects once, in order, under the stable
26
26
  qualified key `package:id`. Each v2 entry explicitly covers parents/contexts,
27
- named zones and cardinality, child concepts, state ownership, required wiring,
27
+ named zones and cardinality, optional explicit JSX prop bindings, child concepts, state ownership, required wiring,
28
28
  responsive ownership, layout and geometry, accessibility obligations, public
29
29
  CSS boundaries, diagnostics, and provenance.
30
30
 
31
+ An entry's optional `cssValueProps` makes CSS-adjacent prop grammar equally
32
+ machine-evaluable. Each path records the property grammar, finite shorthands,
33
+ canonical versus exceptional spacing choices, standalone and expression-only
34
+ helpers, raw/unsafe policy, and serialization examples. Nested paths use the
35
+ bounded `items[].property` form. Consumer catalogs can publish the same facts;
36
+ ESLint, `kerf-ui-analyze`, and `kerf-ui-doctor` then issue the same stable
37
+ `KUI-L013`–`KUI-L017` feedback for application and third-party components.
38
+
31
39
  The generator starts with permissive defaults. An `any` mode records that the
32
40
  catalog has no defensible prohibition; it does not claim every composition is
33
41
  recommended. Objective rules live in
@@ -35,6 +43,17 @@ recommended. Objective rules live in
35
43
  diagnostics. A tool reports a diagnostic only after proving its exact `when`
36
44
  condition. Subjective choice, product policy, and visual taste remain prose.
37
45
 
46
+ Kerf UI calls component content positions **named `SafeHtml` prop slots**.
47
+ Use `children` for one homogeneous primary region; use explicit named
48
+ `SafeHtml` props for semantic positions or replacement content such as
49
+ `header`, `footer`, `leading`, `trailing`, `icon`, and `action`. These are typed
50
+ function-component props, not native web-component `<slot>` elements and not a
51
+ generic `slots={{...}}` object. A v2 zone declares `jsx.prop` only when tooling
52
+ can soundly bind that zone to one public JSX prop; `children` is spelled
53
+ explicitly. Zones without that binding remain guidance and are never guessed
54
+ from their ids. Static tools inspect only visible JSX structure and leave
55
+ dynamic `SafeHtml` expressions to runtime and accessibility evaluation.
56
+
38
57
  V1 consumers continue unchanged. V2 consumers read v1 for selection/delivery
39
58
  and v2 for composition. `npm run catalog:sync` projects every new component,
40
59
  recipe, and supported Web Awesome entry, and the completeness gate prevents
@@ -140,7 +159,7 @@ claim Kerf delivery paths for them.
140
159
  - Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
141
160
  - Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
142
161
  - A reusable component never owns per-instance mutable module state.
143
- - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; prefer an equivalent prop or token before writing a selector.
162
+ - Consumers style through `--kui-*` semantic tokens and public component classes. Foundation tokens provide opinionated neutral, brand/info, non-status pop, success, warning, and danger fill/border/foreground roles. Stateful components expose local override variables; prefer an equivalent prop or token before writing a selector.
144
163
 
145
164
  `ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
146
165
  `ListHeader.rootAttributes`, `AppTab.rootAttributes`,
@@ -195,7 +214,11 @@ need, request a supported hook instead of inferring one from rendered markup.
195
214
 
196
215
  `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
197
216
  default while retaining the row's 44px minimum interactive target. Multiline
198
- rows align that 18px visual with the first inherited text line.
217
+ rows align that 18px visual with the first inherited text line. The row clips
218
+ descendant painting to its rounded root so labels, status, and dormant trailing
219
+ content cannot escape its visible boundary. Rows with descriptions grow enough
220
+ to keep their owned two-line label stack readable; use `multiline` when the
221
+ primary label should wrap rather than truncate.
199
222
 
200
223
  `DisclosureArrow` uses an 18px root-scaled visual by default. Override
201
224
  `--kui-disclosure-arrow-size` on the component or its containing scope when a
@@ -224,6 +247,13 @@ segmented-control, app-tab, and tab-bar colors likewise use their public
224
247
  hover, and selected-state variables, so rounded, pill, and toolbar presentations
225
248
  remain opinionated but locally overridable.
226
249
 
250
+ Inset hover and selection surfaces follow the outer control shape instead of
251
+ choosing an independent radius. `--kui-layout-highlight-inset` is the full
252
+ distance between those edges; the inner radius is the outer radius minus that
253
+ inset. `ToolbarControlGroup` publishes its derived radius to nested toolbar
254
+ `SegmentedControl` choices, keeping both direct buttons and exclusive-choice
255
+ highlights concentric when the group switches between pill and rounded shapes.
256
+
227
257
  `ResizableRegion` owns the Hot Sheet 2 split treatment: a persistent 1px
228
258
  separator with a compact grip that appears on hover or keyboard focus. Override
229
259
  `--kui-resizable-region-separator-color`,
@@ -238,12 +268,24 @@ Logical-edge separator lines are independently opt-in and default off.
238
268
  `@kerfjs/ui/layout.css` retains the pane roles and supplies the related content
239
269
  geometry classes.
240
270
  `List` is the corresponding layout-only vertical stack: its children stretch by
241
- default, while `gap`, `flex`, and `scrollable` opt into standard/custom spacing,
271
+ default, while `gap`, `flex`, and `scrollable` opt into typed spacing,
242
272
  flex growth, and vertical scroll ownership. `dividerSides` accepts canonical
243
273
  physical top/right/bottom/left combinations such as `tr` and `trbl`; the stack
244
- adds no list semantics, margin, or padding of its own. String props receive
245
- browser CSS, so use `gap="var(--kui-space-2xs)"` for the root-scaled 4px token or
246
- `gap="0.25rem"`; source-only `remify(4px)` is not valid at runtime.
274
+ adds no list semantics, margin, or padding of its own. Use a direct finite
275
+ spacing shorthand such as `gap="2xs"`, or pass a `CssLength` created by the
276
+ CSS-free `@kerfjs/ui/css-values` helpers: `space('m')`, `rem(0.25)`,
277
+ `lengthVar('--app-gap')`, or `calc(plus(rem(0.25), pct(10)))`. `plus` returns a
278
+ non-standalone `CssLengthExpression`; only `calc` turns it into a complete
279
+ length. Raw CSS strings and source-only `remify(4px)` are not valid runtime
280
+ props. The `CssLength` name intentionally includes percentages for UI dimension
281
+ props. Its opaque string brand improves authoring correctness; it is not a CSS
282
+ sanitizer or security boundary.
283
+ `List.flex` likewise accepts its boolean default, finite keywords, or `CssFlex`
284
+ from `flex(grow, shrink, basis)`. `Skeleton` width/height use `CssSize`, radius
285
+ uses `CssLength`, and `SelectChoice.color` uses `CssColor` from `uiColor()` or
286
+ `colorVar()`. Never exchange these property grammars. List rows expose
287
+ `className`, public tokens, and semantic props instead of unrestricted `style`
288
+ declarations.
247
289
  `.kui-content` gives major children 24px vertical separation.
248
290
  `.kui-content-item` gives one child 8px inline margin, a real 1px border,
249
291
  8px padding, and 12px corners; border and background may be transparent without
@@ -255,7 +297,13 @@ groups and inside items. For an ordinary icon/action control inside a group, use
255
297
  a plain `<button>` — the group styles `> button` fully, and it keeps the group
256
298
  free of a Web Awesome dependency and shadow DOM. Reach for `wa-button` only when
257
299
  you need a Web Awesome feature, chiefly the `slot="trigger"` button of a
258
- `wa-dropdown` popup menu. `ListHeader` similarly separates its dormant title and
300
+ `wa-dropdown` popup menu. For a compact mixed-content group, set
301
+ `nestedDropdown`; a text-and-caret trigger grows to its intrinsic width while an
302
+ icon-only trigger can remain square, keeping the separator and caret inside the
303
+ group. The short text trigger has an engine-stable 66px floor because WebKit
304
+ does not include the shadow caret in the custom-element host's intrinsic width;
305
+ raise `--kui-toolbar-dropdown-trigger-width` for longer localized copy.
306
+ `ListHeader` similarly separates its dormant title and
259
307
  optional count or badge from its optional 44px action. Use the mutually
260
308
  exclusive `count`/`countLabel` pair for non-negative safe-integer section
261
309
  quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
@@ -36,6 +36,42 @@ useful subtree. Prefer a component prop or component-specific token when the
36
36
  change belongs to one component or instance, and preserve the documented
37
37
  foreground/background contrast relationships and visible focus ring.
38
38
 
39
+ ### Typed runtime dimensions
40
+
41
+ Use `List` spacing shorthands for the common case: `gap="xs"`, `gap="m"`, and
42
+ the other `UiSpaceName` values resolve to their matching `--kui-space-*` token.
43
+ The canonical rhythm is `none`, `2xs`, `xs`, `m`, and `l`; use `s` and `xl`
44
+ only as deliberate exceptions.
45
+
46
+ When a value cannot be expressed by one spacing step, import the CSS-free
47
+ `@kerfjs/ui/css-values` subpath. `px`, `rem`, `em`, and `pct` create typed
48
+ `CssLength` values; `space` and `lengthVar` reference spacing or
49
+ application-owned length tokens. `plus` creates a non-standalone
50
+ `CssLengthExpression`, so wrap it with `calc` before passing it to `List.gap`:
51
+
52
+ ```tsx
53
+ import { calc, pct, plus, rem, space } from "@kerfjs/ui/css-values";
54
+ import { List } from "@kerfjs/ui/list";
55
+
56
+ <List gap="xs">...</List>;
57
+ <List gap={space("m")}>...</List>;
58
+ <List gap={calc(plus(rem(0.25), pct(10)))}>...</List>;
59
+ ```
60
+
61
+ `CssValue` is the common branded base, not an arbitrary-string constructor.
62
+ Raw strings such as `"0.25rem"` no longer satisfy `List.gap`; this breaking
63
+ contract lands before the 5.0 stable release so misspelled tokens and incomplete
64
+ expressions fail during typechecking rather than in the browser.
65
+
66
+ Other CSS-valued props use distinct contracts: `flex()` creates `CssFlex` for
67
+ `List.flex`; `Skeleton` dimensions take typed lengths (plus finite intrinsic
68
+ keywords for width/height); and `uiColor()`/`colorVar()` create `CssColor` for
69
+ `SelectChoice.color`. Do not substitute one brand for another. Row components
70
+ have no declaration-string `style` prop; use `className`, documented public
71
+ tokens, and semantic component props. Catalog media queries remain strings and
72
+ semantic pixel measurements remain numbers because those are different APIs.
73
+ The corresponding public builders are `flex`, `uiColor`, and `colorVar`.
74
+
39
75
  ## Production recipes
40
76
 
41
77
  Use the [complete recipe guide](./recipes.md) when several primitives form one
@@ -80,17 +116,17 @@ an upstream component or recipe request.
80
116
  | Icon — `LucideIcon` | A decorative or explicitly labeled Lucide-compatible icon belongs in app UI. | Do not use an icon as the only name of an unfamiliar action; add visible or accessible text. Prefer it over Web Awesome `wa-icon`. | None. | Icon choice and meaningful label. | `@kerfjs/ui/lucide-icon` | [Accessibility](./accessibility.md#shared-rules) |
81
117
  | Disclosure indicator — `DisclosureArrow` | A control needs one animated 18px root-scaled visual for open and closed state, including configurable directions or a replacement icon. | Do not use it as the interactive control or accessible name; place it inside the button or control that exposes expanded state. | Pass the controlled `open` state, render it inside the owning control, author replacement icon content facing right before transforms, and override `--kui-disclosure-arrow-size` only when another visual size is required. Direction changes use the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. | Open state, interaction, accessible name, size override, replacement glyph, direction choices, and shortest-path rotation. | `@kerfjs/ui/disclosure-arrow` | [Component ownership](./component-contract.md#ownership-boundaries) |
82
118
  | Application toolbar or heading — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar or a page/panel/dialog heading. | Do not add bespoke heading geometry or a private wrapper; use the same zone contract everywhere. | Put identity/title text directly in a zone as `ToolbarText`; group controls and icon tiles in `ToolbarControlGroup`. | Actions, command availability, responsive relocation, state, and supporting copy below a heading. | `@kerfjs/ui/toolbar` | [Toolbar composition](../README.md#component-subpaths) |
83
- | Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained/borderless chrome, compact/tight geometry, icon/text/mixed/avatar anatomy, selected treatment, or nested dropdown sizing. | Do not use it merely to align unrelated buttons; use toolbar slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; declare typed content and appearance instead of overriding descendants or `::part(base)`; use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
119
+ | Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained/borderless chrome, compact/tight geometry, icon/text/mixed/avatar anatomy, selected treatment, or nested dropdown sizing. | Do not use it merely to align unrelated buttons; use Toolbar's named `SafeHtml` prop slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; declare typed content and appearance instead of overriding descendants or `::part(base)`; use `avatarImage` instead of inserting an `img` (single groups paint the outer group; multi-button groups paint the pressed highlight); use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
84
120
  | Floating controls over content — `FloatingToolbar` | A small cluster of controls (e.g. a drawer restore) must float over scrolling content — distinct and forced-dark — inside a positioned container. | Do not use it for a primary page or panel toolbar (use `Toolbar`), or for anything that must sit above dialogs/overlays — it is not top-layer. | Compose `ToolbarControlGroup`s and delegate their actions; the app owns visibility and position. | Controls, visibility, and position. | `@kerfjs/ui/floating-toolbar` | [Component subpaths](../README.md#component-subpaths) |
85
121
  | Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel`. | Optional `headingLevel` for `role="heading"` + `aria-level`. Defaults to one line, ellipsized when it does not fit; `wrap` flows onto multiple lines, `ellipsis` toggles the trailing …, and `maxLines` caps a wrap. | Text, heading level, overflow behavior, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
86
122
  | Vertical stack — `List` | Rows, sections, or arbitrary components need a consistent vertical stretch layout, optional standard/custom gap, flex growth, one vertical scroll owner, or edge dividers. | It is layout-only and does not provide `ul`/`ol` semantics. Do not nest scroll owners or use it when a horizontal layout is required. | Choose `gap`, `flex`, `scrollable`, and canonical `dividerSides` (`t`, `r`, `b`, `l` combinations in that order); bound the block size when scrolling. | Child semantics/content, containing height, and which optional layout behaviors apply. | `@kerfjs/ui/list` | [Pane geometry](../README.md#pane-and-content-geometry) |
87
- | Navigation row — `ListItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `ListActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
123
+ | Navigation row — `ListItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `ListActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. The rounded root clips overflowing descendants; set `multiline` when the primary label should wrap. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
88
124
  | Navigation row with trailing action — `ListActionRow` | A full-width row needs a selectable primary action and an independently focusable trailing action. | Use `ListItem` when trailing content is dormant metadata. Do not put controls inside the row's `label`, `icon`, or `trailingActionIcon` SafeHtml slots. Do not use `AppTab` outside tablist semantics or `ToolbarControlGroup` outside a toolbar. | Delegate both action strings; update controlled selection and any popover/context-menu state in the app. | Routing, selection, both action policies, domain metadata, and popover/context-menu behavior. | `@kerfjs/ui/list-action-row` | [Accessibility](./accessibility.md#listactionrow) |
89
125
  | Navigation section heading — `ListHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing. Do not shrink its 44px action target to the 18px visual. Do not use it as a page, panel, or dialog title; use a heading `Toolbar`. | Delegate its optional action; the app controls expanded state and revealed content. Toggle mode supplies `DisclosureArrow` unless `actionIcon` replaces it. Use `triggerAttributes` only for domain `data-*` or a native popover relationship. | Section organization, valid count and localized count label, disclosure state and content, non-count badge content, popover target behavior, and policy. | `@kerfjs/ui/list-header` | [Pane geometry](../README.md#pane-and-content-geometry) |
90
126
  | Inset self-bordered control — `ListInsetControl` | A control that owns its own border and padding but no outer margin (a search input, a `SegmentedControl`) must line up inside a `.kui-content` list with the standard 8px inline margins and stretch to fill the row. | Do not wrap a `.kui-content-item` or a `ListItem`/`ListHeader` that already owns its inline margin — that double-insets it. Do not add ad-hoc `margin`/`padding` around a bare control to align it; use this instead. | Place the self-bordered control(s) as children; they stretch to fill. It applies only the inline margin, flex stretch, and 8px gap — the child owns its own border and padding. | The control(s), their state, and action wiring. | `@kerfjs/ui/list-inset-control` | [Pane geometry](../README.md#component-subpaths) |
91
127
  | Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. Pass `horizontalOnly` to keep that horizontal inset but drop the vertical margin, border, and padding for tight text layout. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text` | [Pane geometry](../README.md#component-subpaths) |
92
- | Application column — `Pane` | A sidebar, main area, inspector, or dialog needs shared vertical header/content/footer organization, one scroll owner, and optional edge separators. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Import `Pane`, provide optional fixed header/footer slots around its primary vertical content, and opt into only the needed logical-edge separators; add `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, responsive relocation, pane visibility state, slot semantics, labels, and separator placement. | `@kerfjs/ui/pane` | [Pane anatomy](./layout.md#anatomy) |
93
- | One-pane navigation — `NavStack` | A compact flow pushes into details while keeping earlier views mounted, or a single-pane screen needs the same stable layout contract. | Do not use it when list and detail should remain visible together; use `SplitView`. Do not use it alone for co-equal top-level destinations; use one stack per `TabScaffold` tab. | Keep the ordered view array controlled, import its CSS explicitly, and call `wireNavStack` for back delegation, transitions, and focus restoration. | View keys/content/titles, push and pop actions, focus targets, and optional bottom toolbar. | `@kerfjs/ui/nav-stack` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
128
+ | Application column — `Pane` | A sidebar, main area, inspector, or dialog needs shared vertical header/content/footer organization, one scroll owner, and optional edge separators. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Import `Pane`, use `children` for its homogeneous primary content and the named `SafeHtml` prop slots `header`/`footer` for optional fixed chrome, then opt into only the needed logical-edge separators; add `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, responsive relocation, pane visibility state, slot semantics, labels, and separator placement. | `@kerfjs/ui/pane` | [Pane anatomy](./layout.md#anatomy) |
129
+ | One-pane navigation — `NavStack` | A compact flow pushes into details while keeping earlier views mounted, or a single-pane screen needs the same stable layout contract. | Do not use it when list and detail should remain visible together; use `SplitView`. Do not use it alone for co-equal top-level destinations; use one stack per `TabScaffold` tab. | Keep the ordered view array controlled, put view-specific bottom chrome on each view (or use the component fallback), import its CSS explicitly, and call `wireNavStack` for back delegation, content-slide/chrome-cross-fade transitions, and focus move/restore. Mark a preferred initial target with `data-nav-focus` when DOM order is insufficient. | View keys/content/titles, push and pop actions, preferred initial focus targets, and per-view or persistent bottom toolbar content. | `@kerfjs/ui/nav-stack` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
94
130
  | Responsive list-detail — `SplitView` | A primary list and related detail belong together on roomy devices but become a one-pane drill-down on compact devices. | Do not use it for a single linear flow or a multi-panel editor shell. | Provide controlled selection/detail state and device class; opt into resize wiring only when the separator is user adjustable. | Selection, detail content, compact back action, device policy, and optional persisted width. | `@kerfjs/ui/split-view` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
95
131
  | Compact top-level destinations — `TabScaffold` | A handset or portrait-tablet app has two to five co-equal destinations whose scenes and nested navigation must remain mounted across switches. | Do not use it for document tabs, reorderable work items, or a desktop navigation rail. | Keep the active id controlled, import its CSS explicitly, and call `wireTabScaffold`; commonly place one `NavStack` in each tab scene. | Destination definitions, active id, routing, persistence, and roomy-device replacement. | `@kerfjs/ui/tab-scaffold` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
96
132
  | Desktop multi-panel workspace — `Workbench` | A desktop-class tool needs a central work area plus independently collapsible navigator, inspector, or console regions. | Do not shrink the full shell onto compact devices or use it for one standalone panel. | Render only the required rails/drawer, keep collapse state controlled, and replace peripheral regions with stacks or overlays below desktop sizes. | Panel presence/content, collapsed states, sizes, persistence, responsive replacement, and controls. | `@kerfjs/ui/workbench` | [Workbench](./workbench.md) |
@@ -101,14 +137,14 @@ an upstream component or recipe request.
101
137
  | One application tab — `AppTab` | A controlled app tab needs selection, close, drag, leading/trailing anatomy, compact/segmented/icon-only presentation, label truncation, safe domain metadata, or a product-specific close glyph. | Do not render it alone or use it for a small settings choice; compose in `TabBar`, or use `SegmentedControl`. Keep `closeIcon` noninteractive. | Compose in `TabBar`; let `wireTabBars` manage interaction. Put only domain `data-*` values in `rootAttributes`; use typed appearance props instead of descendant CSS. | Tab identity, order, selection, close policy, content, domain metadata values, and outer placement. | `@kerfjs/ui/app-tab` | [Tabs contract](./accessibility.md#tabs) |
102
138
  | Application tab strip — `TabBar`, `wireTabBars`, `reorderTabs` | Tabs switch page regions and may overflow, close, reorder, fill a segmented inspector strip, or sit beside a trailing action. | Do not use it for a compact local view toggle; use `SegmentedControl`. Do not use it for a long choice list; use `Select`. Prefer it over Web Awesome `wa-tab-group`, `wa-tab`, and `wa-tab-panel` for Kerf app tabs. | Call `wireTabBars` once, retain the disposer, and apply `onReorder` synchronously; `reorderTabs` is the default array helper. Choose typed presentation/allocation props while the parent owns outer placement. | Ordered tabs, selection, panels, routing, closing, persistence, and outer placement. | `@kerfjs/ui/tab-bar` plus `@kerfjs/ui/wire-tab-bars` | [Tabs contract](./accessibility.md#tabs) |
103
139
  | Panel, dialog, or page heading — `Toolbar` + `ToolbarText` | A panel, dialog, or page needs an extra-large title, optional icon, grouped trailing actions, and optional supporting copy. | Do not add a private heading wrapper or bespoke layout. The toolbar supplies structure, not modal behavior; use an application overlay or Web Awesome `wa-dialog` for that behavior. | Connect title/supporting-copy ids to the host, group controls, and delegate actions. **For a page or view title set `headingLevel` (usually `1`)** on `ToolbarText`; omit it for a dialog title referenced by `aria-labelledby`. | Open state, focus lifecycle, dismissal, controls, ids, copy, and heading level. | `@kerfjs/ui/toolbar` + `@kerfjs/ui/toolbar-text` | [Toolbar headings](./accessibility.md#toolbar-headings) |
104
- | Dialog or popup geometry — `DialogSurface`, `PopupSurface` | Recurring Web Awesome dialogs need standard sizes/presentations/body/footer insets, or dropdown menus need list-compatible inset ownership. | Do not use these wrappers as generic layout or to replace native dialog/dropdown behavior. Avoid consumer `::part()` overrides for covered patterns. | Wrap one `wa-dialog` or `wa-dropdown`; choose the typed geometry while retaining native labeling, open state, focus, dismissal, and menu semantics. | State, focus lifecycle, dismissal, labels, content, and outer placement. | `@kerfjs/ui/surface-scaffold` | [Surface scaffolds](./surface-scaffold.md) |
140
+ | Dialog or popup geometry — `DialogSurface`, `PopupSurface` | Recurring Web Awesome dialogs need standard sizes/presentations/body/footer insets, or dropdown menus need list-compatible inset ownership. | Do not use these wrappers as generic layout or to replace native dialog/dropdown behavior. Avoid consumer `::part()` overrides and do not stack a dialog body inset around list-owned child geometry. | Wrap one `wa-dialog` or `wa-dropdown`; choose the typed geometry while retaining native labeling, open state, focus, dismissal, and menu semantics. Compose a dialog body as a `List` by default, use `bodyInset="none"` when its children own list geometry, and wrap bare prose in `ListInsetText`. | State, focus lifecycle, dismissal, labels, content, and outer placement. | `@kerfjs/ui/surface-scaffold` | [Surface scaffolds](./surface-scaffold.md) |
105
141
  | Key/value facts — `ValueTable`, `ValueTableRow` | Read-only labels and values form a semantic definition list, optionally with a leading icon. | Do not use it for editable form fields or a row/column data grid; use native form or table semantics. | Compose typed `ValueTableRow` entries; pass `icon` when a 24px leading icon adds useful context. | Values, formatting, icon meaning, and empty/loading policy. | `@kerfjs/ui/value-table` | [Component ownership](./component-contract.md#ownership-boundaries) |
106
142
  | Indeterminate activity — `LoadingSpinner` | A Kerf surface needs compact, labeled or decorative indeterminate progress. | Do not use it for known progress; use Web Awesome `wa-progress-bar` or `wa-progress-ring`. Direct Web Awesome UI may use `wa-spinner`; do not mix spinner systems within one surface. | None; pass a label when the spinner conveys status. | Loading lifecycle and adjacent status copy. | `@kerfjs/ui/loading-spinner` | [Accessibility](./accessibility.md#shared-rules) |
107
143
  | Loading placeholder — `Skeleton` + a component's `placeholder` prop | A value or a whole component is still loading and should hold its space as a subtle, unanimated block, keeping the layout stable — an inspector or detail view rendering its real chrome with per-record values absent. | Do not use it for known progress (use `LoadingSpinner`), do not animate it, and do not hand-rebuild a component's empty state — set `placeholder` on the component instead. Prefer it over `wa-skeleton`, which the pure-Kerf primitives avoid to stay Web-Awesome-free. | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render skeletons in its value slots with interactivity disabled; use the standalone `Skeleton` for a custom slot. | Loading lifecycle, which slots are unknown, and announcing the loading region. | `@kerfjs/ui/skeleton` | [Accessibility](./accessibility.md#shared-rules) |
108
144
  | Value selection — `Select` | A controlled form, toolbar, or compact navigation value comes from a moderate or long choice list, possibly grouped, icon-bearing, icon-only when closed, or truncating. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once; listen for standard input/change events. Use typed presentation props rather than consumer `::part()` overrides; let the parent own placement. | Controlled value, validation, choices, domain mapping, and outer placement. | `@kerfjs/ui/select` | [Web Awesome integration](../README.md#web-awesome-theme) |
109
145
  | Small exclusive choice — `SegmentedControl` | A few visible choices switch a compact view or setting, with toolbar, rounded, or pill presentation. | Do not use it for tabpanel semantics; use `TabBar`. Do not use it for many choices; use `Select`. Prefer it over `wa-button-group` when the controls select one value. | Delegate its action, read `data-segment-value`, update `value`, and rerender. | Controlled value, labels, action, and persistence. | `@kerfjs/ui/segmented-control` | [SegmentedControl contract](./accessibility.md#segmentedcontrol) |
110
146
  | Structured search editor — `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields` | Free text and ordered, editable, removable filter tokens share one searchbox; enable `collapsible` when an empty, unfocused field should reduce to one iconic action, standalone or in a toolbar group. | Do not use it for ordinary text entry; use a native input or Web Awesome `wa-input`. Do not use it when filters belong in separate form controls. | Read DOM-owned text on input, empty `textContent` on clear, and use `placeTokenSearchCaret` after explicit controlled focus changes. Call `wireTokenSearchFields` from `@kerfjs/ui/wire-token-search-fields` once so Enter submits without adding a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. In `collapsible` mode it also manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse); bind the field's `expanded` to the signal on the returned handle (`handle.expanded(id)`) or adopt your own via `collapsible.signals`, and opt out per behavior only when the app must own it. | Parsing, suggestions, tokens, query execution, results, announcements, and — only if overriding the default — the collapsible `expanded` signal. | `@kerfjs/ui/token-search-field` | [TokenSearchField contract](./accessibility.md#tokensearchfield) |
111
- | Persistent inline status — `StateBanner` | A neutral, info, success, warning, or danger message belongs next to the affected work. | Do not use it for a no-content screen; use `EmptyState`. Do not use it for transient confirmation; use a toast. Web Awesome `wa-callout` is the ecosystem alternative for Web Awesome-owned content. | Delegate an optional action; choose alert urgency only for attention-requiring failure. Use the optional tone-tinted `badge` for a terse count or status beside the title, not as the only expression of meaning. | State mapping, message lifetime, retry/action behavior, badge content, and copy. | `@kerfjs/ui/state-banner` | [Feedback accessibility](./accessibility.md#shared-rules) |
147
+ | Persistent inline status — `StateBanner` | A neutral, info, pop, success, warning, or danger message belongs next to the affected work; pop highlights featured or novel content without implying status. | Do not use pop as a success, warning, or danger substitute. Do not use StateBanner for a no-content screen; use `EmptyState`. Do not use it for transient confirmation; use a toast. Web Awesome `wa-callout` is the ecosystem alternative for Web Awesome-owned content. | Delegate an optional action; choose alert urgency only for attention-requiring failure. Use the optional tone-tinted `badge` for a terse count or status beside the title, not as the only expression of meaning. | State mapping, message lifetime, retry/action behavior, badge content, and copy. | `@kerfjs/ui/state-banner` | [Feedback accessibility](./accessibility.md#shared-rules) |
112
148
  | Empty or busy content area — `EmptyState` | A content region has no items, cannot proceed, or is loading and needs explanation plus an optional action. | Do not use it for an inline status update; use `StateBanner`. Do not use it for transient success; use `wa-toast`/`wa-toast-item` or the application's toast system. | Delegate its optional action; it composes `LoadingSpinner` when busy. | Empty/busy policy, recovery action, illustration, and copy. | `@kerfjs/ui/empty-state` | [Feedback ownership](./component-contract.md#extracted-versus-application-specific) |
113
149
 
114
150
  ## Ambiguous choices
@@ -153,7 +189,7 @@ Common toolbar patterns:
153
189
  | Identity or title text | `<ToolbarText text="…" size="large" />` (or `xlarge` for a page/panel title) | Wrap in a `single` borderless group only when it must align with adjacent control pills |
154
190
  | One or more icon/text buttons | `<ToolbarControlGroup>{buttons}</ToolbarControlGroup>` | Use `buttonAppearance="push"` for toggle buttons with `aria-pressed`; `single` for a lone control |
155
191
  | An exclusive view switch | `<ToolbarControlGroup><SegmentedControl … /></ToolbarControlGroup>` | Not `TabBar`, which switches tabpanels |
156
- | A value list | `<ToolbarControlGroup><Select … /></ToolbarControlGroup>` | Register `@kerfjs/ui/select/register` once |
192
+ | A value list | `<ToolbarControlGroup><Select … /></ToolbarControlGroup>` | Register `@kerfjs/ui/select/register` once; use `focusRingOwner="group"` so focus follows the group's geometry |
157
193
  | A collapsible search box | `<ToolbarControlGroup single><TokenSearchField collapsible … /></ToolbarControlGroup>` | The group animates the iconic ↔ expanded states; `wireTokenSearchFields` manages expand/collapse/focus by default |
158
194
 
159
195
  A **popup menu in a toolbar** is a `single` `ToolbarControlGroup` wrapping a Web
@@ -183,7 +219,8 @@ Configure the List family instead of selecting its descendant classes. Use
183
219
  label line, `status` for dormant state text, and `busy` for known progress that
184
220
  keeps current content visible. `divider` marks group boundaries without an
185
221
  app-owned separator rule. `ListHeader.indicatorTone` gives count, badge, or
186
- status content neutral, accent, or danger attention.
222
+ status content neutral, accent, pop, or danger attention. Pop marks featured or
223
+ novel content without claiming a status transition.
187
224
 
188
225
  When a row needs a context action, use `ListActionRow`; its two native buttons
189
226
  remain siblings. `trailingActionVisibility="interaction"` keeps the action
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 190" width="420" height="190"><defs><clipPath id="cp0"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="cp2"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="ct3"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="cp4"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="cp6"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="ct7"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(245, 245, 247)"><clipPath id="svgic1"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic1)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp2)"><g clip-path="url(#ct3)"><text x="63" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Priority</text></g></g><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp4)"><g color="rgb(245, 245, 247)"><clipPath id="svgic5"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgic5)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp6)"><g clip-path="url(#ct7)"><text x="63" y="92" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">All work</text></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 190" width="420" height="190"><defs><clipPath id="cp0"><rect x="28" y="20" width="324" height="44"/></clipPath><clipPath id="ov1"><rect x="29" y="21" width="322" height="42" rx="11"/></clipPath><clipPath id="cp2"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="cp4"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="ov5"><rect x="63" y="33" width="272" height="18" rx="0"/></clipPath><clipPath id="ct6"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="cp7"><rect x="28" y="64" width="324" height="44"/></clipPath><clipPath id="ov8"><rect x="29" y="65" width="322" height="42" rx="11"/></clipPath><clipPath id="cp9"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="cp11"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="ov12"><rect x="63" y="77" width="272" height="18" rx="0"/></clipPath><clipPath id="ct13"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g color="rgb(245, 245, 247)"><clipPath id="svgic3"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic3)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp4)"><g clip-path="url(#ov5)"><text x="63" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Priority</text></g></g></g></g><g clip-path="url(#cp7)"><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov8)"><g clip-path="url(#cp9)"><g color="rgb(245, 245, 247)"><clipPath id="svgic10"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgic10)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp11)"><g clip-path="url(#ov12)"><text x="63" y="92" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">All work</text></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 190" width="420" height="190"><defs><clipPath id="cp0"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="cp2"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="ct3"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="cp4"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="cp6"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="ct7"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(29, 29, 31)"><clipPath id="svgic1"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic1)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp2)"><g clip-path="url(#ct3)"><text x="63" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Priority</text></g></g><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp4)"><g color="rgb(29, 29, 31)"><clipPath id="svgic5"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgic5)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp6)"><g clip-path="url(#ct7)"><text x="63" y="92" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">All work</text></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 190" width="420" height="190"><defs><clipPath id="cp0"><rect x="28" y="20" width="324" height="44"/></clipPath><clipPath id="ov1"><rect x="29" y="21" width="322" height="42" rx="11"/></clipPath><clipPath id="cp2"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="cp4"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="ov5"><rect x="63" y="33" width="272" height="18" rx="0"/></clipPath><clipPath id="ct6"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="cp7"><rect x="28" y="64" width="324" height="44"/></clipPath><clipPath id="ov8"><rect x="29" y="65" width="322" height="42" rx="11"/></clipPath><clipPath id="cp9"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="cp11"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="ov12"><rect x="63" y="77" width="272" height="18" rx="0"/></clipPath><clipPath id="ct13"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g color="rgb(29, 29, 31)"><clipPath id="svgic3"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic3)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp4)"><g clip-path="url(#ov5)"><text x="63" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Priority</text></g></g></g></g><g clip-path="url(#cp7)"><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov8)"><g clip-path="url(#cp9)"><g color="rgb(29, 29, 31)"><clipPath id="svgic10"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgic10)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp11)"><g clip-path="url(#ov12)"><text x="63" y="92" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">All work</text></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="cp3"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp5"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ct6"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp7"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp9"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ct10"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="37" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><rect x="126.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(17,17,19)"/><text x="134.33" y="46" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="10" font-weight="700" fill="rgb(174,174,178)">2</text><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#cp3)"><g color="rgb(245, 245, 247)"><clipPath id="svgic4"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic4)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp5)"><g clip-path="url(#ct6)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp7)"><g color="rgb(245, 245, 247)"><clipPath id="svgic8"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic8)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp9)"><g clip-path="url(#ct10)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="37" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><rect x="126.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(17,17,19)"/><text x="134.33" y="46" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="10" font-weight="700" fill="rgb(174,174,178)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="cp3"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp5"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ct6"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp7"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp9"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ct10"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="37" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">WORKSPACE</text></g></g><rect x="126.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(242,242,247)"/><text x="134.33" y="46" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="10" font-weight="700" fill="rgb(110,110,115)">2</text><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(214,236,255)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(166,213,255)" stroke-width="1"/><g clip-path="url(#cp3)"><g color="rgb(29, 29, 31)"><clipPath id="svgic4"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic4)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp5)"><g clip-path="url(#ct6)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(29,29,31)">Inbox</text></g></g><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp7)"><g color="rgb(29, 29, 31)"><clipPath id="svgic8"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic8)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp9)"><g clip-path="url(#ct10)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Projects</text></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="37" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="126.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="37" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">WORKSPACE</text></g></g><rect x="126.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(242,242,247)"/><text x="134.33" y="46" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="10" font-weight="700" fill="rgb(110,110,115)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(214,236,255)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(166,213,255)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(29, 29, 31)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(29,29,31)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(29, 29, 31)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">Projects</text></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ct4"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="cp5"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgba(0,0,0,0)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(245, 245, 247)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M10 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M14 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 6h18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ct4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">staging.example.com</text></g></g><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic6)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ov4"><rect x="69" y="28" width="271" height="28" rx="0"/></clipPath><clipPath id="ct5"><rect x="69" y="33" width="271" height="18"/></clipPath><clipPath id="cp6"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgba(0,0,0,0)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(245, 245, 247)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M10 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M14 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 6h18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ov4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">staging.example.com</text></g></g><g clip-path="url(#cp6)"><g color="rgb(245, 245, 247)"><clipPath id="svgic7"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ct4"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="cp5"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgba(0,0,0,0)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(29, 29, 31)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M10 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M14 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 6h18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ct4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">staging.example.com</text></g></g><g clip-path="url(#cp5)"><g color="rgb(29, 29, 31)"><clipPath id="svgic6"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic6)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ov4"><rect x="69" y="28" width="271" height="28" rx="0"/></clipPath><clipPath id="ct5"><rect x="69" y="33" width="271" height="18"/></clipPath><clipPath id="cp6"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgba(0,0,0,0)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(29, 29, 31)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M10 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M14 11v6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 6h18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ov4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(29,29,31)">staging.example.com</text></g></g><g clip-path="url(#cp6)"><g color="rgb(29, 29, 31)"><clipPath id="svgic7"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ct4"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="cp5"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><rect x="28" y="20" width="364" height="44" rx="12" fill="rgb(40,57,66)"/><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgb(53,92,109)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(245, 245, 247)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M21.2 6.8a1 1 0 0 0-4-4L3.8 16.2l-.5.8L2 21.4a.5.5 0 0 0 .6.6L7 20.7l.8-.5Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m15 5 4 4" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ct4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">production.example.com</text></g></g><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic6)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="ishc0"><rect x="28" y="20" width="364" height="44" rx="12"/></clipPath><clipPath id="cp1"><rect x="362" y="34" width="16" height="16"/></clipPath><clipPath id="cp3"><rect x="69" y="28" width="271" height="28"/></clipPath><clipPath id="ov4"><rect x="69" y="28" width="271" height="28" rx="0"/></clipPath><clipPath id="ct5"><rect x="69" y="33" width="271" height="18"/></clipPath><clipPath id="cp6"><rect x="37" y="30" width="24" height="24"/></clipPath></defs><rect x="28" y="20" width="364" height="44" rx="12" fill="rgb(40,57,66)"/><g clip-path="url(#ishc0)"><path d="M24 16h372v52H24zm16 5h340a11 11 0 0 1 11 11v20a11 11 0 0 1-11 11H40a11 11 0 0 1-11-11V32a11 11 0 0 1 11-11" fill="rgb(53,92,109)" fill-rule="evenodd"/></g><g clip-path="url(#cp1)"><g color="rgb(245, 245, 247)"><clipPath id="svgic2"><rect x="362" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic2)"><g transform="translate(362 34)scale(.66667)"><path d="M21.2 6.8a1 1 0 0 0-4-4L3.8 16.2l-.5.8L2 21.4a.5.5 0 0 0 .6.6L7 20.7l.8-.5Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m15 5 4 4" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp3)"><g clip-path="url(#ov4)"><text x="69" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">production.example.com</text></g></g><g clip-path="url(#cp6)"><g color="rgb(245, 245, 247)"><clipPath id="svgic7"><rect x="37" y="30" width="24" height="24"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(37 30)"><path d="M12 15v5s3-.6 4-2c1-1.6 0-5 0-5" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M4.5 16.5c-1.5 1.3-2 5-2 5s3.7-.5 5-2c.7-.8.7-2.1 0-3a2 2 0 0 0-3 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12a22 22 0 0 1 2-4 13 13 0 0 1 11-6c0 2.7-.8 7.5-6 11a22 22 0 0 1-4 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 12H4s.5-3 2-4c1.6-1 5 0 5 0" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>