@maxhealth.tech/prefab 0.3.22 → 0.3.24

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 (113) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +8 -0
  3. package/dist/a2ui/catalog.d.ts.map +1 -1
  4. package/dist/a2ui/catalog.js +1 -10
  5. package/dist/a2ui/catalog.js.map +1 -1
  6. package/dist/a2ui/control.d.ts.map +1 -1
  7. package/dist/a2ui/control.js +1 -10
  8. package/dist/a2ui/control.js.map +1 -1
  9. package/dist/a2ui.min.js +1 -1
  10. package/dist/auto/chart.js +1 -1
  11. package/dist/auto/chart.js.map +1 -1
  12. package/dist/auto/comparison.js +1 -1
  13. package/dist/auto/comparison.js.map +1 -1
  14. package/dist/auto/form.d.ts +1 -1
  15. package/dist/auto/form.d.ts.map +1 -1
  16. package/dist/auto/form.js +15 -2
  17. package/dist/auto/form.js.map +1 -1
  18. package/dist/auto/index.d.ts +2 -10
  19. package/dist/auto/index.d.ts.map +1 -1
  20. package/dist/auto/index.js +5 -61
  21. package/dist/auto/index.js.map +1 -1
  22. package/dist/auto/metrics.js +1 -1
  23. package/dist/auto/metrics.js.map +1 -1
  24. package/dist/auto/progress.d.ts.map +1 -1
  25. package/dist/auto/progress.js +8 -7
  26. package/dist/auto/progress.js.map +1 -1
  27. package/dist/auto/status.d.ts +17 -0
  28. package/dist/auto/status.d.ts.map +1 -0
  29. package/dist/auto/status.js +79 -0
  30. package/dist/auto/status.js.map +1 -0
  31. package/dist/auto/timeline.d.ts.map +1 -1
  32. package/dist/auto/timeline.js +3 -14
  33. package/dist/auto/timeline.js.map +1 -1
  34. package/dist/components/form/index.d.ts +3 -2
  35. package/dist/components/form/index.d.ts.map +1 -1
  36. package/dist/components/form/index.js +8 -2
  37. package/dist/components/form/index.js.map +1 -1
  38. package/dist/components/layout/index.d.ts +7 -1
  39. package/dist/components/layout/index.d.ts.map +1 -1
  40. package/dist/components/layout/index.js +6 -2
  41. package/dist/components/layout/index.js.map +1 -1
  42. package/dist/core/guards.d.ts +2 -0
  43. package/dist/core/guards.d.ts.map +1 -1
  44. package/dist/core/guards.js +13 -1
  45. package/dist/core/guards.js.map +1 -1
  46. package/dist/core/version.d.ts +1 -1
  47. package/dist/core/version.js +1 -1
  48. package/dist/prefab.css +742 -427
  49. package/dist/renderer/cdn.d.ts +5 -0
  50. package/dist/renderer/cdn.d.ts.map +1 -0
  51. package/dist/renderer/cdn.js +19 -0
  52. package/dist/renderer/cdn.js.map +1 -0
  53. package/dist/renderer/components/alert.d.ts.map +1 -1
  54. package/dist/renderer/components/alert.js +2 -6
  55. package/dist/renderer/components/alert.js.map +1 -1
  56. package/dist/renderer/components/card.js +0 -2
  57. package/dist/renderer/components/card.js.map +1 -1
  58. package/dist/renderer/components/charts/cartesian.d.ts +2 -2
  59. package/dist/renderer/components/charts/cartesian.d.ts.map +1 -1
  60. package/dist/renderer/components/charts/cartesian.js +6 -7
  61. package/dist/renderer/components/charts/cartesian.js.map +1 -1
  62. package/dist/renderer/components/charts/helpers.d.ts +12 -2
  63. package/dist/renderer/components/charts/helpers.d.ts.map +1 -1
  64. package/dist/renderer/components/charts/helpers.js +64 -26
  65. package/dist/renderer/components/charts/helpers.js.map +1 -1
  66. package/dist/renderer/components/charts/index.d.ts.map +1 -1
  67. package/dist/renderer/components/charts/index.js +6 -5
  68. package/dist/renderer/components/charts/index.js.map +1 -1
  69. package/dist/renderer/components/charts/scatter.d.ts +2 -2
  70. package/dist/renderer/components/charts/scatter.d.ts.map +1 -1
  71. package/dist/renderer/components/charts/scatter.js +39 -20
  72. package/dist/renderer/components/charts/scatter.js.map +1 -1
  73. package/dist/renderer/components/choice.js +67 -39
  74. package/dist/renderer/components/choice.js.map +1 -1
  75. package/dist/renderer/components/data.d.ts.map +1 -1
  76. package/dist/renderer/components/data.js +42 -74
  77. package/dist/renderer/components/data.js.map +1 -1
  78. package/dist/renderer/components/form.d.ts +8 -10
  79. package/dist/renderer/components/form.d.ts.map +1 -1
  80. package/dist/renderer/components/form.js +147 -238
  81. package/dist/renderer/components/form.js.map +1 -1
  82. package/dist/renderer/components/interactive.d.ts.map +1 -1
  83. package/dist/renderer/components/interactive.js +115 -158
  84. package/dist/renderer/components/interactive.js.map +1 -1
  85. package/dist/renderer/components/layout.js +29 -14
  86. package/dist/renderer/components/layout.js.map +1 -1
  87. package/dist/renderer/components/media.d.ts.map +1 -1
  88. package/dist/renderer/components/media.js +24 -15
  89. package/dist/renderer/components/media.js.map +1 -1
  90. package/dist/renderer/components/pdf.d.ts +38 -0
  91. package/dist/renderer/components/pdf.d.ts.map +1 -1
  92. package/dist/renderer/components/pdf.js +152 -174
  93. package/dist/renderer/components/pdf.js.map +1 -1
  94. package/dist/renderer/components/table.d.ts +4 -0
  95. package/dist/renderer/components/table.d.ts.map +1 -1
  96. package/dist/renderer/components/table.js +47 -35
  97. package/dist/renderer/components/table.js.map +1 -1
  98. package/dist/renderer/icons.d.ts +5 -0
  99. package/dist/renderer/icons.d.ts.map +1 -0
  100. package/dist/renderer/icons.generated.d.ts +3 -0
  101. package/dist/renderer/icons.generated.d.ts.map +1 -0
  102. package/dist/renderer/icons.generated.js +64 -0
  103. package/dist/renderer/icons.generated.js.map +1 -0
  104. package/dist/renderer/icons.js +23 -0
  105. package/dist/renderer/icons.js.map +1 -0
  106. package/dist/renderer/index.js +7 -12
  107. package/dist/renderer/index.js.map +1 -1
  108. package/dist/renderer/theme.d.ts.map +1 -1
  109. package/dist/renderer/theme.js +3 -32
  110. package/dist/renderer/theme.js.map +1 -1
  111. package/dist/renderer.auto.min.js +10 -10
  112. package/dist/renderer.min.js +10 -10
  113. package/package.json +3 -1
package/dist/prefab.css CHANGED
@@ -1,31 +1,12 @@
1
- /*
2
- * prefab.css — Base theme for the prefab renderer.
3
- *
4
- * Provides CSS custom properties (shadcn-compatible design tokens) and
5
- * structural styles for all pf-* component classes. Import this file or
6
- * add a <link> tag to get a polished default look without BYO CSS.
7
- *
8
- * Token naming follows shadcn/ui conventions so existing Tailwind themes
9
- * can override them seamlessly.
10
- */
11
-
12
- /* ═══════════════════════════════════════════════════════════════════════════
13
- 1. DESIGN TOKENS — Light & Dark
14
- ═══════════════════════════════════════════════════════════════════════════
15
- Fallback chain: MCP Apps vars → VS Code vars → static defaults.
16
- When rendered inside Claude Desktop, VS Code webviews, or standalone,
17
- the correct tokens are resolved automatically without user CSS.
18
-
19
- MCP Apps spec: --color-background-primary, --color-text-primary, …
20
- VS Code: --vscode-editor-background, --vscode-editor-foreground, …
21
- ═══════════════════════════════════════════════════════════════════════════ */
1
+ /* prefab.css: shadcn-compatible tokens and pf-* component styles. Built into dist/prefab.css. */
22
2
 
23
3
  :root {
24
- /* Radii */
4
+ color-scheme: light;
5
+
25
6
  --radius: var(--border-radius-md, 8px);
26
7
  --radius-sm: var(--border-radius-sm, 6px);
8
+ --radius-lg: var(--border-radius-lg, 12px);
27
9
 
28
- /* Core palette — MCP Apps → VS Code → static */
29
10
  --background: var(--color-background-primary, var(--vscode-editor-background, #ffffff));
30
11
  --foreground: var(--color-text-primary, var(--vscode-editor-foreground, #09090b));
31
12
 
@@ -50,24 +31,24 @@
50
31
  --destructive: var(--color-background-danger, var(--vscode-errorForeground, #ef4444));
51
32
  --destructive-foreground: var(--color-text-inverse, #ffffff);
52
33
 
53
- --success: var(--color-background-success, #22c55e);
34
+ --success: var(--color-background-success, #16a34a);
54
35
  --success-foreground: var(--color-text-inverse, #ffffff);
55
36
 
56
37
  --warning: var(--color-background-warning, #f59e0b);
57
- --warning-foreground: var(--color-text-inverse, #ffffff);
38
+ --warning-foreground: var(--color-text-inverse, #422006);
39
+
40
+ --info: var(--color-text-info, #0284c7);
41
+ --info-foreground: var(--color-text-inverse, #ffffff);
58
42
 
59
43
  --border: var(--color-border-primary, var(--vscode-panel-border, #e5e7eb));
60
44
  --input: var(--color-border-secondary, var(--vscode-input-background, #e5e7eb));
61
45
  --ring: var(--color-ring-primary, var(--vscode-focusBorder, #3b82f6));
62
46
 
63
- /* Typography — MCP Apps uses --font-sans/--font-mono directly (same names);
64
- host inline styles override these automatically. VS Code fallback here. */
65
47
  --font-sans: var(--vscode-font-family, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
66
48
  Roboto, "Helvetica Neue", Arial, sans-serif);
67
49
  --font-mono: var(--vscode-editor-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
68
50
  "Liberation Mono", "Courier New", monospace);
69
51
 
70
- /* Shadows — MCP Apps host overrides these names inline when present */
71
52
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
72
53
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
73
54
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
@@ -75,6 +56,8 @@
75
56
 
76
57
  @media (prefers-color-scheme: dark) {
77
58
  :root:not([data-theme="light"]) {
59
+ color-scheme: dark;
60
+
78
61
  --background: var(--color-background-primary, var(--vscode-editor-background, #09090b));
79
62
  --foreground: var(--color-text-primary, var(--vscode-editor-foreground, #fafafa));
80
63
 
@@ -105,30 +88,22 @@
105
88
  --warning: var(--color-background-warning, #fbbf24);
106
89
  --warning-foreground: var(--color-text-inverse, #09090b);
107
90
 
91
+ --info: var(--color-text-info, #38bdf8);
92
+ --info-foreground: var(--color-text-inverse, #09090b);
93
+
108
94
  --border: var(--color-border-primary, var(--vscode-panel-border, #27272a));
109
95
  --input: var(--color-border-secondary, var(--vscode-input-background, #27272a));
110
96
  --ring: var(--color-ring-primary, var(--vscode-focusBorder, #60a5fa));
111
97
  }
112
98
  }
113
99
 
114
- /* Explicit dark override, via the data-theme attribute or the dark class.
115
- Static values only — NO host var references.
116
- In hosted mode (Claude/VS Code), data-theme is never set; the host's inline
117
- vars resolve through the var() chain in :root / @media-dark above.
118
-
119
- Three selectors, matching what compileThemeCss() emits for a wire theme, so
120
- the base tokens and the theme's tokens always flip on the same element:
121
- - :root[...] keeps specificity (0,2,0) to beat the @media dark :root:not(...)
122
- rule, which it ties with and wins on document order.
123
- - the bare attribute and class selectors carry (0,1,0) and match at ANY depth,
124
- which is what setThemeAttrs needs: it themes the prefab mount container, and
125
- createThemeToggle({ syncDocument: false }) themes ONLY that container.
126
- Specificity is not a concern below the root, since every other token rule
127
- here is :root-scoped and so does not match a container at all — a
128
- declaration on the element always beats what it would otherwise inherit. */
100
+ /* Explicit schemes via data-theme or the dark/light class. Static values only, so
101
+ the bare selectors also theme a nested mount container at any depth. */
129
102
  :root[data-theme="dark"],
130
103
  [data-theme="dark"],
131
104
  .dark {
105
+ color-scheme: dark;
106
+
132
107
  --background: #09090b;
133
108
  --foreground: #fafafa;
134
109
 
@@ -159,17 +134,19 @@
159
134
  --warning: #fbbf24;
160
135
  --warning-foreground: #09090b;
161
136
 
137
+ --info: #38bdf8;
138
+ --info-foreground: #09090b;
139
+
162
140
  --border: #27272a;
163
141
  --input: #27272a;
164
142
  --ring: #60a5fa;
165
143
  }
166
144
 
167
- /* Explicit light override, via the data-theme attribute or the light class.
168
- Same specificity, depth and static-value strategy as the dark block above.
169
- This is the direction that makes a light island under a dark root work. */
170
145
  :root[data-theme="light"],
171
146
  [data-theme="light"],
172
147
  .light {
148
+ color-scheme: light;
149
+
173
150
  --background: #ffffff;
174
151
  --foreground: #09090b;
175
152
 
@@ -194,69 +171,97 @@
194
171
  --destructive: #ef4444;
195
172
  --destructive-foreground: #ffffff;
196
173
 
197
- --success: #22c55e;
174
+ --success: #16a34a;
198
175
  --success-foreground: #ffffff;
199
176
 
200
177
  --warning: #f59e0b;
201
- --warning-foreground: #ffffff;
178
+ --warning-foreground: #422006;
179
+
180
+ --info: #0284c7;
181
+ --info-foreground: #ffffff;
202
182
 
203
183
  --border: #e5e7eb;
204
184
  --input: #e5e7eb;
205
185
  --ring: #3b82f6;
206
186
  }
207
187
 
208
- /* ═══════════════════════════════════════════════════════════════════════════
209
- 2. RESET & BASE
210
- ═══════════════════════════════════════════════════════════════════════════ */
211
-
212
188
  *, *::before, *::after {
213
189
  box-sizing: border-box;
214
190
  }
215
191
 
216
192
  .pf-app-root {
217
193
  font-family: var(--font-sans);
194
+ font-size: 1rem;
218
195
  color: var(--foreground);
219
196
  background-color: var(--background);
220
197
  line-height: 1.5;
221
198
  -webkit-font-smoothing: antialiased;
222
199
  -moz-osx-font-smoothing: grayscale;
200
+ text-rendering: optimizeLegibility;
201
+ }
202
+
203
+ :where(.pf-button, .pf-input, .pf-textarea, .pf-select, .pf-combobox-input, .pf-datatable-search,
204
+ .pf-tab-trigger, .pf-accordion-trigger, .pf-carousel-prev, .pf-carousel-next, .pf-dialog-close,
205
+ .pf-theme-toggle, .pf-expandable-row-summary) {
206
+ font: inherit;
207
+ color: inherit;
208
+ letter-spacing: inherit;
209
+ }
210
+
211
+ :where(.pf-app-root, .pf-toast-region, .pf-dialog) :focus-visible {
212
+ outline: 2px solid var(--ring);
213
+ outline-offset: 2px;
223
214
  }
224
215
 
225
- /* ═══════════════════════════════════════════════════════════════════════════
226
- 3. LAYOUT
227
- ═══════════════════════════════════════════════════════════════════════════ */
216
+ @media (prefers-reduced-motion: reduce) {
217
+ :where(.pf-app-root, .pf-toast-region) *,
218
+ :where(.pf-app-root, .pf-toast-region) *::before,
219
+ :where(.pf-app-root, .pf-toast-region) *::after {
220
+ animation-duration: 0.01ms !important;
221
+ transition-duration: 0.01ms !important;
222
+ }
223
+ }
228
224
 
229
225
  .pf-column { display: flex; flex-direction: column; }
230
226
  .pf-row { display: flex; flex-direction: row; flex-wrap: wrap; }
231
227
  .pf-grid { display: grid; }
232
228
 
233
229
  .pf-grid-item { min-width: 0; }
230
+ .pf-grid-item > .pf-card:only-child { height: 100%; }
234
231
  .pf-container { width: 100%; max-width: 1200px; margin: 0 auto; }
235
232
  .pf-div { display: block; }
236
233
  .pf-span { display: inline; }
237
234
  .pf-pages { position: relative; }
238
235
 
239
- /* ═══════════════════════════════════════════════════════════════════════════
240
- 4. TYPOGRAPHY
241
- ═══════════════════════════════════════════════════════════════════════════ */
236
+ .pf-master-detail { display: flex; flex-direction: row; min-height: 0; }
237
+ .pf-master-detail-master { flex-shrink: 0; overflow: auto; }
238
+ .pf-master-detail-detail { flex: 1; min-width: 0; overflow: auto; }
242
239
 
243
- .pf-heading { margin: 0; font-weight: 600; letter-spacing: -0.02em; }
244
- .pf-h1 { font-size: 2.25rem; line-height: 2.5rem; }
240
+ @media (max-width: 560px) {
241
+ .pf-grid { grid-template-columns: minmax(0, 1fr) !important; }
242
+ .pf-grid-item { grid-column: auto !important; grid-row: auto !important; }
243
+ .pf-master-detail { flex-direction: column; }
244
+ .pf-master-detail-master { width: auto !important; }
245
+ }
246
+
247
+ .pf-heading { margin: 0; font-weight: 600; letter-spacing: -0.02em; text-wrap: balance; }
248
+ .pf-h1 { font-size: 2.25rem; line-height: 2.5rem; font-weight: 700; }
245
249
  .pf-h2 { font-size: 1.875rem; line-height: 2.25rem; }
246
250
  .pf-h3 { font-size: 1.5rem; line-height: 2rem; }
247
251
  .pf-h4 { font-size: 1.25rem; line-height: 1.75rem; }
252
+ .pf-h5 { font-size: 1.125rem; line-height: 1.75rem; }
253
+ .pf-h6 { font-size: 1rem; line-height: 1.5rem; }
248
254
 
249
- .pf-text { }
250
- .pf-p { margin: 0; }
251
- .pf-lead { font-size: 1.25rem; color: var(--muted-foreground); }
252
- .pf-large { font-size: 1.125rem; font-weight: 600; }
253
- .pf-small { font-size: 0.875rem; }
254
- .pf-muted { color: var(--muted-foreground); font-size: 0.875rem; margin: 0; }
255
+ .pf-p { margin: 0; line-height: 1.625; }
256
+ .pf-lead { margin: 0; font-size: 1.125rem; line-height: 1.75rem; color: var(--muted-foreground); }
257
+ .pf-large { font-size: 1.125rem; line-height: 1.75rem; font-weight: 600; }
258
+ .pf-small { font-size: 0.875rem; line-height: 1.25rem; font-weight: 500; }
259
+ .pf-muted { margin: 0; color: var(--muted-foreground); font-size: 0.875rem; line-height: 1.25rem; }
255
260
 
256
261
  .pf-blockquote {
257
262
  margin: 0;
258
263
  padding-left: 1rem;
259
- border-left: 3px solid var(--border);
264
+ border-left: 2px solid var(--border);
260
265
  font-style: italic;
261
266
  color: var(--muted-foreground);
262
267
  }
@@ -264,31 +269,40 @@
264
269
  .pf-label {
265
270
  font-size: 0.875rem;
266
271
  font-weight: 500;
272
+ line-height: 1.25rem;
267
273
  }
268
274
 
269
275
  .pf-link {
270
276
  color: var(--primary);
271
277
  text-decoration: underline;
278
+ text-decoration-color: color-mix(in oklab, var(--primary) 40%, transparent);
272
279
  text-underline-offset: 4px;
273
280
  cursor: pointer;
281
+ transition: text-decoration-color 0.15s;
274
282
  }
275
- .pf-link:hover { text-decoration-thickness: 2px; }
283
+ .pf-link:hover { text-decoration-color: currentColor; }
276
284
 
277
285
  .pf-code {
278
286
  font-family: var(--font-mono);
279
- font-size: 0.875rem;
287
+ font-size: 0.8125rem;
288
+ line-height: 1.6;
280
289
  background: var(--muted);
281
290
  border: 1px solid var(--border);
282
291
  border-radius: var(--radius-sm);
283
- padding: 1rem;
292
+ padding: 0.875rem 1rem;
284
293
  overflow-x: auto;
285
294
  margin: 0;
286
295
  white-space: pre;
287
296
  }
288
297
 
289
298
  .pf-markdown { line-height: 1.7; }
290
- .pf-markdown h1, .pf-markdown h2, .pf-markdown h3 { margin-top: 1.5em; margin-bottom: 0.5em; }
299
+ .pf-markdown > :first-child { margin-top: 0; }
300
+ .pf-markdown > :last-child { margin-bottom: 0; }
301
+ .pf-markdown h1, .pf-markdown h2, .pf-markdown h3 { margin: 1.5em 0 0.5em; line-height: 1.3; letter-spacing: -0.01em; }
291
302
  .pf-markdown p { margin: 0.75em 0; }
303
+ .pf-markdown ul, .pf-markdown ol { margin: 0.75em 0; padding-left: 1.5em; }
304
+ .pf-markdown li + li { margin-top: 0.25em; }
305
+ .pf-markdown a { color: var(--primary); text-underline-offset: 4px; }
292
306
  .pf-markdown code {
293
307
  font-family: var(--font-mono);
294
308
  font-size: 0.875em;
@@ -296,6 +310,13 @@
296
310
  padding: 0.15em 0.4em;
297
311
  border-radius: 4px;
298
312
  }
313
+ .pf-markdown pre {
314
+ background: var(--muted);
315
+ border: 1px solid var(--border);
316
+ border-radius: var(--radius-sm);
317
+ padding: 0.875rem 1rem;
318
+ overflow-x: auto;
319
+ }
299
320
  .pf-markdown pre code { background: none; padding: 0; }
300
321
 
301
322
  .pf-kbd {
@@ -304,101 +325,195 @@
304
325
  justify-content: center;
305
326
  font-family: var(--font-mono);
306
327
  font-size: 0.75rem;
328
+ font-weight: 500;
329
+ line-height: 1;
307
330
  min-width: 1.5em;
308
- padding: 0.15em 0.4em;
331
+ height: 1.5em;
332
+ padding: 0 0.4em;
309
333
  border: 1px solid var(--border);
310
334
  border-radius: 4px;
311
335
  background: var(--muted);
336
+ color: var(--muted-foreground);
312
337
  box-shadow: 0 1px 0 var(--border);
313
338
  }
314
339
 
315
- /* ═══════════════════════════════════════════════════════════════════════════
316
- 5. CARD
317
- ═══════════════════════════════════════════════════════════════════════════ */
340
+ .pf-app-root [role="button"]:not(button, .pf-expandable-row-summary) { cursor: pointer; }
318
341
 
319
342
  .pf-card {
320
343
  background: var(--card);
321
344
  color: var(--card-foreground);
322
345
  border: 1px solid var(--border);
323
- border-radius: var(--radius);
324
- overflow: hidden;
346
+ border-radius: var(--radius-lg);
347
+ box-shadow: var(--shadow-sm);
325
348
  }
349
+ .pf-card:not(:has(> .pf-card-header, > .pf-card-content, > .pf-card-footer)) { padding: 1.5rem; }
326
350
 
327
- .pf-card-header { padding: 1.5rem 1.5rem 0; }
328
- .pf-card-content { padding: 1.5rem; }
329
- .pf-card-footer { padding: 0 1.5rem 1.5rem; display: flex; align-items: center; gap: 0.5rem; }
351
+ .pf-card[role="button"] { transition: border-color 0.15s, box-shadow 0.15s; }
352
+ .pf-card[role="button"]:hover { border-color: color-mix(in oklab, var(--primary) 35%, var(--border)); box-shadow: var(--shadow-md); }
330
353
 
331
- .pf-card-title { margin: 0; font-size: 1.25rem; font-weight: 600; }
332
- .pf-card-description { margin: 0.25rem 0 0; color: var(--muted-foreground); font-size: 0.875rem; }
354
+ .pf-card-header { display: flex; flex-direction: column; gap: 0.375rem; padding: 1.5rem 1.5rem 0; }
355
+ .pf-card-content { padding: 1.5rem; }
356
+ .pf-card-header + .pf-card-content { padding-top: 1.25rem; }
357
+ .pf-card-footer { display: flex; align-items: center; gap: 0.5rem; padding: 0 1.5rem 1.5rem; }
358
+ .pf-card-header:last-child { padding-bottom: 1.5rem; }
333
359
 
334
- /* ═══════════════════════════════════════════════════════════════════════════
335
- 6. ALERT
336
- ═══════════════════════════════════════════════════════════════════════════ */
360
+ .pf-card-title { margin: 0; font-size: 1.125rem; line-height: 1.4; font-weight: 600; letter-spacing: -0.01em; }
361
+ .pf-card-description { margin: 0; color: var(--muted-foreground); font-size: 0.875rem; line-height: 1.25rem; }
337
362
 
338
363
  .pf-alert {
364
+ --pf-tone: var(--foreground);
339
365
  position: relative;
340
- padding: 1rem 1rem 1rem 3rem;
366
+ display: flex;
367
+ flex-direction: column;
368
+ gap: 0.25rem;
369
+ padding: 0.875rem 1rem;
341
370
  border: 1px solid var(--border);
342
371
  border-radius: var(--radius);
372
+ background: var(--card);
373
+ color: var(--card-foreground);
374
+ font-size: 0.875rem;
375
+ line-height: 1.25rem;
343
376
  }
344
- .pf-alert[data-variant="destructive"] {
345
- border-color: var(--destructive);
346
- color: var(--destructive);
377
+ .pf-alert:has(> .pf-alert-icon) { padding-left: 2.75rem; }
378
+ .pf-alert[data-variant="destructive"] { --pf-tone: var(--destructive); }
379
+ .pf-alert[data-variant="success"] { --pf-tone: var(--success); }
380
+ .pf-alert[data-variant="warning"] { --pf-tone: var(--warning); }
381
+ .pf-alert[data-variant="info"] { --pf-tone: var(--info); }
382
+ .pf-alert:not([data-variant="default"]) {
383
+ border-color: color-mix(in oklab, var(--pf-tone) 45%, var(--border));
384
+ background: color-mix(in oklab, var(--pf-tone) 7%, var(--card));
385
+ color: color-mix(in oklab, var(--pf-tone) 70%, var(--foreground));
347
386
  }
348
387
  .pf-alert-icon {
349
388
  position: absolute;
350
389
  left: 1rem;
351
- top: 1rem;
390
+ top: 0.9375rem;
391
+ width: 1.125rem;
392
+ height: 1.125rem;
393
+ color: var(--pf-tone);
352
394
  }
353
- .pf-alert-title { margin: 0; font-weight: 600; font-size: 0.875rem; }
354
- .pf-alert-description { margin: 0.25rem 0 0; font-size: 0.875rem; }
355
-
356
- /* ═══════════════════════════════════════════════════════════════════════════
357
- 7. BADGE
358
- ═══════════════════════════════════════════════════════════════════════════ */
395
+ .pf-alert-title { margin: 0; font-size: 0.875rem; font-weight: 600; line-height: 1.25rem; }
396
+ .pf-alert-description { margin: 0; font-size: 0.875rem; line-height: 1.25rem; opacity: 0.9; }
397
+ .pf-alert[data-variant="default"] .pf-alert-description { color: var(--muted-foreground); opacity: 1; }
359
398
 
360
399
  .pf-badge {
361
400
  display: inline-flex;
362
401
  align-items: center;
363
- /* Hug content: as a flex child, inline-flex is blockified to flex and would
364
- otherwise stretch to the container's cross size (full width in a column,
365
- full height in a row). align-self keeps the pill intrinsically sized; an
366
- explicit w-full/width utility still overrides it. */
367
402
  align-self: flex-start;
403
+ gap: 0.25rem;
404
+ border: 1px solid transparent;
368
405
  border-radius: 9999px;
369
- padding: 0.15em 0.6em;
406
+ padding: 0.125rem 0.5rem;
370
407
  font-size: 0.75rem;
371
- font-weight: 600;
372
- line-height: 1;
408
+ font-weight: 500;
409
+ line-height: 1rem;
373
410
  white-space: nowrap;
374
411
  transition: background-color 0.15s;
375
412
  }
413
+ .pf-row > .pf-badge { align-self: center; }
376
414
  .pf-badge[data-variant="default"] { background: var(--primary); color: var(--primary-foreground); }
377
415
  .pf-badge[data-variant="secondary"] { background: var(--secondary); color: var(--secondary-foreground); }
378
416
  .pf-badge[data-variant="destructive"] { background: var(--destructive); color: var(--destructive-foreground); }
379
417
  .pf-badge[data-variant="success"] { background: var(--success); color: var(--success-foreground); }
380
418
  .pf-badge[data-variant="warning"] { background: var(--warning); color: var(--warning-foreground); }
381
- .pf-badge[data-variant="outline"] { background: transparent; border: 1px solid var(--border); color: var(--foreground); }
419
+ .pf-badge[data-variant="info"] { background: var(--info); color: var(--info-foreground); }
420
+ .pf-badge[data-variant="outline"] { background: transparent; border-color: var(--border); color: var(--foreground); }
382
421
 
383
422
  .pf-dot {
384
423
  display: inline-block;
424
+ flex-shrink: 0;
385
425
  width: 0.5rem;
386
426
  height: 0.5rem;
387
427
  border-radius: 9999px;
428
+ background-color: var(--muted-foreground);
388
429
  }
389
430
 
390
- /* ═══════════════════════════════════════════════════════════════════════════
391
- 8. DATA — Metric, Ring, Progress, Separator, Loader, Icon, Sparkline
392
- ═══════════════════════════════════════════════════════════════════════════ */
393
-
394
- .pf-metric { display: flex; flex-direction: column; gap: 0.25rem; }
395
- .pf-metric-label { font-size: 0.875rem; color: var(--muted-foreground); }
396
- .pf-metric-value { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
397
- .pf-metric-delta { font-size: 0.875rem; font-weight: 500; margin-left: 0.5rem; }
398
- .pf-metric-desc { font-size: 0.75rem; color: var(--muted-foreground); }
431
+ .pf-toast-region {
432
+ position: fixed;
433
+ right: 1rem;
434
+ bottom: 1rem;
435
+ z-index: 9999;
436
+ display: flex;
437
+ flex-direction: column;
438
+ gap: 0.5rem;
439
+ width: min(24rem, calc(100vw - 2rem));
440
+ font-family: var(--font-sans);
441
+ color: var(--foreground);
442
+ line-height: 1.5;
443
+ pointer-events: none;
444
+ }
445
+ .pf-toast {
446
+ --pf-tone: var(--border);
447
+ display: flex;
448
+ flex-direction: column;
449
+ gap: 0.125rem;
450
+ background: var(--popover);
451
+ color: var(--popover-foreground);
452
+ border: 1px solid var(--border);
453
+ border-left: 3px solid var(--pf-tone);
454
+ border-radius: var(--radius);
455
+ padding: 0.75rem 1rem;
456
+ box-shadow: var(--shadow-lg);
457
+ pointer-events: auto;
458
+ animation: pf-toast-in 0.2s ease-out;
459
+ transition: opacity 0.3s ease, transform 0.3s ease;
460
+ }
461
+ .pf-toast--success { --pf-tone: var(--success); }
462
+ .pf-toast--error { --pf-tone: var(--destructive); }
463
+ .pf-toast--warning { --pf-tone: var(--warning); }
464
+ .pf-toast--info { --pf-tone: var(--info); }
465
+ .pf-toast--leaving { opacity: 0; transform: translateY(0.5rem); }
466
+ .pf-toast-title { font-size: 0.875rem; font-weight: 600; line-height: 1.25rem; }
467
+ .pf-toast-description { font-size: 0.8125rem; line-height: 1.25rem; color: var(--muted-foreground); }
468
+ @keyframes pf-toast-in { from { opacity: 0; transform: translateY(0.5rem); } }
469
+
470
+ .pf-theme-toggle {
471
+ position: absolute;
472
+ z-index: 100;
473
+ display: flex;
474
+ align-items: center;
475
+ justify-content: center;
476
+ width: 2rem;
477
+ height: 2rem;
478
+ padding: 0;
479
+ border: 1px solid var(--border);
480
+ border-radius: var(--radius-sm);
481
+ background: var(--card);
482
+ color: var(--muted-foreground);
483
+ cursor: pointer;
484
+ backdrop-filter: blur(4px);
485
+ transition: color 0.15s, background-color 0.15s;
486
+ }
487
+ .pf-theme-toggle:hover { color: var(--foreground); background: var(--muted); }
488
+ .pf-theme-toggle[data-position="top-right"] { top: 0.25rem; right: 0.25rem; }
489
+ .pf-theme-toggle[data-position="top-left"] { top: 0.25rem; left: 0.25rem; }
490
+ .pf-theme-toggle[data-position="bottom-right"] { bottom: 0.25rem; right: 0.25rem; }
491
+ .pf-theme-toggle[data-position="bottom-left"] { bottom: 0.25rem; left: 0.25rem; }
492
+ .pf-app-root:has(> .pf-theme-toggle[data-position^="top"]) { padding-top: 2.75rem; }
493
+ .pf-app-root:has(> .pf-theme-toggle[data-position^="bottom"]) { padding-bottom: 2.75rem; }
494
+
495
+ .pf-metric { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
496
+ .pf-metric-label { font-size: 0.875rem; font-weight: 500; line-height: 1.25rem; color: var(--muted-foreground); }
497
+ .pf-metric-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
498
+ .pf-metric-value { font-size: 1.75rem; line-height: 2.25rem; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
499
+ .pf-metric-delta {
500
+ display: inline-flex;
501
+ align-items: center;
502
+ gap: 0.125rem;
503
+ font-size: 0.8125rem;
504
+ font-weight: 500;
505
+ font-variant-numeric: tabular-nums;
506
+ color: var(--muted-foreground);
507
+ }
508
+ .pf-metric-delta[data-sentiment="positive"] { color: color-mix(in oklab, var(--success) 80%, var(--foreground)); }
509
+ .pf-metric-delta[data-sentiment="negative"] { color: color-mix(in oklab, var(--destructive) 85%, var(--foreground)); }
510
+ .pf-metric-desc { font-size: 0.75rem; line-height: 1rem; color: var(--muted-foreground); }
399
511
 
400
- .pf-ring { position: relative; display: inline-flex; align-items: center; justify-content: center; }
401
- .pf-ring-label { position: absolute; text-align: center; font-size: 0.875rem; font-weight: 600; }
512
+ .pf-ring { position: relative; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
513
+ .pf-ring svg { display: block; }
514
+ .pf-ring-track { stroke: var(--muted); }
515
+ .pf-ring-fill { stroke: var(--primary); transform: rotate(-90deg); transform-origin: center; transition: stroke-dashoffset 0.4s ease; }
516
+ .pf-ring-label { position: absolute; text-align: center; font-size: 0.8125rem; font-weight: 600; font-variant-numeric: tabular-nums; }
402
517
 
403
518
  .pf-progress {
404
519
  width: 100%;
@@ -415,300 +530,433 @@
415
530
  }
416
531
 
417
532
  .pf-separator {
418
- border: none;
419
- border-top: 1px solid var(--border);
533
+ flex-shrink: 0;
534
+ width: 100%;
535
+ height: 0;
420
536
  margin: 0;
537
+ border: 0;
538
+ border-top: 1px solid var(--border);
539
+ }
540
+
541
+ .pf-separator[data-orientation="vertical"] {
542
+ width: 0;
543
+ height: auto;
544
+ align-self: stretch;
545
+ border-top: 0;
546
+ border-left: 1px solid var(--border);
421
547
  }
422
548
 
423
549
  .pf-loader {
424
550
  display: inline-block;
551
+ flex-shrink: 0;
552
+ align-self: center;
425
553
  width: 1.5rem;
426
554
  height: 1.5rem;
427
555
  border: 2px solid var(--muted);
428
556
  border-top-color: var(--primary);
429
557
  border-radius: 50%;
430
- animation: pf-spin 0.6s linear infinite;
558
+ animation: pf-spin 0.7s linear infinite;
431
559
  }
432
560
  @keyframes pf-spin { to { transform: rotate(360deg); } }
433
561
 
434
- .pf-icon { display: inline-flex; align-items: center; }
435
-
436
- .pf-sparkline svg { display: block; }
562
+ .pf-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 1.25em; height: 1.25em; vertical-align: -0.25em; }
563
+ .pf-icon svg { width: 100%; height: 100%; }
437
564
 
438
- /* ═══════════════════════════════════════════════════════════════════════════
439
- 9. DATATABLE
440
- ═══════════════════════════════════════════════════════════════════════════ */
565
+ .pf-sparkline { display: inline-flex; flex-shrink: 0; }
566
+ .pf-sparkline svg { display: block; overflow: visible; }
567
+ .pf-sparkline polyline { stroke: var(--primary); stroke-linecap: round; stroke-linejoin: round; }
441
568
 
442
- .pf-datatable-wrapper { overflow-x: auto; }
569
+ .pf-datatable-wrapper { display: flex; flex-direction: column; gap: 0.75rem; min-width: 0; }
570
+ .pf-datatable-scroll {
571
+ overflow-x: auto;
572
+ border: 1px solid var(--border);
573
+ border-radius: var(--radius);
574
+ }
443
575
 
444
- .pf-datatable {
576
+ .pf-datatable, .pf-table {
445
577
  width: 100%;
446
578
  border-collapse: collapse;
447
579
  font-size: 0.875rem;
580
+ line-height: 1.25rem;
448
581
  }
449
- .pf-datatable-th {
582
+ .pf-datatable-th, .pf-table-header {
583
+ height: 2.5rem;
584
+ padding: 0 0.75rem;
450
585
  text-align: left;
451
- padding: 0.75rem 1rem;
452
- font-weight: 600;
453
- border-bottom: 2px solid var(--border);
586
+ vertical-align: middle;
587
+ font-size: 0.8125rem;
588
+ font-weight: 500;
589
+ color: var(--muted-foreground);
590
+ border-bottom: 1px solid var(--border);
454
591
  white-space: nowrap;
455
592
  }
456
- .pf-datatable-td {
457
- padding: 0.75rem 1rem;
593
+ .pf-datatable-th { background: color-mix(in oklab, var(--muted) 45%, transparent); }
594
+ .pf-datatable-td, .pf-table-cell {
595
+ padding: 0.75rem;
596
+ vertical-align: middle;
458
597
  border-bottom: 1px solid var(--border);
459
598
  }
460
- .pf-datatable-search {
461
- width: 100%;
462
- max-width: 20rem;
463
- padding: 0.5rem 0.75rem;
464
- margin-bottom: 0.75rem;
465
- border: 1px solid var(--input);
466
- border-radius: var(--radius-sm);
467
- font-size: 0.875rem;
468
- background: var(--background);
469
- color: var(--foreground);
470
- }
471
- .pf-datatable-search:focus {
472
- outline: 2px solid var(--ring);
473
- outline-offset: -1px;
474
- }
599
+ .pf-datatable tbody tr:last-child .pf-datatable-td { border-bottom: 0; }
600
+ .pf-datatable-row, .pf-table tbody .pf-table-row { transition: background-color 0.15s; }
601
+ .pf-datatable-row:hover, .pf-table tbody .pf-table-row:hover { background: color-mix(in oklab, var(--muted) 50%, transparent); }
602
+ .pf-datatable-row-clickable { cursor: pointer; }
603
+ .pf-datatable-row-selected,
604
+ .pf-datatable-row-selected:hover { background: color-mix(in oklab, var(--primary) 12%, transparent); }
605
+ .pf-datatable-empty { padding: 1.5rem 0.75rem; text-align: center; color: var(--muted-foreground); }
475
606
 
476
- /* ═══════════════════════════════════════════════════════════════════════════
477
- 10. TABLE (semantic HTML table)
478
- ═══════════════════════════════════════════════════════════════════════════ */
479
-
480
- .pf-table {
481
- width: 100%;
482
- border-collapse: collapse;
483
- font-size: 0.875rem;
484
- }
485
- .pf-table-row { }
486
- /* Table({ striped: true }) — shade alternate body rows. */
487
607
  .pf-table-striped tbody .pf-table-row:nth-child(even) {
488
608
  background: color-mix(in oklab, var(--muted) 40%, transparent);
489
609
  }
490
- .pf-table-header {
491
- text-align: left;
492
- padding: 0.75rem 1rem;
493
- font-weight: 600;
494
- border-bottom: 2px solid var(--border);
495
- }
496
- .pf-table-cell {
497
- padding: 0.75rem 1rem;
498
- border-bottom: 1px solid var(--border);
499
- }
610
+ .pf-tfoot .pf-table-cell { font-weight: 500; background: color-mix(in oklab, var(--muted) 45%, transparent); }
500
611
  .pf-table-caption {
501
612
  caption-side: bottom;
502
- padding: 0.5rem;
613
+ padding-top: 0.75rem;
503
614
  color: var(--muted-foreground);
504
- font-size: 0.875rem;
615
+ font-size: 0.8125rem;
505
616
  }
506
617
 
507
- .pf-expandable-row { }
618
+ .pf-expandable-row { border-bottom: 1px solid var(--border); }
508
619
  .pf-expandable-row-summary {
509
620
  display: flex;
510
621
  align-items: center;
511
622
  gap: 0.5rem;
623
+ width: 100%;
624
+ padding: 0.625rem 0;
625
+ font-size: 0.875rem;
626
+ font-weight: 500;
627
+ text-align: left;
512
628
  cursor: pointer;
513
629
  user-select: none;
514
630
  }
515
631
  .pf-expandable-arrow {
516
632
  display: inline-block;
633
+ flex-shrink: 0;
634
+ width: 0.4375rem;
635
+ height: 0.4375rem;
636
+ margin: 0 0.25rem;
637
+ border-right: 1.5px solid var(--muted-foreground);
638
+ border-bottom: 1.5px solid var(--muted-foreground);
639
+ transform: rotate(-45deg);
517
640
  transition: transform 0.2s;
518
641
  }
519
- .pf-expandable-row-detail {
520
- padding-left: 1.5rem;
521
- }
642
+ .pf-expandable-row-summary[aria-expanded="true"] .pf-expandable-arrow { transform: rotate(45deg); }
643
+ .pf-expandable-row-detail { padding: 0 0 0.75rem 1.5rem; }
522
644
 
523
- /* ═══════════════════════════════════════════════════════════════════════════
524
- 11. FORM
525
- ═══════════════════════════════════════════════════════════════════════════ */
645
+ .pf-ring[data-variant="success"] .pf-ring-fill, .pf-progress[data-variant="success"] .pf-progress-fill { stroke: var(--success); background: var(--success); }
646
+ .pf-ring[data-variant="warning"] .pf-ring-fill, .pf-progress[data-variant="warning"] .pf-progress-fill { stroke: var(--warning); background: var(--warning); }
647
+ .pf-ring[data-variant="destructive"] .pf-ring-fill, .pf-progress[data-variant="destructive"] .pf-progress-fill { stroke: var(--destructive); background: var(--destructive); }
648
+ .pf-ring[data-variant="info"] .pf-ring-fill, .pf-progress[data-variant="info"] .pf-progress-fill { stroke: var(--info); background: var(--info); }
526
649
 
527
650
  .pf-form { display: flex; flex-direction: column; gap: 1rem; }
528
651
 
529
- .pf-input-wrapper, .pf-textarea-wrapper, .pf-select-wrapper, .pf-slider-wrapper {
652
+ .pf-labeled, .pf-input-wrapper, .pf-textarea-wrapper, .pf-select-wrapper, .pf-slider-wrapper, .pf-field {
530
653
  display: flex;
531
654
  flex-direction: column;
532
- gap: 0.375rem;
655
+ gap: 0.5rem;
656
+ min-width: 0;
533
657
  }
534
658
 
535
- .pf-input-label {
659
+ .pf-input-label, .pf-field-title {
536
660
  font-size: 0.875rem;
537
661
  font-weight: 500;
662
+ line-height: 1.25rem;
538
663
  }
664
+ .pf-input-label[data-required]::after, .pf-radio-legend[data-required]::after { content: " *"; color: var(--destructive); }
539
665
 
540
- .pf-input, .pf-textarea, .pf-select {
541
- padding: 0.5rem 0.75rem;
666
+ .pf-input, .pf-textarea, .pf-select, .pf-combobox-input, .pf-datatable-search {
667
+ display: block;
668
+ width: 100%;
669
+ min-height: 2.25rem;
670
+ padding: 0.4375rem 0.75rem;
542
671
  border: 1px solid var(--input);
543
672
  border-radius: var(--radius-sm);
544
- font-size: 0.875rem;
545
673
  background: var(--background);
546
674
  color: var(--foreground);
675
+ font-size: 0.875rem;
676
+ line-height: 1.25rem;
677
+ box-shadow: var(--shadow-sm);
547
678
  transition: border-color 0.15s, box-shadow 0.15s;
548
679
  }
549
- .pf-input:focus, .pf-textarea:focus, .pf-select:focus {
550
- outline: 2px solid var(--ring);
551
- outline-offset: -1px;
680
+ :is(.pf-input, .pf-textarea, .pf-combobox-input, .pf-datatable-search)::placeholder {
681
+ color: var(--muted-foreground);
682
+ opacity: 1;
683
+ }
684
+ :is(.pf-input, .pf-textarea, .pf-select, .pf-combobox-input, .pf-datatable-search):focus-visible {
685
+ outline: none;
552
686
  border-color: var(--ring);
687
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--ring) 25%, transparent);
688
+ }
689
+ :is(.pf-input, .pf-textarea, .pf-select, .pf-combobox-input)[aria-invalid="true"] { border-color: var(--destructive); }
690
+ :is(.pf-input, .pf-textarea, .pf-select, .pf-combobox-input)[aria-invalid="true"]:focus-visible {
691
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--destructive) 25%, transparent);
553
692
  }
693
+ :is(.pf-input, .pf-textarea, .pf-select, .pf-combobox-input):disabled { opacity: 0.5; cursor: not-allowed; }
554
694
  .pf-textarea { min-height: 5rem; resize: vertical; }
695
+ .pf-datatable-search { max-width: 20rem; }
696
+ .pf-input[type="date"] { cursor: text; }
697
+ .pf-input[type="date"]::-webkit-calendar-picker-indicator { cursor: pointer; opacity: 0.6; }
698
+ .pf-input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }
699
+
700
+ .pf-select:not([multiple]) {
701
+ appearance: none;
702
+ padding-right: 2.25rem;
703
+ background-image:
704
+ linear-gradient(45deg, transparent 50%, var(--muted-foreground) 50%),
705
+ linear-gradient(135deg, var(--muted-foreground) 50%, transparent 50%);
706
+ background-position: calc(100% - 1.125rem) 52%, calc(100% - 0.8125rem) 52%;
707
+ background-size: 0.3125rem 0.3125rem;
708
+ background-repeat: no-repeat;
709
+ cursor: pointer;
710
+ }
711
+ .pf-select[multiple] { padding: 0.25rem; }
712
+ .pf-select[multiple] option { padding: 0.375rem 0.5rem; border-radius: calc(var(--radius-sm) - 2px); }
713
+ .pf-select-group { display: contents; }
714
+ .pf-select-label { font-size: 0.75rem; color: var(--muted-foreground); font-weight: 600; padding: 0.25rem 0; }
555
715
 
556
- /* Buttons */
557
716
  .pf-button {
558
717
  display: inline-flex;
559
718
  align-items: center;
560
719
  justify-content: center;
561
720
  gap: 0.5rem;
562
- padding: 0.5rem 1rem;
563
- border: none;
721
+ flex-shrink: 0;
722
+ height: 2.25rem;
723
+ padding: 0 1rem;
724
+ border: 1px solid transparent;
564
725
  border-radius: var(--radius-sm);
565
726
  font-size: 0.875rem;
566
727
  font-weight: 500;
567
- cursor: pointer;
568
- transition: opacity 0.15s, background-color 0.15s;
728
+ line-height: 1;
569
729
  white-space: nowrap;
730
+ text-decoration: none;
731
+ cursor: pointer;
732
+ user-select: none;
733
+ transition: background-color 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.15s;
570
734
  }
571
- .pf-button:hover { opacity: 0.9; }
572
- .pf-button:active { opacity: 0.8; }
573
735
  .pf-button:disabled { opacity: 0.5; cursor: not-allowed; }
736
+ .pf-button:active:not(:disabled) { transform: translateY(0.5px); }
574
737
 
575
- .pf-button[data-variant="default"] { background: var(--primary); color: var(--primary-foreground); }
738
+ .pf-button[data-variant="default"] { background: var(--primary); color: var(--primary-foreground); box-shadow: var(--shadow-sm); }
576
739
  .pf-button[data-variant="secondary"] { background: var(--secondary); color: var(--secondary-foreground); }
577
- .pf-button[data-variant="destructive"] { background: var(--destructive); color: var(--destructive-foreground); }
740
+ .pf-button[data-variant="destructive"] { background: var(--destructive); color: var(--destructive-foreground); box-shadow: var(--shadow-sm); }
741
+ .pf-button[data-variant="outline"] { background: var(--background); color: var(--foreground); border-color: var(--input); box-shadow: var(--shadow-sm); }
578
742
  .pf-button[data-variant="ghost"] { background: transparent; color: var(--foreground); }
579
- .pf-button[data-variant="ghost"]:hover { background: var(--accent); }
580
- .pf-button[data-variant="outline"] { background: transparent; color: var(--foreground); border: 1px solid var(--border); }
581
- .pf-button[data-variant="outline"]:hover { background: var(--accent); }
582
- .pf-button[data-variant="link"] { background: transparent; color: var(--primary); text-decoration: underline; padding: 0; }
743
+ .pf-button[data-variant="link"] { height: auto; padding: 0; background: transparent; color: var(--primary); text-underline-offset: 4px; }
583
744
 
584
- .pf-button-group { display: flex; gap: 0.5rem; flex-wrap: wrap; }
745
+ .pf-button[data-variant="default"]:hover:not(:disabled) { background: color-mix(in oklab, var(--primary) 88%, var(--foreground)); }
746
+ .pf-button[data-variant="secondary"]:hover:not(:disabled) { background: color-mix(in oklab, var(--secondary) 80%, var(--foreground)); }
747
+ .pf-button[data-variant="destructive"]:hover:not(:disabled) { background: color-mix(in oklab, var(--destructive) 88%, var(--foreground)); }
748
+ .pf-button[data-variant="outline"]:hover:not(:disabled),
749
+ .pf-button[data-variant="ghost"]:hover:not(:disabled) { background: var(--muted); }
750
+ .pf-button[data-variant="link"]:hover:not(:disabled) { text-decoration: underline; }
585
751
 
586
- /* Checkbox, Switch, Slider, Radio */
587
- .pf-checkbox-wrapper, .pf-switch-wrapper {
588
- display: flex;
589
- align-items: center;
590
- gap: 0.5rem;
591
- cursor: pointer;
592
- }
593
- .pf-checkbox, .pf-switch { accent-color: var(--primary); }
752
+ .pf-button[data-size="sm"] { height: 2rem; padding: 0 0.75rem; font-size: 0.8125rem; gap: 0.375rem; }
753
+ .pf-button[data-size="lg"] { height: 2.75rem; padding: 0 1.5rem; font-size: 0.9375rem; border-radius: var(--radius); }
754
+ .pf-button[data-size="icon"] { width: 2.25rem; padding: 0; }
594
755
 
595
- .pf-slider { width: 100%; accent-color: var(--primary); }
756
+ .pf-button-group { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
596
757
 
597
- .pf-radio {
598
- display: flex;
758
+ .pf-checkbox-wrapper, .pf-switch-wrapper, .pf-radio {
759
+ display: inline-flex;
599
760
  align-items: center;
600
- gap: 0.5rem;
761
+ align-self: flex-start;
762
+ gap: 0.625rem;
763
+ font-size: 0.875rem;
764
+ line-height: 1.25rem;
601
765
  cursor: pointer;
766
+ user-select: none;
602
767
  }
603
- .pf-radio-label { font-size: 0.875rem; }
604
- .pf-radio-group {
605
- border: none;
606
- padding: 0;
768
+ .pf-checkbox, .pf-radio-input {
769
+ flex-shrink: 0;
770
+ width: 1rem;
771
+ height: 1rem;
607
772
  margin: 0;
608
- display: flex;
609
- flex-direction: column;
610
- gap: 0.5rem;
773
+ accent-color: var(--primary);
774
+ cursor: pointer;
611
775
  }
612
776
 
613
- /* Select separator */
614
- .pf-select-group { }
615
- .pf-select-label { font-size: 0.75rem; color: var(--muted-foreground); font-weight: 600; padding: 0.25rem 0; }
777
+ .pf-switch {
778
+ appearance: none;
779
+ position: relative;
780
+ flex-shrink: 0;
781
+ width: 2.25rem;
782
+ height: 1.25rem;
783
+ margin: 0;
784
+ border: 0;
785
+ border-radius: 9999px;
786
+ background: color-mix(in oklab, var(--input) 65%, var(--muted-foreground));
787
+ cursor: pointer;
788
+ transition: background-color 0.2s;
789
+ }
790
+ .pf-switch::before {
791
+ content: "";
792
+ position: absolute;
793
+ top: 0.125rem;
794
+ left: 0.125rem;
795
+ width: 1rem;
796
+ height: 1rem;
797
+ border-radius: 50%;
798
+ background: #fff;
799
+ box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
800
+ transition: transform 0.2s;
801
+ }
802
+ .pf-switch:checked { background: var(--primary); }
803
+ .pf-switch:checked::before { transform: translateX(1rem); }
804
+ .pf-switch:disabled, .pf-checkbox:disabled { opacity: 0.5; cursor: not-allowed; }
616
805
 
617
- /* Field */
618
- .pf-field {
806
+ .pf-radio-group {
619
807
  display: flex;
620
808
  flex-direction: column;
621
- gap: 0.375rem;
809
+ gap: 0.625rem;
810
+ min-width: 0;
811
+ margin: 0;
812
+ padding: 0;
813
+ border: 0;
622
814
  }
623
- .pf-field-title { font-size: 0.875rem; font-weight: 500; }
624
- .pf-field-description { font-size: 0.75rem; color: var(--muted-foreground); }
625
- .pf-field-content { }
626
- .pf-field-error { font-size: 0.75rem; color: var(--destructive); }
627
-
628
- /* Combobox */
629
- .pf-combobox { position: relative; }
630
- .pf-combobox-input {
815
+ .pf-radio-legend {
816
+ float: left;
631
817
  width: 100%;
632
- padding: 0.5rem 0.75rem;
633
- border: 1px solid var(--input);
634
- border-radius: var(--radius-sm);
818
+ margin-bottom: 0.125rem;
819
+ padding: 0;
635
820
  font-size: 0.875rem;
821
+ font-weight: 500;
822
+ line-height: 1.25rem;
823
+ }
824
+ .pf-radio-legend + * { clear: both; }
825
+
826
+ .pf-slider {
827
+ appearance: none;
828
+ width: 100%;
829
+ height: 1.25rem;
830
+ margin: 0;
831
+ background: transparent;
832
+ cursor: pointer;
833
+ }
834
+ .pf-slider::-webkit-slider-runnable-track {
835
+ height: 0.375rem;
836
+ border-radius: 9999px;
837
+ background:
838
+ linear-gradient(var(--primary), var(--primary)) 0 / var(--pf-fill, 50%) 100% no-repeat,
839
+ var(--muted);
840
+ }
841
+ .pf-slider::-moz-range-track { height: 0.375rem; border-radius: 9999px; background: var(--muted); }
842
+ .pf-slider::-moz-range-progress { height: 0.375rem; border-radius: 9999px; background: var(--primary); }
843
+ .pf-slider::-webkit-slider-thumb {
844
+ appearance: none;
845
+ width: 1rem;
846
+ height: 1rem;
847
+ margin-top: -0.3125rem;
848
+ border: 2px solid var(--primary);
849
+ border-radius: 50%;
636
850
  background: var(--background);
637
- color: var(--foreground);
851
+ box-shadow: var(--shadow-sm);
852
+ transition: box-shadow 0.15s;
638
853
  }
639
- .pf-combobox-input:focus {
640
- outline: 2px solid var(--ring);
641
- outline-offset: -1px;
854
+ .pf-slider::-moz-range-thumb {
855
+ width: 0.75rem;
856
+ height: 0.75rem;
857
+ border: 2px solid var(--primary);
858
+ border-radius: 50%;
859
+ background: var(--background);
642
860
  }
861
+ .pf-slider:focus-visible { outline: none; }
862
+ .pf-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px color-mix(in oklab, var(--ring) 30%, transparent); }
863
+ .pf-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px color-mix(in oklab, var(--ring) 30%, transparent); }
864
+
865
+ .pf-field-description { font-size: 0.8125rem; line-height: 1.25rem; color: var(--muted-foreground); }
866
+ .pf-field-content { display: flex; flex-direction: column; gap: 0.5rem; }
867
+ .pf-field-error { margin: 0; font-size: 0.8125rem; line-height: 1.25rem; font-weight: 500; color: var(--destructive); }
868
+
869
+ .pf-combobox { position: relative; }
643
870
  .pf-combobox-dropdown {
644
871
  position: absolute;
645
- top: 100%;
872
+ top: calc(100% + 0.25rem);
646
873
  left: 0;
647
874
  right: 0;
648
875
  z-index: 50;
649
- margin-top: 0.25rem;
876
+ max-height: 15rem;
877
+ overflow-y: auto;
878
+ padding: 0.25rem;
650
879
  background: var(--popover);
651
880
  color: var(--popover-foreground);
652
881
  border: 1px solid var(--border);
653
882
  border-radius: var(--radius-sm);
654
- box-shadow: 0 4px 6px -1px rgba(0,0,0,.1), 0 2px 4px -2px rgba(0,0,0,.1);
655
- max-height: 15rem;
656
- overflow-y: auto;
883
+ box-shadow: var(--shadow-md);
884
+ animation: pf-pop-in 0.12s ease-out;
657
885
  }
658
886
  .pf-combobox-option {
659
- padding: 0.5rem 0.75rem;
660
- cursor: pointer;
887
+ padding: 0.375rem 0.5rem;
888
+ border-radius: calc(var(--radius-sm) - 2px);
661
889
  font-size: 0.875rem;
890
+ cursor: pointer;
662
891
  }
663
- .pf-combobox-option:hover { background: var(--accent); }
664
- .pf-combobox-group { }
665
- .pf-combobox-label { font-size: 0.75rem; color: var(--muted-foreground); font-weight: 600; padding: 0.5rem 0.75rem 0.25rem; }
892
+ .pf-combobox-option:hover, .pf-combobox-option[aria-selected="true"] { background: var(--muted); }
893
+ .pf-combobox-label { font-size: 0.75rem; color: var(--muted-foreground); font-weight: 600; padding: 0.375rem 0.5rem 0.25rem; }
894
+ .pf-combobox-dropdown .pf-separator, .pf-select-wrapper .pf-separator { margin: 0.25rem -0.25rem; width: auto; }
666
895
 
667
- /* Calendar & DatePicker */
668
- .pf-calendar {
669
- border: 1px solid var(--border);
670
- border-radius: var(--radius-sm);
671
- padding: 0.75rem;
672
- font-size: 0.875rem;
673
- }
674
- .pf-datepicker {
896
+ .pf-calendar, .pf-datepicker { display: flex; flex-direction: column; gap: 0.5rem; }
897
+
898
+ .pf-choice-card {
675
899
  display: flex;
676
900
  flex-direction: column;
677
- gap: 0.375rem;
901
+ gap: 0.25rem;
902
+ padding: 1rem;
903
+ border: 1px solid var(--border);
904
+ border-radius: var(--radius);
905
+ background: var(--card);
906
+ cursor: pointer;
907
+ transition: border-color 0.15s, background-color 0.15s, box-shadow 0.15s;
678
908
  }
909
+ .pf-choice-card:hover { border-color: color-mix(in oklab, var(--primary) 40%, var(--border)); }
910
+ .pf-choice-card[data-selected="true"] {
911
+ border-color: var(--primary);
912
+ background: color-mix(in oklab, var(--primary) 6%, var(--card));
913
+ box-shadow: 0 0 0 1px var(--primary);
914
+ }
915
+ .pf-choice-card-label { font-size: 0.875rem; font-weight: 600; line-height: 1.25rem; }
916
+ .pf-choice-card-description { font-size: 0.8125rem; line-height: 1.25rem; color: var(--muted-foreground); }
679
917
 
680
- /* ChoiceCard */
681
- .pf-choice-card {
682
- border: 2px solid var(--border);
918
+ .pf-dropzone {
919
+ display: flex;
920
+ flex-direction: column;
921
+ align-items: center;
922
+ justify-content: center;
923
+ gap: 0.5rem;
924
+ padding: 2rem 1.5rem;
925
+ border: 1.5px dashed var(--input);
683
926
  border-radius: var(--radius);
684
- padding: 1rem;
927
+ text-align: center;
928
+ font-size: 0.875rem;
929
+ color: var(--muted-foreground);
685
930
  cursor: pointer;
686
- transition: border-color 0.15s, background-color 0.15s;
931
+ transition: border-color 0.15s, background-color 0.15s, color 0.15s;
932
+ }
933
+ .pf-dropzone:hover, .pf-dropzone.pf-dropzone--active {
934
+ border-color: var(--primary);
935
+ background: color-mix(in oklab, var(--primary) 5%, transparent);
936
+ color: var(--foreground);
687
937
  }
688
- .pf-choice-card:hover { border-color: var(--ring); }
689
- .pf-choice-card-label { font-weight: 500; }
690
- .pf-choice-card-description { font-size: 0.875rem; color: var(--muted-foreground); margin-top: 0.25rem; }
691
-
692
- /* ═══════════════════════════════════════════════════════════════════════════
693
- 12. TABS
694
- ═══════════════════════════════════════════════════════════════════════════ */
695
938
 
696
- .pf-tabs { }
939
+ .pf-tabs { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
697
940
  .pf-tabs-bar {
698
941
  display: flex;
699
- gap: 0;
942
+ gap: 0.25rem;
943
+ overflow-x: auto;
700
944
  border-bottom: 1px solid var(--border);
701
- margin-bottom: 1rem;
945
+ scrollbar-width: none;
702
946
  }
703
947
  .pf-tab-trigger {
704
- padding: 0.5rem 1rem;
948
+ flex-shrink: 0;
949
+ margin-bottom: -1px;
950
+ padding: 0.5rem 0.875rem;
951
+ border: 0;
952
+ border-bottom: 2px solid transparent;
953
+ background: transparent;
954
+ color: var(--muted-foreground);
705
955
  font-size: 0.875rem;
706
956
  font-weight: 500;
957
+ line-height: 1.25rem;
958
+ white-space: nowrap;
707
959
  cursor: pointer;
708
- background: transparent;
709
- border: none;
710
- border-bottom: 2px solid transparent;
711
- color: var(--muted-foreground);
712
960
  transition: color 0.15s, border-color 0.15s;
713
961
  }
714
962
  .pf-tab-trigger:hover { color: var(--foreground); }
@@ -716,12 +964,8 @@
716
964
  color: var(--foreground);
717
965
  border-bottom-color: var(--primary);
718
966
  }
719
- .pf-tab-panel { }
720
- .pf-tab { }
721
-
722
- /* ═══════════════════════════════════════════════════════════════════════════
723
- 13. ACCORDION
724
- ═══════════════════════════════════════════════════════════════════════════ */
967
+ .pf-tab-trigger:focus-visible { outline-offset: -2px; border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
968
+ .pf-tab-panel:focus-visible { outline-offset: 4px; border-radius: var(--radius-sm); }
725
969
 
726
970
  .pf-accordion { display: flex; flex-direction: column; }
727
971
  .pf-accordion-item { border-bottom: 1px solid var(--border); }
@@ -729,215 +973,286 @@
729
973
  display: flex;
730
974
  align-items: center;
731
975
  justify-content: space-between;
976
+ gap: 1rem;
732
977
  width: 100%;
733
978
  padding: 1rem 0;
979
+ border: 0;
980
+ background: transparent;
734
981
  font-size: 0.875rem;
735
982
  font-weight: 500;
736
- cursor: pointer;
737
- background: transparent;
738
- border: none;
983
+ line-height: 1.25rem;
739
984
  text-align: left;
740
- color: var(--foreground);
985
+ cursor: pointer;
986
+ }
987
+ .pf-accordion-trigger:hover { text-decoration: underline; text-underline-offset: 4px; }
988
+ .pf-accordion-trigger::after {
989
+ content: "";
990
+ flex-shrink: 0;
991
+ width: 0.4375rem;
992
+ height: 0.4375rem;
993
+ margin-right: 0.25rem;
994
+ border-right: 1.5px solid var(--muted-foreground);
995
+ border-bottom: 1.5px solid var(--muted-foreground);
996
+ transform: translateY(-25%) rotate(45deg);
997
+ transition: transform 0.2s;
741
998
  }
742
- .pf-accordion-trigger:hover { text-decoration: underline; }
743
- .pf-accordion-content { padding-bottom: 1rem; }
999
+ .pf-accordion-trigger[aria-expanded="true"]::after { transform: translateY(25%) rotate(-135deg); }
1000
+ .pf-accordion-trigger:focus-visible { outline-offset: -2px; border-radius: var(--radius-sm); }
1001
+ .pf-accordion-content { padding-bottom: 1rem; font-size: 0.875rem; line-height: 1.5rem; }
744
1002
 
745
- /* ═══════════════════════════════════════════════════════════════════════════
746
- 14. DIALOG
747
- ═══════════════════════════════════════════════════════════════════════════ */
1003
+ .pf-carousel { position: relative; overflow: hidden; border-radius: var(--radius); }
1004
+ .pf-carousel-track {
1005
+ display: flex;
1006
+ transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1);
1007
+ }
1008
+ .pf-carousel-track > * { flex: 0 0 100%; min-width: 0; }
1009
+ .pf-carousel-prev,
1010
+ .pf-carousel-next {
1011
+ position: absolute;
1012
+ top: 50%;
1013
+ z-index: 10;
1014
+ display: flex;
1015
+ align-items: center;
1016
+ justify-content: center;
1017
+ width: 2rem;
1018
+ height: 2rem;
1019
+ padding: 0 0 0.125rem;
1020
+ border: 1px solid var(--border);
1021
+ border-radius: 50%;
1022
+ background: color-mix(in oklab, var(--background) 85%, transparent);
1023
+ color: var(--foreground);
1024
+ font-size: 1.25rem;
1025
+ line-height: 1;
1026
+ box-shadow: var(--shadow-sm);
1027
+ backdrop-filter: blur(4px);
1028
+ cursor: pointer;
1029
+ transform: translateY(-50%);
1030
+ transition: opacity 0.15s, background-color 0.15s;
1031
+ }
1032
+ .pf-carousel-prev { left: 0.5rem; }
1033
+ .pf-carousel-next { right: 0.5rem; }
1034
+ .pf-carousel-prev:hover:not(:disabled),
1035
+ .pf-carousel-next:hover:not(:disabled) { background: var(--muted); }
1036
+ .pf-carousel-prev:disabled,
1037
+ .pf-carousel-next:disabled { opacity: 0; pointer-events: none; }
748
1038
 
749
- .pf-dialog-wrapper { }
750
1039
  .pf-dialog {
1040
+ position: fixed;
1041
+ width: calc(100% - 2rem);
1042
+ max-width: 32rem;
1043
+ max-height: calc(100% - 2rem);
1044
+ overflow-y: auto;
1045
+ padding: 1.5rem;
751
1046
  background: var(--card);
752
1047
  color: var(--card-foreground);
753
1048
  border: 1px solid var(--border);
754
- border-radius: var(--radius);
755
- padding: 1.5rem;
756
- max-width: 32rem;
757
- width: 90vw;
1049
+ border-radius: var(--radius-lg);
1050
+ box-shadow: var(--shadow-lg);
1051
+ font-family: var(--font-sans);
1052
+ line-height: 1.5;
758
1053
  }
1054
+ .pf-dialog[open] { animation: pf-dialog-in 0.16s ease-out; }
759
1055
  .pf-dialog::backdrop {
760
- background: rgba(0, 0, 0, 0.5);
1056
+ background: rgb(0 0 0 / 0.55);
1057
+ backdrop-filter: blur(2px);
1058
+ animation: pf-fade-in 0.16s ease-out;
1059
+ }
1060
+ .pf-dialog-title { margin: 0 0 0.375rem; padding-right: 2rem; font-size: 1.125rem; font-weight: 600; line-height: 1.75rem; letter-spacing: -0.01em; }
1061
+ .pf-dialog-desc { margin: 0 0 1.25rem; color: var(--muted-foreground); font-size: 0.875rem; line-height: 1.25rem; }
1062
+ .pf-dialog-body { display: flex; flex-direction: column; gap: 1rem; }
1063
+ .pf-dialog-close {
1064
+ position: absolute;
1065
+ top: 1rem;
1066
+ right: 1rem;
1067
+ display: flex;
1068
+ align-items: center;
1069
+ justify-content: center;
1070
+ width: 1.75rem;
1071
+ height: 1.75rem;
1072
+ padding: 0;
1073
+ border: 0;
1074
+ border-radius: var(--radius-sm);
1075
+ background: transparent;
1076
+ color: var(--muted-foreground);
1077
+ font-size: 1.25rem;
1078
+ line-height: 1;
1079
+ cursor: pointer;
1080
+ transition: color 0.15s, background-color 0.15s;
761
1081
  }
762
- .pf-dialog-title { margin: 0 0 0.5rem; font-size: 1.125rem; font-weight: 600; }
763
- .pf-dialog-desc { margin: 0 0 1rem; color: var(--muted-foreground); font-size: 0.875rem; }
764
- .pf-dialog-body { }
1082
+ .pf-dialog-close:hover { color: var(--foreground); background: var(--muted); }
765
1083
 
766
- /* ═══════════════════════════════════════════════════════════════════════════
767
- 15. POPOVER, TOOLTIP, HOVER CARD
768
- ═══════════════════════════════════════════════════════════════════════════ */
1084
+ .pf-popover, .pf-tooltip, .pf-hover-card { position: relative; display: inline-block; }
769
1085
 
770
- .pf-popover { position: relative; display: inline-block; }
771
- .pf-popover-content {
1086
+ .pf-popover-content, .pf-hover-card-content {
772
1087
  position: absolute;
1088
+ top: calc(100% + 0.5rem);
1089
+ left: 0;
773
1090
  z-index: 50;
774
1091
  min-width: 12rem;
775
- padding: 1rem;
1092
+ max-width: min(20rem, calc(100vw - 2rem));
1093
+ padding: 0.875rem 1rem;
776
1094
  background: var(--popover);
777
1095
  color: var(--popover-foreground);
778
1096
  border: 1px solid var(--border);
779
1097
  border-radius: var(--radius);
780
- box-shadow: 0 4px 6px -1px rgba(0,0,0,.1), 0 2px 4px -2px rgba(0,0,0,.1);
1098
+ box-shadow: var(--shadow-md);
1099
+ font-size: 0.875rem;
1100
+ line-height: 1.25rem;
1101
+ animation: pf-pop-in 0.12s ease-out;
1102
+ }
1103
+ .pf-hover-card-content { min-width: 16rem; }
1104
+ .pf-hover-card-content::before {
1105
+ content: "";
1106
+ position: absolute;
1107
+ left: 0;
1108
+ right: 0;
1109
+ bottom: 100%;
1110
+ height: 0.5rem;
781
1111
  }
782
- .pf-popover-title { font-weight: 600; margin-bottom: 0.5rem; }
1112
+ .pf-popover-title { margin-bottom: 0.375rem; font-weight: 600; }
783
1113
 
784
- .pf-tooltip { position: relative; display: inline-block; }
785
1114
  .pf-tooltip-content {
786
1115
  position: absolute;
787
- z-index: 50;
788
- bottom: 100%;
1116
+ bottom: calc(100% + 0.375rem);
789
1117
  left: 50%;
790
- transform: translateX(-50%);
791
- margin-bottom: 0.5rem;
792
- padding: 0.375rem 0.75rem;
1118
+ z-index: 50;
1119
+ padding: 0.375rem 0.625rem;
793
1120
  background: var(--foreground);
794
1121
  color: var(--background);
795
1122
  border-radius: var(--radius-sm);
796
1123
  font-size: 0.75rem;
1124
+ font-weight: 500;
1125
+ line-height: 1rem;
797
1126
  white-space: nowrap;
798
1127
  pointer-events: none;
1128
+ transform: translateX(-50%);
1129
+ animation: pf-tooltip-in 0.12s ease-out;
799
1130
  }
800
1131
 
801
- .pf-hover-card { position: relative; display: inline-block; }
802
- .pf-hover-card-content {
803
- position: absolute;
804
- z-index: 50;
805
- min-width: 16rem;
806
- padding: 1rem;
807
- background: var(--card);
808
- color: var(--card-foreground);
809
- border: 1px solid var(--border);
810
- border-radius: var(--radius);
811
- box-shadow: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);
812
- }
813
-
814
- /* ═══════════════════════════════════════════════════════════════════════════
815
- 16. CAROUSEL
816
- ═══════════════════════════════════════════════════════════════════════════ */
817
-
818
- .pf-carousel { position: relative; overflow: hidden; }
819
- .pf-carousel-track {
820
- display: flex;
821
- transition: transform 0.3s ease;
822
- }
823
- .pf-carousel-track > * { flex: 0 0 100%; min-width: 0; }
824
-
825
- .pf-carousel-prev,
826
- .pf-carousel-next {
827
- position: absolute;
828
- top: 50%;
829
- transform: translateY(-50%);
830
- z-index: 10;
831
- width: 2rem;
832
- height: 2rem;
833
- display: flex;
834
- align-items: center;
835
- justify-content: center;
836
- border-radius: 50%;
837
- border: 1px solid var(--border);
838
- background: var(--card);
839
- color: var(--foreground);
840
- cursor: pointer;
841
- font-size: 1rem;
842
- }
843
- .pf-carousel-prev { left: 0.5rem; }
844
- .pf-carousel-next { right: 0.5rem; }
845
- .pf-carousel-prev:hover,
846
- .pf-carousel-next:hover { background: var(--accent); }
847
-
848
- /* ═══════════════════════════════════════════════════════════════════════════
849
- 17. CHARTS
850
- ═══════════════════════════════════════════════════════════════════════════ */
1132
+ @keyframes pf-fade-in { from { opacity: 0; } }
1133
+ @keyframes pf-pop-in { from { opacity: 0; transform: translateY(-0.25rem); } }
1134
+ @keyframes pf-tooltip-in { from { opacity: 0; transform: translate(-50%, 0.25rem); } }
1135
+ @keyframes pf-dialog-in { from { opacity: 0; transform: translateY(0.5rem) scale(0.98); } }
851
1136
 
852
- .pf-chart { position: relative; }
853
- .pf-chart svg { display: block; width: 100%; height: auto; }
1137
+ .pf-chart { position: relative; min-width: 0; }
1138
+ .pf-chart svg { display: block; max-width: 100%; height: auto; margin: 0 auto; overflow: visible; }
1139
+ .pf-chart text { font-family: var(--font-sans); font-variant-numeric: tabular-nums; }
854
1140
 
855
1141
  .pf-chart-tooltip {
856
1142
  position: absolute;
857
1143
  pointer-events: none;
858
1144
  z-index: 50;
859
- background: var(--popover, #fff);
860
- color: var(--popover-foreground, #09090b);
861
- border: 1px solid var(--border, #e5e7eb);
862
- border-radius: var(--radius, 0.375rem);
1145
+ background: var(--popover);
1146
+ color: var(--popover-foreground);
1147
+ border: 1px solid var(--border);
1148
+ border-radius: var(--radius-sm);
863
1149
  padding: 0.375rem 0.625rem;
864
1150
  font-size: 0.75rem;
865
1151
  line-height: 1.25rem;
866
- box-shadow: 0 2px 8px rgb(0 0 0 / 0.12);
1152
+ box-shadow: var(--shadow-md);
867
1153
  white-space: nowrap;
868
1154
  opacity: 0;
869
1155
  transition: opacity 0.15s ease;
870
1156
  }
871
1157
  .pf-chart-tooltip.pf-visible { opacity: 1; }
872
- .pf-chart-tooltip-label { font-weight: 500; margin-bottom: 0.125rem; }
873
- .pf-chart-tooltip-row { display: flex; align-items: center; gap: 0.375rem; }
874
- .pf-chart-tooltip-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
1158
+ .pf-chart-tooltip-label { font-weight: 600; margin-bottom: 0.125rem; }
1159
+ .pf-chart-tooltip-row { display: flex; align-items: center; gap: 0.375rem; font-variant-numeric: tabular-nums; }
1160
+ .pf-chart-tooltip-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }
875
1161
 
876
- .pf-chart-legend { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 0.75rem; font-size: 0.75rem; }
1162
+ .pf-chart-legend { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; margin-bottom: 0.75rem; font-size: 0.75rem; color: var(--muted-foreground); }
877
1163
  .pf-chart-legend-item { display: flex; align-items: center; gap: 0.375rem; }
1164
+ .pf-chart-legend-dot { width: 0.5rem; height: 0.5rem; border-radius: 2px; flex-shrink: 0; }
878
1165
 
879
- /* ═══════════════════════════════════════════════════════════════════════════
880
- 18. MEDIA
881
- ═══════════════════════════════════════════════════════════════════════════ */
882
-
883
- .pf-image { max-width: 100%; height: auto; display: block; }
1166
+ .pf-image { max-width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }
884
1167
  .pf-audio { width: 100%; }
885
- .pf-video { max-width: 100%; height: auto; display: block; }
886
- .pf-embed { position: relative; overflow: hidden; }
887
- .pf-embed iframe { border: none; }
1168
+ .pf-video { max-width: 100%; height: auto; display: block; border-radius: var(--radius-sm); }
1169
+ .pf-embed { position: relative; overflow: hidden; border-radius: var(--radius-sm); }
1170
+ .pf-embed iframe { display: block; width: 100%; border: none; }
888
1171
  .pf-svg { display: inline-block; }
889
- .pf-mermaid { overflow-x: auto; }
1172
+ .pf-mermaid { overflow-x: auto; min-width: 0; }
890
1173
 
891
- .pf-dropzone {
892
- border: 2px dashed var(--border);
1174
+ .pf-pdf-viewer {
1175
+ display: flex;
1176
+ flex-direction: column;
1177
+ overflow: hidden;
1178
+ border: 1px solid var(--border);
893
1179
  border-radius: var(--radius);
894
- padding: 2rem;
1180
+ background: var(--muted);
1181
+ }
1182
+ .pf-pdf-message {
1183
+ display: flex;
1184
+ flex: 1;
1185
+ align-items: center;
1186
+ justify-content: center;
1187
+ padding: 1rem;
895
1188
  text-align: center;
1189
+ font-size: 0.875rem;
896
1190
  color: var(--muted-foreground);
897
- cursor: pointer;
898
- transition: border-color 0.15s;
899
1191
  }
900
- .pf-dropzone:hover, .pf-dropzone.pf-dropzone--active {
901
- border-color: var(--primary);
902
- }
903
-
904
- /* ═══════════════════════════════════════════════════════════════════════════
905
- 19. TOAST
906
- ═══════════════════════════════════════════════════════════════════════════ */
907
-
908
- .pf-toast {
1192
+ .pf-pdf-message[data-state="error"] { color: var(--destructive); }
1193
+ .pf-pdf-toolbar {
1194
+ display: flex;
1195
+ flex-shrink: 0;
1196
+ align-items: center;
1197
+ gap: 0.375rem;
1198
+ padding: 0.375rem 0.5rem;
1199
+ border-bottom: 1px solid var(--border);
909
1200
  background: var(--card);
910
- color: var(--card-foreground);
911
- border: 1px solid var(--border);
912
- border-radius: var(--radius);
913
- padding: 1rem;
914
- box-shadow: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -4px rgba(0,0,0,.1);
915
- max-width: 24rem;
916
- }
917
- .pf-toast--success {
918
- border-color: var(--success, #22c55e);
919
- background: color-mix(in srgb, var(--success, #22c55e) 10%, var(--card));
1201
+ font-size: 0.8125rem;
1202
+ font-variant-numeric: tabular-nums;
920
1203
  }
921
- .pf-toast--error {
922
- border-color: var(--destructive);
923
- background: color-mix(in srgb, var(--destructive) 10%, var(--card));
1204
+ .pf-pdf-spacer { flex: 1; }
1205
+ .pf-pdf-btn {
1206
+ display: inline-flex;
1207
+ align-items: center;
1208
+ justify-content: center;
1209
+ width: 1.75rem;
1210
+ height: 1.75rem;
1211
+ padding: 0;
1212
+ border: 1px solid transparent;
1213
+ border-radius: var(--radius-sm);
1214
+ background: transparent;
1215
+ color: var(--foreground);
1216
+ font: inherit;
1217
+ font-size: 1rem;
1218
+ line-height: 1;
1219
+ cursor: pointer;
1220
+ transition: background-color 0.15s;
924
1221
  }
925
- .pf-toast--warning {
926
- border-color: var(--warning, #f59e0b);
927
- background: color-mix(in srgb, var(--warning, #f59e0b) 10%, var(--card));
1222
+ .pf-pdf-btn:hover:not(:disabled) { background: var(--muted); }
1223
+ .pf-pdf-btn:disabled { opacity: 0.4; cursor: not-allowed; }
1224
+ .pf-pdf-btn[aria-pressed="true"] { background: var(--muted); }
1225
+ .pf-pdf-page-input {
1226
+ width: 2.75rem;
1227
+ height: 1.75rem;
1228
+ padding: 0 0.25rem;
1229
+ border: 1px solid var(--input);
1230
+ border-radius: var(--radius-sm);
1231
+ background: var(--background);
1232
+ color: var(--foreground);
1233
+ font: inherit;
1234
+ text-align: center;
928
1235
  }
929
- .pf-toast--info {
930
- border-color: var(--primary);
931
- background: color-mix(in srgb, var(--primary) 10%, var(--card));
1236
+ .pf-pdf-page-input:focus-visible { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in oklab, var(--ring) 25%, transparent); }
1237
+ .pf-pdf-page-count, .pf-pdf-zoom-label { color: var(--muted-foreground); }
1238
+ .pf-pdf-zoom-label { min-width: 3rem; text-align: center; }
1239
+ .pf-pdf-canvas-container { flex: 1; min-height: 0; overflow: auto; padding: 1rem; }
1240
+ .pf-pdf-canvas { display: block; margin: 0 auto; background: #fff; box-shadow: var(--shadow-md); }
1241
+ .pf-mermaid-source {
1242
+ margin: 0;
1243
+ padding: 0.875rem 1rem;
1244
+ border: 1px dashed var(--border);
1245
+ border-radius: var(--radius-sm);
1246
+ font-family: var(--font-mono);
1247
+ font-size: 0.8125rem;
1248
+ color: var(--muted-foreground);
1249
+ white-space: pre;
1250
+ overflow-x: auto;
932
1251
  }
1252
+ .pf-mermaid[data-state="rendered"] { display: flex; justify-content: center; }
1253
+ .pf-mermaid svg { max-width: 100%; height: auto; }
933
1254
 
934
- /* ═══════════════════════════════════════════════════════════════════════════
935
- 20. UTILITY — Tailwind-compatible helpers for cssClass
936
- ═══════════════════════════════════════════════════════════════════════════
937
- All classes used by auto-renderers and builders are defined here so the
938
- bundle works without Tailwind. The scale mirrors Tailwind's default
939
- spacing (1 unit = 0.25rem) and typography tokens.
940
- ═══════════════════════════════════════════════════════════════════════════ */
1255
+ /* Tailwind-compatible helpers for cssClass, so the bundle works without Tailwind. */
941
1256
 
942
1257
  /* ── Display ──────────────────────────────────────────────────────────────── */
943
1258