@ds-mo/ui 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/dist/components/Accordion/Accordion.d.ts +29 -0
  2. package/dist/components/Accordion/Accordion.d.ts.map +1 -0
  3. package/dist/components/Accordion/index.d.ts +3 -0
  4. package/dist/components/Accordion/index.d.ts.map +1 -0
  5. package/dist/components/Badge/Badge.d.ts +18 -0
  6. package/dist/components/Badge/Badge.d.ts.map +1 -0
  7. package/dist/components/Badge/index.d.ts +3 -0
  8. package/dist/components/Badge/index.d.ts.map +1 -0
  9. package/dist/components/Banner/Banner.d.ts +16 -0
  10. package/dist/components/Banner/Banner.d.ts.map +1 -0
  11. package/dist/components/Banner/index.d.ts +3 -0
  12. package/dist/components/Banner/index.d.ts.map +1 -0
  13. package/dist/components/Breadcrumb/Breadcrumb.d.ts +15 -0
  14. package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +1 -0
  15. package/dist/components/Breadcrumb/index.d.ts +3 -0
  16. package/dist/components/Breadcrumb/index.d.ts.map +1 -0
  17. package/dist/components/Button/Button.d.ts +85 -0
  18. package/dist/components/Button/Button.d.ts.map +1 -0
  19. package/dist/components/Button/index.d.ts +3 -0
  20. package/dist/components/Button/index.d.ts.map +1 -0
  21. package/dist/components/ButtonGroup/ButtonGroup.d.ts +26 -0
  22. package/dist/components/ButtonGroup/ButtonGroup.d.ts.map +1 -0
  23. package/dist/components/ButtonGroup/index.d.ts +3 -0
  24. package/dist/components/ButtonGroup/index.d.ts.map +1 -0
  25. package/dist/components/Card/Card.d.ts +20 -0
  26. package/dist/components/Card/Card.d.ts.map +1 -0
  27. package/dist/components/Card/index.d.ts +3 -0
  28. package/dist/components/Card/index.d.ts.map +1 -0
  29. package/dist/components/Checkbox/Checkbox.d.ts +18 -0
  30. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -0
  31. package/dist/components/Checkbox/index.d.ts +3 -0
  32. package/dist/components/Checkbox/index.d.ts.map +1 -0
  33. package/dist/components/Divider/Divider.d.ts +9 -0
  34. package/dist/components/Divider/Divider.d.ts.map +1 -0
  35. package/dist/components/Divider/index.d.ts +3 -0
  36. package/dist/components/Divider/index.d.ts.map +1 -0
  37. package/dist/components/EmptyState/EmptyState.d.ts +9 -0
  38. package/dist/components/EmptyState/EmptyState.d.ts.map +1 -0
  39. package/dist/components/EmptyState/index.d.ts +3 -0
  40. package/dist/components/EmptyState/index.d.ts.map +1 -0
  41. package/dist/components/ErrorBoundary/ErrorBoundary.d.ts +18 -0
  42. package/dist/components/ErrorBoundary/ErrorBoundary.d.ts.map +1 -0
  43. package/dist/components/ErrorBoundary/index.d.ts +3 -0
  44. package/dist/components/ErrorBoundary/index.d.ts.map +1 -0
  45. package/dist/components/Fade/Fade.d.ts +11 -0
  46. package/dist/components/Fade/Fade.d.ts.map +1 -0
  47. package/dist/components/Fade/index.d.ts +3 -0
  48. package/dist/components/Fade/index.d.ts.map +1 -0
  49. package/dist/components/Field/Field.d.ts +9 -0
  50. package/dist/components/Field/Field.d.ts.map +1 -0
  51. package/dist/components/Field/index.d.ts +3 -0
  52. package/dist/components/Field/index.d.ts.map +1 -0
  53. package/dist/components/Header/Header.d.ts +12 -0
  54. package/dist/components/Header/Header.d.ts.map +1 -0
  55. package/dist/components/Header/index.d.ts +3 -0
  56. package/dist/components/Header/index.d.ts.map +1 -0
  57. package/dist/components/Input/Input.d.ts +27 -0
  58. package/dist/components/Input/Input.d.ts.map +1 -0
  59. package/dist/components/Input/index.d.ts +3 -0
  60. package/dist/components/Input/index.d.ts.map +1 -0
  61. package/dist/components/LabelWrap/LabelWrap.d.ts +27 -0
  62. package/dist/components/LabelWrap/LabelWrap.d.ts.map +1 -0
  63. package/dist/components/LabelWrap/index.d.ts +2 -0
  64. package/dist/components/LabelWrap/index.d.ts.map +1 -0
  65. package/dist/components/Loader/Loader.d.ts +33 -0
  66. package/dist/components/Loader/Loader.d.ts.map +1 -0
  67. package/dist/components/Loader/index.d.ts +3 -0
  68. package/dist/components/Loader/index.d.ts.map +1 -0
  69. package/dist/components/Menu/DestructiveMenuItem.d.ts +12 -0
  70. package/dist/components/Menu/DestructiveMenuItem.d.ts.map +1 -0
  71. package/dist/components/Menu/Menu.d.ts +55 -0
  72. package/dist/components/Menu/Menu.d.ts.map +1 -0
  73. package/dist/components/Menu/MenuItem.d.ts +33 -0
  74. package/dist/components/Menu/MenuItem.d.ts.map +1 -0
  75. package/dist/components/Menu/index.d.ts +7 -0
  76. package/dist/components/Menu/index.d.ts.map +1 -0
  77. package/dist/components/Modal/Modal.d.ts +15 -0
  78. package/dist/components/Modal/Modal.d.ts.map +1 -0
  79. package/dist/components/Modal/index.d.ts +3 -0
  80. package/dist/components/Modal/index.d.ts.map +1 -0
  81. package/dist/components/Pagination/Pagination.d.ts +16 -0
  82. package/dist/components/Pagination/Pagination.d.ts.map +1 -0
  83. package/dist/components/Pagination/index.d.ts +3 -0
  84. package/dist/components/Pagination/index.d.ts.map +1 -0
  85. package/dist/components/Radio/Radio.d.ts +35 -0
  86. package/dist/components/Radio/Radio.d.ts.map +1 -0
  87. package/dist/components/Radio/index.d.ts +3 -0
  88. package/dist/components/Radio/index.d.ts.map +1 -0
  89. package/dist/components/Scrollbar/Scrollbar.d.ts +13 -0
  90. package/dist/components/Scrollbar/Scrollbar.d.ts.map +1 -0
  91. package/dist/components/Scrollbar/index.d.ts +3 -0
  92. package/dist/components/Scrollbar/index.d.ts.map +1 -0
  93. package/dist/components/Select/Select.d.ts +22 -0
  94. package/dist/components/Select/Select.d.ts.map +1 -0
  95. package/dist/components/Select/index.d.ts +3 -0
  96. package/dist/components/Select/index.d.ts.map +1 -0
  97. package/dist/components/Sidebar/Sidebar.d.ts +15 -0
  98. package/dist/components/Sidebar/Sidebar.d.ts.map +1 -0
  99. package/dist/components/Sidebar/SidebarItem.d.ts +14 -0
  100. package/dist/components/Sidebar/SidebarItem.d.ts.map +1 -0
  101. package/dist/components/Sidebar/SidebarSection.d.ts +10 -0
  102. package/dist/components/Sidebar/SidebarSection.d.ts.map +1 -0
  103. package/dist/components/Sidebar/index.d.ts +7 -0
  104. package/dist/components/Sidebar/index.d.ts.map +1 -0
  105. package/dist/components/Skeleton/Skeleton.d.ts +17 -0
  106. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
  107. package/dist/components/Skeleton/index.d.ts +3 -0
  108. package/dist/components/Skeleton/index.d.ts.map +1 -0
  109. package/dist/components/Slider/Slider.d.ts +16 -0
  110. package/dist/components/Slider/Slider.d.ts.map +1 -0
  111. package/dist/components/Slider/index.d.ts +3 -0
  112. package/dist/components/Slider/index.d.ts.map +1 -0
  113. package/dist/components/Surface/Surface.d.ts +59 -0
  114. package/dist/components/Surface/Surface.d.ts.map +1 -0
  115. package/dist/components/Surface/index.d.ts +3 -0
  116. package/dist/components/Surface/index.d.ts.map +1 -0
  117. package/dist/components/Tab/Tab.d.ts +21 -0
  118. package/dist/components/Tab/Tab.d.ts.map +1 -0
  119. package/dist/components/Tab/index.d.ts +3 -0
  120. package/dist/components/Tab/index.d.ts.map +1 -0
  121. package/dist/components/TabGroup/TabGroup.d.ts +26 -0
  122. package/dist/components/TabGroup/TabGroup.d.ts.map +1 -0
  123. package/dist/components/TabGroup/index.d.ts +3 -0
  124. package/dist/components/TabGroup/index.d.ts.map +1 -0
  125. package/dist/components/Table/Table.d.ts +46 -0
  126. package/dist/components/Table/Table.d.ts.map +1 -0
  127. package/dist/components/Table/index.d.ts +3 -0
  128. package/dist/components/Table/index.d.ts.map +1 -0
  129. package/dist/components/Tag/Tag.d.ts +38 -0
  130. package/dist/components/Tag/Tag.d.ts.map +1 -0
  131. package/dist/components/Tag/index.d.ts +3 -0
  132. package/dist/components/Tag/index.d.ts.map +1 -0
  133. package/dist/components/Text/Text.d.ts +41 -0
  134. package/dist/components/Text/Text.d.ts.map +1 -0
  135. package/dist/components/Text/index.d.ts +3 -0
  136. package/dist/components/Text/index.d.ts.map +1 -0
  137. package/dist/components/Toast/Toast.d.ts +33 -0
  138. package/dist/components/Toast/Toast.d.ts.map +1 -0
  139. package/dist/components/Toast/index.d.ts +3 -0
  140. package/dist/components/Toast/index.d.ts.map +1 -0
  141. package/dist/components/Toggle/Toggle.d.ts +17 -0
  142. package/dist/components/Toggle/Toggle.d.ts.map +1 -0
  143. package/dist/components/Toggle/index.d.ts +3 -0
  144. package/dist/components/Toggle/index.d.ts.map +1 -0
  145. package/dist/components/ToggleButton/ToggleButton.d.ts +35 -0
  146. package/dist/components/ToggleButton/ToggleButton.d.ts.map +1 -0
  147. package/dist/components/ToggleButton/index.d.ts +3 -0
  148. package/dist/components/ToggleButton/index.d.ts.map +1 -0
  149. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.ts +24 -0
  150. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.ts.map +1 -0
  151. package/dist/components/ToggleButtonGroup/index.d.ts +3 -0
  152. package/dist/components/ToggleButtonGroup/index.d.ts.map +1 -0
  153. package/dist/components/Tooltip/Tooltip.d.ts +17 -0
  154. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -0
  155. package/dist/components/Tooltip/index.d.ts +3 -0
  156. package/dist/components/Tooltip/index.d.ts.map +1 -0
  157. package/dist/index.css +1 -1
  158. package/dist/index.d.ts +82 -969
  159. package/dist/index.d.ts.map +1 -0
  160. package/dist/index.js +1641 -1165
  161. package/dist/index.js.map +1 -1
  162. package/dist/r/badge.json +1 -1
  163. package/dist/r/banner.json +2 -2
  164. package/dist/r/loader.json +2 -2
  165. package/dist/r/menu.json +4 -4
  166. package/dist/r/select.json +1 -1
  167. package/dist/r/tab-group.json +1 -1
  168. package/dist/r/tab.json +1 -1
  169. package/dist/r/toast.json +1 -1
  170. package/dist/r/toggle.json +1 -1
  171. package/dist/types/icons.d.ts +14 -0
  172. package/dist/types/icons.d.ts.map +1 -0
  173. package/dist/types/index.d.ts +2 -0
  174. package/dist/types/index.d.ts.map +1 -0
  175. package/dist/utils/cn.d.ts +5 -0
  176. package/dist/utils/cn.d.ts.map +1 -0
  177. package/dist/utils/css-tokens.d.ts +11 -0
  178. package/dist/utils/css-tokens.d.ts.map +1 -0
  179. package/package.json +17 -12
  180. package/src/components/Accordion/Accordion.tsx +10 -1
  181. package/src/components/Badge/Badge.stories.tsx +32 -0
  182. package/src/components/Badge/Badge.tsx +19 -2
  183. package/src/components/Banner/Banner.module.css +38 -0
  184. package/src/components/Banner/Banner.tsx +34 -4
  185. package/src/components/Button/Button.mdx +143 -0
  186. package/src/components/Button/Button.stories.tsx +1 -1
  187. package/src/components/Button/Button.tsx +42 -11
  188. package/src/components/Checkbox/Checkbox.tsx +6 -3
  189. package/src/components/Field/Field.tsx +20 -7
  190. package/src/components/Input/Input.module.css +21 -0
  191. package/src/components/Input/Input.tsx +62 -21
  192. package/src/components/Loader/Loader.module.css +17 -0
  193. package/src/components/Loader/Loader.stories.tsx +9 -0
  194. package/src/components/Loader/Loader.tsx +42 -20
  195. package/src/components/Menu/DestructiveMenuItem.tsx +59 -6
  196. package/src/components/Menu/Menu.tsx +160 -11
  197. package/src/components/Menu/MenuItem.module.css +2 -0
  198. package/src/components/Menu/MenuItem.tsx +48 -5
  199. package/src/components/Modal/Modal.tsx +81 -4
  200. package/src/components/Radio/Radio.tsx +117 -29
  201. package/src/components/Scrollbar/Scrollbar.module.css +5 -0
  202. package/src/components/Scrollbar/Scrollbar.tsx +18 -4
  203. package/src/components/Select/Select.tsx +139 -9
  204. package/src/components/Sidebar/Sidebar.module.css +7 -0
  205. package/src/components/Sidebar/Sidebar.tsx +102 -4
  206. package/src/components/Slider/Slider.module.css +5 -1
  207. package/src/components/Slider/Slider.stories.tsx +25 -0
  208. package/src/components/Slider/Slider.tsx +4 -4
  209. package/src/components/Tab/Tab.tsx +32 -2
  210. package/src/components/TabGroup/TabGroup.stories.tsx +46 -15
  211. package/src/components/TabGroup/TabGroup.tsx +77 -10
  212. package/src/components/Table/Table.module.css +10 -0
  213. package/src/components/Table/Table.tsx +58 -29
  214. package/src/components/Tag/Tag.tsx +5 -2
  215. package/src/components/Toast/Toast.tsx +44 -8
  216. package/src/components/Toggle/Toggle.tsx +23 -22
  217. package/src/components/Tooltip/Tooltip.tsx +42 -6
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/components/Text/Text.module.css","../src/components/Text/Text.tsx","../src/components/Surface/Surface.module.css","../src/components/Surface/Surface.tsx","../src/components/Card/Card.module.css","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/components/LabelWrap/LabelWrap.module.css","../src/components/LabelWrap/LabelWrap.tsx","../src/components/Loader/Loader.module.css","../src/components/Loader/Loader.tsx","../src/components/Button/Button.module.css","../src/components/Button/Button.tsx","../src/components/ToggleButton/ToggleButton.module.css","../src/components/ToggleButton/ToggleButton.tsx","../src/components/ButtonGroup/ButtonGroup.module.css","../src/components/ButtonGroup/ButtonGroup.tsx","../src/components/ToggleButtonGroup/ToggleButtonGroup.module.css","../src/components/ToggleButtonGroup/ToggleButtonGroup.tsx","../src/components/Tag/Tag.module.css","../src/components/Tag/Tag.tsx","../src/components/Badge/Badge.module.css","../src/components/Badge/Badge.tsx","../src/components/Toggle/Toggle.module.css","../src/components/Toggle/Toggle.tsx","../src/components/Checkbox/Checkbox.module.css","../src/components/Checkbox/Checkbox.tsx","../src/components/Input/Input.module.css","../src/components/Input/Input.tsx","../src/components/Slider/Slider.module.css","../src/components/Slider/Slider.tsx","../src/components/Field/Field.module.css","../src/components/Field/Field.tsx","../src/components/Modal/Modal.module.css","../src/components/Modal/Modal.tsx","../src/components/Menu/MenuItem.module.css","../src/components/Menu/MenuItem.tsx","../src/components/Menu/DestructiveMenuItem.module.css","../src/components/Menu/DestructiveMenuItem.tsx","../src/utils/css-tokens.ts","../src/components/Menu/Menu.module.css","../src/components/Menu/Menu.tsx","../src/components/Tooltip/Tooltip.module.css","../src/components/Tooltip/Tooltip.tsx","../src/components/Select/Select.module.css","../src/components/Select/Select.tsx","../src/components/Banner/Banner.module.css","../src/components/Banner/Banner.tsx","../src/components/Table/Table.module.css","../src/components/Table/Table.tsx","../src/components/Tab/Tab.module.css","../src/components/Tab/Tab.tsx","../src/components/EmptyState/EmptyState.module.css","../src/components/EmptyState/EmptyState.tsx","../src/components/Fade/Fade.module.css","../src/components/Fade/Fade.tsx","../src/components/Scrollbar/Scrollbar.module.css","../src/components/Scrollbar/Scrollbar.tsx","../src/components/ErrorBoundary/ErrorBoundary.module.css","../src/components/ErrorBoundary/ErrorBoundary.tsx","../src/components/Sidebar/Sidebar.module.css","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/SidebarSection.tsx","../src/components/Sidebar/SidebarItem.tsx","../src/components/Header/Header.module.css","../src/components/Header/Header.tsx","../src/components/Radio/Radio.module.css","../src/components/Radio/Radio.tsx","../src/components/TabGroup/TabGroup.module.css","../src/components/TabGroup/TabGroup.tsx","../src/components/Accordion/Accordion.module.css","../src/components/Accordion/Accordion.tsx","../src/components/Breadcrumb/Breadcrumb.module.css","../src/components/Breadcrumb/Breadcrumb.tsx","../src/components/Pagination/Pagination.module.css","../src/components/Pagination/Pagination.tsx","../src/components/Divider/Divider.module.css","../src/components/Divider/Divider.tsx","../src/components/Skeleton/Skeleton.module.css","../src/components/Skeleton/Skeleton.tsx","../src/components/Toast/Toast.module.css","../src/components/Toast/Toast.tsx"],"sourcesContent":[".text {\n margin: 0;\n}\n\n/* ============================================\n LINE TRUNCATION\n ============================================ */\n\n.truncate1Line {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.truncate2Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate3Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate4Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 4;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate5Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.noTruncation {\n word-break: break-word;\n white-space: normal;\n}\n\n.wrapNowrap {\n white-space: nowrap;\n word-break: normal;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.wrapBalance {\n text-wrap: balance;\n}\n\n.wrapPretty {\n text-wrap: pretty;\n}\n\n/* ============================================\n TEXT COLOR - Semantic Tokens\n ============================================ */\n\n.colorPrimary {\n color: var(--color-foreground-primary);\n}\n\n.colorSecondary {\n color: var(--color-foreground-secondary);\n}\n\n.colorTertiary {\n color: var(--color-foreground-tertiary);\n}\n\n.colorBrand {\n color: var(--color-foreground-bold-brand);\n}\n\n.colorNegative {\n color: var(--color-foreground-bold-negative);\n}\n\n.colorPositive {\n color: var(--color-foreground-bold-positive);\n}\n\n.colorWarning {\n color: var(--color-foreground-bold-warning);\n}\n\n.colorCaution {\n color: var(--color-foreground-bold-caution);\n}\n\n.colorAi {\n color: var(--color-foreground-bold-ai);\n}\n\n.colorOnStrong {\n color: var(--color-foreground-on-strong-background-primary);\n}\n\n.colorOnBold {\n color: var(--color-foreground-on-bold-background-primary);\n}\n\n.colorInherit {\n color: inherit;\n}\n\n/* ============================================\n TEXT DECORATION\n ============================================ */\n\n.decorationNone {\n text-decoration: none;\n}\n\n.decorationUnderline {\n text-decoration: underline;\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n}\n\n.decorationDottedUnderline {\n text-decoration: underline dotted;\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n}\n\n/* ============================================\n FONT STYLE\n ============================================ */\n\n.italic {\n font-style: italic;\n}\n\n/* ============================================\n TEXT ALIGNMENT\n ============================================ */\n\n.alignLeft {\n text-align: left;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.alignRight {\n text-align: right;\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Text.module.css';\n\n/**\n * Text variant options.\n * Each variant maps to a TokoMo typography class with predefined font-size, line-height,\n * font-weight, and letter-spacing.\n */\nexport type TextVariant =\n | 'text-display-medium'\n | 'text-display-small'\n | 'text-title-large'\n | 'text-title-medium'\n | 'text-title-small'\n | 'text-body-large'\n | 'text-body-large-emphasis'\n | 'text-body-medium'\n | 'text-body-medium-emphasis'\n | 'text-body-small'\n | 'text-body-small-emphasis'\n | 'text-caption'\n | 'text-caption-emphasis';\n\n/** @deprecated Use `TextVariant` instead. */\nexport type TextStyle = TextVariant;\n\n/**\n * Semantic color tokens for text.\n * Maps to TokoMo --color-foreground-* CSS custom properties.\n */\nexport type TextColorToken =\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'brand'\n | 'negative'\n | 'positive'\n | 'warning'\n | 'caution'\n | 'ai'\n | 'on-strong'\n | 'on-bold'\n | 'inherit';\n\n/** Text color — semantic token or CSS variable escape hatch. */\nexport type TextColor = TextColorToken | `var(--${string})`;\n\nexport type TextDecoration = 'none' | 'underline' | 'dotted-underline';\nexport type TextAlign = 'left' | 'center' | 'right';\nexport type LineTruncation = 1 | 2 | 3 | 4 | 5 | 'none';\nexport type TextWrap = 'wrap' | 'nowrap' | 'balance' | 'pretty';\nexport type TextElement = 'p' | 'span' | 'div' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\nexport interface TextProps {\n /** Typography variant. Maps to a TokoMo typography class. Defaults to 'text-body-medium'. */\n variant?: TextVariant;\n children: React.ReactNode;\n\n // Appearance\n color?: TextColor;\n decoration?: TextDecoration;\n italic?: boolean;\n align?: TextAlign;\n\n // Truncation / wrap\n /** Max lines before ellipsis. Ignored when wrap is 'nowrap'. Defaults to 'none'. */\n lineTruncation?: LineTruncation;\n /** 'nowrap' = single line, truncates with ellipsis when constrained. */\n wrap?: TextWrap;\n\n // Semantic HTML\n as?: TextElement;\n id?: string;\n htmlFor?: string;\n\n // Escape hatches\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst colorClassMap: Record<TextColorToken, string> = {\n primary: styles.colorPrimary,\n secondary: styles.colorSecondary,\n tertiary: styles.colorTertiary,\n brand: styles.colorBrand,\n negative: styles.colorNegative,\n positive: styles.colorPositive,\n warning: styles.colorWarning,\n caution: styles.colorCaution,\n ai: styles.colorAi,\n 'on-strong': styles.colorOnStrong,\n 'on-bold': styles.colorOnBold,\n inherit: styles.colorInherit,\n};\n\nconst decorationClassMap: Record<TextDecoration, string> = {\n none: styles.decorationNone,\n underline: styles.decorationUnderline,\n 'dotted-underline': styles.decorationDottedUnderline,\n};\n\nconst alignClassMap: Record<TextAlign, string> = {\n left: styles.alignLeft,\n center: styles.alignCenter,\n right: styles.alignRight,\n};\n\nconst truncationClassMap: Record<LineTruncation, string> = {\n 1: styles.truncate1Line,\n 2: styles.truncate2Lines,\n 3: styles.truncate3Lines,\n 4: styles.truncate4Lines,\n 5: styles.truncate5Lines,\n none: styles.noTruncation,\n};\n\nconst isCustomColor = (color: TextColor): color is `var(--${string})` =>\n color.startsWith('var(--');\n\nexport const Text = forwardRef<HTMLElement, TextProps>(\n (\n {\n variant = 'text-body-medium',\n children,\n color,\n decoration,\n italic,\n align,\n lineTruncation = 'none',\n wrap,\n as: Component = 'p',\n id,\n htmlFor,\n className = '',\n style,\n },\n ref\n ) => {\n const wrapClass =\n wrap === 'nowrap' ? styles.wrapNowrap\n : wrap === 'balance' ? styles.wrapBalance\n : wrap === 'pretty' ? styles.wrapPretty\n : '';\n const truncationClass =\n wrap === 'nowrap' ? '' : truncationClassMap[lineTruncation];\n\n const classes = [\n variant,\n styles.text,\n wrapClass,\n truncationClass,\n color && !isCustomColor(color) ? colorClassMap[color] : '',\n decoration ? decorationClassMap[decoration] : '',\n italic ? styles.italic : '',\n align ? alignClassMap[align] : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const computedStyle: React.CSSProperties = {\n ...style,\n ...(color && isCustomColor(color) ? { color } : {}),\n };\n\n const props: React.HTMLAttributes<HTMLElement> & { htmlFor?: string } = {\n className: classes,\n style: Object.keys(computedStyle).length > 0 ? computedStyle : undefined,\n ...(id ? { id } : {}),\n ...(Component === 'label' && htmlFor ? { htmlFor } : {}),\n };\n\n return (\n <Component ref={ref as React.Ref<never>} {...props}>\n {children}\n </Component>\n );\n }\n);\n\nText.displayName = 'Text';\n","/**\n * Surface — lean container primitive.\n * Backgrounds, elevation, edges, radius, and interactive states.\n * Hover/pressed via direct background-color + color-mix(). No pseudo-element overlays.\n */\n\n.surface {\n box-sizing: border-box;\n position: relative;\n /* Reset native button/anchor chrome when rendered as those elements */\n border: none;\n padding: 0;\n margin: 0;\n font: inherit;\n color: inherit;\n background: none;\n text-decoration: none;\n text-align: left;\n cursor: default;\n appearance: none;\n -webkit-appearance: none;\n}\n\n/* ==========================================================================\n Backgrounds\n ========================================================================== */\n\n.bgPrimary {\n background-color: var(--color-background-primary);\n}\n\n.bgSecondary {\n background-color: var(--color-background-secondary);\n}\n\n.bgTransparent {\n background-color: transparent;\n}\n\n.bgTranslucent {\n background-color: var(--color-background-translucent);\n backdrop-filter: blur(var(--effect-blur-md));\n -webkit-backdrop-filter: blur(var(--effect-blur-md));\n}\n\n/* ==========================================================================\n Semantic Intent Backgrounds — intent{Intent}{Contrast}\n ========================================================================== */\n\n/* Brand */\n.intentBrandFaint { background-color: var(--color-background-faint-brand); }\n.intentBrandMedium { background-color: var(--color-background-medium-brand); }\n.intentBrandBold { background-color: var(--color-background-bold-brand); }\n.intentBrandStrong { background-color: var(--color-background-strong-brand); }\n\n/* Positive */\n.intentPositiveFaint { background-color: var(--color-background-faint-positive); }\n.intentPositiveMedium { background-color: var(--color-background-medium-positive); }\n.intentPositiveBold { background-color: var(--color-background-bold-positive); }\n.intentPositiveStrong { background-color: var(--color-background-strong-positive); }\n\n/* Negative */\n.intentNegativeFaint { background-color: var(--color-background-faint-negative); }\n.intentNegativeMedium { background-color: var(--color-background-medium-negative); }\n.intentNegativeBold { background-color: var(--color-background-bold-negative); }\n.intentNegativeStrong { background-color: var(--color-background-strong-negative); }\n\n/* Warning */\n.intentWarningFaint { background-color: var(--color-background-faint-warning); }\n.intentWarningMedium { background-color: var(--color-background-medium-warning); }\n.intentWarningBold { background-color: var(--color-background-bold-warning); }\n.intentWarningStrong { background-color: var(--color-background-strong-warning); }\n\n/* Caution */\n.intentCautionFaint { background-color: var(--color-background-faint-caution); }\n.intentCautionMedium { background-color: var(--color-background-medium-caution); }\n.intentCautionBold { background-color: var(--color-background-bold-caution); }\n.intentCautionStrong { background-color: var(--color-background-strong-caution); }\n\n/* AI */\n.intentAiFaint { background-color: var(--color-background-faint-ai); }\n.intentAiMedium { background-color: var(--color-background-medium-ai); }\n.intentAiBold { background-color: var(--color-background-bold-ai); }\n.intentAiStrong { background-color: var(--color-background-strong-ai); }\n\n/* Neutral */\n.intentNeutralFaint { background-color: var(--color-background-faint-neutral); }\n.intentNeutralMedium { background-color: var(--color-background-medium-neutral); }\n.intentNeutralBold { background-color: var(--color-background-bold-neutral); }\n.intentNeutralStrong { background-color: var(--color-background-strong-neutral); }\n\n/* Walkthrough */\n.intentWalkthroughFaint { background-color: var(--color-background-faint-walkthrough); }\n.intentWalkthroughMedium { background-color: var(--color-background-medium-walkthrough); }\n.intentWalkthroughBold { background-color: var(--color-background-bold-walkthrough); }\n.intentWalkthroughStrong { background-color: var(--color-background-strong-walkthrough); }\n\n/* Guide */\n.intentGuideFaint { background-color: var(--color-background-faint-guide); }\n.intentGuideMedium { background-color: var(--color-background-medium-guide); }\n.intentGuideBold { background-color: var(--color-background-bold-guide); }\n.intentGuideStrong { background-color: var(--color-background-strong-guide); }\n\n/* ==========================================================================\n Elevation — progressive: none → flat → elevated → floating\n ========================================================================== */\n\n.elevationNone {}\n\n.elevationDepressed {\n box-shadow: var(--effect-elevation-depressed-sm);\n}\n\n.elevationDepressedMd {\n box-shadow: var(--effect-elevation-depressed-md);\n}\n\n.elevationFlat {\n box-shadow: var(--effect-elevation-elevated-sm);\n}\n\n.elevationElevated {\n box-shadow: var(--effect-elevation-elevated-md);\n}\n\n.elevationFloating {\n box-shadow: var(--effect-elevation-elevated-floating);\n}\n\n.elevationOverlayTop {\n box-shadow: var(--effect-elevation-elevated-panel-top);\n}\n\n.elevationOverlayRight {\n box-shadow: var(--effect-elevation-elevated-panel-right);\n}\n\n.elevationOverlayBottom {\n box-shadow: var(--effect-elevation-elevated-panel-bottom);\n}\n\n.elevationOverlayLeft {\n box-shadow: var(--effect-elevation-elevated-panel-left);\n}\n\n/* ==========================================================================\n Edge Borders (only when elevation='none')\n ========================================================================== */\n\n.edgeTop { border-top: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeRight { border-right: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeBottom { border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeLeft { border-left: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n\n/* ==========================================================================\n Corner Radius\n ========================================================================== */\n\n.radiusNone { border-radius: var(--dimension-radius-000); }\n.radiusXs { border-radius: var(--dimension-radius-050); }\n.radiusSm { border-radius: var(--dimension-radius-075); }\n.radiusMd { border-radius: var(--dimension-radius-100); }\n.radiusLg { border-radius: var(--dimension-radius-125); }\n.radiusXl { border-radius: var(--dimension-radius-175); }\n.radius2xl { border-radius: var(--dimension-radius-200); }\n.radiusFull { border-radius: var(--dimension-radius-half); }\n\n/* ==========================================================================\n Interactive States — direct background-color, no pseudo-elements\n ========================================================================== */\n\n.interactive {\n cursor: pointer;\n transition: transform var(--effect-motion-short-2);\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n.interactive:hover {\n background-color: var(--_hover-bg);\n}\n\n.interactive:active {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n.interactive:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n/* ==========================================================================\n Selected State — persistent overlay on any background via ::before\n ========================================================================== */\n\n.selected::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 0;\n background-color: var(--color-interaction-hover);\n}\n\n.selected > * {\n position: relative;\n z-index: 1;\n}\n\n/* ==========================================================================\n Inactive State\n ========================================================================== */\n\n.inactive {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Surface.module.css';\n\n/**\n * Semantic intent for colored surfaces.\n * Each intent has four contrast levels (faint, medium, bold, strong).\n */\nexport type SurfaceIntent =\n | 'brand'\n | 'positive'\n | 'negative'\n | 'warning'\n | 'caution'\n | 'ai'\n | 'neutral'\n | 'walkthrough'\n | 'guide';\n\n/** Background type for non-intent surfaces. */\nexport type SurfaceBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\n/** Contrast level for semantic intents. */\nexport type SurfaceContrast = 'faint' | 'medium' | 'bold' | 'strong';\n\n/** Elevation for depth/shadow effects. Progressive: none → flat → elevated → floating. */\nexport type SurfaceElevation =\n | 'none'\n | 'depressed'\n | 'depressed-md'\n | 'flat'\n | 'elevated'\n | 'floating'\n | 'overlayTop'\n | 'overlayRight'\n | 'overlayBottom'\n | 'overlayLeft';\n\n/** Edge divider border direction. */\nexport type SurfaceEdge = 'top' | 'right' | 'bottom' | 'left';\n\n/** Corner radius presets. */\nexport type SurfaceRadiusPreset = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';\n\n/** Corner radius — preset, CSS variable, or custom string (e.g. '12px 12px 0 0'). */\nexport type SurfaceRadius = SurfaceRadiusPreset | (string & {});\n\n/** HTML elements Surface can render as. */\nexport type SurfaceElement =\n | 'div'\n | 'section'\n | 'aside'\n | 'article'\n | 'header'\n | 'footer'\n | 'main'\n | 'nav'\n | 'span'\n | 'button'\n | 'td'\n | 'th';\n\n/** Props shared by both surface modes. */\ninterface SurfaceBaseProps extends React.HTMLAttributes<HTMLElement> {\n children?: React.ReactNode;\n /** Elevation for depth/shadow effects. Defaults to 'none'. */\n elevation?: SurfaceElevation;\n /** Edge divider border(s). Only applies when elevation is 'none'. */\n edge?: SurfaceEdge | SurfaceEdge[];\n /** Corner radius — preset or CSS variable. */\n radius?: SurfaceRadius;\n /** Enable hover/pressed interaction overlay. */\n interactive?: boolean;\n /** Apply selected background state. */\n selected?: boolean;\n /** Dim and disable pointer events. */\n inactive?: boolean;\n /** HTML element to render. Defaults to 'div'. */\n as?: SurfaceElement;\n /** Button type — only used when as='button'. */\n type?: 'button' | 'submit' | 'reset';\n}\n\n/** Non-intent surface — uses a basic background color. */\ninterface SurfaceDefaultProps extends SurfaceBaseProps {\n /** Background color. Defaults to 'transparent'. */\n background?: SurfaceBackground;\n intent?: never;\n contrast?: never;\n}\n\n/** Intent surface — uses a semantic color with contrast level. */\ninterface SurfaceIntentProps extends SurfaceBaseProps {\n /** Semantic intent color. */\n intent: SurfaceIntent;\n /** Contrast level for the intent background. Defaults to 'faint'. */\n contrast?: SurfaceContrast;\n background?: never;\n}\n\nexport type SurfaceProps = SurfaceDefaultProps | SurfaceIntentProps;\n\nconst backgroundClassMap: Record<SurfaceBackground, string> = {\n primary: styles.bgPrimary,\n secondary: styles.bgSecondary,\n transparent: styles.bgTransparent,\n translucent: styles.bgTranslucent,\n};\n\nconst elevationClassMap: Record<SurfaceElevation, string> = {\n none: styles.elevationNone,\n depressed: styles.elevationDepressed,\n 'depressed-md': styles.elevationDepressedMd,\n flat: styles.elevationFlat,\n elevated: styles.elevationElevated,\n floating: styles.elevationFloating,\n overlayTop: styles.elevationOverlayTop,\n overlayRight: styles.elevationOverlayRight,\n overlayBottom: styles.elevationOverlayBottom,\n overlayLeft: styles.elevationOverlayLeft,\n};\n\nconst edgeClassMap: Record<SurfaceEdge, string> = {\n top: styles.edgeTop,\n right: styles.edgeRight,\n bottom: styles.edgeBottom,\n left: styles.edgeLeft,\n};\n\nconst radiusClassMap: Record<SurfaceRadiusPreset, string> = {\n none: styles.radiusNone,\n xs: styles.radiusXs,\n sm: styles.radiusSm,\n md: styles.radiusMd,\n lg: styles.radiusLg,\n xl: styles.radiusXl,\n '2xl': styles.radius2xl,\n full: styles.radiusFull,\n};\n\nconst getIntentContrastClass = (intent: SurfaceIntent, contrast: SurfaceContrast): string => {\n const intentKey = intent.charAt(0).toUpperCase() + intent.slice(1);\n const contrastKey = contrast.charAt(0).toUpperCase() + contrast.slice(1);\n return styles[`intent${intentKey}${contrastKey}`] || '';\n};\n\nconst isPresetRadius = (radius: SurfaceRadius): radius is SurfaceRadiusPreset =>\n radius in radiusClassMap;\n\nexport const Surface = forwardRef<HTMLElement, SurfaceProps>(\n (\n {\n children,\n background = 'transparent',\n intent,\n contrast = 'faint',\n elevation = 'none',\n edge,\n radius,\n interactive = false,\n selected = false,\n inactive = false,\n as: Component = 'div',\n className = '',\n style,\n type,\n ...rest\n },\n ref\n ) => {\n const classes = [\n styles.surface,\n // Background or intent+contrast\n intent\n ? getIntentContrastClass(intent, contrast)\n : backgroundClassMap[background],\n // Elevation\n elevationClassMap[elevation],\n // Edge(s) — only when elevation is 'none'\n ...(edge && elevation === 'none'\n ? Array.isArray(edge)\n ? edge.map(e => edgeClassMap[e])\n : [edgeClassMap[edge]]\n : []),\n // Radius (preset only — custom handled via inline style)\n radius && isPresetRadius(radius) ? radiusClassMap[radius] : '',\n // States\n interactive ? styles.interactive : '',\n selected ? styles.selected : '',\n inactive ? styles.inactive : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const computedStyle: React.CSSProperties = {\n ...style,\n ...(radius && !isPresetRadius(radius) ? { borderRadius: radius } : {}),\n };\n\n const hasStyle =\n (radius && !isPresetRadius(radius)) || (style && Object.keys(style).length > 0);\n\n const elementProps = {\n ref,\n className: classes,\n style: hasStyle ? computedStyle : undefined,\n disabled: Component === 'button' ? inactive : undefined,\n type: Component === 'button' ? type || 'button' : undefined,\n ...rest,\n };\n\n return (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n <Component {...(elementProps as any)}>{children}</Component>\n );\n }\n);\n\nSurface.displayName = 'Surface';\n","/**\n * Card — structured container with optional header/footer.\n * Uses TokoMo tokens directly (not built on Surface).\n */\n\n.card {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n overflow: hidden;\n}\n\n/* Elevation */\n.elevationFlat { box-shadow: var(--effect-elevation-elevated-none); }\n.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n.elevationFloating { box-shadow: var(--effect-elevation-elevated-floating); }\n\n/* Radius */\n.radiusSm { border-radius: var(--dimension-radius-075); }\n.radiusMd { border-radius: var(--dimension-radius-100); }\n.radiusLg { border-radius: var(--dimension-radius-125); }\n.radiusXl { border-radius: var(--dimension-radius-175); }\n\n/* Sections */\n.header {\n padding: var(--dimension-space-150) var(--dimension-space-200);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.body {\n padding: var(--dimension-space-200);\n}\n\n.footer {\n padding: var(--dimension-space-150) var(--dimension-space-200);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n","/**\n * Joins class names, filtering out falsy values.\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Card.module.css';\nimport { cn } from '@/utils/cn';\n\nexport type CardElevation = 'flat' | 'elevated' | 'floating';\nexport type CardRadius = 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface CardProps {\n children: React.ReactNode;\n /** Optional header content — rendered with a bottom divider. */\n header?: React.ReactNode;\n /** Optional footer content — rendered with a top divider. */\n footer?: React.ReactNode;\n /** Elevation level. Defaults to 'elevated'. */\n elevation?: CardElevation;\n /** Corner radius. Defaults to 'lg'. */\n radius?: CardRadius;\n /** Additional CSS classes. */\n className?: string;\n /** Inline styles. */\n style?: React.CSSProperties;\n}\n\nconst elevationClassMap: Record<CardElevation, string> = {\n flat: styles.elevationFlat,\n elevated: styles.elevationElevated,\n floating: styles.elevationFloating,\n};\n\nconst radiusClassMap: Record<CardRadius, string> = {\n sm: styles.radiusSm,\n md: styles.radiusMd,\n lg: styles.radiusLg,\n xl: styles.radiusXl,\n};\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(\n ({ children, header, footer, elevation = 'elevated', radius = 'lg', className, style }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(styles.card, elevationClassMap[elevation], radiusClassMap[radius], className)}\n style={style}\n >\n {header && <div className={styles.header}>{header}</div>}\n <div className={styles.body}>{children}</div>\n {footer && <div className={styles.footer}>{footer}</div>}\n </div>\n );\n }\n);\n\nCard.displayName = 'Card';\n","/* ==========================================================================\n LabelWrap — internal utility\n Kills the inherited line-height strut so the component's fixed height\n is not inflated by body { line-height: 1.5 }, then adds optical\n horizontal padding around the text.\n ========================================================================== */\n\n.labelWrap {\n line-height: 0;\n padding: 0 var(--dimension-space-050); /* 4px — body sm / md / lg */\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Small scale: tighter optical padding */\n.sizeSm { padding: 0 var(--dimension-space-025); } /* 2px */\n\n/* Caption scale: tighter optical padding */\n.sizeXs { padding: 0 var(--dimension-space-025); } /* 2px */\n\n/* Truncation mode — used when parent is full-width and label must ellipsize */\n.truncate {\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n}\n\n.truncate > span {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './LabelWrap.module.css';\n\ninterface LabelWrapProps {\n children: React.ReactNode;\n /**\n * Maps to typography size — controls optical horizontal padding:\n * xs | sm → 2px (tighter scale)\n * md | lg → 4px (body scale, default)\n */\n size?: 'xs' | 'sm' | 'md' | 'lg';\n /** Enables truncation with ellipsis — use inside full-width containers. */\n truncate?: boolean;\n className?: string;\n}\n\n/**\n * Internal utility wrapper used inside interactive components (Button, Tag,\n * Input, Select, MenuItem, etc.) to:\n * 1. Kill the inherited line-height strut from body { line-height: 1.5 }\n * 2. Add optical horizontal padding around the text\n *\n * Not exported from the public barrel — internal use only.\n */\nexport const LabelWrap = ({ children, size = 'md', truncate = false, className }: LabelWrapProps) => (\n <span className={cn(styles.labelWrap, size === 'sm' && styles.sizeSm, size === 'xs' && styles.sizeXs, truncate && styles.truncate, className)}>\n {children}\n </span>\n);\n\nLabelWrap.displayName = 'LabelWrap';\n",".loader {\n flex-shrink: 0;\n animation: spin 0.75s linear infinite;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n","import React from 'react';\nimport styles from './Loader.module.css';\n\nexport interface LoaderProps {\n /**\n * Render size in px. Designed at 16px (r=6, strokeWidth=1).\n * Stroke weight scales proportionally with size — same behaviour as icons.\n * Defaults to 20.\n */\n size?: number;\n className?: string;\n}\n\n/**\n * Placeholder spinner component. Will be replaced with a full Loader\n * component once motion/brand specs are finalised.\n *\n * Designed at 16×16 viewBox so it matches the icon grid:\n * - r=5 → 10px circle in a 16px box (3px optical padding each side)\n * - strokeWidth=1 at native size → scales to 1.25px at 20px, 1.5px at 24px\n */\nexport const Loader = ({ size = 20, className }: LoaderProps) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className={`${styles.loader}${className ? ` ${className}` : ''}`}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"5\"\n stroke=\"currentColor\"\n strokeWidth=\"1\"\n strokeLinecap=\"round\"\n strokeDasharray=\"23.6 7.9\"\n />\n </svg>\n);\n\nLoader.displayName = 'Loader';\n","/* ==========================================================================\n Button — unified primary/secondary\n Hover/pressed via color-mix() on background-color. No pseudo-element overlays.\n ========================================================================== */\n\n.button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n position: relative;\n transition: transform var(--effect-motion-short-2);\n height: var(--dimension-size-400);\n font-family: inherit;\n color: var(--color-foreground-primary);\n background: transparent;\n box-sizing: border-box;\n text-decoration: none;\n -webkit-user-select: none;\n user-select: none;\n\n /* Interaction — ghost defaults (semi-transparent overlay) */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_border: var(--color-border-tertiary);\n}\n\n.button:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.button:hover:not(.inactive) {\n background-color: var(--_hover-bg);\n}\n\n.button:active:not(.inactive) {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* ==========================================================================\n Background context — parent surface awareness\n Adjusts hover tokens and secondary fg for colored parent surfaces.\n 1-class specificity; overridden by filled variant rules (2+ classes).\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_border: var(--color-border-on-medium-background-tertiary);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_border: var(--color-border-on-bold-background-tertiary);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_border: var(--color-border-on-strong-background-tertiary);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_border: var(--color-always-dark-border-tertiary);\n}\n\n/* ==========================================================================\n Variant: Primary\n Bold background, on-bold content. Elevation controls shadow.\n ========================================================================== */\n\n.primary {\n color: var(--color-foreground-on-bold-background-primary);\n}\n\n/* Primary intent: none — inverted surface (black in light mode, white in dark mode) */\n.primary.intentNone {\n background-color: var(--color-inverted-background);\n color: var(--color-inverted-foreground-primary);\n --_hover-bg: color-mix(in oklch, var(--color-inverted-background) 90%, var(--color-inverted-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-inverted-background) 85%, var(--color-inverted-foreground-primary));\n --_border: var(--color-inverted-border-tertiary);\n}\n\n/* Filled primary — background from --_bg, bold-contrast hover via color-mix.\n 2-class specificity beats background context (1-class). */\n.primary:not(.intentNone) {\n background-color: var(--_bg);\n --_hover-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-on-bold-background-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 80%, var(--color-foreground-on-bold-background-primary));\n}\n\n/* ── Primary bold contrast (default) ────────────────────────────────── */\n\n.primary.intentBrand { --_bg: var(--color-background-bold-brand); color: var(--color-foreground-faint-brand); }\n.primary.intentNeutral { --_bg: var(--color-background-bold-neutral); color: var(--color-foreground-faint-neutral); }\n.primary.intentPositive { --_bg: var(--color-background-bold-positive); color: var(--color-foreground-faint-positive); }\n.primary.intentNegative { --_bg: var(--color-background-bold-negative); color: var(--color-foreground-faint-negative); }\n.primary.intentWarning { --_bg: var(--color-background-bold-warning); color: var(--color-foreground-faint-warning); }\n.primary.intentCaution { --_bg: var(--color-background-bold-caution); color: var(--color-foreground-faint-caution); }\n.primary.intentAi { --_bg: var(--color-background-bold-ai); color: var(--color-foreground-faint-ai); }\n\n/* ── Primary medium contrast ────────────────────────────────────────── */\n\n.primary.contrastMedium {\n --_hover-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 80%, var(--color-foreground-primary));\n}\n.primary.contrastMedium.intentBrand { --_bg: var(--color-background-medium-brand); color: var(--color-foreground-strong-brand); }\n.primary.contrastMedium.intentNeutral { --_bg: var(--color-background-medium-neutral); color: var(--color-foreground-strong-neutral); }\n.primary.contrastMedium.intentPositive { --_bg: var(--color-background-medium-positive); color: var(--color-foreground-strong-positive); }\n.primary.contrastMedium.intentNegative { --_bg: var(--color-background-medium-negative); color: var(--color-foreground-strong-negative); }\n.primary.contrastMedium.intentWarning { --_bg: var(--color-background-medium-warning); color: var(--color-foreground-strong-warning); }\n.primary.contrastMedium.intentCaution { --_bg: var(--color-background-medium-caution); color: var(--color-foreground-strong-caution); }\n.primary.contrastMedium.intentAi { --_bg: var(--color-background-medium-ai); color: var(--color-foreground-strong-ai); }\n\n/* ── Primary strong contrast ────────────────────────────────────────── */\n\n.primary.contrastStrong {\n --_hover-bg: color-mix(in oklch, var(--_bg) 90%, var(--color-foreground-on-bold-background-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-on-bold-background-primary));\n}\n.primary.contrastStrong.intentBrand { --_bg: var(--color-background-strong-brand); color: var(--color-foreground-medium-brand); }\n.primary.contrastStrong.intentNeutral { --_bg: var(--color-background-strong-neutral); color: var(--color-foreground-medium-neutral); }\n.primary.contrastStrong.intentPositive { --_bg: var(--color-background-strong-positive); color: var(--color-foreground-medium-positive); }\n.primary.contrastStrong.intentNegative { --_bg: var(--color-background-strong-negative); color: var(--color-foreground-medium-negative); }\n.primary.contrastStrong.intentWarning { --_bg: var(--color-background-strong-warning); color: var(--color-foreground-medium-warning); }\n.primary.contrastStrong.intentCaution { --_bg: var(--color-background-strong-caution); color: var(--color-foreground-medium-caution); }\n.primary.contrastStrong.intentAi { --_bg: var(--color-background-strong-ai); color: var(--color-foreground-medium-ai); }\n\n/* ── Primary faint contrast ─────────────────────────────────────────── */\n\n.primary.contrastFaint {\n --_hover-bg: color-mix(in oklch, var(--_bg) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-primary));\n}\n.primary.contrastFaint.intentBrand { --_bg: var(--color-background-faint-brand); color: var(--color-foreground-bold-brand); }\n.primary.contrastFaint.intentNeutral { --_bg: var(--color-background-faint-neutral); color: var(--color-foreground-bold-neutral); }\n.primary.contrastFaint.intentPositive { --_bg: var(--color-background-faint-positive); color: var(--color-foreground-bold-positive); }\n.primary.contrastFaint.intentNegative { --_bg: var(--color-background-faint-negative); color: var(--color-foreground-bold-negative); }\n.primary.contrastFaint.intentWarning { --_bg: var(--color-background-faint-warning); color: var(--color-foreground-bold-warning); }\n.primary.contrastFaint.intentCaution { --_bg: var(--color-background-faint-caution); color: var(--color-foreground-bold-caution); }\n.primary.contrastFaint.intentAi { --_bg: var(--color-background-faint-ai); color: var(--color-foreground-bold-ai); }\n\n/* ==========================================================================\n Variant: Secondary\n Base is ghost (transparent, no border, no shadow).\n Elevation classes add the chrome — flat=border, elevated=bg+shadow, floating=bg+floating.\n ========================================================================== */\n\n.secondary {\n background-color: transparent;\n color: var(--color-foreground-secondary);\n}\n\n/* Secondary intent — bold fg color */\n.secondary.intentBrand { color: var(--color-foreground-bold-brand); }\n.secondary.intentNeutral { color: var(--color-foreground-bold-neutral); }\n.secondary.intentPositive { color: var(--color-foreground-bold-positive); }\n.secondary.intentNegative { color: var(--color-foreground-bold-negative); }\n.secondary.intentWarning { color: var(--color-foreground-bold-warning); }\n.secondary.intentCaution { color: var(--color-foreground-bold-caution); }\n.secondary.intentAi { color: var(--color-foreground-bold-ai); }\n\n/* ── Secondary fg on medium surface ─────────────────────────────────── */\n\n.secondary.onMedium { color: var(--color-foreground-primary); }\n.secondary.onMedium.intentBrand { color: var(--color-foreground-strong-brand); }\n.secondary.onMedium.intentNeutral { color: var(--color-foreground-strong-neutral); }\n.secondary.onMedium.intentPositive { color: var(--color-foreground-strong-positive); }\n.secondary.onMedium.intentNegative { color: var(--color-foreground-strong-negative); }\n.secondary.onMedium.intentWarning { color: var(--color-foreground-strong-warning); }\n.secondary.onMedium.intentCaution { color: var(--color-foreground-strong-caution); }\n.secondary.onMedium.intentAi { color: var(--color-foreground-strong-ai); }\n\n/* ── Secondary fg on bold surface ──────────────────────────────────── */\n\n.secondary.onBold { color: var(--color-foreground-on-bold-background-secondary); }\n.secondary.onBold.intentBrand { color: var(--color-foreground-faint-brand); }\n.secondary.onBold.intentNeutral { color: var(--color-foreground-faint-neutral); }\n.secondary.onBold.intentPositive { color: var(--color-foreground-faint-positive); }\n.secondary.onBold.intentNegative { color: var(--color-foreground-faint-negative); }\n.secondary.onBold.intentWarning { color: var(--color-foreground-faint-warning); }\n.secondary.onBold.intentCaution { color: var(--color-foreground-faint-caution); }\n.secondary.onBold.intentAi { color: var(--color-foreground-faint-ai); }\n\n/* ── Secondary fg on always-dark surface ──────────────────────────── */\n\n.secondary.onAlwaysDark { color: var(--color-always-dark-foreground-secondary); }\n.secondary.onAlwaysDark.intentBrand { color: var(--color-always-dark-foreground-brand); }\n.secondary.onAlwaysDark.intentNeutral { color: var(--color-always-dark-foreground-neutral); }\n.secondary.onAlwaysDark.intentPositive { color: var(--color-always-dark-foreground-positive); }\n.secondary.onAlwaysDark.intentNegative { color: var(--color-always-dark-foreground-negative); }\n.secondary.onAlwaysDark.intentWarning { color: var(--color-always-dark-foreground-warning); }\n.secondary.onAlwaysDark.intentCaution { color: var(--color-always-dark-foreground-caution); }\n.secondary.onAlwaysDark.intentAi { color: var(--color-always-dark-foreground-ai); }\n\n/* ── Secondary fg on strong surface ─────────────────────────────────── */\n\n.secondary.onStrong { color: var(--color-foreground-on-bold-background-secondary); }\n.secondary.onStrong.intentBrand { color: var(--color-foreground-faint-brand); }\n.secondary.onStrong.intentNeutral { color: var(--color-foreground-faint-neutral); }\n.secondary.onStrong.intentPositive { color: var(--color-foreground-faint-positive); }\n.secondary.onStrong.intentNegative { color: var(--color-foreground-faint-negative); }\n.secondary.onStrong.intentWarning { color: var(--color-foreground-faint-warning); }\n.secondary.onStrong.intentCaution { color: var(--color-foreground-faint-caution); }\n.secondary.onStrong.intentAi { color: var(--color-foreground-faint-ai); }\n\n/* ==========================================================================\n Elevation\n ========================================================================== */\n\n/* ── Secondary chrome ───────────────────────────────────────────────── */\n\n/* elevationNone = ghost base — no extra CSS needed */\n\n.secondary.elevationFlat {\n box-shadow: inset 0 0 0 1px var(--_border);\n}\n\n.secondary.elevationElevated {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n.secondary.elevationFloating {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-floating);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Primary shadow + border control ───────────────────────────────── */\n\n/* elevated */\n.primary.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n\n/* none = no shadow, no border (flat colored button — default for primary) */\n.primary.elevationNone { box-shadow: none; }\n\n/* flat = inset ring against the page background (not the button fill) */\n.primary.elevationFlat { box-shadow: inset 0 0 0 1px var(--_border); }\n\n/* intentNone flat: inverted fill + default border ring (bg/fg inherited from .primary.intentNone) */\n.primary.intentNone.elevationFlat {\n --_border: var(--color-border-tertiary);\n}\n\n/* intentNone on strong/always-dark: flip to surface bg/fg — inverted (black) would be invisible */\n.primary.intentNone.onStrong,\n.primary.intentNone.onAlwaysDark {\n background-color: var(--color-background-primary);\n color: var(--color-foreground-primary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n --_border: var(--color-border-tertiary);\n}\n\n/* floating = FAB-strength shadow for both variants */\n.primary.elevationFloating { box-shadow: var(--effect-elevation-elevated-floating) !important; }\n\n/* ==========================================================================\n Layout: icon-only, label-only, icon+label, dropdown\n ========================================================================== */\n\n.iconOnly { padding: 0; width: var(--dimension-size-400); min-width: var(--dimension-size-400); }\n.labelOnly { padding: 0 var(--dimension-space-100); }\n.iconAndLabel { padding: 0 var(--dimension-space-100) 0 var(--dimension-space-075); gap: var(--dimension-space-025); }\n.dropdown { gap: var(--dimension-space-050); }\n\n/* ==========================================================================\n Sizes\n ========================================================================== */\n\n.sizeSM { height: var(--dimension-size-300); }\n.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.sizeSM.labelOnly { padding: 0 var(--dimension-space-075); }\n.sizeSM.iconAndLabel { padding: 0 var(--dimension-space-075) 0 var(--dimension-space-050); gap: 1px; }\n\n.sizeXS { height: var(--dimension-size-200); }\n.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n.sizeXS.labelOnly, .sizeXS.iconAndLabel { padding: 0 var(--dimension-space-025); gap: 0; }\n\n.sizeLG { height: var(--dimension-size-500); }\n.sizeLG.iconOnly { width: var(--dimension-size-500); min-width: var(--dimension-size-500); }\n.sizeLG.labelOnly { padding: 0 var(--dimension-space-150); }\n.sizeLG.iconAndLabel { padding: 0 var(--dimension-space-150) 0 var(--dimension-space-100); gap: var(--dimension-space-075); }\n\n/* ==========================================================================\n Rounded (pill shape)\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n.rounded.labelOnly { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.iconAndLabel { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.sizeSM.labelOnly { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeSM.iconAndLabel { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeLG.labelOnly { padding-left: calc(var(--dimension-space-150) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-150) + var(--dimension-space-050)); }\n.rounded.sizeLG.iconAndLabel { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-150) + var(--dimension-space-050)); }\n.rounded.iconOnly { width: var(--dimension-size-400); min-width: var(--dimension-size-400); padding: 0; }\n.rounded.sizeLG.iconOnly { width: var(--dimension-size-500); min-width: var(--dimension-size-500); }\n.rounded.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.rounded.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n\n/* ==========================================================================\n Badge\n ========================================================================== */\n\n.badge {\n position: absolute;\n top: var(--dimension-space-025);\n right: var(--dimension-space-025);\n font-size: var(--typography-fontsize-xs);\n font-weight: var(--typography-weight-semibold);\n line-height: var(--typography-lineheight-xs);\n color: var(--color-foreground-secondary);\n pointer-events: none;\n z-index: 10;\n}\n\n/* ==========================================================================\n Full width\n ========================================================================== */\n\n.fullWidth {\n display: flex;\n width: 100%;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport { Loader } from '@/components/Loader';\nimport { ChevronDown } from '@ds-mo/icons';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'primary' | 'secondary';\nexport type ButtonElevation = 'none' | 'flat' | 'elevated' | 'floating';\nexport type ButtonIntent = 'none' | 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonContrast = 'strong' | 'bold' | 'medium' | 'faint';\nexport type ButtonBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface ButtonProps {\n /** Polymorphic element type. Defaults to 'button'. */\n as?: React.ElementType;\n /** Visual variant. Defaults to 'primary'. */\n variant?: ButtonVariant;\n /** Label text. */\n label?: string;\n /** Leading icon component from @ds-mo/icons. */\n icon?: IconComponent;\n /** Semantic intent. Defaults to 'brand'. */\n intent?: ButtonIntent;\n /** Size. Defaults to 'md'. */\n size?: ButtonSize;\n /** Pill shape with extra padding. */\n rounded?: boolean;\n /** Fill container width. Label truncates if space is tight. */\n fullWidth?: boolean;\n /** Fixed width. Omit for content width. */\n width?: React.CSSProperties['width'];\n /** Contrast level (primary variant only). Defaults to 'bold'. */\n contrast?: ButtonContrast;\n /**\n * Parent surface context. Adjusts hover tokens and secondary fg colors\n * for buttons placed on colored backgrounds.\n * faint — default, no adjustment\n * medium — use on-medium-background interaction tokens\n * bold — use on-bold-background interaction + inverted fg\n * strong — use on-strong-background interaction + inverted fg\n * always-dark — dark surface (no theme flip), on-bold-background tokens\n */\n background?: ButtonBackground;\n /** Show trailing ChevronDown dropdown indicator. */\n dropdown?: boolean;\n /** Badge count. */\n badgeCount?: number;\n /**\n * Chrome level for secondary; shadow level for primary.\n * none — ghost (transparent, no border, no shadow)\n * flat — border only, transparent bg [default for secondary]\n * elevated — bg-primary + shadow [default for primary]\n * floating — bg-primary + FAB-strength shadow\n */\n elevation?: ButtonElevation;\n /** Show loading spinner in place of icon. Prevents interaction. */\n loading?: boolean;\n\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onMouseEnter?: React.MouseEventHandler<HTMLElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n inactive?: boolean;\n type?: 'button' | 'submit' | 'reset';\n id?: string;\n 'aria-label'?: string;\n href?: string;\n target?: string;\n rel?: string;\n}\n\nconst ICON_SIZE_MAP: Record<ButtonSize, number> = { xs: 12, sm: 16, md: 20, lg: 24 };\n\nconst TEXT_STYLE_MAP: Record<ButtonSize, string> = {\n xs: 'text-caption-emphasis',\n sm: 'text-body-small-emphasis',\n md: 'text-body-medium-emphasis',\n lg: 'text-body-large-emphasis',\n};\n\n\nexport const Button = forwardRef<HTMLElement, ButtonProps>(\n (\n {\n as,\n variant = 'primary',\n label,\n icon: Icon,\n intent = 'brand',\n size = 'md',\n rounded = false,\n fullWidth = false,\n width,\n contrast = 'bold',\n background,\n dropdown = false,\n badgeCount,\n elevation,\n loading = false,\n onClick,\n onMouseEnter,\n onMouseLeave,\n className,\n inactive = false,\n type = 'button',\n id,\n 'aria-label': ariaLabel,\n href,\n target,\n rel,\n },\n ref\n ) => {\n const Component = (as ?? 'button') as React.ElementType;\n const isButton = !as || as === 'button';\n const isInteractive = !inactive && !loading;\n\n const hasIcon = !!Icon;\n const hasLabel = !!label;\n const showLeading = hasIcon || loading; // spinner fills the icon slot\n const isIconOnly = showLeading && !hasLabel;\n const isLabelOnly = hasLabel && !showLeading;\n const isIconAndLabel = showLeading && hasLabel;\n const iconSize = ICON_SIZE_MAP[size];\n const textStyle = TEXT_STYLE_MAP[size];\n\n // Derive default elevation per variant: primary→none, secondary→flat\n const effectiveElevation: ButtonElevation = elevation ?? (variant === 'primary' ? 'none' : 'flat');\n const elevKey = effectiveElevation.charAt(0).toUpperCase() + effectiveElevation.slice(1);\n\n const classes = cn(\n styles.button,\n styles[variant],\n styles[`intent${intent.charAt(0).toUpperCase() + intent.slice(1)}`],\n size !== 'md' && styles[`size${size.toUpperCase()}`],\n rounded && styles.rounded,\n (inactive || loading) && styles.inactive,\n isIconOnly && styles.iconOnly,\n isLabelOnly && styles.labelOnly,\n isIconAndLabel && styles.iconAndLabel,\n dropdown && styles.dropdown,\n variant === 'primary' && intent !== 'none' && contrast !== 'bold' && styles[`contrast${contrast.charAt(0).toUpperCase() + contrast.slice(1)}`],\n styles[`elevation${elevKey}`],\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n fullWidth && styles.fullWidth,\n className,\n );\n\n const resolvedAriaLabel = ariaLabel || label || 'button';\n\n const extraProps: Record<string, unknown> = {};\n if (isButton) {\n extraProps.type = type;\n extraProps.disabled = inactive || loading;\n }\n if (href) extraProps.href = href;\n if (target) extraProps.target = target;\n if (rel) extraProps.rel = rel;\n\n return (\n <Component\n ref={ref}\n id={id}\n className={classes}\n style={width ? { width } : undefined}\n onClick={isInteractive ? onClick : undefined}\n onMouseEnter={isInteractive ? onMouseEnter : undefined}\n onMouseLeave={isInteractive ? onMouseLeave : undefined}\n aria-label={resolvedAriaLabel}\n aria-busy={loading || undefined}\n {...extraProps}\n >\n {loading ? (\n <Loader size={iconSize} />\n ) : (\n Icon && <Icon size={iconSize} />\n )}\n {label && (\n <LabelWrap truncate={fullWidth}>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n )}\n {dropdown && <ChevronDown size={iconSize} />}\n {badgeCount != null && badgeCount > 0 && (\n <span className={styles.badge}>{badgeCount > 9 ? '+' : badgeCount}</span>\n )}\n </Component>\n );\n }\n);\n\nButton.displayName = 'Button';\n","/* ==========================================================================\n ToggleButton — hover/pressed via direct background-color + color-mix().\n No pseudo-element overlays.\n Elevation controls the chrome level:\n elevated — bg-primary + shadow (default)\n flat — border only\n none — ghost (transparent, no border, no shadow)\n floating — bg-primary + FAB-strength shadow\n ========================================================================== */\n\n.toggleButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n position: relative;\n transition: transform var(--effect-motion-short-2);\n height: var(--dimension-size-400);\n font-family: inherit;\n background: transparent;\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_border: var(--color-border-tertiary);\n}\n\n.toggleButton:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.toggleButton:hover:not(.inactive) {\n background-color: var(--_hover-bg);\n}\n\n.toggleButton:active:not(.inactive) {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_border: var(--color-border-on-medium-background-tertiary);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_border: var(--color-border-on-bold-background-tertiary);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_border: var(--color-border-on-strong-background-tertiary);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_border: var(--color-always-dark-border-tertiary);\n}\n\n/* ==========================================================================\n Elevation levels\n ========================================================================== */\n\n/* ── Elevated (default): bg-primary + shadow ───────────────────────────── */\n\n.elevationElevated {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n color: var(--color-foreground-secondary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Flat: border only, transparent bg ─────────────────────────────────── */\n\n.elevationFlat {\n box-shadow: inset 0 0 0 1px var(--_border);\n color: var(--color-foreground-secondary);\n}\n\n/* ── None: ghost — transparent, no border, no shadow ───────────────────── */\n\n.elevationNone {\n color: var(--color-foreground-secondary);\n}\n\n/* ── Floating: bg-primary + FAB-strength shadow ─────────────────────────── */\n\n.elevationFloating {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-floating);\n color: var(--color-foreground-secondary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Fg on bold / strong surface ────────────────────────────────────────── */\n\n.onBold.elevationNone, .onBold.elevationFlat,\n.onStrong.elevationNone, .onStrong.elevationFlat {\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n/* ── Fg on always-dark surface ─────────────────────────────────────────── */\n\n.onAlwaysDark.elevationNone, .onAlwaysDark.elevationFlat {\n color: var(--color-always-dark-foreground-secondary);\n}\n\n/* ==========================================================================\n Pressed state — shared across all elevation levels\n ========================================================================== */\n\n.pressed {\n background-color: var(--color-background-faint-brand);\n color: var(--color-foreground-bold-brand);\n}\n\n/* ==========================================================================\n Layout\n ========================================================================== */\n\n.iconOnly { padding: 0; width: var(--dimension-size-400); min-width: var(--dimension-size-400); }\n.labelOnly { padding: 0 var(--dimension-space-100); }\n.iconAndLabel{ padding: 0 var(--dimension-space-100) 0 var(--dimension-space-075); gap: var(--dimension-space-025); }\n\n/* ==========================================================================\n Sizes\n ========================================================================== */\n\n.sizeSM { height: var(--dimension-size-300); }\n.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.sizeSM.labelOnly { padding: 0 var(--dimension-space-075); }\n.sizeSM.iconAndLabel { padding: 0 var(--dimension-space-075) 0 var(--dimension-space-050); gap: 0; }\n\n.sizeXS { height: var(--dimension-size-200); }\n.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n.sizeXS.labelOnly, .sizeXS.iconAndLabel { padding: 0 var(--dimension-space-025); gap: 0; }\n\n/* ==========================================================================\n Rounded (pill shape)\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n.rounded.labelOnly { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.iconAndLabel { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.sizeSM.labelOnly { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeSM.iconAndLabel { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.iconOnly { width: var(--dimension-size-400); min-width: var(--dimension-size-400); padding: 0; }\n.rounded.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.rounded.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './ToggleButton.module.css';\n\nexport type ToggleButtonElevation = 'none' | 'flat' | 'elevated' | 'floating';\nexport type ToggleButtonSize = 'md' | 'sm' | 'xs';\nexport type ToggleButtonBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface ToggleButtonProps {\n /**\n * Chrome level.\n * none — ghost (transparent, no border, no shadow)\n * flat — border only, transparent bg\n * elevated — bg-primary + shadow [default]\n * floating — bg-primary + FAB-strength shadow\n */\n elevation?: ToggleButtonElevation;\n /** Label text. */\n label?: string;\n /** Leading icon component. */\n icon?: IconComponent;\n /** Size: md (32px), sm (24px), xs (16px). Defaults to 'md'. */\n size?: ToggleButtonSize;\n /** Pill shape. */\n rounded?: boolean;\n /** Parent surface context. Adjusts hover tokens for toggle buttons on colored backgrounds. */\n background?: ToggleButtonBackground;\n /** Controlled pressed state. */\n pressed: boolean;\n /** Called when pressed state changes. */\n onPressedChange: (pressed: boolean) => void;\n inactive?: boolean;\n className?: string;\n id?: string;\n 'aria-label'?: string;\n}\n\nconst ICON_SIZE_MAP: Record<ToggleButtonSize, number> = { md: 20, sm: 16, xs: 12 };\n\nconst TEXT_STYLE_MAP: Record<ToggleButtonSize, string> = {\n md: 'text-body-medium-emphasis',\n sm: 'text-body-small-emphasis',\n xs: 'text-caption-emphasis',\n};\n\nexport const ToggleButton = forwardRef<HTMLButtonElement, ToggleButtonProps>(\n (\n {\n elevation = 'elevated',\n label,\n icon: Icon,\n size = 'md',\n rounded = false,\n background,\n pressed,\n onPressedChange,\n inactive = false,\n className,\n id,\n 'aria-label': ariaLabel,\n },\n ref\n ) => {\n const hasIcon = !!Icon;\n const hasLabel = !!label;\n const isIconOnly = hasIcon && !hasLabel;\n const isLabelOnly = hasLabel && !hasIcon;\n const isIconAndLabel = hasIcon && hasLabel;\n const iconSize = ICON_SIZE_MAP[size];\n const textStyle = TEXT_STYLE_MAP[size];\n\n const elevKey = elevation.charAt(0).toUpperCase() + elevation.slice(1);\n\n const classes = cn(\n styles.toggleButton,\n styles[`elevation${elevKey}`],\n size !== 'md' && styles[`size${size.toUpperCase()}`],\n rounded && styles.rounded,\n inactive && styles.inactive,\n isIconOnly && styles.iconOnly,\n isLabelOnly && styles.labelOnly,\n isIconAndLabel && styles.iconAndLabel,\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n pressed && styles.pressed,\n className,\n );\n\n return (\n <button\n ref={ref}\n id={id}\n className={classes}\n onClick={inactive ? undefined : () => onPressedChange(!pressed)}\n type=\"button\"\n disabled={inactive}\n aria-label={ariaLabel || label || 'toggle'}\n aria-pressed={pressed}\n >\n {Icon && <Icon size={iconSize} />}\n {label && (\n <LabelWrap>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n )}\n </button>\n );\n }\n);\n\nToggleButton.displayName = 'ToggleButton';\n","/* ==========================================================================\n ButtonGroup — flush row of Button components\n ========================================================================== */\n\n.group {\n display: inline-flex;\n align-items: stretch;\n border-radius: var(--dimension-radius-050);\n position: relative;\n}\n\n/* Inset ring / highlight overlay — sits above button children so it isn't\n covered by their backgrounds. Outset shadow stays on the element itself. */\n.group::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n}\n\n/* ── Group-level elevation ──────────────────────────────────────────────── */\n/* Individual item chrome is suppressed via .item — the group container\n carries the elevation so it wraps the whole control as one visual unit. */\n\n/* Outset shadow on element; inset highlight on ::after (children would cover it otherwise) */\n.groupElevated { box-shadow: var(--effect-shadow-elevated-sm); }\n.groupElevated::after { box-shadow: var(--effect-highlight-elevated-sm); }\n\n/* Flat ring lives entirely on ::after — same reasoning as highlight */\n.groupFlat::after { box-shadow: inset 0 0 0 1px var(--color-border-tertiary); }\n\n.groupFloating { box-shadow: var(--effect-shadow-elevated-floating); }\n.groupFloating::after { box-shadow: var(--effect-highlight-elevated-floating); }\n/* groupNone = ghost / primary — no shadow, no border */\n\n.groupRounded { border-radius: var(--dimension-radius-half); }\n\n/* ── Base item ─────────────────────────────────────────────────────────────── */\n\n.item {\n flex-shrink: 0;\n /* Suppress individual elevation so the group reads as one unit */\n box-shadow: none !important;\n /* Suppress noElevation individual border — divider handles separation */\n border: none !important;\n /* Suppress scale-on-press: transform would detach the divider from the\n adjacent button, creating a visible gap. Pressed state is still\n communicated via the ::after overlay colour. */\n}\n.item:active {\n transform: none !important;\n}\n\n/* ── Divider ────────────────────────────────────────────────────────────────\n * Rendered as a separate <div> between items so it is never part of any\n * button's stacking context — disabled (opacity: 0.5) or other state changes\n * on adjacent buttons cannot bleed through to the divider.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* Full-height divider (secondary + primary).\n * Overlaps each neighbour by 0.5px and paints on top so the alpha token\n * composites over the button fill rather than the page background. */\n.divider {\n width: 1px;\n flex-shrink: 0;\n background-color: var(--color-border-tertiary);\n position: relative;\n z-index: 1;\n margin: 0 -0.5px;\n pointer-events: none;\n}\n\n/* Ghost (elevation=none): short centred divider at icon height */\n.dividerGhost { height: 20px; align-self: center; } /* md default */\n.dividerGhostXS { height: 12px; }\n.dividerGhostSM { height: 16px; }\n.dividerGhostLG { height: 24px; }\n\n/* Primary intent: on-background divider colour */\n.dividerBold { background-color: var(--color-border-on-bold-background-tertiary); }\n.dividerMedium { background-color: var(--color-border-on-medium-background-tertiary); }\n.dividerStrong { background-color: var(--color-border-on-strong-background-tertiary); }\n\n/* Ghost hover-fade: hide the divider on either side of a hovered ghost button */\n.item:hover + .dividerGhost,\n.dividerGhost:has(+ .item:hover) { opacity: 0; }\n\n/* ── Ghost interaction states: rounded chips ──────────────────────────────────\n * Ghost items have no group chrome — hover/press overlay should appear as\n * fully rounded chips (4px all corners). Rounded groups: outer corners of\n * first/last become pill; inner corners stay 4px.\n *\n * Uses .group ancestor (2-class specificity) to reliably beat .first / .last /\n * .middle (1-class) regardless of load order. Explicit longhands throughout to\n * avoid shorthand/longhand cascade ambiguity with the !important rules above.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* ::after hover/press overlay — all positions: 4px all corners */\n.group .itemShort::after {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* ── Border radius: flatten only the inner-facing corners ──────────────────── */\n/* Outer corners keep the button's own radius — works for default + rounded */\n\n.first {\n border-top-right-radius: 0 !important;\n border-bottom-right-radius: 0 !important;\n}\n\n.last {\n border-top-left-radius: 0 !important;\n border-bottom-left-radius: 0 !important;\n}\n\n.middle {\n border-radius: 0 !important;\n}\n\n/* Rounded group: first — left corners become pill (3-class specificity) */\n.groupRounded .first.itemShort::after {\n border-top-left-radius: var(--dimension-radius-half) !important;\n border-bottom-left-radius: var(--dimension-radius-half) !important;\n}\n\n/* Rounded group: last — right corners become pill (3-class specificity) */\n.groupRounded .last.itemShort::after {\n border-top-right-radius: var(--dimension-radius-half) !important;\n border-bottom-right-radius: var(--dimension-radius-half) !important;\n}\n\n/* ── Rounded: inner-edge padding correction ────────────────────────────────── */\n/*\n * Rounded buttons add `space-050` extra padding on each side.\n * In a group the inner-facing edge should use base (non-pill) padding instead.\n * These classes are injected by ButtonGroup for first/last/mid × size.\n * XS rounded has no extra padding so needs no correction.\n */\n\n/* MD — base padding: space-100 */\n.roundedFirstMD { padding-right: var(--dimension-space-100) !important; }\n.roundedLastMD { padding-left: var(--dimension-space-100) !important; }\n.roundedMidMD { padding-left: var(--dimension-space-100) !important; padding-right: var(--dimension-space-100) !important; }\n\n/* SM — base padding: space-075 */\n.roundedFirstSM { padding-right: var(--dimension-space-075) !important; }\n.roundedLastSM { padding-left: var(--dimension-space-075) !important; }\n.roundedMidSM { padding-left: var(--dimension-space-075) !important; padding-right: var(--dimension-space-075) !important; }\n\n/* LG — base padding: space-150 */\n.roundedFirstLG { padding-right: var(--dimension-space-150) !important; }\n.roundedLastLG { padding-left: var(--dimension-space-150) !important; }\n.roundedMidLG { padding-left: var(--dimension-space-150) !important; padding-right: var(--dimension-space-150) !important; }\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './ButtonGroup.module.css';\n\nexport interface ButtonGroupProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/**\n * Renders Button children flush side-by-side with a 1px divider between them.\n * Outer corners keep the button's own border-radius; inner corners are flattened.\n *\n * Individual button chrome (shadow/border) is suppressed — the group container\n * carries the elevation so it wraps the whole control as one visual unit.\n *\n * Divider behaviour by variant:\n * secondary / primary+none — full-height color-border-tertiary line\n * primary (with intent) — color-border-tertiary-on-{contrast}-background\n * ghost (secondary+none) — short centred line (icon/text height)\n *\n * Rounded groups: outer edges keep pill padding; inner edges revert to base padding.\n * Mix of intents is only valid when variant=\"secondary\"; primary groups must be\n * homogeneous (same intent + contrast on all items).\n */\nexport const ButtonGroup = ({ children, className }: ButtonGroupProps) => {\n const items = React.Children.toArray(children).filter(React.isValidElement);\n const count = items.length;\n\n // Read elevation + rounded from first child to drive the group container style.\n const firstEl = items[0] as React.ReactElement<Record<string, unknown>> | undefined;\n const firstProps = firstEl?.props as { variant?: string; elevation?: string; rounded?: boolean } | undefined;\n const firstVariant = firstProps?.variant ?? 'secondary';\n const firstElevation = firstProps?.elevation ?? (firstVariant === 'primary' ? 'none' : 'flat');\n const groupRounded = !!firstProps?.rounded;\n const groupElevKey = firstElevation.charAt(0).toUpperCase() + firstElevation.slice(1);\n\n return (\n <div\n className={cn(\n styles.group,\n (styles as Record<string, string>)[`group${groupElevKey}`],\n groupRounded && styles.groupRounded,\n className,\n )}\n role=\"group\"\n >\n {items.map((child, i) => {\n const el = child as React.ReactElement<Record<string, unknown>>;\n const p = el.props as {\n className?: string;\n variant?: string;\n elevation?: string;\n size?: string;\n intent?: string;\n contrast?: string;\n rounded?: boolean;\n icon?: unknown;\n label?: unknown;\n };\n\n const isFirst = i === 0;\n const isLast = i === count - 1;\n const isMid = !isFirst && !isLast;\n\n const variant = p.variant ?? 'secondary';\n const size = (p.size ?? 'md') as 'xs' | 'sm' | 'md' | 'lg';\n const contrast = p.contrast ?? 'bold';\n const intent = p.intent ?? 'brand';\n const isRounded = !!p.rounded;\n const isIconOnly = !!p.icon && !p.label;\n // Ghost: secondary button with elevation='none' (replaces old tertiary variant)\n const isGhost = variant === 'secondary' && (p.elevation ?? 'flat') === 'none';\n const isPrimary = variant === 'primary' && intent !== 'none';\n\n // Contrast class suffix — capitalised first letter\n const contrastKey = contrast.charAt(0).toUpperCase() + contrast.slice(1);\n\n // Size suffix for rounded padding correction — uppercase\n // XS rounded has no extra padding in Button so needs no correction\n const sizeKey = size.toUpperCase() as 'MD' | 'SM' | 'LG' | 'XS';\n const needsRoundedCorrection = isRounded && !isIconOnly && size !== 'xs';\n\n // Divider injected as a separate element so it's never affected by\n // the adjacent button's opacity (e.g. disabled state).\n const dividerClasses = cn(\n styles.divider,\n isGhost && styles.dividerGhost,\n isGhost && size === 'xs' && styles.dividerGhostXS,\n isGhost && size === 'sm' && styles.dividerGhostSM,\n isGhost && size === 'lg' && styles.dividerGhostLG,\n isPrimary && (styles as Record<string, string>)[`divider${contrastKey}`],\n );\n\n return (\n <React.Fragment key={i}>\n {i > 0 && <div className={dividerClasses} aria-hidden=\"true\" />}\n {React.cloneElement(el, {\n className: cn(\n p.className,\n styles.item,\n isFirst && styles.first,\n isLast && styles.last,\n isMid && styles.middle,\n\n // Ghost (secondary+elevation=none): ::after overlay gets 4px radius treatment\n isGhost && styles.itemShort,\n\n // Rounded: revert inner-edge padding to base (non-pill) value\n needsRoundedCorrection && isFirst && (styles as Record<string, string>)[`roundedFirst${sizeKey}`],\n needsRoundedCorrection && isLast && (styles as Record<string, string>)[`roundedLast${sizeKey}`],\n needsRoundedCorrection && isMid && (styles as Record<string, string>)[`roundedMid${sizeKey}`],\n ),\n })}\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n\nButtonGroup.displayName = 'ButtonGroup';\n","/* ==========================================================================\n ToggleButtonGroup — flush row of ToggleButton components\n ========================================================================== */\n\n.group {\n display: inline-flex;\n align-items: stretch;\n border-radius: var(--dimension-radius-050);\n position: relative;\n}\n\n/* Inset ring / highlight overlay — sits above button children so it isn't\n covered by their backgrounds. Outset shadow stays on the element itself. */\n.group::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n}\n\n/* ── Group-level elevation ──────────────────────────────────────────────── */\n/* Individual item chrome (shadow/border) is suppressed via .item below.\n The group container carries the elevation so it wraps the whole control. */\n\n/* Outset shadow on element; inset highlight on ::after (children would cover it otherwise) */\n.groupElevated { box-shadow: var(--effect-shadow-elevated-sm); }\n.groupElevated::after { box-shadow: var(--effect-highlight-elevated-sm); }\n\n/* Flat ring lives entirely on ::after — same reasoning as highlight */\n.groupFlat::after { box-shadow: inset 0 0 0 1px var(--color-border-tertiary); }\n\n.groupFloating { box-shadow: var(--effect-shadow-elevated-floating); }\n.groupFloating::after { box-shadow: var(--effect-highlight-elevated-floating); }\n/* groupNone = ghost — no shadow, no border */\n\n.groupRounded { border-radius: var(--dimension-radius-half); }\n\n/* ── Base item ─────────────────────────────────────────────────────────────── */\n\n.item {\n flex-shrink: 0;\n /* Suppress individual elevation so the group reads as one unit */\n box-shadow: none !important;\n /* Suppress noElevation individual border — divider handles separation */\n border: none !important;\n /* Suppress scale-on-press: transform would detach the divider from the\n adjacent button, creating a visible gap. Pressed state is still\n communicated via the ::after overlay colour. */\n}\n.item:active {\n transform: none !important;\n}\n\n/* ── Divider ────────────────────────────────────────────────────────────────\n * Rendered as a separate <div> between items so it is never part of any\n * button's stacking context — disabled (opacity: 0.5) or other state changes\n * on adjacent buttons cannot bleed through to the divider.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* Full-height divider (elevated / flat / floating).\n * Rendered as a separate element (independent of adjacent button opacity),\n * then nudged ±0.5px so it overlaps each neighbour and paints on top via\n * z-index — this lets the alpha token (rgb(0 0 0 / 0.1)) composite over\n * whatever fill the buttons carry (white, blue pressed state, etc.). */\n.divider {\n width: 1px;\n flex-shrink: 0;\n background-color: var(--color-border-tertiary);\n position: relative;\n z-index: 1;\n margin: 0 -0.5px;\n pointer-events: none;\n}\n\n/* Ghost (elevation=none): short centred divider at icon height */\n.dividerGhost { height: 20px; align-self: center; } /* md default */\n.dividerGhostXS { height: 12px; }\n.dividerGhostSM { height: 16px; }\n\n/* Ghost hover-fade: hide the divider on either side of a hovered ghost button */\n.item:hover + .dividerGhost,\n.dividerGhost:has(+ .item:hover) { opacity: 0; }\n\n/* Ghost pressed-state: hide the divider on either side of a selected button */\n.itemPressed + .dividerGhost,\n.dividerGhost:has(+ .itemPressed) { opacity: 0; }\n\n\n/* ── Ghost interaction states: rounded chips ──────────────────────────────────\n * Ghost items have no connecting chrome — hover/press overlay and selected\n * state always appear as independent rounded chips (4px on all corners).\n * Rounded groups: outer corners of first/last become pill; inner stay 4px.\n *\n * Uses explicit longhands throughout to avoid shorthand/longhand cascade\n * ordering ambiguity with the !important rules in .first / .last / .middle.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* ::after hover/press overlay — all positions: 4px all corners.\n Uses .group as ancestor (2-class specificity) to reliably beat\n .first / .last / .middle (1-class) regardless of load order. */\n.group .itemShort::after {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* Selected chip — all positions: 4px all corners */\n.group .itemPressed {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* ── Border radius: flatten only the inner-facing corners ──────────────────── */\n/* Outer corners keep the button's own radius — works for default + rounded */\n\n.first {\n border-top-right-radius: 0 !important;\n border-bottom-right-radius: 0 !important;\n}\n\n.last {\n border-top-left-radius: 0 !important;\n border-bottom-left-radius: 0 !important;\n}\n\n.middle {\n border-radius: 0 !important;\n}\n\n/* Rounded group: first — left corners become pill (3-class specificity) */\n.groupRounded .first.itemShort::after,\n.groupRounded .first.itemPressed {\n border-top-left-radius: var(--dimension-radius-half) !important;\n border-bottom-left-radius: var(--dimension-radius-half) !important;\n}\n\n/* Rounded group: last — right corners become pill (3-class specificity) */\n.groupRounded .last.itemShort::after,\n.groupRounded .last.itemPressed {\n border-top-right-radius: var(--dimension-radius-half) !important;\n border-bottom-right-radius: var(--dimension-radius-half) !important;\n}\n\n/* ── Rounded: inner-edge padding correction ────────────────────────────────── */\n/*\n * Rounded buttons add `space-050` extra padding on each side.\n * In a group the inner-facing edge should use base (non-pill) padding instead.\n * XS rounded has no extra padding so needs no correction.\n */\n\n/* MD — base padding: space-100 */\n.roundedFirstMD { padding-right: var(--dimension-space-100) !important; }\n.roundedLastMD { padding-left: var(--dimension-space-100) !important; }\n.roundedMidMD { padding-left: var(--dimension-space-100) !important; padding-right: var(--dimension-space-100) !important; }\n\n/* SM — base padding: space-075 */\n.roundedFirstSM { padding-right: var(--dimension-space-075) !important; }\n.roundedLastSM { padding-left: var(--dimension-space-075) !important; }\n.roundedMidSM { padding-left: var(--dimension-space-075) !important; padding-right: var(--dimension-space-075) !important; }\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './ToggleButtonGroup.module.css';\n\nexport interface ToggleButtonGroupProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/**\n * Renders ToggleButton children flush side-by-side with a 1px divider between them.\n * Outer corners keep the button's own border-radius; inner corners are flattened.\n *\n * Individual button chrome (shadow/border) is suppressed — the group container\n * carries the elevation so it wraps the whole control as one visual unit.\n *\n * Divider behaviour by elevation:\n * elevated / flat / floating — full-height color-border-tertiary line\n * none (ghost) — short centred line (icon/text height)\n *\n * Rounded groups: outer edges keep pill padding; inner edges revert to base padding.\n * Pressed state and onPressedChange are managed by the consumer on each ToggleButton.\n */\nexport const ToggleButtonGroup = ({ children, className }: ToggleButtonGroupProps) => {\n const items = React.Children.toArray(children).filter(React.isValidElement);\n const count = items.length;\n\n // Read elevation + rounded from first child to drive the group container style.\n const firstEl = items[0] as React.ReactElement<Record<string, unknown>> | undefined;\n const firstProps = firstEl?.props as { elevation?: string; rounded?: boolean } | undefined;\n const groupElevation = firstProps?.elevation ?? 'elevated';\n const groupRounded = !!firstProps?.rounded;\n const groupElevKey = groupElevation.charAt(0).toUpperCase() + groupElevation.slice(1);\n\n return (\n <div\n className={cn(\n styles.group,\n (styles as Record<string, string>)[`group${groupElevKey}`],\n groupRounded && styles.groupRounded,\n className,\n )}\n role=\"group\"\n >\n {items.map((child, i) => {\n const el = child as React.ReactElement<Record<string, unknown>>;\n const p = el.props as {\n className?: string;\n elevation?: string;\n size?: string;\n rounded?: boolean;\n pressed?: boolean;\n icon?: unknown;\n label?: unknown;\n };\n\n const isFirst = i === 0;\n const isLast = i === count - 1;\n const isMid = !isFirst && !isLast;\n\n const size = (p.size ?? 'md') as 'xs' | 'sm' | 'md';\n const isRounded = !!p.rounded;\n const isPressed = !!p.pressed;\n const isIconOnly = !!p.icon && !p.label;\n // Ghost: elevation='none' (no chrome) → short centred divider\n const isGhost = (p.elevation ?? 'elevated') === 'none';\n\n // XS rounded has no extra padding in ToggleButton so needs no correction\n const sizeKey = size.toUpperCase() as 'XS' | 'SM' | 'MD';\n const needsRoundedCorrection = isRounded && !isIconOnly && size !== 'xs';\n\n // Divider injected as a separate element so it's never affected by\n // the adjacent button's opacity (e.g. disabled state).\n const dividerClasses = cn(\n styles.divider,\n isGhost && styles.dividerGhost,\n isGhost && size === 'xs' && styles.dividerGhostXS,\n isGhost && size === 'sm' && styles.dividerGhostSM,\n );\n\n return (\n <React.Fragment key={i}>\n {i > 0 && <div className={dividerClasses} aria-hidden=\"true\" />}\n {React.cloneElement(el, {\n className: cn(\n p.className,\n styles.item,\n isFirst && styles.first,\n isLast && styles.last,\n isMid && styles.middle,\n\n // Ghost variant: ::after overlay gets 4px radius treatment\n isGhost && styles.itemShort,\n\n // Ghost + pressed: selected state background chip\n isGhost && isPressed && styles.itemPressed,\n\n // Rounded: revert inner-edge padding to base (non-pill) value\n needsRoundedCorrection && isFirst && (styles as Record<string, string>)[`roundedFirst${sizeKey}`],\n needsRoundedCorrection && isLast && (styles as Record<string, string>)[`roundedLast${sizeKey}`],\n needsRoundedCorrection && isMid && (styles as Record<string, string>)[`roundedMid${sizeKey}`],\n ),\n })}\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n\nToggleButtonGroup.displayName = 'ToggleButtonGroup';\n","/* ==========================================================================\n Tag — hover/pressed via direct background-color + color-mix().\n No pseudo-element overlays.\n ========================================================================== */\n\n.tag {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--dimension-radius-050);\n box-sizing: border-box;\n color: var(--color-foreground-primary);\n position: relative;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n/* ==========================================================================\n Sizes\n md 28px — no size-350 token, expressed as 7/2 × base\n sm 20px — size-250\n xs 12px — size-150\n ========================================================================== */\n\n.sizeMd { height: calc(var(--dimension-size-base) * 7 / 2); padding: 0 var(--dimension-space-075); gap: 0; }\n.sizeSm { height: var(--dimension-size-250); padding: 0 var(--dimension-space-050); gap: 0; }\n.sizeXs { height: var(--dimension-size-150); padding: 0 var(--dimension-space-012); gap: 0; }\n\n/* ==========================================================================\n Rounded\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n\n/*\n * Pill padding correction — add space-050 to sides that have no content anchor.\n * Applied by Tag.tsx based on whether a leading icon or trailing remove is present:\n * no leading icon → roundedLeft{Size} (left side is bare label text)\n * no trailing icon → roundedRight{Size} (right side is bare label text)\n * Placed after size rules so same-specificity cascade wins correctly.\n */\n\n/* MD — base: space-075 */\n.roundedLeftMD { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.roundedRightMD { padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n\n/* SM — base: space-050 */\n.roundedLeftSM { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); }\n.roundedRightSM { padding-right: calc(var(--dimension-space-050) + var(--dimension-space-050)); }\n\n/* XS — base: space-012 (1px) */\n.roundedLeftXS { padding-left: calc(var(--dimension-space-012) + var(--dimension-space-050)); }\n.roundedRightXS { padding-right: calc(var(--dimension-space-012) + var(--dimension-space-050)); }\n\n/*\n * Icon-edge padding correction — when an icon (leading or remove) sits on a\n * side, that side's padding should match the top/bottom optical gap:\n * (height − icon_size) / 2\n *\n * md: (28 − 20) / 2 = 4px → space-050\n * sm: (20 − 16) / 2 = 2px → space-025\n * xs: (12 − 12) / 2 = 0px → 0\n *\n * Applied by Tag.tsx: iconLeft when Icon present, iconRight when removable.\n * Placed after size + rounded rules so same-specificity cascade wins.\n */\n.iconLeftMD { padding-left: var(--dimension-space-050); }\n.iconRightMD { padding-right: var(--dimension-space-050); }\n\n.iconLeftSM { padding-left: var(--dimension-space-025); }\n.iconRightSM { padding-right: var(--dimension-space-025); }\n\n.iconLeftXS { padding-left: 0; }\n.iconRightXS { padding-right: 0; }\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n}\n\n/* ==========================================================================\n Elevation\n none — filled intent bg, no border, no shadow (default)\n flat — transparent bg + intent-coloured border ring\n elevated — filled intent bg + elevated shadow\n ========================================================================== */\n\n/* elevationNone — no extra chrome needed, intent+contrast classes handle fill */\n\n.elevationFlat {\n background-color: transparent !important;\n box-shadow: inset 0 0 0 var(--dimension-stroke-width-015) currentColor;\n}\n\n/* Flat: no background — use on-surface fg tokens matched to the contrast level.\n The border ring is currentColor so it follows text color automatically.\n 3-class specificity beats the 2-class intent+contrast filled rules above. */\n\n.elevationFlat.intentNeutral.contrastBold { color: var(--color-foreground-bold-neutral); }\n.elevationFlat.intentBrand.contrastBold { color: var(--color-foreground-bold-brand); }\n.elevationFlat.intentAi.contrastBold { color: var(--color-foreground-bold-ai); }\n.elevationFlat.intentNegative.contrastBold { color: var(--color-foreground-bold-negative); }\n.elevationFlat.intentWarning.contrastBold { color: var(--color-foreground-bold-warning); }\n.elevationFlat.intentCaution.contrastBold { color: var(--color-foreground-bold-caution); }\n.elevationFlat.intentPositive.contrastBold { color: var(--color-foreground-bold-positive); }\n\n.elevationFlat.intentNeutral.contrastStrong { color: var(--color-foreground-strong-neutral); }\n.elevationFlat.intentBrand.contrastStrong { color: var(--color-foreground-strong-brand); }\n.elevationFlat.intentAi.contrastStrong { color: var(--color-foreground-strong-ai); }\n.elevationFlat.intentNegative.contrastStrong { color: var(--color-foreground-strong-negative); }\n.elevationFlat.intentWarning.contrastStrong { color: var(--color-foreground-strong-warning); }\n.elevationFlat.intentCaution.contrastStrong { color: var(--color-foreground-strong-caution); }\n.elevationFlat.intentPositive.contrastStrong { color: var(--color-foreground-strong-positive); }\n\n.elevationFlat.intentNeutral.contrastMedium { color: var(--color-foreground-medium-neutral); }\n.elevationFlat.intentBrand.contrastMedium { color: var(--color-foreground-medium-brand); }\n.elevationFlat.intentAi.contrastMedium { color: var(--color-foreground-medium-ai); }\n.elevationFlat.intentNegative.contrastMedium { color: var(--color-foreground-medium-negative); }\n.elevationFlat.intentWarning.contrastMedium { color: var(--color-foreground-medium-warning); }\n.elevationFlat.intentCaution.contrastMedium { color: var(--color-foreground-medium-caution); }\n.elevationFlat.intentPositive.contrastMedium { color: var(--color-foreground-medium-positive); }\n\n.elevationFlat.intentNeutral.contrastFaint { color: var(--color-foreground-faint-neutral); }\n.elevationFlat.intentBrand.contrastFaint { color: var(--color-foreground-faint-brand); }\n.elevationFlat.intentAi.contrastFaint { color: var(--color-foreground-faint-ai); }\n.elevationFlat.intentNegative.contrastFaint { color: var(--color-foreground-faint-negative); }\n.elevationFlat.intentWarning.contrastFaint { color: var(--color-foreground-faint-warning); }\n.elevationFlat.intentCaution.contrastFaint { color: var(--color-foreground-faint-caution); }\n.elevationFlat.intentPositive.contrastFaint { color: var(--color-foreground-faint-positive); }\n\n.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n\n/* ==========================================================================\n Intent + contrast — strong\n ========================================================================== */\n\n.intentNeutral.contrastStrong { background-color: var(--color-background-strong-neutral); color: var(--color-foreground-medium-neutral); }\n.intentBrand.contrastStrong { background-color: var(--color-background-strong-brand); color: var(--color-foreground-medium-brand); }\n.intentAi.contrastStrong { background-color: var(--color-background-strong-ai); color: var(--color-foreground-medium-ai); }\n.intentNegative.contrastStrong { background-color: var(--color-background-strong-negative); color: var(--color-foreground-medium-negative); }\n.intentWarning.contrastStrong { background-color: var(--color-background-strong-warning); color: var(--color-foreground-medium-warning); }\n.intentCaution.contrastStrong { background-color: var(--color-background-strong-caution); color: var(--color-foreground-medium-caution); }\n.intentPositive.contrastStrong { background-color: var(--color-background-strong-positive); color: var(--color-foreground-medium-positive); }\n\n/* ==========================================================================\n Intent + contrast — bold\n ========================================================================== */\n\n.intentNeutral.contrastBold { background-color: var(--color-background-bold-neutral); color: var(--color-foreground-on-bold-background-primary); }\n.intentBrand.contrastBold { background-color: var(--color-background-bold-brand); color: var(--color-foreground-on-bold-background-primary); }\n.intentAi.contrastBold { background-color: var(--color-background-bold-ai); color: var(--color-foreground-on-bold-background-primary); }\n.intentNegative.contrastBold { background-color: var(--color-background-bold-negative); color: var(--color-foreground-on-bold-background-primary); }\n.intentWarning.contrastBold { background-color: var(--color-background-bold-warning); color: var(--color-foreground-on-bold-background-primary); }\n.intentCaution.contrastBold { background-color: var(--color-background-bold-caution); color: var(--color-foreground-on-bold-background-primary); }\n.intentPositive.contrastBold { background-color: var(--color-background-bold-positive); color: var(--color-foreground-on-bold-background-primary); }\n\n/* ==========================================================================\n Intent + contrast — medium\n ========================================================================== */\n\n.intentNeutral.contrastMedium { background-color: var(--color-background-medium-neutral); color: var(--color-foreground-strong-neutral); }\n.intentBrand.contrastMedium { background-color: var(--color-background-medium-brand); color: var(--color-foreground-strong-brand); }\n.intentAi.contrastMedium { background-color: var(--color-background-medium-ai); color: var(--color-foreground-strong-ai); }\n.intentNegative.contrastMedium { background-color: var(--color-background-medium-negative); color: var(--color-foreground-strong-negative); }\n.intentWarning.contrastMedium { background-color: var(--color-background-medium-warning); color: var(--color-foreground-strong-warning); }\n.intentCaution.contrastMedium { background-color: var(--color-background-medium-caution); color: var(--color-foreground-strong-caution); }\n.intentPositive.contrastMedium { background-color: var(--color-background-medium-positive); color: var(--color-foreground-strong-positive); }\n\n/* ==========================================================================\n Intent + contrast — faint\n ========================================================================== */\n\n.intentNeutral.contrastFaint { background-color: var(--color-background-faint-neutral); color: var(--color-foreground-bold-neutral); }\n.intentBrand.contrastFaint { background-color: var(--color-background-faint-brand); color: var(--color-foreground-bold-brand); }\n.intentAi.contrastFaint { background-color: var(--color-background-faint-ai); color: var(--color-foreground-bold-ai); }\n.intentNegative.contrastFaint { background-color: var(--color-background-faint-negative); color: var(--color-foreground-bold-negative); }\n.intentWarning.contrastFaint { background-color: var(--color-background-faint-warning); color: var(--color-foreground-bold-warning); }\n.intentCaution.contrastFaint { background-color: var(--color-background-faint-caution); color: var(--color-foreground-bold-caution); }\n.intentPositive.contrastFaint { background-color: var(--color-background-faint-positive); color: var(--color-foreground-bold-positive); }\n\n/* ==========================================================================\n Interactive (clickable / filter-chip)\n ========================================================================== */\n\n.interactive {\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n outline: none;\n}\n\n.interactive:hover { background-color: var(--_hover-bg); }\n.interactive:active { background-color: var(--_pressed-bg); }\n\n.interactive:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n/* ==========================================================================\n Pressed / selected (filter-chip active state)\n Always brand — same language as ToggleButton\n ========================================================================== */\n\n.tag.pressed {\n background-color: var(--color-background-faint-brand) !important;\n color: var(--color-foreground-bold-brand) !important;\n border-color: transparent !important;\n}\n\n/* ==========================================================================\n Remove button — keeps ::before overlay for its own isolated hit area\n ========================================================================== */\n\n.removable { gap: var(--dimension-space-025); }\n.sizeXs.removable { gap: 0; }\n\n.removeButton {\n padding: 0; margin: 0; border: none; background: none;\n display: flex; align-items: center; justify-content: center;\n cursor: pointer; color: inherit; flex-shrink: 0;\n position: relative; border-radius: var(--dimension-radius-050);\n}\n\n.removeButton::before {\n content: ''; position: absolute; inset: -2px;\n border-radius: var(--dimension-radius-025);\n background-color: transparent;\n transition: var(--effect-transition-interaction-background-short-2);\n pointer-events: none;\n}\n\n.removeButton:hover::before { background-color: var(--color-interaction-hover); }\n.removeButton:active::before { background-color: var(--color-interaction-pressed); }\n\n/* SM — 1px gap, inset -1px → 18×18 hover area */\n.sizeSm .removeButton::before { inset: -1px; border-radius: 3px; }\n\n/* XS — flush, inset 0 → 12×12 hover area matching tag radius */\n.sizeXs .removeButton::before { inset: 0; border-radius: var(--dimension-radius-050); }\n\n.rounded .removeButton,\n.rounded .removeButton::before { border-radius: var(--dimension-radius-half); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; pointer-events: none; cursor: not-allowed; }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport { Cross } from '@ds-mo/icons';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Tag.module.css';\n\nexport type TagIntent = 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';\nexport type TagContrast = 'strong' | 'bold' | 'medium' | 'faint';\nexport type TagElevation = 'none' | 'flat' | 'elevated';\nexport type TagSize = 'md' | 'sm' | 'xs';\nexport type TagBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface TagProps {\n label: string;\n intent?: TagIntent;\n contrast?: TagContrast;\n /**\n * Visual chrome level.\n * none — filled with intent bg, no border, no shadow [default]\n * flat — transparent bg + intent-coloured border ring\n * elevated — filled with intent bg + elevated shadow\n */\n elevation?: TagElevation;\n size?: TagSize;\n rounded?: boolean;\n /** Leading icon component. */\n icon?: IconComponent;\n removable?: boolean;\n onRemove?: () => void;\n /** Override the default Cross remove icon. */\n removeIcon?: IconComponent;\n maxWidth?: string | number;\n inactive?: boolean;\n /** Parent surface context. Adjusts hover tokens for tags on colored backgrounds. */\n background?: TagBackground;\n /** Makes the tag clickable. Pair with pressed/onPressedChange for filter-chip behaviour. */\n onClick?: () => void;\n pressed?: boolean;\n onPressedChange?: (pressed: boolean) => void;\n className?: string;\n}\n\nconst ICON_SIZE: Record<TagSize, number> = { md: 20, sm: 16, xs: 12 };\n\nconst TEXT_STYLE_MAP: Record<TagSize, string> = {\n md: 'text-body-medium',\n sm: 'text-body-small',\n xs: 'text-caption',\n};\n\nexport const Tag = forwardRef<HTMLDivElement, TagProps>(\n (\n {\n label,\n intent = 'neutral',\n contrast = 'faint',\n elevation = 'none',\n size = 'md',\n rounded = false,\n icon: Icon,\n removable = false,\n onRemove,\n removeIcon: RemoveIcon,\n maxWidth,\n inactive = false,\n background,\n onClick,\n pressed,\n onPressedChange,\n className,\n },\n ref\n ) => {\n const isInteractive = !!onClick || !!onPressedChange;\n const hasRemove = removable && !!onRemove;\n const iconSize = ICON_SIZE[size];\n const textStyle = TEXT_STYLE_MAP[size];\n const elevKey = elevation.charAt(0).toUpperCase() + elevation.slice(1);\n const sizeKey = size.toUpperCase() as 'MD' | 'SM' | 'XS';\n\n const classes = cn(\n styles.tag,\n styles[`intent${intent.charAt(0).toUpperCase() + intent.slice(1)}`],\n styles[`contrast${contrast.charAt(0).toUpperCase() + contrast.slice(1)}`],\n styles[`elevation${elevKey}`],\n styles[`size${size.charAt(0).toUpperCase() + size.slice(1)}`],\n rounded && styles.rounded,\n // Pill padding correction — extra space-050 on bare sides (no content anchor)\n rounded && !Icon && (styles as Record<string, string>)[`roundedLeft${sizeKey}`],\n rounded && !hasRemove && (styles as Record<string, string>)[`roundedRight${sizeKey}`],\n // Icon-edge correction — reduce padding to (height − icon) / 2 on icon sides\n !!Icon && (styles as Record<string, string>)[`iconLeft${sizeKey}`],\n hasRemove && (styles as Record<string, string>)[`iconRight${sizeKey}`],\n removable && styles.removable,\n isInteractive && styles.interactive,\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n inactive && styles.inactive,\n pressed && styles.pressed,\n className,\n );\n\n const style = maxWidth != null\n ? { maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth }\n : undefined;\n\n const handleInteract = isInteractive && !inactive\n ? () => {\n onPressedChange?.(!pressed);\n onClick?.();\n }\n : undefined;\n\n const handleKeyDown = isInteractive && !inactive\n ? (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onPressedChange?.(!pressed);\n onClick?.();\n }\n }\n : undefined;\n\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n onClick={handleInteract}\n onKeyDown={handleKeyDown}\n role={isInteractive ? 'button' : undefined}\n tabIndex={isInteractive && !inactive ? 0 : undefined}\n aria-pressed={onPressedChange != null ? pressed : undefined}\n aria-disabled={inactive || undefined}\n >\n {Icon && <Icon size={iconSize} />}\n <LabelWrap size={size}>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n {removable && onRemove && (\n <button\n type=\"button\"\n className={styles.removeButton}\n onClick={(e) => { e.stopPropagation(); onRemove(); }}\n aria-label={`Remove ${label}`}\n tabIndex={-1}\n >\n {RemoveIcon ? <RemoveIcon size={iconSize} /> : <Cross size={iconSize} />}\n </button>\n )}\n </div>\n );\n }\n);\n\nTag.displayName = 'Tag';\n",".badge {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n}\n","import React from 'react';\nimport { Text } from '@/components/Text';\nimport styles from './Badge.module.css';\n\nexport interface BadgeProps {\n count: number;\n isSelected?: boolean;\n className?: string;\n}\n\nexport const Badge: React.FC<BadgeProps> = ({ count, isSelected = false, className }) => {\n if (count === 0) return null;\n const displayText = count > 9 ? '+' : count.toString();\n return (\n <span className={`${styles.badge} ${className || ''}`} aria-label={`${count} unread`}>\n <Text variant=\"text-caption-emphasis\" as=\"span\" color={isSelected ? 'primary' : 'secondary'}>\n {displayText}\n </Text>\n </span>\n );\n};\n\nBadge.displayName = 'Badge';\n",".toggle {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n width: var(--dimension-size-400);\n height: var(--dimension-size-250);\n padding: 0 var(--dimension-space-025);\n border: none;\n border-radius: var(--dimension-radius-half);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n outline: none;\n flex-shrink: 0;\n background-color: var(--color-background-medium-neutral);\n box-shadow: var(--effect-highlight-depressed-sm);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.toggle::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: var(--effect-shadow-depressed-sm);\n pointer-events: none;\n}\n\n.toggle:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.checked {\n background-color: var(--color-foreground-bold-brand) !important;\n}\n\n.thumb {\n position: relative;\n flex-shrink: 0;\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-half);\n box-shadow: var(--effect-elevation-elevated-sm);\n transition: transform var(--effect-motion-short-2);\n transform: translateX(0);\n z-index: 1;\n}\n\n.thumb::after {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: inherit;\n transition: var(--effect-transition-interaction-background-instant);\n pointer-events: none;\n}\n\n.toggle:hover:not(.inactive) .thumb::after {\n background-color: var(--color-interaction-hover);\n}\n\n.toggle:active:not(.inactive) .thumb::after {\n background-color: var(--color-interaction-pressed);\n}\n\n.checked .thumb {\n transform: translateX(var(--dimension-offset-150));\n}\n\n.toggle:active:not(.inactive) .thumb {\n transform: translateX(0) scale(var(--dimension-scale-subtle)) !important;\n transition: transform var(--effect-motion-instant);\n}\n\n.checked.toggle:active:not(.inactive) .thumb {\n transform: translateX(var(--dimension-offset-150)) scale(var(--dimension-scale-subtle)) !important;\n transition: transform var(--effect-motion-instant);\n}\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n}\n","import React, { forwardRef, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Toggle.module.css';\n\nexport interface ToggleProps {\n checked?: boolean;\n onChange?: (checked: boolean) => void;\n inactive?: boolean;\n className?: string;\n 'aria-label'?: string;\n}\n\nexport const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(\n ({ checked = false, onChange, inactive = false, className, 'aria-label': ariaLabel }, ref) => {\n const [isPressed, setIsPressed] = useState(false);\n\n const handleMouseDown = (e: React.MouseEvent) => {\n if (inactive) return;\n e.preventDefault();\n setIsPressed(true);\n };\n\n const handleMouseUp = () => {\n if (inactive || !isPressed) return;\n setIsPressed(false);\n onChange?.(!checked);\n };\n\n const handleMouseLeave = () => {\n if (isPressed) setIsPressed(false);\n };\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={ariaLabel}\n disabled={inactive}\n className={cn(styles.toggle, checked && styles.checked, inactive && styles.inactive, className)}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n >\n <span className={styles.thumb} />\n </button>\n );\n }\n);\n\nToggle.displayName = 'Toggle';\n",".checkbox {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n height: var(--dimension-size-400);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border-radius: var(--dimension-radius-075);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.checkbox:hover { background-color: var(--color-interaction-hover); }\n.checkbox:active { background-color: var(--color-interaction-pressed); }\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* Fallback checkbox box (when no icon components provided) */\n.box {\n width: 20px;\n height: 20px;\n border: 1.5px solid var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-050);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all var(--effect-motion-short-2);\n}\n\n.boxChecked {\n background-color: var(--color-foreground-primary);\n border-color: var(--color-foreground-primary);\n}\n\n.checkmark {\n color: var(--color-foreground-on-bold-background-primary);\n font-size: 14px;\n line-height: 1;\n font-weight: 700;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Checkbox.module.css';\n\nexport interface CheckboxProps {\n label: string;\n checked?: boolean;\n indeterminate?: boolean;\n onChange?: (checked: boolean) => void;\n inactive?: boolean;\n className?: string;\n /** Icon for checked state. */\n checkedIcon?: IconComponent;\n /** Icon for unchecked state. */\n uncheckedIcon?: IconComponent;\n /** Icon for indeterminate state. */\n indeterminateIcon?: IconComponent;\n}\n\nexport const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(\n (\n {\n label,\n checked = false,\n indeterminate = false,\n onChange,\n inactive = false,\n className,\n checkedIcon: CheckedIcon,\n uncheckedIcon: UncheckedIcon,\n indeterminateIcon: IndeterminateIcon,\n },\n ref\n ) => {\n const handleClick = () => {\n if (!inactive) onChange?.(!checked);\n };\n\n const iconColor = indeterminate || checked ? 'var(--color-foreground-primary)' : 'var(--color-foreground-secondary)';\n const Icon = indeterminate ? IndeterminateIcon : checked ? CheckedIcon : UncheckedIcon;\n\n return (\n <div\n ref={ref}\n role=\"checkbox\"\n aria-checked={indeterminate ? 'mixed' : checked}\n aria-inactive={inactive}\n tabIndex={inactive ? -1 : 0}\n className={cn(styles.checkbox, inactive && styles.inactive, className)}\n onClick={handleClick}\n onKeyDown={e => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); handleClick(); } }}\n >\n {Icon ? <Icon size={20} color={iconColor} /> : (\n <span className={cn(styles.box, (checked || indeterminate) && styles.boxChecked)}>\n {(checked || indeterminate) && <span className={styles.checkmark}>{indeterminate ? '−' : '✓'}</span>}\n </span>\n )}\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </div>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n",".wrapper {\n width: 100%;\n height: var(--dimension-size-400);\n display: flex;\n align-items: center;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-depressed-sm);\n box-sizing: border-box;\n}\n\n.wrapper:focus-within {\n box-shadow: inset 0 0 0 1.25px var(--color-foreground-bold-brand);\n}\n\n.row {\n display: flex;\n align-items: center;\n width: 100%;\n height: 100%;\n gap: var(--dimension-space-050);\n}\n\n.input {\n flex: 1;\n min-width: 0;\n height: 100%;\n padding: 0 var(--dimension-space-100);\n background: transparent;\n border: none;\n outline: none;\n font-family: inherit;\n font-size: var(--typography-fontsize-md);\n line-height: var(--typography-lineheight-md);\n color: var(--color-foreground-primary);\n border-radius: var(--dimension-radius-075);\n -webkit-appearance: none;\n appearance: none;\n}\n\n.input:disabled { opacity: 0.5; cursor: not-allowed; }\n.input::placeholder { color: var(--color-foreground-secondary); }\n.input:focus::placeholder { color: var(--color-foreground-tertiary); }\n\n/* Hide native search clear */\n.input[type=\"search\"]::-webkit-search-cancel-button,\n.input[type=\"search\"]::-webkit-search-decoration { display: none; }\n\n.clearButton {\n flex-shrink: 0;\n margin-right: var(--dimension-space-050);\n padding: var(--dimension-space-050);\n border: none;\n background: none;\n cursor: pointer;\n color: var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-050);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.clearButton:hover { background-color: var(--color-interaction-hover); }\n\n.suffix {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n margin-right: var(--dimension-space-050);\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Input.module.css';\n\nexport type InputType = 'text' | 'email' | 'tel' | 'url' | 'search' | 'password';\n\nexport interface InputProps {\n value: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n id?: string;\n placeholder?: string;\n autoFocus?: boolean;\n className?: string;\n type?: InputType;\n inactive?: boolean;\n onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /** Content rendered inside the field on the right. */\n suffix?: React.ReactNode;\n /** Icon for clear button (search type). */\n clearIcon?: IconComponent;\n 'aria-label'?: string;\n}\n\nexport const Input = forwardRef<HTMLDivElement, InputProps>(\n (\n {\n value,\n onChange,\n id,\n placeholder,\n autoFocus = false,\n className,\n type = 'text',\n inactive = false,\n onKeyDown,\n suffix,\n clearIcon: ClearIcon,\n 'aria-label': ariaLabel,\n },\n ref\n ) => {\n const showClear = type === 'search' && value.length > 0 && !inactive;\n\n const handleClear = () => {\n onChange({ target: { value: '' } } as React.ChangeEvent<HTMLInputElement>);\n };\n\n return (\n <div ref={ref} className={cn(styles.wrapper, className)}>\n <div className={styles.row}>\n <input\n type={type}\n id={id}\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n className={styles.input}\n autoFocus={autoFocus}\n disabled={inactive}\n aria-label={ariaLabel}\n />\n {showClear && (\n <button type=\"button\" className={styles.clearButton} onClick={handleClear} aria-label=\"Clear\">\n {ClearIcon ? <ClearIcon size={16} /> : <span aria-hidden>&times;</span>}\n </button>\n )}\n {suffix && <div className={styles.suffix}>{suffix}</div>}\n </div>\n </div>\n );\n }\n);\n\nInput.displayName = 'Input';\n",".field { display: flex; flex-direction: column; gap: var(--dimension-space-050); width: 100%; }\n.labelRow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--dimension-space-050); }\n\n.track {\n position: relative; width: 100%; height: var(--dimension-size-400);\n padding: 0 var(--dimension-space-025); border-radius: var(--dimension-radius-075); cursor: pointer; -webkit-user-select: none;\n user-select: none;\n}\n\n.trackInner {\n position: absolute; inset: 0; border-radius: inherit;\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-depressed-sm); pointer-events: none; z-index: 1;\n}\n\n.fillTrack { position: absolute; top: var(--dimension-space-025); right: 0; bottom: var(--dimension-space-025); left: 0; z-index: 1; }\n\n.fill {\n position: absolute; left: var(--dimension-space-025); top: 0; bottom: 0;\n width: max(0px, calc((var(--slider-pct, 0) / 100) * (100% - var(--dimension-size-150)) - var(--dimension-space-025)));\n background-color: var(--color-background-bold-brand);\n box-shadow: var(--effect-elevation-elevated-sm);\n border-radius: var(--dimension-radius-050);\n transition: opacity var(--effect-motion-short-2);\n}\n\n.trackAtMin .fill { opacity: 0; }\n\n.thumb {\n position: absolute; top: 0; bottom: 0;\n left: calc((var(--slider-pct, 0) / 100) * (100% - var(--dimension-size-150)));\n width: var(--dimension-size-150); padding: var(--dimension-space-025);\n box-sizing: border-box; pointer-events: none; z-index: 2;\n}\n\n.thumb::before {\n content: ''; position: absolute; inset: var(--dimension-space-025);\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n border-radius: var(--dimension-radius-050);\n}\n\n.thumb::after {\n content: ''; position: absolute; inset: var(--dimension-space-025);\n background-color: transparent; border-radius: var(--dimension-radius-050);\n transition: var(--effect-transition-interaction-background-instant);\n}\n\n.track:hover:not(.trackInactive) .thumb::after { background-color: var(--color-interaction-hover); }\n.track:active:not(.trackInactive) .thumb::after { background-color: var(--color-interaction-pressed); }\n\n.trackInactive { cursor: not-allowed; opacity: 0.5; }\n\n.input {\n position: absolute; inset: 0; width: 100%; height: 100%;\n margin: 0; padding: 0; opacity: 0; cursor: pointer;\n -webkit-appearance: none; appearance: none; outline: none; z-index: 3;\n}\n\n.input:disabled { cursor: not-allowed; }\n.input:hover { cursor: grab; }\n.input:active { cursor: grabbing; }\n","import React, { forwardRef, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Slider.module.css';\n\nexport interface SliderProps {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label: string;\n id?: string;\n inactive?: boolean;\n className?: string;\n}\n\nexport const Slider = forwardRef<HTMLDivElement, SliderProps>(\n ({ value, onChange, min = 0, max = 100, step = 1, label, id: idProp, inactive = false, className }, ref) => {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const containerRef = useRef<HTMLDivElement>(null);\n const [pct, setPct] = useState(() => {\n const range = max - min;\n return range === 0 ? 0 : Math.round(((value - min) / range) * 100);\n });\n\n const sync = useCallback(() => {\n const range = max - min;\n setPct(range === 0 ? 0 : Math.round(((value - min) / range) * 100));\n }, [value, min, max]);\n\n useEffect(() => { sync(); }, [sync]);\n\n const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(Number(e.target.value));\n };\n\n return (\n <div ref={ref} className={cn(styles.field, className)}>\n <div className={styles.labelRow}>\n <Text variant=\"text-body-small-emphasis\" as=\"label\" htmlFor={id}>{label}</Text>\n <Text variant=\"text-body-small-emphasis\" as=\"span\">{value}</Text>\n </div>\n <div\n ref={containerRef}\n className={cn(styles.track, inactive && styles.trackInactive, pct === 0 && styles.trackAtMin)}\n style={{ '--slider-pct': pct } as React.CSSProperties}\n >\n <div className={styles.trackInner}>\n <div className={styles.fillTrack}><div className={styles.fill} /></div>\n <div className={styles.thumb} />\n </div>\n <input\n type=\"range\"\n id={id}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleInput}\n disabled={inactive}\n className={styles.input}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n />\n </div>\n </div>\n );\n }\n);\n\nSlider.displayName = 'Slider';\n",".field {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Field.module.css';\n\nexport interface FieldProps {\n label: string;\n children: React.ReactNode;\n id?: string;\n className?: string;\n}\n\nexport const Field = forwardRef<HTMLDivElement, FieldProps>(\n ({ label, children, id, className }, ref) => (\n <div ref={ref} className={cn(styles.field, className)}>\n <Text variant=\"text-body-small-emphasis\" as=\"label\" htmlFor={id}>{label}</Text>\n {children}\n </div>\n )\n);\n\nField.displayName = 'Field';\n",".backdrop {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-200);\n background-color: var(--color-background-shade);\n backdrop-filter: blur(var(--effect-blur-sm));\n -webkit-backdrop-filter: blur(var(--effect-blur-sm));\n animation: modalBackdropFadeIn var(--effect-motion-short-2) forwards;\n z-index: 9999;\n}\n\n.backdrop.closing {\n animation: modalBackdropFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes modalBackdropFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes modalBackdropFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.dialog {\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 32px);\n overflow: hidden;\n animation: modalDialogFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.backdrop.closing .dialog {\n animation: modalDialogFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes modalDialogFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes modalDialogFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.header {\n padding: var(--dimension-space-200) var(--dimension-space-200) var(--dimension-space-100) var(--dimension-space-200);\n}\n\n.subtitle {\n margin-top: var(--dimension-space-100);\n text-wrap: balance;\n}\n\n.body {\n padding: var(--dimension-space-100) var(--dimension-space-200);\n overflow-y: auto;\n}\n\n.footer {\n padding: var(--dimension-space-100) var(--dimension-space-200) var(--dimension-space-200) var(--dimension-space-200);\n}\n","import React, { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport styles from './Modal.module.css';\n\nexport type ModalWidth = 'sm' | 'md' | 'lg';\n\nconst WIDTH_MAP: Record<ModalWidth, string> = {\n sm: 'var(--dimension-modal-width-sm, 400px)',\n md: 'var(--dimension-modal-width-md, 560px)',\n lg: 'var(--dimension-modal-width-lg, 720px)',\n};\n\nconst CLOSE_ANIMATION_MS = 220;\n\nexport interface ModalProps {\n isOpen: boolean;\n onClose: () => void;\n title: string;\n subtitle?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n width?: ModalWidth | string;\n bodyClassName?: string;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n footer,\n width = 'md',\n bodyClassName,\n}) => {\n const dialogRef = useRef<HTMLDivElement>(null);\n const titleId = useId();\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(isOpen);\n\n const resolvedWidth = useMemo(() => {\n if (width === 'sm' || width === 'md' || width === 'lg') {\n return WIDTH_MAP[width];\n }\n return width;\n }, [width]);\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n setIsClosing(false);\n } else if (shouldRender) {\n setIsClosing(true);\n const timer = setTimeout(() => {\n setShouldRender(false);\n setIsClosing(false);\n }, CLOSE_ANIMATION_MS);\n return () => clearTimeout(timer);\n }\n }, [isOpen, shouldRender]);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (!isOpen || !shouldRender) return;\n const id = requestAnimationFrame(() => {\n dialogRef.current?.focus();\n });\n return () => cancelAnimationFrame(id);\n }, [isOpen, shouldRender]);\n\n if (!shouldRender) return null;\n\n return createPortal(\n <div\n className={`${styles.backdrop} ${isClosing ? styles.closing : ''}`}\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <Surface\n ref={dialogRef}\n background=\"primary\"\n elevation=\"floating\"\n radius=\"var(--dimension-radius-275, 22px)\"\n className={styles.dialog}\n style={{ width: `min(${resolvedWidth}, calc(100vw - 32px))` }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n tabIndex={-1}\n >\n <div className={styles.header}>\n <Text id={titleId} as=\"h2\" variant=\"text-title-small\">\n {title}\n </Text>\n {subtitle != null && (\n <div className={styles.subtitle}>{subtitle}</div>\n )}\n </div>\n <div className={`${styles.body} ${bodyClassName ?? ''}`.trim()}>\n {children}\n </div>\n {footer != null && (\n <div className={styles.footer}>{footer}</div>\n )}\n </Surface>\n </div>,\n document.body\n );\n};\n\nModal.displayName = 'Modal';\n",".menuItem {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n border: none;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n width: 100%;\n min-height: var(--dimension-size-400);\n}\n\n.menuItem:has(.subtext) { align-items: flex-start; }\n\n.iconPrefix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.menuItemSelected .iconPrefix { color: var(--color-foreground-primary); }\n\n.content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.label { color: var(--color-foreground-secondary); }\n.menuItem:has(.subtext) .label { color: var(--color-foreground-primary); }\n.menuItemSelected .label { color: var(--color-foreground-primary) !important; }\n.menuItemLabelTertiary .label, .menuItemLabelTertiary .iconPrefix { color: var(--color-foreground-tertiary); }\n.menuItemNegative .label { color: var(--color-foreground-bold-negative) !important; }\n\n.subtext { color: var(--color-foreground-secondary); line-height: 1.4; }\n\n.menuItemInactive { opacity: 0.5; cursor: default; pointer-events: none; }\n\n.toggleSuffix { flex-shrink: 0; display: flex; align-items: center; }\n\n.toggle {\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n background-color: var(--color-background-translucent);\n border-radius: var(--dimension-radius-125);\n position: relative;\n transition: var(--effect-transition-interaction-background-short-2);\n}\n\n.toggleOn { background-color: var(--color-background-medium-brand); }\n\n.toggleThumb {\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n background-color: var(--color-foreground-on-bold-background-primary);\n border-radius: 50%;\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n transition: transform var(--effect-motion-short-2);\n}\n\n.toggleOn .toggleThumb { transform: translateX(var(--dimension-offset-200)); }\n\n.checkSuffix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-primary);\n}\n\n.chevronSuffix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.menuItemSelected .chevronSuffix { color: var(--color-foreground-primary); }\n","import React, { forwardRef } from 'react';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport type { IconComponent } from '@/types';\nimport styles from './MenuItem.module.css';\n\nexport type MenuItemSelectionStyle = 'highlight' | 'radio' | 'noOverlay';\n\nexport interface MenuItemProps {\n label: string;\n onClick: () => void;\n isSelected?: boolean;\n isInactive?: boolean;\n icon?: IconComponent;\n labelColor?: 'primary' | 'secondary' | 'tertiary';\n subtext?: string;\n showToggle?: boolean;\n toggleValue?: boolean;\n intent?: 'negative';\n selectionStyle?: MenuItemSelectionStyle;\n showTrailingChevron?: boolean;\n checkIcon?: IconComponent;\n chevronIcon?: IconComponent;\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(\n ({\n label,\n onClick,\n isSelected = false,\n isInactive = false,\n icon: Icon,\n labelColor,\n subtext,\n showToggle = false,\n toggleValue = false,\n intent,\n selectionStyle = 'highlight',\n showTrailingChevron = false,\n checkIcon: CheckIcon,\n chevronIcon: ChevronIcon,\n }, ref) => {\n const useRadioStyle = selectionStyle === 'radio';\n const noOverlay = selectionStyle === 'noOverlay' || useRadioStyle;\n const showSelectedOverlay = isSelected && !noOverlay;\n\n return (\n <Surface\n ref={ref as React.Ref<HTMLElement>}\n as=\"button\"\n interactive={!isInactive}\n selected={showSelectedOverlay}\n radius=\"sm\"\n className={`${styles.menuItem} ${isSelected ? styles.menuItemSelected : ''} ${isInactive ? styles.menuItemInactive : ''} ${intent === 'negative' ? styles.menuItemNegative : ''} ${labelColor === 'tertiary' ? styles.menuItemLabelTertiary : ''}`}\n onClick={onClick}\n type=\"button\"\n inactive={isInactive}\n >\n {Icon && (\n <div className={styles.iconPrefix}>\n <Icon size={20} />\n </div>\n )}\n <div className={styles.content}>\n <Text\n variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'}\n color={labelColor}\n as=\"span\"\n className={styles.label}\n >\n {label}\n </Text>\n {subtext && (\n <Text variant=\"text-body-small\" as=\"span\" className={styles.subtext}>\n {subtext}\n </Text>\n )}\n </div>\n {showToggle && (\n <div className={styles.toggleSuffix}>\n <div className={`${styles.toggle} ${toggleValue ? styles.toggleOn : ''}`}>\n <div className={styles.toggleThumb} />\n </div>\n </div>\n )}\n {useRadioStyle && isSelected && CheckIcon && (\n <div className={styles.checkSuffix}>\n <CheckIcon size={20} />\n </div>\n )}\n {showTrailingChevron && ChevronIcon && (\n <div className={styles.chevronSuffix}>\n <ChevronIcon size={20} />\n </div>\n )}\n </Surface>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n",".destructiveMenuItem {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n width: 100%;\n min-height: var(--dimension-size-400);\n position: relative;\n transition: var(--effect-transition-interaction-background-instant);\n overflow: hidden;\n}\n\n.destructiveMenuItem:has(.subtext) { align-items: flex-start; }\n\n.progressFill {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n background-color: var(--color-background-faint-negative);\n border-radius: var(--dimension-radius-075);\n transition: width 0ms linear;\n pointer-events: none;\n z-index: 0;\n}\n\n.destructiveMenuItem::before {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: var(--dimension-radius-075);\n transition: var(--effect-transition-interaction-background-instant);\n pointer-events: none;\n z-index: 1;\n}\n\n.content {\n position: relative;\n z-index: 2;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.label { color: var(--color-foreground-bold-negative); }\n.subtext { color: var(--color-foreground-secondary); text-wrap: pretty; }\n\n.destructiveMenuItem:hover::before { background-color: var(--color-interaction-hover); }\n.destructiveMenuItem:active::before { background-color: transparent; }\n","import React, { forwardRef, useState, useRef, useEffect } from 'react';\nimport { Text } from '@/components/Text';\nimport styles from './DestructiveMenuItem.module.css';\n\nexport interface DestructiveMenuItemProps {\n label: string;\n onClick: () => void;\n holdDuration?: number;\n subtext?: string;\n}\n\nexport const DestructiveMenuItem = forwardRef<HTMLButtonElement, DestructiveMenuItemProps>(\n ({ label, onClick, holdDuration = 4000, subtext }, ref) => {\n const [progress, setProgress] = useState(0);\n const pressTimerRef = useRef<number | null>(null);\n const startTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n\n const resetState = () => {\n setProgress(0);\n if (pressTimerRef.current) { clearTimeout(pressTimerRef.current); pressTimerRef.current = null; }\n if (animationFrameRef.current) { cancelAnimationFrame(animationFrameRef.current); animationFrameRef.current = null; }\n };\n\n const handleMouseDown = (e: React.MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n if (holdDuration === 0) { onClick(); return; }\n startTimeRef.current = performance.now();\n const animate = () => {\n const elapsed = performance.now() - startTimeRef.current;\n const newProgress = Math.min((elapsed / holdDuration) * 100, 100);\n setProgress(newProgress);\n if (newProgress < 100) animationFrameRef.current = requestAnimationFrame(animate);\n };\n animationFrameRef.current = requestAnimationFrame(animate);\n pressTimerRef.current = window.setTimeout(() => { onClick(); resetState(); }, holdDuration);\n };\n\n const handleMouseUp = (e: React.MouseEvent) => { e.stopPropagation(); resetState(); };\n const handleMouseLeave = (e: React.MouseEvent) => { e.stopPropagation(); resetState(); };\n\n useEffect(() => () => { resetState(); }, []);\n\n return (\n <button\n ref={ref}\n className={styles.destructiveMenuItem}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n type=\"button\"\n >\n <div className={styles.progressFill} style={{ width: `${progress}%` }} />\n <div className={styles.content}>\n <Text variant=\"text-body-medium\" as=\"span\" className={styles.label}>{label}</Text>\n {subtext && <Text variant=\"text-body-small\" as=\"span\" className={styles.subtext}>{subtext}</Text>}\n </div>\n </button>\n );\n }\n);\n\nDestructiveMenuItem.displayName = 'DestructiveMenuItem';\n","/**\n * Reads a CSS custom property value from :root as a pixel number.\n * Returns the fallback if the property is not set or not parseable.\n */\nexport function getCssSpacePx(property: string, fallback: number): number {\n if (typeof document === 'undefined') return fallback;\n const raw = getComputedStyle(document.documentElement).getPropertyValue(property).trim();\n const parsed = parseFloat(raw);\n return Number.isNaN(parsed) ? fallback : parsed;\n}\n\n/**\n * Reads a CSS custom property value from :root as a millisecond number.\n * Handles both \"300ms\" and \"0.3s\" formats.\n */\nexport function getCssTimeMs(property: string, fallback: number): number {\n if (typeof document === 'undefined') return fallback;\n const raw = getComputedStyle(document.documentElement).getPropertyValue(property).trim();\n if (raw.endsWith('ms')) return parseFloat(raw) || fallback;\n if (raw.endsWith('s')) return (parseFloat(raw) || 0) * 1000 || fallback;\n return fallback;\n}\n",".menuContainer {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-125);\n box-shadow: var(--effect-elevation-elevated-floating);\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-width: 600px;\n overflow: hidden;\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.menuContainer.closing {\n animation: menuFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.menuSection {\n padding: var(--dimension-space-050);\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n}\n\n.sectionHeader {\n padding: var(--dimension-space-050) var(--dimension-space-075);\n display: flex;\n align-items: center;\n height: var(--dimension-size-400);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.sectionLabel {\n color: var(--color-foreground-secondary);\n text-align: left;\n}\n","import React, { useState, useEffect, useLayoutEffect, useRef, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport { MenuItem as MenuItemComponent } from './MenuItem';\nimport { DestructiveMenuItem } from './DestructiveMenuItem';\nimport { getCssSpacePx } from '@/utils/css-tokens';\nimport type { IconComponent } from '@/types';\nimport type { MenuItemSelectionStyle } from './MenuItem';\nimport styles from './Menu.module.css';\n\nconst CLOSE_ANIMATION_MS = 220;\n\nexport type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuItemData {\n label: string;\n onClick: () => void;\n isSelected?: boolean;\n isDestructive?: boolean;\n isInactive?: boolean;\n intent?: 'negative';\n keepOpenOnClick?: boolean;\n holdDuration?: number;\n icon?: IconComponent;\n subtext?: string;\n showToggle?: boolean;\n toggleValue?: boolean;\n selectionStyle?: MenuItemSelectionStyle;\n}\n\nexport interface MenuSection {\n header?: string;\n items: MenuItemData[];\n}\n\nexport interface MenuProps {\n isOpen: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n items?: MenuItemData[];\n sections?: MenuSection[];\n side?: MenuSide;\n align?: MenuAlign;\n sideOffset?: number;\n alignOffset?: number;\n sideOffsetToken?: string;\n alignOffsetToken?: string;\n width?: string;\n minWidth?: string;\n maxWidth?: string;\n matchAnchorWidth?: boolean;\n matchAnchorWidthOffset?: number;\n usePortal?: boolean;\n}\n\nexport const Menu: React.FC<MenuProps> = ({\n isOpen,\n onClose,\n anchorRef,\n items,\n sections,\n side = 'bottom',\n align = 'start',\n sideOffset = 4,\n alignOffset = 0,\n sideOffsetToken,\n alignOffsetToken,\n width,\n minWidth,\n maxWidth,\n matchAnchorWidth = false,\n matchAnchorWidthOffset = 0,\n usePortal = true,\n}) => {\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(isOpen);\n const [isPositionReady, setIsPositionReady] = useState(false);\n const [position, setPosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const [menuSize, setMenuSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const [anchorSize, setAnchorSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const positionCalculatedRef = useRef(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const lastSectionsRef = useRef<MenuSection[]>([]);\n\n const menuSections: MenuSection[] = sections || (items ? [{ items }] : []);\n\n const hasItems = menuSections.some((s) => s.items.length > 0);\n if (!isClosing && menuSections.length > 0 && hasItems) {\n lastSectionsRef.current = menuSections;\n }\n const sectionsToRender = isClosing ? lastSectionsRef.current : menuSections;\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n setIsClosing(false);\n setIsPositionReady(false);\n positionCalculatedRef.current = false;\n } else if (shouldRender) {\n setIsClosing(true);\n const timer = setTimeout(() => {\n setShouldRender(false);\n setIsClosing(false);\n positionCalculatedRef.current = false;\n }, CLOSE_ANIMATION_MS);\n return () => clearTimeout(timer);\n }\n }, [isOpen, shouldRender]);\n\n useLayoutEffect(() => {\n if (!isOpen || !shouldRender || !menuRef.current) return;\n const updateSize = () => {\n if (!menuRef.current) return;\n const rect = menuRef.current.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) setMenuSize({ width: rect.width, height: rect.height });\n };\n updateSize();\n requestAnimationFrame(() => requestAnimationFrame(updateSize));\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(updateSize);\n observer.observe(menuRef.current);\n return () => observer.disconnect();\n }\n }, [isOpen, shouldRender, menuSections.length]);\n\n useLayoutEffect(() => {\n if (!isOpen || !shouldRender || !anchorRef.current || !menuRef.current) return;\n const calculatePosition = () => {\n const anchor = anchorRef.current;\n const menu = menuRef.current;\n if (!anchor || !menu) return;\n const anchorRect = anchor.getBoundingClientRect();\n const menuRect = menu.getBoundingClientRect();\n const menuWidth = menuRect.width || menuSize.width || 200;\n const menuHeight = menuRect.height || menuSize.height || 160;\n setAnchorSize({ width: anchorRect.width, height: anchorRect.height });\n const gap = sideOffsetToken != null ? getCssSpacePx(sideOffsetToken, 12) : sideOffset;\n const alignOff = alignOffsetToken != null ? getCssSpacePx(alignOffsetToken, 4) : alignOffset;\n let x = 0, y = 0;\n switch (side) {\n case 'top':\n y = anchorRect.top - menuHeight - gap;\n x = align === 'start' ? anchorRect.left + alignOff : align === 'end' ? anchorRect.right - menuWidth + alignOff : anchorRect.left + anchorRect.width / 2 - menuWidth / 2 + alignOff;\n break;\n case 'bottom':\n y = anchorRect.bottom + gap;\n x = align === 'start' ? anchorRect.left + alignOff : align === 'end' ? anchorRect.right - menuWidth + alignOff : anchorRect.left + anchorRect.width / 2 - menuWidth / 2 + alignOff;\n break;\n case 'left':\n x = anchorRect.left - menuWidth - gap;\n y = align === 'start' ? anchorRect.top + alignOff : align === 'end' ? anchorRect.bottom - menuHeight + alignOff : anchorRect.top + anchorRect.height / 2 - menuHeight / 2 + alignOff;\n break;\n case 'right':\n x = anchorRect.right + gap;\n y = align === 'start' ? anchorRect.top + alignOff : align === 'end' ? anchorRect.bottom - menuHeight + alignOff : anchorRect.top + anchorRect.height / 2 - menuHeight / 2 + alignOff;\n break;\n }\n const vp = 4;\n setPosition({\n x: Math.min(Math.max(x, vp), window.innerWidth - menuWidth - vp),\n y: Math.min(Math.max(y, vp), window.innerHeight - menuHeight - vp),\n });\n positionCalculatedRef.current = true;\n setIsPositionReady(true);\n };\n if (!positionCalculatedRef.current) {\n calculatePosition();\n requestAnimationFrame(() => { if (!positionCalculatedRef.current) calculatePosition(); });\n }\n const handleScrollResize = () => calculatePosition();\n window.addEventListener('scroll', handleScrollResize, true);\n window.addEventListener('resize', handleScrollResize);\n return () => {\n window.removeEventListener('scroll', handleScrollResize, true);\n window.removeEventListener('resize', handleScrollResize);\n };\n }, [isOpen, shouldRender, anchorRef, side, align, sideOffset, alignOffset, sideOffsetToken, alignOffsetToken, menuSize.width, menuSize.height, menuSections.length, matchAnchorWidthOffset]);\n\n useEffect(() => {\n if (!isOpen || !shouldRender) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (menuRef.current?.contains(target)) return;\n if (anchorRef.current?.contains(target)) return;\n onClose();\n };\n document.addEventListener('mousedown', handleClickOutside, true);\n return () => document.removeEventListener('mousedown', handleClickOutside, true);\n }, [isOpen, shouldRender, onClose, anchorRef]);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleEscape = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, onClose]);\n\n if (!shouldRender || sectionsToRender.length === 0) return null;\n\n const renderMenuItem = (item: MenuItemData, index: number) => {\n if (item.isDestructive) {\n return (\n <DestructiveMenuItem\n key={index}\n label={item.label}\n subtext={item.subtext}\n holdDuration={item.holdDuration ?? 4000}\n onClick={() => { item.onClick(); if (!item.keepOpenOnClick) onClose(); }}\n />\n );\n }\n return (\n <MenuItemComponent\n key={index}\n icon={item.icon}\n label={item.label}\n subtext={item.subtext}\n onClick={() => { if (!item.isInactive) { item.onClick(); if (!item.keepOpenOnClick) onClose(); } }}\n isSelected={item.isSelected}\n isInactive={item.isInactive}\n intent={item.intent}\n showToggle={item.showToggle}\n toggleValue={item.toggleValue}\n selectionStyle={item.selectionStyle}\n />\n );\n };\n\n const menuStyle: React.CSSProperties = {\n position: 'absolute',\n left: 0,\n top: 0,\n transform: `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`,\n willChange: 'transform',\n zIndex: 9998,\n visibility: isPositionReady ? 'visible' : 'hidden',\n ...(matchAnchorWidth && anchorSize.width > 0 ? { width: `${anchorSize.width + matchAnchorWidthOffset}px` } : width ? { width } : {}),\n ...(minWidth ? { minWidth } : {}),\n ...(maxWidth ? { maxWidth } : {}),\n };\n\n const menuContent = (\n <div ref={menuRef} className={`${styles.menuContainer} ${isClosing ? styles.closing : ''}`} style={menuStyle} role=\"menu\" aria-label=\"Menu\">\n {sectionsToRender.map((section, sectionIndex) => (\n <Surface\n key={sectionIndex}\n as=\"div\"\n className={styles.menuSection}\n edge={sectionIndex < sectionsToRender.length - 1 ? 'bottom' : undefined}\n elevation=\"none\"\n >\n {section.header && (\n <div className={styles.sectionHeader}>\n <Text variant=\"text-body-small-emphasis\" as=\"span\" className={styles.sectionLabel}>{section.header}</Text>\n </div>\n )}\n {section.items.map((item, itemIndex) => renderMenuItem(item, itemIndex))}\n </Surface>\n ))}\n </div>\n );\n\n if (usePortal) return createPortal(menuContent, document.body);\n return menuContent;\n};\n\nMenu.displayName = 'Menu';\n",".tooltip {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-elevated-floating);\n padding: var(--dimension-space-050);\n line-height: var(--typography-lineheight-sm);\n pointer-events: none;\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n animation: tooltipFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.tooltipInner {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n.keyHint {\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: var(--dimension-stroke-width-015) solid var(--color-foreground-tertiary);\n border-bottom-width: var(--dimension-stroke-width-025);\n border-radius: var(--dimension-radius-025);\n}\n\n.tooltip.closing {\n animation: tooltipFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes tooltipFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes tooltipFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getCssTimeMs } from '@/utils/css-tokens';\nimport { Text } from '@/components/Text';\nimport styles from './Tooltip.module.css';\n\nconst HOVER_DELAY_FALLBACK_MS = 1000;\nconst INSTANT_REOPEN_MS = 300;\nconst FADE_OUT_DURATION_MS = 200;\n\nlet lastTooltipDismissedAt = 0;\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\nexport type TooltipAlign = 'start' | 'center' | 'end';\n\nexport interface TooltipProps {\n label: string;\n children: React.ReactElement;\n delay?: number;\n side?: TooltipSide;\n align?: TooltipAlign;\n sideOffset?: number;\n alignOffset?: number;\n shortcutKey?: string;\n shortcutKeyPosition?: 'start' | 'end';\n usePortal?: boolean;\n}\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n label,\n children,\n delay,\n side = 'top',\n align = 'center',\n sideOffset = 4,\n alignOffset = 0,\n shortcutKey,\n shortcutKeyPosition = 'end',\n usePortal = true,\n}) => {\n const hoverDelayMs = getCssTimeMs('--effect-animation-delay-medium-3', HOVER_DELAY_FALLBACK_MS);\n const resolvedDelay = delay ?? hoverDelayMs;\n const anchorRef = useRef<HTMLElement | null>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n\n const setAnchorRef = useCallback(\n (el: HTMLElement | null) => {\n (anchorRef as React.MutableRefObject<HTMLElement | null>).current = el;\n const childEl = React.Children.only(children) as React.ReactElement<{ ref?: React.Ref<unknown> }>;\n const childRef = 'ref' in childEl ? childEl.ref : undefined;\n if (typeof childRef === 'function') childRef(el);\n else if (childRef && typeof childRef === 'object') (childRef as React.MutableRefObject<unknown>).current = el;\n },\n [children]\n );\n\n const [open, setOpen] = useState(false);\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(false);\n const [position, setPosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const [tooltipSize, setTooltipSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const viewportPadding = 4;\n\n const clearDelayTimer = () => {\n if (delayTimerRef.current) { clearTimeout(delayTimerRef.current); delayTimerRef.current = null; }\n };\n\n const handleOpen = () => {\n clearDelayTimer();\n const showImmediately = Date.now() - lastTooltipDismissedAt < INSTANT_REOPEN_MS;\n if (showImmediately) {\n setOpen(true); setShouldRender(true); setIsClosing(false); return;\n }\n delayTimerRef.current = setTimeout(() => {\n delayTimerRef.current = null;\n setOpen(true); setShouldRender(true); setIsClosing(false);\n }, resolvedDelay);\n };\n\n const handleClose = () => {\n clearDelayTimer();\n if (closeTimerRef.current) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; }\n if (!open && !shouldRender) return;\n lastTooltipDismissedAt = Date.now();\n setIsClosing(true);\n closeTimerRef.current = setTimeout(() => {\n closeTimerRef.current = null;\n setShouldRender(false); setOpen(false); setIsClosing(false);\n }, FADE_OUT_DURATION_MS);\n };\n\n useEffect(() => () => { clearDelayTimer(); if (closeTimerRef.current) clearTimeout(closeTimerRef.current); }, []);\n\n useLayoutEffect(() => {\n if (!shouldRender || !tooltipRef.current) return;\n const updateSize = () => {\n if (!tooltipRef.current) return;\n const rect = tooltipRef.current.getBoundingClientRect();\n const w = rect.width || tooltipRef.current.offsetWidth;\n const h = rect.height || tooltipRef.current.offsetHeight;\n if (w > 0 && h > 0) setTooltipSize({ width: w, height: h });\n };\n updateSize();\n requestAnimationFrame(updateSize);\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(updateSize);\n observer.observe(tooltipRef.current);\n return () => observer.disconnect();\n }\n }, [shouldRender, label, shortcutKey, shortcutKeyPosition]);\n\n useLayoutEffect(() => {\n if (!shouldRender || !anchorRef.current || !tooltipRef.current) return;\n const calculatePosition = () => {\n if (!anchorRef.current || !tooltipRef.current) return;\n const a = anchorRef.current.getBoundingClientRect();\n const tw = tooltipRef.current.getBoundingClientRect().width || tooltipSize.width || 80;\n const th = tooltipRef.current.getBoundingClientRect().height || tooltipSize.height || 24;\n let x = 0, y = 0;\n switch (side) {\n case 'top':\n y = a.top - th - sideOffset;\n x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'bottom':\n y = a.bottom + sideOffset;\n x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'left':\n x = a.left - tw - sideOffset;\n y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n case 'right':\n x = a.right + sideOffset;\n y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n }\n setPosition({\n x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),\n y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),\n });\n };\n calculatePosition();\n requestAnimationFrame(() => requestAnimationFrame(calculatePosition));\n }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height, label]);\n\n useEffect(() => {\n if (!shouldRender) return;\n const onScrollResize = () => {\n if (!anchorRef.current || !tooltipRef.current) return;\n const a = anchorRef.current.getBoundingClientRect();\n const tw = tooltipSize.width || 80;\n const th = tooltipSize.height || 24;\n let x = 0, y = 0;\n switch (side) {\n case 'top': y = a.top - th - sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;\n case 'bottom': y = a.bottom + sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;\n case 'left': x = a.left - tw - sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;\n case 'right': x = a.right + sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;\n }\n setPosition({\n x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),\n y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),\n });\n };\n window.addEventListener('scroll', onScrollResize, true);\n window.addEventListener('resize', onScrollResize);\n return () => { window.removeEventListener('scroll', onScrollResize, true); window.removeEventListener('resize', onScrollResize); };\n }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height]);\n\n const keyHint = shortcutKey ? (\n <div className={styles.keyHint} aria-hidden>\n <Text variant=\"text-caption-emphasis\" as=\"span\" color=\"primary\">{shortcutKey}</Text>\n </div>\n ) : null;\n\n const tooltipContent = shouldRender ? (\n <div\n ref={tooltipRef}\n className={`${styles.tooltip} ${isClosing ? styles.closing : ''}`}\n style={{\n position: 'fixed',\n left: 0,\n top: 0,\n transform: `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`,\n willChange: 'transform',\n zIndex: 10000,\n }}\n role=\"tooltip\"\n >\n <div className={styles.tooltipInner}>\n {shortcutKey && shortcutKeyPosition === 'start' && keyHint}\n <Text variant=\"text-body-small\" as=\"span\" color=\"primary\">{label}</Text>\n {shortcutKey && shortcutKeyPosition === 'end' && keyHint}\n </div>\n </div>\n ) : null;\n\n const trigger = React.Children.only(children);\n const triggerWithRefAndHandlers = React.isValidElement(trigger)\n ? React.cloneElement(trigger as React.ReactElement<any>, {\n ref: setAnchorRef,\n onMouseEnter: (e: React.MouseEvent) => {\n handleOpen();\n (trigger as any).props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent) => {\n handleClose();\n (trigger as any).props.onMouseLeave?.(e);\n },\n })\n : children;\n\n return (\n <>\n {triggerWithRefAndHandlers}\n {usePortal ? createPortal(tooltipContent, document.body) : tooltipContent}\n </>\n );\n};\n\nTooltip.displayName = 'Tooltip';\n",".selectWrapper {\n width: 100%;\n position: relative;\n}\n\n.selectButton {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: var(--dimension-size-400);\n padding: 0 var(--dimension-space-075);\n gap: var(--dimension-space-050);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border: none;\n outline: none;\n}\n\n.selectButton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.chevron {\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n flex-shrink: 0;\n}\n","import React, { forwardRef, useState, useRef } from 'react';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport { Menu } from '@/components/Menu';\nimport type { MenuItemData } from '@/components/Menu';\nimport type { IconComponent } from '@/types';\nimport styles from './Select.module.css';\n\nexport interface SelectOption {\n label: string;\n value: string | number;\n}\n\nexport interface SelectProps {\n value: string | number;\n onChange: (value: string | number) => void;\n options: SelectOption[];\n placeholder?: string;\n className?: string;\n inactive?: boolean;\n id?: string;\n chevronIcon?: IconComponent;\n}\n\nexport const Select = forwardRef<HTMLDivElement, SelectProps>(\n ({ value, onChange, options, placeholder = 'Select option', className, inactive = false, id, chevronIcon: ChevronIcon }, ref) => {\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const selectedOption = options.find(opt => opt.value === value);\n const selectedLabel = selectedOption?.label || placeholder;\n\n const menuItems: MenuItemData[] = options.map(option => ({\n label: option.label,\n onClick: () => {\n onChange(option.value);\n setIsMenuOpen(false);\n },\n isSelected: option.value === value,\n }));\n\n const handleToggle = () => {\n if (!inactive) setIsMenuOpen(prev => !prev);\n };\n\n return (\n <div ref={ref} className={`${styles.selectWrapper} ${className || ''}`}>\n <Surface\n id={id}\n ref={buttonRef as React.RefObject<HTMLElement>}\n as=\"button\"\n type=\"button\"\n elevation=\"elevated\"\n radius=\"sm\"\n interactive\n selected={isMenuOpen}\n className={styles.selectButton}\n onClick={handleToggle}\n inactive={inactive}\n >\n <Text\n variant=\"text-body-medium\"\n as=\"span\"\n \n color={selectedOption ? 'primary' : 'secondary'}\n >\n {selectedLabel}\n </Text>\n {ChevronIcon && (\n <span className={styles.chevron}>\n <ChevronIcon size={16} />\n </span>\n )}\n </Surface>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={buttonRef as React.RefObject<HTMLElement | null>}\n items={menuItems}\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n alignOffset={-4}\n matchAnchorWidth\n matchAnchorWidthOffset={8}\n />\n </div>\n );\n }\n);\n\nSelect.displayName = 'Select';\n",".bannerWrapper {}\n\n.banner {\n position: relative;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.bannerHeaderSurface {\n width: 100%;\n height: var(--dimension-space-100);\n flex-shrink: 0;\n overflow: hidden;\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.bannerHeader {\n width: 100%;\n height: 100%;\n background: repeating-linear-gradient(\n -45deg,\n var(--banner-content),\n var(--banner-content) var(--dimension-size-100),\n transparent var(--dimension-size-100),\n transparent var(--dimension-size-200)\n );\n}\n\n.bannerBody {\n padding: var(--dimension-space-075);\n min-height: var(--dimension-size-400);\n}\n\n.message {\n color: var(--banner-content);\n line-height: var(--typography-lineheight-md);\n display: block;\n}\n\n.floatingPosition {\n position: fixed;\n top: var(--dimension-space-200);\n left: 50%;\n transform: translateX(-50%);\n pointer-events: none;\n}\n\n.floatingToast {\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n animation: toastFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.floatingToast.closing {\n animation: toastFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes toastFadeIn {\n from { opacity: 0; transform: translateY(-8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes toastFadeOut {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-4px); }\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport { getCssTimeMs } from '@/utils/css-tokens';\nimport styles from './Banner.module.css';\n\nconst TOAST_DURATION_FALLBACK_MS = 4000;\nconst FADE_OUT_DURATION_MS = 200;\n\nexport type BannerIntent =\n | 'brand' | 'positive' | 'negative' | 'warning' | 'caution'\n | 'ai' | 'neutral' | 'walkthrough' | 'guide';\n\nexport type BannerContrast = 'faint' | 'medium' | 'bold' | 'strong';\n\nexport interface BannerProps {\n intent: BannerIntent;\n contrast: BannerContrast;\n message: string;\n header?: boolean;\n className?: string;\n floating?: boolean;\n onDismiss?: () => void;\n}\n\nconst getContentColorVar = (intent: BannerIntent, contrast: BannerContrast): string => {\n if (contrast === 'bold') return 'var(--color-foreground-on-bold-background-primary)';\n const contentContrast = contrast === 'faint' ? 'bold' : contrast === 'medium' ? 'strong' : 'medium';\n return `var(--color-foreground-${contentContrast}-${intent})`;\n};\n\nexport const Banner: React.FC<BannerProps> = ({\n intent,\n contrast,\n message,\n header = false,\n className = '',\n floating = false,\n onDismiss,\n}) => {\n const toastDurationMs = getCssTimeMs('--effect-animation-delay-long-2', TOAST_DURATION_FALLBACK_MS);\n const messageColor = getContentColorVar(intent, contrast);\n const [isClosing, setIsClosing] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const scheduleDismiss = useCallback(() => {\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n dismissTimerRef.current = setTimeout(() => {\n dismissTimerRef.current = null;\n setIsClosing(true);\n closeTimerRef.current = setTimeout(() => {\n closeTimerRef.current = null;\n onDismiss?.();\n }, FADE_OUT_DURATION_MS);\n }, toastDurationMs);\n }, [onDismiss, toastDurationMs]);\n\n useEffect(() => {\n if (floating && message) scheduleDismiss();\n return () => {\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n };\n }, [floating, message, scheduleDismiss]);\n\n const content = (\n <div\n className={`${styles.bannerWrapper} ${className}`.trim()}\n style={{ '--banner-content': messageColor } as React.CSSProperties}\n >\n <Surface\n elevation={floating ? 'floating' : 'elevated'}\n intent={intent}\n contrast={contrast}\n radius=\"sm\"\n className={styles.banner}\n >\n {header && (\n <div className={styles.bannerHeaderSurface}>\n <div className={styles.bannerHeader} aria-hidden />\n </div>\n )}\n <div className={styles.bannerBody}>\n <Text variant=\"text-body-medium\" as=\"span\" className={styles.message}>\n {message}\n </Text>\n </div>\n </Surface>\n </div>\n );\n\n if (floating) {\n return createPortal(\n <div className={styles.floatingPosition} style={{ zIndex: 9998 }}>\n <div className={`${styles.floatingToast} ${isClosing ? styles.closing : ''}`}>\n {content}\n </div>\n </div>,\n document.body\n );\n }\n\n return content;\n};\n\nBanner.displayName = 'Banner';\n",".tableWrapper {\n display: flex;\n flex-direction: column;\n width: 100%;\n overflow: hidden;\n border-radius: var(--dimension-radius-075);\n}\n\n.tableScroll {\n overflow-x: auto;\n width: 100%;\n}\n\n.table {\n display: grid;\n width: 100%;\n min-width: max-content;\n}\n\n.headerRow {\n display: contents;\n}\n\n.headerCell {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075) var(--dimension-space-100);\n background-color: var(--color-background-secondary);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n -webkit-user-select: none;\n user-select: none;\n position: sticky;\n top: 0;\n z-index: 2;\n}\n\n.headerCell.sortable {\n cursor: pointer;\n}\n\n.headerCell.sortable:hover {\n background-color: var(--color-background-translucent);\n}\n\n.sortIndicator {\n font-size: 12px;\n color: var(--color-foreground-secondary);\n}\n\n.row {\n display: contents;\n}\n\n.row:hover .cell {\n background-color: var(--color-interaction-hover);\n}\n\n.rowSelected .cell {\n background-color: var(--color-background-faint-brand);\n}\n\n.rowClickable {\n cursor: pointer;\n}\n\n.cell {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-075) var(--dimension-space-100);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n min-height: var(--dimension-size-500);\n background-color: var(--color-background-primary);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.alignRight { justify-content: flex-end; text-align: right; }\n.alignCenter { justify-content: center; text-align: center; }\n\n.emptyRow {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-400);\n background-color: var(--color-background-primary);\n}\n\n.skeleton {\n height: 14px;\n width: 60%;\n background-color: var(--color-background-translucent);\n border-radius: var(--dimension-radius-050);\n animation: shimmer 1.5s infinite;\n}\n\n@keyframes shimmer {\n 0% { opacity: 0.5; }\n 50% { opacity: 1; }\n 100% { opacity: 0.5; }\n}\n\n.pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-100);\n padding: var(--dimension-space-100);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n background-color: var(--color-background-primary);\n}\n\n.pageButton {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-050) var(--dimension-space-100);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n transition: background-color var(--effect-motion-short-2);\n}\n\n.pageButton:hover:not(:disabled) {\n background-color: var(--color-interaction-hover);\n}\n\n.pageButton:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n","import React, { useMemo, useState, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Table.module.css';\n\nexport type SortDirection = 'asc' | 'desc';\nexport type CellType = 'string' | 'numbers' | 'tag' | 'checkbox' | 'button' | 'spacer' | 'image' | 'icon' | 'empty';\nexport type FilterValue = string | number | Array<string | number> | undefined;\nexport type FilterState = Record<string, FilterValue>;\n\nexport interface SortState {\n columnId: string;\n direction: SortDirection;\n}\n\nexport interface PaginationState {\n pageIndex: number;\n pageSize: number;\n}\n\nexport interface TableColumn<T = unknown> {\n id: string;\n header: string | React.ReactNode;\n accessorKey?: string;\n accessor?: (row: T) => unknown;\n sortable?: boolean;\n align?: 'left' | 'right' | 'center';\n width?: string | number;\n minWidth?: string | number;\n maxWidth?: string | number;\n renderCell?: (row: T, rowIndex: number) => React.ReactNode;\n cellType?: CellType;\n hide?: boolean;\n pinned?: 'left' | 'right';\n}\n\nexport interface TableProps<T = unknown> {\n columns: TableColumn<T>[];\n data: T[];\n sortState?: SortState;\n onSort?: (columnId: string) => void;\n className?: string;\n onRowClick?: (row: T, rowIndex: number) => void;\n selectedRows?: Set<number>;\n loading?: boolean;\n pagination?: PaginationState;\n onPaginationChange?: (pageIndex: number, pageSize: number) => void;\n emptyMessage?: string;\n}\n\nfunction getColumnValue<T>(column: TableColumn<T>, row: T): unknown {\n if (column.accessorKey) return (row as Record<string, unknown>)[column.accessorKey];\n if (column.accessor) return column.accessor(row);\n return undefined;\n}\n\nfunction compareValues(a: unknown, b: unknown, direction: SortDirection): number {\n const mult = direction === 'asc' ? 1 : -1;\n if (a == null && b == null) return 0;\n if (a == null) return mult;\n if (b == null) return -mult;\n if (typeof a === 'number' && typeof b === 'number') return (a - b) * mult;\n return String(a).localeCompare(String(b)) * mult;\n}\n\nexport function Table<T>({\n columns,\n data,\n sortState,\n onSort,\n className,\n onRowClick,\n selectedRows,\n loading = false,\n pagination,\n onPaginationChange,\n emptyMessage = 'No results found.',\n}: TableProps<T>) {\n const visibleColumns = useMemo(() => columns.filter(c => !c.hide), [columns]);\n\n const gridTemplateColumns = useMemo(() =>\n visibleColumns.map(col => {\n if (col.width) return typeof col.width === 'number' ? `${col.width}px` : col.width;\n return 'minmax(120px, 1fr)';\n }).join(' '),\n [visibleColumns]\n );\n\n const sortedData = useMemo(() => {\n if (!sortState) return data;\n const col = columns.find(c => c.id === sortState.columnId);\n if (!col) return data;\n return [...data].sort((a, b) =>\n compareValues(getColumnValue(col, a), getColumnValue(col, b), sortState.direction)\n );\n }, [data, columns, sortState]);\n\n const pagedData = useMemo(() => {\n if (!pagination) return sortedData;\n const start = pagination.pageIndex * pagination.pageSize;\n return sortedData.slice(start, start + pagination.pageSize);\n }, [sortedData, pagination]);\n\n const totalPages = pagination ? Math.ceil(sortedData.length / pagination.pageSize) : 1;\n const isEmpty = !loading && pagedData.length === 0;\n\n const handleSort = (columnId: string) => {\n if (onSort) onSort(columnId);\n };\n\n return (\n <div className={cn(styles.tableWrapper, className)}>\n <div className={styles.tableScroll}>\n <div className={styles.table} style={{ gridTemplateColumns }} role=\"table\">\n {/* Header */}\n <div className={styles.headerRow} role=\"row\">\n {visibleColumns.map(col => (\n <div\n key={col.id}\n className={cn(\n styles.headerCell,\n col.sortable && styles.sortable,\n col.align === 'right' && styles.alignRight,\n col.align === 'center' && styles.alignCenter\n )}\n role=\"columnheader\"\n onClick={() => col.sortable && handleSort(col.id)}\n style={col.minWidth ? { minWidth: typeof col.minWidth === 'number' ? `${col.minWidth}px` : col.minWidth } : undefined}\n >\n {typeof col.header === 'string' ? (\n <Text variant=\"text-body-small-emphasis\" as=\"span\" color=\"secondary\">\n {col.header}\n </Text>\n ) : col.header}\n {sortState?.columnId === col.id && (\n <span className={styles.sortIndicator} aria-hidden>\n {sortState.direction === 'asc' ? '\\u2191' : '\\u2193'}\n </span>\n )}\n </div>\n ))}\n </div>\n\n {/* Loading skeleton */}\n {loading && Array.from({ length: 5 }).map((_, i) => (\n <div key={`skeleton-${i}`} className={styles.row} role=\"row\">\n {visibleColumns.map(col => (\n <div key={col.id} className={styles.cell} role=\"cell\">\n <div className={styles.skeleton} />\n </div>\n ))}\n </div>\n ))}\n\n {/* Empty state */}\n {isEmpty && (\n <div className={styles.emptyRow} style={{ gridColumn: `1 / -1` }}>\n <Text variant=\"text-body-medium\" as=\"p\" color=\"secondary\">{emptyMessage}</Text>\n </div>\n )}\n\n {/* Data rows */}\n {!loading && pagedData.map((row, rowIndex) => {\n const isSelected = selectedRows?.has(rowIndex);\n return (\n <div\n key={rowIndex}\n className={cn(\n styles.row,\n isSelected && styles.rowSelected,\n onRowClick && styles.rowClickable\n )}\n role=\"row\"\n onClick={() => onRowClick?.(row, rowIndex)}\n >\n {visibleColumns.map(col => (\n <div\n key={col.id}\n className={cn(\n styles.cell,\n col.align === 'right' && styles.alignRight,\n col.align === 'center' && styles.alignCenter\n )}\n role=\"cell\"\n >\n {col.renderCell\n ? col.renderCell(row, rowIndex)\n : <Text variant=\"text-body-medium\" as=\"span\" lineTruncation={1}>{String(getColumnValue(col, row) ?? '')}</Text>\n }\n </div>\n ))}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Pagination */}\n {pagination && onPaginationChange && totalPages > 1 && (\n <div className={styles.pagination}>\n <button\n className={styles.pageButton}\n disabled={pagination.pageIndex === 0}\n onClick={() => onPaginationChange(pagination.pageIndex - 1, pagination.pageSize)}\n type=\"button\"\n >\n <Text variant=\"text-body-small\" as=\"span\">Previous</Text>\n </button>\n <Text variant=\"text-body-small\" as=\"span\" color=\"secondary\">\n {`Page ${pagination.pageIndex + 1} of ${totalPages}`}\n </Text>\n <button\n className={styles.pageButton}\n disabled={pagination.pageIndex >= totalPages - 1}\n onClick={() => onPaginationChange(pagination.pageIndex + 1, pagination.pageSize)}\n type=\"button\"\n >\n <Text variant=\"text-body-small\" as=\"span\">Next</Text>\n </button>\n </div>\n )}\n </div>\n );\n}\n\nTable.displayName = 'Table';\n","/* ==========================================================================\n Tab — hover/pressed via direct background-color, no pseudo-element overlay.\n ========================================================================== */\n\n.tab {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n color: var(--color-foreground-secondary);\n position: relative;\n will-change: color;\n transition: color var(--effect-motion-short-2),\n background-color var(--effect-motion-short-2);\n flex-shrink: 0;\n height: var(--dimension-size-400);\n box-sizing: border-box;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n.tab:hover { background-color: var(--_hover-bg); }\n.tab:active { background-color: var(--_pressed-bg); }\n\n.tabSelected { color: var(--color-foreground-primary); }\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.onBold.tabSelected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.onStrong.tabSelected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n color: var(--color-always-dark-foreground-secondary);\n}\n\n.onAlwaysDark.tabSelected { color: var(--color-always-dark-foreground-primary); }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Tab.module.css';\n\nexport type TabBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface TabProps {\n id?: string;\n label: string;\n isSelected?: boolean;\n /** Parent surface context. Adjusts hover tokens and fg for tabs on colored backgrounds. */\n background?: TabBackground;\n onClick?: () => void;\n className?: string;\n}\n\nexport const Tab = forwardRef<HTMLButtonElement, TabProps>(\n ({ id, label, isSelected = false, background, onClick, className }, ref) => {\n const bgClass = background && background !== 'faint'\n ? styles[background === 'always-dark' ? 'onAlwaysDark' : `on${background.charAt(0).toUpperCase() + background.slice(1)}`]\n : undefined;\n return (\n <button\n ref={ref}\n id={id}\n className={cn(styles.tab, isSelected && styles.tabSelected, bgClass, className)}\n onClick={onClick}\n type=\"button\"\n aria-selected={isSelected}\n role=\"tab\"\n >\n <Text variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'} as=\"span\">\n {label}\n </Text>\n </button>\n );\n }\n);\n\nTab.displayName = 'Tab';\n",".emptyState {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n min-height: 400px;\n width: 100%;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './EmptyState.module.css';\n\nexport type EmptyStateType = 'no-content' | 'no-results' | 'no-results-filter' | 'no-access';\n\nconst defaultMessages: Record<EmptyStateType, string> = {\n 'no-content': 'No page contents to display.',\n 'no-results': 'No results found.',\n 'no-results-filter': 'No results found. Please update search criteria.',\n 'no-access': \"You don't have access to this page.\",\n};\n\nexport interface EmptyStateProps {\n type?: EmptyStateType;\n message?: string;\n className?: string;\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(\n ({ type = 'no-content', message, className }, ref) => (\n <div ref={ref} className={cn(styles.emptyState, className)}>\n <Text variant=\"text-body-medium\" as=\"p\" color=\"secondary\">\n {message || defaultMessages[type]}\n </Text>\n </div>\n )\n);\n\nEmptyState.displayName = 'EmptyState';\n",".fade {\n position: absolute;\n pointer-events: none;\n z-index: 10;\n transform: translateZ(0);\n backface-visibility: hidden;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .fade { transition: none; }\n}\n\n.fadeTop {\n top: 0; left: 0; right: 0;\n background: linear-gradient(to bottom, var(--background) 0%, var(--background) 50%, transparent 100%);\n}\n\n.fadeBottom {\n bottom: 0; left: 0; right: 0;\n background: linear-gradient(to top, var(--background) 0%, transparent 100%);\n}\n\n.fadeLeft {\n top: 0; bottom: 0; left: 0;\n background: linear-gradient(to right, var(--background) 0%, transparent 100%);\n}\n\n.fadeRight {\n top: 0; bottom: 0; right: 0;\n background: linear-gradient(to left, var(--background) 0%, transparent 100%);\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Fade.module.css';\n\nexport type FadeSide = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface FadeProps {\n side: FadeSide;\n height: string;\n background?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst sideClassMap: Record<FadeSide, string> = {\n top: 'fadeTop',\n bottom: 'fadeBottom',\n left: 'fadeLeft',\n right: 'fadeRight',\n};\n\nexport const Fade = forwardRef<HTMLDivElement, FadeProps>(\n ({ side, height, background = 'var(--color-background-secondary)', className, style = {} }, ref) => (\n <div\n ref={ref}\n className={cn(styles.fade, styles[sideClassMap[side]], className)}\n style={{ ...style, height, '--background': background } as React.CSSProperties}\n aria-hidden=\"true\"\n />\n )\n);\n\nFade.displayName = 'Fade';\n",".container {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n.content {\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow-y: auto;\n overflow-x: auto;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.content::-webkit-scrollbar { display: none; }\n\n.track {\n position: absolute;\n top: 0; right: 0; bottom: 0;\n width: var(--dimension-size-050, 4px);\n pointer-events: none;\n z-index: 10;\n opacity: 0;\n transition: opacity var(--effect-motion-short-2);\n}\n\n.container[data-show-track='true'] .track {\n opacity: 1;\n pointer-events: auto;\n}\n\n.thumb {\n position: absolute;\n right: 0;\n width: var(--dimension-size-050, 4px);\n cursor: grab;\n border-radius: 0;\n background-color: var(--color-foreground-quaternary);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.thumb:active { cursor: grabbing; }\n\n.trackHorizontal {\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: var(--dimension-size-050, 4px);\n pointer-events: none;\n z-index: 10;\n opacity: 0;\n transition: opacity var(--effect-motion-short-2);\n}\n\n.container[data-show-track='true'] .trackHorizontal {\n opacity: 1;\n pointer-events: auto;\n}\n\n.thumbHorizontal {\n position: absolute;\n bottom: 0;\n height: var(--dimension-size-050, 4px);\n cursor: grab;\n border-radius: 0;\n background-color: var(--color-foreground-quaternary);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.thumbHorizontal:active { cursor: grabbing; }\n\n.thick .track { width: var(--dimension-size-100, 8px); }\n.thick .thumb { width: var(--dimension-size-100, 8px); }\n.thick .trackHorizontal { height: var(--dimension-size-100, 8px); }\n.thick .thumbHorizontal { height: var(--dimension-size-100, 8px); }\n","import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Scrollbar.module.css';\n\nexport type ScrollbarVariant = 'default' | 'thick';\n\nexport interface ScrollbarProps {\n children: React.ReactNode;\n className?: string;\n variant?: ScrollbarVariant;\n showTrackOnHover?: boolean;\n onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;\n fadeOverlay?: React.ReactNode;\n contentRef?: React.RefObject<HTMLDivElement>;\n}\n\nexport const Scrollbar: React.FC<ScrollbarProps> = ({\n children,\n className,\n variant = 'default',\n showTrackOnHover = true,\n onScroll,\n fadeOverlay,\n contentRef: externalContentRef,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const internalContentRef = useRef<HTMLDivElement>(null);\n const contentRef = externalContentRef || internalContentRef;\n const thumbRef = useRef<HTMLDivElement>(null);\n const thumbHRef = useRef<HTMLDivElement>(null);\n const [thumbHeight, setThumbHeight] = useState(0);\n const [thumbTop, setThumbTop] = useState(0);\n const [thumbWidth, setThumbWidth] = useState(0);\n const [thumbLeft, setThumbLeft] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isDraggingH, setIsDraggingH] = useState(false);\n const [isPointerInside, setIsPointerInside] = useState(false);\n const dragStartY = useRef(0);\n const dragStartScrollTop = useRef(0);\n const dragStartX = useRef(0);\n const dragStartScrollLeft = useRef(0);\n\n const handleMouseEnter = useCallback(() => {\n if (showTrackOnHover) setIsPointerInside(true);\n }, [showTrackOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n setIsPointerInside(false);\n }, []);\n\n const updateThumb = useCallback(() => {\n const container = containerRef.current;\n const content = contentRef.current;\n if (!container || !content) return;\n\n const containerHeight = container.clientHeight;\n const containerWidth = container.clientWidth;\n const contentHeight = content.scrollHeight;\n const contentWidth = content.scrollWidth;\n const scrollTop = content.scrollTop;\n const scrollLeft = content.scrollLeft;\n\n if (contentHeight <= containerHeight) {\n setThumbHeight(0);\n } else {\n const ratio = containerHeight / contentHeight;\n const h = Math.max(20, containerHeight * ratio);\n setThumbHeight(h);\n setThumbTop((scrollTop / (contentHeight - containerHeight)) * (containerHeight - h));\n }\n\n if (contentWidth <= containerWidth) {\n setThumbWidth(0);\n } else {\n const ratio = containerWidth / contentWidth;\n const w = Math.max(20, containerWidth * ratio);\n setThumbWidth(w);\n setThumbLeft((scrollLeft / (contentWidth - containerWidth)) * (containerWidth - w));\n }\n }, [contentRef]);\n\n useEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n const handleScroll = (e: Event) => {\n updateThumb();\n if (onScroll) onScroll(e as unknown as React.UIEvent<HTMLDivElement>);\n };\n content.addEventListener('scroll', handleScroll);\n return () => content.removeEventListener('scroll', handleScroll);\n }, [updateThumb, onScroll, contentRef]);\n\n useEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n const handleResize = () => updateThumb();\n window.addEventListener('resize', handleResize);\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(handleResize);\n observer.observe(content);\n return () => { window.removeEventListener('resize', handleResize); observer.disconnect(); };\n }\n return () => window.removeEventListener('resize', handleResize);\n }, [updateThumb, contentRef]);\n\n useEffect(() => { updateThumb(); }, [updateThumb, children]);\n\n const handleThumbMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const content = contentRef.current;\n if (!content) return;\n setIsDragging(true);\n dragStartY.current = e.clientY;\n dragStartScrollTop.current = content.scrollTop;\n const handleMouseMove = (e: MouseEvent) => {\n const container = containerRef.current;\n if (!container || !content) return;\n const deltaY = e.clientY - dragStartY.current;\n const scrollableHeight = content.scrollHeight - container.clientHeight;\n const scrollRatio = scrollableHeight / (container.clientHeight - thumbHeight);\n content.scrollTop = Math.max(0, Math.min(scrollableHeight, dragStartScrollTop.current + deltaY * scrollRatio));\n };\n const handleMouseUp = () => {\n setIsDragging(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [thumbHeight, contentRef]);\n\n const handleThumbHMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const content = contentRef.current;\n if (!content) return;\n setIsDraggingH(true);\n dragStartX.current = e.clientX;\n dragStartScrollLeft.current = content.scrollLeft;\n const handleMouseMove = (e: MouseEvent) => {\n const container = containerRef.current;\n if (!container || !content) return;\n const deltaX = e.clientX - dragStartX.current;\n const scrollableWidth = content.scrollWidth - container.clientWidth;\n const scrollRatio = scrollableWidth / (container.clientWidth - thumbWidth);\n content.scrollLeft = Math.max(0, Math.min(scrollableWidth, dragStartScrollLeft.current + deltaX * scrollRatio));\n };\n const handleMouseUp = () => {\n setIsDraggingH(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [thumbWidth, contentRef]);\n\n const showThumb = thumbHeight > 0;\n const showThumbH = thumbWidth > 0;\n const showTrack = showTrackOnHover && (isPointerInside || isDragging || isDraggingH);\n\n return (\n <div\n ref={containerRef}\n className={cn(styles.container, variant === 'thick' && styles.thick, className)}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n data-dragging={isDragging || isDraggingH}\n data-show-track={showTrack ? 'true' : 'false'}\n >\n <div ref={contentRef} className={styles.content}>{children}</div>\n {fadeOverlay}\n {showThumb && (\n <div className={styles.track}>\n <div ref={thumbRef} className={styles.thumb} style={{ height: `${thumbHeight}px`, top: `${thumbTop}px` }} onMouseDown={handleThumbMouseDown} />\n </div>\n )}\n {showThumbH && (\n <div className={styles.trackHorizontal}>\n <div ref={thumbHRef} className={styles.thumbHorizontal} style={{ width: `${thumbWidth}px`, left: `${thumbLeft}px` }} onMouseDown={handleThumbHMouseDown} />\n </div>\n )}\n </div>\n );\n};\n\nScrollbar.displayName = 'Scrollbar';\n",".errorBoundary {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n padding: var(--dimension-space-400);\n gap: var(--dimension-space-200);\n}\n\n.errorDetails {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--dimension-space-200);\n max-width: 600px;\n text-align: center;\n}\n","import React, { Component, ReactNode } from 'react';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Text } from '@/components/Text';\nimport styles from './ErrorBoundary.module.css';\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n override componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error('ErrorBoundary caught an error:', error, errorInfo);\n }\n\n handleReset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n override render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n return (\n <div className={styles.errorBoundary}>\n <EmptyState type=\"no-content\" />\n <div className={styles.errorDetails}>\n <Text variant=\"text-body-small\" as=\"p\" color=\"secondary\">\n Something went wrong. Please refresh the page.\n </Text>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","/* Sidebar */\n.sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--color-background-secondary);\n border-right: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n position: relative;\n flex-shrink: 0;\n overflow: hidden;\n transition: width var(--effect-motion-short-2);\n}\n\n.sidebar.resizing { transition: none; }\n\n.sidebar.collapsed { width: 0 !important; border-right: none; }\n\n.sidebar.mobile {\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n z-index: 9997;\n}\n\n.sidebar.mini .itemLabel { display: none; }\n.sidebar.mini .itemBadge { display: none; }\n.sidebar.mini .sectionHeader { display: none; }\n\n.backdrop {\n position: fixed;\n inset: 0;\n background-color: var(--color-background-shade);\n z-index: 9996;\n}\n\n.content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--dimension-space-050);\n scrollbar-width: none;\n}\n\n.content::-webkit-scrollbar { display: none; }\n\n.footer {\n flex-shrink: 0;\n padding: var(--dimension-space-050);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n/* Resize Handle */\n.resizeHandle {\n position: absolute;\n top: 0;\n right: -3px;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n z-index: 10;\n}\n\n.resizeHandle:hover {\n background-color: var(--color-border-brand);\n opacity: 0.5;\n}\n\n/* Sections */\n.section {\n display: flex;\n flex-direction: column;\n}\n\n.section + .section {\n margin-top: var(--dimension-space-050);\n padding-top: var(--dimension-space-050);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.sectionHeader {\n padding: var(--dimension-space-050) var(--dimension-space-075);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.sectionHeaderClickable { cursor: pointer; }\n\n.sectionItems {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n}\n\n/* Items */\n.itemWrapper {\n display: flex;\n flex-direction: column;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-075);\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n width: 100%;\n text-align: left;\n position: relative;\n min-height: var(--dimension-size-400);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.item::before {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: var(--dimension-radius-075);\n transition: var(--effect-transition-interaction-background-short-2);\n pointer-events: none;\n}\n\n.item:hover::before { background-color: var(--color-interaction-hover); }\n.item:active::before { background-color: var(--color-interaction-pressed); }\n\n.itemSelected { background-color: var(--color-background-faint-brand); }\n.itemSelected::before { display: none; }\n\n.itemDisabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n\n.itemIcon {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.itemSelected .itemIcon { color: var(--color-foreground-primary); }\n\n.itemLabel {\n flex: 1;\n min-width: 0;\n}\n\n.itemBadge {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n}\n\n/* Sub-items */\n.subItems {\n display: flex;\n flex-direction: column;\n padding-left: var(--dimension-space-300);\n gap: var(--dimension-space-025);\n}\n","import React, { forwardRef, useRef, useCallback, useEffect, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Sidebar.module.css';\n\nexport type SidebarWidth = 'mini' | 'default' | number;\n\nexport interface SidebarProps {\n children: React.ReactNode;\n isCollapsed?: boolean;\n onToggle?: () => void;\n width?: SidebarWidth;\n onWidthChange?: (width: SidebarWidth) => void;\n resizable?: boolean;\n footer?: React.ReactNode;\n className?: string;\n isMobile?: boolean;\n}\n\nconst MINI_WIDTH = 56;\nconst DEFAULT_WIDTH = 240;\nconst MIN_DRAG_WIDTH = 180;\nconst SNAP_THRESHOLD = 140;\n\nexport const Sidebar = forwardRef<HTMLElement, SidebarProps>(\n ({\n children,\n isCollapsed = false,\n onToggle,\n width = 'default',\n onWidthChange,\n resizable = true,\n footer,\n className,\n isMobile = false,\n }, ref) => {\n const internalRef = useRef<HTMLElement>(null);\n const sidebarRef = (ref as React.RefObject<HTMLElement>) || internalRef;\n const [isResizing, setIsResizing] = useState(false);\n\n const isMini = width === 'mini';\n const resolvedWidth = width === 'mini' ? MINI_WIDTH : width === 'default' ? DEFAULT_WIDTH : width;\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (!resizable || !onWidthChange) return;\n e.preventDefault();\n setIsResizing(true);\n const startX = e.clientX;\n\n const handleMouseMove = (e: MouseEvent) => {\n const newWidth = e.clientX;\n if (newWidth < SNAP_THRESHOLD) {\n onWidthChange('mini');\n } else if (newWidth < MIN_DRAG_WIDTH) {\n onWidthChange('default');\n } else {\n onWidthChange(newWidth);\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [resizable, onWidthChange]);\n\n // Close sidebar on Escape (mobile)\n useEffect(() => {\n if (!isMobile || isCollapsed) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onToggle?.();\n };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isMobile, isCollapsed, onToggle]);\n\n if (isCollapsed && !isMobile) return null;\n\n return (\n <>\n {/* Mobile backdrop */}\n {isMobile && !isCollapsed && (\n <div className={styles.backdrop} onClick={onToggle} aria-hidden />\n )}\n <aside\n ref={sidebarRef}\n className={cn(\n styles.sidebar,\n isMini && styles.mini,\n isMobile && styles.mobile,\n isCollapsed && styles.collapsed,\n isResizing && styles.resizing,\n className\n )}\n style={{ width: isCollapsed ? 0 : resolvedWidth }}\n role=\"navigation\"\n aria-label=\"Sidebar\"\n >\n <div className={styles.content}>\n {children}\n </div>\n {footer && (\n <div className={styles.footer}>\n {footer}\n </div>\n )}\n {resizable && !isMobile && (\n <div\n className={styles.resizeHandle}\n onMouseDown={handleMouseDown}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize sidebar\"\n />\n )}\n </aside>\n </>\n );\n }\n);\n\nSidebar.displayName = 'Sidebar';\n","import React, { forwardRef, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Sidebar.module.css';\n\nexport interface SidebarSectionProps {\n label?: string;\n children: React.ReactNode;\n collapsible?: boolean;\n defaultCollapsed?: boolean;\n className?: string;\n}\n\nexport const SidebarSection = forwardRef<HTMLDivElement, SidebarSectionProps>(\n ({ label, children, collapsible = false, defaultCollapsed = false, className }, ref) => {\n const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);\n\n return (\n <div ref={ref} className={cn(styles.section, className)}>\n {label && (\n <div\n className={cn(styles.sectionHeader, collapsible && styles.sectionHeaderClickable)}\n onClick={collapsible ? () => setIsCollapsed(prev => !prev) : undefined}\n role={collapsible ? 'button' : undefined}\n aria-expanded={collapsible ? !isCollapsed : undefined}\n >\n <Text variant=\"text-caption-emphasis\" as=\"span\" color=\"tertiary\">\n {label}\n </Text>\n </div>\n )}\n {!isCollapsed && (\n <div className={styles.sectionItems}>\n {children}\n </div>\n )}\n </div>\n );\n }\n);\n\nSidebarSection.displayName = 'SidebarSection';\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport type { IconComponent } from '@/types';\nimport styles from './Sidebar.module.css';\n\nexport interface SidebarItemProps {\n label: string;\n icon?: IconComponent;\n isSelected?: boolean;\n isDisabled?: boolean;\n onClick?: () => void;\n badge?: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n}\n\nexport const SidebarItem = forwardRef<HTMLButtonElement, SidebarItemProps>(\n ({ label, icon: Icon, isSelected = false, isDisabled = false, onClick, badge, children, className }, ref) => (\n <div className={cn(styles.itemWrapper, className)}>\n <button\n ref={ref}\n className={cn(\n styles.item,\n isSelected && styles.itemSelected,\n isDisabled && styles.itemDisabled\n )}\n onClick={onClick}\n disabled={isDisabled}\n type=\"button\"\n aria-current={isSelected ? 'page' : undefined}\n >\n {Icon && (\n <span className={styles.itemIcon}>\n <Icon size={20} />\n </span>\n )}\n <Text\n variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'}\n as=\"span\"\n className={styles.itemLabel}\n lineTruncation={1}\n >\n {label}\n </Text>\n {badge && <span className={styles.itemBadge}>{badge}</span>}\n </button>\n {children && isSelected && (\n <div className={styles.subItems}>\n {children}\n </div>\n )}\n </div>\n )\n);\n\nSidebarItem.displayName = 'SidebarItem';\n",".header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: var(--dimension-size-600, 48px);\n padding: 0 var(--dimension-space-100);\n flex-shrink: 0;\n gap: var(--dimension-space-100);\n}\n\n.left {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-100);\n flex-shrink: 0;\n min-width: 0;\n}\n\n.center {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-050);\n flex: 1;\n min-width: 0;\n}\n\n.right {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport styles from './Header.module.css';\n\nexport type HeaderBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\nexport interface HeaderProps {\n title?: string;\n left?: React.ReactNode;\n center?: React.ReactNode;\n right?: React.ReactNode;\n background?: HeaderBackground;\n className?: string;\n}\n\nexport const Header = forwardRef<HTMLElement, HeaderProps>(\n ({ title, left, center, right, background = 'secondary', className }, ref) => (\n <Surface\n ref={ref}\n as=\"header\"\n background={background}\n elevation=\"none\"\n edge=\"bottom\"\n className={cn(styles.header, className)}\n >\n <div className={styles.left}>\n {left}\n {title && !center && (\n <Text variant=\"text-title-small\" as=\"h1\" lineTruncation={1}>\n {title}\n </Text>\n )}\n </div>\n {center && <div className={styles.center}>{center}</div>}\n <div className={styles.right}>{right}</div>\n </Surface>\n )\n);\n\nHeader.displayName = 'Header';\n",".group {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n}\n\n.horizontal {\n flex-direction: row;\n gap: var(--dimension-space-100);\n}\n\n/* ─── Radio item ────────────────────────────────────────────────────────────── */\n\n.radio {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n height: var(--dimension-size-400);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border-radius: var(--dimension-radius-075);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.radio:hover { background-color: var(--color-interaction-hover); }\n.radio:active { background-color: var(--color-interaction-pressed); }\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Circle indicator ──────────────────────────────────────────────────────── */\n\n.circle {\n width: 20px;\n height: 20px;\n border: 1.5px solid var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-half);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all var(--effect-motion-short-2);\n box-sizing: border-box;\n}\n\n.circleChecked {\n border-color: var(--color-foreground-primary);\n}\n\n.dot {\n width: 10px;\n height: 10px;\n border-radius: var(--dimension-radius-half);\n background-color: var(--color-foreground-primary);\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Radio.module.css';\n\nexport interface RadioOption {\n label: string;\n value: string;\n inactive?: boolean;\n}\n\nexport interface RadioGroupProps {\n /** Currently selected value. */\n value: string;\n /** Called when selection changes. */\n onChange: (value: string) => void;\n /** Radio options to render. */\n options: RadioOption[];\n /** Group label for accessibility. */\n 'aria-label'?: string;\n /** Layout direction. */\n direction?: 'vertical' | 'horizontal';\n /** Disables the entire group. */\n inactive?: boolean;\n className?: string;\n}\n\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value,\n onChange,\n options,\n 'aria-label': ariaLabel,\n direction = 'vertical',\n inactive = false,\n className,\n },\n ref\n ) => (\n <div\n ref={ref}\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className={cn(\n styles.group,\n direction === 'horizontal' && styles.horizontal,\n className\n )}\n >\n {options.map(opt => (\n <RadioItem\n key={opt.value}\n label={opt.label}\n checked={value === opt.value}\n inactive={inactive || opt.inactive}\n onChange={() => onChange(opt.value)}\n />\n ))}\n </div>\n )\n);\n\nRadioGroup.displayName = 'RadioGroup';\n\n/* ─── Individual Radio Item ─────────────────────────────────────────────────── */\n\nexport interface RadioItemProps {\n label: string;\n checked?: boolean;\n onChange?: () => void;\n inactive?: boolean;\n className?: string;\n}\n\nexport const RadioItem = forwardRef<HTMLDivElement, RadioItemProps>(\n ({ label, checked = false, onChange, inactive = false, className }, ref) => {\n const handleClick = () => {\n if (!inactive && !checked) onChange?.();\n };\n\n return (\n <div\n ref={ref}\n role=\"radio\"\n aria-checked={checked}\n tabIndex={inactive ? -1 : 0}\n className={cn(styles.radio, inactive && styles.inactive, className)}\n onClick={handleClick}\n onKeyDown={e => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n handleClick();\n }\n }}\n >\n <span className={cn(styles.circle, checked && styles.circleChecked)}>\n {checked && <span className={styles.dot} />}\n </span>\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </div>\n );\n }\n);\n\nRadioItem.displayName = 'RadioItem';\n",".tabGroup {\n display: flex;\n flex-direction: column;\n position: relative;\n}\n\n.tabsRow {\n display: flex;\n gap: var(--dimension-space-025);\n}\n\n.track {\n height: 2px;\n background-color: var(--color-border-secondary);\n position: relative;\n}\n\n.indicator {\n position: absolute;\n bottom: 0;\n height: 2px;\n background-color: var(--color-foreground-primary);\n border-radius: 1px;\n transition: transform var(--effect-motion-short-3), width var(--effect-motion-short-3);\n will-change: transform, width;\n}\n","import React, { forwardRef, useRef, useEffect, useState, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Tab } from '@/components/Tab';\nimport styles from './TabGroup.module.css';\n\nexport interface TabGroupTab {\n label: string;\n id?: string;\n}\n\nexport interface TabGroupProps {\n /** Tab definitions. */\n tabs: TabGroupTab[];\n /** Index of the active tab. */\n activeIndex?: number;\n /** Called when a tab is clicked. */\n onTabChange?: (index: number) => void;\n className?: string;\n}\n\nexport const TabGroup = forwardRef<HTMLDivElement, TabGroupProps>(\n ({ tabs, activeIndex = 0, onTabChange, className }, ref) => {\n const tabsRef = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState({ left: 0, width: 0 });\n\n const updateIndicator = useCallback(() => {\n const el = tabsRef.current[activeIndex];\n if (el) {\n const parent = el.parentElement;\n if (parent) {\n setIndicator({\n left: el.offsetLeft,\n width: el.offsetWidth,\n });\n }\n }\n }, [activeIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n // Recalculate on resize\n useEffect(() => {\n const observer = new ResizeObserver(updateIndicator);\n const container = tabsRef.current[0]?.parentElement;\n if (container) observer.observe(container);\n return () => observer.disconnect();\n }, [updateIndicator]);\n\n return (\n <div\n ref={ref}\n role=\"tablist\"\n className={cn(styles.tabGroup, className)}\n >\n <div className={styles.tabsRow}>\n {tabs.map((tab, i) => (\n <Tab\n key={tab.id ?? i}\n ref={el => { tabsRef.current[i] = el; }}\n id={tab.id}\n label={tab.label}\n isSelected={i === activeIndex}\n onClick={() => onTabChange?.(i)}\n />\n ))}\n </div>\n <div className={styles.track}>\n <div\n className={styles.indicator}\n style={{\n transform: `translateX(${indicator.left}px)`,\n width: indicator.width,\n }}\n />\n </div>\n </div>\n );\n }\n);\n\nTabGroup.displayName = 'TabGroup';\n",".accordion {\n display: flex;\n flex-direction: column;\n}\n\n/* ─── Item ──────────────────────────────────────────────────────────────────── */\n\n.item {\n border-bottom: 1px solid var(--color-border-secondary);\n}\n\n.item:first-child {\n border-top: 1px solid var(--color-border-secondary);\n}\n\n.inactive {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Trigger ───────────────────────────────────────────────────────────────── */\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: var(--dimension-space-100) var(--dimension-space-050);\n background: none;\n border: none;\n cursor: pointer;\n color: var(--color-foreground-primary);\n border-radius: var(--dimension-radius-050);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.trigger:hover { background-color: var(--color-interaction-hover); }\n.trigger:active { background-color: var(--color-interaction-pressed); }\n\n/* ─── Chevron ───────────────────────────────────────────────────────────────── */\n\n.chevron {\n font-size: 18px;\n line-height: 1;\n transform: rotate(0deg);\n transition: transform var(--effect-motion-short-3);\n color: var(--color-foreground-secondary);\n}\n\n.chevronOpen {\n transform: rotate(90deg);\n}\n\n/* ─── Body (animated height) ────────────────────────────────────────────────── */\n\n.body {\n overflow: hidden;\n transition: height var(--effect-motion-short-3);\n}\n\n.bodyInner {\n padding: var(--dimension-space-050) var(--dimension-space-050) var(--dimension-space-100);\n color: var(--color-foreground-secondary);\n}\n","import React, { forwardRef, useState, useRef, useEffect, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Accordion.module.css';\n\nexport interface AccordionItemData {\n id: string;\n label: string;\n content: React.ReactNode;\n inactive?: boolean;\n}\n\nexport interface AccordionProps {\n /** Items to render. */\n items: AccordionItemData[];\n /** Allow multiple items open at once. When false, behaves as an accordion. */\n multiple?: boolean;\n /** Controlled: which item IDs are expanded. */\n expandedIds?: string[];\n /** Called when expansion state changes. */\n onExpandedChange?: (ids: string[]) => void;\n className?: string;\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n ({ items, multiple = false, expandedIds: controlledIds, onExpandedChange, className }, ref) => {\n const [internalIds, setInternalIds] = useState<string[]>([]);\n const expandedIds = controlledIds ?? internalIds;\n\n const toggle = (id: string) => {\n let next: string[];\n if (expandedIds.includes(id)) {\n next = expandedIds.filter(x => x !== id);\n } else {\n next = multiple ? [...expandedIds, id] : [id];\n }\n setInternalIds(next);\n onExpandedChange?.(next);\n };\n\n return (\n <div ref={ref} className={cn(styles.accordion, className)}>\n {items.map(item => (\n <AccordionItem\n key={item.id}\n label={item.label}\n isExpanded={expandedIds.includes(item.id)}\n inactive={item.inactive}\n onToggle={() => toggle(item.id)}\n >\n {item.content}\n </AccordionItem>\n ))}\n </div>\n );\n }\n);\n\nAccordion.displayName = 'Accordion';\n\n/* ─── AccordionItem ─────────────────────────────────────────────────────────── */\n\nexport interface AccordionItemProps {\n label: string;\n children: React.ReactNode;\n isExpanded?: boolean;\n onToggle?: () => void;\n inactive?: boolean;\n className?: string;\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(\n ({ label, children, isExpanded = false, onToggle, inactive = false, className }, ref) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number>(0);\n\n const measure = useCallback(() => {\n if (contentRef.current) {\n setHeight(contentRef.current.scrollHeight);\n }\n }, []);\n\n useEffect(() => {\n measure();\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, [measure]);\n\n return (\n <div ref={ref} className={cn(styles.item, inactive && styles.inactive, className)}>\n <button\n type=\"button\"\n className={styles.trigger}\n onClick={() => !inactive && onToggle?.()}\n aria-expanded={isExpanded}\n tabIndex={inactive ? -1 : 0}\n >\n <Text variant=\"text-body-medium-emphasis\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n <span className={cn(styles.chevron, isExpanded && styles.chevronOpen)}>\n &#x203A;\n </span>\n </button>\n <div\n className={styles.body}\n style={{ height: isExpanded ? height : 0 }}\n aria-hidden={!isExpanded}\n >\n <div ref={contentRef} className={styles.bodyInner}>\n {children}\n </div>\n </div>\n </div>\n );\n }\n);\n\nAccordionItem.displayName = 'AccordionItem';\n",".breadcrumb {\n display: flex;\n align-items: center;\n}\n\n.list {\n display: flex;\n align-items: center;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: var(--dimension-space-050);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n.link {\n color: var(--color-foreground-secondary);\n text-decoration: none;\n background: none;\n border: none;\n padding: var(--dimension-space-025) var(--dimension-space-050);\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n transition: background-color var(--effect-motion-short-2), color var(--effect-motion-short-2);\n}\n\n.link:hover {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n.link:active {\n background-color: var(--color-interaction-pressed);\n}\n\n.separator {\n color: var(--color-foreground-tertiary);\n font-size: 12px;\n -webkit-user-select: none;\n user-select: none;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Breadcrumb.module.css';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n onClick?: () => void;\n}\n\nexport interface BreadcrumbProps {\n /** Ordered list of breadcrumb items. Last item is treated as current page. */\n items: BreadcrumbItem[];\n /** Custom separator. Defaults to '/'. */\n separator?: React.ReactNode;\n className?: string;\n}\n\nexport const Breadcrumb = forwardRef<HTMLElement, BreadcrumbProps>(\n ({ items, separator = '/', className }, ref) => (\n <nav ref={ref} aria-label=\"Breadcrumb\" className={cn(styles.breadcrumb, className)}>\n <ol className={styles.list}>\n {items.map((item, i) => {\n const isLast = i === items.length - 1;\n return (\n <li key={i} className={styles.item}>\n {isLast ? (\n <Text variant=\"text-body-medium-emphasis\" as=\"span\" color=\"primary\" aria-current=\"page\">\n {item.label}\n </Text>\n ) : (\n <>\n {item.href ? (\n <a\n href={item.href}\n className={styles.link}\n onClick={e => { if (item.onClick) { e.preventDefault(); item.onClick(); } }}\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {item.label}\n </Text>\n </a>\n ) : (\n <button\n type=\"button\"\n className={styles.link}\n onClick={item.onClick}\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {item.label}\n </Text>\n </button>\n )}\n <span className={styles.separator} aria-hidden=\"true\">\n {separator}\n </span>\n </>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n )\n);\n\nBreadcrumb.displayName = 'Breadcrumb';\n",".pagination {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-025);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.inactive {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Button ────────────────────────────────────────────────────────────────── */\n\n.button {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: var(--dimension-size-300);\n height: var(--dimension-size-300);\n padding: 0 var(--dimension-space-050);\n background: none;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n color: var(--color-foreground-secondary);\n transition: background-color var(--effect-motion-short-2), color var(--effect-motion-short-2);\n}\n\n.button:hover:not(:disabled) {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n.button:active:not(:disabled) {\n background-color: var(--color-interaction-pressed);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.35;\n}\n\n.active {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n/* ─── Nav arrows ────────────────────────────────────────────────────────────── */\n\n.nav {\n font-size: 18px;\n}\n\n/* ─── Ellipsis ──────────────────────────────────────────────────────────────── */\n\n.ellipsis {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: var(--dimension-size-300);\n height: var(--dimension-size-300);\n}\n","import React, { forwardRef, useMemo } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Pagination.module.css';\n\nexport interface PaginationProps {\n /** Current page (1-based). */\n page: number;\n /** Total number of pages. */\n totalPages: number;\n /** Called when page changes. */\n onPageChange: (page: number) => void;\n /** Max page buttons visible (excluding prev/next). */\n siblingCount?: number;\n /** Disables all interaction. */\n inactive?: boolean;\n className?: string;\n}\n\nfunction buildRange(start: number, end: number): (number | 'ellipsis')[] {\n const items: (number | 'ellipsis')[] = [];\n for (let i = start; i <= end; i++) items.push(i);\n return items;\n}\n\nfunction buildPages(page: number, totalPages: number, siblings: number): (number | 'ellipsis')[] {\n const totalSlots = siblings * 2 + 5; // siblings + boundaries + ellipses + current\n\n if (totalPages <= totalSlots) return buildRange(1, totalPages);\n\n const leftSibling = Math.max(page - siblings, 2);\n const rightSibling = Math.min(page + siblings, totalPages - 1);\n\n const showLeftEllipsis = leftSibling > 2;\n const showRightEllipsis = rightSibling < totalPages - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const left = buildRange(1, siblings * 2 + 3);\n return [...left, 'ellipsis', totalPages];\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n const right = buildRange(totalPages - (siblings * 2 + 2), totalPages);\n return [1, 'ellipsis', ...right];\n }\n\n return [1, 'ellipsis', ...buildRange(leftSibling, rightSibling), 'ellipsis', totalPages];\n}\n\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(\n ({ page, totalPages, onPageChange, siblingCount = 1, inactive = false, className }, ref) => {\n const pages = useMemo(() => buildPages(page, totalPages, siblingCount), [page, totalPages, siblingCount]);\n\n if (totalPages <= 1) return null;\n\n return (\n <nav ref={ref} aria-label=\"Pagination\" className={cn(styles.pagination, inactive && styles.inactive, className)}>\n <button\n type=\"button\"\n className={cn(styles.button, styles.nav)}\n disabled={page <= 1 || inactive}\n onClick={() => onPageChange(page - 1)}\n aria-label=\"Previous page\"\n >\n <Text variant=\"text-body-small\" as=\"span\" color=\"inherit\">&#x2039;</Text>\n </button>\n\n {pages.map((item, i) =>\n item === 'ellipsis' ? (\n <span key={`e${i}`} className={styles.ellipsis}>\n <Text variant=\"text-body-small\" as=\"span\" color=\"tertiary\">&hellip;</Text>\n </span>\n ) : (\n <button\n key={item}\n type=\"button\"\n className={cn(styles.button, item === page && styles.active)}\n onClick={() => onPageChange(item)}\n aria-current={item === page ? 'page' : undefined}\n disabled={inactive}\n >\n <Text variant={item === page ? 'text-body-small-emphasis' : 'text-body-small'} as=\"span\" color=\"inherit\">\n {item}\n </Text>\n </button>\n )\n )}\n\n <button\n type=\"button\"\n className={cn(styles.button, styles.nav)}\n disabled={page >= totalPages || inactive}\n onClick={() => onPageChange(page + 1)}\n aria-label=\"Next page\"\n >\n <Text variant=\"text-body-small\" as=\"span\" color=\"inherit\">&#x203A;</Text>\n </button>\n </nav>\n );\n }\n);\n\nPagination.displayName = 'Pagination';\n",".divider {\n border: none;\n margin: 0;\n flex-shrink: 0;\n background-color: var(--color-border-secondary);\n}\n\n/* Horizontal (default) */\n.divider:not(.vertical) {\n width: 100%;\n height: 1px;\n}\n\n/* Vertical */\n.vertical {\n width: 1px;\n height: 100%;\n align-self: stretch;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Divider.module.css';\n\nexport type DividerOrientation = 'horizontal' | 'vertical';\n\nexport interface DividerProps {\n /** Direction of the divider line. */\n orientation?: DividerOrientation;\n className?: string;\n}\n\nexport const Divider = forwardRef<HTMLHRElement, DividerProps>(\n ({ orientation = 'horizontal', className }, ref) => (\n <hr\n ref={ref}\n role=\"separator\"\n aria-orientation={orientation}\n className={cn(\n styles.divider,\n orientation === 'vertical' && styles.vertical,\n className\n )}\n />\n )\n);\n\nDivider.displayName = 'Divider';\n",".skeleton {\n background-color: var(--color-background-secondary);\n position: relative;\n overflow: hidden;\n}\n\n/* ─── Variants ──────────────────────────────────────────────────────────────── */\n\n.text {\n height: 14px;\n border-radius: var(--dimension-radius-050);\n width: 100%;\n}\n\n.circular {\n width: 40px;\n height: 40px;\n border-radius: var(--dimension-radius-half);\n}\n\n.rectangular {\n width: 100%;\n height: 80px;\n border-radius: var(--dimension-radius-075);\n}\n\n/* ─── Text group ────────────────────────────────────────────────────────────── */\n\n.textGroup {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-075);\n}\n\n/* ─── Shimmer animation ─────────────────────────────────────────────────────── */\n\n.animate::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n var(--color-interaction-hover) 50%,\n transparent 100%\n );\n animation: shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Skeleton.module.css';\n\nexport type SkeletonVariant = 'text' | 'circular' | 'rectangular';\n\nexport interface SkeletonProps {\n /** Shape of the skeleton. */\n variant?: SkeletonVariant;\n /** Width (CSS value). */\n width?: string | number;\n /** Height (CSS value). */\n height?: string | number;\n /** Number of text lines to render. Only applies to 'text' variant. */\n lines?: number;\n /** Whether to animate the shimmer. */\n animate?: boolean;\n className?: string;\n}\n\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n (\n {\n variant = 'text',\n width,\n height,\n lines = 1,\n animate = true,\n className,\n },\n ref\n ) => {\n if (variant === 'text' && lines > 1) {\n return (\n <div ref={ref} className={cn(styles.textGroup, className)} style={{ width }}>\n {Array.from({ length: lines }, (_, i) => (\n <div\n key={i}\n className={cn(styles.skeleton, styles.text, animate && styles.animate)}\n style={{\n width: i === lines - 1 ? '60%' : '100%',\n height,\n }}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n styles.skeleton,\n styles[variant],\n animate && styles.animate,\n className\n )}\n style={{ width, height }}\n aria-hidden=\"true\"\n />\n );\n }\n);\n\nSkeleton.displayName = 'Skeleton';\n","/* ─── Container ─────────────────────────────────────────────────────────────── */\n\n.container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-075);\n pointer-events: none;\n padding: var(--dimension-space-100);\n max-width: 480px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.topCenter {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.topRight {\n top: 0;\n right: 0;\n align-items: flex-end;\n}\n\n.bottomCenter {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.bottomRight {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n}\n\n/* ─── Toast ─────────────────────────────────────────────────────────────────── */\n\n.toast {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-075);\n padding: var(--dimension-space-075) var(--dimension-space-100);\n min-height: var(--dimension-size-400);\n pointer-events: auto;\n animation: slideIn var(--effect-motion-short-3) ease-out;\n}\n\n.toastExit {\n animation: fadeOut 200ms ease-in forwards;\n}\n\n.dismiss {\n background: none;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: var(--dimension-space-025);\n margin-left: auto;\n font-size: 16px;\n line-height: 1;\n opacity: 0.7;\n border-radius: var(--dimension-radius-050);\n transition: opacity var(--effect-motion-short-2);\n flex-shrink: 0;\n}\n\n.dismiss:hover { opacity: 1; }\n\n/* ─── Animations ────────────────────────────────────────────────────────────── */\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes fadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import React, { forwardRef, useEffect, useState, useCallback, useRef, useSyncExternalStore } from 'react';\nimport ReactDOM from 'react-dom';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport type { SurfaceIntent } from '@/components/Surface';\nimport styles from './Toast.module.css';\n\n/* ─── Toast Types ───────────────────────────────────────────────────────────── */\n\nexport type ToastIntent = 'neutral' | 'brand' | 'positive' | 'negative' | 'warning' | 'caution';\nexport type ToastPosition = 'top-center' | 'top-right' | 'bottom-center' | 'bottom-right';\n\nexport interface ToastData {\n id: string;\n message: string;\n intent?: ToastIntent;\n duration?: number;\n onDismiss?: () => void;\n}\n\nexport interface ToastOptions {\n message: string;\n intent?: ToastIntent;\n /** Auto-dismiss duration in ms. 0 = no auto-dismiss. Default 4000. */\n duration?: number;\n onDismiss?: () => void;\n}\n\n/* ─── Toast Store (external, framework-agnostic) ────────────────────────────── */\n\nlet toasts: ToastData[] = [];\nconst listeners = new Set<() => void>();\n\nfunction emit() {\n listeners.forEach(fn => fn());\n}\n\nfunction getSnapshot(): ToastData[] {\n return toasts;\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n}\n\nlet idCounter = 0;\n\nexport const toast = {\n show(options: ToastOptions): string {\n const id = `toast-${++idCounter}`;\n toasts = [...toasts, { id, ...options }];\n emit();\n return id;\n },\n info(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'neutral', ...options });\n },\n success(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'positive', ...options });\n },\n error(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'negative', ...options });\n },\n warning(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'warning', ...options });\n },\n dismiss(id: string) {\n toasts = toasts.filter(t => t.id !== id);\n emit();\n },\n dismissAll() {\n toasts = [];\n emit();\n },\n};\n\n/* ─── useToasts hook ────────────────────────────────────────────────────────── */\n\nexport function useToasts(): ToastData[] {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/* ─── Single Toast ──────────────────────────────────────────────────────────── */\n\nconst INTENT_MAP: Record<ToastIntent, SurfaceIntent> = {\n neutral: 'neutral',\n brand: 'brand',\n positive: 'positive',\n negative: 'negative',\n warning: 'warning',\n caution: 'caution',\n};\n\ninterface ToastItemProps {\n data: ToastData;\n}\n\nconst ToastItem: React.FC<ToastItemProps> = ({ data }) => {\n const [exiting, setExiting] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n\n const dismiss = useCallback(() => {\n setExiting(true);\n setTimeout(() => {\n toast.dismiss(data.id);\n data.onDismiss?.();\n }, 200);\n }, [data]);\n\n useEffect(() => {\n const duration = data.duration ?? 4000;\n if (duration > 0) {\n timerRef.current = setTimeout(dismiss, duration);\n }\n return () => { if (timerRef.current) clearTimeout(timerRef.current); };\n }, [data.duration, dismiss]);\n\n return (\n <Surface\n intent={INTENT_MAP[data.intent ?? 'neutral']}\n contrast=\"bold\"\n elevation=\"floating\"\n radius=\"lg\"\n className={cn(styles.toast, exiting && styles.toastExit)}\n role=\"status\"\n aria-live=\"polite\"\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {data.message}\n </Text>\n <button\n type=\"button\"\n className={styles.dismiss}\n onClick={dismiss}\n aria-label=\"Dismiss\"\n >\n &times;\n </button>\n </Surface>\n );\n};\n\n/* ─── ToastContainer ────────────────────────────────────────────────────────── */\n\nexport interface ToastContainerProps {\n /** Where to render toasts on screen. */\n position?: ToastPosition;\n}\n\nexport const ToastContainer = forwardRef<HTMLDivElement, ToastContainerProps>(\n ({ position = 'top-center' }, ref) => {\n const items = useToasts();\n\n if (typeof document === 'undefined') return null;\n\n return ReactDOM.createPortal(\n <div\n ref={ref}\n className={cn(styles.container, styles[positionClass(position)])}\n aria-label=\"Notifications\"\n >\n {items.map(item => (\n <ToastItem key={item.id} data={item} />\n ))}\n </div>,\n document.body\n );\n }\n);\n\nToastContainer.displayName = 'ToastContainer';\n\nfunction positionClass(position: ToastPosition): string {\n switch (position) {\n case 'top-center': return 'topCenter';\n case 'top-right': return 'topRight';\n case 'bottom-center': return 'bottomCenter';\n case 'bottom-right': return 'bottomRight';\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/components/Text/Text.module.css","../src/components/Text/Text.tsx","../src/components/Surface/Surface.module.css","../src/components/Surface/Surface.tsx","../src/components/Card/Card.module.css","../src/utils/cn.ts","../src/components/Card/Card.tsx","../src/components/LabelWrap/LabelWrap.module.css","../src/components/LabelWrap/LabelWrap.tsx","../src/components/Loader/Loader.module.css","../src/components/Loader/Loader.tsx","../src/components/Button/Button.module.css","../src/components/Button/Button.tsx","../src/components/ToggleButton/ToggleButton.module.css","../src/components/ToggleButton/ToggleButton.tsx","../src/components/ButtonGroup/ButtonGroup.module.css","../src/components/ButtonGroup/ButtonGroup.tsx","../src/components/ToggleButtonGroup/ToggleButtonGroup.module.css","../src/components/ToggleButtonGroup/ToggleButtonGroup.tsx","../src/components/Tag/Tag.module.css","../src/components/Tag/Tag.tsx","../src/components/Badge/Badge.module.css","../src/components/Badge/Badge.tsx","../src/components/Toggle/Toggle.module.css","../src/components/Toggle/Toggle.tsx","../src/components/Checkbox/Checkbox.module.css","../src/components/Checkbox/Checkbox.tsx","../src/components/Input/Input.module.css","../src/components/Input/Input.tsx","../src/components/Slider/Slider.module.css","../src/components/Slider/Slider.tsx","../src/components/Field/Field.module.css","../src/components/Field/Field.tsx","../src/components/Modal/Modal.module.css","../src/components/Modal/Modal.tsx","../src/components/Menu/MenuItem.module.css","../src/components/Menu/MenuItem.tsx","../src/components/Menu/DestructiveMenuItem.module.css","../src/components/Menu/DestructiveMenuItem.tsx","../src/utils/css-tokens.ts","../src/components/Menu/Menu.module.css","../src/components/Menu/Menu.tsx","../src/components/Tooltip/Tooltip.module.css","../src/components/Tooltip/Tooltip.tsx","../src/components/Select/Select.module.css","../src/components/Select/Select.tsx","../src/components/Banner/Banner.module.css","../src/components/Banner/Banner.tsx","../src/components/Table/Table.module.css","../src/components/Table/Table.tsx","../src/components/Tab/Tab.module.css","../src/components/Tab/Tab.tsx","../src/components/EmptyState/EmptyState.module.css","../src/components/EmptyState/EmptyState.tsx","../src/components/Fade/Fade.module.css","../src/components/Fade/Fade.tsx","../src/components/Scrollbar/Scrollbar.module.css","../src/components/Scrollbar/Scrollbar.tsx","../src/components/ErrorBoundary/ErrorBoundary.module.css","../src/components/ErrorBoundary/ErrorBoundary.tsx","../src/components/Sidebar/Sidebar.module.css","../src/components/Sidebar/Sidebar.tsx","../src/components/Sidebar/SidebarSection.tsx","../src/components/Sidebar/SidebarItem.tsx","../src/components/Header/Header.module.css","../src/components/Header/Header.tsx","../src/components/Radio/Radio.module.css","../src/components/Radio/Radio.tsx","../src/components/TabGroup/TabGroup.module.css","../src/components/TabGroup/TabGroup.tsx","../src/components/Accordion/Accordion.module.css","../src/components/Accordion/Accordion.tsx","../src/components/Breadcrumb/Breadcrumb.module.css","../src/components/Breadcrumb/Breadcrumb.tsx","../src/components/Pagination/Pagination.module.css","../src/components/Pagination/Pagination.tsx","../src/components/Divider/Divider.module.css","../src/components/Divider/Divider.tsx","../src/components/Skeleton/Skeleton.module.css","../src/components/Skeleton/Skeleton.tsx","../src/components/Toast/Toast.module.css","../src/components/Toast/Toast.tsx"],"sourcesContent":[".text {\n margin: 0;\n}\n\n/* ============================================\n LINE TRUNCATION\n ============================================ */\n\n.truncate1Line {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.truncate2Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate3Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate4Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 4;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.truncate5Lines {\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 5;\n -webkit-box-orient: vertical;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n\n.noTruncation {\n word-break: break-word;\n white-space: normal;\n}\n\n.wrapNowrap {\n white-space: nowrap;\n word-break: normal;\n overflow: hidden;\n text-overflow: ellipsis;\n min-width: 0;\n}\n\n.wrapBalance {\n text-wrap: balance;\n}\n\n.wrapPretty {\n text-wrap: pretty;\n}\n\n/* ============================================\n TEXT COLOR - Semantic Tokens\n ============================================ */\n\n.colorPrimary {\n color: var(--color-foreground-primary);\n}\n\n.colorSecondary {\n color: var(--color-foreground-secondary);\n}\n\n.colorTertiary {\n color: var(--color-foreground-tertiary);\n}\n\n.colorBrand {\n color: var(--color-foreground-bold-brand);\n}\n\n.colorNegative {\n color: var(--color-foreground-bold-negative);\n}\n\n.colorPositive {\n color: var(--color-foreground-bold-positive);\n}\n\n.colorWarning {\n color: var(--color-foreground-bold-warning);\n}\n\n.colorCaution {\n color: var(--color-foreground-bold-caution);\n}\n\n.colorAi {\n color: var(--color-foreground-bold-ai);\n}\n\n.colorOnStrong {\n color: var(--color-foreground-on-strong-background-primary);\n}\n\n.colorOnBold {\n color: var(--color-foreground-on-bold-background-primary);\n}\n\n.colorInherit {\n color: inherit;\n}\n\n/* ============================================\n TEXT DECORATION\n ============================================ */\n\n.decorationNone {\n text-decoration: none;\n}\n\n.decorationUnderline {\n text-decoration: underline;\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n}\n\n.decorationDottedUnderline {\n text-decoration: underline dotted;\n text-underline-offset: 2px;\n text-decoration-thickness: 1px;\n}\n\n/* ============================================\n FONT STYLE\n ============================================ */\n\n.italic {\n font-style: italic;\n}\n\n/* ============================================\n TEXT ALIGNMENT\n ============================================ */\n\n.alignLeft {\n text-align: left;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.alignRight {\n text-align: right;\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Text.module.css';\n\n/**\n * Text variant options.\n * Each variant maps to a TokoMo typography class with predefined font-size, line-height,\n * font-weight, and letter-spacing.\n */\nexport type TextVariant =\n | 'text-display-medium'\n | 'text-display-small'\n | 'text-title-large'\n | 'text-title-medium'\n | 'text-title-small'\n | 'text-body-large'\n | 'text-body-large-emphasis'\n | 'text-body-medium'\n | 'text-body-medium-emphasis'\n | 'text-body-small'\n | 'text-body-small-emphasis'\n | 'text-caption'\n | 'text-caption-emphasis';\n\n/** @deprecated Use `TextVariant` instead. */\nexport type TextStyle = TextVariant;\n\n/**\n * Semantic color tokens for text.\n * Maps to TokoMo --color-foreground-* CSS custom properties.\n */\nexport type TextColorToken =\n | 'primary'\n | 'secondary'\n | 'tertiary'\n | 'brand'\n | 'negative'\n | 'positive'\n | 'warning'\n | 'caution'\n | 'ai'\n | 'on-strong'\n | 'on-bold'\n | 'inherit';\n\n/** Text color — semantic token or CSS variable escape hatch. */\nexport type TextColor = TextColorToken | `var(--${string})`;\n\nexport type TextDecoration = 'none' | 'underline' | 'dotted-underline';\nexport type TextAlign = 'left' | 'center' | 'right';\nexport type LineTruncation = 1 | 2 | 3 | 4 | 5 | 'none';\nexport type TextWrap = 'wrap' | 'nowrap' | 'balance' | 'pretty';\nexport type TextElement = 'p' | 'span' | 'div' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n\nexport interface TextProps {\n /** Typography variant. Maps to a TokoMo typography class. Defaults to 'text-body-medium'. */\n variant?: TextVariant;\n children: React.ReactNode;\n\n // Appearance\n color?: TextColor;\n decoration?: TextDecoration;\n italic?: boolean;\n align?: TextAlign;\n\n // Truncation / wrap\n /** Max lines before ellipsis. Ignored when wrap is 'nowrap'. Defaults to 'none'. */\n lineTruncation?: LineTruncation;\n /** 'nowrap' = single line, truncates with ellipsis when constrained. */\n wrap?: TextWrap;\n\n // Semantic HTML\n as?: TextElement;\n id?: string;\n htmlFor?: string;\n\n // Escape hatches\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst colorClassMap: Record<TextColorToken, string> = {\n primary: styles.colorPrimary,\n secondary: styles.colorSecondary,\n tertiary: styles.colorTertiary,\n brand: styles.colorBrand,\n negative: styles.colorNegative,\n positive: styles.colorPositive,\n warning: styles.colorWarning,\n caution: styles.colorCaution,\n ai: styles.colorAi,\n 'on-strong': styles.colorOnStrong,\n 'on-bold': styles.colorOnBold,\n inherit: styles.colorInherit,\n};\n\nconst decorationClassMap: Record<TextDecoration, string> = {\n none: styles.decorationNone,\n underline: styles.decorationUnderline,\n 'dotted-underline': styles.decorationDottedUnderline,\n};\n\nconst alignClassMap: Record<TextAlign, string> = {\n left: styles.alignLeft,\n center: styles.alignCenter,\n right: styles.alignRight,\n};\n\nconst truncationClassMap: Record<LineTruncation, string> = {\n 1: styles.truncate1Line,\n 2: styles.truncate2Lines,\n 3: styles.truncate3Lines,\n 4: styles.truncate4Lines,\n 5: styles.truncate5Lines,\n none: styles.noTruncation,\n};\n\nconst isCustomColor = (color: TextColor): color is `var(--${string})` =>\n color.startsWith('var(--');\n\nexport const Text = forwardRef<HTMLElement, TextProps>(\n (\n {\n variant = 'text-body-medium',\n children,\n color,\n decoration,\n italic,\n align,\n lineTruncation = 'none',\n wrap,\n as: Component = 'p',\n id,\n htmlFor,\n className = '',\n style,\n },\n ref\n ) => {\n const wrapClass =\n wrap === 'nowrap' ? styles.wrapNowrap\n : wrap === 'balance' ? styles.wrapBalance\n : wrap === 'pretty' ? styles.wrapPretty\n : '';\n const truncationClass =\n wrap === 'nowrap' ? '' : truncationClassMap[lineTruncation];\n\n const classes = [\n variant,\n styles.text,\n wrapClass,\n truncationClass,\n color && !isCustomColor(color) ? colorClassMap[color] : '',\n decoration ? decorationClassMap[decoration] : '',\n italic ? styles.italic : '',\n align ? alignClassMap[align] : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const computedStyle: React.CSSProperties = {\n ...style,\n ...(color && isCustomColor(color) ? { color } : {}),\n };\n\n const props: React.HTMLAttributes<HTMLElement> & { htmlFor?: string } = {\n className: classes,\n style: Object.keys(computedStyle).length > 0 ? computedStyle : undefined,\n ...(id ? { id } : {}),\n ...(Component === 'label' && htmlFor ? { htmlFor } : {}),\n };\n\n return (\n <Component ref={ref as React.Ref<never>} {...props}>\n {children}\n </Component>\n );\n }\n);\n\nText.displayName = 'Text';\n","/**\n * Surface — lean container primitive.\n * Backgrounds, elevation, edges, radius, and interactive states.\n * Hover/pressed via direct background-color + color-mix(). No pseudo-element overlays.\n */\n\n.surface {\n box-sizing: border-box;\n position: relative;\n /* Reset native button/anchor chrome when rendered as those elements */\n border: none;\n padding: 0;\n margin: 0;\n font: inherit;\n color: inherit;\n background: none;\n text-decoration: none;\n text-align: left;\n cursor: default;\n appearance: none;\n -webkit-appearance: none;\n}\n\n/* ==========================================================================\n Backgrounds\n ========================================================================== */\n\n.bgPrimary {\n background-color: var(--color-background-primary);\n}\n\n.bgSecondary {\n background-color: var(--color-background-secondary);\n}\n\n.bgTransparent {\n background-color: transparent;\n}\n\n.bgTranslucent {\n background-color: var(--color-background-translucent);\n backdrop-filter: blur(var(--effect-blur-md));\n -webkit-backdrop-filter: blur(var(--effect-blur-md));\n}\n\n/* ==========================================================================\n Semantic Intent Backgrounds — intent{Intent}{Contrast}\n ========================================================================== */\n\n/* Brand */\n.intentBrandFaint { background-color: var(--color-background-faint-brand); }\n.intentBrandMedium { background-color: var(--color-background-medium-brand); }\n.intentBrandBold { background-color: var(--color-background-bold-brand); }\n.intentBrandStrong { background-color: var(--color-background-strong-brand); }\n\n/* Positive */\n.intentPositiveFaint { background-color: var(--color-background-faint-positive); }\n.intentPositiveMedium { background-color: var(--color-background-medium-positive); }\n.intentPositiveBold { background-color: var(--color-background-bold-positive); }\n.intentPositiveStrong { background-color: var(--color-background-strong-positive); }\n\n/* Negative */\n.intentNegativeFaint { background-color: var(--color-background-faint-negative); }\n.intentNegativeMedium { background-color: var(--color-background-medium-negative); }\n.intentNegativeBold { background-color: var(--color-background-bold-negative); }\n.intentNegativeStrong { background-color: var(--color-background-strong-negative); }\n\n/* Warning */\n.intentWarningFaint { background-color: var(--color-background-faint-warning); }\n.intentWarningMedium { background-color: var(--color-background-medium-warning); }\n.intentWarningBold { background-color: var(--color-background-bold-warning); }\n.intentWarningStrong { background-color: var(--color-background-strong-warning); }\n\n/* Caution */\n.intentCautionFaint { background-color: var(--color-background-faint-caution); }\n.intentCautionMedium { background-color: var(--color-background-medium-caution); }\n.intentCautionBold { background-color: var(--color-background-bold-caution); }\n.intentCautionStrong { background-color: var(--color-background-strong-caution); }\n\n/* AI */\n.intentAiFaint { background-color: var(--color-background-faint-ai); }\n.intentAiMedium { background-color: var(--color-background-medium-ai); }\n.intentAiBold { background-color: var(--color-background-bold-ai); }\n.intentAiStrong { background-color: var(--color-background-strong-ai); }\n\n/* Neutral */\n.intentNeutralFaint { background-color: var(--color-background-faint-neutral); }\n.intentNeutralMedium { background-color: var(--color-background-medium-neutral); }\n.intentNeutralBold { background-color: var(--color-background-bold-neutral); }\n.intentNeutralStrong { background-color: var(--color-background-strong-neutral); }\n\n/* Walkthrough */\n.intentWalkthroughFaint { background-color: var(--color-background-faint-walkthrough); }\n.intentWalkthroughMedium { background-color: var(--color-background-medium-walkthrough); }\n.intentWalkthroughBold { background-color: var(--color-background-bold-walkthrough); }\n.intentWalkthroughStrong { background-color: var(--color-background-strong-walkthrough); }\n\n/* Guide */\n.intentGuideFaint { background-color: var(--color-background-faint-guide); }\n.intentGuideMedium { background-color: var(--color-background-medium-guide); }\n.intentGuideBold { background-color: var(--color-background-bold-guide); }\n.intentGuideStrong { background-color: var(--color-background-strong-guide); }\n\n/* ==========================================================================\n Elevation — progressive: none → flat → elevated → floating\n ========================================================================== */\n\n.elevationNone {}\n\n.elevationDepressed {\n box-shadow: var(--effect-elevation-depressed-sm);\n}\n\n.elevationDepressedMd {\n box-shadow: var(--effect-elevation-depressed-md);\n}\n\n.elevationFlat {\n box-shadow: var(--effect-elevation-elevated-sm);\n}\n\n.elevationElevated {\n box-shadow: var(--effect-elevation-elevated-md);\n}\n\n.elevationFloating {\n box-shadow: var(--effect-elevation-elevated-floating);\n}\n\n.elevationOverlayTop {\n box-shadow: var(--effect-elevation-elevated-panel-top);\n}\n\n.elevationOverlayRight {\n box-shadow: var(--effect-elevation-elevated-panel-right);\n}\n\n.elevationOverlayBottom {\n box-shadow: var(--effect-elevation-elevated-panel-bottom);\n}\n\n.elevationOverlayLeft {\n box-shadow: var(--effect-elevation-elevated-panel-left);\n}\n\n/* ==========================================================================\n Edge Borders (only when elevation='none')\n ========================================================================== */\n\n.edgeTop { border-top: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeRight { border-right: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeBottom { border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n.edgeLeft { border-left: var(--dimension-stroke-width-015) solid var(--color-border-tertiary); }\n\n/* ==========================================================================\n Corner Radius\n ========================================================================== */\n\n.radiusNone { border-radius: var(--dimension-radius-000); }\n.radiusXs { border-radius: var(--dimension-radius-050); }\n.radiusSm { border-radius: var(--dimension-radius-075); }\n.radiusMd { border-radius: var(--dimension-radius-100); }\n.radiusLg { border-radius: var(--dimension-radius-125); }\n.radiusXl { border-radius: var(--dimension-radius-175); }\n.radius2xl { border-radius: var(--dimension-radius-200); }\n.radiusFull { border-radius: var(--dimension-radius-half); }\n\n/* ==========================================================================\n Interactive States — direct background-color, no pseudo-elements\n ========================================================================== */\n\n.interactive {\n cursor: pointer;\n transition: transform var(--effect-motion-short-2);\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n.interactive:hover {\n background-color: var(--_hover-bg);\n}\n\n.interactive:active {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n.interactive:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n/* ==========================================================================\n Selected State — persistent overlay on any background via ::before\n ========================================================================== */\n\n.selected::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n z-index: 0;\n background-color: var(--color-interaction-hover);\n}\n\n.selected > * {\n position: relative;\n z-index: 1;\n}\n\n/* ==========================================================================\n Inactive State\n ========================================================================== */\n\n.inactive {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Surface.module.css';\n\n/**\n * Semantic intent for colored surfaces.\n * Each intent has four contrast levels (faint, medium, bold, strong).\n */\nexport type SurfaceIntent =\n | 'brand'\n | 'positive'\n | 'negative'\n | 'warning'\n | 'caution'\n | 'ai'\n | 'neutral'\n | 'walkthrough'\n | 'guide';\n\n/** Background type for non-intent surfaces. */\nexport type SurfaceBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\n/** Contrast level for semantic intents. */\nexport type SurfaceContrast = 'faint' | 'medium' | 'bold' | 'strong';\n\n/** Elevation for depth/shadow effects. Progressive: none → flat → elevated → floating. */\nexport type SurfaceElevation =\n | 'none'\n | 'depressed'\n | 'depressed-md'\n | 'flat'\n | 'elevated'\n | 'floating'\n | 'overlayTop'\n | 'overlayRight'\n | 'overlayBottom'\n | 'overlayLeft';\n\n/** Edge divider border direction. */\nexport type SurfaceEdge = 'top' | 'right' | 'bottom' | 'left';\n\n/** Corner radius presets. */\nexport type SurfaceRadiusPreset = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';\n\n/** Corner radius — preset, CSS variable, or custom string (e.g. '12px 12px 0 0'). */\nexport type SurfaceRadius = SurfaceRadiusPreset | (string & {});\n\n/** HTML elements Surface can render as. */\nexport type SurfaceElement =\n | 'div'\n | 'section'\n | 'aside'\n | 'article'\n | 'header'\n | 'footer'\n | 'main'\n | 'nav'\n | 'span'\n | 'button'\n | 'td'\n | 'th';\n\n/** Props shared by both surface modes. */\ninterface SurfaceBaseProps extends React.HTMLAttributes<HTMLElement> {\n children?: React.ReactNode;\n /** Elevation for depth/shadow effects. Defaults to 'none'. */\n elevation?: SurfaceElevation;\n /** Edge divider border(s). Only applies when elevation is 'none'. */\n edge?: SurfaceEdge | SurfaceEdge[];\n /** Corner radius — preset or CSS variable. */\n radius?: SurfaceRadius;\n /** Enable hover/pressed interaction overlay. */\n interactive?: boolean;\n /** Apply selected background state. */\n selected?: boolean;\n /** Dim and disable pointer events. */\n inactive?: boolean;\n /** HTML element to render. Defaults to 'div'. */\n as?: SurfaceElement;\n /** Button type — only used when as='button'. */\n type?: 'button' | 'submit' | 'reset';\n}\n\n/** Non-intent surface — uses a basic background color. */\ninterface SurfaceDefaultProps extends SurfaceBaseProps {\n /** Background color. Defaults to 'transparent'. */\n background?: SurfaceBackground;\n intent?: never;\n contrast?: never;\n}\n\n/** Intent surface — uses a semantic color with contrast level. */\ninterface SurfaceIntentProps extends SurfaceBaseProps {\n /** Semantic intent color. */\n intent: SurfaceIntent;\n /** Contrast level for the intent background. Defaults to 'faint'. */\n contrast?: SurfaceContrast;\n background?: never;\n}\n\nexport type SurfaceProps = SurfaceDefaultProps | SurfaceIntentProps;\n\nconst backgroundClassMap: Record<SurfaceBackground, string> = {\n primary: styles.bgPrimary,\n secondary: styles.bgSecondary,\n transparent: styles.bgTransparent,\n translucent: styles.bgTranslucent,\n};\n\nconst elevationClassMap: Record<SurfaceElevation, string> = {\n none: styles.elevationNone,\n depressed: styles.elevationDepressed,\n 'depressed-md': styles.elevationDepressedMd,\n flat: styles.elevationFlat,\n elevated: styles.elevationElevated,\n floating: styles.elevationFloating,\n overlayTop: styles.elevationOverlayTop,\n overlayRight: styles.elevationOverlayRight,\n overlayBottom: styles.elevationOverlayBottom,\n overlayLeft: styles.elevationOverlayLeft,\n};\n\nconst edgeClassMap: Record<SurfaceEdge, string> = {\n top: styles.edgeTop,\n right: styles.edgeRight,\n bottom: styles.edgeBottom,\n left: styles.edgeLeft,\n};\n\nconst radiusClassMap: Record<SurfaceRadiusPreset, string> = {\n none: styles.radiusNone,\n xs: styles.radiusXs,\n sm: styles.radiusSm,\n md: styles.radiusMd,\n lg: styles.radiusLg,\n xl: styles.radiusXl,\n '2xl': styles.radius2xl,\n full: styles.radiusFull,\n};\n\nconst getIntentContrastClass = (intent: SurfaceIntent, contrast: SurfaceContrast): string => {\n const intentKey = intent.charAt(0).toUpperCase() + intent.slice(1);\n const contrastKey = contrast.charAt(0).toUpperCase() + contrast.slice(1);\n return styles[`intent${intentKey}${contrastKey}`] || '';\n};\n\nconst isPresetRadius = (radius: SurfaceRadius): radius is SurfaceRadiusPreset =>\n radius in radiusClassMap;\n\nexport const Surface = forwardRef<HTMLElement, SurfaceProps>(\n (\n {\n children,\n background = 'transparent',\n intent,\n contrast = 'faint',\n elevation = 'none',\n edge,\n radius,\n interactive = false,\n selected = false,\n inactive = false,\n as: Component = 'div',\n className = '',\n style,\n type,\n ...rest\n },\n ref\n ) => {\n const classes = [\n styles.surface,\n // Background or intent+contrast\n intent\n ? getIntentContrastClass(intent, contrast)\n : backgroundClassMap[background],\n // Elevation\n elevationClassMap[elevation],\n // Edge(s) — only when elevation is 'none'\n ...(edge && elevation === 'none'\n ? Array.isArray(edge)\n ? edge.map(e => edgeClassMap[e])\n : [edgeClassMap[edge]]\n : []),\n // Radius (preset only — custom handled via inline style)\n radius && isPresetRadius(radius) ? radiusClassMap[radius] : '',\n // States\n interactive ? styles.interactive : '',\n selected ? styles.selected : '',\n inactive ? styles.inactive : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n const computedStyle: React.CSSProperties = {\n ...style,\n ...(radius && !isPresetRadius(radius) ? { borderRadius: radius } : {}),\n };\n\n const hasStyle =\n (radius && !isPresetRadius(radius)) || (style && Object.keys(style).length > 0);\n\n const elementProps = {\n ref,\n className: classes,\n style: hasStyle ? computedStyle : undefined,\n disabled: Component === 'button' ? inactive : undefined,\n type: Component === 'button' ? type || 'button' : undefined,\n ...rest,\n };\n\n return (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n <Component {...(elementProps as any)}>{children}</Component>\n );\n }\n);\n\nSurface.displayName = 'Surface';\n","/**\n * Card — structured container with optional header/footer.\n * Uses TokoMo tokens directly (not built on Surface).\n */\n\n.card {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n overflow: hidden;\n}\n\n/* Elevation */\n.elevationFlat { box-shadow: var(--effect-elevation-elevated-none); }\n.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n.elevationFloating { box-shadow: var(--effect-elevation-elevated-floating); }\n\n/* Radius */\n.radiusSm { border-radius: var(--dimension-radius-075); }\n.radiusMd { border-radius: var(--dimension-radius-100); }\n.radiusLg { border-radius: var(--dimension-radius-125); }\n.radiusXl { border-radius: var(--dimension-radius-175); }\n\n/* Sections */\n.header {\n padding: var(--dimension-space-150) var(--dimension-space-200);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.body {\n padding: var(--dimension-space-200);\n}\n\n.footer {\n padding: var(--dimension-space-150) var(--dimension-space-200);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n","/**\n * Joins class names, filtering out falsy values.\n */\nexport function cn(...classes: (string | undefined | null | false)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n","import React, { forwardRef } from 'react';\nimport styles from './Card.module.css';\nimport { cn } from '@/utils/cn';\n\nexport type CardElevation = 'flat' | 'elevated' | 'floating';\nexport type CardRadius = 'sm' | 'md' | 'lg' | 'xl';\n\nexport interface CardProps {\n children: React.ReactNode;\n /** Optional header content — rendered with a bottom divider. */\n header?: React.ReactNode;\n /** Optional footer content — rendered with a top divider. */\n footer?: React.ReactNode;\n /** Elevation level. Defaults to 'elevated'. */\n elevation?: CardElevation;\n /** Corner radius. Defaults to 'lg'. */\n radius?: CardRadius;\n /** Additional CSS classes. */\n className?: string;\n /** Inline styles. */\n style?: React.CSSProperties;\n}\n\nconst elevationClassMap: Record<CardElevation, string> = {\n flat: styles.elevationFlat,\n elevated: styles.elevationElevated,\n floating: styles.elevationFloating,\n};\n\nconst radiusClassMap: Record<CardRadius, string> = {\n sm: styles.radiusSm,\n md: styles.radiusMd,\n lg: styles.radiusLg,\n xl: styles.radiusXl,\n};\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(\n ({ children, header, footer, elevation = 'elevated', radius = 'lg', className, style }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(styles.card, elevationClassMap[elevation], radiusClassMap[radius], className)}\n style={style}\n >\n {header && <div className={styles.header}>{header}</div>}\n <div className={styles.body}>{children}</div>\n {footer && <div className={styles.footer}>{footer}</div>}\n </div>\n );\n }\n);\n\nCard.displayName = 'Card';\n","/* ==========================================================================\n LabelWrap — internal utility\n Kills the inherited line-height strut so the component's fixed height\n is not inflated by body { line-height: 1.5 }, then adds optical\n horizontal padding around the text.\n ========================================================================== */\n\n.labelWrap {\n line-height: 0;\n padding: 0 var(--dimension-space-050); /* 4px — body sm / md / lg */\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n/* Small scale: tighter optical padding */\n.sizeSm { padding: 0 var(--dimension-space-025); } /* 2px */\n\n/* Caption scale: tighter optical padding */\n.sizeXs { padding: 0 var(--dimension-space-025); } /* 2px */\n\n/* Truncation mode — used when parent is full-width and label must ellipsize */\n.truncate {\n flex-shrink: 1;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n}\n\n.truncate > span {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './LabelWrap.module.css';\n\ninterface LabelWrapProps {\n children: React.ReactNode;\n /**\n * Maps to typography size — controls optical horizontal padding:\n * xs | sm → 2px (tighter scale)\n * md | lg → 4px (body scale, default)\n */\n size?: 'xs' | 'sm' | 'md' | 'lg';\n /** Enables truncation with ellipsis — use inside full-width containers. */\n truncate?: boolean;\n className?: string;\n}\n\n/**\n * Internal utility wrapper used inside interactive components (Button, Tag,\n * Input, Select, MenuItem, etc.) to:\n * 1. Kill the inherited line-height strut from body { line-height: 1.5 }\n * 2. Add optical horizontal padding around the text\n *\n * Not exported from the public barrel — internal use only.\n */\nexport const LabelWrap = ({ children, size = 'md', truncate = false, className }: LabelWrapProps) => (\n <span className={cn(styles.labelWrap, size === 'sm' && styles.sizeSm, size === 'xs' && styles.sizeXs, truncate && styles.truncate, className)}>\n {children}\n </span>\n);\n\nLabelWrap.displayName = 'LabelWrap';\n",".loader {\n flex-shrink: 0;\n animation: spin 0.75s linear infinite;\n}\n\n.status {\n display: inline-flex;\n align-items: center;\n}\n\n.visuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n@keyframes spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n","import React from 'react';\nimport styles from './Loader.module.css';\n\nexport interface LoaderProps {\n /**\n * Render size in px. Designed at 16px (r=6, strokeWidth=1).\n * Stroke weight scales proportionally with size — same behaviour as icons.\n * Defaults to 20.\n */\n size?: number;\n className?: string;\n /**\n * Accessible label announced by assistive tech when the Loader is used\n * standalone. When provided, the spinner is wrapped in a live region\n * (`role=\"status\"`, `aria-live=\"polite\"`) and the label is rendered\n * visually-hidden so screen readers announce it on mount.\n *\n * Omit when the Loader is rendered inside a host that already conveys\n * busy state (e.g. a Button with `aria-busy`) — the spinner stays\n * `aria-hidden` to avoid double-announcing.\n */\n label?: string;\n}\n\n/**\n * Placeholder spinner component. Will be replaced with a full Loader\n * component once motion/brand specs are finalised.\n *\n * Designed at 16×16 viewBox so it matches the icon grid:\n * - r=5 → 10px circle in a 16px box (3px optical padding each side)\n * - strokeWidth=1 at native size → scales to 1.25px at 20px, 1.5px at 24px\n */\nexport const Loader = ({ size = 20, className, label }: LoaderProps) => {\n const svg = (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className={`${styles.loader}${className ? ` ${className}` : ''}`}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"5\"\n stroke=\"currentColor\"\n strokeWidth=\"1\"\n strokeLinecap=\"round\"\n strokeDasharray=\"23.6 7.9\"\n />\n </svg>\n );\n\n if (label === undefined) return svg;\n\n return (\n <span role=\"status\" aria-live=\"polite\" className={styles.status}>\n {svg}\n <span className={styles.visuallyHidden}>{label}</span>\n </span>\n );\n};\n\nLoader.displayName = 'Loader';\n","/* ==========================================================================\n Button — unified primary/secondary\n Hover/pressed via color-mix() on background-color. No pseudo-element overlays.\n ========================================================================== */\n\n.button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n position: relative;\n transition: transform var(--effect-motion-short-2);\n height: var(--dimension-size-400);\n font-family: inherit;\n color: var(--color-foreground-primary);\n background: transparent;\n box-sizing: border-box;\n text-decoration: none;\n -webkit-user-select: none;\n user-select: none;\n\n /* Interaction — ghost defaults (semi-transparent overlay) */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_border: var(--color-border-tertiary);\n}\n\n.button:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.button:hover:not(.inactive) {\n background-color: var(--_hover-bg);\n}\n\n.button:active:not(.inactive) {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* ==========================================================================\n Background context — parent surface awareness\n Adjusts hover tokens and secondary fg for colored parent surfaces.\n 1-class specificity; overridden by filled variant rules (2+ classes).\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_border: var(--color-border-on-medium-background-tertiary);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_border: var(--color-border-on-bold-background-tertiary);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_border: var(--color-border-on-strong-background-tertiary);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_border: var(--color-always-dark-border-tertiary);\n}\n\n/* ==========================================================================\n Variant: Primary\n Bold background, on-bold content. Elevation controls shadow.\n ========================================================================== */\n\n.primary {\n color: var(--color-foreground-on-bold-background-primary);\n}\n\n/* Primary intent: none — inverted surface (black in light mode, white in dark mode) */\n.primary.intentNone {\n background-color: var(--color-inverted-background);\n color: var(--color-inverted-foreground-primary);\n --_hover-bg: color-mix(in oklch, var(--color-inverted-background) 90%, var(--color-inverted-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-inverted-background) 85%, var(--color-inverted-foreground-primary));\n --_border: var(--color-inverted-border-tertiary);\n}\n\n/* Filled primary — background from --_bg, bold-contrast hover via color-mix.\n 2-class specificity beats background context (1-class). */\n.primary:not(.intentNone) {\n background-color: var(--_bg);\n --_hover-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-on-bold-background-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 80%, var(--color-foreground-on-bold-background-primary));\n}\n\n/* ── Primary bold contrast (default) ────────────────────────────────── */\n\n.primary.intentBrand { --_bg: var(--color-background-bold-brand); color: var(--color-foreground-faint-brand); }\n.primary.intentNeutral { --_bg: var(--color-background-bold-neutral); color: var(--color-foreground-faint-neutral); }\n.primary.intentPositive { --_bg: var(--color-background-bold-positive); color: var(--color-foreground-faint-positive); }\n.primary.intentNegative { --_bg: var(--color-background-bold-negative); color: var(--color-foreground-faint-negative); }\n.primary.intentWarning { --_bg: var(--color-background-bold-warning); color: var(--color-foreground-faint-warning); }\n.primary.intentCaution { --_bg: var(--color-background-bold-caution); color: var(--color-foreground-faint-caution); }\n.primary.intentAi { --_bg: var(--color-background-bold-ai); color: var(--color-foreground-faint-ai); }\n\n/* ── Primary medium contrast ────────────────────────────────────────── */\n\n.primary.contrastMedium {\n --_hover-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 80%, var(--color-foreground-primary));\n}\n.primary.contrastMedium.intentBrand { --_bg: var(--color-background-medium-brand); color: var(--color-foreground-strong-brand); }\n.primary.contrastMedium.intentNeutral { --_bg: var(--color-background-medium-neutral); color: var(--color-foreground-strong-neutral); }\n.primary.contrastMedium.intentPositive { --_bg: var(--color-background-medium-positive); color: var(--color-foreground-strong-positive); }\n.primary.contrastMedium.intentNegative { --_bg: var(--color-background-medium-negative); color: var(--color-foreground-strong-negative); }\n.primary.contrastMedium.intentWarning { --_bg: var(--color-background-medium-warning); color: var(--color-foreground-strong-warning); }\n.primary.contrastMedium.intentCaution { --_bg: var(--color-background-medium-caution); color: var(--color-foreground-strong-caution); }\n.primary.contrastMedium.intentAi { --_bg: var(--color-background-medium-ai); color: var(--color-foreground-strong-ai); }\n\n/* ── Primary strong contrast ────────────────────────────────────────── */\n\n.primary.contrastStrong {\n --_hover-bg: color-mix(in oklch, var(--_bg) 90%, var(--color-foreground-on-bold-background-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-on-bold-background-primary));\n}\n.primary.contrastStrong.intentBrand { --_bg: var(--color-background-strong-brand); color: var(--color-foreground-medium-brand); }\n.primary.contrastStrong.intentNeutral { --_bg: var(--color-background-strong-neutral); color: var(--color-foreground-medium-neutral); }\n.primary.contrastStrong.intentPositive { --_bg: var(--color-background-strong-positive); color: var(--color-foreground-medium-positive); }\n.primary.contrastStrong.intentNegative { --_bg: var(--color-background-strong-negative); color: var(--color-foreground-medium-negative); }\n.primary.contrastStrong.intentWarning { --_bg: var(--color-background-strong-warning); color: var(--color-foreground-medium-warning); }\n.primary.contrastStrong.intentCaution { --_bg: var(--color-background-strong-caution); color: var(--color-foreground-medium-caution); }\n.primary.contrastStrong.intentAi { --_bg: var(--color-background-strong-ai); color: var(--color-foreground-medium-ai); }\n\n/* ── Primary faint contrast ─────────────────────────────────────────── */\n\n.primary.contrastFaint {\n --_hover-bg: color-mix(in oklch, var(--_bg) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--_bg) 85%, var(--color-foreground-primary));\n}\n.primary.contrastFaint.intentBrand { --_bg: var(--color-background-faint-brand); color: var(--color-foreground-bold-brand); }\n.primary.contrastFaint.intentNeutral { --_bg: var(--color-background-faint-neutral); color: var(--color-foreground-bold-neutral); }\n.primary.contrastFaint.intentPositive { --_bg: var(--color-background-faint-positive); color: var(--color-foreground-bold-positive); }\n.primary.contrastFaint.intentNegative { --_bg: var(--color-background-faint-negative); color: var(--color-foreground-bold-negative); }\n.primary.contrastFaint.intentWarning { --_bg: var(--color-background-faint-warning); color: var(--color-foreground-bold-warning); }\n.primary.contrastFaint.intentCaution { --_bg: var(--color-background-faint-caution); color: var(--color-foreground-bold-caution); }\n.primary.contrastFaint.intentAi { --_bg: var(--color-background-faint-ai); color: var(--color-foreground-bold-ai); }\n\n/* ==========================================================================\n Variant: Secondary\n Base is ghost (transparent, no border, no shadow).\n Elevation classes add the chrome — flat=border, elevated=bg+shadow, floating=bg+floating.\n ========================================================================== */\n\n.secondary {\n background-color: transparent;\n color: var(--color-foreground-secondary);\n}\n\n/* Secondary intent — bold fg color */\n.secondary.intentBrand { color: var(--color-foreground-bold-brand); }\n.secondary.intentNeutral { color: var(--color-foreground-bold-neutral); }\n.secondary.intentPositive { color: var(--color-foreground-bold-positive); }\n.secondary.intentNegative { color: var(--color-foreground-bold-negative); }\n.secondary.intentWarning { color: var(--color-foreground-bold-warning); }\n.secondary.intentCaution { color: var(--color-foreground-bold-caution); }\n.secondary.intentAi { color: var(--color-foreground-bold-ai); }\n\n/* ── Secondary fg on medium surface ─────────────────────────────────── */\n\n.secondary.onMedium { color: var(--color-foreground-primary); }\n.secondary.onMedium.intentBrand { color: var(--color-foreground-strong-brand); }\n.secondary.onMedium.intentNeutral { color: var(--color-foreground-strong-neutral); }\n.secondary.onMedium.intentPositive { color: var(--color-foreground-strong-positive); }\n.secondary.onMedium.intentNegative { color: var(--color-foreground-strong-negative); }\n.secondary.onMedium.intentWarning { color: var(--color-foreground-strong-warning); }\n.secondary.onMedium.intentCaution { color: var(--color-foreground-strong-caution); }\n.secondary.onMedium.intentAi { color: var(--color-foreground-strong-ai); }\n\n/* ── Secondary fg on bold surface ──────────────────────────────────── */\n\n.secondary.onBold { color: var(--color-foreground-on-bold-background-secondary); }\n.secondary.onBold.intentBrand { color: var(--color-foreground-faint-brand); }\n.secondary.onBold.intentNeutral { color: var(--color-foreground-faint-neutral); }\n.secondary.onBold.intentPositive { color: var(--color-foreground-faint-positive); }\n.secondary.onBold.intentNegative { color: var(--color-foreground-faint-negative); }\n.secondary.onBold.intentWarning { color: var(--color-foreground-faint-warning); }\n.secondary.onBold.intentCaution { color: var(--color-foreground-faint-caution); }\n.secondary.onBold.intentAi { color: var(--color-foreground-faint-ai); }\n\n/* ── Secondary fg on always-dark surface ──────────────────────────── */\n\n.secondary.onAlwaysDark { color: var(--color-always-dark-foreground-secondary); }\n.secondary.onAlwaysDark.intentBrand { color: var(--color-always-dark-foreground-brand); }\n.secondary.onAlwaysDark.intentNeutral { color: var(--color-always-dark-foreground-neutral); }\n.secondary.onAlwaysDark.intentPositive { color: var(--color-always-dark-foreground-positive); }\n.secondary.onAlwaysDark.intentNegative { color: var(--color-always-dark-foreground-negative); }\n.secondary.onAlwaysDark.intentWarning { color: var(--color-always-dark-foreground-warning); }\n.secondary.onAlwaysDark.intentCaution { color: var(--color-always-dark-foreground-caution); }\n.secondary.onAlwaysDark.intentAi { color: var(--color-always-dark-foreground-ai); }\n\n/* ── Secondary fg on strong surface ─────────────────────────────────── */\n\n.secondary.onStrong { color: var(--color-foreground-on-bold-background-secondary); }\n.secondary.onStrong.intentBrand { color: var(--color-foreground-faint-brand); }\n.secondary.onStrong.intentNeutral { color: var(--color-foreground-faint-neutral); }\n.secondary.onStrong.intentPositive { color: var(--color-foreground-faint-positive); }\n.secondary.onStrong.intentNegative { color: var(--color-foreground-faint-negative); }\n.secondary.onStrong.intentWarning { color: var(--color-foreground-faint-warning); }\n.secondary.onStrong.intentCaution { color: var(--color-foreground-faint-caution); }\n.secondary.onStrong.intentAi { color: var(--color-foreground-faint-ai); }\n\n/* ==========================================================================\n Elevation\n ========================================================================== */\n\n/* ── Secondary chrome ───────────────────────────────────────────────── */\n\n/* elevationNone = ghost base — no extra CSS needed */\n\n.secondary.elevationFlat {\n box-shadow: inset 0 0 0 1px var(--_border);\n}\n\n.secondary.elevationElevated {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n.secondary.elevationFloating {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-floating);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Primary shadow + border control ───────────────────────────────── */\n\n/* elevated */\n.primary.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n\n/* none = no shadow, no border (flat colored button — default for primary) */\n.primary.elevationNone { box-shadow: none; }\n\n/* flat = inset ring against the page background (not the button fill) */\n.primary.elevationFlat { box-shadow: inset 0 0 0 1px var(--_border); }\n\n/* intentNone flat: inverted fill + default border ring (bg/fg inherited from .primary.intentNone) */\n.primary.intentNone.elevationFlat {\n --_border: var(--color-border-tertiary);\n}\n\n/* intentNone on strong/always-dark: flip to surface bg/fg — inverted (black) would be invisible */\n.primary.intentNone.onStrong,\n.primary.intentNone.onAlwaysDark {\n background-color: var(--color-background-primary);\n color: var(--color-foreground-primary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n --_border: var(--color-border-tertiary);\n}\n\n/* floating = FAB-strength shadow for both variants */\n.primary.elevationFloating { box-shadow: var(--effect-elevation-elevated-floating) !important; }\n\n/* ==========================================================================\n Layout: icon-only, label-only, icon+label, dropdown\n ========================================================================== */\n\n.iconOnly { padding: 0; width: var(--dimension-size-400); min-width: var(--dimension-size-400); }\n.labelOnly { padding: 0 var(--dimension-space-100); }\n.iconAndLabel { padding: 0 var(--dimension-space-100) 0 var(--dimension-space-075); gap: var(--dimension-space-025); }\n.dropdown { gap: var(--dimension-space-050); }\n\n/* ==========================================================================\n Sizes\n ========================================================================== */\n\n.sizeSM { height: var(--dimension-size-300); }\n.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.sizeSM.labelOnly { padding: 0 var(--dimension-space-075); }\n.sizeSM.iconAndLabel { padding: 0 var(--dimension-space-075) 0 var(--dimension-space-050); gap: 1px; }\n\n.sizeXS { height: var(--dimension-size-200); }\n.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n.sizeXS.labelOnly, .sizeXS.iconAndLabel { padding: 0 var(--dimension-space-025); gap: 0; }\n\n.sizeLG { height: var(--dimension-size-500); }\n.sizeLG.iconOnly { width: var(--dimension-size-500); min-width: var(--dimension-size-500); }\n.sizeLG.labelOnly { padding: 0 var(--dimension-space-150); }\n.sizeLG.iconAndLabel { padding: 0 var(--dimension-space-150) 0 var(--dimension-space-100); gap: var(--dimension-space-075); }\n\n/* ==========================================================================\n Rounded (pill shape)\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n.rounded.labelOnly { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.iconAndLabel { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.sizeSM.labelOnly { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeSM.iconAndLabel { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeLG.labelOnly { padding-left: calc(var(--dimension-space-150) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-150) + var(--dimension-space-050)); }\n.rounded.sizeLG.iconAndLabel { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-150) + var(--dimension-space-050)); }\n.rounded.iconOnly { width: var(--dimension-size-400); min-width: var(--dimension-size-400); padding: 0; }\n.rounded.sizeLG.iconOnly { width: var(--dimension-size-500); min-width: var(--dimension-size-500); }\n.rounded.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.rounded.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n\n/* ==========================================================================\n Badge\n ========================================================================== */\n\n.badge {\n position: absolute;\n top: var(--dimension-space-025);\n right: var(--dimension-space-025);\n font-size: var(--typography-fontsize-xs);\n font-weight: var(--typography-weight-semibold);\n line-height: var(--typography-lineheight-xs);\n color: var(--color-foreground-secondary);\n pointer-events: none;\n z-index: 10;\n}\n\n/* ==========================================================================\n Full width\n ========================================================================== */\n\n.fullWidth {\n display: flex;\n width: 100%;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport { Loader } from '@/components/Loader';\nimport { ChevronDown } from '@ds-mo/icons';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'primary' | 'secondary';\nexport type ButtonElevation = 'none' | 'flat' | 'elevated' | 'floating';\nexport type ButtonIntent = 'none' | 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonContrast = 'strong' | 'bold' | 'medium' | 'faint';\nexport type ButtonBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\ninterface ButtonBaseProps {\n /** Polymorphic element type. Defaults to 'button'. */\n as?: React.ElementType;\n /** Visual variant. Defaults to 'primary'. */\n variant?: ButtonVariant;\n /** Leading icon component from @ds-mo/icons. */\n icon?: IconComponent;\n /** Semantic intent. Defaults to 'brand'. */\n intent?: ButtonIntent;\n /** Size. Defaults to 'md'. */\n size?: ButtonSize;\n /** Pill shape with extra padding. */\n rounded?: boolean;\n /** Fill container width. Label truncates if space is tight. */\n fullWidth?: boolean;\n /** Fixed width. Omit for content width. */\n width?: React.CSSProperties['width'];\n /** Contrast level (primary variant only). Defaults to 'bold'. */\n contrast?: ButtonContrast;\n /**\n * Parent surface context. Adjusts hover tokens and secondary fg colors\n * for buttons placed on colored backgrounds.\n * faint — default, no adjustment\n * medium — use on-medium-background interaction tokens\n * bold — use on-bold-background interaction + inverted fg\n * strong — use on-strong-background interaction + inverted fg\n * always-dark — dark surface (no theme flip), on-bold-background tokens\n */\n background?: ButtonBackground;\n /** Show trailing ChevronDown dropdown indicator. */\n dropdown?: boolean;\n /** Badge count. */\n badgeCount?: number;\n /**\n * Chrome level for secondary; shadow level for primary.\n * none — ghost (transparent, no border, no shadow)\n * flat — border only, transparent bg [default for secondary]\n * elevated — bg-primary + shadow [default for primary]\n * floating — bg-primary + FAB-strength shadow\n */\n elevation?: ButtonElevation;\n /** Show loading spinner in place of icon. Prevents interaction. */\n loading?: boolean;\n\n onClick?: (e: React.MouseEvent<HTMLElement>) => void;\n onMouseEnter?: React.MouseEventHandler<HTMLElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLElement>;\n className?: string;\n inactive?: boolean;\n type?: 'button' | 'submit' | 'reset';\n id?: string;\n href?: string;\n target?: string;\n rel?: string;\n}\n\n/**\n * Accessible-name requirement: a Button must expose text via `label`,\n * `aria-label`, or `aria-labelledby`. Icon-only buttons that omit all three\n * fail at the call site (TypeScript), with a runtime warning as a soft\n * fallback for callers that bypass the type system.\n */\ntype ButtonAccessibleNameProps =\n | { label: string; 'aria-label'?: string; 'aria-labelledby'?: string }\n | { label?: string; 'aria-label': string; 'aria-labelledby'?: string }\n | { label?: string; 'aria-label'?: string; 'aria-labelledby': string };\n\nexport type ButtonProps = ButtonBaseProps & ButtonAccessibleNameProps;\n\nconst ICON_SIZE_MAP: Record<ButtonSize, number> = { xs: 12, sm: 16, md: 20, lg: 24 };\n\nconst TEXT_STYLE_MAP: Record<ButtonSize, string> = {\n xs: 'text-caption-emphasis',\n sm: 'text-body-small-emphasis',\n md: 'text-body-medium-emphasis',\n lg: 'text-body-large-emphasis',\n};\n\n\nexport const Button = forwardRef<HTMLElement, ButtonProps>(\n (props, ref) => {\n const {\n as,\n variant = 'primary',\n label,\n icon: Icon,\n intent = 'brand',\n size = 'md',\n rounded = false,\n fullWidth = false,\n width,\n contrast = 'bold',\n background,\n dropdown = false,\n badgeCount,\n elevation,\n loading = false,\n onClick,\n onMouseEnter,\n onMouseLeave,\n className,\n inactive = false,\n type = 'button',\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n href,\n target,\n rel,\n } = props;\n\n const Component = (as ?? 'button') as React.ElementType;\n const isButton = !as || as === 'button';\n const isLink = as === 'a';\n const isCustomInteractive = !isButton && !isLink;\n const isInteractive = !inactive && !loading;\n\n const hasIcon = !!Icon;\n const hasLabel = !!label;\n const showLeading = hasIcon || loading; // spinner fills the icon slot\n const isIconOnly = showLeading && !hasLabel;\n const isLabelOnly = hasLabel && !showLeading;\n const isIconAndLabel = showLeading && hasLabel;\n const iconSize = ICON_SIZE_MAP[size];\n const textStyle = TEXT_STYLE_MAP[size];\n\n // Derive default elevation per variant: primary→none, secondary→flat\n const effectiveElevation: ButtonElevation = elevation ?? (variant === 'primary' ? 'none' : 'flat');\n const elevKey = effectiveElevation.charAt(0).toUpperCase() + effectiveElevation.slice(1);\n\n const classes = cn(\n styles.button,\n styles[variant],\n styles[`intent${intent.charAt(0).toUpperCase() + intent.slice(1)}`],\n size !== 'md' && styles[`size${size.toUpperCase()}`],\n rounded && styles.rounded,\n (inactive || loading) && styles.inactive,\n isIconOnly && styles.iconOnly,\n isLabelOnly && styles.labelOnly,\n isIconAndLabel && styles.iconAndLabel,\n dropdown && styles.dropdown,\n variant === 'primary' && intent !== 'none' && contrast !== 'bold' && styles[`contrast${contrast.charAt(0).toUpperCase() + contrast.slice(1)}`],\n styles[`elevation${elevKey}`],\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n fullWidth && styles.fullWidth,\n className,\n );\n\n if (isIconOnly && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[@ds-mo/ui Button] Icon-only Button is missing an accessible name. Provide `label`, `aria-label`, or `aria-labelledby`.'\n );\n }\n\n const extraProps: Record<string, unknown> = {};\n if (isButton) {\n extraProps.type = type;\n extraProps.disabled = inactive || loading;\n }\n if (href) extraProps.href = href;\n if (target) extraProps.target = target;\n if (rel) extraProps.rel = rel;\n\n if (isCustomInteractive) {\n extraProps.role = 'button';\n extraProps.tabIndex = isInteractive ? 0 : -1;\n if (isInteractive) {\n extraProps.onKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (e.currentTarget as HTMLElement).click();\n }\n };\n }\n }\n\n return (\n <Component\n ref={ref}\n id={id}\n className={classes}\n style={width ? { width } : undefined}\n onClick={isInteractive ? onClick : undefined}\n onMouseEnter={isInteractive ? onMouseEnter : undefined}\n onMouseLeave={isInteractive ? onMouseLeave : undefined}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-disabled={inactive || loading || undefined}\n aria-busy={loading || undefined}\n {...extraProps}\n >\n {loading ? (\n <Loader size={iconSize} />\n ) : (\n Icon && <Icon size={iconSize} />\n )}\n {label && (\n <LabelWrap truncate={fullWidth}>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n )}\n {dropdown && <ChevronDown size={iconSize} />}\n {badgeCount != null && badgeCount > 0 && (\n <span className={styles.badge}>{badgeCount > 9 ? '+' : badgeCount}</span>\n )}\n </Component>\n );\n }\n);\n\nButton.displayName = 'Button';\n","/* ==========================================================================\n ToggleButton — hover/pressed via direct background-color + color-mix().\n No pseudo-element overlays.\n Elevation controls the chrome level:\n elevated — bg-primary + shadow (default)\n flat — border only\n none — ghost (transparent, no border, no shadow)\n floating — bg-primary + FAB-strength shadow\n ========================================================================== */\n\n.toggleButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n position: relative;\n transition: transform var(--effect-motion-short-2);\n height: var(--dimension-size-400);\n font-family: inherit;\n background: transparent;\n box-sizing: border-box;\n -webkit-user-select: none;\n user-select: none;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n --_border: var(--color-border-tertiary);\n}\n\n.toggleButton:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.toggleButton:hover:not(.inactive) {\n background-color: var(--_hover-bg);\n}\n\n.toggleButton:active:not(.inactive) {\n background-color: var(--_pressed-bg);\n transform: scale(var(--dimension-scale-subtle));\n}\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n --_border: var(--color-border-on-medium-background-tertiary);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n --_border: var(--color-border-on-bold-background-tertiary);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n --_border: var(--color-border-on-strong-background-tertiary);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n --_border: var(--color-always-dark-border-tertiary);\n}\n\n/* ==========================================================================\n Elevation levels\n ========================================================================== */\n\n/* ── Elevated (default): bg-primary + shadow ───────────────────────────── */\n\n.elevationElevated {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n color: var(--color-foreground-secondary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Flat: border only, transparent bg ─────────────────────────────────── */\n\n.elevationFlat {\n box-shadow: inset 0 0 0 1px var(--_border);\n color: var(--color-foreground-secondary);\n}\n\n/* ── None: ghost — transparent, no border, no shadow ───────────────────── */\n\n.elevationNone {\n color: var(--color-foreground-secondary);\n}\n\n/* ── Floating: bg-primary + FAB-strength shadow ─────────────────────────── */\n\n.elevationFloating {\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-floating);\n color: var(--color-foreground-secondary);\n --_hover-bg: color-mix(in oklch, var(--color-background-primary) 90%, var(--color-foreground-primary));\n --_pressed-bg: color-mix(in oklch, var(--color-background-primary) 85%, var(--color-foreground-primary));\n}\n\n/* ── Fg on bold / strong surface ────────────────────────────────────────── */\n\n.onBold.elevationNone, .onBold.elevationFlat,\n.onStrong.elevationNone, .onStrong.elevationFlat {\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n/* ── Fg on always-dark surface ─────────────────────────────────────────── */\n\n.onAlwaysDark.elevationNone, .onAlwaysDark.elevationFlat {\n color: var(--color-always-dark-foreground-secondary);\n}\n\n/* ==========================================================================\n Pressed state — shared across all elevation levels\n ========================================================================== */\n\n.pressed {\n background-color: var(--color-background-faint-brand);\n color: var(--color-foreground-bold-brand);\n}\n\n/* ==========================================================================\n Layout\n ========================================================================== */\n\n.iconOnly { padding: 0; width: var(--dimension-size-400); min-width: var(--dimension-size-400); }\n.labelOnly { padding: 0 var(--dimension-space-100); }\n.iconAndLabel{ padding: 0 var(--dimension-space-100) 0 var(--dimension-space-075); gap: var(--dimension-space-025); }\n\n/* ==========================================================================\n Sizes\n ========================================================================== */\n\n.sizeSM { height: var(--dimension-size-300); }\n.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.sizeSM.labelOnly { padding: 0 var(--dimension-space-075); }\n.sizeSM.iconAndLabel { padding: 0 var(--dimension-space-075) 0 var(--dimension-space-050); gap: 0; }\n\n.sizeXS { height: var(--dimension-size-200); }\n.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n.sizeXS.labelOnly, .sizeXS.iconAndLabel { padding: 0 var(--dimension-space-025); gap: 0; }\n\n/* ==========================================================================\n Rounded (pill shape)\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n.rounded.labelOnly { padding-left: calc(var(--dimension-space-100) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.iconAndLabel { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-100) + var(--dimension-space-050)); }\n.rounded.sizeSM.labelOnly { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.sizeSM.iconAndLabel { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.rounded.iconOnly { width: var(--dimension-size-400); min-width: var(--dimension-size-400); padding: 0; }\n.rounded.sizeSM.iconOnly { width: var(--dimension-size-300); min-width: var(--dimension-size-300); }\n.rounded.sizeXS.iconOnly { width: var(--dimension-size-200); min-width: var(--dimension-size-200); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './ToggleButton.module.css';\n\nexport type ToggleButtonElevation = 'none' | 'flat' | 'elevated' | 'floating';\nexport type ToggleButtonSize = 'md' | 'sm' | 'xs';\nexport type ToggleButtonBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface ToggleButtonProps {\n /**\n * Chrome level.\n * none — ghost (transparent, no border, no shadow)\n * flat — border only, transparent bg\n * elevated — bg-primary + shadow [default]\n * floating — bg-primary + FAB-strength shadow\n */\n elevation?: ToggleButtonElevation;\n /** Label text. */\n label?: string;\n /** Leading icon component. */\n icon?: IconComponent;\n /** Size: md (32px), sm (24px), xs (16px). Defaults to 'md'. */\n size?: ToggleButtonSize;\n /** Pill shape. */\n rounded?: boolean;\n /** Parent surface context. Adjusts hover tokens for toggle buttons on colored backgrounds. */\n background?: ToggleButtonBackground;\n /** Controlled pressed state. */\n pressed: boolean;\n /** Called when pressed state changes. */\n onPressedChange: (pressed: boolean) => void;\n inactive?: boolean;\n className?: string;\n id?: string;\n 'aria-label'?: string;\n}\n\nconst ICON_SIZE_MAP: Record<ToggleButtonSize, number> = { md: 20, sm: 16, xs: 12 };\n\nconst TEXT_STYLE_MAP: Record<ToggleButtonSize, string> = {\n md: 'text-body-medium-emphasis',\n sm: 'text-body-small-emphasis',\n xs: 'text-caption-emphasis',\n};\n\nexport const ToggleButton = forwardRef<HTMLButtonElement, ToggleButtonProps>(\n (\n {\n elevation = 'elevated',\n label,\n icon: Icon,\n size = 'md',\n rounded = false,\n background,\n pressed,\n onPressedChange,\n inactive = false,\n className,\n id,\n 'aria-label': ariaLabel,\n },\n ref\n ) => {\n const hasIcon = !!Icon;\n const hasLabel = !!label;\n const isIconOnly = hasIcon && !hasLabel;\n const isLabelOnly = hasLabel && !hasIcon;\n const isIconAndLabel = hasIcon && hasLabel;\n const iconSize = ICON_SIZE_MAP[size];\n const textStyle = TEXT_STYLE_MAP[size];\n\n const elevKey = elevation.charAt(0).toUpperCase() + elevation.slice(1);\n\n const classes = cn(\n styles.toggleButton,\n styles[`elevation${elevKey}`],\n size !== 'md' && styles[`size${size.toUpperCase()}`],\n rounded && styles.rounded,\n inactive && styles.inactive,\n isIconOnly && styles.iconOnly,\n isLabelOnly && styles.labelOnly,\n isIconAndLabel && styles.iconAndLabel,\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n pressed && styles.pressed,\n className,\n );\n\n return (\n <button\n ref={ref}\n id={id}\n className={classes}\n onClick={inactive ? undefined : () => onPressedChange(!pressed)}\n type=\"button\"\n disabled={inactive}\n aria-label={ariaLabel || label || 'toggle'}\n aria-pressed={pressed}\n >\n {Icon && <Icon size={iconSize} />}\n {label && (\n <LabelWrap>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n )}\n </button>\n );\n }\n);\n\nToggleButton.displayName = 'ToggleButton';\n","/* ==========================================================================\n ButtonGroup — flush row of Button components\n ========================================================================== */\n\n.group {\n display: inline-flex;\n align-items: stretch;\n border-radius: var(--dimension-radius-050);\n position: relative;\n}\n\n/* Inset ring / highlight overlay — sits above button children so it isn't\n covered by their backgrounds. Outset shadow stays on the element itself. */\n.group::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n}\n\n/* ── Group-level elevation ──────────────────────────────────────────────── */\n/* Individual item chrome is suppressed via .item — the group container\n carries the elevation so it wraps the whole control as one visual unit. */\n\n/* Outset shadow on element; inset highlight on ::after (children would cover it otherwise) */\n.groupElevated { box-shadow: var(--effect-shadow-elevated-sm); }\n.groupElevated::after { box-shadow: var(--effect-highlight-elevated-sm); }\n\n/* Flat ring lives entirely on ::after — same reasoning as highlight */\n.groupFlat::after { box-shadow: inset 0 0 0 1px var(--color-border-tertiary); }\n\n.groupFloating { box-shadow: var(--effect-shadow-elevated-floating); }\n.groupFloating::after { box-shadow: var(--effect-highlight-elevated-floating); }\n/* groupNone = ghost / primary — no shadow, no border */\n\n.groupRounded { border-radius: var(--dimension-radius-half); }\n\n/* ── Base item ─────────────────────────────────────────────────────────────── */\n\n.item {\n flex-shrink: 0;\n /* Suppress individual elevation so the group reads as one unit */\n box-shadow: none !important;\n /* Suppress noElevation individual border — divider handles separation */\n border: none !important;\n /* Suppress scale-on-press: transform would detach the divider from the\n adjacent button, creating a visible gap. Pressed state is still\n communicated via the ::after overlay colour. */\n}\n.item:active {\n transform: none !important;\n}\n\n/* ── Divider ────────────────────────────────────────────────────────────────\n * Rendered as a separate <div> between items so it is never part of any\n * button's stacking context — disabled (opacity: 0.5) or other state changes\n * on adjacent buttons cannot bleed through to the divider.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* Full-height divider (secondary + primary).\n * Overlaps each neighbour by 0.5px and paints on top so the alpha token\n * composites over the button fill rather than the page background. */\n.divider {\n width: 1px;\n flex-shrink: 0;\n background-color: var(--color-border-tertiary);\n position: relative;\n z-index: 1;\n margin: 0 -0.5px;\n pointer-events: none;\n}\n\n/* Ghost (elevation=none): short centred divider at icon height */\n.dividerGhost { height: 20px; align-self: center; } /* md default */\n.dividerGhostXS { height: 12px; }\n.dividerGhostSM { height: 16px; }\n.dividerGhostLG { height: 24px; }\n\n/* Primary intent: on-background divider colour */\n.dividerBold { background-color: var(--color-border-on-bold-background-tertiary); }\n.dividerMedium { background-color: var(--color-border-on-medium-background-tertiary); }\n.dividerStrong { background-color: var(--color-border-on-strong-background-tertiary); }\n\n/* Ghost hover-fade: hide the divider on either side of a hovered ghost button */\n.item:hover + .dividerGhost,\n.dividerGhost:has(+ .item:hover) { opacity: 0; }\n\n/* ── Ghost interaction states: rounded chips ──────────────────────────────────\n * Ghost items have no group chrome — hover/press overlay should appear as\n * fully rounded chips (4px all corners). Rounded groups: outer corners of\n * first/last become pill; inner corners stay 4px.\n *\n * Uses .group ancestor (2-class specificity) to reliably beat .first / .last /\n * .middle (1-class) regardless of load order. Explicit longhands throughout to\n * avoid shorthand/longhand cascade ambiguity with the !important rules above.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* ::after hover/press overlay — all positions: 4px all corners */\n.group .itemShort::after {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* ── Border radius: flatten only the inner-facing corners ──────────────────── */\n/* Outer corners keep the button's own radius — works for default + rounded */\n\n.first {\n border-top-right-radius: 0 !important;\n border-bottom-right-radius: 0 !important;\n}\n\n.last {\n border-top-left-radius: 0 !important;\n border-bottom-left-radius: 0 !important;\n}\n\n.middle {\n border-radius: 0 !important;\n}\n\n/* Rounded group: first — left corners become pill (3-class specificity) */\n.groupRounded .first.itemShort::after {\n border-top-left-radius: var(--dimension-radius-half) !important;\n border-bottom-left-radius: var(--dimension-radius-half) !important;\n}\n\n/* Rounded group: last — right corners become pill (3-class specificity) */\n.groupRounded .last.itemShort::after {\n border-top-right-radius: var(--dimension-radius-half) !important;\n border-bottom-right-radius: var(--dimension-radius-half) !important;\n}\n\n/* ── Rounded: inner-edge padding correction ────────────────────────────────── */\n/*\n * Rounded buttons add `space-050` extra padding on each side.\n * In a group the inner-facing edge should use base (non-pill) padding instead.\n * These classes are injected by ButtonGroup for first/last/mid × size.\n * XS rounded has no extra padding so needs no correction.\n */\n\n/* MD — base padding: space-100 */\n.roundedFirstMD { padding-right: var(--dimension-space-100) !important; }\n.roundedLastMD { padding-left: var(--dimension-space-100) !important; }\n.roundedMidMD { padding-left: var(--dimension-space-100) !important; padding-right: var(--dimension-space-100) !important; }\n\n/* SM — base padding: space-075 */\n.roundedFirstSM { padding-right: var(--dimension-space-075) !important; }\n.roundedLastSM { padding-left: var(--dimension-space-075) !important; }\n.roundedMidSM { padding-left: var(--dimension-space-075) !important; padding-right: var(--dimension-space-075) !important; }\n\n/* LG — base padding: space-150 */\n.roundedFirstLG { padding-right: var(--dimension-space-150) !important; }\n.roundedLastLG { padding-left: var(--dimension-space-150) !important; }\n.roundedMidLG { padding-left: var(--dimension-space-150) !important; padding-right: var(--dimension-space-150) !important; }\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './ButtonGroup.module.css';\n\nexport interface ButtonGroupProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/**\n * Renders Button children flush side-by-side with a 1px divider between them.\n * Outer corners keep the button's own border-radius; inner corners are flattened.\n *\n * Individual button chrome (shadow/border) is suppressed — the group container\n * carries the elevation so it wraps the whole control as one visual unit.\n *\n * Divider behaviour by variant:\n * secondary / primary+none — full-height color-border-tertiary line\n * primary (with intent) — color-border-tertiary-on-{contrast}-background\n * ghost (secondary+none) — short centred line (icon/text height)\n *\n * Rounded groups: outer edges keep pill padding; inner edges revert to base padding.\n * Mix of intents is only valid when variant=\"secondary\"; primary groups must be\n * homogeneous (same intent + contrast on all items).\n */\nexport const ButtonGroup = ({ children, className }: ButtonGroupProps) => {\n const items = React.Children.toArray(children).filter(React.isValidElement);\n const count = items.length;\n\n // Read elevation + rounded from first child to drive the group container style.\n const firstEl = items[0] as React.ReactElement<Record<string, unknown>> | undefined;\n const firstProps = firstEl?.props as { variant?: string; elevation?: string; rounded?: boolean } | undefined;\n const firstVariant = firstProps?.variant ?? 'secondary';\n const firstElevation = firstProps?.elevation ?? (firstVariant === 'primary' ? 'none' : 'flat');\n const groupRounded = !!firstProps?.rounded;\n const groupElevKey = firstElevation.charAt(0).toUpperCase() + firstElevation.slice(1);\n\n return (\n <div\n className={cn(\n styles.group,\n (styles as Record<string, string>)[`group${groupElevKey}`],\n groupRounded && styles.groupRounded,\n className,\n )}\n role=\"group\"\n >\n {items.map((child, i) => {\n const el = child as React.ReactElement<Record<string, unknown>>;\n const p = el.props as {\n className?: string;\n variant?: string;\n elevation?: string;\n size?: string;\n intent?: string;\n contrast?: string;\n rounded?: boolean;\n icon?: unknown;\n label?: unknown;\n };\n\n const isFirst = i === 0;\n const isLast = i === count - 1;\n const isMid = !isFirst && !isLast;\n\n const variant = p.variant ?? 'secondary';\n const size = (p.size ?? 'md') as 'xs' | 'sm' | 'md' | 'lg';\n const contrast = p.contrast ?? 'bold';\n const intent = p.intent ?? 'brand';\n const isRounded = !!p.rounded;\n const isIconOnly = !!p.icon && !p.label;\n // Ghost: secondary button with elevation='none' (replaces old tertiary variant)\n const isGhost = variant === 'secondary' && (p.elevation ?? 'flat') === 'none';\n const isPrimary = variant === 'primary' && intent !== 'none';\n\n // Contrast class suffix — capitalised first letter\n const contrastKey = contrast.charAt(0).toUpperCase() + contrast.slice(1);\n\n // Size suffix for rounded padding correction — uppercase\n // XS rounded has no extra padding in Button so needs no correction\n const sizeKey = size.toUpperCase() as 'MD' | 'SM' | 'LG' | 'XS';\n const needsRoundedCorrection = isRounded && !isIconOnly && size !== 'xs';\n\n // Divider injected as a separate element so it's never affected by\n // the adjacent button's opacity (e.g. disabled state).\n const dividerClasses = cn(\n styles.divider,\n isGhost && styles.dividerGhost,\n isGhost && size === 'xs' && styles.dividerGhostXS,\n isGhost && size === 'sm' && styles.dividerGhostSM,\n isGhost && size === 'lg' && styles.dividerGhostLG,\n isPrimary && (styles as Record<string, string>)[`divider${contrastKey}`],\n );\n\n return (\n <React.Fragment key={i}>\n {i > 0 && <div className={dividerClasses} aria-hidden=\"true\" />}\n {React.cloneElement(el, {\n className: cn(\n p.className,\n styles.item,\n isFirst && styles.first,\n isLast && styles.last,\n isMid && styles.middle,\n\n // Ghost (secondary+elevation=none): ::after overlay gets 4px radius treatment\n isGhost && styles.itemShort,\n\n // Rounded: revert inner-edge padding to base (non-pill) value\n needsRoundedCorrection && isFirst && (styles as Record<string, string>)[`roundedFirst${sizeKey}`],\n needsRoundedCorrection && isLast && (styles as Record<string, string>)[`roundedLast${sizeKey}`],\n needsRoundedCorrection && isMid && (styles as Record<string, string>)[`roundedMid${sizeKey}`],\n ),\n })}\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n\nButtonGroup.displayName = 'ButtonGroup';\n","/* ==========================================================================\n ToggleButtonGroup — flush row of ToggleButton components\n ========================================================================== */\n\n.group {\n display: inline-flex;\n align-items: stretch;\n border-radius: var(--dimension-radius-050);\n position: relative;\n}\n\n/* Inset ring / highlight overlay — sits above button children so it isn't\n covered by their backgrounds. Outset shadow stays on the element itself. */\n.group::after {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n}\n\n/* ── Group-level elevation ──────────────────────────────────────────────── */\n/* Individual item chrome (shadow/border) is suppressed via .item below.\n The group container carries the elevation so it wraps the whole control. */\n\n/* Outset shadow on element; inset highlight on ::after (children would cover it otherwise) */\n.groupElevated { box-shadow: var(--effect-shadow-elevated-sm); }\n.groupElevated::after { box-shadow: var(--effect-highlight-elevated-sm); }\n\n/* Flat ring lives entirely on ::after — same reasoning as highlight */\n.groupFlat::after { box-shadow: inset 0 0 0 1px var(--color-border-tertiary); }\n\n.groupFloating { box-shadow: var(--effect-shadow-elevated-floating); }\n.groupFloating::after { box-shadow: var(--effect-highlight-elevated-floating); }\n/* groupNone = ghost — no shadow, no border */\n\n.groupRounded { border-radius: var(--dimension-radius-half); }\n\n/* ── Base item ─────────────────────────────────────────────────────────────── */\n\n.item {\n flex-shrink: 0;\n /* Suppress individual elevation so the group reads as one unit */\n box-shadow: none !important;\n /* Suppress noElevation individual border — divider handles separation */\n border: none !important;\n /* Suppress scale-on-press: transform would detach the divider from the\n adjacent button, creating a visible gap. Pressed state is still\n communicated via the ::after overlay colour. */\n}\n.item:active {\n transform: none !important;\n}\n\n/* ── Divider ────────────────────────────────────────────────────────────────\n * Rendered as a separate <div> between items so it is never part of any\n * button's stacking context — disabled (opacity: 0.5) or other state changes\n * on adjacent buttons cannot bleed through to the divider.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* Full-height divider (elevated / flat / floating).\n * Rendered as a separate element (independent of adjacent button opacity),\n * then nudged ±0.5px so it overlaps each neighbour and paints on top via\n * z-index — this lets the alpha token (rgb(0 0 0 / 0.1)) composite over\n * whatever fill the buttons carry (white, blue pressed state, etc.). */\n.divider {\n width: 1px;\n flex-shrink: 0;\n background-color: var(--color-border-tertiary);\n position: relative;\n z-index: 1;\n margin: 0 -0.5px;\n pointer-events: none;\n}\n\n/* Ghost (elevation=none): short centred divider at icon height */\n.dividerGhost { height: 20px; align-self: center; } /* md default */\n.dividerGhostXS { height: 12px; }\n.dividerGhostSM { height: 16px; }\n\n/* Ghost hover-fade: hide the divider on either side of a hovered ghost button */\n.item:hover + .dividerGhost,\n.dividerGhost:has(+ .item:hover) { opacity: 0; }\n\n/* Ghost pressed-state: hide the divider on either side of a selected button */\n.itemPressed + .dividerGhost,\n.dividerGhost:has(+ .itemPressed) { opacity: 0; }\n\n\n/* ── Ghost interaction states: rounded chips ──────────────────────────────────\n * Ghost items have no connecting chrome — hover/press overlay and selected\n * state always appear as independent rounded chips (4px on all corners).\n * Rounded groups: outer corners of first/last become pill; inner stay 4px.\n *\n * Uses explicit longhands throughout to avoid shorthand/longhand cascade\n * ordering ambiguity with the !important rules in .first / .last / .middle.\n * ─────────────────────────────────────────────────────────────────────────── */\n\n/* ::after hover/press overlay — all positions: 4px all corners.\n Uses .group as ancestor (2-class specificity) to reliably beat\n .first / .last / .middle (1-class) regardless of load order. */\n.group .itemShort::after {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* Selected chip — all positions: 4px all corners */\n.group .itemPressed {\n border-top-left-radius: var(--dimension-radius-050) !important;\n border-top-right-radius: var(--dimension-radius-050) !important;\n border-bottom-right-radius: var(--dimension-radius-050) !important;\n border-bottom-left-radius: var(--dimension-radius-050) !important;\n}\n\n/* ── Border radius: flatten only the inner-facing corners ──────────────────── */\n/* Outer corners keep the button's own radius — works for default + rounded */\n\n.first {\n border-top-right-radius: 0 !important;\n border-bottom-right-radius: 0 !important;\n}\n\n.last {\n border-top-left-radius: 0 !important;\n border-bottom-left-radius: 0 !important;\n}\n\n.middle {\n border-radius: 0 !important;\n}\n\n/* Rounded group: first — left corners become pill (3-class specificity) */\n.groupRounded .first.itemShort::after,\n.groupRounded .first.itemPressed {\n border-top-left-radius: var(--dimension-radius-half) !important;\n border-bottom-left-radius: var(--dimension-radius-half) !important;\n}\n\n/* Rounded group: last — right corners become pill (3-class specificity) */\n.groupRounded .last.itemShort::after,\n.groupRounded .last.itemPressed {\n border-top-right-radius: var(--dimension-radius-half) !important;\n border-bottom-right-radius: var(--dimension-radius-half) !important;\n}\n\n/* ── Rounded: inner-edge padding correction ────────────────────────────────── */\n/*\n * Rounded buttons add `space-050` extra padding on each side.\n * In a group the inner-facing edge should use base (non-pill) padding instead.\n * XS rounded has no extra padding so needs no correction.\n */\n\n/* MD — base padding: space-100 */\n.roundedFirstMD { padding-right: var(--dimension-space-100) !important; }\n.roundedLastMD { padding-left: var(--dimension-space-100) !important; }\n.roundedMidMD { padding-left: var(--dimension-space-100) !important; padding-right: var(--dimension-space-100) !important; }\n\n/* SM — base padding: space-075 */\n.roundedFirstSM { padding-right: var(--dimension-space-075) !important; }\n.roundedLastSM { padding-left: var(--dimension-space-075) !important; }\n.roundedMidSM { padding-left: var(--dimension-space-075) !important; padding-right: var(--dimension-space-075) !important; }\n","import React from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './ToggleButtonGroup.module.css';\n\nexport interface ToggleButtonGroupProps {\n children: React.ReactNode;\n className?: string;\n}\n\n/**\n * Renders ToggleButton children flush side-by-side with a 1px divider between them.\n * Outer corners keep the button's own border-radius; inner corners are flattened.\n *\n * Individual button chrome (shadow/border) is suppressed — the group container\n * carries the elevation so it wraps the whole control as one visual unit.\n *\n * Divider behaviour by elevation:\n * elevated / flat / floating — full-height color-border-tertiary line\n * none (ghost) — short centred line (icon/text height)\n *\n * Rounded groups: outer edges keep pill padding; inner edges revert to base padding.\n * Pressed state and onPressedChange are managed by the consumer on each ToggleButton.\n */\nexport const ToggleButtonGroup = ({ children, className }: ToggleButtonGroupProps) => {\n const items = React.Children.toArray(children).filter(React.isValidElement);\n const count = items.length;\n\n // Read elevation + rounded from first child to drive the group container style.\n const firstEl = items[0] as React.ReactElement<Record<string, unknown>> | undefined;\n const firstProps = firstEl?.props as { elevation?: string; rounded?: boolean } | undefined;\n const groupElevation = firstProps?.elevation ?? 'elevated';\n const groupRounded = !!firstProps?.rounded;\n const groupElevKey = groupElevation.charAt(0).toUpperCase() + groupElevation.slice(1);\n\n return (\n <div\n className={cn(\n styles.group,\n (styles as Record<string, string>)[`group${groupElevKey}`],\n groupRounded && styles.groupRounded,\n className,\n )}\n role=\"group\"\n >\n {items.map((child, i) => {\n const el = child as React.ReactElement<Record<string, unknown>>;\n const p = el.props as {\n className?: string;\n elevation?: string;\n size?: string;\n rounded?: boolean;\n pressed?: boolean;\n icon?: unknown;\n label?: unknown;\n };\n\n const isFirst = i === 0;\n const isLast = i === count - 1;\n const isMid = !isFirst && !isLast;\n\n const size = (p.size ?? 'md') as 'xs' | 'sm' | 'md';\n const isRounded = !!p.rounded;\n const isPressed = !!p.pressed;\n const isIconOnly = !!p.icon && !p.label;\n // Ghost: elevation='none' (no chrome) → short centred divider\n const isGhost = (p.elevation ?? 'elevated') === 'none';\n\n // XS rounded has no extra padding in ToggleButton so needs no correction\n const sizeKey = size.toUpperCase() as 'XS' | 'SM' | 'MD';\n const needsRoundedCorrection = isRounded && !isIconOnly && size !== 'xs';\n\n // Divider injected as a separate element so it's never affected by\n // the adjacent button's opacity (e.g. disabled state).\n const dividerClasses = cn(\n styles.divider,\n isGhost && styles.dividerGhost,\n isGhost && size === 'xs' && styles.dividerGhostXS,\n isGhost && size === 'sm' && styles.dividerGhostSM,\n );\n\n return (\n <React.Fragment key={i}>\n {i > 0 && <div className={dividerClasses} aria-hidden=\"true\" />}\n {React.cloneElement(el, {\n className: cn(\n p.className,\n styles.item,\n isFirst && styles.first,\n isLast && styles.last,\n isMid && styles.middle,\n\n // Ghost variant: ::after overlay gets 4px radius treatment\n isGhost && styles.itemShort,\n\n // Ghost + pressed: selected state background chip\n isGhost && isPressed && styles.itemPressed,\n\n // Rounded: revert inner-edge padding to base (non-pill) value\n needsRoundedCorrection && isFirst && (styles as Record<string, string>)[`roundedFirst${sizeKey}`],\n needsRoundedCorrection && isLast && (styles as Record<string, string>)[`roundedLast${sizeKey}`],\n needsRoundedCorrection && isMid && (styles as Record<string, string>)[`roundedMid${sizeKey}`],\n ),\n })}\n </React.Fragment>\n );\n })}\n </div>\n );\n};\n\nToggleButtonGroup.displayName = 'ToggleButtonGroup';\n","/* ==========================================================================\n Tag — hover/pressed via direct background-color + color-mix().\n No pseudo-element overlays.\n ========================================================================== */\n\n.tag {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--dimension-radius-050);\n box-sizing: border-box;\n color: var(--color-foreground-primary);\n position: relative;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n/* ==========================================================================\n Sizes\n md 28px — no size-350 token, expressed as 7/2 × base\n sm 20px — size-250\n xs 12px — size-150\n ========================================================================== */\n\n.sizeMd { height: calc(var(--dimension-size-base) * 7 / 2); padding: 0 var(--dimension-space-075); gap: 0; }\n.sizeSm { height: var(--dimension-size-250); padding: 0 var(--dimension-space-050); gap: 0; }\n.sizeXs { height: var(--dimension-size-150); padding: 0 var(--dimension-space-012); gap: 0; }\n\n/* ==========================================================================\n Rounded\n ========================================================================== */\n\n.rounded { border-radius: var(--dimension-radius-half); }\n\n/*\n * Pill padding correction — add space-050 to sides that have no content anchor.\n * Applied by Tag.tsx based on whether a leading icon or trailing remove is present:\n * no leading icon → roundedLeft{Size} (left side is bare label text)\n * no trailing icon → roundedRight{Size} (right side is bare label text)\n * Placed after size rules so same-specificity cascade wins correctly.\n */\n\n/* MD — base: space-075 */\n.roundedLeftMD { padding-left: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n.roundedRightMD { padding-right: calc(var(--dimension-space-075) + var(--dimension-space-050)); }\n\n/* SM — base: space-050 */\n.roundedLeftSM { padding-left: calc(var(--dimension-space-050) + var(--dimension-space-050)); }\n.roundedRightSM { padding-right: calc(var(--dimension-space-050) + var(--dimension-space-050)); }\n\n/* XS — base: space-012 (1px) */\n.roundedLeftXS { padding-left: calc(var(--dimension-space-012) + var(--dimension-space-050)); }\n.roundedRightXS { padding-right: calc(var(--dimension-space-012) + var(--dimension-space-050)); }\n\n/*\n * Icon-edge padding correction — when an icon (leading or remove) sits on a\n * side, that side's padding should match the top/bottom optical gap:\n * (height − icon_size) / 2\n *\n * md: (28 − 20) / 2 = 4px → space-050\n * sm: (20 − 16) / 2 = 2px → space-025\n * xs: (12 − 12) / 2 = 0px → 0\n *\n * Applied by Tag.tsx: iconLeft when Icon present, iconRight when removable.\n * Placed after size + rounded rules so same-specificity cascade wins.\n */\n.iconLeftMD { padding-left: var(--dimension-space-050); }\n.iconRightMD { padding-right: var(--dimension-space-050); }\n\n.iconLeftSM { padding-left: var(--dimension-space-025); }\n.iconRightSM { padding-right: var(--dimension-space-025); }\n\n.iconLeftXS { padding-left: 0; }\n.iconRightXS { padding-right: 0; }\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n}\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n}\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n}\n\n/* ==========================================================================\n Elevation\n none — filled intent bg, no border, no shadow (default)\n flat — transparent bg + intent-coloured border ring\n elevated — filled intent bg + elevated shadow\n ========================================================================== */\n\n/* elevationNone — no extra chrome needed, intent+contrast classes handle fill */\n\n.elevationFlat {\n background-color: transparent !important;\n box-shadow: inset 0 0 0 var(--dimension-stroke-width-015) currentColor;\n}\n\n/* Flat: no background — use on-surface fg tokens matched to the contrast level.\n The border ring is currentColor so it follows text color automatically.\n 3-class specificity beats the 2-class intent+contrast filled rules above. */\n\n.elevationFlat.intentNeutral.contrastBold { color: var(--color-foreground-bold-neutral); }\n.elevationFlat.intentBrand.contrastBold { color: var(--color-foreground-bold-brand); }\n.elevationFlat.intentAi.contrastBold { color: var(--color-foreground-bold-ai); }\n.elevationFlat.intentNegative.contrastBold { color: var(--color-foreground-bold-negative); }\n.elevationFlat.intentWarning.contrastBold { color: var(--color-foreground-bold-warning); }\n.elevationFlat.intentCaution.contrastBold { color: var(--color-foreground-bold-caution); }\n.elevationFlat.intentPositive.contrastBold { color: var(--color-foreground-bold-positive); }\n\n.elevationFlat.intentNeutral.contrastStrong { color: var(--color-foreground-strong-neutral); }\n.elevationFlat.intentBrand.contrastStrong { color: var(--color-foreground-strong-brand); }\n.elevationFlat.intentAi.contrastStrong { color: var(--color-foreground-strong-ai); }\n.elevationFlat.intentNegative.contrastStrong { color: var(--color-foreground-strong-negative); }\n.elevationFlat.intentWarning.contrastStrong { color: var(--color-foreground-strong-warning); }\n.elevationFlat.intentCaution.contrastStrong { color: var(--color-foreground-strong-caution); }\n.elevationFlat.intentPositive.contrastStrong { color: var(--color-foreground-strong-positive); }\n\n.elevationFlat.intentNeutral.contrastMedium { color: var(--color-foreground-medium-neutral); }\n.elevationFlat.intentBrand.contrastMedium { color: var(--color-foreground-medium-brand); }\n.elevationFlat.intentAi.contrastMedium { color: var(--color-foreground-medium-ai); }\n.elevationFlat.intentNegative.contrastMedium { color: var(--color-foreground-medium-negative); }\n.elevationFlat.intentWarning.contrastMedium { color: var(--color-foreground-medium-warning); }\n.elevationFlat.intentCaution.contrastMedium { color: var(--color-foreground-medium-caution); }\n.elevationFlat.intentPositive.contrastMedium { color: var(--color-foreground-medium-positive); }\n\n.elevationFlat.intentNeutral.contrastFaint { color: var(--color-foreground-faint-neutral); }\n.elevationFlat.intentBrand.contrastFaint { color: var(--color-foreground-faint-brand); }\n.elevationFlat.intentAi.contrastFaint { color: var(--color-foreground-faint-ai); }\n.elevationFlat.intentNegative.contrastFaint { color: var(--color-foreground-faint-negative); }\n.elevationFlat.intentWarning.contrastFaint { color: var(--color-foreground-faint-warning); }\n.elevationFlat.intentCaution.contrastFaint { color: var(--color-foreground-faint-caution); }\n.elevationFlat.intentPositive.contrastFaint { color: var(--color-foreground-faint-positive); }\n\n.elevationElevated { box-shadow: var(--effect-elevation-elevated-sm); }\n\n/* ==========================================================================\n Intent + contrast — strong\n ========================================================================== */\n\n.intentNeutral.contrastStrong { background-color: var(--color-background-strong-neutral); color: var(--color-foreground-medium-neutral); }\n.intentBrand.contrastStrong { background-color: var(--color-background-strong-brand); color: var(--color-foreground-medium-brand); }\n.intentAi.contrastStrong { background-color: var(--color-background-strong-ai); color: var(--color-foreground-medium-ai); }\n.intentNegative.contrastStrong { background-color: var(--color-background-strong-negative); color: var(--color-foreground-medium-negative); }\n.intentWarning.contrastStrong { background-color: var(--color-background-strong-warning); color: var(--color-foreground-medium-warning); }\n.intentCaution.contrastStrong { background-color: var(--color-background-strong-caution); color: var(--color-foreground-medium-caution); }\n.intentPositive.contrastStrong { background-color: var(--color-background-strong-positive); color: var(--color-foreground-medium-positive); }\n\n/* ==========================================================================\n Intent + contrast — bold\n ========================================================================== */\n\n.intentNeutral.contrastBold { background-color: var(--color-background-bold-neutral); color: var(--color-foreground-on-bold-background-primary); }\n.intentBrand.contrastBold { background-color: var(--color-background-bold-brand); color: var(--color-foreground-on-bold-background-primary); }\n.intentAi.contrastBold { background-color: var(--color-background-bold-ai); color: var(--color-foreground-on-bold-background-primary); }\n.intentNegative.contrastBold { background-color: var(--color-background-bold-negative); color: var(--color-foreground-on-bold-background-primary); }\n.intentWarning.contrastBold { background-color: var(--color-background-bold-warning); color: var(--color-foreground-on-bold-background-primary); }\n.intentCaution.contrastBold { background-color: var(--color-background-bold-caution); color: var(--color-foreground-on-bold-background-primary); }\n.intentPositive.contrastBold { background-color: var(--color-background-bold-positive); color: var(--color-foreground-on-bold-background-primary); }\n\n/* ==========================================================================\n Intent + contrast — medium\n ========================================================================== */\n\n.intentNeutral.contrastMedium { background-color: var(--color-background-medium-neutral); color: var(--color-foreground-strong-neutral); }\n.intentBrand.contrastMedium { background-color: var(--color-background-medium-brand); color: var(--color-foreground-strong-brand); }\n.intentAi.contrastMedium { background-color: var(--color-background-medium-ai); color: var(--color-foreground-strong-ai); }\n.intentNegative.contrastMedium { background-color: var(--color-background-medium-negative); color: var(--color-foreground-strong-negative); }\n.intentWarning.contrastMedium { background-color: var(--color-background-medium-warning); color: var(--color-foreground-strong-warning); }\n.intentCaution.contrastMedium { background-color: var(--color-background-medium-caution); color: var(--color-foreground-strong-caution); }\n.intentPositive.contrastMedium { background-color: var(--color-background-medium-positive); color: var(--color-foreground-strong-positive); }\n\n/* ==========================================================================\n Intent + contrast — faint\n ========================================================================== */\n\n.intentNeutral.contrastFaint { background-color: var(--color-background-faint-neutral); color: var(--color-foreground-bold-neutral); }\n.intentBrand.contrastFaint { background-color: var(--color-background-faint-brand); color: var(--color-foreground-bold-brand); }\n.intentAi.contrastFaint { background-color: var(--color-background-faint-ai); color: var(--color-foreground-bold-ai); }\n.intentNegative.contrastFaint { background-color: var(--color-background-faint-negative); color: var(--color-foreground-bold-negative); }\n.intentWarning.contrastFaint { background-color: var(--color-background-faint-warning); color: var(--color-foreground-bold-warning); }\n.intentCaution.contrastFaint { background-color: var(--color-background-faint-caution); color: var(--color-foreground-bold-caution); }\n.intentPositive.contrastFaint { background-color: var(--color-background-faint-positive); color: var(--color-foreground-bold-positive); }\n\n/* ==========================================================================\n Interactive (clickable / filter-chip)\n ========================================================================== */\n\n.interactive {\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n outline: none;\n}\n\n.interactive:hover { background-color: var(--_hover-bg); }\n.interactive:active { background-color: var(--_pressed-bg); }\n\n.interactive:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n/* ==========================================================================\n Pressed / selected (filter-chip active state)\n Always brand — same language as ToggleButton\n ========================================================================== */\n\n.tag.pressed {\n background-color: var(--color-background-faint-brand) !important;\n color: var(--color-foreground-bold-brand) !important;\n border-color: transparent !important;\n}\n\n/* ==========================================================================\n Remove button — keeps ::before overlay for its own isolated hit area\n ========================================================================== */\n\n.removable { gap: var(--dimension-space-025); }\n.sizeXs.removable { gap: 0; }\n\n.removeButton {\n padding: 0; margin: 0; border: none; background: none;\n display: flex; align-items: center; justify-content: center;\n cursor: pointer; color: inherit; flex-shrink: 0;\n position: relative; border-radius: var(--dimension-radius-050);\n}\n\n.removeButton::before {\n content: ''; position: absolute; inset: -2px;\n border-radius: var(--dimension-radius-025);\n background-color: transparent;\n transition: var(--effect-transition-interaction-background-short-2);\n pointer-events: none;\n}\n\n.removeButton:hover::before { background-color: var(--color-interaction-hover); }\n.removeButton:active::before { background-color: var(--color-interaction-pressed); }\n\n/* SM — 1px gap, inset -1px → 18×18 hover area */\n.sizeSm .removeButton::before { inset: -1px; border-radius: 3px; }\n\n/* XS — flush, inset 0 → 12×12 hover area matching tag radius */\n.sizeXs .removeButton::before { inset: 0; border-radius: var(--dimension-radius-050); }\n\n.rounded .removeButton,\n.rounded .removeButton::before { border-radius: var(--dimension-radius-half); }\n\n/* ==========================================================================\n Disabled\n ========================================================================== */\n\n.inactive { opacity: 0.5; pointer-events: none; cursor: not-allowed; }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { LabelWrap } from '@/components/LabelWrap';\nimport { Cross } from '@ds-mo/icons';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Tag.module.css';\n\nexport type TagIntent = 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';\nexport type TagContrast = 'strong' | 'bold' | 'medium' | 'faint';\nexport type TagElevation = 'none' | 'flat' | 'elevated';\nexport type TagSize = 'md' | 'sm' | 'xs';\nexport type TagBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface TagProps {\n label: string;\n intent?: TagIntent;\n contrast?: TagContrast;\n /**\n * Visual chrome level.\n * none — filled with intent bg, no border, no shadow [default]\n * flat — transparent bg + intent-coloured border ring\n * elevated — filled with intent bg + elevated shadow\n */\n elevation?: TagElevation;\n size?: TagSize;\n rounded?: boolean;\n /** Leading icon component. */\n icon?: IconComponent;\n removable?: boolean;\n onRemove?: () => void;\n /** Override the default Cross remove icon. */\n removeIcon?: IconComponent;\n maxWidth?: string | number;\n inactive?: boolean;\n /** Parent surface context. Adjusts hover tokens for tags on colored backgrounds. */\n background?: TagBackground;\n /** Makes the tag clickable. Pair with pressed/onPressedChange for filter-chip behaviour. */\n onClick?: () => void;\n pressed?: boolean;\n onPressedChange?: (pressed: boolean) => void;\n className?: string;\n}\n\nconst ICON_SIZE: Record<TagSize, number> = { md: 20, sm: 16, xs: 12 };\n\nconst TEXT_STYLE_MAP: Record<TagSize, string> = {\n md: 'text-body-medium',\n sm: 'text-body-small',\n xs: 'text-caption',\n};\n\nexport const Tag = forwardRef<HTMLDivElement, TagProps>(\n (\n {\n label,\n intent = 'neutral',\n contrast = 'faint',\n elevation = 'none',\n size = 'md',\n rounded = false,\n icon: Icon,\n removable = false,\n onRemove,\n removeIcon: RemoveIcon,\n maxWidth,\n inactive = false,\n background,\n onClick,\n pressed,\n onPressedChange,\n className,\n },\n ref\n ) => {\n const isInteractive = !!onClick || !!onPressedChange;\n const hasRemove = removable && !!onRemove;\n const iconSize = ICON_SIZE[size];\n const textStyle = TEXT_STYLE_MAP[size];\n const elevKey = elevation.charAt(0).toUpperCase() + elevation.slice(1);\n const sizeKey = size.toUpperCase() as 'MD' | 'SM' | 'XS';\n\n const classes = cn(\n styles.tag,\n styles[`intent${intent.charAt(0).toUpperCase() + intent.slice(1)}`],\n styles[`contrast${contrast.charAt(0).toUpperCase() + contrast.slice(1)}`],\n styles[`elevation${elevKey}`],\n styles[`size${size.charAt(0).toUpperCase() + size.slice(1)}`],\n rounded && styles.rounded,\n // Pill padding correction — extra space-050 on bare sides (no content anchor)\n rounded && !Icon && (styles as Record<string, string>)[`roundedLeft${sizeKey}`],\n rounded && !hasRemove && (styles as Record<string, string>)[`roundedRight${sizeKey}`],\n // Icon-edge correction — reduce padding to (height − icon) / 2 on icon sides\n !!Icon && (styles as Record<string, string>)[`iconLeft${sizeKey}`],\n hasRemove && (styles as Record<string, string>)[`iconRight${sizeKey}`],\n removable && styles.removable,\n isInteractive && styles.interactive,\n background && background !== 'faint' && styles[\n background === 'always-dark' ? 'onAlwaysDark'\n : `on${background.charAt(0).toUpperCase() + background.slice(1)}`\n ],\n inactive && styles.inactive,\n pressed && styles.pressed,\n className,\n );\n\n const style = maxWidth != null\n ? { maxWidth: typeof maxWidth === 'number' ? `${maxWidth}px` : maxWidth }\n : undefined;\n\n const handleInteract = isInteractive && !inactive\n ? () => {\n onPressedChange?.(!pressed);\n onClick?.();\n }\n : undefined;\n\n const handleKeyDown = isInteractive && !inactive\n ? (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onPressedChange?.(!pressed);\n onClick?.();\n }\n }\n : undefined;\n\n // Rendered as <div role=\"button\"> rather than a native <button> because\n // removable tags contain an inner <button> for the remove affordance, and\n // nesting <button> inside <button> is invalid HTML.\n return (\n <div\n ref={ref}\n className={classes}\n style={style}\n onClick={handleInteract}\n onKeyDown={handleKeyDown}\n role={isInteractive ? 'button' : undefined}\n tabIndex={isInteractive ? (inactive ? -1 : 0) : undefined}\n aria-pressed={isInteractive && pressed !== undefined ? !!pressed : undefined}\n aria-disabled={inactive || undefined}\n >\n {Icon && <Icon size={iconSize} />}\n <LabelWrap size={size}>\n <Text variant={textStyle as never} as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </LabelWrap>\n {removable && onRemove && (\n <button\n type=\"button\"\n className={styles.removeButton}\n onClick={(e) => { e.stopPropagation(); onRemove(); }}\n aria-label={`Remove ${label}`}\n tabIndex={-1}\n >\n {RemoveIcon ? <RemoveIcon size={iconSize} /> : <Cross size={iconSize} />}\n </button>\n )}\n </div>\n );\n }\n);\n\nTag.displayName = 'Tag';\n",".badge {\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n}\n","import React from 'react';\nimport { Text } from '@/components/Text';\nimport styles from './Badge.module.css';\n\nexport interface BadgeProps {\n count: number;\n isSelected?: boolean;\n className?: string;\n /**\n * Accessible label announced by screen readers. Takes precedence over `labelFormat`.\n * Provide this when the badge has a specific meaning (e.g. `\"3 unread messages\"`).\n */\n 'aria-label'?: string;\n /**\n * Formats the accessible label from the count. Used when `aria-label` is not provided.\n * Defaults to returning the count as a string.\n */\n labelFormat?: (count: number) => string;\n}\n\nexport const Badge: React.FC<BadgeProps> = ({\n count,\n isSelected = false,\n className,\n 'aria-label': ariaLabel,\n labelFormat,\n}) => {\n if (count === 0) return null;\n const displayText = count > 9 ? '+' : count.toString();\n const accessibleLabel = ariaLabel ?? labelFormat?.(count) ?? String(count);\n return (\n <span className={`${styles.badge} ${className || ''}`} aria-label={accessibleLabel}>\n <Text variant=\"text-caption-emphasis\" as=\"span\" color={isSelected ? 'primary' : 'secondary'}>\n {displayText}\n </Text>\n </span>\n );\n};\n\nBadge.displayName = 'Badge';\n",".toggle {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n width: var(--dimension-size-400);\n height: var(--dimension-size-250);\n padding: 0 var(--dimension-space-025);\n border: none;\n border-radius: var(--dimension-radius-half);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n outline: none;\n flex-shrink: 0;\n background-color: var(--color-background-medium-neutral);\n box-shadow: var(--effect-highlight-depressed-sm);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.toggle::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n box-shadow: var(--effect-shadow-depressed-sm);\n pointer-events: none;\n}\n\n.toggle:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-space-025);\n}\n\n.checked {\n background-color: var(--color-foreground-bold-brand) !important;\n}\n\n.thumb {\n position: relative;\n flex-shrink: 0;\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-half);\n box-shadow: var(--effect-elevation-elevated-sm);\n transition: transform var(--effect-motion-short-2);\n transform: translateX(0);\n z-index: 1;\n}\n\n.thumb::after {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: inherit;\n transition: var(--effect-transition-interaction-background-instant);\n pointer-events: none;\n}\n\n.toggle:hover:not(.inactive) .thumb::after {\n background-color: var(--color-interaction-hover);\n}\n\n.toggle:active:not(.inactive) .thumb::after {\n background-color: var(--color-interaction-pressed);\n}\n\n.checked .thumb {\n transform: translateX(var(--dimension-offset-150));\n}\n\n.toggle:active:not(.inactive) .thumb {\n transform: translateX(0) scale(var(--dimension-scale-subtle)) !important;\n transition: transform var(--effect-motion-instant);\n}\n\n.checked.toggle:active:not(.inactive) .thumb {\n transform: translateX(var(--dimension-offset-150)) scale(var(--dimension-scale-subtle)) !important;\n transition: transform var(--effect-motion-instant);\n}\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Toggle.module.css';\n\ninterface ToggleBaseProps {\n checked?: boolean;\n onChange?: (checked: boolean) => void;\n inactive?: boolean;\n className?: string;\n}\n\nexport type ToggleProps = ToggleBaseProps &\n (\n | { 'aria-label': string; 'aria-labelledby'?: never }\n | { 'aria-label'?: never; 'aria-labelledby': string }\n );\n\nexport const Toggle = forwardRef<HTMLButtonElement, ToggleProps>(\n (\n {\n checked = false,\n onChange,\n inactive = false,\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n },\n ref,\n ) => {\n const handleClick = () => {\n if (inactive) return;\n onChange?.(!checked);\n };\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledby}\n disabled={inactive}\n className={cn(styles.toggle, checked && styles.checked, inactive && styles.inactive, className)}\n onClick={handleClick}\n >\n <span className={styles.thumb} />\n </button>\n );\n },\n);\n\nToggle.displayName = 'Toggle';\n",".checkbox {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n height: var(--dimension-size-400);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border-radius: var(--dimension-radius-075);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.checkbox:hover { background-color: var(--color-interaction-hover); }\n.checkbox:active { background-color: var(--color-interaction-pressed); }\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* Fallback checkbox box (when no icon components provided) */\n.box {\n width: 20px;\n height: 20px;\n border: 1.5px solid var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-050);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all var(--effect-motion-short-2);\n}\n\n.boxChecked {\n background-color: var(--color-foreground-primary);\n border-color: var(--color-foreground-primary);\n}\n\n.checkmark {\n color: var(--color-foreground-on-bold-background-primary);\n font-size: 14px;\n line-height: 1;\n font-weight: 700;\n}\n","import React, { forwardRef, useId } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Checkbox.module.css';\n\nexport interface CheckboxProps {\n label: string;\n checked?: boolean;\n indeterminate?: boolean;\n onChange?: (checked: boolean) => void;\n inactive?: boolean;\n className?: string;\n /** Icon for checked state. */\n checkedIcon?: IconComponent;\n /** Icon for unchecked state. */\n uncheckedIcon?: IconComponent;\n /** Icon for indeterminate state. */\n indeterminateIcon?: IconComponent;\n}\n\nexport const Checkbox = forwardRef<HTMLDivElement, CheckboxProps>(\n (\n {\n label,\n checked = false,\n indeterminate = false,\n onChange,\n inactive = false,\n className,\n checkedIcon: CheckedIcon,\n uncheckedIcon: UncheckedIcon,\n indeterminateIcon: IndeterminateIcon,\n },\n ref\n ) => {\n const labelId = useId();\n const handleClick = () => {\n if (!inactive) onChange?.(!checked);\n };\n\n const iconColor = indeterminate || checked ? 'var(--color-foreground-primary)' : 'var(--color-foreground-secondary)';\n const Icon = indeterminate ? IndeterminateIcon : checked ? CheckedIcon : UncheckedIcon;\n\n return (\n <div\n ref={ref}\n role=\"checkbox\"\n aria-checked={indeterminate ? 'mixed' : checked}\n aria-disabled={inactive || undefined}\n aria-labelledby={labelId}\n data-inactive={inactive || undefined}\n tabIndex={inactive ? -1 : 0}\n className={cn(styles.checkbox, inactive && styles.inactive, className)}\n onClick={handleClick}\n onKeyDown={e => { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); handleClick(); } }}\n >\n {Icon ? <Icon size={20} color={iconColor} /> : (\n <span className={cn(styles.box, (checked || indeterminate) && styles.boxChecked)}>\n {(checked || indeterminate) && <span className={styles.checkmark}>{indeterminate ? '−' : '✓'}</span>}\n </span>\n )}\n <Text id={labelId} variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </div>\n );\n }\n);\n\nCheckbox.displayName = 'Checkbox';\n",".container {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n width: 100%;\n}\n\n.wrapper {\n width: 100%;\n height: var(--dimension-size-400);\n display: flex;\n align-items: center;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-depressed-sm);\n box-sizing: border-box;\n}\n\n.wrapper:focus-within {\n box-shadow: inset 0 0 0 1.25px var(--color-foreground-bold-brand);\n}\n\n.wrapperError {\n box-shadow: inset 0 0 0 1.25px var(--color-border-bold-negative);\n}\n\n.wrapperError:focus-within {\n box-shadow: inset 0 0 0 1.25px var(--color-border-bold-negative);\n}\n\n.errorText {\n font-size: var(--typography-fontsize-sm);\n line-height: var(--typography-lineheight-sm);\n color: var(--color-foreground-bold-negative);\n}\n\n.row {\n display: flex;\n align-items: center;\n width: 100%;\n height: 100%;\n gap: var(--dimension-space-050);\n}\n\n.input {\n flex: 1;\n min-width: 0;\n height: 100%;\n padding: 0 var(--dimension-space-100);\n background: transparent;\n border: none;\n outline: none;\n font-family: inherit;\n font-size: var(--typography-fontsize-md);\n line-height: var(--typography-lineheight-md);\n color: var(--color-foreground-primary);\n border-radius: var(--dimension-radius-075);\n -webkit-appearance: none;\n appearance: none;\n}\n\n.input:disabled { opacity: 0.5; cursor: not-allowed; }\n.input::placeholder { color: var(--color-foreground-secondary); }\n.input:focus::placeholder { color: var(--color-foreground-tertiary); }\n\n/* Hide native search clear */\n.input[type=\"search\"]::-webkit-search-cancel-button,\n.input[type=\"search\"]::-webkit-search-decoration { display: none; }\n\n.clearButton {\n flex-shrink: 0;\n margin-right: var(--dimension-space-050);\n padding: var(--dimension-space-050);\n border: none;\n background: none;\n cursor: pointer;\n color: var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-050);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.clearButton:hover { background-color: var(--color-interaction-hover); }\n\n.suffix {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n margin-right: var(--dimension-space-050);\n}\n","import React, { forwardRef, useEffect, useId } from 'react';\nimport { cn } from '@/utils/cn';\nimport type { IconComponent } from '@/types/icons';\nimport styles from './Input.module.css';\n\nexport type InputType = 'text' | 'email' | 'tel' | 'url' | 'search' | 'password';\n\nexport interface InputProps {\n value: string;\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;\n id?: string;\n placeholder?: string;\n autoFocus?: boolean;\n className?: string;\n type?: InputType;\n inactive?: boolean;\n onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;\n /** Content rendered inside the field on the right. */\n suffix?: React.ReactNode;\n /** Icon for clear button (search type). */\n clearIcon?: IconComponent;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n /** Marks the input as invalid; sets `aria-invalid` and applies error styling. */\n error?: boolean;\n /** Message rendered below the input when `error` is true; auto-linked via `aria-describedby`. */\n errorMessage?: string;\n}\n\nconst isDevEnv = (): boolean => {\n const meta = import.meta as { env?: { DEV?: boolean } };\n return Boolean(meta.env?.DEV);\n};\n\nexport const Input = forwardRef<HTMLDivElement, InputProps>(\n (\n {\n value,\n onChange,\n id,\n placeholder,\n autoFocus = false,\n className,\n type = 'text',\n inactive = false,\n onKeyDown,\n suffix,\n clearIcon: ClearIcon,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n error = false,\n errorMessage,\n },\n ref\n ) => {\n const reactId = useId();\n const errorId = `${reactId}-error`;\n const showClear = type === 'search' && value.length > 0 && !inactive;\n const showErrorMessage = error && Boolean(errorMessage);\n\n const describedBy =\n [ariaDescribedBy, showErrorMessage ? errorId : undefined].filter(Boolean).join(' ') ||\n undefined;\n\n useEffect(() => {\n if (!isDevEnv()) return;\n if (!id && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[@ds-mo/ui] <Input> is missing an accessible name. Provide one of: `id` (paired with a <label htmlFor>), `aria-label`, or `aria-labelledby`.'\n );\n }\n }, [id, ariaLabel, ariaLabelledBy]);\n\n const handleClear = () => {\n onChange({ target: { value: '' } } as React.ChangeEvent<HTMLInputElement>);\n };\n\n return (\n <div className={styles.container}>\n <div ref={ref} className={cn(styles.wrapper, error && styles.wrapperError, className)}>\n <div className={styles.row}>\n <input\n type={type}\n id={id}\n value={value}\n onChange={onChange}\n onKeyDown={onKeyDown}\n placeholder={placeholder}\n className={styles.input}\n autoFocus={autoFocus}\n disabled={inactive}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={describedBy}\n aria-invalid={error || undefined}\n />\n {showClear && (\n <button type=\"button\" className={styles.clearButton} onClick={handleClear} aria-label=\"Clear\">\n {ClearIcon ? <ClearIcon size={16} /> : <span aria-hidden>&times;</span>}\n </button>\n )}\n {suffix && <div className={styles.suffix}>{suffix}</div>}\n </div>\n </div>\n {showErrorMessage && (\n <div id={errorId} role=\"alert\" className={styles.errorText}>\n {errorMessage}\n </div>\n )}\n </div>\n );\n }\n);\n\nInput.displayName = 'Input';\n",".field { display: flex; flex-direction: column; gap: var(--dimension-space-050); width: 100%; }\n.labelRow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--dimension-space-050); }\n\n.track {\n position: relative; width: 100%; height: var(--dimension-size-400);\n padding: 0 var(--dimension-space-025); border-radius: var(--dimension-radius-075); cursor: pointer; -webkit-user-select: none;\n user-select: none;\n}\n\n.trackInner {\n position: absolute; inset: 0; border-radius: inherit;\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-depressed-sm); pointer-events: none; z-index: 1;\n}\n\n.fillTrack {\n position: absolute; top: var(--dimension-space-025); right: 0; bottom: var(--dimension-space-025); left: 0;\n z-index: 1; pointer-events: none;\n}\n\n.fill {\n position: absolute; left: var(--dimension-space-025); top: 0; bottom: 0;\n width: max(0px, calc((var(--slider-pct, 0) / 100) * (100% - var(--dimension-size-150)) - var(--dimension-space-025)));\n background-color: var(--color-background-bold-brand);\n box-shadow: var(--effect-elevation-elevated-sm);\n border-radius: var(--dimension-radius-050);\n transition: opacity var(--effect-motion-short-2);\n pointer-events: none;\n}\n\n.trackAtMin .fill { opacity: 0; }\n\n.thumb {\n position: absolute; top: 0; bottom: 0;\n left: calc((var(--slider-pct, 0) / 100) * (100% - var(--dimension-size-150)));\n width: var(--dimension-size-150); padding: var(--dimension-space-025);\n box-sizing: border-box; pointer-events: none; z-index: 2;\n}\n\n.thumb::before {\n content: ''; position: absolute; inset: var(--dimension-space-025);\n background-color: var(--color-background-primary);\n box-shadow: var(--effect-elevation-elevated-sm);\n border-radius: var(--dimension-radius-050);\n}\n\n.thumb::after {\n content: ''; position: absolute; inset: var(--dimension-space-025);\n background-color: transparent; border-radius: var(--dimension-radius-050);\n transition: var(--effect-transition-interaction-background-instant);\n}\n\n.track:hover:not(.trackInactive) .thumb::after { background-color: var(--color-interaction-hover); }\n.track:active:not(.trackInactive) .thumb::after { background-color: var(--color-interaction-pressed); }\n\n.trackInactive { cursor: not-allowed; opacity: 0.5; }\n\n.input {\n position: absolute; inset: 0; width: 100%; height: 100%;\n margin: 0; padding: 0; opacity: 0; cursor: pointer;\n -webkit-appearance: none; appearance: none; outline: none; z-index: 3;\n}\n\n.input:disabled { cursor: not-allowed; }\n.input:hover { cursor: grab; }\n.input:active { cursor: grabbing; }\n","import React, { forwardRef, useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Slider.module.css';\n\nexport interface SliderProps {\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n label: string;\n id?: string;\n inactive?: boolean;\n className?: string;\n /** Human-readable text for assistive tech when the numeric value alone isn't meaningful (e.g. \"Low\", \"Medium\", \"High\"). Maps to `aria-valuetext`. */\n valueText?: string;\n}\n\nexport const Slider = forwardRef<HTMLDivElement, SliderProps>(\n ({ value, onChange, min = 0, max = 100, step = 1, label, id: idProp, inactive = false, className, valueText }, ref) => {\n const generatedId = useId();\n const id = idProp ?? generatedId;\n const containerRef = useRef<HTMLDivElement>(null);\n const [pct, setPct] = useState(() => {\n const range = max - min;\n return range === 0 ? 0 : Math.round(((value - min) / range) * 100);\n });\n\n const sync = useCallback(() => {\n const range = max - min;\n setPct(range === 0 ? 0 : Math.round(((value - min) / range) * 100));\n }, [value, min, max]);\n\n useEffect(() => { sync(); }, [sync]);\n\n const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {\n onChange(Number(e.target.value));\n };\n\n return (\n <div ref={ref} className={cn(styles.field, className)}>\n <div className={styles.labelRow}>\n <Text variant=\"text-body-small-emphasis\" as=\"label\" htmlFor={id}>{label}</Text>\n <Text variant=\"text-body-small-emphasis\" as=\"span\">{value}</Text>\n </div>\n <div\n ref={containerRef}\n className={cn(styles.track, inactive && styles.trackInactive, pct === 0 && styles.trackAtMin)}\n style={{ '--slider-pct': pct } as React.CSSProperties}\n >\n <div className={styles.trackInner}>\n <div className={styles.fillTrack}><div className={styles.fill} /></div>\n <div className={styles.thumb} />\n </div>\n <input\n type=\"range\"\n id={id}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={handleInput}\n disabled={inactive}\n className={styles.input}\n aria-valuetext={valueText}\n />\n </div>\n </div>\n );\n }\n);\n\nSlider.displayName = 'Slider';\n",".field {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n}\n","import React, { forwardRef, useId, isValidElement, cloneElement } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Field.module.css';\n\nexport interface FieldProps {\n label: string;\n children: React.ReactNode;\n id?: string;\n className?: string;\n}\n\nexport const Field = forwardRef<HTMLDivElement, FieldProps>(\n ({ label, children, id, className }, ref) => {\n const generatedId = useId();\n const fieldId = id ?? generatedId;\n\n let content = children;\n if (isValidElement(children)) {\n const childProps = children.props as { id?: string };\n if (childProps.id === undefined) {\n content = cloneElement(children as React.ReactElement<{ id?: string }>, { id: fieldId });\n }\n }\n\n return (\n <div ref={ref} className={cn(styles.field, className)}>\n <Text variant=\"text-body-small-emphasis\" as=\"label\" htmlFor={fieldId}>{label}</Text>\n {content}\n </div>\n );\n }\n);\n\nField.displayName = 'Field';\n",".backdrop {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-200);\n background-color: var(--color-background-shade);\n backdrop-filter: blur(var(--effect-blur-sm));\n -webkit-backdrop-filter: blur(var(--effect-blur-sm));\n animation: modalBackdropFadeIn var(--effect-motion-short-2) forwards;\n z-index: 9999;\n}\n\n.backdrop.closing {\n animation: modalBackdropFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes modalBackdropFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes modalBackdropFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.dialog {\n display: flex;\n flex-direction: column;\n max-height: calc(100vh - 32px);\n overflow: hidden;\n animation: modalDialogFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.backdrop.closing .dialog {\n animation: modalDialogFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes modalDialogFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes modalDialogFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.header {\n padding: var(--dimension-space-200) var(--dimension-space-200) var(--dimension-space-100) var(--dimension-space-200);\n}\n\n.subtitle {\n margin-top: var(--dimension-space-100);\n text-wrap: balance;\n}\n\n.body {\n padding: var(--dimension-space-100) var(--dimension-space-200);\n overflow-y: auto;\n}\n\n.footer {\n padding: var(--dimension-space-100) var(--dimension-space-200) var(--dimension-space-200) var(--dimension-space-200);\n}\n","import React, { useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport styles from './Modal.module.css';\n\nexport type ModalWidth = 'sm' | 'md' | 'lg';\n\nconst WIDTH_MAP: Record<ModalWidth, string> = {\n sm: 'var(--dimension-modal-width-sm, 400px)',\n md: 'var(--dimension-modal-width-md, 560px)',\n lg: 'var(--dimension-modal-width-lg, 720px)',\n};\n\nconst CLOSE_ANIMATION_MS = 220;\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n 'iframe',\n 'object',\n 'embed',\n '[contenteditable=\"true\"]',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(',');\n\nconst getFocusableElements = (root: HTMLElement): HTMLElement[] => {\n const nodes = root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR);\n return Array.from(nodes).filter(\n (el) => !el.hasAttribute('disabled') && el.getAttribute('aria-hidden') !== 'true'\n );\n};\n\nexport interface ModalProps {\n isOpen: boolean;\n onClose: () => void;\n title: string;\n subtitle?: React.ReactNode;\n children: React.ReactNode;\n footer?: React.ReactNode;\n width?: ModalWidth | string;\n bodyClassName?: string;\n initialFocus?: React.RefObject<HTMLElement>;\n}\n\nexport const Modal: React.FC<ModalProps> = ({\n isOpen,\n onClose,\n title,\n subtitle,\n children,\n footer,\n width = 'md',\n bodyClassName,\n initialFocus,\n}) => {\n const dialogRef = useRef<HTMLDivElement>(null);\n const previouslyFocusedRef = useRef<HTMLElement | null>(null);\n const titleId = useId();\n const subtitleId = useId();\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(isOpen);\n\n const resolvedWidth = useMemo(() => {\n if (width === 'sm' || width === 'md' || width === 'lg') {\n return WIDTH_MAP[width];\n }\n return width;\n }, [width]);\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n setIsClosing(false);\n } else if (shouldRender) {\n setIsClosing(true);\n const timer = setTimeout(() => {\n setShouldRender(false);\n setIsClosing(false);\n }, CLOSE_ANIMATION_MS);\n return () => clearTimeout(timer);\n }\n }, [isOpen, shouldRender]);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, onClose]);\n\n useEffect(() => {\n if (!isOpen || !shouldRender) return;\n previouslyFocusedRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n const id = requestAnimationFrame(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (initialFocus?.current) {\n initialFocus.current.focus();\n return;\n }\n const focusables = getFocusableElements(dialog);\n if (focusables.length > 0) {\n focusables[0].focus();\n } else {\n dialog.focus();\n }\n });\n return () => {\n cancelAnimationFrame(id);\n const previous = previouslyFocusedRef.current;\n if (previous && document.contains(previous)) {\n previous.focus();\n }\n previouslyFocusedRef.current = null;\n };\n }, [isOpen, shouldRender, initialFocus]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key !== 'Tab') return;\n const dialog = dialogRef.current;\n if (!dialog) return;\n const focusables = getFocusableElements(dialog);\n if (focusables.length === 0) {\n e.preventDefault();\n dialog.focus();\n return;\n }\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey) {\n if (active === first || active === dialog || !dialog.contains(active)) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (active === last || !dialog.contains(active)) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n\n if (!shouldRender) return null;\n\n const describedById = subtitle != null ? subtitleId : undefined;\n\n return createPortal(\n <div\n className={`${styles.backdrop} ${isClosing ? styles.closing : ''}`}\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n onKeyDown={handleKeyDown}\n >\n <Surface\n ref={dialogRef}\n background=\"primary\"\n elevation=\"floating\"\n radius=\"var(--dimension-radius-275, 22px)\"\n className={styles.dialog}\n style={{ width: `min(${resolvedWidth}, calc(100vw - 32px))` }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby={titleId}\n aria-describedby={describedById}\n tabIndex={-1}\n >\n <div className={styles.header}>\n <Text id={titleId} as=\"h2\" variant=\"text-title-small\">\n {title}\n </Text>\n {subtitle != null && (\n <div id={subtitleId} className={styles.subtitle}>\n {subtitle}\n </div>\n )}\n </div>\n <div className={`${styles.body} ${bodyClassName ?? ''}`.trim()}>\n {children}\n </div>\n {footer != null && (\n <div className={styles.footer}>{footer}</div>\n )}\n </Surface>\n </div>,\n document.body\n );\n};\n\nModal.displayName = 'Modal';\n",".menuItem {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n border: none;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n width: 100%;\n min-height: var(--dimension-size-400);\n}\n\n.menuItem:has(.subtext) { align-items: flex-start; }\n\n.iconPrefix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.menuItemSelected .iconPrefix { color: var(--color-foreground-primary); }\n\n.content {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.label { color: var(--color-foreground-secondary); }\n.menuItem:has(.subtext) .label { color: var(--color-foreground-primary); }\n.menuItemSelected .label { color: var(--color-foreground-primary) !important; }\n.menuItemLabelTertiary .label, .menuItemLabelTertiary .iconPrefix { color: var(--color-foreground-tertiary); }\n.menuItemNegative .label { color: var(--color-foreground-bold-negative) !important; }\n\n.subtext { color: var(--color-foreground-secondary); line-height: 1.4; }\n\n.menuItemInactive { opacity: 0.5; cursor: default; pointer-events: none; }\n\n.menuItemActive { background-color: var(--color-interaction-hover); }\n\n.toggleSuffix { flex-shrink: 0; display: flex; align-items: center; }\n\n.toggle {\n width: calc(var(--dimension-size-400) + var(--dimension-size-050));\n height: var(--dimension-size-250);\n background-color: var(--color-background-translucent);\n border-radius: var(--dimension-radius-125);\n position: relative;\n transition: var(--effect-transition-interaction-background-short-2);\n}\n\n.toggleOn { background-color: var(--color-background-medium-brand); }\n\n.toggleThumb {\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n background-color: var(--color-foreground-on-bold-background-primary);\n border-radius: 50%;\n position: absolute;\n top: var(--dimension-space-025);\n left: var(--dimension-space-025);\n transition: transform var(--effect-motion-short-2);\n}\n\n.toggleOn .toggleThumb { transform: translateX(var(--dimension-offset-200)); }\n\n.checkSuffix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-primary);\n}\n\n.chevronSuffix {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.menuItemSelected .chevronSuffix { color: var(--color-foreground-primary); }\n","import React, { forwardRef } from 'react';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport type { IconComponent } from '@/types';\nimport styles from './MenuItem.module.css';\n\nexport type MenuItemSelectionStyle = 'highlight' | 'radio' | 'noOverlay';\n\nexport interface MenuItemProps {\n label: string;\n onClick: () => void;\n isSelected?: boolean;\n isInactive?: boolean;\n icon?: IconComponent;\n labelColor?: 'primary' | 'secondary' | 'tertiary';\n subtext?: string;\n showToggle?: boolean;\n toggleValue?: boolean;\n intent?: 'negative';\n selectionStyle?: MenuItemSelectionStyle;\n showTrailingChevron?: boolean;\n checkIcon?: IconComponent;\n chevronIcon?: IconComponent;\n /** Override the implicit role. Defaults derive from menu context: `menuitem`, `menuitemcheckbox` (showToggle), or `menuitemradio` (radio selectionStyle). Pass `'option'` for listbox usage. */\n role?: string;\n /** Element id — required when used as an `option` referenced by `aria-activedescendant`. */\n id?: string;\n /** Maps to `aria-selected`. Used when role is `option`. */\n ariaSelected?: boolean;\n /** Visual highlight for keyboard \"active\" cursor (separate from selection state). */\n isActive?: boolean;\n /** Override default tabIndex (e.g. -1 for listbox options driven by aria-activedescendant). */\n tabIndex?: number;\n onKeyDown?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;\n onFocus?: (e: React.FocusEvent<HTMLButtonElement>) => void;\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(\n ({\n label,\n onClick,\n isSelected = false,\n isInactive = false,\n icon: Icon,\n labelColor,\n subtext,\n showToggle = false,\n toggleValue = false,\n intent,\n selectionStyle = 'highlight',\n showTrailingChevron = false,\n checkIcon: CheckIcon,\n chevronIcon: ChevronIcon,\n role,\n id,\n ariaSelected,\n isActive = false,\n tabIndex,\n onKeyDown,\n onFocus,\n }, ref) => {\n const useRadioStyle = selectionStyle === 'radio';\n const noOverlay = selectionStyle === 'noOverlay' || useRadioStyle;\n const showSelectedOverlay = isSelected && !noOverlay;\n\n const resolvedRole = role ?? (\n showToggle ? 'menuitemcheckbox'\n : useRadioStyle ? 'menuitemradio'\n : 'menuitem'\n );\n\n const ariaCheckedValue: boolean | undefined = role\n ? undefined\n : resolvedRole === 'menuitemcheckbox'\n ? !!toggleValue\n : resolvedRole === 'menuitemradio'\n ? !!isSelected\n : undefined;\n\n const ariaSelectedValue: boolean | undefined = role && ariaSelected !== undefined ? ariaSelected : undefined;\n\n return (\n <Surface\n ref={ref as React.Ref<HTMLElement>}\n as=\"button\"\n interactive={!isInactive}\n selected={showSelectedOverlay}\n radius=\"sm\"\n className={`${styles.menuItem} ${isSelected ? styles.menuItemSelected : ''} ${isInactive ? styles.menuItemInactive : ''} ${intent === 'negative' ? styles.menuItemNegative : ''} ${labelColor === 'tertiary' ? styles.menuItemLabelTertiary : ''} ${isActive ? styles.menuItemActive : ''}`}\n onClick={onClick}\n type=\"button\"\n inactive={isInactive}\n role={resolvedRole}\n id={id}\n aria-checked={ariaCheckedValue}\n aria-selected={ariaSelectedValue}\n aria-disabled={isInactive || undefined}\n tabIndex={tabIndex}\n onKeyDown={onKeyDown}\n onFocus={onFocus}\n >\n {Icon && (\n <div className={styles.iconPrefix} aria-hidden=\"true\">\n <Icon size={20} />\n </div>\n )}\n <div className={styles.content}>\n <Text\n variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'}\n color={labelColor}\n as=\"span\"\n className={styles.label}\n >\n {label}\n </Text>\n {subtext && (\n <Text variant=\"text-body-small\" as=\"span\" className={styles.subtext}>\n {subtext}\n </Text>\n )}\n </div>\n {showToggle && (\n <div className={styles.toggleSuffix} aria-hidden=\"true\">\n <div className={`${styles.toggle} ${toggleValue ? styles.toggleOn : ''}`}>\n <div className={styles.toggleThumb} />\n </div>\n </div>\n )}\n {useRadioStyle && isSelected && CheckIcon && (\n <div className={styles.checkSuffix} aria-hidden=\"true\">\n <CheckIcon size={20} />\n </div>\n )}\n {showTrailingChevron && ChevronIcon && (\n <div className={styles.chevronSuffix} aria-hidden=\"true\">\n <ChevronIcon size={20} />\n </div>\n )}\n </Surface>\n );\n }\n);\n\nMenuItem.displayName = 'MenuItem';\n",".destructiveMenuItem {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n text-align: left;\n width: 100%;\n min-height: var(--dimension-size-400);\n position: relative;\n transition: var(--effect-transition-interaction-background-instant);\n overflow: hidden;\n}\n\n.destructiveMenuItem:has(.subtext) { align-items: flex-start; }\n\n.progressFill {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n background-color: var(--color-background-faint-negative);\n border-radius: var(--dimension-radius-075);\n transition: width 0ms linear;\n pointer-events: none;\n z-index: 0;\n}\n\n.destructiveMenuItem::before {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: var(--dimension-radius-075);\n transition: var(--effect-transition-interaction-background-instant);\n pointer-events: none;\n z-index: 1;\n}\n\n.content {\n position: relative;\n z-index: 2;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n min-width: 0;\n}\n\n.label { color: var(--color-foreground-bold-negative); }\n.subtext { color: var(--color-foreground-secondary); text-wrap: pretty; }\n\n.destructiveMenuItem:hover::before { background-color: var(--color-interaction-hover); }\n.destructiveMenuItem:active::before { background-color: transparent; }\n","import React, { forwardRef, useState, useRef, useEffect } from 'react';\nimport { Text } from '@/components/Text';\nimport styles from './DestructiveMenuItem.module.css';\n\nexport interface DestructiveMenuItemProps {\n label: string;\n onClick: () => void;\n holdDuration?: number;\n subtext?: string;\n tabIndex?: number;\n onKeyDown?: (e: React.KeyboardEvent<HTMLButtonElement>) => void;\n onFocus?: (e: React.FocusEvent<HTMLButtonElement>) => void;\n}\n\nexport const DestructiveMenuItem = forwardRef<HTMLButtonElement, DestructiveMenuItemProps>(\n ({ label, onClick, holdDuration = 4000, subtext, tabIndex, onKeyDown, onFocus }, ref) => {\n const [progress, setProgress] = useState(0);\n const pressTimerRef = useRef<number | null>(null);\n const startTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n const isHoldingRef = useRef(false);\n\n const resetState = () => {\n setProgress(0);\n isHoldingRef.current = false;\n if (pressTimerRef.current) { clearTimeout(pressTimerRef.current); pressTimerRef.current = null; }\n if (animationFrameRef.current) { cancelAnimationFrame(animationFrameRef.current); animationFrameRef.current = null; }\n };\n\n const startHold = () => {\n if (isHoldingRef.current) return;\n isHoldingRef.current = true;\n if (holdDuration === 0) { onClick(); resetState(); return; }\n startTimeRef.current = performance.now();\n const animate = () => {\n const elapsed = performance.now() - startTimeRef.current;\n const newProgress = Math.min((elapsed / holdDuration) * 100, 100);\n setProgress(newProgress);\n if (newProgress < 100) animationFrameRef.current = requestAnimationFrame(animate);\n };\n animationFrameRef.current = requestAnimationFrame(animate);\n pressTimerRef.current = window.setTimeout(() => { onClick(); resetState(); }, holdDuration);\n };\n\n const handleMouseDown = (e: React.MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n startHold();\n };\n\n const handleMouseUp = (e: React.MouseEvent) => { e.stopPropagation(); resetState(); };\n const handleMouseLeave = (e: React.MouseEvent) => { e.stopPropagation(); resetState(); };\n\n const isSpaceKey = (e: React.KeyboardEvent) => e.key === ' ' || e.key === 'Spacebar';\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isSpaceKey(e)) {\n e.preventDefault();\n if (e.repeat) return;\n e.stopPropagation();\n startHold();\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n return;\n }\n onKeyDown?.(e);\n };\n\n const handleKeyUp = (e: React.KeyboardEvent<HTMLButtonElement>) => {\n if (isSpaceKey(e)) {\n e.preventDefault();\n e.stopPropagation();\n resetState();\n }\n };\n\n const handleBlur = () => { resetState(); };\n\n useEffect(() => () => { resetState(); }, []);\n\n return (\n <button\n ref={ref}\n className={styles.destructiveMenuItem}\n onMouseDown={handleMouseDown}\n onMouseUp={handleMouseUp}\n onMouseLeave={handleMouseLeave}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onBlur={handleBlur}\n onFocus={onFocus}\n type=\"button\"\n role=\"menuitem\"\n tabIndex={tabIndex ?? -1}\n aria-keyshortcuts=\"Space\"\n >\n <div\n className={styles.progressFill}\n style={{ width: `${progress}%` }}\n role=\"progressbar\"\n aria-valuenow={Math.round(progress)}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label={`Hold to confirm ${label}`}\n />\n <div className={styles.content}>\n <Text variant=\"text-body-medium\" as=\"span\" className={styles.label}>{label}</Text>\n {subtext && <Text variant=\"text-body-small\" as=\"span\" className={styles.subtext}>{subtext}</Text>}\n </div>\n </button>\n );\n }\n);\n\nDestructiveMenuItem.displayName = 'DestructiveMenuItem';\n","/**\n * Reads a CSS custom property value from :root as a pixel number.\n * Returns the fallback if the property is not set or not parseable.\n */\nexport function getCssSpacePx(property: string, fallback: number): number {\n if (typeof document === 'undefined') return fallback;\n const raw = getComputedStyle(document.documentElement).getPropertyValue(property).trim();\n const parsed = parseFloat(raw);\n return Number.isNaN(parsed) ? fallback : parsed;\n}\n\n/**\n * Reads a CSS custom property value from :root as a millisecond number.\n * Handles both \"300ms\" and \"0.3s\" formats.\n */\nexport function getCssTimeMs(property: string, fallback: number): number {\n if (typeof document === 'undefined') return fallback;\n const raw = getComputedStyle(document.documentElement).getPropertyValue(property).trim();\n if (raw.endsWith('ms')) return parseFloat(raw) || fallback;\n if (raw.endsWith('s')) return (parseFloat(raw) || 0) * 1000 || fallback;\n return fallback;\n}\n",".menuContainer {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-125);\n box-shadow: var(--effect-elevation-elevated-floating);\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-width: 600px;\n overflow: hidden;\n animation: menuFadeIn var(--effect-motion-short-2) forwards;\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n}\n\n@keyframes menuFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n.menuContainer.closing {\n animation: menuFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes menuFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n\n.menuSection {\n padding: var(--dimension-space-050);\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-050);\n}\n\n.sectionHeader {\n padding: var(--dimension-space-050) var(--dimension-space-075);\n display: flex;\n align-items: center;\n height: var(--dimension-size-400);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.sectionLabel {\n color: var(--color-foreground-secondary);\n text-align: left;\n}\n","import React, { useState, useEffect, useLayoutEffect, useRef, useMemo, useCallback } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport { MenuItem as MenuItemComponent } from './MenuItem';\nimport { DestructiveMenuItem } from './DestructiveMenuItem';\nimport { getCssSpacePx } from '@/utils/css-tokens';\nimport type { IconComponent } from '@/types';\nimport type { MenuItemSelectionStyle } from './MenuItem';\nimport styles from './Menu.module.css';\n\nconst CLOSE_ANIMATION_MS = 220;\n\nexport type MenuSide = 'top' | 'right' | 'bottom' | 'left';\nexport type MenuAlign = 'start' | 'center' | 'end';\n\nexport interface MenuItemData {\n label: string;\n onClick: () => void;\n isSelected?: boolean;\n isDestructive?: boolean;\n isInactive?: boolean;\n intent?: 'negative';\n keepOpenOnClick?: boolean;\n holdDuration?: number;\n icon?: IconComponent;\n subtext?: string;\n showToggle?: boolean;\n toggleValue?: boolean;\n selectionStyle?: MenuItemSelectionStyle;\n}\n\nexport interface MenuSection {\n header?: string;\n items: MenuItemData[];\n}\n\nexport interface MenuProps {\n isOpen: boolean;\n onClose: () => void;\n anchorRef: React.RefObject<HTMLElement | null>;\n items?: MenuItemData[];\n sections?: MenuSection[];\n side?: MenuSide;\n align?: MenuAlign;\n sideOffset?: number;\n alignOffset?: number;\n sideOffsetToken?: string;\n alignOffsetToken?: string;\n width?: string;\n minWidth?: string;\n maxWidth?: string;\n matchAnchorWidth?: boolean;\n matchAnchorWidthOffset?: number;\n usePortal?: boolean;\n /** Container role + item role semantics. Defaults to `menu` (items are buttons with menuitem* roles, keyboard nav handled internally). `listbox` makes items render as `option` with `aria-selected`, with keyboard nav handled by the consumer via `activeIndex`. */\n role?: 'menu' | 'listbox';\n /** DOM id for the popup container — required when an external combobox references it via `aria-controls`/`aria-activedescendant`. */\n id?: string;\n /** Accessible label for the popup container. Defaults to `'Menu'` for menu role; omitted for listbox (let consumer provide via aria-labelledby on the combobox). */\n ariaLabel?: string;\n /** Active descendant index for listbox keyboard nav — highlights one option visually without moving DOM focus. */\n activeIndex?: number;\n /** Builds the DOM id for option `index`. Required in listbox mode if `aria-activedescendant` is used externally. */\n getOptionId?: (index: number) => string;\n}\n\nexport const Menu: React.FC<MenuProps> = ({\n isOpen,\n onClose,\n anchorRef,\n items,\n sections,\n side = 'bottom',\n align = 'start',\n sideOffset = 4,\n alignOffset = 0,\n sideOffsetToken,\n alignOffsetToken,\n width,\n minWidth,\n maxWidth,\n matchAnchorWidth = false,\n matchAnchorWidthOffset = 0,\n usePortal = true,\n role = 'menu',\n id,\n ariaLabel,\n activeIndex,\n getOptionId,\n}) => {\n const isListbox = role === 'listbox';\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(isOpen);\n const [isPositionReady, setIsPositionReady] = useState(false);\n const [position, setPosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const [menuSize, setMenuSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const [anchorSize, setAnchorSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const [focusedIndex, setFocusedIndex] = useState(0);\n const positionCalculatedRef = useRef(false);\n const menuRef = useRef<HTMLDivElement>(null);\n const lastSectionsRef = useRef<MenuSection[]>([]);\n const itemRefs = useRef<Array<HTMLButtonElement | null>>([]);\n const focusedOnOpenRef = useRef(false);\n\n const menuSections: MenuSection[] = sections || (items ? [{ items }] : []);\n\n const hasItems = menuSections.some((s) => s.items.length > 0);\n if (!isClosing && menuSections.length > 0 && hasItems) {\n lastSectionsRef.current = menuSections;\n }\n const sectionsToRender = isClosing ? lastSectionsRef.current : menuSections;\n\n const flatItems = useMemo(() => {\n const list: MenuItemData[] = [];\n sectionsToRender.forEach((section) => {\n section.items.forEach((it) => list.push(it));\n });\n return list;\n }, [sectionsToRender]);\n\n useEffect(() => {\n if (isOpen) {\n setShouldRender(true);\n setIsClosing(false);\n setIsPositionReady(false);\n positionCalculatedRef.current = false;\n } else if (shouldRender) {\n setIsClosing(true);\n const timer = setTimeout(() => {\n setShouldRender(false);\n setIsClosing(false);\n positionCalculatedRef.current = false;\n }, CLOSE_ANIMATION_MS);\n return () => clearTimeout(timer);\n }\n }, [isOpen, shouldRender]);\n\n useLayoutEffect(() => {\n if (!isOpen || !shouldRender || !menuRef.current) return;\n const updateSize = () => {\n if (!menuRef.current) return;\n const rect = menuRef.current.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) setMenuSize({ width: rect.width, height: rect.height });\n };\n updateSize();\n requestAnimationFrame(() => requestAnimationFrame(updateSize));\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(updateSize);\n observer.observe(menuRef.current);\n return () => observer.disconnect();\n }\n }, [isOpen, shouldRender, menuSections.length]);\n\n useLayoutEffect(() => {\n if (!isOpen || !shouldRender || !anchorRef.current || !menuRef.current) return;\n const calculatePosition = () => {\n const anchor = anchorRef.current;\n const menu = menuRef.current;\n if (!anchor || !menu) return;\n const anchorRect = anchor.getBoundingClientRect();\n const menuRect = menu.getBoundingClientRect();\n const menuWidth = menuRect.width || menuSize.width || 200;\n const menuHeight = menuRect.height || menuSize.height || 160;\n setAnchorSize({ width: anchorRect.width, height: anchorRect.height });\n const gap = sideOffsetToken != null ? getCssSpacePx(sideOffsetToken, 12) : sideOffset;\n const alignOff = alignOffsetToken != null ? getCssSpacePx(alignOffsetToken, 4) : alignOffset;\n let x = 0, y = 0;\n switch (side) {\n case 'top':\n y = anchorRect.top - menuHeight - gap;\n x = align === 'start' ? anchorRect.left + alignOff : align === 'end' ? anchorRect.right - menuWidth + alignOff : anchorRect.left + anchorRect.width / 2 - menuWidth / 2 + alignOff;\n break;\n case 'bottom':\n y = anchorRect.bottom + gap;\n x = align === 'start' ? anchorRect.left + alignOff : align === 'end' ? anchorRect.right - menuWidth + alignOff : anchorRect.left + anchorRect.width / 2 - menuWidth / 2 + alignOff;\n break;\n case 'left':\n x = anchorRect.left - menuWidth - gap;\n y = align === 'start' ? anchorRect.top + alignOff : align === 'end' ? anchorRect.bottom - menuHeight + alignOff : anchorRect.top + anchorRect.height / 2 - menuHeight / 2 + alignOff;\n break;\n case 'right':\n x = anchorRect.right + gap;\n y = align === 'start' ? anchorRect.top + alignOff : align === 'end' ? anchorRect.bottom - menuHeight + alignOff : anchorRect.top + anchorRect.height / 2 - menuHeight / 2 + alignOff;\n break;\n }\n const vp = 4;\n setPosition({\n x: Math.min(Math.max(x, vp), window.innerWidth - menuWidth - vp),\n y: Math.min(Math.max(y, vp), window.innerHeight - menuHeight - vp),\n });\n positionCalculatedRef.current = true;\n setIsPositionReady(true);\n };\n if (!positionCalculatedRef.current) {\n calculatePosition();\n requestAnimationFrame(() => { if (!positionCalculatedRef.current) calculatePosition(); });\n }\n const handleScrollResize = () => calculatePosition();\n window.addEventListener('scroll', handleScrollResize, true);\n window.addEventListener('resize', handleScrollResize);\n return () => {\n window.removeEventListener('scroll', handleScrollResize, true);\n window.removeEventListener('resize', handleScrollResize);\n };\n }, [isOpen, shouldRender, anchorRef, side, align, sideOffset, alignOffset, sideOffsetToken, alignOffsetToken, menuSize.width, menuSize.height, menuSections.length, matchAnchorWidthOffset]);\n\n const closeAndRestoreFocus = useCallback(() => {\n const active = document.activeElement as HTMLElement | null;\n const focusInside = !!(active && menuRef.current?.contains(active));\n if (focusInside && anchorRef.current) {\n anchorRef.current.focus();\n }\n onClose();\n }, [onClose, anchorRef]);\n\n useEffect(() => {\n if (!isOpen || !shouldRender) return;\n const handleClickOutside = (event: MouseEvent) => {\n const target = event.target as HTMLElement;\n if (menuRef.current?.contains(target)) return;\n if (anchorRef.current?.contains(target)) return;\n onClose();\n };\n document.addEventListener('mousedown', handleClickOutside, true);\n return () => document.removeEventListener('mousedown', handleClickOutside, true);\n }, [isOpen, shouldRender, onClose, anchorRef]);\n\n useEffect(() => {\n if (!isOpen) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n if (isListbox) {\n onClose();\n } else {\n e.preventDefault();\n closeAndRestoreFocus();\n }\n }\n };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isOpen, isListbox, onClose, closeAndRestoreFocus]);\n\n useEffect(() => {\n if (!isOpen) {\n focusedOnOpenRef.current = false;\n return;\n }\n if (isListbox || !isPositionReady || focusedOnOpenRef.current) return;\n const firstEnabled = flatItems.findIndex((it) => !it.isInactive);\n const targetIdx = firstEnabled >= 0 ? firstEnabled : 0;\n setFocusedIndex(targetIdx);\n itemRefs.current[targetIdx]?.focus();\n focusedOnOpenRef.current = true;\n }, [isOpen, isListbox, isPositionReady, flatItems]);\n\n const moveFocus = useCallback((idx: number) => {\n setFocusedIndex(idx);\n itemRefs.current[idx]?.focus();\n }, []);\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {\n if (isListbox || !flatItems.length) return;\n const enabled: number[] = [];\n flatItems.forEach((it, i) => { if (!it.isInactive) enabled.push(i); });\n if (!enabled.length) return;\n const currentPos = enabled.indexOf(focusedIndex);\n const safePos = currentPos < 0 ? 0 : currentPos;\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n e.stopPropagation();\n moveFocus(enabled[(safePos + 1) % enabled.length]);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n e.stopPropagation();\n moveFocus(enabled[(safePos - 1 + enabled.length) % enabled.length]);\n break;\n }\n case 'Home': {\n e.preventDefault();\n e.stopPropagation();\n moveFocus(enabled[0]);\n break;\n }\n case 'End': {\n e.preventDefault();\n e.stopPropagation();\n moveFocus(enabled[enabled.length - 1]);\n break;\n }\n case 'Tab': {\n e.preventDefault();\n closeAndRestoreFocus();\n break;\n }\n }\n }, [isListbox, flatItems, focusedIndex, moveFocus, closeAndRestoreFocus]);\n\n if (!shouldRender || sectionsToRender.length === 0) return null;\n\n const setItemRef = (flatIndex: number) => (el: HTMLButtonElement | null) => {\n itemRefs.current[flatIndex] = el;\n };\n\n const handleItemFocus = (flatIndex: number) => () => {\n setFocusedIndex(flatIndex);\n };\n\n const handleItemActivate = (item: MenuItemData) => {\n if (item.isInactive) return;\n item.onClick();\n if (item.keepOpenOnClick) return;\n if (isListbox) {\n onClose();\n } else {\n closeAndRestoreFocus();\n }\n };\n\n const renderMenuItem = (item: MenuItemData, key: number, flatIndex: number) => {\n if (item.isDestructive) {\n const tabIndexValue = isListbox ? -1 : (focusedIndex === flatIndex ? 0 : -1);\n return (\n <DestructiveMenuItem\n key={key}\n ref={setItemRef(flatIndex)}\n label={item.label}\n subtext={item.subtext}\n holdDuration={item.holdDuration ?? 4000}\n onClick={() => { item.onClick(); if (!item.keepOpenOnClick) { if (isListbox) onClose(); else closeAndRestoreFocus(); } }}\n tabIndex={tabIndexValue}\n onFocus={handleItemFocus(flatIndex)}\n />\n );\n }\n const optionId = isListbox && getOptionId ? getOptionId(flatIndex) : undefined;\n const tabIndexValue = isListbox ? -1 : (focusedIndex === flatIndex ? 0 : -1);\n return (\n <MenuItemComponent\n key={key}\n ref={setItemRef(flatIndex)}\n icon={item.icon}\n label={item.label}\n subtext={item.subtext}\n onClick={() => handleItemActivate(item)}\n isSelected={item.isSelected}\n isInactive={item.isInactive}\n intent={item.intent}\n showToggle={item.showToggle}\n toggleValue={item.toggleValue}\n selectionStyle={item.selectionStyle}\n role={isListbox ? 'option' : undefined}\n id={optionId}\n ariaSelected={isListbox ? !!item.isSelected : undefined}\n isActive={isListbox && activeIndex === flatIndex}\n tabIndex={tabIndexValue}\n onFocus={handleItemFocus(flatIndex)}\n />\n );\n };\n\n const menuStyle: React.CSSProperties = {\n position: 'absolute',\n left: 0,\n top: 0,\n transform: `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`,\n willChange: 'transform',\n zIndex: 9998,\n visibility: isPositionReady ? 'visible' : 'hidden',\n ...(matchAnchorWidth && anchorSize.width > 0 ? { width: `${anchorSize.width + matchAnchorWidthOffset}px` } : width ? { width } : {}),\n ...(minWidth ? { minWidth } : {}),\n ...(maxWidth ? { maxWidth } : {}),\n };\n\n let flatIndexCounter = 0;\n const containerLabel = ariaLabel ?? (isListbox ? undefined : 'Menu');\n const menuContent = (\n <div\n ref={menuRef}\n id={id}\n className={`${styles.menuContainer} ${isClosing ? styles.closing : ''}`}\n style={menuStyle}\n role={role}\n aria-label={containerLabel}\n aria-orientation=\"vertical\"\n onKeyDown={handleKeyDown}\n >\n {sectionsToRender.map((section, sectionIndex) => (\n <Surface\n key={sectionIndex}\n as=\"div\"\n className={styles.menuSection}\n edge={sectionIndex < sectionsToRender.length - 1 ? 'bottom' : undefined}\n elevation=\"none\"\n role={section.header ? 'group' : undefined}\n aria-label={section.header}\n >\n {section.header && (\n <div className={styles.sectionHeader} aria-hidden=\"true\">\n <Text variant=\"text-body-small-emphasis\" as=\"span\" className={styles.sectionLabel}>{section.header}</Text>\n </div>\n )}\n {section.items.map((item, itemIndex) => renderMenuItem(item, itemIndex, flatIndexCounter++))}\n </Surface>\n ))}\n </div>\n );\n\n if (usePortal) return createPortal(menuContent, document.body);\n return menuContent;\n};\n\nMenu.displayName = 'Menu';\n",".tooltip {\n box-sizing: border-box;\n background-color: var(--color-background-primary);\n border-radius: var(--dimension-radius-075);\n box-shadow: var(--effect-elevation-elevated-floating);\n padding: var(--dimension-space-050);\n line-height: var(--typography-lineheight-sm);\n pointer-events: none;\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n animation: tooltipFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.tooltipInner {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n.keyHint {\n width: var(--dimension-size-200);\n height: var(--dimension-size-200);\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n border: var(--dimension-stroke-width-015) solid var(--color-foreground-tertiary);\n border-bottom-width: var(--dimension-stroke-width-025);\n border-radius: var(--dimension-radius-025);\n}\n\n.tooltip.closing {\n animation: tooltipFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes tooltipFadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes tooltipFadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback, useId } from 'react';\nimport { createPortal } from 'react-dom';\nimport { getCssTimeMs } from '@/utils/css-tokens';\nimport { Text } from '@/components/Text';\nimport styles from './Tooltip.module.css';\n\nconst HOVER_DELAY_FALLBACK_MS = 1000;\nconst INSTANT_REOPEN_MS = 300;\nconst FADE_OUT_DURATION_MS = 200;\n\nlet lastTooltipDismissedAt = 0;\n\nexport type TooltipSide = 'top' | 'right' | 'bottom' | 'left';\nexport type TooltipAlign = 'start' | 'center' | 'end';\n\nexport interface TooltipProps {\n label: string;\n children: React.ReactElement;\n delay?: number;\n side?: TooltipSide;\n align?: TooltipAlign;\n sideOffset?: number;\n alignOffset?: number;\n shortcutKey?: string;\n shortcutKeyPosition?: 'start' | 'end';\n usePortal?: boolean;\n}\n\nexport const Tooltip: React.FC<TooltipProps> = ({\n label,\n children,\n delay,\n side = 'top',\n align = 'center',\n sideOffset = 4,\n alignOffset = 0,\n shortcutKey,\n shortcutKeyPosition = 'end',\n usePortal = true,\n}) => {\n const hoverDelayMs = getCssTimeMs('--effect-animation-delay-medium-3', HOVER_DELAY_FALLBACK_MS);\n const resolvedDelay = delay ?? hoverDelayMs;\n const anchorRef = useRef<HTMLElement | null>(null);\n const tooltipRef = useRef<HTMLDivElement>(null);\n const tooltipId = useId();\n\n const setAnchorRef = useCallback(\n (el: HTMLElement | null) => {\n (anchorRef as React.MutableRefObject<HTMLElement | null>).current = el;\n const childEl = React.Children.only(children) as React.ReactElement<{ ref?: React.Ref<unknown> }>;\n const childRef = 'ref' in childEl ? childEl.ref : undefined;\n if (typeof childRef === 'function') childRef(el);\n else if (childRef && typeof childRef === 'object') (childRef as React.MutableRefObject<unknown>).current = el;\n },\n [children]\n );\n\n const [open, setOpen] = useState(false);\n const [isClosing, setIsClosing] = useState(false);\n const [shouldRender, setShouldRender] = useState(false);\n const [position, setPosition] = useState<{ x: number; y: number }>({ x: 0, y: 0 });\n const [tooltipSize, setTooltipSize] = useState<{ width: number; height: number }>({ width: 0, height: 0 });\n const delayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const viewportPadding = 4;\n\n const clearDelayTimer = () => {\n if (delayTimerRef.current) { clearTimeout(delayTimerRef.current); delayTimerRef.current = null; }\n };\n\n const handleOpen = () => {\n clearDelayTimer();\n const showImmediately = Date.now() - lastTooltipDismissedAt < INSTANT_REOPEN_MS;\n if (showImmediately) {\n setOpen(true); setShouldRender(true); setIsClosing(false); return;\n }\n delayTimerRef.current = setTimeout(() => {\n delayTimerRef.current = null;\n setOpen(true); setShouldRender(true); setIsClosing(false);\n }, resolvedDelay);\n };\n\n const handleClose = () => {\n clearDelayTimer();\n if (closeTimerRef.current) { clearTimeout(closeTimerRef.current); closeTimerRef.current = null; }\n if (!open && !shouldRender) return;\n lastTooltipDismissedAt = Date.now();\n setIsClosing(true);\n closeTimerRef.current = setTimeout(() => {\n closeTimerRef.current = null;\n setShouldRender(false); setOpen(false); setIsClosing(false);\n }, FADE_OUT_DURATION_MS);\n };\n\n useEffect(() => () => { clearDelayTimer(); if (closeTimerRef.current) clearTimeout(closeTimerRef.current); }, []);\n\n useEffect(() => {\n if (!shouldRender) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') handleClose();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n // handleClose is stable in effect — re-subscribing on each render would churn the listener\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [shouldRender]);\n\n useLayoutEffect(() => {\n if (!shouldRender || !tooltipRef.current) return;\n const updateSize = () => {\n if (!tooltipRef.current) return;\n const rect = tooltipRef.current.getBoundingClientRect();\n const w = rect.width || tooltipRef.current.offsetWidth;\n const h = rect.height || tooltipRef.current.offsetHeight;\n if (w > 0 && h > 0) setTooltipSize({ width: w, height: h });\n };\n updateSize();\n requestAnimationFrame(updateSize);\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(updateSize);\n observer.observe(tooltipRef.current);\n return () => observer.disconnect();\n }\n }, [shouldRender, label, shortcutKey, shortcutKeyPosition]);\n\n useLayoutEffect(() => {\n if (!shouldRender || !anchorRef.current || !tooltipRef.current) return;\n const calculatePosition = () => {\n if (!anchorRef.current || !tooltipRef.current) return;\n const a = anchorRef.current.getBoundingClientRect();\n const tw = tooltipRef.current.getBoundingClientRect().width || tooltipSize.width || 80;\n const th = tooltipRef.current.getBoundingClientRect().height || tooltipSize.height || 24;\n let x = 0, y = 0;\n switch (side) {\n case 'top':\n y = a.top - th - sideOffset;\n x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'bottom':\n y = a.bottom + sideOffset;\n x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset;\n break;\n case 'left':\n x = a.left - tw - sideOffset;\n y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n case 'right':\n x = a.right + sideOffset;\n y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset;\n break;\n }\n setPosition({\n x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),\n y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),\n });\n };\n calculatePosition();\n requestAnimationFrame(() => requestAnimationFrame(calculatePosition));\n }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height, label]);\n\n useEffect(() => {\n if (!shouldRender) return;\n const onScrollResize = () => {\n if (!anchorRef.current || !tooltipRef.current) return;\n const a = anchorRef.current.getBoundingClientRect();\n const tw = tooltipSize.width || 80;\n const th = tooltipSize.height || 24;\n let x = 0, y = 0;\n switch (side) {\n case 'top': y = a.top - th - sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;\n case 'bottom': y = a.bottom + sideOffset; x = align === 'start' ? a.left + alignOffset : align === 'end' ? a.right - tw + alignOffset : a.left + a.width / 2 - tw / 2 + alignOffset; break;\n case 'left': x = a.left - tw - sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;\n case 'right': x = a.right + sideOffset; y = align === 'start' ? a.top + alignOffset : align === 'end' ? a.bottom - th + alignOffset : a.top + a.height / 2 - th / 2 + alignOffset; break;\n }\n setPosition({\n x: Math.min(Math.max(x, viewportPadding), window.innerWidth - tw - viewportPadding),\n y: Math.min(Math.max(y, viewportPadding), window.innerHeight - th - viewportPadding),\n });\n };\n window.addEventListener('scroll', onScrollResize, true);\n window.addEventListener('resize', onScrollResize);\n return () => { window.removeEventListener('scroll', onScrollResize, true); window.removeEventListener('resize', onScrollResize); };\n }, [shouldRender, side, align, sideOffset, alignOffset, tooltipSize.width, tooltipSize.height]);\n\n const keyHint = shortcutKey ? (\n <div className={styles.keyHint} aria-hidden>\n <Text variant=\"text-caption-emphasis\" as=\"span\" color=\"primary\">{shortcutKey}</Text>\n </div>\n ) : null;\n\n const tooltipContent = shouldRender ? (\n <div\n ref={tooltipRef}\n id={tooltipId}\n className={`${styles.tooltip} ${isClosing ? styles.closing : ''}`}\n style={{\n position: 'fixed',\n left: 0,\n top: 0,\n transform: `translate(${Math.round(position.x)}px, ${Math.round(position.y)}px)`,\n willChange: 'transform',\n zIndex: 10000,\n }}\n role=\"tooltip\"\n onMouseEnter={handleOpen}\n onMouseLeave={handleClose}\n >\n <div className={styles.tooltipInner}>\n {shortcutKey && shortcutKeyPosition === 'start' && keyHint}\n <Text variant=\"text-body-small\" as=\"span\" color=\"primary\">{label}</Text>\n {shortcutKey && shortcutKeyPosition === 'end' && keyHint}\n </div>\n </div>\n ) : null;\n\n type TriggerProps = {\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n onFocus?: (e: React.FocusEvent) => void;\n onBlur?: (e: React.FocusEvent) => void;\n 'aria-describedby'?: string;\n };\n const trigger = React.Children.only(children);\n const triggerEl = React.isValidElement<TriggerProps>(trigger) ? trigger : null;\n const existingDescribedBy = triggerEl?.props['aria-describedby'];\n const mergedDescribedBy =\n [existingDescribedBy, shouldRender ? tooltipId : undefined].filter(Boolean).join(' ') ||\n undefined;\n const triggerWithRefAndHandlers = triggerEl\n ? React.cloneElement(triggerEl, {\n ref: setAnchorRef,\n 'aria-describedby': mergedDescribedBy,\n onMouseEnter: (e: React.MouseEvent) => {\n handleOpen();\n triggerEl.props.onMouseEnter?.(e);\n },\n onMouseLeave: (e: React.MouseEvent) => {\n handleClose();\n triggerEl.props.onMouseLeave?.(e);\n },\n onFocus: (e: React.FocusEvent) => {\n handleOpen();\n triggerEl.props.onFocus?.(e);\n },\n onBlur: (e: React.FocusEvent) => {\n handleClose();\n triggerEl.props.onBlur?.(e);\n },\n } as Partial<TriggerProps> & { ref: typeof setAnchorRef })\n : children;\n\n return (\n <>\n {triggerWithRefAndHandlers}\n {usePortal ? createPortal(tooltipContent, document.body) : tooltipContent}\n </>\n );\n};\n\nTooltip.displayName = 'Tooltip';\n",".selectWrapper {\n width: 100%;\n position: relative;\n}\n\n.selectButton {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n height: var(--dimension-size-400);\n padding: 0 var(--dimension-space-075);\n gap: var(--dimension-space-050);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border: none;\n outline: none;\n}\n\n.selectButton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.chevron {\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n flex-shrink: 0;\n}\n","import React, { forwardRef, useId, useState, useRef, useEffect, useCallback } from 'react';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport { Menu } from '@/components/Menu';\nimport type { MenuItemData } from '@/components/Menu';\nimport type { IconComponent } from '@/types';\nimport styles from './Select.module.css';\n\nexport interface SelectOption {\n label: string;\n value: string | number;\n}\n\nexport interface SelectProps {\n value: string | number;\n onChange: (value: string | number) => void;\n options: SelectOption[];\n placeholder?: string;\n className?: string;\n inactive?: boolean;\n id?: string;\n chevronIcon?: IconComponent;\n /** Accessible name. Required when no associated `<label htmlFor>` element exists. */\n 'aria-label'?: string;\n /** Accessible name reference. Use when a visible label already exists outside the trigger. */\n 'aria-labelledby'?: string;\n}\n\nexport const Select = forwardRef<HTMLDivElement, SelectProps>(\n (\n {\n value,\n onChange,\n options,\n placeholder = 'Select option',\n className,\n inactive = false,\n id,\n chevronIcon: ChevronIcon,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n },\n ref\n ) => {\n const [isMenuOpen, setIsMenuOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(-1);\n const buttonRef = useRef<HTMLButtonElement>(null);\n\n const reactId = useId();\n const triggerId = id ?? `select-${reactId}`;\n const listboxId = `${triggerId}-listbox`;\n const getOptionId = useCallback((index: number) => `${triggerId}-option-${index}`, [triggerId]);\n\n const selectedIndex = options.findIndex(opt => opt.value === value);\n const selectedOption = selectedIndex >= 0 ? options[selectedIndex] : undefined;\n const selectedLabel = selectedOption?.label || placeholder;\n\n const commitSelection = useCallback(\n (index: number) => {\n const option = options[index];\n if (!option) return;\n onChange(option.value);\n setIsMenuOpen(false);\n },\n [options, onChange]\n );\n\n const openWith = useCallback(\n (initialIndex: number) => {\n if (inactive || options.length === 0) return;\n const clamped = Math.max(0, Math.min(options.length - 1, initialIndex));\n setActiveIndex(clamped);\n setIsMenuOpen(true);\n },\n [inactive, options.length]\n );\n\n useEffect(() => {\n if (isMenuOpen) {\n setActiveIndex(prev => {\n if (prev >= 0 && prev < options.length) return prev;\n return selectedIndex >= 0 ? selectedIndex : 0;\n });\n } else {\n setActiveIndex(-1);\n }\n }, [isMenuOpen, options.length, selectedIndex]);\n\n const menuItems: MenuItemData[] = options.map((option, index) => ({\n label: option.label,\n onClick: () => commitSelection(index),\n isSelected: option.value === value,\n }));\n\n const handleToggle = () => {\n if (inactive) return;\n if (isMenuOpen) {\n setIsMenuOpen(false);\n } else {\n openWith(selectedIndex >= 0 ? selectedIndex : 0);\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {\n if (inactive || options.length === 0) return;\n const last = options.length - 1;\n\n if (!isMenuOpen) {\n switch (event.key) {\n case 'ArrowDown':\n case 'ArrowUp':\n case 'Enter':\n case ' ':\n event.preventDefault();\n openWith(selectedIndex >= 0 ? selectedIndex : 0);\n return;\n case 'Home':\n event.preventDefault();\n openWith(0);\n return;\n case 'End':\n event.preventDefault();\n openWith(last);\n return;\n default:\n return;\n }\n }\n\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setActiveIndex(prev => Math.min(last, (prev < 0 ? -1 : prev) + 1));\n break;\n case 'ArrowUp':\n event.preventDefault();\n setActiveIndex(prev => Math.max(0, (prev < 0 ? options.length : prev) - 1));\n break;\n case 'Home':\n event.preventDefault();\n setActiveIndex(0);\n break;\n case 'End':\n event.preventDefault();\n setActiveIndex(last);\n break;\n case 'Enter':\n case ' ':\n event.preventDefault();\n if (activeIndex >= 0) commitSelection(activeIndex);\n break;\n case 'Escape':\n event.preventDefault();\n setIsMenuOpen(false);\n break;\n case 'Tab':\n setIsMenuOpen(false);\n break;\n }\n };\n\n const activeDescendantId =\n isMenuOpen && activeIndex >= 0 ? getOptionId(activeIndex) : undefined;\n\n return (\n <div ref={ref} className={`${styles.selectWrapper} ${className || ''}`}>\n <Surface\n id={triggerId}\n ref={buttonRef as React.RefObject<HTMLElement>}\n as=\"button\"\n type=\"button\"\n elevation=\"elevated\"\n radius=\"sm\"\n interactive\n selected={isMenuOpen}\n className={styles.selectButton}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n inactive={inactive}\n role=\"combobox\"\n aria-haspopup=\"listbox\"\n aria-expanded={isMenuOpen}\n aria-controls={isMenuOpen ? listboxId : undefined}\n aria-activedescendant={activeDescendantId}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n >\n <Text\n variant=\"text-body-medium\"\n as=\"span\"\n color={selectedOption ? 'primary' : 'secondary'}\n >\n {selectedLabel}\n </Text>\n {ChevronIcon && (\n <span className={styles.chevron}>\n <ChevronIcon size={16} />\n </span>\n )}\n </Surface>\n <Menu\n isOpen={isMenuOpen}\n onClose={() => setIsMenuOpen(false)}\n anchorRef={buttonRef as React.RefObject<HTMLElement | null>}\n items={menuItems}\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n alignOffset={-4}\n matchAnchorWidth\n matchAnchorWidthOffset={8}\n role=\"listbox\"\n id={listboxId}\n activeIndex={activeIndex}\n getOptionId={getOptionId}\n />\n </div>\n );\n }\n);\n\nSelect.displayName = 'Select';\n",".bannerWrapper {}\n\n.banner {\n position: relative;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.bannerHeaderSurface {\n width: 100%;\n height: var(--dimension-space-100);\n flex-shrink: 0;\n overflow: hidden;\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.bannerHeader {\n width: 100%;\n height: 100%;\n background: repeating-linear-gradient(\n -45deg,\n var(--banner-content),\n var(--banner-content) var(--dimension-size-100),\n transparent var(--dimension-size-100),\n transparent var(--dimension-size-200)\n );\n}\n\n.bannerBody {\n padding: var(--dimension-space-075);\n min-height: var(--dimension-size-400);\n display: flex;\n align-items: flex-start;\n gap: var(--dimension-space-075);\n}\n\n.message {\n color: var(--banner-content);\n line-height: var(--typography-lineheight-md);\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.dismiss {\n background: none;\n border: none;\n margin: 0;\n padding: var(--dimension-space-025);\n color: var(--banner-content);\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border-radius: var(--dimension-radius-050);\n position: relative;\n}\n\n.dismiss::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background-color: transparent;\n transition: var(--effect-transition-interaction-background-short-2);\n pointer-events: none;\n}\n\n.dismiss:hover::before { background-color: var(--color-interaction-hover); }\n.dismiss:active::before { background-color: var(--color-interaction-pressed); }\n\n.dismiss:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: var(--dimension-stroke-width-015);\n}\n\n.floatingPosition {\n position: fixed;\n top: var(--dimension-space-200);\n left: 50%;\n transform: translateX(-50%);\n pointer-events: none;\n}\n\n.floatingToast {\n backface-visibility: hidden;\n -webkit-font-smoothing: subpixel-antialiased;\n animation: toastFadeIn var(--effect-motion-short-2) forwards;\n}\n\n.floatingToast.closing {\n animation: toastFadeOut var(--effect-motion-short-3) forwards;\n}\n\n@keyframes toastFadeIn {\n from { opacity: 0; transform: translateY(-8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n@keyframes toastFadeOut {\n from { opacity: 1; transform: translateY(0); }\n to { opacity: 0; transform: translateY(-4px); }\n}\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Cross } from '@ds-mo/icons';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport { getCssTimeMs } from '@/utils/css-tokens';\nimport styles from './Banner.module.css';\n\nconst TOAST_DURATION_FALLBACK_MS = 4000;\nconst FADE_OUT_DURATION_MS = 200;\n\nexport type BannerIntent =\n | 'brand' | 'positive' | 'negative' | 'warning' | 'caution'\n | 'ai' | 'neutral' | 'walkthrough' | 'guide';\n\nexport type BannerContrast = 'faint' | 'medium' | 'bold' | 'strong';\n\nexport interface BannerProps {\n intent: BannerIntent;\n contrast: BannerContrast;\n message: string;\n header?: boolean;\n className?: string;\n floating?: boolean;\n onDismiss?: () => void;\n /** Accessible label for the dismiss button. Defaults to \"Dismiss\". */\n dismissLabel?: string;\n}\n\nconst getContentColorVar = (intent: BannerIntent, contrast: BannerContrast): string => {\n if (contrast === 'bold') return 'var(--color-foreground-on-bold-background-primary)';\n const contentContrast = contrast === 'faint' ? 'bold' : contrast === 'medium' ? 'strong' : 'medium';\n return `var(--color-foreground-${contentContrast}-${intent})`;\n};\n\nexport const Banner: React.FC<BannerProps> = ({\n intent,\n contrast,\n message,\n header = false,\n className = '',\n floating = false,\n onDismiss,\n dismissLabel = 'Dismiss',\n}) => {\n const toastDurationMs = getCssTimeMs('--effect-animation-delay-long-2', TOAST_DURATION_FALLBACK_MS);\n const messageColor = getContentColorVar(intent, contrast);\n const [isClosing, setIsClosing] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const closeTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const beginClose = useCallback(() => {\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n dismissTimerRef.current = null;\n if (floating) {\n setIsClosing(true);\n closeTimerRef.current = setTimeout(() => {\n closeTimerRef.current = null;\n onDismiss?.();\n }, FADE_OUT_DURATION_MS);\n } else {\n onDismiss?.();\n }\n }, [floating, onDismiss]);\n\n const scheduleDismiss = useCallback(() => {\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n dismissTimerRef.current = setTimeout(() => {\n dismissTimerRef.current = null;\n beginClose();\n }, toastDurationMs);\n }, [beginClose, toastDurationMs]);\n\n useEffect(() => {\n if (floating && message) scheduleDismiss();\n return () => {\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n if (closeTimerRef.current) clearTimeout(closeTimerRef.current);\n };\n }, [floating, message, scheduleDismiss]);\n\n const isAssertive = intent === 'negative';\n const role = isAssertive ? 'alert' : 'status';\n const ariaLive = isAssertive ? undefined : 'polite';\n\n const content = (\n <div\n className={`${styles.bannerWrapper} ${className}`.trim()}\n style={{ '--banner-content': messageColor } as React.CSSProperties}\n role={role}\n aria-live={ariaLive}\n >\n <Surface\n elevation={floating ? 'floating' : 'elevated'}\n intent={intent}\n contrast={contrast}\n radius=\"sm\"\n className={styles.banner}\n >\n {header && (\n <div className={styles.bannerHeaderSurface}>\n <div className={styles.bannerHeader} aria-hidden />\n </div>\n )}\n <div className={styles.bannerBody}>\n <Text variant=\"text-body-medium\" as=\"span\" className={styles.message}>\n {message}\n </Text>\n {onDismiss && (\n <button\n type=\"button\"\n className={styles.dismiss}\n onClick={beginClose}\n aria-label={dismissLabel}\n >\n <Cross size={16} />\n </button>\n )}\n </div>\n </Surface>\n </div>\n );\n\n if (floating) {\n return createPortal(\n <div className={styles.floatingPosition} style={{ zIndex: 9998 }}>\n <div className={`${styles.floatingToast} ${isClosing ? styles.closing : ''}`}>\n {content}\n </div>\n </div>,\n document.body\n );\n }\n\n return content;\n};\n\nBanner.displayName = 'Banner';\n",".tableWrapper {\n display: flex;\n flex-direction: column;\n width: 100%;\n overflow: hidden;\n border-radius: var(--dimension-radius-075);\n}\n\n.tableScroll {\n overflow-x: auto;\n width: 100%;\n}\n\n.table {\n display: grid;\n width: 100%;\n min-width: max-content;\n}\n\n.headerRow {\n display: contents;\n}\n\n.headerCell {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075) var(--dimension-space-100);\n background-color: var(--color-background-secondary);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n -webkit-user-select: none;\n user-select: none;\n position: sticky;\n top: 0;\n z-index: 2;\n}\n\n.headerCell.sortable {\n cursor: pointer;\n}\n\n.headerCell.sortable:hover {\n background-color: var(--color-background-translucent);\n}\n\n.headerCell.sortable:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: calc(var(--dimension-space-025) * -1);\n}\n\n.sortIndicator {\n font-size: 12px;\n color: var(--color-foreground-secondary);\n}\n\n.row {\n display: contents;\n}\n\n.row:hover .cell {\n background-color: var(--color-interaction-hover);\n}\n\n.rowSelected .cell {\n background-color: var(--color-background-faint-brand);\n}\n\n.rowClickable {\n cursor: pointer;\n}\n\n.rowClickable:focus-visible .cell {\n background-color: var(--color-interaction-hover);\n box-shadow: inset 0 0 0 var(--dimension-stroke-width-025) var(--color-interaction-focus);\n}\n\n.cell {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-075) var(--dimension-space-100);\n border-bottom: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n min-height: var(--dimension-size-500);\n background-color: var(--color-background-primary);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.alignRight { justify-content: flex-end; text-align: right; }\n.alignCenter { justify-content: center; text-align: center; }\n\n.emptyRow {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-400);\n background-color: var(--color-background-primary);\n}\n\n.skeleton {\n height: 14px;\n width: 60%;\n background-color: var(--color-background-translucent);\n border-radius: var(--dimension-radius-050);\n animation: shimmer 1.5s infinite;\n}\n\n@keyframes shimmer {\n 0% { opacity: 0.5; }\n 50% { opacity: 1; }\n 100% { opacity: 0.5; }\n}\n\n.pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-100);\n padding: var(--dimension-space-100);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n background-color: var(--color-background-primary);\n}\n\n.pageButton {\n display: flex;\n align-items: center;\n padding: var(--dimension-space-050) var(--dimension-space-100);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n transition: background-color var(--effect-motion-short-2);\n}\n\n.pageButton:hover:not(:disabled) {\n background-color: var(--color-interaction-hover);\n}\n\n.pageButton:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n","import React, { useMemo } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Table.module.css';\n\nexport type SortDirection = 'asc' | 'desc';\nexport type CellType = 'string' | 'numbers' | 'tag' | 'checkbox' | 'button' | 'spacer' | 'image' | 'icon' | 'empty';\nexport type FilterValue = string | number | Array<string | number> | undefined;\nexport type FilterState = Record<string, FilterValue>;\n\nexport interface SortState {\n columnId: string;\n direction: SortDirection;\n}\n\nexport interface PaginationState {\n pageIndex: number;\n pageSize: number;\n}\n\nexport interface TableColumn<T = unknown> {\n id: string;\n header: string | React.ReactNode;\n accessorKey?: string;\n accessor?: (row: T) => unknown;\n sortable?: boolean;\n align?: 'left' | 'right' | 'center';\n width?: string | number;\n minWidth?: string | number;\n maxWidth?: string | number;\n renderCell?: (row: T, rowIndex: number) => React.ReactNode;\n cellType?: CellType;\n hide?: boolean;\n pinned?: 'left' | 'right';\n}\n\nexport interface TableProps<T = unknown> {\n columns: TableColumn<T>[];\n data: T[];\n sortState?: SortState;\n onSort?: (columnId: string) => void;\n className?: string;\n onRowClick?: (row: T, rowIndex: number) => void;\n selectedRows?: Set<number>;\n loading?: boolean;\n pagination?: PaginationState;\n onPaginationChange?: (pageIndex: number, pageSize: number) => void;\n emptyMessage?: string;\n}\n\nfunction getColumnValue<T>(column: TableColumn<T>, row: T): unknown {\n if (column.accessorKey) return (row as Record<string, unknown>)[column.accessorKey];\n if (column.accessor) return column.accessor(row);\n return undefined;\n}\n\nfunction compareValues(a: unknown, b: unknown, direction: SortDirection): number {\n const mult = direction === 'asc' ? 1 : -1;\n if (a == null && b == null) return 0;\n if (a == null) return mult;\n if (b == null) return -mult;\n if (typeof a === 'number' && typeof b === 'number') return (a - b) * mult;\n return String(a).localeCompare(String(b)) * mult;\n}\n\nexport function Table<T>({\n columns,\n data,\n sortState,\n onSort,\n className,\n onRowClick,\n selectedRows,\n loading = false,\n pagination,\n onPaginationChange,\n emptyMessage = 'No results found.',\n}: TableProps<T>) {\n const visibleColumns = useMemo(() => columns.filter(c => !c.hide), [columns]);\n\n const gridTemplateColumns = useMemo(() =>\n visibleColumns.map(col => {\n if (col.width) return typeof col.width === 'number' ? `${col.width}px` : col.width;\n return 'minmax(120px, 1fr)';\n }).join(' '),\n [visibleColumns]\n );\n\n const sortedData = useMemo(() => {\n if (!sortState) return data;\n const col = columns.find(c => c.id === sortState.columnId);\n if (!col) return data;\n return [...data].sort((a, b) =>\n compareValues(getColumnValue(col, a), getColumnValue(col, b), sortState.direction)\n );\n }, [data, columns, sortState]);\n\n const pagedData = useMemo(() => {\n if (!pagination) return sortedData;\n const start = pagination.pageIndex * pagination.pageSize;\n return sortedData.slice(start, start + pagination.pageSize);\n }, [sortedData, pagination]);\n\n const totalPages = pagination ? Math.ceil(sortedData.length / pagination.pageSize) : 1;\n const isEmpty = !loading && pagedData.length === 0;\n\n const handleSort = (columnId: string) => {\n if (onSort) onSort(columnId);\n };\n\n return (\n <div className={cn(styles.tableWrapper, className)} aria-busy={loading || undefined}>\n <div className={styles.tableScroll}>\n <div className={styles.table} style={{ gridTemplateColumns }} role=\"table\">\n {/* Header */}\n <div className={styles.headerRow} role=\"row\">\n {visibleColumns.map(col => {\n const isSorted = sortState?.columnId === col.id;\n const ariaSort: 'ascending' | 'descending' | 'none' | undefined = col.sortable\n ? (isSorted ? (sortState.direction === 'asc' ? 'ascending' : 'descending') : 'none')\n : undefined;\n const onHeaderActivate = () => col.sortable && handleSort(col.id);\n return (\n <div\n key={col.id}\n className={cn(\n styles.headerCell,\n col.sortable && styles.sortable,\n col.align === 'right' && styles.alignRight,\n col.align === 'center' && styles.alignCenter\n )}\n role=\"columnheader\"\n aria-sort={ariaSort}\n tabIndex={col.sortable ? 0 : undefined}\n onClick={onHeaderActivate}\n onKeyDown={col.sortable ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onHeaderActivate();\n }\n } : undefined}\n style={col.minWidth ? { minWidth: typeof col.minWidth === 'number' ? `${col.minWidth}px` : col.minWidth } : undefined}\n >\n {typeof col.header === 'string' ? (\n <Text variant=\"text-body-small-emphasis\" as=\"span\" color=\"secondary\">\n {col.header}\n </Text>\n ) : col.header}\n {isSorted && (\n <span className={styles.sortIndicator} aria-hidden>\n {sortState.direction === 'asc' ? '\\u2191' : '\\u2193'}\n </span>\n )}\n </div>\n );\n })}\n </div>\n\n {/* Loading skeleton */}\n {loading && Array.from({ length: 5 }).map((_, i) => (\n <div\n key={`skeleton-${i}`}\n className={styles.row}\n role={i === 0 ? 'status' : 'row'}\n aria-label={i === 0 ? 'Loading' : undefined}\n >\n {visibleColumns.map(col => (\n <div key={col.id} className={styles.cell} role=\"cell\">\n <div className={styles.skeleton} />\n </div>\n ))}\n </div>\n ))}\n\n {/* Empty state */}\n {isEmpty && (\n <div className={styles.emptyRow} style={{ gridColumn: `1 / -1` }}>\n <Text variant=\"text-body-medium\" as=\"p\" color=\"secondary\">{emptyMessage}</Text>\n </div>\n )}\n\n {/* Data rows */}\n {!loading && pagedData.map((row, rowIndex) => {\n const isSelected = selectedRows?.has(rowIndex);\n const isClickable = Boolean(onRowClick);\n return (\n <div\n key={rowIndex}\n className={cn(\n styles.row,\n isSelected && styles.rowSelected,\n isClickable && styles.rowClickable\n )}\n role=\"row\"\n tabIndex={isClickable ? 0 : undefined}\n aria-selected={selectedRows ? Boolean(isSelected) : undefined}\n onClick={() => onRowClick?.(row, rowIndex)}\n onKeyDown={isClickable ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onRowClick?.(row, rowIndex);\n }\n } : undefined}\n >\n {visibleColumns.map(col => (\n <div\n key={col.id}\n className={cn(\n styles.cell,\n col.align === 'right' && styles.alignRight,\n col.align === 'center' && styles.alignCenter\n )}\n role=\"cell\"\n >\n {col.renderCell\n ? col.renderCell(row, rowIndex)\n : <Text variant=\"text-body-medium\" as=\"span\" lineTruncation={1}>{String(getColumnValue(col, row) ?? '')}</Text>\n }\n </div>\n ))}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Pagination */}\n {pagination && onPaginationChange && totalPages > 1 && (\n <div className={styles.pagination}>\n <button\n className={styles.pageButton}\n disabled={pagination.pageIndex === 0}\n onClick={() => onPaginationChange(pagination.pageIndex - 1, pagination.pageSize)}\n type=\"button\"\n >\n <Text variant=\"text-body-small\" as=\"span\">Previous</Text>\n </button>\n <Text variant=\"text-body-small\" as=\"span\" color=\"secondary\">\n {`Page ${pagination.pageIndex + 1} of ${totalPages}`}\n </Text>\n <button\n className={styles.pageButton}\n disabled={pagination.pageIndex >= totalPages - 1}\n onClick={() => onPaginationChange(pagination.pageIndex + 1, pagination.pageSize)}\n type=\"button\"\n >\n <Text variant=\"text-body-small\" as=\"span\">Next</Text>\n </button>\n </div>\n )}\n </div>\n );\n}\n\nTable.displayName = 'Table';\n","/* ==========================================================================\n Tab — hover/pressed via direct background-color, no pseudo-element overlay.\n ========================================================================== */\n\n.tab {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n color: var(--color-foreground-secondary);\n position: relative;\n will-change: color;\n transition: color var(--effect-motion-short-2),\n background-color var(--effect-motion-short-2);\n flex-shrink: 0;\n height: var(--dimension-size-400);\n box-sizing: border-box;\n\n /* Interaction — ghost defaults */\n --_hover-bg: var(--color-interaction-hover);\n --_pressed-bg: var(--color-interaction-pressed);\n}\n\n.tab:hover { background-color: var(--_hover-bg); }\n.tab:active { background-color: var(--_pressed-bg); }\n\n.tabSelected { color: var(--color-foreground-primary); }\n\n/* ==========================================================================\n Background context — parent surface awareness\n ========================================================================== */\n\n.onMedium {\n --_hover-bg: var(--color-interaction-on-medium-background-hover);\n --_pressed-bg: var(--color-interaction-on-medium-background-pressed);\n}\n\n.onBold {\n --_hover-bg: var(--color-interaction-on-bold-background-hover);\n --_pressed-bg: var(--color-interaction-on-bold-background-pressed);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.onBold.tabSelected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onStrong {\n --_hover-bg: var(--color-interaction-on-strong-background-hover);\n --_pressed-bg: var(--color-interaction-on-strong-background-pressed);\n color: var(--color-foreground-on-bold-background-secondary);\n}\n\n.onStrong.tabSelected { color: var(--color-foreground-on-bold-background-primary); }\n\n.onAlwaysDark {\n --_hover-bg: var(--color-always-dark-interaction-hover);\n --_pressed-bg: var(--color-always-dark-interaction-pressed);\n color: var(--color-always-dark-foreground-secondary);\n}\n\n.onAlwaysDark.tabSelected { color: var(--color-always-dark-foreground-primary); }\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Tab.module.css';\n\nexport type TabBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';\n\nexport interface TabProps {\n /** id of this tab. Pair with the tabpanel's `aria-labelledby` to wire SR semantics. */\n id?: string;\n /** id of the tabpanel this tab controls. Sets `aria-controls`. */\n controls?: string;\n label: string;\n isSelected?: boolean;\n disabled?: boolean;\n /** Parent surface context. Adjusts hover tokens and fg for tabs on colored backgrounds. */\n background?: TabBackground;\n onClick?: () => void;\n onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;\n onFocus?: React.FocusEventHandler<HTMLButtonElement>;\n /** Override tab order. Defaults to a roving pattern (0 when selected, -1 otherwise). */\n tabIndex?: number;\n className?: string;\n}\n\nexport const Tab = forwardRef<HTMLButtonElement, TabProps>(\n (\n {\n id,\n controls,\n label,\n isSelected = false,\n disabled = false,\n background,\n onClick,\n onKeyDown,\n onFocus,\n tabIndex,\n className,\n },\n ref,\n ) => {\n const bgClass = background && background !== 'faint'\n ? styles[background === 'always-dark' ? 'onAlwaysDark' : `on${background.charAt(0).toUpperCase() + background.slice(1)}`]\n : undefined;\n const effectiveTabIndex = tabIndex ?? (isSelected ? 0 : -1);\n return (\n <button\n ref={ref}\n id={id}\n className={cn(styles.tab, isSelected && styles.tabSelected, bgClass, className)}\n onClick={onClick}\n onKeyDown={onKeyDown}\n onFocus={onFocus}\n type=\"button\"\n role=\"tab\"\n aria-selected={isSelected}\n aria-controls={controls}\n aria-disabled={disabled || undefined}\n disabled={disabled}\n tabIndex={effectiveTabIndex}\n >\n <Text variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'} as=\"span\">\n {label}\n </Text>\n </button>\n );\n }\n);\n\nTab.displayName = 'Tab';\n",".emptyState {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n min-height: 400px;\n width: 100%;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './EmptyState.module.css';\n\nexport type EmptyStateType = 'no-content' | 'no-results' | 'no-results-filter' | 'no-access';\n\nconst defaultMessages: Record<EmptyStateType, string> = {\n 'no-content': 'No page contents to display.',\n 'no-results': 'No results found.',\n 'no-results-filter': 'No results found. Please update search criteria.',\n 'no-access': \"You don't have access to this page.\",\n};\n\nexport interface EmptyStateProps {\n type?: EmptyStateType;\n message?: string;\n className?: string;\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(\n ({ type = 'no-content', message, className }, ref) => (\n <div ref={ref} className={cn(styles.emptyState, className)}>\n <Text variant=\"text-body-medium\" as=\"p\" color=\"secondary\">\n {message || defaultMessages[type]}\n </Text>\n </div>\n )\n);\n\nEmptyState.displayName = 'EmptyState';\n",".fade {\n position: absolute;\n pointer-events: none;\n z-index: 10;\n transform: translateZ(0);\n backface-visibility: hidden;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .fade { transition: none; }\n}\n\n.fadeTop {\n top: 0; left: 0; right: 0;\n background: linear-gradient(to bottom, var(--background) 0%, var(--background) 50%, transparent 100%);\n}\n\n.fadeBottom {\n bottom: 0; left: 0; right: 0;\n background: linear-gradient(to top, var(--background) 0%, transparent 100%);\n}\n\n.fadeLeft {\n top: 0; bottom: 0; left: 0;\n background: linear-gradient(to right, var(--background) 0%, transparent 100%);\n}\n\n.fadeRight {\n top: 0; bottom: 0; right: 0;\n background: linear-gradient(to left, var(--background) 0%, transparent 100%);\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Fade.module.css';\n\nexport type FadeSide = 'top' | 'bottom' | 'left' | 'right';\n\nexport interface FadeProps {\n side: FadeSide;\n height: string;\n background?: string;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst sideClassMap: Record<FadeSide, string> = {\n top: 'fadeTop',\n bottom: 'fadeBottom',\n left: 'fadeLeft',\n right: 'fadeRight',\n};\n\nexport const Fade = forwardRef<HTMLDivElement, FadeProps>(\n ({ side, height, background = 'var(--color-background-secondary)', className, style = {} }, ref) => (\n <div\n ref={ref}\n className={cn(styles.fade, styles[sideClassMap[side]], className)}\n style={{ ...style, height, '--background': background } as React.CSSProperties}\n aria-hidden=\"true\"\n />\n )\n);\n\nFade.displayName = 'Fade';\n",".container {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n.content {\n width: 100%;\n height: 100%;\n min-height: 0;\n overflow-y: auto;\n overflow-x: auto;\n scrollbar-width: none;\n -ms-overflow-style: none;\n}\n\n.content::-webkit-scrollbar { display: none; }\n\n.content:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-interaction-focus);\n outline-offset: calc(var(--dimension-space-025) * -1);\n}\n\n.track {\n position: absolute;\n top: 0; right: 0; bottom: 0;\n width: var(--dimension-size-050, 4px);\n pointer-events: none;\n z-index: 10;\n opacity: 0;\n transition: opacity var(--effect-motion-short-2);\n}\n\n.container[data-show-track='true'] .track {\n opacity: 1;\n pointer-events: auto;\n}\n\n.thumb {\n position: absolute;\n right: 0;\n width: var(--dimension-size-050, 4px);\n cursor: grab;\n border-radius: 0;\n background-color: var(--color-foreground-quaternary);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.thumb:active { cursor: grabbing; }\n\n.trackHorizontal {\n position: absolute;\n left: 0; right: 0; bottom: 0;\n height: var(--dimension-size-050, 4px);\n pointer-events: none;\n z-index: 10;\n opacity: 0;\n transition: opacity var(--effect-motion-short-2);\n}\n\n.container[data-show-track='true'] .trackHorizontal {\n opacity: 1;\n pointer-events: auto;\n}\n\n.thumbHorizontal {\n position: absolute;\n bottom: 0;\n height: var(--dimension-size-050, 4px);\n cursor: grab;\n border-radius: 0;\n background-color: var(--color-foreground-quaternary);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.thumbHorizontal:active { cursor: grabbing; }\n\n.thick .track { width: var(--dimension-size-100, 8px); }\n.thick .thumb { width: var(--dimension-size-100, 8px); }\n.thick .trackHorizontal { height: var(--dimension-size-100, 8px); }\n.thick .thumbHorizontal { height: var(--dimension-size-100, 8px); }\n","import React, { useRef, useEffect, useState, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Scrollbar.module.css';\n\nexport type ScrollbarVariant = 'default' | 'thick';\n\nexport interface ScrollbarProps {\n children: React.ReactNode;\n className?: string;\n variant?: ScrollbarVariant;\n showTrackOnHover?: boolean;\n onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;\n fadeOverlay?: React.ReactNode;\n contentRef?: React.RefObject<HTMLDivElement>;\n}\n\nexport const Scrollbar: React.FC<ScrollbarProps> = ({\n children,\n className,\n variant = 'default',\n showTrackOnHover = true,\n onScroll,\n fadeOverlay,\n contentRef: externalContentRef,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const internalContentRef = useRef<HTMLDivElement>(null);\n const contentRef = externalContentRef || internalContentRef;\n const thumbRef = useRef<HTMLDivElement>(null);\n const thumbHRef = useRef<HTMLDivElement>(null);\n const [thumbHeight, setThumbHeight] = useState(0);\n const [thumbTop, setThumbTop] = useState(0);\n const [thumbWidth, setThumbWidth] = useState(0);\n const [thumbLeft, setThumbLeft] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const [isDraggingH, setIsDraggingH] = useState(false);\n const [isPointerInside, setIsPointerInside] = useState(false);\n const dragStartY = useRef(0);\n const dragStartScrollTop = useRef(0);\n const dragStartX = useRef(0);\n const dragStartScrollLeft = useRef(0);\n\n const handleMouseEnter = useCallback(() => {\n if (showTrackOnHover) setIsPointerInside(true);\n }, [showTrackOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n setIsPointerInside(false);\n }, []);\n\n const updateThumb = useCallback(() => {\n const container = containerRef.current;\n const content = contentRef.current;\n if (!container || !content) return;\n\n const containerHeight = container.clientHeight;\n const containerWidth = container.clientWidth;\n const contentHeight = content.scrollHeight;\n const contentWidth = content.scrollWidth;\n const scrollTop = content.scrollTop;\n const scrollLeft = content.scrollLeft;\n\n if (contentHeight <= containerHeight) {\n setThumbHeight(0);\n } else {\n const ratio = containerHeight / contentHeight;\n const h = Math.max(20, containerHeight * ratio);\n setThumbHeight(h);\n setThumbTop((scrollTop / (contentHeight - containerHeight)) * (containerHeight - h));\n }\n\n if (contentWidth <= containerWidth) {\n setThumbWidth(0);\n } else {\n const ratio = containerWidth / contentWidth;\n const w = Math.max(20, containerWidth * ratio);\n setThumbWidth(w);\n setThumbLeft((scrollLeft / (contentWidth - containerWidth)) * (containerWidth - w));\n }\n }, [contentRef]);\n\n useEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n const handleScroll = (e: Event) => {\n updateThumb();\n if (onScroll) onScroll(e as unknown as React.UIEvent<HTMLDivElement>);\n };\n content.addEventListener('scroll', handleScroll);\n return () => content.removeEventListener('scroll', handleScroll);\n }, [updateThumb, onScroll, contentRef]);\n\n useEffect(() => {\n const content = contentRef.current;\n if (!content) return;\n const handleResize = () => updateThumb();\n window.addEventListener('resize', handleResize);\n if (typeof ResizeObserver !== 'undefined') {\n const observer = new ResizeObserver(handleResize);\n observer.observe(content);\n return () => { window.removeEventListener('resize', handleResize); observer.disconnect(); };\n }\n return () => window.removeEventListener('resize', handleResize);\n }, [updateThumb, contentRef]);\n\n useEffect(() => { updateThumb(); }, [updateThumb, children]);\n\n const handleThumbMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const content = contentRef.current;\n if (!content) return;\n setIsDragging(true);\n dragStartY.current = e.clientY;\n dragStartScrollTop.current = content.scrollTop;\n const handleMouseMove = (e: MouseEvent) => {\n const container = containerRef.current;\n if (!container || !content) return;\n const deltaY = e.clientY - dragStartY.current;\n const scrollableHeight = content.scrollHeight - container.clientHeight;\n const scrollRatio = scrollableHeight / (container.clientHeight - thumbHeight);\n content.scrollTop = Math.max(0, Math.min(scrollableHeight, dragStartScrollTop.current + deltaY * scrollRatio));\n };\n const handleMouseUp = () => {\n setIsDragging(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [thumbHeight, contentRef]);\n\n const handleThumbHMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const content = contentRef.current;\n if (!content) return;\n setIsDraggingH(true);\n dragStartX.current = e.clientX;\n dragStartScrollLeft.current = content.scrollLeft;\n const handleMouseMove = (e: MouseEvent) => {\n const container = containerRef.current;\n if (!container || !content) return;\n const deltaX = e.clientX - dragStartX.current;\n const scrollableWidth = content.scrollWidth - container.clientWidth;\n const scrollRatio = scrollableWidth / (container.clientWidth - thumbWidth);\n content.scrollLeft = Math.max(0, Math.min(scrollableWidth, dragStartScrollLeft.current + deltaX * scrollRatio));\n };\n const handleMouseUp = () => {\n setIsDraggingH(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [thumbWidth, contentRef]);\n\n const showThumb = thumbHeight > 0;\n const showThumbH = thumbWidth > 0;\n const showTrack = showTrackOnHover && (isPointerInside || isDragging || isDraggingH);\n const isScrollable = showThumb || showThumbH;\n\n // A11y model: the custom thumbs are a visual reskin of the native scrollbar,\n // not a separate widget. The `.content` div retains native `overflow: auto`,\n // so when it is focusable the browser handles arrow keys, Page Up/Down,\n // Home/End, and Space for free — implementing the full `role=\"scrollbar\"`\n // ARIA pattern would just re-create that behavior. We therefore expose the\n // scroll container itself as the keyboard target (tabIndex=0 only when\n // content overflows) and hide the decorative thumbs from assistive tech.\n return (\n <div\n ref={containerRef}\n className={cn(styles.container, variant === 'thick' && styles.thick, className)}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n data-dragging={isDragging || isDraggingH}\n data-show-track={showTrack ? 'true' : 'false'}\n >\n <div\n ref={contentRef}\n className={styles.content}\n tabIndex={isScrollable ? 0 : undefined}\n >\n {children}\n </div>\n {fadeOverlay}\n {showThumb && (\n <div className={styles.track} aria-hidden=\"true\">\n <div ref={thumbRef} className={styles.thumb} style={{ height: `${thumbHeight}px`, top: `${thumbTop}px` }} onMouseDown={handleThumbMouseDown} />\n </div>\n )}\n {showThumbH && (\n <div className={styles.trackHorizontal} aria-hidden=\"true\">\n <div ref={thumbHRef} className={styles.thumbHorizontal} style={{ width: `${thumbWidth}px`, left: `${thumbLeft}px` }} onMouseDown={handleThumbHMouseDown} />\n </div>\n )}\n </div>\n );\n};\n\nScrollbar.displayName = 'Scrollbar';\n",".errorBoundary {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n min-height: 400px;\n padding: var(--dimension-space-400);\n gap: var(--dimension-space-200);\n}\n\n.errorDetails {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--dimension-space-200);\n max-width: 600px;\n text-align: center;\n}\n","import React, { Component, ReactNode } from 'react';\nimport { EmptyState } from '@/components/EmptyState';\nimport { Text } from '@/components/Text';\nimport styles from './ErrorBoundary.module.css';\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n override componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n console.error('ErrorBoundary caught an error:', error, errorInfo);\n }\n\n handleReset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n override render() {\n if (this.state.hasError) {\n if (this.props.fallback) return this.props.fallback;\n return (\n <div className={styles.errorBoundary}>\n <EmptyState type=\"no-content\" />\n <div className={styles.errorDetails}>\n <Text variant=\"text-body-small\" as=\"p\" color=\"secondary\">\n Something went wrong. Please refresh the page.\n </Text>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","/* Sidebar */\n.sidebar {\n display: flex;\n flex-direction: column;\n height: 100%;\n background-color: var(--color-background-secondary);\n border-right: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n position: relative;\n flex-shrink: 0;\n overflow: hidden;\n transition: width var(--effect-motion-short-2);\n}\n\n.sidebar.resizing { transition: none; }\n\n.sidebar.collapsed { width: 0 !important; border-right: none; }\n\n.sidebar.mobile {\n position: fixed;\n top: 0;\n left: 0;\n bottom: 0;\n z-index: 9997;\n}\n\n.sidebar.mini .itemLabel { display: none; }\n.sidebar.mini .itemBadge { display: none; }\n.sidebar.mini .sectionHeader { display: none; }\n\n.backdrop {\n position: fixed;\n inset: 0;\n background-color: var(--color-background-shade);\n z-index: 9996;\n}\n\n.content {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n padding: var(--dimension-space-050);\n scrollbar-width: none;\n}\n\n.content::-webkit-scrollbar { display: none; }\n\n.footer {\n flex-shrink: 0;\n padding: var(--dimension-space-050);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n/* Resize Handle */\n.resizeHandle {\n position: absolute;\n top: 0;\n right: -3px;\n bottom: 0;\n width: 6px;\n cursor: col-resize;\n z-index: 10;\n}\n\n.resizeHandle:hover {\n background-color: var(--color-border-brand);\n opacity: 0.5;\n}\n\n.resizeHandle:focus-visible {\n outline: var(--dimension-stroke-width-025) solid var(--color-border-brand);\n outline-offset: var(--dimension-stroke-width-015);\n background-color: var(--color-border-brand);\n opacity: 0.5;\n}\n\n/* Sections */\n.section {\n display: flex;\n flex-direction: column;\n}\n\n.section + .section {\n margin-top: var(--dimension-space-050);\n padding-top: var(--dimension-space-050);\n border-top: var(--dimension-stroke-width-015) solid var(--color-border-primary);\n}\n\n.sectionHeader {\n padding: var(--dimension-space-050) var(--dimension-space-075);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.sectionHeaderClickable { cursor: pointer; }\n\n.sectionItems {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n}\n\n/* Items */\n.itemWrapper {\n display: flex;\n flex-direction: column;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-075);\n padding: var(--dimension-space-075);\n background-color: transparent;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n width: 100%;\n text-align: left;\n position: relative;\n min-height: var(--dimension-size-400);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.item::before {\n content: '';\n position: absolute;\n inset: 0;\n background-color: transparent;\n border-radius: var(--dimension-radius-075);\n transition: var(--effect-transition-interaction-background-short-2);\n pointer-events: none;\n}\n\n.item:hover::before { background-color: var(--color-interaction-hover); }\n.item:active::before { background-color: var(--color-interaction-pressed); }\n\n.itemSelected { background-color: var(--color-background-faint-brand); }\n.itemSelected::before { display: none; }\n\n.itemDisabled { opacity: 0.5; cursor: not-allowed; pointer-events: none; }\n\n.itemIcon {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n color: var(--color-foreground-secondary);\n}\n\n.itemSelected .itemIcon { color: var(--color-foreground-primary); }\n\n.itemLabel {\n flex: 1;\n min-width: 0;\n}\n\n.itemBadge {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n}\n\n/* Sub-items */\n.subItems {\n display: flex;\n flex-direction: column;\n padding-left: var(--dimension-space-300);\n gap: var(--dimension-space-025);\n}\n","import React, { forwardRef, useRef, useCallback, useEffect, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Sidebar.module.css';\n\nexport type SidebarWidth = 'mini' | 'default' | number;\n\nexport interface SidebarProps {\n children: React.ReactNode;\n isCollapsed?: boolean;\n onToggle?: () => void;\n width?: SidebarWidth;\n onWidthChange?: (width: SidebarWidth) => void;\n resizable?: boolean;\n footer?: React.ReactNode;\n className?: string;\n isMobile?: boolean;\n}\n\nconst MINI_WIDTH = 56;\nconst DEFAULT_WIDTH = 240;\nconst MAX_WIDTH = 480;\nconst MIN_DRAG_WIDTH = 180;\nconst SNAP_THRESHOLD = 140;\nconst KEYBOARD_STEP = 16;\n\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\nexport const Sidebar = forwardRef<HTMLElement, SidebarProps>(\n ({\n children,\n isCollapsed = false,\n onToggle,\n width = 'default',\n onWidthChange,\n resizable = true,\n footer,\n className,\n isMobile = false,\n }, ref) => {\n const internalRef = useRef<HTMLElement>(null);\n const sidebarRef = (ref as React.RefObject<HTMLElement>) || internalRef;\n const triggerRef = useRef<HTMLElement | null>(null);\n const [isResizing, setIsResizing] = useState(false);\n\n const isMini = width === 'mini';\n const resolvedWidth = width === 'mini' ? MINI_WIDTH : width === 'default' ? DEFAULT_WIDTH : width;\n\n const handleMouseDown = useCallback((e: React.MouseEvent) => {\n if (!resizable || !onWidthChange) return;\n e.preventDefault();\n setIsResizing(true);\n\n const handleMouseMove = (e: MouseEvent) => {\n const newWidth = e.clientX;\n if (newWidth < SNAP_THRESHOLD) {\n onWidthChange('mini');\n } else if (newWidth < MIN_DRAG_WIDTH) {\n onWidthChange('default');\n } else {\n onWidthChange(newWidth);\n }\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n };\n\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n }, [resizable, onWidthChange]);\n\n // Keyboard resize: arrows step, Home → mini, End → max.\n // Stepping below MIN_DRAG_WIDTH snaps to 'mini'; stepping up from 'mini' snaps to 'default'.\n const handleResizeKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (!resizable || !onWidthChange) return;\n switch (e.key) {\n case 'ArrowLeft': {\n e.preventDefault();\n if (width === 'mini') return;\n const next = resolvedWidth - KEYBOARD_STEP;\n onWidthChange(next < MIN_DRAG_WIDTH ? 'mini' : next);\n break;\n }\n case 'ArrowRight': {\n e.preventDefault();\n if (width === 'mini') {\n onWidthChange('default');\n return;\n }\n const next = Math.min(resolvedWidth + KEYBOARD_STEP, MAX_WIDTH);\n onWidthChange(next);\n break;\n }\n case 'Home':\n e.preventDefault();\n onWidthChange('mini');\n break;\n case 'End':\n e.preventDefault();\n onWidthChange(MAX_WIDTH);\n break;\n }\n }, [resizable, onWidthChange, width, resolvedWidth]);\n\n // Close sidebar on Escape (mobile)\n useEffect(() => {\n if (!isMobile || isCollapsed) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onToggle?.();\n };\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [isMobile, isCollapsed, onToggle]);\n\n // Mobile dialog: capture trigger, focus first element, trap Tab, restore focus on close.\n const isMobileOpen = isMobile && !isCollapsed;\n useEffect(() => {\n if (!isMobileOpen) return;\n triggerRef.current = (document.activeElement as HTMLElement) ?? null;\n\n const container = sidebarRef.current;\n if (!container) return;\n\n const focusables = () =>\n Array.from(container.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('aria-hidden') && el.offsetParent !== null,\n );\n\n const initial = focusables();\n (initial[0] ?? container).focus();\n\n const handleTab = (e: KeyboardEvent) => {\n if (e.key !== 'Tab') return;\n const items = focusables();\n if (items.length === 0) {\n e.preventDefault();\n container.focus();\n return;\n }\n const first = items[0];\n const last = items[items.length - 1];\n const active = document.activeElement as HTMLElement | null;\n if (e.shiftKey && (active === first || !container.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (active === last || !container.contains(active))) {\n e.preventDefault();\n first.focus();\n }\n };\n\n document.addEventListener('keydown', handleTab);\n return () => {\n document.removeEventListener('keydown', handleTab);\n triggerRef.current?.focus?.();\n triggerRef.current = null;\n };\n }, [isMobileOpen, sidebarRef]);\n\n if (isCollapsed && !isMobile) return null;\n\n const dialogProps = isMobileOpen\n ? { role: 'dialog' as const, 'aria-modal': true, tabIndex: -1 }\n : { role: 'navigation' as const };\n\n return (\n <>\n {/* Mobile backdrop — mouse-only convenience; Escape handler covers keyboard. */}\n {isMobile && !isCollapsed && (\n <div className={styles.backdrop} onClick={onToggle} aria-hidden=\"true\" />\n )}\n <aside\n ref={sidebarRef}\n className={cn(\n styles.sidebar,\n isMini && styles.mini,\n isMobile && styles.mobile,\n isCollapsed && styles.collapsed,\n isResizing && styles.resizing,\n className\n )}\n style={{ width: isCollapsed ? 0 : resolvedWidth }}\n aria-label=\"Sidebar\"\n {...dialogProps}\n >\n <div className={styles.content}>\n {children}\n </div>\n {footer && (\n <div className={styles.footer}>\n {footer}\n </div>\n )}\n {resizable && !isMobile && (\n <div\n className={styles.resizeHandle}\n onMouseDown={handleMouseDown}\n onKeyDown={handleResizeKeyDown}\n role=\"separator\"\n aria-orientation=\"vertical\"\n aria-label=\"Resize sidebar\"\n aria-valuenow={resolvedWidth}\n aria-valuemin={MINI_WIDTH}\n aria-valuemax={MAX_WIDTH}\n tabIndex={0}\n />\n )}\n </aside>\n </>\n );\n }\n);\n\nSidebar.displayName = 'Sidebar';\n","import React, { forwardRef, useState } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Sidebar.module.css';\n\nexport interface SidebarSectionProps {\n label?: string;\n children: React.ReactNode;\n collapsible?: boolean;\n defaultCollapsed?: boolean;\n className?: string;\n}\n\nexport const SidebarSection = forwardRef<HTMLDivElement, SidebarSectionProps>(\n ({ label, children, collapsible = false, defaultCollapsed = false, className }, ref) => {\n const [isCollapsed, setIsCollapsed] = useState(defaultCollapsed);\n\n return (\n <div ref={ref} className={cn(styles.section, className)}>\n {label && (\n <div\n className={cn(styles.sectionHeader, collapsible && styles.sectionHeaderClickable)}\n onClick={collapsible ? () => setIsCollapsed(prev => !prev) : undefined}\n role={collapsible ? 'button' : undefined}\n aria-expanded={collapsible ? !isCollapsed : undefined}\n >\n <Text variant=\"text-caption-emphasis\" as=\"span\" color=\"tertiary\">\n {label}\n </Text>\n </div>\n )}\n {!isCollapsed && (\n <div className={styles.sectionItems}>\n {children}\n </div>\n )}\n </div>\n );\n }\n);\n\nSidebarSection.displayName = 'SidebarSection';\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport type { IconComponent } from '@/types';\nimport styles from './Sidebar.module.css';\n\nexport interface SidebarItemProps {\n label: string;\n icon?: IconComponent;\n isSelected?: boolean;\n isDisabled?: boolean;\n onClick?: () => void;\n badge?: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n}\n\nexport const SidebarItem = forwardRef<HTMLButtonElement, SidebarItemProps>(\n ({ label, icon: Icon, isSelected = false, isDisabled = false, onClick, badge, children, className }, ref) => (\n <div className={cn(styles.itemWrapper, className)}>\n <button\n ref={ref}\n className={cn(\n styles.item,\n isSelected && styles.itemSelected,\n isDisabled && styles.itemDisabled\n )}\n onClick={onClick}\n disabled={isDisabled}\n type=\"button\"\n aria-current={isSelected ? 'page' : undefined}\n >\n {Icon && (\n <span className={styles.itemIcon}>\n <Icon size={20} />\n </span>\n )}\n <Text\n variant={isSelected ? 'text-body-medium-emphasis' : 'text-body-medium'}\n as=\"span\"\n className={styles.itemLabel}\n lineTruncation={1}\n >\n {label}\n </Text>\n {badge && <span className={styles.itemBadge}>{badge}</span>}\n </button>\n {children && isSelected && (\n <div className={styles.subItems}>\n {children}\n </div>\n )}\n </div>\n )\n);\n\nSidebarItem.displayName = 'SidebarItem';\n",".header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n height: var(--dimension-size-600, 48px);\n padding: 0 var(--dimension-space-100);\n flex-shrink: 0;\n gap: var(--dimension-space-100);\n}\n\n.left {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-100);\n flex-shrink: 0;\n min-width: 0;\n}\n\n.center {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: var(--dimension-space-050);\n flex: 1;\n min-width: 0;\n}\n\n.right {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n flex-shrink: 0;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Surface } from '@/components/Surface';\nimport { Text } from '@/components/Text';\nimport styles from './Header.module.css';\n\nexport type HeaderBackground = 'primary' | 'secondary' | 'transparent' | 'translucent';\n\nexport interface HeaderProps {\n title?: string;\n left?: React.ReactNode;\n center?: React.ReactNode;\n right?: React.ReactNode;\n background?: HeaderBackground;\n className?: string;\n}\n\nexport const Header = forwardRef<HTMLElement, HeaderProps>(\n ({ title, left, center, right, background = 'secondary', className }, ref) => (\n <Surface\n ref={ref}\n as=\"header\"\n background={background}\n elevation=\"none\"\n edge=\"bottom\"\n className={cn(styles.header, className)}\n >\n <div className={styles.left}>\n {left}\n {title && !center && (\n <Text variant=\"text-title-small\" as=\"h1\" lineTruncation={1}>\n {title}\n </Text>\n )}\n </div>\n {center && <div className={styles.center}>{center}</div>}\n <div className={styles.right}>{right}</div>\n </Surface>\n )\n);\n\nHeader.displayName = 'Header';\n",".group {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-025);\n}\n\n.horizontal {\n flex-direction: row;\n gap: var(--dimension-space-100);\n}\n\n/* ─── Radio item ────────────────────────────────────────────────────────────── */\n\n.radio {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n padding: var(--dimension-space-075);\n height: var(--dimension-size-400);\n box-sizing: border-box;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n border-radius: var(--dimension-radius-075);\n transition: background-color var(--effect-motion-short-2);\n}\n\n.radio:hover { background-color: var(--color-interaction-hover); }\n.radio:active { background-color: var(--color-interaction-pressed); }\n\n.inactive {\n cursor: not-allowed;\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Circle indicator ──────────────────────────────────────────────────────── */\n\n.circle {\n width: 20px;\n height: 20px;\n border: 1.5px solid var(--color-foreground-secondary);\n border-radius: var(--dimension-radius-half);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n transition: all var(--effect-motion-short-2);\n box-sizing: border-box;\n}\n\n.circleChecked {\n border-color: var(--color-foreground-primary);\n}\n\n.dot {\n width: 10px;\n height: 10px;\n border-radius: var(--dimension-radius-half);\n background-color: var(--color-foreground-primary);\n}\n","import React, { forwardRef, useRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Radio.module.css';\n\nexport interface RadioOption {\n label: string;\n value: string;\n inactive?: boolean;\n}\n\nexport interface RadioGroupProps {\n /** Currently selected value. */\n value: string;\n /** Called when selection changes. */\n onChange: (value: string) => void;\n /** Radio options to render. */\n options: RadioOption[];\n /** Accessible name for the group. One of `aria-label` or `aria-labelledby` is required. */\n 'aria-label'?: string;\n /** ID of an element labeling the group. One of `aria-label` or `aria-labelledby` is required. */\n 'aria-labelledby'?: string;\n /** Layout direction. */\n direction?: 'vertical' | 'horizontal';\n /** Disables the entire group. */\n inactive?: boolean;\n className?: string;\n}\n\nexport const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n (\n {\n value,\n onChange,\n options,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n direction = 'vertical',\n inactive = false,\n className,\n },\n ref\n ) => {\n if (!ariaLabel && !ariaLabelledBy) {\n const env = (globalThis as { process?: { env?: { NODE_ENV?: string } } })\n .process?.env?.NODE_ENV;\n if (env !== 'production') {\n console.warn(\n 'RadioGroup: an accessible name is required. Pass either `aria-label` or `aria-labelledby`.'\n );\n }\n }\n\n const itemRefs = useRef<Array<HTMLDivElement | null>>([]);\n\n const isActive = (i: number) =>\n i >= 0 && i < options.length && !inactive && !options[i].inactive;\n\n const activeIndices = options.reduce<number[]>((acc, _, i) => {\n if (isActive(i)) acc.push(i);\n return acc;\n }, []);\n\n const selectedIdx = options.findIndex(o => o.value === value);\n const focusableIdx = isActive(selectedIdx)\n ? selectedIdx\n : (activeIndices[0] ?? -1);\n\n const focusAndSelect = (i: number) => {\n itemRefs.current[i]?.focus();\n if (options[i].value !== value) onChange(options[i].value);\n };\n\n const moveFocus = (from: number, delta: 1 | -1) => {\n if (activeIndices.length === 0) return;\n const pos = activeIndices.indexOf(from);\n // If focus somehow lands on an inactive radio, anchor at the boundary so\n // the first arrow keystroke moves to the nearest active option.\n const startPos = pos === -1 ? (delta === 1 ? -1 : 0) : pos;\n const nextPos =\n (startPos + delta + activeIndices.length) % activeIndices.length;\n focusAndSelect(activeIndices[nextPos]);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement;\n const idx = itemRefs.current.findIndex(el => el === target);\n if (idx === -1) return;\n\n switch (e.key) {\n case 'ArrowDown':\n case 'ArrowRight':\n e.preventDefault();\n moveFocus(idx, 1);\n break;\n case 'ArrowUp':\n case 'ArrowLeft':\n e.preventDefault();\n moveFocus(idx, -1);\n break;\n case 'Home':\n e.preventDefault();\n if (activeIndices.length) focusAndSelect(activeIndices[0]);\n break;\n case 'End':\n e.preventDefault();\n if (activeIndices.length)\n focusAndSelect(activeIndices[activeIndices.length - 1]);\n break;\n }\n };\n\n return (\n <div\n ref={ref}\n role=\"radiogroup\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n onKeyDown={handleKeyDown}\n className={cn(\n styles.group,\n direction === 'horizontal' && styles.horizontal,\n className\n )}\n >\n {options.map((opt, i) => (\n <RadioItem\n key={opt.value}\n ref={el => {\n itemRefs.current[i] = el;\n }}\n label={opt.label}\n checked={value === opt.value}\n inactive={inactive || opt.inactive}\n tabIndex={i === focusableIdx ? 0 : -1}\n onChange={() => onChange(opt.value)}\n />\n ))}\n </div>\n );\n }\n);\n\nRadioGroup.displayName = 'RadioGroup';\n\n/* ─── Individual Radio Item ─────────────────────────────────────────────────── */\n\nexport interface RadioItemProps {\n label: string;\n checked?: boolean;\n onChange?: () => void;\n inactive?: boolean;\n /** Roving tabindex value. RadioGroup manages this; defaults to -1 when inactive, else 0. */\n tabIndex?: number;\n className?: string;\n}\n\nexport const RadioItem = forwardRef<HTMLDivElement, RadioItemProps>(\n (\n { label, checked = false, onChange, inactive = false, tabIndex, className },\n ref\n ) => {\n const handleActivate = () => {\n if (!inactive && !checked) onChange?.();\n };\n\n const resolvedTabIndex = tabIndex ?? (inactive ? -1 : 0);\n\n return (\n <div\n ref={ref}\n role=\"radio\"\n aria-checked={checked}\n aria-disabled={inactive || undefined}\n tabIndex={resolvedTabIndex}\n className={cn(styles.radio, inactive && styles.inactive, className)}\n onClick={handleActivate}\n onKeyDown={e => {\n if (e.key === ' ' || e.key === 'Enter') {\n e.preventDefault();\n handleActivate();\n }\n }}\n >\n <span className={cn(styles.circle, checked && styles.circleChecked)}>\n {checked && <span className={styles.dot} />}\n </span>\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n </div>\n );\n }\n);\n\nRadioItem.displayName = 'RadioItem';\n",".tabGroup {\n display: flex;\n flex-direction: column;\n position: relative;\n}\n\n.tabsRow {\n display: flex;\n gap: var(--dimension-space-025);\n}\n\n.track {\n height: 2px;\n background-color: var(--color-border-secondary);\n position: relative;\n}\n\n.indicator {\n position: absolute;\n bottom: 0;\n height: 2px;\n background-color: var(--color-foreground-primary);\n border-radius: 1px;\n transition: transform var(--effect-motion-short-3), width var(--effect-motion-short-3);\n will-change: transform, width;\n}\n","import React, { forwardRef, useRef, useEffect, useState, useCallback } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Tab } from '@/components/Tab';\nimport styles from './TabGroup.module.css';\n\nexport interface TabGroupTab {\n label: string;\n /** id for the tab. Pair with `panelId` to wire SR semantics on the consumer's tabpanel. */\n id?: string;\n /** id of the tabpanel this tab controls. Forwarded to the Tab as `aria-controls`. */\n panelId?: string;\n disabled?: boolean;\n}\n\nexport interface TabGroupProps {\n /** Tab definitions. */\n tabs: TabGroupTab[];\n /** Index of the active tab. */\n activeIndex?: number;\n /** Called when a tab is activated (click or keyboard). */\n onTabChange?: (index: number) => void;\n /** Tablist orientation. Determines which arrow keys navigate. */\n orientation?: 'horizontal' | 'vertical';\n /** Accessible label for the tablist. */\n 'aria-label'?: string;\n /** id of an external label for the tablist. */\n 'aria-labelledby'?: string;\n className?: string;\n}\n\nexport const TabGroup = forwardRef<HTMLDivElement, TabGroupProps>(\n (\n {\n tabs,\n activeIndex = 0,\n onTabChange,\n orientation = 'horizontal',\n className,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n },\n ref,\n ) => {\n const tabsRef = useRef<(HTMLButtonElement | null)[]>([]);\n const [indicator, setIndicator] = useState({ left: 0, width: 0 });\n\n const updateIndicator = useCallback(() => {\n const el = tabsRef.current[activeIndex];\n if (el) {\n setIndicator({\n left: el.offsetLeft,\n width: el.offsetWidth,\n });\n }\n }, [activeIndex]);\n\n useEffect(() => {\n updateIndicator();\n }, [updateIndicator]);\n\n useEffect(() => {\n const observer = new ResizeObserver(updateIndicator);\n const container = tabsRef.current[0]?.parentElement;\n if (container) observer.observe(container);\n return () => observer.disconnect();\n }, [updateIndicator]);\n\n const findEnabled = useCallback(\n (from: number, step: number): number => {\n const len = tabs.length;\n if (len === 0) return from;\n let i = from;\n for (let n = 0; n < len; n++) {\n i = (i + step + len) % len;\n if (!tabs[i].disabled) return i;\n }\n return from;\n },\n [tabs],\n );\n\n const activate = useCallback(\n (index: number) => {\n if (index !== activeIndex) onTabChange?.(index);\n tabsRef.current[index]?.focus();\n },\n [activeIndex, onTabChange],\n );\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const isHorizontal = orientation !== 'vertical';\n const nextKey = isHorizontal ? 'ArrowRight' : 'ArrowDown';\n const prevKey = isHorizontal ? 'ArrowLeft' : 'ArrowUp';\n\n let nextIndex: number | null = null;\n if (e.key === nextKey) {\n nextIndex = findEnabled(activeIndex, 1);\n } else if (e.key === prevKey) {\n nextIndex = findEnabled(activeIndex, -1);\n } else if (e.key === 'Home') {\n nextIndex = findEnabled(-1, 1);\n } else if (e.key === 'End') {\n nextIndex = findEnabled(tabs.length, -1);\n }\n\n if (nextIndex !== null) {\n e.preventDefault();\n activate(nextIndex);\n }\n };\n\n return (\n <div\n ref={ref}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-orientation={orientation === 'vertical' ? 'vertical' : undefined}\n onKeyDown={handleKeyDown}\n className={cn(styles.tabGroup, className)}\n >\n <div className={styles.tabsRow}>\n {tabs.map((tab, i) => (\n <Tab\n key={tab.id ?? i}\n ref={el => { tabsRef.current[i] = el; }}\n id={tab.id}\n controls={tab.panelId}\n label={tab.label}\n isSelected={i === activeIndex}\n disabled={tab.disabled}\n onClick={() => onTabChange?.(i)}\n />\n ))}\n </div>\n <div className={styles.track}>\n <div\n className={styles.indicator}\n style={{\n transform: `translateX(${indicator.left}px)`,\n width: indicator.width,\n }}\n />\n </div>\n </div>\n );\n }\n);\n\nTabGroup.displayName = 'TabGroup';\n",".accordion {\n display: flex;\n flex-direction: column;\n}\n\n/* ─── Item ──────────────────────────────────────────────────────────────────── */\n\n.item {\n border-bottom: 1px solid var(--color-border-secondary);\n}\n\n.item:first-child {\n border-top: 1px solid var(--color-border-secondary);\n}\n\n.inactive {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Trigger ───────────────────────────────────────────────────────────────── */\n\n.trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: var(--dimension-space-100) var(--dimension-space-050);\n background: none;\n border: none;\n cursor: pointer;\n color: var(--color-foreground-primary);\n border-radius: var(--dimension-radius-050);\n transition: background-color var(--effect-motion-short-2);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.trigger:hover { background-color: var(--color-interaction-hover); }\n.trigger:active { background-color: var(--color-interaction-pressed); }\n\n/* ─── Chevron ───────────────────────────────────────────────────────────────── */\n\n.chevron {\n font-size: 18px;\n line-height: 1;\n transform: rotate(0deg);\n transition: transform var(--effect-motion-short-3);\n color: var(--color-foreground-secondary);\n}\n\n.chevronOpen {\n transform: rotate(90deg);\n}\n\n/* ─── Body (animated height) ────────────────────────────────────────────────── */\n\n.body {\n overflow: hidden;\n transition: height var(--effect-motion-short-3);\n}\n\n.bodyInner {\n padding: var(--dimension-space-050) var(--dimension-space-050) var(--dimension-space-100);\n color: var(--color-foreground-secondary);\n}\n","import React, { forwardRef, useState, useRef, useEffect, useCallback, useId } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Accordion.module.css';\n\nexport interface AccordionItemData {\n id: string;\n label: string;\n content: React.ReactNode;\n inactive?: boolean;\n}\n\nexport interface AccordionProps {\n /** Items to render. */\n items: AccordionItemData[];\n /** Allow multiple items open at once. When false, behaves as an accordion. */\n multiple?: boolean;\n /** Controlled: which item IDs are expanded. */\n expandedIds?: string[];\n /** Called when expansion state changes. */\n onExpandedChange?: (ids: string[]) => void;\n className?: string;\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(\n ({ items, multiple = false, expandedIds: controlledIds, onExpandedChange, className }, ref) => {\n const [internalIds, setInternalIds] = useState<string[]>([]);\n const expandedIds = controlledIds ?? internalIds;\n\n const toggle = (id: string) => {\n let next: string[];\n if (expandedIds.includes(id)) {\n next = expandedIds.filter(x => x !== id);\n } else {\n next = multiple ? [...expandedIds, id] : [id];\n }\n setInternalIds(next);\n onExpandedChange?.(next);\n };\n\n return (\n <div ref={ref} className={cn(styles.accordion, className)}>\n {items.map(item => (\n <AccordionItem\n key={item.id}\n label={item.label}\n isExpanded={expandedIds.includes(item.id)}\n inactive={item.inactive}\n onToggle={() => toggle(item.id)}\n >\n {item.content}\n </AccordionItem>\n ))}\n </div>\n );\n }\n);\n\nAccordion.displayName = 'Accordion';\n\n/* ─── AccordionItem ─────────────────────────────────────────────────────────── */\n\nexport interface AccordionItemProps {\n label: string;\n children: React.ReactNode;\n isExpanded?: boolean;\n onToggle?: () => void;\n inactive?: boolean;\n className?: string;\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(\n ({ label, children, isExpanded = false, onToggle, inactive = false, className }, ref) => {\n const contentRef = useRef<HTMLDivElement>(null);\n const [height, setHeight] = useState<number>(0);\n const reactId = useId();\n const triggerId = `${reactId}-trigger`;\n const panelId = `${reactId}-panel`;\n\n const measure = useCallback(() => {\n if (contentRef.current) {\n setHeight(contentRef.current.scrollHeight);\n }\n }, []);\n\n useEffect(() => {\n measure();\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, [measure]);\n\n return (\n <div ref={ref} className={cn(styles.item, inactive && styles.inactive, className)}>\n <button\n type=\"button\"\n id={triggerId}\n className={styles.trigger}\n onClick={() => !inactive && onToggle?.()}\n aria-expanded={isExpanded}\n aria-controls={panelId}\n aria-disabled={inactive || undefined}\n tabIndex={inactive ? -1 : 0}\n >\n <Text variant=\"text-body-medium-emphasis\" as=\"span\" color=\"inherit\">\n {label}\n </Text>\n <span className={cn(styles.chevron, isExpanded && styles.chevronOpen)}>\n &#x203A;\n </span>\n </button>\n <div\n id={panelId}\n role=\"region\"\n aria-labelledby={triggerId}\n className={styles.body}\n style={{ height: isExpanded ? height : 0 }}\n aria-hidden={!isExpanded}\n >\n <div ref={contentRef} className={styles.bodyInner}>\n {children}\n </div>\n </div>\n </div>\n );\n }\n);\n\nAccordionItem.displayName = 'AccordionItem';\n",".breadcrumb {\n display: flex;\n align-items: center;\n}\n\n.list {\n display: flex;\n align-items: center;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: var(--dimension-space-050);\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-050);\n}\n\n.link {\n color: var(--color-foreground-secondary);\n text-decoration: none;\n background: none;\n border: none;\n padding: var(--dimension-space-025) var(--dimension-space-050);\n border-radius: var(--dimension-radius-050);\n cursor: pointer;\n transition: background-color var(--effect-motion-short-2), color var(--effect-motion-short-2);\n}\n\n.link:hover {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n.link:active {\n background-color: var(--color-interaction-pressed);\n}\n\n.separator {\n color: var(--color-foreground-tertiary);\n font-size: 12px;\n -webkit-user-select: none;\n user-select: none;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Breadcrumb.module.css';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n onClick?: () => void;\n}\n\nexport interface BreadcrumbProps {\n /** Ordered list of breadcrumb items. Last item is treated as current page. */\n items: BreadcrumbItem[];\n /** Custom separator. Defaults to '/'. */\n separator?: React.ReactNode;\n className?: string;\n}\n\nexport const Breadcrumb = forwardRef<HTMLElement, BreadcrumbProps>(\n ({ items, separator = '/', className }, ref) => (\n <nav ref={ref} aria-label=\"Breadcrumb\" className={cn(styles.breadcrumb, className)}>\n <ol className={styles.list}>\n {items.map((item, i) => {\n const isLast = i === items.length - 1;\n return (\n <li key={i} className={styles.item}>\n {isLast ? (\n <Text variant=\"text-body-medium-emphasis\" as=\"span\" color=\"primary\" aria-current=\"page\">\n {item.label}\n </Text>\n ) : (\n <>\n {item.href ? (\n <a\n href={item.href}\n className={styles.link}\n onClick={e => { if (item.onClick) { e.preventDefault(); item.onClick(); } }}\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {item.label}\n </Text>\n </a>\n ) : (\n <button\n type=\"button\"\n className={styles.link}\n onClick={item.onClick}\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {item.label}\n </Text>\n </button>\n )}\n <span className={styles.separator} aria-hidden=\"true\">\n {separator}\n </span>\n </>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n )\n);\n\nBreadcrumb.displayName = 'Breadcrumb';\n",".pagination {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-025);\n -webkit-user-select: none;\n user-select: none;\n}\n\n.inactive {\n opacity: 0.5;\n pointer-events: none;\n}\n\n/* ─── Button ────────────────────────────────────────────────────────────────── */\n\n.button {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: var(--dimension-size-300);\n height: var(--dimension-size-300);\n padding: 0 var(--dimension-space-050);\n background: none;\n border: none;\n border-radius: var(--dimension-radius-075);\n cursor: pointer;\n color: var(--color-foreground-secondary);\n transition: background-color var(--effect-motion-short-2), color var(--effect-motion-short-2);\n}\n\n.button:hover:not(:disabled) {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n.button:active:not(:disabled) {\n background-color: var(--color-interaction-pressed);\n}\n\n.button:disabled {\n cursor: not-allowed;\n opacity: 0.35;\n}\n\n.active {\n background-color: var(--color-interaction-hover);\n color: var(--color-foreground-primary);\n}\n\n/* ─── Nav arrows ────────────────────────────────────────────────────────────── */\n\n.nav {\n font-size: 18px;\n}\n\n/* ─── Ellipsis ──────────────────────────────────────────────────────────────── */\n\n.ellipsis {\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: var(--dimension-size-300);\n height: var(--dimension-size-300);\n}\n","import React, { forwardRef, useMemo } from 'react';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport styles from './Pagination.module.css';\n\nexport interface PaginationProps {\n /** Current page (1-based). */\n page: number;\n /** Total number of pages. */\n totalPages: number;\n /** Called when page changes. */\n onPageChange: (page: number) => void;\n /** Max page buttons visible (excluding prev/next). */\n siblingCount?: number;\n /** Disables all interaction. */\n inactive?: boolean;\n className?: string;\n}\n\nfunction buildRange(start: number, end: number): (number | 'ellipsis')[] {\n const items: (number | 'ellipsis')[] = [];\n for (let i = start; i <= end; i++) items.push(i);\n return items;\n}\n\nfunction buildPages(page: number, totalPages: number, siblings: number): (number | 'ellipsis')[] {\n const totalSlots = siblings * 2 + 5; // siblings + boundaries + ellipses + current\n\n if (totalPages <= totalSlots) return buildRange(1, totalPages);\n\n const leftSibling = Math.max(page - siblings, 2);\n const rightSibling = Math.min(page + siblings, totalPages - 1);\n\n const showLeftEllipsis = leftSibling > 2;\n const showRightEllipsis = rightSibling < totalPages - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const left = buildRange(1, siblings * 2 + 3);\n return [...left, 'ellipsis', totalPages];\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n const right = buildRange(totalPages - (siblings * 2 + 2), totalPages);\n return [1, 'ellipsis', ...right];\n }\n\n return [1, 'ellipsis', ...buildRange(leftSibling, rightSibling), 'ellipsis', totalPages];\n}\n\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(\n ({ page, totalPages, onPageChange, siblingCount = 1, inactive = false, className }, ref) => {\n const pages = useMemo(() => buildPages(page, totalPages, siblingCount), [page, totalPages, siblingCount]);\n\n if (totalPages <= 1) return null;\n\n return (\n <nav ref={ref} aria-label=\"Pagination\" className={cn(styles.pagination, inactive && styles.inactive, className)}>\n <button\n type=\"button\"\n className={cn(styles.button, styles.nav)}\n disabled={page <= 1 || inactive}\n onClick={() => onPageChange(page - 1)}\n aria-label=\"Previous page\"\n >\n <Text variant=\"text-body-small\" as=\"span\" color=\"inherit\">&#x2039;</Text>\n </button>\n\n {pages.map((item, i) =>\n item === 'ellipsis' ? (\n <span key={`e${i}`} className={styles.ellipsis}>\n <Text variant=\"text-body-small\" as=\"span\" color=\"tertiary\">&hellip;</Text>\n </span>\n ) : (\n <button\n key={item}\n type=\"button\"\n className={cn(styles.button, item === page && styles.active)}\n onClick={() => onPageChange(item)}\n aria-current={item === page ? 'page' : undefined}\n disabled={inactive}\n >\n <Text variant={item === page ? 'text-body-small-emphasis' : 'text-body-small'} as=\"span\" color=\"inherit\">\n {item}\n </Text>\n </button>\n )\n )}\n\n <button\n type=\"button\"\n className={cn(styles.button, styles.nav)}\n disabled={page >= totalPages || inactive}\n onClick={() => onPageChange(page + 1)}\n aria-label=\"Next page\"\n >\n <Text variant=\"text-body-small\" as=\"span\" color=\"inherit\">&#x203A;</Text>\n </button>\n </nav>\n );\n }\n);\n\nPagination.displayName = 'Pagination';\n",".divider {\n border: none;\n margin: 0;\n flex-shrink: 0;\n background-color: var(--color-border-secondary);\n}\n\n/* Horizontal (default) */\n.divider:not(.vertical) {\n width: 100%;\n height: 1px;\n}\n\n/* Vertical */\n.vertical {\n width: 1px;\n height: 100%;\n align-self: stretch;\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Divider.module.css';\n\nexport type DividerOrientation = 'horizontal' | 'vertical';\n\nexport interface DividerProps {\n /** Direction of the divider line. */\n orientation?: DividerOrientation;\n className?: string;\n}\n\nexport const Divider = forwardRef<HTMLHRElement, DividerProps>(\n ({ orientation = 'horizontal', className }, ref) => (\n <hr\n ref={ref}\n role=\"separator\"\n aria-orientation={orientation}\n className={cn(\n styles.divider,\n orientation === 'vertical' && styles.vertical,\n className\n )}\n />\n )\n);\n\nDivider.displayName = 'Divider';\n",".skeleton {\n background-color: var(--color-background-secondary);\n position: relative;\n overflow: hidden;\n}\n\n/* ─── Variants ──────────────────────────────────────────────────────────────── */\n\n.text {\n height: 14px;\n border-radius: var(--dimension-radius-050);\n width: 100%;\n}\n\n.circular {\n width: 40px;\n height: 40px;\n border-radius: var(--dimension-radius-half);\n}\n\n.rectangular {\n width: 100%;\n height: 80px;\n border-radius: var(--dimension-radius-075);\n}\n\n/* ─── Text group ────────────────────────────────────────────────────────────── */\n\n.textGroup {\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-075);\n}\n\n/* ─── Shimmer animation ─────────────────────────────────────────────────────── */\n\n.animate::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n var(--color-interaction-hover) 50%,\n transparent 100%\n );\n animation: shimmer 1.5s ease-in-out infinite;\n}\n\n@keyframes shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n}\n","import React, { forwardRef } from 'react';\nimport { cn } from '@/utils/cn';\nimport styles from './Skeleton.module.css';\n\nexport type SkeletonVariant = 'text' | 'circular' | 'rectangular';\n\nexport interface SkeletonProps {\n /** Shape of the skeleton. */\n variant?: SkeletonVariant;\n /** Width (CSS value). */\n width?: string | number;\n /** Height (CSS value). */\n height?: string | number;\n /** Number of text lines to render. Only applies to 'text' variant. */\n lines?: number;\n /** Whether to animate the shimmer. */\n animate?: boolean;\n className?: string;\n}\n\nexport const Skeleton = forwardRef<HTMLDivElement, SkeletonProps>(\n (\n {\n variant = 'text',\n width,\n height,\n lines = 1,\n animate = true,\n className,\n },\n ref\n ) => {\n if (variant === 'text' && lines > 1) {\n return (\n <div ref={ref} className={cn(styles.textGroup, className)} style={{ width }}>\n {Array.from({ length: lines }, (_, i) => (\n <div\n key={i}\n className={cn(styles.skeleton, styles.text, animate && styles.animate)}\n style={{\n width: i === lines - 1 ? '60%' : '100%',\n height,\n }}\n />\n ))}\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n styles.skeleton,\n styles[variant],\n animate && styles.animate,\n className\n )}\n style={{ width, height }}\n aria-hidden=\"true\"\n />\n );\n }\n);\n\nSkeleton.displayName = 'Skeleton';\n","/* ─── Container ─────────────────────────────────────────────────────────────── */\n\n.container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: var(--dimension-space-075);\n pointer-events: none;\n padding: var(--dimension-space-100);\n max-width: 480px;\n width: 100%;\n box-sizing: border-box;\n}\n\n.topCenter {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.topRight {\n top: 0;\n right: 0;\n align-items: flex-end;\n}\n\n.bottomCenter {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n}\n\n.bottomRight {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n}\n\n/* ─── Toast ─────────────────────────────────────────────────────────────────── */\n\n.toast {\n display: flex;\n align-items: center;\n gap: var(--dimension-space-075);\n padding: var(--dimension-space-075) var(--dimension-space-100);\n min-height: var(--dimension-size-400);\n pointer-events: auto;\n animation: slideIn var(--effect-motion-short-3) ease-out;\n}\n\n.toastExit {\n animation: fadeOut 200ms ease-in forwards;\n}\n\n.dismiss {\n background: none;\n border: none;\n color: inherit;\n cursor: pointer;\n padding: var(--dimension-space-025);\n margin-left: auto;\n font-size: 16px;\n line-height: 1;\n opacity: 0.7;\n border-radius: var(--dimension-radius-050);\n transition: opacity var(--effect-motion-short-2);\n flex-shrink: 0;\n}\n\n.dismiss:hover { opacity: 1; }\n\n/* ─── Animations ────────────────────────────────────────────────────────────── */\n\n@keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes fadeOut {\n from { opacity: 1; }\n to { opacity: 0; }\n}\n","import React, { forwardRef, useEffect, useState, useCallback, useRef, useSyncExternalStore } from 'react';\nimport ReactDOM from 'react-dom';\nimport { cn } from '@/utils/cn';\nimport { Text } from '@/components/Text';\nimport { Surface } from '@/components/Surface';\nimport type { SurfaceIntent } from '@/components/Surface';\nimport styles from './Toast.module.css';\n\n/* ─── Toast Types ───────────────────────────────────────────────────────────── */\n\nexport type ToastIntent = 'neutral' | 'brand' | 'positive' | 'negative' | 'warning' | 'caution';\nexport type ToastPosition = 'top-center' | 'top-right' | 'bottom-center' | 'bottom-right';\n\nexport interface ToastData {\n id: string;\n message: string;\n intent?: ToastIntent;\n duration?: number;\n onDismiss?: () => void;\n}\n\nexport interface ToastOptions {\n message: string;\n intent?: ToastIntent;\n /** Auto-dismiss duration in ms. 0 = no auto-dismiss. Default 4000. */\n duration?: number;\n onDismiss?: () => void;\n}\n\n/* ─── Toast Store (external, framework-agnostic) ────────────────────────────── */\n\nlet toasts: ToastData[] = [];\nconst listeners = new Set<() => void>();\n\nfunction emit() {\n listeners.forEach(fn => fn());\n}\n\nfunction getSnapshot(): ToastData[] {\n return toasts;\n}\n\nfunction subscribe(listener: () => void) {\n listeners.add(listener);\n return () => { listeners.delete(listener); };\n}\n\nlet idCounter = 0;\n\nexport const toast = {\n show(options: ToastOptions): string {\n const id = `toast-${++idCounter}`;\n toasts = [...toasts, { id, ...options }];\n emit();\n return id;\n },\n info(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'neutral', ...options });\n },\n success(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'positive', ...options });\n },\n error(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'negative', ...options });\n },\n warning(message: string, options?: Omit<ToastOptions, 'message'>): string {\n return toast.show({ message, intent: 'warning', ...options });\n },\n dismiss(id: string) {\n toasts = toasts.filter(t => t.id !== id);\n emit();\n },\n dismissAll() {\n toasts = [];\n emit();\n },\n};\n\n/* ─── useToasts hook ────────────────────────────────────────────────────────── */\n\nexport function useToasts(): ToastData[] {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n}\n\n/* ─── Single Toast ──────────────────────────────────────────────────────────── */\n\nconst INTENT_MAP: Record<ToastIntent, SurfaceIntent> = {\n neutral: 'neutral',\n brand: 'brand',\n positive: 'positive',\n negative: 'negative',\n warning: 'warning',\n caution: 'caution',\n};\n\ninterface ToastItemProps {\n data: ToastData;\n}\n\nconst ToastItem: React.FC<ToastItemProps> = ({ data }) => {\n const [exiting, setExiting] = useState(false);\n const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const remainingRef = useRef<number>(data.duration ?? 4000);\n const startedAtRef = useRef<number>(0);\n const pausedRef = useRef<boolean>(false);\n\n const dismiss = useCallback(() => {\n setExiting(true);\n setTimeout(() => {\n toast.dismiss(data.id);\n data.onDismiss?.();\n }, 200);\n }, [data]);\n\n const clearTimer = useCallback(() => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = undefined;\n }\n }, []);\n\n const startTimer = useCallback((ms: number) => {\n if (ms <= 0) return;\n startedAtRef.current = Date.now();\n timerRef.current = setTimeout(dismiss, ms);\n }, [dismiss]);\n\n const pause = useCallback(() => {\n if (pausedRef.current || !timerRef.current) return;\n pausedRef.current = true;\n const elapsed = Date.now() - startedAtRef.current;\n remainingRef.current = Math.max(0, remainingRef.current - elapsed);\n clearTimer();\n }, [clearTimer]);\n\n const resume = useCallback(() => {\n if (!pausedRef.current) return;\n pausedRef.current = false;\n startTimer(remainingRef.current);\n }, [startTimer]);\n\n useEffect(() => {\n remainingRef.current = data.duration ?? 4000;\n pausedRef.current = false;\n startTimer(remainingRef.current);\n return clearTimer;\n }, [data.duration, startTimer, clearTimer]);\n\n const isNegative = data.intent === 'negative';\n\n return (\n <Surface\n intent={INTENT_MAP[data.intent ?? 'neutral']}\n contrast=\"bold\"\n elevation=\"floating\"\n radius=\"lg\"\n className={cn(styles.toast, exiting && styles.toastExit)}\n role={isNegative ? 'alert' : 'status'}\n aria-live={isNegative ? 'assertive' : 'polite'}\n onMouseEnter={pause}\n onMouseLeave={resume}\n onFocus={pause}\n onBlur={resume}\n >\n <Text variant=\"text-body-medium\" as=\"span\" color=\"inherit\">\n {data.message}\n </Text>\n <button\n type=\"button\"\n className={styles.dismiss}\n onClick={dismiss}\n aria-label=\"Dismiss\"\n >\n &times;\n </button>\n </Surface>\n );\n};\n\n/* ─── ToastContainer ────────────────────────────────────────────────────────── */\n\nexport interface ToastContainerProps {\n /** Where to render toasts on screen. */\n position?: ToastPosition;\n}\n\nexport const ToastContainer = forwardRef<HTMLDivElement, ToastContainerProps>(\n ({ position = 'top-center' }, ref) => {\n const items = useToasts();\n\n if (typeof document === 'undefined') return null;\n\n return ReactDOM.createPortal(\n <div\n ref={ref}\n className={cn(styles.container, styles[positionClass(position)])}\n role=\"region\"\n aria-label=\"Notifications\"\n >\n {items.map(item => (\n <ToastItem key={item.id} data={item} />\n ))}\n </div>,\n document.body\n );\n }\n);\n\nToastContainer.displayName = 'ToastContainer';\n\nfunction positionClass(position: ToastPosition): string {\n switch (position) {\n case 'top-center': return 'topCenter';\n case 'top-right': return 'topRight';\n case 'bottom-center': return 'bottomCenter';\n case 'bottom-right': return 'bottomRight';\n }\n}\n"],"mappings":"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"}