@efolusi/meridian 1.5.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 (231) hide show
  1. package/README.md +12 -0
  2. package/ai/AgentRun.d.ts +20 -0
  3. package/ai/AgentRun.js +100 -0
  4. package/ai/ChatMessage.d.ts +19 -0
  5. package/ai/ChatMessage.js +81 -0
  6. package/ai/Citation.d.ts +23 -0
  7. package/ai/Citation.js +146 -0
  8. package/ai/Confirmation.d.ts +26 -0
  9. package/ai/Confirmation.js +84 -0
  10. package/ai/Conversation.d.ts +15 -0
  11. package/ai/Conversation.js +81 -0
  12. package/ai/DocumentCard.d.ts +17 -0
  13. package/ai/DocumentCard.js +101 -0
  14. package/ai/FeedbackBar.d.ts +14 -0
  15. package/ai/FeedbackBar.js +84 -0
  16. package/ai/GeneratedImage.d.ts +22 -0
  17. package/ai/GeneratedImage.js +100 -0
  18. package/ai/ModelSelector.d.ts +21 -0
  19. package/ai/ModelSelector.js +112 -0
  20. package/ai/Player.d.ts +18 -0
  21. package/ai/Player.js +201 -0
  22. package/ai/PromptComposer.d.ts +28 -0
  23. package/ai/PromptComposer.js +111 -0
  24. package/ai/PromptSteps.d.ts +18 -0
  25. package/ai/PromptSteps.js +167 -0
  26. package/ai/Reasoning.d.ts +17 -0
  27. package/ai/Reasoning.js +57 -0
  28. package/ai/RichComposer.d.ts +25 -0
  29. package/ai/RichComposer.js +247 -0
  30. package/ai/Sandbox.d.ts +20 -0
  31. package/ai/Sandbox.js +96 -0
  32. package/ai/SelectionQuote.d.ts +15 -0
  33. package/ai/SelectionQuote.js +123 -0
  34. package/ai/SourceCard.d.ts +17 -0
  35. package/ai/SourceCard.js +57 -0
  36. package/ai/Suggestions.d.ts +10 -0
  37. package/ai/Suggestions.js +38 -0
  38. package/ai/Task.d.ts +15 -0
  39. package/ai/Task.js +49 -0
  40. package/ai/Todo.d.ts +13 -0
  41. package/ai/Todo.js +87 -0
  42. package/ai/ToolCall.d.ts +30 -0
  43. package/ai/ToolCall.js +147 -0
  44. package/ai/Transcript.d.ts +27 -0
  45. package/ai/Transcript.js +96 -0
  46. package/ai/UsageMeter.d.ts +21 -0
  47. package/ai/UsageMeter.js +81 -0
  48. package/ai/WebPreview.d.ts +19 -0
  49. package/ai/WebPreview.js +179 -0
  50. package/assets/fonts/BricolageGrotesque-Variable.ttf +0 -0
  51. package/assets/fonts/Figtree-Italic-Variable.ttf +0 -0
  52. package/assets/fonts/Figtree-Variable.ttf +0 -0
  53. package/assets/fonts/JetBrainsMono-Italic-Variable.ttf +0 -0
  54. package/assets/fonts/JetBrainsMono-Variable.ttf +0 -0
  55. package/assets/fonts/OFL-BricolageGrotesque.txt +93 -0
  56. package/assets/fonts/OFL-Figtree.txt +93 -0
  57. package/assets/fonts/OFL-JetBrainsMono.txt +93 -0
  58. package/code/CodeBlock.d.ts +17 -0
  59. package/code/CodeBlock.js +99 -0
  60. package/code/Console.d.ts +19 -0
  61. package/code/Console.js +124 -0
  62. package/code/CopyField.d.ts +10 -0
  63. package/code/CopyField.js +54 -0
  64. package/code/Diff.d.ts +26 -0
  65. package/code/Diff.js +358 -0
  66. package/code/EnvList.d.ts +14 -0
  67. package/code/EnvList.js +89 -0
  68. package/code/Exception.d.ts +25 -0
  69. package/code/Exception.js +90 -0
  70. package/code/Terminal.d.ts +20 -0
  71. package/code/Terminal.js +58 -0
  72. package/data/BarChart.d.ts +14 -0
  73. package/data/BarChart.js +44 -0
  74. package/data/DonutChart.d.ts +17 -0
  75. package/data/DonutChart.js +114 -0
  76. package/data/EmptyState.d.ts +13 -0
  77. package/data/EmptyState.js +39 -0
  78. package/data/KeyValueList.d.ts +14 -0
  79. package/data/KeyValueList.js +34 -0
  80. package/data/LineChart.d.ts +15 -0
  81. package/data/LineChart.js +85 -0
  82. package/data/Skeleton.d.ts +11 -0
  83. package/data/Skeleton.js +49 -0
  84. package/data/Sparkline.d.ts +14 -0
  85. package/data/Sparkline.js +42 -0
  86. package/data/Stat.d.ts +14 -0
  87. package/data/Stat.js +40 -0
  88. package/data/StatusDot.d.ts +10 -0
  89. package/data/StatusDot.js +34 -0
  90. package/data/Table.d.ts +53 -0
  91. package/data/Table.js +174 -0
  92. package/dates/Calendar.d.ts +8 -0
  93. package/dates/Calendar.js +143 -0
  94. package/dates/DatePicker.d.ts +12 -0
  95. package/dates/DatePicker.js +118 -0
  96. package/display/Accordion.d.ts +15 -0
  97. package/display/Accordion.js +52 -0
  98. package/display/AspectRatio.d.ts +8 -0
  99. package/display/AspectRatio.js +24 -0
  100. package/display/Avatar.d.ts +17 -0
  101. package/display/Avatar.js +52 -0
  102. package/display/Badge.d.ts +10 -0
  103. package/display/Badge.js +34 -0
  104. package/display/Card.d.ts +17 -0
  105. package/display/Card.js +51 -0
  106. package/display/Carousel.d.ts +16 -0
  107. package/display/Carousel.js +97 -0
  108. package/display/Collapsible.d.ts +12 -0
  109. package/display/Collapsible.js +46 -0
  110. package/display/Divider.d.ts +9 -0
  111. package/display/Divider.js +33 -0
  112. package/display/Kbd.d.ts +7 -0
  113. package/display/Kbd.js +18 -0
  114. package/display/Link.d.ts +12 -0
  115. package/display/Link.js +41 -0
  116. package/display/ListItem.d.ts +19 -0
  117. package/display/ListItem.js +61 -0
  118. package/display/Resizable.d.ts +16 -0
  119. package/display/Resizable.js +90 -0
  120. package/display/ScrollArea.d.ts +8 -0
  121. package/display/ScrollArea.js +28 -0
  122. package/display/Tag.d.ts +9 -0
  123. package/display/Tag.js +41 -0
  124. package/display/Toolbar.d.ts +22 -0
  125. package/display/Toolbar.js +55 -0
  126. package/display/TreeList.d.ts +20 -0
  127. package/display/TreeList.js +101 -0
  128. package/feedback/Alert.d.ts +14 -0
  129. package/feedback/Alert.js +56 -0
  130. package/feedback/Banner.d.ts +15 -0
  131. package/feedback/Banner.js +49 -0
  132. package/feedback/ConfirmDialog.d.ts +18 -0
  133. package/feedback/ConfirmDialog.js +49 -0
  134. package/feedback/Dialog.d.ts +13 -0
  135. package/feedback/Dialog.js +107 -0
  136. package/feedback/Loader.d.ts +12 -0
  137. package/feedback/Loader.js +41 -0
  138. package/feedback/Progress.d.ts +15 -0
  139. package/feedback/Progress.js +48 -0
  140. package/feedback/Spinner.d.ts +9 -0
  141. package/feedback/Spinner.js +38 -0
  142. package/feedback/Toast.d.ts +70 -0
  143. package/feedback/Toast.js +216 -0
  144. package/feedback/Tooltip.d.ts +12 -0
  145. package/feedback/Tooltip.js +86 -0
  146. package/files/FileDrop.d.ts +15 -0
  147. package/files/FileDrop.js +75 -0
  148. package/files/FileTile.d.ts +19 -0
  149. package/files/FileTile.js +96 -0
  150. package/files/FileTypeIcon.d.ts +11 -0
  151. package/files/FileTypeIcon.js +121 -0
  152. package/finance/PaymentCard.d.ts +17 -0
  153. package/finance/PaymentCard.js +109 -0
  154. package/forms/Button.d.ts +15 -0
  155. package/forms/Button.js +82 -0
  156. package/forms/ButtonGroup.d.ts +5 -0
  157. package/forms/ButtonGroup.js +22 -0
  158. package/forms/ButtonTile.d.ts +21 -0
  159. package/forms/ButtonTile.js +69 -0
  160. package/forms/Checkbox.d.ts +6 -0
  161. package/forms/Checkbox.js +52 -0
  162. package/forms/Combobox.d.ts +17 -0
  163. package/forms/Combobox.js +162 -0
  164. package/forms/DigitEntry.d.ts +15 -0
  165. package/forms/DigitEntry.js +88 -0
  166. package/forms/FormField.d.ts +39 -0
  167. package/forms/FormField.js +127 -0
  168. package/forms/IconButton.d.ts +11 -0
  169. package/forms/IconButton.js +41 -0
  170. package/forms/Input.d.ts +14 -0
  171. package/forms/Input.js +75 -0
  172. package/forms/InputGroup.d.ts +15 -0
  173. package/forms/InputGroup.js +59 -0
  174. package/forms/Label.d.ts +11 -0
  175. package/forms/Label.js +29 -0
  176. package/forms/Radio.d.ts +6 -0
  177. package/forms/Radio.js +46 -0
  178. package/forms/Select.d.ts +10 -0
  179. package/forms/Select.js +68 -0
  180. package/forms/Slider.d.ts +18 -0
  181. package/forms/Slider.js +75 -0
  182. package/forms/Switch.d.ts +6 -0
  183. package/forms/Switch.js +46 -0
  184. package/forms/Textarea.d.ts +8 -0
  185. package/forms/Textarea.js +58 -0
  186. package/forms/Toggle.d.ts +26 -0
  187. package/forms/Toggle.js +85 -0
  188. package/icons/Icon.d.ts +13 -0
  189. package/icons/Icon.js +54 -0
  190. package/index.d.ts +106 -0
  191. package/index.js +106 -0
  192. package/navigation/Breadcrumbs.d.ts +12 -0
  193. package/navigation/Breadcrumbs.js +41 -0
  194. package/navigation/Menubar.d.ts +10 -0
  195. package/navigation/Menubar.js +173 -0
  196. package/navigation/PageControl.d.ts +11 -0
  197. package/navigation/PageControl.js +36 -0
  198. package/navigation/Pagination.d.ts +9 -0
  199. package/navigation/Pagination.js +68 -0
  200. package/navigation/SegmentedControl.d.ts +17 -0
  201. package/navigation/SegmentedControl.js +42 -0
  202. package/navigation/SideNav.d.ts +18 -0
  203. package/navigation/SideNav.js +87 -0
  204. package/navigation/Steps.d.ts +15 -0
  205. package/navigation/Steps.js +61 -0
  206. package/navigation/Tabs.d.ts +17 -0
  207. package/navigation/Tabs.js +76 -0
  208. package/navigation/TopNav.d.ts +10 -0
  209. package/navigation/TopNav.js +26 -0
  210. package/overlay/CommandPalette.d.ts +21 -0
  211. package/overlay/CommandPalette.js +164 -0
  212. package/overlay/ContextMenu.d.ts +11 -0
  213. package/overlay/ContextMenu.js +140 -0
  214. package/overlay/Drawer.d.ts +14 -0
  215. package/overlay/Drawer.js +99 -0
  216. package/overlay/HoverCard.d.ts +17 -0
  217. package/overlay/HoverCard.js +74 -0
  218. package/overlay/Menu.d.ts +24 -0
  219. package/overlay/Menu.js +153 -0
  220. package/overlay/Popover.d.ts +16 -0
  221. package/overlay/Popover.js +96 -0
  222. package/overlay/Portal.d.ts +10 -0
  223. package/overlay/Portal.js +127 -0
  224. package/package.json +41 -0
  225. package/styles.css +6 -0
  226. package/tokens/base.css +10 -0
  227. package/tokens/colors.css +38 -0
  228. package/tokens/effects.css +22 -0
  229. package/tokens/fonts.css +5 -0
  230. package/tokens/spacing.css +12 -0
  231. package/tokens/typography.css +9 -0
@@ -0,0 +1,127 @@
1
+ import React from 'react';
2
+ // Bare imports are stripped by the bundle compiler, so this resolves to the
3
+ // window global there; in an ESM consumer it resolves normally. Both work.
4
+ import ReactDOM from 'react-dom';
5
+ import { injectEfCss } from "../forms/Button.js";
6
+ const CSS = `
7
+ .ef-portal{position:fixed;top:0;left:0;width:0;height:0}
8
+ `;
9
+
10
+ /**
11
+ * Renders children into document.body (or `container`).
12
+ *
13
+ * Every floating surface needs this. An overlay positioned inside its trigger's
14
+ * subtree is clipped by the first ancestor with overflow:auto|hidden — which in
15
+ * practice is the scrolling table, drawer, or card it was opened from.
16
+ */
17
+ export function Portal({
18
+ children,
19
+ container
20
+ }) {
21
+ injectEfCss('ef-css-portal', CSS);
22
+ const hostRef = React.useRef(null);
23
+ if (hostRef.current === null && typeof document !== 'undefined') {
24
+ hostRef.current = document.createElement('div');
25
+ hostRef.current.className = 'ef-portal';
26
+ }
27
+ // Children mount into the host on the first render, while it is still detached,
28
+ // and this layout effect attaches it before paint. Gating the render on a
29
+ // "mounted" state instead would leave the panel absent when the parent measures
30
+ // it for placement, which puts every anchored overlay at the viewport origin.
31
+ React.useLayoutEffect(() => {
32
+ const host = hostRef.current;
33
+ if (!host) return;
34
+ const parent = container || document.body;
35
+ parent.appendChild(host);
36
+ return () => {
37
+ if (host.parentNode) host.parentNode.removeChild(host);
38
+ };
39
+ }, [container]);
40
+ if (!hostRef.current) return null;
41
+ return /*#__PURE__*/ReactDOM.createPortal(children, hostRef.current);
42
+ }
43
+
44
+ /**
45
+ * Position a portaled panel against its anchor, in viewport coordinates.
46
+ *
47
+ * Flips to the opposite side when the preferred one would overflow, then shifts
48
+ * along the cross axis to stay on screen. Returns { style, side } — the panel is
49
+ * hidden for the first frame so the measurement never flashes, and `side` is the
50
+ * placement actually resolved, which a caller drawing an arrow has to know.
51
+ *
52
+ * Not exported on the namespace — it is a building block for the overlay
53
+ * components, and is only useful with a panel ref you already control.
54
+ */
55
+ export function useAnchoredStyle(anchorRef, panelRef, {
56
+ open,
57
+ placement = 'bottom',
58
+ align = 'start',
59
+ offset = 6,
60
+ matchWidth = false
61
+ } = {}) {
62
+ const [state, setState] = React.useState({
63
+ style: {
64
+ position: 'fixed',
65
+ top: 0,
66
+ left: 0,
67
+ visibility: 'hidden'
68
+ },
69
+ side: placement
70
+ });
71
+ React.useLayoutEffect(() => {
72
+ if (!open) {
73
+ setState(s => s.style.visibility === 'hidden' ? s : {
74
+ ...s,
75
+ style: {
76
+ ...s.style,
77
+ visibility: 'hidden'
78
+ }
79
+ });
80
+ return;
81
+ }
82
+ const place = () => {
83
+ const anchor = anchorRef.current;
84
+ const panel = panelRef.current;
85
+ if (!anchor || !panel) return;
86
+ const a = anchor.getBoundingClientRect();
87
+ const p = panel.getBoundingClientRect();
88
+ const vw = document.documentElement.clientWidth;
89
+ const vh = document.documentElement.clientHeight;
90
+ const edge = 8;
91
+ const roomBelow = vh - a.bottom - offset;
92
+ const roomAbove = a.top - offset;
93
+ const wantsTop = placement === 'top';
94
+ const side = wantsTop ? roomAbove >= p.height || roomAbove >= roomBelow ? 'top' : 'bottom' : roomBelow >= p.height || roomBelow >= roomAbove ? 'bottom' : 'top';
95
+
96
+ // a width-matched panel (a listbox under its input) is measured at the
97
+ // anchor's width, not its own, or the clamp below uses the wrong number
98
+ const width = matchWidth ? a.width : p.width;
99
+ let top = side === 'bottom' ? a.bottom + offset : a.top - offset - p.height;
100
+ let left = align === 'end' ? a.right - width : align === 'center' ? a.left + a.width / 2 - width / 2 : a.left;
101
+ left = Math.max(edge, Math.min(left, vw - width - edge));
102
+ top = Math.max(edge, Math.min(top, vh - p.height - edge));
103
+ const next = {
104
+ position: 'fixed',
105
+ top: Math.round(top),
106
+ left: Math.round(left),
107
+ right: 'auto',
108
+ bottom: 'auto',
109
+ visibility: 'visible'
110
+ };
111
+ if (matchWidth) next.width = Math.round(a.width);
112
+ setState({
113
+ style: next,
114
+ side
115
+ });
116
+ };
117
+ place();
118
+ // capture phase: any scrolling ancestor moves the anchor, not just the window
119
+ window.addEventListener('scroll', place, true);
120
+ window.addEventListener('resize', place);
121
+ return () => {
122
+ window.removeEventListener('scroll', place, true);
123
+ window.removeEventListener('resize', place);
124
+ };
125
+ }, [open, placement, align, offset, matchWidth, anchorRef, panelRef]);
126
+ return state;
127
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@efolusi/meridian",
3
+ "version": "1.5.0",
4
+ "description": "A general-purpose open-source design system by Efolusi: accessible React components, design tokens, blocks and example apps.",
5
+ "license": "MIT",
6
+ "homepage": "https://meridian.efolusi.com",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/efolusi/meridian.git"
10
+ },
11
+ "type": "module",
12
+ "sideEffects": [
13
+ "*.css"
14
+ ],
15
+ "main": "./index.js",
16
+ "types": "./index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./index.d.ts",
20
+ "default": "./index.js"
21
+ },
22
+ "./styles.css": "./styles.css",
23
+ "./tokens/*": "./tokens/*",
24
+ "./*": {
25
+ "types": "./*.d.ts",
26
+ "default": "./*.js"
27
+ }
28
+ },
29
+ "peerDependencies": {
30
+ "react": ">=18",
31
+ "react-dom": ">=18"
32
+ },
33
+ "keywords": [
34
+ "design-system",
35
+ "react",
36
+ "components",
37
+ "accessible",
38
+ "design-tokens",
39
+ "meridian"
40
+ ]
41
+ }
package/styles.css ADDED
@@ -0,0 +1,6 @@
1
+ @import "tokens/fonts.css";
2
+ @import "tokens/colors.css";
3
+ @import "tokens/typography.css";
4
+ @import "tokens/spacing.css";
5
+ @import "tokens/effects.css";
6
+ @import "tokens/base.css";
@@ -0,0 +1,10 @@
1
+ body{margin:0;font-family:var(--font-sans);font-size:var(--text-md);line-height:var(--leading-normal);color:var(--text-primary);background:var(--surface-page);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
2
+ h1,h2,h3,h4{font-family:var(--font-display);letter-spacing:var(--tracking-display);line-height:var(--leading-snug);margin:0}
3
+ p{margin:0}
4
+ a{color:var(--text-link);text-decoration:none;transition:color var(--dur-fast) var(--ease-out)}
5
+ a:hover{color:var(--accent-hover);text-decoration:underline;text-underline-offset:3px}
6
+ a:focus-visible{outline:none;box-shadow:var(--focus-ring);border-radius:var(--radius-sm)}
7
+ code,pre,kbd{font-family:var(--font-mono)}
8
+ ::selection{background:var(--brand-100)}
9
+ *,*::before,*::after{box-sizing:border-box}
10
+ @media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}
@@ -0,0 +1,38 @@
1
+ :root{
2
+ /* Sand — warm neutrals */
3
+ --sand-25:#FCFBF9;--sand-50:#FAF9F6;--sand-100:#F3F1EB;--sand-200:#E7E3D9;--sand-300:#D5CFC0;--sand-400:#B4AB97;--sand-500:#948A74;--sand-600:#786E59;--sand-700:#5E5545;--sand-800:#443D32;--sand-900:#2E2922;--sand-950:#1E1A14;
4
+ /* Brand — cream→peach→caramel→cocoa ramp sampled from the owl mark */
5
+ --brand-50:#F8F4E6;--brand-100:#F4E9D2;--brand-200:#EFCFAC;--brand-300:#DFB585;--brand-400:#CE9C66;--brand-500:#C08A5A;--brand-600:#A0693C;--brand-700:#7A4E2B;--brand-800:#5C3A1F;--brand-900:#482818;--brand-950:#2C1709;
6
+ /* Named logo tones (aliases into the ramp) */
7
+ --cocoa-950:var(--brand-950);--cocoa-900:#3A2012;--cocoa-700:var(--brand-900);--caramel-500:var(--brand-500);--peach-200:var(--brand-200);--cream-50:var(--brand-50);
8
+ /* Status — each 600 fg holds ≥4.5:1 on its 100 tint and on white */
9
+ --success-600:#2F7A40;--success-100:#EBF5EC;--success-300:#BFE0C6;
10
+ --warning-600:#B45309;--warning-100:#FDF3E0;--warning-300:#F3D9A8;
11
+ --danger-600:#C81E1E;--danger-700:#B91C1C;--danger-100:#FDEEEC;--danger-300:#F5C6C0;
12
+ /* Semantic aliases */
13
+ --surface-page:var(--sand-50);--surface-card:#FFFFFF;--surface-sunken:var(--sand-100);--surface-subtle:var(--sand-25);--surface-inverse:var(--sand-950);--surface-brand:var(--brand-900);
14
+ --surface-code:#14110B;--text-code:#E8E3D9;--border-code:rgba(240,235,225,.09);/* code/terminal surface — fixed dark espresso in BOTH themes (never remap) */
15
+ --overlay-scrim:rgba(31,26,20,.45);/* modal/drawer backdrop */--text-on-brand-muted:rgba(248,244,230,.75);/* muted text on brand/inverse surfaces */
16
+ --text-primary:var(--sand-950);--text-secondary:var(--sand-700);--text-muted:#746A55;/* between sand-600/700: ≥4.5:1 on page, card, and sunken */--text-inverse:var(--sand-50);--text-link:var(--brand-700);
17
+ --border-default:var(--sand-200);--border-strong:var(--sand-300);--border-inverse:rgba(250,249,246,.18);
18
+ --accent:var(--brand-950);--accent-hover:#1D0E04;--accent-active:#120801;--accent-subtle:var(--brand-50);--accent-subtle-border:var(--brand-200);--accent-contrast:#FFFFFF;
19
+ --danger-contrast:#FFFFFF;/* label on a solid --danger-600 fill; flips in dark where the red lightens */
20
+ /* Focus ring — opaque, two-layer. The inner offset ring is surface-coloured so the
21
+ indicator never sits directly against a control fill; the outer ring only ever needs
22
+ contrast against the surface, clearing WCAG 1.4.11 (3:1 non-text) on every background. */
23
+ --focus-ring-color:var(--brand-700);--focus-ring-offset:var(--surface-card);
24
+ --focus-ring:0 0 0 2px var(--focus-ring-offset),0 0 0 4px var(--focus-ring-color);
25
+ --focus-ring-danger:0 0 0 2px var(--focus-ring-offset),0 0 0 4px var(--danger-600);
26
+ }
27
+ /* Dark theme — semantic remap only; ramps stay fixed */
28
+ [data-theme="dark"]{
29
+ --surface-page:#191512;--surface-card:#211C17;--surface-sunken:#2A251E;--surface-subtle:#1D1814;--surface-inverse:var(--sand-50);--surface-brand:var(--brand-950);
30
+ --text-primary:#F3EFE7;--text-secondary:#C9C0B2;--text-muted:#9C9280;--text-inverse:var(--sand-950);--text-link:var(--brand-400);
31
+ --border-default:#332C24;--border-strong:#453C31;--border-inverse:rgba(30,26,20,.2);
32
+ --accent:#F3EFE7;--accent-hover:#FFFFFF;--accent-active:#D5CFC0;--accent-subtle:#2A2119;--accent-subtle-border:#453728;--accent-contrast:#1E1A14;
33
+ --success-600:#5FB86E;--success-100:#1C2B1F;--success-300:#2E4A34;
34
+ --warning-100:#2E2413;--warning-300:#4A3A1D;--warning-600:#D9822B;
35
+ --danger-100:#321B18;--danger-300:#54291F;--danger-600:#E85D4A;--danger-contrast:#1E1A14;
36
+ --focus-ring-color:var(--brand-400);/* offset + composite inherit from :root and re-resolve here */
37
+ }
38
+ [data-theme="dark"] ::selection{background:#453728}
@@ -0,0 +1,22 @@
1
+ :root{
2
+ --shadow-xs:0 1px 2px rgba(46,41,34,.05);
3
+ --shadow-sm:0 1px 3px rgba(46,41,34,.07);
4
+ --shadow-md:0 4px 12px rgba(46,41,34,.08);
5
+ --shadow-lg:0 12px 28px rgba(46,41,34,.12);
6
+ --shadow-xl:0 16px 40px rgba(31,26,20,.18),0 2px 8px rgba(31,26,20,.08);
7
+ --shadow-pop:var(--shadow-xl);/* deprecated alias of --shadow-xl; kept one major */
8
+ /* Elevation scale — the single source of overlay stacking order */
9
+ --z-dropdown:1000;/* @kind other */
10
+ --z-sticky:1100;/* @kind other */
11
+ --z-overlay:1200;/* @kind other */
12
+ --z-modal:1300;/* @kind other */
13
+ --z-popover:1400;/* @kind other */
14
+ --z-toast:1500;/* @kind other */
15
+ --z-tooltip:1600;/* @kind other */
16
+ --ease-spring:cubic-bezier(.3,1.04,.35,1);/* @kind other */
17
+ --ease-out:cubic-bezier(.22,1,.36,1);/* @kind other */
18
+ --ease-in-out:cubic-bezier(.65,0,.35,1);/* @kind other */
19
+ --dur-fast:100ms;/* @kind other */
20
+ --dur-med:160ms;/* @kind other */
21
+ --dur-slow:240ms;/* @kind other */
22
+ }
@@ -0,0 +1,5 @@
1
+ @font-face{font-family:'Bricolage Grotesque';src:url('../assets/fonts/BricolageGrotesque-Variable.ttf') format('truetype-variations');font-weight:200 800;font-style:normal;font-display:swap}
2
+ @font-face{font-family:'Figtree';src:url('../assets/fonts/Figtree-Variable.ttf') format('truetype-variations');font-weight:300 900;font-style:normal;font-display:swap}
3
+ @font-face{font-family:'Figtree';src:url('../assets/fonts/Figtree-Italic-Variable.ttf') format('truetype-variations');font-weight:300 900;font-style:italic;font-display:swap}
4
+ @font-face{font-family:'JetBrains Mono';src:url('../assets/fonts/JetBrainsMono-Variable.ttf') format('truetype-variations');font-weight:100 800;font-style:normal;font-display:swap}
5
+ @font-face{font-family:'JetBrains Mono';src:url('../assets/fonts/JetBrainsMono-Italic-Variable.ttf') format('truetype-variations');font-weight:100 800;font-style:italic;font-display:swap}
@@ -0,0 +1,12 @@
1
+ :root{
2
+ --space-0:0;--space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:20px;--space-6:24px;--space-8:32px;--space-10:40px;--space-12:48px;--space-16:64px;--space-20:80px;--space-24:96px;--space-32:128px;
3
+ --radius-sm:4px;--radius-md:8px;--radius-lg:12px;--radius-xl:16px;--radius-full:999px;
4
+ --container-max:1200px;--container-text:720px;
5
+ --control-h-sm:28px;--control-h-md:36px;--control-h-lg:44px;
6
+ --table-pad-y:12px;--table-pad-x:16px;
7
+ }
8
+ /* Compact density — data-heavy B2B views */
9
+ [data-density="compact"]{
10
+ --control-h-sm:24px;--control-h-md:30px;--control-h-lg:38px;
11
+ --table-pad-y:7px;--table-pad-x:12px;
12
+ }
@@ -0,0 +1,9 @@
1
+ :root{
2
+ --font-display:'Bricolage Grotesque','Figtree',ui-sans-serif,system-ui,sans-serif;
3
+ --font-sans:'Figtree',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
4
+ --font-mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;
5
+ --text-2xs:11px;--text-xs:12px;--text-sm:13px;--text-md:14px;--text-lg:16px;--text-xl:18px;--text-2xl:21px;--text-3xl:26px;--text-4xl:34px;--text-5xl:44px;--text-6xl:60px;--text-7xl:76px;
6
+ --leading-tight:1.05;--leading-snug:1.25;--leading-normal:1.5;--leading-relaxed:1.65;
7
+ --tracking-display:-0.02em;--tracking-tight:-0.01em;--tracking-wide:0.06em;
8
+ --weight-regular:400;--weight-medium:500;--weight-semibold:600;--weight-bold:700;--weight-display:680;
9
+ }