@kerfjs/ui 5.0.0-beta.76 → 5.0.0-beta.77

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 (101) hide show
  1. package/README.md +12 -0
  2. package/ai/component-catalog.json +212 -19
  3. package/ai/component-composition.json +122 -11
  4. package/ai/components/nav-stack.md +1 -0
  5. package/ai/components/select.md +1 -0
  6. package/ai/components/split-view.md +1 -0
  7. package/ai/components/text.md +4 -2
  8. package/ai/components/toolbar-control-group.md +20 -3
  9. package/ai/components/toolbar-text.md +19 -4
  10. package/ai/components/toolbar.md +10 -4
  11. package/ai/public-api-signatures-v1.md +51 -7
  12. package/ai/skill.md +26 -2
  13. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  14. package/dist/catalog.js +5 -5
  15. package/dist/{chunk-ZVYA6TLR.js → chunk-4Y4L5YEI.js} +3 -1
  16. package/dist/chunk-4Y4L5YEI.js.map +1 -0
  17. package/dist/{chunk-7QWIJEK5.js → chunk-6VQPLV3O.js} +3 -3
  18. package/dist/{chunk-7QWIJEK5.js.map → chunk-6VQPLV3O.js.map} +1 -1
  19. package/dist/{chunk-IVLTEBBT.js → chunk-M6BWQMQY.js} +2 -2
  20. package/dist/{chunk-IVLTEBBT.js.map → chunk-M6BWQMQY.js.map} +1 -1
  21. package/dist/{chunk-72LLWYP2.js → chunk-NVKRZ5DI.js} +1 -1
  22. package/dist/chunk-NVKRZ5DI.js.map +1 -0
  23. package/dist/{chunk-GO2CZX4M.js → chunk-RRCD3A6G.js} +13 -5
  24. package/dist/chunk-RRCD3A6G.js.map +1 -0
  25. package/dist/{chunk-5PAVAR4B.js → chunk-VHXHLZ6R.js} +10 -1
  26. package/dist/chunk-VHXHLZ6R.js.map +1 -0
  27. package/dist/chunk-WJN3V2H5.js +256 -0
  28. package/dist/chunk-WJN3V2H5.js.map +1 -0
  29. package/dist/{chunk-SJY7KC45.js → chunk-Z4EPMX25.js} +3 -3
  30. package/dist/{chunk-SJY7KC45.js.map → chunk-Z4EPMX25.js.map} +1 -1
  31. package/dist/{chunk-HGSTMZZ6.js → chunk-Z6PE5T7N.js} +2 -2
  32. package/dist/{chunk-HGSTMZZ6.js.map → chunk-Z6PE5T7N.js.map} +1 -1
  33. package/dist/collapsible-panel.js +2 -2
  34. package/dist/index.d.ts +3 -2
  35. package/dist/index.js +6 -5
  36. package/dist/list-header.d.ts +1 -0
  37. package/dist/list-header.js +1 -1
  38. package/dist/nav-stack.d.ts +1 -0
  39. package/dist/nav-stack.js +1 -1
  40. package/dist/select-register.js +3 -0
  41. package/dist/select-register.js.map +1 -1
  42. package/dist/select.d.ts +1 -0
  43. package/dist/select.js +1 -1
  44. package/dist/split-view.js +1 -1
  45. package/dist/styles/components/actions/toolbar/toolbar.css +32 -0
  46. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +51 -0
  47. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +11 -0
  48. package/dist/styles/components/navigation/nav-stack/nav-stack.css +11 -0
  49. package/dist/styles/components/typography/text/text.css +19 -0
  50. package/dist/styles/nav-stack.css +11 -0
  51. package/dist/styles/text.css +19 -0
  52. package/dist/styles/toolbar-control-group.css +51 -0
  53. package/dist/styles/toolbar-text.css +11 -0
  54. package/dist/styles/toolbar.css +32 -0
  55. package/dist/text.d.ts +5 -2
  56. package/dist/text.js +1 -1
  57. package/dist/toolbar-control-group.d.ts +14 -2
  58. package/dist/toolbar-control-group.js +1 -1
  59. package/dist/toolbar-text.d.ts +10 -2
  60. package/dist/toolbar-text.js +1 -1
  61. package/dist/wire-nav-stack.js +58 -22
  62. package/dist/wire-nav-stack.js.map +1 -1
  63. package/dist/wire-toolbar-visibility.d.ts +13 -0
  64. package/dist/wire-toolbar-visibility.js +3 -0
  65. package/dist/wire-toolbar-visibility.js.map +1 -0
  66. package/dist/workbench.js +1 -1
  67. package/docs/accessibility.md +15 -0
  68. package/docs/collapsible-panel.md +4 -0
  69. package/docs/component-contract.md +31 -0
  70. package/docs/component-selection.md +55 -1
  71. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  72. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  73. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  74. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  75. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  76. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  77. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  78. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  79. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  80. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  81. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  82. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  83. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  84. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  85. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  86. package/docs/design/templates/toolbar-control-group.svg +1 -1
  87. package/docs/design/templates/toolbar-dark.svg +1 -1
  88. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  89. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  90. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  91. package/docs/design/templates/toolbar-text.svg +1 -1
  92. package/docs/design/templates/toolbar.svg +1 -1
  93. package/docs/design/templates.md +2 -0
  94. package/docs/layout.md +12 -1
  95. package/docs/nav-stack.md +5 -1
  96. package/llms.txt +24 -0
  97. package/package.json +5 -1
  98. package/dist/chunk-5PAVAR4B.js.map +0 -1
  99. package/dist/chunk-72LLWYP2.js.map +0 -1
  100. package/dist/chunk-GO2CZX4M.js.map +0 -1
  101. package/dist/chunk-ZVYA6TLR.js.map +0 -1
@@ -27,7 +27,7 @@ function reducedMotion(view) {
27
27
  function chromeOf(section) {
28
28
  return Array.from(
29
29
  section.querySelectorAll(
30
- ":scope > [data-nav-stack-chrome], :scope > [data-nav-stack-bottom]"
30
+ ":scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy]), :scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])"
31
31
  )
32
32
  );
33
33
  }
@@ -56,6 +56,32 @@ function wireNavStack(root, options = {}) {
56
56
  );
57
57
  let activeKey = topView(viewport)?.dataset.navKey;
58
58
  const timers = /* @__PURE__ */ new Set();
59
+ const frames = /* @__PURE__ */ new Set();
60
+ const frame = (fn) => {
61
+ const id = view.requestAnimationFrame(() => {
62
+ frames.delete(id);
63
+ fn();
64
+ });
65
+ frames.add(id);
66
+ };
67
+ const finishTransition = () => {
68
+ for (const id of frames) view.cancelAnimationFrame(id);
69
+ frames.clear();
70
+ for (const id of timers) view.clearTimeout(id);
71
+ timers.clear();
72
+ section.querySelectorAll(":scope > [data-nav-chrome-copy]").forEach((element) => element.remove());
73
+ chromeOf(section).forEach(
74
+ (element) => element.classList.remove("kui-nav-stack__chrome--entering")
75
+ );
76
+ viewsOf(viewport).forEach((element) => {
77
+ if (element.dataset.navExiting === "true") element.remove();
78
+ else {
79
+ element.classList.remove("kui-nav-stack__view--entering");
80
+ delete element.dataset.navRevealed;
81
+ }
82
+ });
83
+ delete section.dataset.navChromeTransition;
84
+ };
59
85
  const rememberedFocus = /* @__PURE__ */ new Map();
60
86
  const generatedFallbacks = /* @__PURE__ */ new Map();
61
87
  let chromeSnapshots = chromeOf(section).map(
@@ -78,16 +104,12 @@ function wireNavStack(root, options = {}) {
78
104
  el.classList.add("kui-nav-stack__view--entering");
79
105
  if (animated) {
80
106
  void el.offsetWidth;
81
- view.requestAnimationFrame(
82
- () => el.classList.remove("kui-nav-stack__view--entering")
83
- );
107
+ frame(() => el.classList.remove("kui-nav-stack__view--entering"));
84
108
  } else {
85
109
  el.classList.remove("kui-nav-stack__view--entering");
86
110
  }
87
111
  } else if (animated) {
88
- view.requestAnimationFrame(
89
- () => el.classList.add("kui-nav-stack__view--exiting")
90
- );
112
+ frame(() => el.classList.add("kui-nav-stack__view--exiting"));
91
113
  } else {
92
114
  el.classList.add("kui-nav-stack__view--exiting");
93
115
  }
@@ -150,7 +172,7 @@ function wireNavStack(root, options = {}) {
150
172
  (element) => element.classList.add("kui-nav-stack__chrome--entering")
151
173
  );
152
174
  void section.offsetWidth;
153
- view.requestAnimationFrame(() => {
175
+ frame(() => {
154
176
  current.forEach(
155
177
  (element) => element.classList.remove("kui-nav-stack__chrome--entering")
156
178
  );
@@ -162,35 +184,47 @@ function wireNavStack(root, options = {}) {
162
184
  copies.forEach((copy) => copy.remove());
163
185
  delete section.dataset.navChromeTransition;
164
186
  });
165
- chromeSnapshots = current.map(
166
- (element) => element.cloneNode(true)
167
- );
187
+ chromeSnapshots = current.map((element) => {
188
+ const snapshot = element.cloneNode(true);
189
+ snapshot.classList.remove("kui-nav-stack__chrome--entering");
190
+ return snapshot;
191
+ });
168
192
  };
169
193
  const observer = new MutationObserver((records) => {
170
194
  const removed = [];
171
- let added = false;
172
195
  for (const record of records) {
196
+ if (record.target !== viewport) continue;
173
197
  record.removedNodes.forEach((node) => {
174
198
  if (node instanceof HTMLElement && node.classList.contains("kui-nav-stack__view") && node.dataset.navExiting !== "true")
175
199
  removed.push(node);
176
200
  });
177
- record.addedNodes.forEach((node) => {
178
- if (node instanceof HTMLElement && node.classList.contains("kui-nav-stack__view"))
179
- added = true;
180
- });
181
201
  }
182
202
  const top = topView(viewport);
183
203
  const currentKey = top?.dataset.navKey;
184
204
  const poppedTop = removed.find((node) => node.dataset.navKey === activeKey);
185
205
  if (poppedTop && currentKey !== activeKey) {
206
+ finishTransition();
207
+ poppedTop.classList.remove(
208
+ "kui-nav-stack__view--entering",
209
+ "kui-nav-stack__view--exiting"
210
+ );
186
211
  poppedTop.dataset.navExiting = "true";
187
212
  poppedTop.setAttribute("aria-hidden", "true");
188
213
  viewport.append(poppedTop);
214
+ void poppedTop.offsetWidth;
189
215
  play(poppedTop, "exiting");
190
216
  crossFadeChrome();
191
217
  if (top) focusInto(top);
192
218
  settle(() => poppedTop.remove());
193
- } else if (added && currentKey !== activeKey && top) {
219
+ } else if (currentKey !== activeKey && top) {
220
+ finishTransition();
221
+ const previous = viewsOf(viewport).find(
222
+ (element) => element.dataset.navKey === activeKey
223
+ );
224
+ if (previous) {
225
+ previous.dataset.navRevealed = "true";
226
+ settle(() => delete previous.dataset.navRevealed);
227
+ }
194
228
  rememberFocusedView(section.ownerDocument.activeElement);
195
229
  play(top, "entering");
196
230
  crossFadeChrome();
@@ -198,15 +232,17 @@ function wireNavStack(root, options = {}) {
198
232
  }
199
233
  activeKey = currentKey;
200
234
  });
201
- observer.observe(viewport, { childList: true });
235
+ observer.observe(viewport, {
236
+ childList: true,
237
+ subtree: true,
238
+ attributes: true,
239
+ attributeFilter: ["data-nav-key", "data-nav-active"]
240
+ });
202
241
  return () => {
203
242
  disposeBack();
204
243
  section.removeEventListener("focusin", onFocusIn);
205
244
  observer.disconnect();
206
- for (const timer of timers) view.clearTimeout(timer);
207
- timers.clear();
208
- section.querySelectorAll("[data-nav-chrome-copy]").forEach((copy) => copy.remove());
209
- delete section.dataset.navChromeTransition;
245
+ finishTransition();
210
246
  for (const [element, previousTabIndex] of generatedFallbacks) {
211
247
  if (!element.isConnected || element.tabIndex !== -1) continue;
212
248
  if (previousTabIndex === null) element.removeAttribute("tabindex");
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/navigation/nav-stack/wiring/wire-nav-stack.ts"],"names":[],"mappings":"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","file":"wire-nav-stack.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireNavStackOptions {\n /** Invoked when the back control is activated. The app pops its own stack. */\n onBack?: () => void;\n /** Transition duration in ms (default 200). Set 0 to disable animation. */\n duration?: number;\n}\n\nconst DEFAULT_DURATION = 200;\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\nfunction viewsOf(viewport: Element): HTMLElement[] {\n return Array.from(\n viewport.querySelectorAll<HTMLElement>(':scope > .kui-nav-stack__view'),\n );\n}\n\nfunction topView(viewport: Element): HTMLElement | undefined {\n const live = viewsOf(viewport).filter(\n (view) => view.dataset.navExiting !== 'true',\n );\n return live[live.length - 1];\n}\n\nfunction reducedMotion(view: Window): boolean {\n return (\n typeof view.matchMedia === 'function' &&\n view.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nfunction chromeOf(section: HTMLElement): HTMLElement[] {\n return Array.from(\n section.querySelectorAll<HTMLElement>(\n ':scope > [data-nav-stack-chrome], :scope > [data-nav-stack-bottom]',\n ),\n );\n}\n\nfunction availableFocusTarget(\n element: Element | null | undefined,\n): element is HTMLElement {\n return (\n element instanceof HTMLElement &&\n element.isConnected &&\n !element.matches('[disabled], [aria-disabled=\"true\"]') &&\n !element.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n );\n}\n\n/**\n * Animate a `NavStack`'s push/pop transitions and wire its back control. The app\n * owns the stack (a signal of `NavStackView[]`) and re-renders `NavStack` when it\n * changes; this helper slides the content and settles the chrome across each\n * change, moves focus into every new top view, restores that view's last focused\n * descendant on pop, and calls `onBack` when the back control is used. Mark a\n * preferred initial target with `data-nav-focus`; otherwise the first focusable\n * descendant (or the view itself) receives focus. Returns a disposer.\n */\nexport function wireNavStack(\n root: Element,\n options: WireNavStackOptions = {},\n): () => void {\n const section = root.matches('[data-component=\"nav-stack\"]')\n ? root\n : root.querySelector('[data-component=\"nav-stack\"]');\n const viewport = section?.querySelector('[data-nav-stack-viewport]');\n if (!(section instanceof HTMLElement) || !viewport) return () => {};\n\n const view = section.ownerDocument.defaultView ?? window;\n const duration = options.duration ?? DEFAULT_DURATION;\n const previousDuration = section.style.getPropertyValue(\n '--kui-nav-stack-transition-duration',\n );\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n `${Math.max(0, duration)}ms`,\n );\n const disposeBack = delegate(section, 'click', '[data-nav-back]', () =>\n options.onBack?.(),\n );\n\n let activeKey = topView(viewport)?.dataset.navKey;\n const timers = new Set<number>();\n const rememberedFocus = new Map<string, HTMLElement>();\n const generatedFallbacks = new Map<HTMLElement, string | null>();\n let chromeSnapshots = chromeOf(section).map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n\n const settle = (fn: () => void): void => {\n if (duration <= 0 || reducedMotion(view)) {\n fn();\n return;\n }\n const timer = view.setTimeout(() => {\n timers.delete(timer);\n fn();\n }, duration);\n timers.add(timer);\n };\n\n const play = (el: HTMLElement, kind: 'entering' | 'exiting'): void => {\n const animated = duration > 0 && !reducedMotion(view);\n if (kind === 'entering') {\n // Push: start the incoming view off the trailing edge, then release it so\n // it slides to rest (translateX(100%) → 0).\n el.classList.add('kui-nav-stack__view--entering');\n if (animated) {\n // Force a reflow so the starting transform applies before we clear it.\n void el.offsetWidth;\n view.requestAnimationFrame(() =>\n el.classList.remove('kui-nav-stack__view--entering'),\n );\n } else {\n el.classList.remove('kui-nav-stack__view--entering');\n }\n } else if (animated) {\n // Pop: the outgoing view is at rest; add the off-edge class on the next\n // frame so it slides OUT (translateX(0) → 100%), not in.\n view.requestAnimationFrame(() =>\n el.classList.add('kui-nav-stack__view--exiting'),\n );\n } else {\n el.classList.add('kui-nav-stack__view--exiting');\n }\n };\n\n const rememberFocusedView = (target: Element | null): void => {\n if (!(target instanceof HTMLElement)) return;\n const owner = target.closest<HTMLElement>('.kui-nav-stack__view');\n const key = owner?.dataset.navKey;\n if (key && owner !== target && viewport.contains(owner))\n rememberedFocus.set(key, target);\n };\n\n const focusInto = (targetView: HTMLElement): void => {\n const key = targetView.dataset.navKey;\n const remembered = key ? rememberedFocus.get(key) : undefined;\n const preferred = Array.from(\n targetView.querySelectorAll<HTMLElement>('[data-nav-focus]'),\n ).find(availableFocusTarget);\n const first = Array.from(\n targetView.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).find(availableFocusTarget);\n const target =\n (availableFocusTarget(remembered) && targetView.contains(remembered)\n ? remembered\n : undefined) ??\n preferred ??\n first;\n if (target) {\n target.focus({ preventScroll: true });\n return;\n }\n\n if (!generatedFallbacks.has(targetView)) {\n generatedFallbacks.set(\n targetView,\n targetView.hasAttribute('tabindex')\n ? targetView.getAttribute('tabindex')\n : null,\n );\n targetView.tabIndex = -1;\n }\n targetView.focus({ preventScroll: true });\n };\n\n const onFocusIn = (event: Event): void =>\n rememberFocusedView(event.target as Element | null);\n section.addEventListener('focusin', onFocusIn);\n rememberFocusedView(section.ownerDocument.activeElement);\n\n const crossFadeChrome = (): void => {\n const current = chromeOf(section);\n const animated = duration > 0 && !reducedMotion(view);\n if (!animated) {\n chromeSnapshots = current.map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n return;\n }\n\n section.dataset.navChromeTransition = 'true';\n const copies = chromeSnapshots.map((snapshot) => {\n const copy = snapshot.cloneNode(true) as HTMLElement;\n copy.classList.add('kui-nav-stack__chrome-copy');\n copy.dataset.navChromeCopy = '';\n copy.setAttribute('aria-hidden', 'true');\n copy.setAttribute('inert', '');\n if (copy.hasAttribute('data-nav-stack-bottom'))\n copy.classList.add('kui-nav-stack__chrome-copy--bottom');\n section.append(copy);\n return copy;\n });\n\n current.forEach((element) =>\n element.classList.add('kui-nav-stack__chrome--entering'),\n );\n void section.offsetWidth;\n view.requestAnimationFrame(() => {\n current.forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n copies.forEach((copy) =>\n copy.classList.add('kui-nav-stack__chrome-copy--exiting'),\n );\n });\n settle(() => {\n copies.forEach((copy) => copy.remove());\n delete section.dataset.navChromeTransition;\n });\n chromeSnapshots = current.map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n };\n\n const observer = new MutationObserver((records) => {\n const removed: HTMLElement[] = [];\n let added = false;\n for (const record of records) {\n record.removedNodes.forEach((node) => {\n if (\n node instanceof HTMLElement &&\n node.classList.contains('kui-nav-stack__view') &&\n node.dataset.navExiting !== 'true'\n )\n removed.push(node);\n });\n record.addedNodes.forEach((node) => {\n if (\n node instanceof HTMLElement &&\n node.classList.contains('kui-nav-stack__view')\n )\n added = true;\n });\n }\n\n const top = topView(viewport);\n const currentKey = top?.dataset.navKey;\n const poppedTop = removed.find((node) => node.dataset.navKey === activeKey);\n\n if (poppedTop && currentKey !== activeKey) {\n // Pop: bring the removed node back briefly to slide it out over the revealed view.\n poppedTop.dataset.navExiting = 'true';\n poppedTop.setAttribute('aria-hidden', 'true');\n viewport.append(poppedTop);\n play(poppedTop, 'exiting');\n crossFadeChrome();\n if (top) focusInto(top);\n settle(() => poppedTop.remove());\n } else if (added && currentKey !== activeKey && top) {\n // Push: slide the new top in.\n rememberFocusedView(section.ownerDocument.activeElement);\n play(top, 'entering');\n crossFadeChrome();\n focusInto(top);\n }\n\n activeKey = currentKey;\n });\n observer.observe(viewport, { childList: true });\n\n return () => {\n disposeBack();\n section.removeEventListener('focusin', onFocusIn);\n observer.disconnect();\n for (const timer of timers) view.clearTimeout(timer);\n timers.clear();\n section\n .querySelectorAll<HTMLElement>('[data-nav-chrome-copy]')\n .forEach((copy) => copy.remove());\n delete section.dataset.navChromeTransition;\n for (const [element, previousTabIndex] of generatedFallbacks) {\n if (!element.isConnected || element.tabIndex !== -1) continue;\n if (previousTabIndex === null) element.removeAttribute('tabindex');\n else element.setAttribute('tabindex', previousTabIndex);\n }\n generatedFallbacks.clear();\n rememberedFocus.clear();\n if (previousDuration)\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n previousDuration,\n );\n else section.style.removeProperty('--kui-nav-stack-transition-duration');\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/components/navigation/nav-stack/wiring/wire-nav-stack.ts"],"names":[],"mappings":"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","file":"wire-nav-stack.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireNavStackOptions {\n /** Invoked when the back control is activated. The app pops its own stack. */\n onBack?: () => void;\n /** Transition duration in ms (default 200). Set 0 to disable animation. */\n duration?: number;\n}\n\nconst DEFAULT_DURATION = 200;\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\nfunction viewsOf(viewport: Element): HTMLElement[] {\n return Array.from(\n viewport.querySelectorAll<HTMLElement>(':scope > .kui-nav-stack__view'),\n );\n}\n\nfunction topView(viewport: Element): HTMLElement | undefined {\n const live = viewsOf(viewport).filter(\n (view) => view.dataset.navExiting !== 'true',\n );\n return live[live.length - 1];\n}\n\nfunction reducedMotion(view: Window): boolean {\n return (\n typeof view.matchMedia === 'function' &&\n view.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nfunction chromeOf(section: HTMLElement): HTMLElement[] {\n return Array.from(\n section.querySelectorAll<HTMLElement>(\n ':scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy]), :scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])',\n ),\n );\n}\n\nfunction availableFocusTarget(\n element: Element | null | undefined,\n): element is HTMLElement {\n return (\n element instanceof HTMLElement &&\n element.isConnected &&\n !element.matches('[disabled], [aria-disabled=\"true\"]') &&\n !element.closest('[inert], [hidden], [aria-hidden=\"true\"]')\n );\n}\n\n/**\n * Animate a `NavStack`'s push/pop transitions and wire its back control. The app\n * owns the stack (a signal of `NavStackView[]`) and re-renders `NavStack` when it\n * changes; this helper slides the content and settles the chrome across each\n * change, moves focus into every new top view, restores that view's last focused\n * descendant on pop, and calls `onBack` when the back control is used. Mark a\n * preferred initial target with `data-nav-focus`; otherwise the first focusable\n * descendant (or the view itself) receives focus. Returns a disposer.\n */\nexport function wireNavStack(\n root: Element,\n options: WireNavStackOptions = {},\n): () => void {\n const section = root.matches('[data-component=\"nav-stack\"]')\n ? root\n : root.querySelector('[data-component=\"nav-stack\"]');\n const viewport = section?.querySelector('[data-nav-stack-viewport]');\n if (!(section instanceof HTMLElement) || !viewport) return () => {};\n\n const view = section.ownerDocument.defaultView ?? window;\n const duration = options.duration ?? DEFAULT_DURATION;\n const previousDuration = section.style.getPropertyValue(\n '--kui-nav-stack-transition-duration',\n );\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n `${Math.max(0, duration)}ms`,\n );\n const disposeBack = delegate(section, 'click', '[data-nav-back]', () =>\n options.onBack?.(),\n );\n\n let activeKey = topView(viewport)?.dataset.navKey;\n const timers = new Set<number>();\n const frames = new Set<number>();\n const frame = (fn: () => void): void => {\n const id = view.requestAnimationFrame(() => {\n frames.delete(id);\n fn();\n });\n frames.add(id);\n };\n const finishTransition = (): void => {\n for (const id of frames) view.cancelAnimationFrame(id);\n frames.clear();\n for (const id of timers) view.clearTimeout(id);\n timers.clear();\n section\n .querySelectorAll<HTMLElement>(':scope > [data-nav-chrome-copy]')\n .forEach((element) => element.remove());\n chromeOf(section).forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n viewsOf(viewport).forEach((element) => {\n if (element.dataset.navExiting === 'true') element.remove();\n else {\n element.classList.remove('kui-nav-stack__view--entering');\n delete element.dataset.navRevealed;\n }\n });\n delete section.dataset.navChromeTransition;\n };\n const rememberedFocus = new Map<string, HTMLElement>();\n const generatedFallbacks = new Map<HTMLElement, string | null>();\n let chromeSnapshots = chromeOf(section).map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n\n const settle = (fn: () => void): void => {\n if (duration <= 0 || reducedMotion(view)) {\n fn();\n return;\n }\n const timer = view.setTimeout(() => {\n timers.delete(timer);\n fn();\n }, duration);\n timers.add(timer);\n };\n\n const play = (el: HTMLElement, kind: 'entering' | 'exiting'): void => {\n const animated = duration > 0 && !reducedMotion(view);\n if (kind === 'entering') {\n // Push: start the incoming view off the trailing edge, then release it so\n // it slides to rest (translateX(100%) → 0).\n el.classList.add('kui-nav-stack__view--entering');\n if (animated) {\n // Force a reflow so the starting transform applies before we clear it.\n void el.offsetWidth;\n frame(() => el.classList.remove('kui-nav-stack__view--entering'));\n } else {\n el.classList.remove('kui-nav-stack__view--entering');\n }\n } else if (animated) {\n // Pop: the outgoing view is at rest; add the off-edge class on the next\n // frame so it slides OUT (translateX(0) → 100%), not in.\n frame(() => el.classList.add('kui-nav-stack__view--exiting'));\n } else {\n el.classList.add('kui-nav-stack__view--exiting');\n }\n };\n\n const rememberFocusedView = (target: Element | null): void => {\n if (!(target instanceof HTMLElement)) return;\n const owner = target.closest<HTMLElement>('.kui-nav-stack__view');\n const key = owner?.dataset.navKey;\n if (key && owner !== target && viewport.contains(owner))\n rememberedFocus.set(key, target);\n };\n\n const focusInto = (targetView: HTMLElement): void => {\n const key = targetView.dataset.navKey;\n const remembered = key ? rememberedFocus.get(key) : undefined;\n const preferred = Array.from(\n targetView.querySelectorAll<HTMLElement>('[data-nav-focus]'),\n ).find(availableFocusTarget);\n const first = Array.from(\n targetView.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR),\n ).find(availableFocusTarget);\n const target =\n (availableFocusTarget(remembered) && targetView.contains(remembered)\n ? remembered\n : undefined) ??\n preferred ??\n first;\n if (target) {\n target.focus({ preventScroll: true });\n return;\n }\n\n if (!generatedFallbacks.has(targetView)) {\n generatedFallbacks.set(\n targetView,\n targetView.hasAttribute('tabindex')\n ? targetView.getAttribute('tabindex')\n : null,\n );\n targetView.tabIndex = -1;\n }\n targetView.focus({ preventScroll: true });\n };\n\n const onFocusIn = (event: Event): void =>\n rememberFocusedView(event.target as Element | null);\n section.addEventListener('focusin', onFocusIn);\n rememberFocusedView(section.ownerDocument.activeElement);\n\n const crossFadeChrome = (): void => {\n const current = chromeOf(section);\n const animated = duration > 0 && !reducedMotion(view);\n if (!animated) {\n chromeSnapshots = current.map((element) =>\n element.cloneNode(true),\n ) as HTMLElement[];\n return;\n }\n\n section.dataset.navChromeTransition = 'true';\n const copies = chromeSnapshots.map((snapshot) => {\n const copy = snapshot.cloneNode(true) as HTMLElement;\n copy.classList.add('kui-nav-stack__chrome-copy');\n copy.dataset.navChromeCopy = '';\n copy.setAttribute('aria-hidden', 'true');\n copy.setAttribute('inert', '');\n if (copy.hasAttribute('data-nav-stack-bottom'))\n copy.classList.add('kui-nav-stack__chrome-copy--bottom');\n section.append(copy);\n return copy;\n });\n\n current.forEach((element) =>\n element.classList.add('kui-nav-stack__chrome--entering'),\n );\n void section.offsetWidth;\n frame(() => {\n current.forEach((element) =>\n element.classList.remove('kui-nav-stack__chrome--entering'),\n );\n copies.forEach((copy) =>\n copy.classList.add('kui-nav-stack__chrome-copy--exiting'),\n );\n });\n settle(() => {\n copies.forEach((copy) => copy.remove());\n delete section.dataset.navChromeTransition;\n });\n chromeSnapshots = current.map((element) => {\n const snapshot = element.cloneNode(true) as HTMLElement;\n snapshot.classList.remove('kui-nav-stack__chrome--entering');\n return snapshot;\n });\n };\n\n const observer = new MutationObserver((records) => {\n const removed: HTMLElement[] = [];\n for (const record of records) {\n if (record.target !== viewport) continue;\n record.removedNodes.forEach((node) => {\n if (\n node instanceof HTMLElement &&\n node.classList.contains('kui-nav-stack__view') &&\n node.dataset.navExiting !== 'true'\n )\n removed.push(node);\n });\n }\n\n const top = topView(viewport);\n const currentKey = top?.dataset.navKey;\n const poppedTop = removed.find((node) => node.dataset.navKey === activeKey);\n\n if (poppedTop && currentKey !== activeKey) {\n finishTransition();\n // Pop: bring the removed node back briefly to slide it out over the revealed view.\n poppedTop.classList.remove(\n 'kui-nav-stack__view--entering',\n 'kui-nav-stack__view--exiting',\n );\n poppedTop.dataset.navExiting = 'true';\n poppedTop.setAttribute('aria-hidden', 'true');\n viewport.append(poppedTop);\n void poppedTop.offsetWidth;\n play(poppedTop, 'exiting');\n crossFadeChrome();\n if (top) focusInto(top);\n settle(() => poppedTop.remove());\n } else if (currentKey !== activeKey && top) {\n finishTransition();\n const previous = viewsOf(viewport).find(\n (element) => element.dataset.navKey === activeKey,\n );\n if (previous) {\n previous.dataset.navRevealed = 'true';\n settle(() => delete previous.dataset.navRevealed);\n }\n // Push: slide the new top in.\n rememberFocusedView(section.ownerDocument.activeElement);\n play(top, 'entering');\n crossFadeChrome();\n focusInto(top);\n }\n\n activeKey = currentKey;\n });\n observer.observe(viewport, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['data-nav-key', 'data-nav-active'],\n });\n\n return () => {\n disposeBack();\n section.removeEventListener('focusin', onFocusIn);\n observer.disconnect();\n finishTransition();\n for (const [element, previousTabIndex] of generatedFallbacks) {\n if (!element.isConnected || element.tabIndex !== -1) continue;\n if (previousTabIndex === null) element.removeAttribute('tabindex');\n else element.setAttribute('tabindex', previousTabIndex);\n }\n generatedFallbacks.clear();\n rememberedFocus.clear();\n if (previousDuration)\n section.style.setProperty(\n '--kui-nav-stack-transition-duration',\n previousDuration,\n );\n else section.style.removeProperty('--kui-nav-stack-transition-duration');\n };\n}\n"]}
@@ -0,0 +1,13 @@
1
+ type Root = HTMLElement | Document;
2
+ /**
3
+ * Wire ToolbarText and ToolbarControlGroup width thresholds below root.
4
+ * Below is strict: hideBelow hides at width < threshold; showBelow hides at
5
+ * width >= threshold. Percentages use the closest Toolbar's content box;
6
+ * em and custom properties use the item's own inherited context. Invalid,
7
+ * negative, unresolved, or contradictory thresholds leave the item visible.
8
+ * This helper changes only a component-owned visibility marker. Existing
9
+ * CSS visibility policies still apply. Dispose with the owning application.
10
+ */
11
+ declare function wireToolbarVisibility(root: Root): () => void;
12
+
13
+ export { wireToolbarVisibility };
@@ -0,0 +1,3 @@
1
+ export { wireToolbarVisibility } from './chunk-WJN3V2H5.js';
2
+
3
+ //# sourceMappingURL=wire-toolbar-visibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"wire-toolbar-visibility.js"}
package/dist/workbench.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Workbench } from './chunk-7QWIJEK5.js';
1
+ export { Workbench } from './chunk-6VQPLV3O.js';
2
2
 
3
3
 
4
4
 
@@ -568,3 +568,18 @@ pattern). See [`workbench.md`](workbench.md).
568
568
  ## Verification matrix
569
569
 
570
570
  For each changed component, inspect default, hover, focus, disabled, selected/pressed, busy/error, long-content, wide, narrow, light, dark, increased-contrast, reduced-motion, keyboard-only, and 200%-zoom states where applicable. DOM order must match reading and focus order, with no clipping or unreachable action.
571
+
572
+ Text contrast checks must measure the painted solid-color backdrop, compositing
573
+ translucent fills from the document canvas through every ancestor and the
574
+ component itself before comparing the foreground. Raw RGB channels from an
575
+ `rgba()` value are not the rendered background. The shared browser helper in
576
+ `tests/browser/painted-contrast.ts` resolves CSS color syntax through canvas and
577
+ uses the evaluator's WCAG ratio calculation; its browser regressions cover
578
+ nested fills, transparent foregrounds, shadow-host backdrops, theme changes,
579
+ and genuinely insufficient contrast. Background images (including the catalog
580
+ checkerboard), filters, and group opacity remain separate visual-review concerns;
581
+ this helper measures only the solid CSS color layers.
582
+
583
+ Separator checks resolve the documented semantic border token in the component's
584
+ context instead of pinning an old opaque palette value, while still verifying
585
+ that the line has its intended width and a visible color.
@@ -142,6 +142,10 @@ top toolbar over a `Pane`:
142
142
  work area when the panel closes; the standard `toggle: { action, name,
143
143
  showLabel?, hideLabel? }` is always the final group.
144
144
 
145
+ Busy groups keep their inert control, spinner, and adjacent live status together
146
+ when relocated. Clearing `busy` restores the same action in its current toolbar;
147
+ expanding the panel returns both control and status to the panel toolbar.
148
+
145
149
  The panel can also take `header` under its toolbar, `footer` below its content,
146
150
  `bottomToolbar` below that, `headerList` / `footerList` for those fixed content
147
151
  stacks, and `headerPlacement` / `footerPlacement` (`fixed`, `scroll`, or `auto`).
@@ -317,6 +317,8 @@ Both row components align a leading icon with the first label line when
317
317
  `multiline` allows the label to wrap; additional lines extend below that fixed
318
318
  visual anchor.
319
319
 
320
+ `ToolbarControlGroup.tileTone` selects `neutral`, `brand`, `success`, `warning`, or `danger` quiet fill, matching quiet border, and on-quiet foreground for a non-interactive icon tile. Compose a contained `single` group whose only child is a direct decorative LucideIcon (`aria-hidden="true"`). Omission preserves the normal group palette. The prop does not recolor interactive, mixed, multi-control, or borderless groups; keep real actions in controls with their existing focus/hover/pressed treatments.
321
+
320
322
  ### Public CSS anatomy
321
323
 
322
324
  The `publicClasses` array on each entry in
@@ -577,6 +579,8 @@ compact segment never becomes an oval. An icon-only `Select` joins a group as
577
579
  one more segment with its siblings' inset, radius, hover, and focus ring; only a
578
580
  lone Select grows the group to its icon-and-caret pill.
579
581
 
582
+ Select menus use native viewport shifting with 10px gutters: default menus grow to content (up to 20rem), while `fitMenu` matches trigger width and long labels wrap. Keep popup sizing and position repairs out of consumer CSS.
583
+
580
584
  For a rail view heading, use `Select presentation="title"`: its intrinsic
581
585
  36px borderless trigger has a bold large label flush with its leading edge and
582
586
  a caret beside that label. Set `focusRingInset` when a NavStack or panel clips
@@ -864,3 +868,30 @@ Keep product adapters outside the package: connection-state maps, ticket empty-s
864
868
  ## Testing contract
865
869
 
866
870
  Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. `npm run check:css-ownership` rejects application selectors into Kerf or Web Awesome components, a non-minimal catalog compatibility stylesheet, or a return of the shared recipe stylesheet. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
871
+
872
+ ### Toolbar width visibility
873
+
874
+ `ToolbarText` and `ToolbarControlGroup` accept typed `hideBelow` and
875
+ `showBelow` CSS lengths. Call `wireToolbarVisibility(root)` from
876
+ `@kerfjs/ui/wire-toolbar-visibility` after mounting, and call its disposer when
877
+ the application unmounts. The nearest Toolbar's **content-box width**, excluding
878
+ padding, borders, and safe-area insets, determines visibility. `hideBelow={px(416)}`
879
+ hides strictly below 416px; `showBelow={px(416)}` shows strictly below 416px. At
880
+ 416px the first is visible and the second hidden. Together they define the visible
881
+ interval `[hideBelow, showBelow)`. Width rules intersect existing visibility and
882
+ expanded-state rules; they never force a CSS-hidden group visible.
883
+
884
+ Use `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, or `calc`/`plus` to construct
885
+ lengths. Percentages resolve against that content box, `em` uses the child item's
886
+ font size, and custom properties use its inherited and own token context. The
887
+ helper follows resizes, theme/token/font changes, inserted items, nested toolbars,
888
+ and relocated groups. Invalid, unresolved, negative, or contradictory thresholds
889
+ leave the item visible under this width policy. Server-rendered content is visible
890
+ until wiring runs; without browser observers, initial wiring and window resize
891
+ still update it. Probe context and lengths are reconciled only when their CSSOM
892
+ values change, so unrelated DOM observers can redraw without feeding an ongoing
893
+ mutation loop. Dispose to remove measurement probes and restore prior markers.
894
+
895
+ Hidden controls leave layout and keyboard navigation. A hidden busy group also
896
+ hides only its own adjacent busy status. Keep primary actions always available;
897
+ show a complementary overflow group for secondary actions at narrow widths.
@@ -160,7 +160,7 @@ beside a `ContentItem` value, and connect its id to the preview group's
160
160
  | 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) |
161
161
  | Toolbar control cluster — `ToolbarControlGroup`, `ToolbarActionLink` | Related toolbar buttons, semantic links, compact/tight controls, avatar actions, or a dropdown trigger/menu surface need one configured chrome contract. | Do not use it merely to align unrelated controls. Do not restyle anchors or dropdown parts in application CSS; use `ToolbarActionLink`, `overflow`, and `menuInset`. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; use `ToolbarActionLink` for native navigation, `overflow="scroll"` for bounded action rows, and `menuInset` for dropdown surface padding. Use `avatarImage` instead of inserting an `img`; use `SegmentedControl` for an exclusive choice. | Actions, destinations, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
162
162
  | 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) |
163
- | 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`. Sizes below `xlarge` are intentionally quiet identity text with no tone option — do not use them as a normal-color subsection title; use `Text` with an `h2`–`h6` variant, or `ListHeader` for a list section. | 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) |
163
+ | 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`. Sizes below `xlarge` are intentionally quiet identity text in default tone — do not use them as a normal-color subsection title; use `Text` with an `h2`–`h6` variant, or `ListHeader` for a list section. | 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) |
164
164
  | Semantic block or inline text — `Text` | Ordinary application copy needs native `h1`–`h6` or `p` semantics plus standard geometry, or inline secondary copy needs a native `span` without box geometry. | Do not choose heading levels for appearance alone or recreate muted, error, small, or code utility classes. Use `ToolbarText` for toolbar identity/title content and `ListInsetText` when list-aligned prose needs full margin/border/padding geometry. | Omit `variant` for the default `p`, choose `h1`–`h6` from the document outline, or choose `span` inside a row, label, or table cell. Independently compose `tone="quiet | danger"`, `size="compact"`, and `font="monospace"`; ordinary native global, `data-_`, and `aria-_` attributes pass through. | Copy, localization, semantic variant, presentation roles, and document heading hierarchy. | `@kerfjs/ui/text` | [Text](./layout.md#text) |
165
165
  | 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) |
166
166
  | Equal-width columns — `Grid` | Equal-width sibling columns need a fixed count or should collapse as their container narrows, while preserving equal tracks despite intrinsic child widths. | Do not use it for intrinsic, asymmetric, spanning, or masonry tracks; use application-owned CSS grid. Do not use it for a user-operable separator; use `ResizableRegion`. | Choose fixed `columns` or typed `minColumnWidth`, plus typed `gap`, optional `flex`, and physical-side `textInsets` / `controlInsets` when the track group needs a standard text or control inset; text wins on overlap. | Child semantics/content, outer width, fixed count or minimum width, and typed gap/flex/inset choices. | `@kerfjs/ui/grid` | [Grid](./layout.md#grid) |
@@ -393,8 +393,14 @@ When the expanded toolbar field has focus, its inset surface uses
393
393
  `--kui-token-search-background` or the default surface color if that token is
394
394
  unset.
395
395
 
396
+ `ToolbarControlGroup.tileTone` selects `neutral`, `brand`, `success`, `warning`, or `danger` quiet fill, matching quiet border, and on-quiet foreground for a non-interactive icon tile. Compose a contained `single` group whose only child is a direct decorative LucideIcon (`aria-hidden="true"`). Omission preserves the normal group palette. The prop does not recolor interactive, mixed, multi-control, or borderless groups; keep real actions in controls with their existing focus/hover/pressed treatments.
397
+
396
398
  ## Toolbar composition
397
399
 
400
+ Use `ToolbarText tone="dark"` on a loud or photo-backed toolbar surface to
401
+ match dark control groups. It applies to read-only headings and actionable
402
+ titles at every size; default tone retains existing identity and heading colors.
403
+
398
404
  A `FloatingToolbar` accepts `ToolbarControlGroup` directly as its children in
399
405
  both floating and inline placement. Name the toolbar with `label`; group its
400
406
  controls as you would in a `Toolbar` zone.
@@ -459,6 +465,29 @@ the control's dimensions, shows `LoadingSpinner` in its icon slot, sets
459
465
  | A command menu | `<ToolbarControlGroup single nestedDropdown><PopupMenu … /></ToolbarControlGroup>` | Register `@kerfjs/ui/popup-menu/register` once; set `menuInset` on the group |
460
466
  | A collapsible search box | `<ToolbarControlGroup single><TokenSearchField collapsible … /></ToolbarControlGroup>` | The group animates the iconic ↔ expanded states; `wireTokenSearchFields` manages expand/collapse/focus by default |
461
467
 
468
+ ### Application surfaces below search
469
+
470
+ Pass `expandedOverflow="visible"` to `ToolbarControlGroup content="search"`
471
+ when an application-owned suggestion list, date picker, or help surface extends
472
+ below it. The group is the positioning containing block, retains auto height,
473
+ and permits overflow only while `expanded` is true. Omission or `"clip"` keeps
474
+ existing behavior, including Kerf's built-in suggestions. Other content modes
475
+ and collapsed searches keep their existing overflow rules.
476
+
477
+ ```tsx
478
+ <ToolbarControlGroup content="search" expanded={open} expandedOverflow="visible">
479
+ <TokenSearchField id="ticket-search" label="Search tickets" presentation="toolbar-group" collapsible expanded={open} />
480
+ {open ? <AppDatePicker data-token-search-keep-open /> : null}
481
+ </ToolbarControlGroup>
482
+ ```
483
+
484
+ The application owns placement (for example absolute positioning below the
485
+ group), stacking, dismissal, and hiding/removing its surface on collapse. Mark
486
+ focusable floating content `data-token-search-keep-open`, or configure
487
+ `collapsible.keepOpenOn`, to keep an empty field open when focus enters it.
488
+ This prop does not escape clipping imposed by an ancestor or create a top-layer
489
+ popover. Do not override the group's position, height, or overflow in app CSS.
490
+
462
491
  ### Popup menu migration
463
492
 
464
493
  A **popup menu in a toolbar** is a `PopupMenu` (`@kerfjs/ui/popup-menu`) in a
@@ -645,3 +674,28 @@ replaces it (`PopupMenu` renders `wa-dropdown`; `Select` renders `wa-select` /
645
674
 
646
675
  All other entries in the [Web Awesome theme contract](./webawesome-theme.md#coverage)
647
676
  remain supported when their native semantic contract matches the product need.
677
+
678
+ ### Toolbar width visibility
679
+
680
+ `ToolbarText` and `ToolbarControlGroup` accept typed `hideBelow` and
681
+ `showBelow` CSS lengths. Call `wireToolbarVisibility` with the application root from
682
+ `@kerfjs/ui/wire-toolbar-visibility` after mounting, and call its disposer when
683
+ the application unmounts. The nearest Toolbar's **content-box width**, excluding
684
+ padding, borders, and safe-area insets, determines visibility. `hideBelow={px(416)}`
685
+ hides strictly below 416px; `showBelow={px(416)}` shows strictly below 416px. At
686
+ 416px the first is visible and the second hidden. Together they define the visible
687
+ interval `[hideBelow, showBelow)`. Width rules intersect existing visibility and
688
+ expanded-state rules; they never force a CSS-hidden group visible.
689
+
690
+ Use `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, or `calc`/`plus` to construct
691
+ lengths. Percentages resolve against that content box, `em` uses the child item's
692
+ font size, and custom properties use its inherited and own token context. The
693
+ helper follows resizes, theme/token/font changes, inserted items, nested toolbars,
694
+ and relocated groups. Invalid, unresolved, negative, or contradictory thresholds
695
+ leave the item visible under this width policy. Server-rendered content is visible
696
+ until wiring runs; without browser observers, initial wiring and window resize
697
+ still update it. Dispose to remove measurement probes and restore prior markers.
698
+
699
+ Hidden controls leave layout and keyboard navigation. A hidden busy group also
700
+ hides only its own adjacent busy status. Keep primary actions always available;
701
+ show a complementary overflow group for secondary actions at narrow widths.
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="24" y="24" width="208" height="52"/></clipPath><clipPath id="ov1"><rect x="24" y="24" width="208" height="52" rx="0"/></clipPath><clipPath id="cp2"><rect x="28" y="28" width="91.9" height="44"/></clipPath><clipPath id="ov3"><rect x="28" y="28" width="91.9" height="44" rx="0"/></clipPath><clipPath id="cp4"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="ct5"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="cp6"><rect x="250" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="302" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="36" y="54.59" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="14" font-weight="650" fill="rgb(194,194,198)">Workspace</text></g></g></g></g></g></g><rect x="236" y="28" width="44" height="44" rx="22" fill="rgba(253,253,255,0.133)"/><rect x="236.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><rect x="238.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(194, 194, 198)"><clipPath id="svgic7"><rect x="250" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(250 42)scale(.66667)"><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(194, 194, 198)" 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(194, 194, 198)" 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(194, 194, 198)" 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(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="288" y="28" width="44" height="44" rx="22" fill="rgba(253,253,255,0.133)"/><rect x="288.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><rect x="290.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(194, 194, 198)"><clipPath id="svgic9"><rect x="302" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(302 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M15 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="24" y="24" width="208" height="52"/></clipPath><clipPath id="ov1"><rect x="24" y="24" width="208" height="52" rx="0"/></clipPath><clipPath id="cp2"><rect x="28" y="28" width="91.9" height="44"/></clipPath><clipPath id="ov3"><rect x="28" y="28" width="91.9" height="44" rx="0"/></clipPath><clipPath id="cp4"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="ct5"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="cp6"><rect x="250" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="302" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="36" y="54.59" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="14" font-weight="650" fill="rgb(98,98,103)">Workspace</text></g></g></g></g></g></g><rect x="236" y="28" width="44" height="44" rx="22" fill="rgba(0,0,49,0.1)"/><rect x="236.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><rect x="238.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(98, 98, 103)"><clipPath id="svgic7"><rect x="250" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(250 42)scale(.66667)"><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(98, 98, 103)" 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(98, 98, 103)" 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(98, 98, 103)" 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(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="288" y="28" width="44" height="44" rx="22" fill="rgba(0,0,49,0.1)"/><rect x="288.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><rect x="290.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(98, 98, 103)"><clipPath id="svgic9"><rect x="302" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(302 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M9 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M15 3v18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="24" y="24" width="448" height="52"/></clipPath><clipPath id="ov1"><rect x="24" y="24" width="448" height="52" rx="0"/></clipPath><clipPath id="cp2"><rect x="28" y="28" width="91.9" height="44"/></clipPath><clipPath id="ov3"><rect x="28" y="28" width="91.9" height="44" rx="0"/></clipPath><clipPath id="cp4"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="ct5"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="cp6"><rect x="490" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="36" y="54.59" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="14" font-weight="650" fill="rgb(194,194,198)">Workspace</text></g></g></g></g></g></g><rect x="476" y="28" width="44" height="44" rx="22" fill="rgba(253,253,255,0.133)"/><rect x="476.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><rect x="478.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(194, 194, 198)"><clipPath id="svgic7"><rect x="490" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(490 42)scale(.66667)"><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(194, 194, 198)" 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(194, 194, 198)" 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(194, 194, 198)" 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(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="528" y="28" width="84" height="44" rx="22" fill="rgba(253,253,255,0.133)"/><rect x="528.5" y="28.5" width="83" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(194, 194, 198)"><clipPath id="svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(542 42)scale(.66667)"><path d="M10 20a1 1 0 0 0 .6.9l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .5-1.3l7.2-8A1 1 0 0 0 21 3H3a1 1 0 0 0-.7 1.7l7.2 8A2 2 0 0 1 10 14Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp10)"><g color="rgb(194, 194, 198)"><clipPath id="svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="24" y="24" width="448" height="52"/></clipPath><clipPath id="ov1"><rect x="24" y="24" width="448" height="52" rx="0"/></clipPath><clipPath id="cp2"><rect x="28" y="28" width="91.9" height="44"/></clipPath><clipPath id="ov3"><rect x="28" y="28" width="91.9" height="44" rx="0"/></clipPath><clipPath id="cp4"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="ct5"><rect x="36" y="41.6" width="75.9" height="16.8"/></clipPath><clipPath id="cp6"><rect x="490" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="36" y="54.59" font-family="&quot;ui-sans-serif&quot;, &quot;-apple-system&quot;, &quot;system-ui&quot;, &quot;Segoe UI&quot;, sans-serif" font-size="14" font-weight="650" fill="rgb(98,98,103)">Workspace</text></g></g></g></g></g></g><rect x="476" y="28" width="44" height="44" rx="22" fill="rgba(0,0,49,0.1)"/><rect x="476.5" y="28.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><rect x="478.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(98, 98, 103)"><clipPath id="svgic7"><rect x="490" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(490 42)scale(.66667)"><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(98, 98, 103)" 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(98, 98, 103)" 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(98, 98, 103)" 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(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="528" y="28" width="84" height="44" rx="22" fill="rgba(0,0,49,0.1)"/><rect x="528.5" y="28.5" width="83" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(98, 98, 103)"><clipPath id="svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(542 42)scale(.66667)"><path d="M10 20a1 1 0 0 0 .6.9l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .5-1.3l7.2-8A1 1 0 0 0 21 3H3a1 1 0 0 0-.7 1.7l7.2 8A2 2 0 0 1 10 14Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp10)"><g color="rgb(98, 98, 103)"><clipPath id="svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(34,43,48)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(138, 203, 255)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(235,244,252)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(166,207,242)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(12, 98, 243)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(44,30,32)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(101,37,40)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(255, 105, 108)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(255, 105, 108)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(255, 105, 108)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(254,237,238)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(249,173,175)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(194, 11, 32)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 11, 32)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 11, 32)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgba(228,228,255,0.075)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.125)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(194, 194, 198)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(194, 194, 198)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgba(0,0,98,0.05)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgba(0,0,49,0.1)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(98, 98, 103)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(98, 98, 103)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(31,52,38)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(36,83,49)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(99, 230, 133)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(99, 230, 133)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(99, 230, 133)" 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>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 96" width="520" height="96"><defs><clipPath id="cp0"><rect x="22" y="22" width="40" height="40"/></clipPath></defs><rect x="20" y="20" width="44" height="44" rx="22" fill="rgb(227,247,232)"/><rect x="20.5" y="20.5" width="43" height="43" rx="21.5" fill="none" stroke="rgb(190,237,202)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(0, 127, 46)"><clipPath id="svgic1"><rect x="34" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(34 34)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(0, 127, 46)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="12" cy="12" r="3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(0, 127, 46)" 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>