@timbal-ai/timbal-react 1.2.0 → 1.4.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.
@@ -15,14 +15,14 @@ import {
15
15
  studioIntegrationCardClass,
16
16
  studioTopbarPillHeightClass,
17
17
  toNum
18
- } from "./chunk-UY7AKWJL.esm.js";
18
+ } from "./chunk-GQBYZRD7.esm.js";
19
19
  import {
20
20
  Checkbox,
21
21
  Skeleton
22
- } from "./chunk-FEYZUVBM.esm.js";
22
+ } from "./chunk-UCGVL7ZY.esm.js";
23
23
  import {
24
24
  PillSegmentedTabs
25
- } from "./chunk-NAMKO2MU.esm.js";
25
+ } from "./chunk-VXMM2HX7.esm.js";
26
26
  import {
27
27
  Button,
28
28
  Dialog,
@@ -35,7 +35,7 @@ import {
35
35
  TimbalV2Button,
36
36
  cn,
37
37
  controlClass
38
- } from "./chunk-BMXFXLVV.esm.js";
38
+ } from "./chunk-QU7ET55D.esm.js";
39
39
 
40
40
  // src/design/ui-vocabulary.ts
41
41
  var SEMANTIC_COLOR_TOKENS = [
@@ -239,6 +239,40 @@ You are **not** required to copy any example layout, page title, section order,
239
239
 
240
240
  When in doubt: compose from the **component menu** + **guidelines**, then adapt creatively to the request.
241
241
 
242
+ ### Layout archetypes \u2014 pick the shape that fits (don't default to one)
243
+
244
+ The most common failure is shipping the **same** layout every time: sidebar + topbar + \`Page\` + one \`MetricRow\` + one full-width \`DataTable\`. That is *one* archetype, not *the* layout. Choose deliberately \u2014 different domains want different shapes, and varying the shell/page composition is encouraged.
245
+
246
+ | Archetype | When | Compose |
247
+ |-----------|------|---------|
248
+ | **Sidebar dashboard** | Multi-section product (CRM, billing, ops) with nav | \`StudioSidebar\` in \`AppShell.sidebar\` + \`Page\` \u2192 \`Section\` |
249
+ | **Focused / no-chrome** | A single tool or one-screen utility | \`AppShell\` (no sidebar) + \`Page\` (optionally just \`AppShellTopbar\`); or a centered narrow column |
250
+ | **Bento overview** | Home / at-a-glance dashboards | \`Page\` + an **asymmetric grid** of \`SurfaceCard\` / \`ChartPanel\` / \`StatTile\` spanning different widths (not a uniform row + table) |
251
+ | **Split master\u2013detail** | Inbox, triage queue, record browser, log explorer | \`AppShell contentFill\` + \`Page fill\` + a two-column flex row, each pane \`min-h-0 overflow-y-auto\` |
252
+ | **Full-page chat / canvas** | Chat-first app, editor, map, single full-bleed surface | \`AppShell contentFill\` + headerless \`Page fill\` + a \`min-h-0 flex-1\` child (e.g. \`TimbalChat\`) |
253
+ | **Copilot overlay** | A data app that also wants an assistant | any of the above + \`AppShell chat={<AppChatPanel />}\` (floating, never a second column) |
254
+ | **Section-switcher** | One page, several views | \`SubNav\` / \`PillSegmentedTabs\` (\`trackVariant="flush"\`) switching panels with state/router |
255
+
256
+ Mix them: vary the grid columns, density, header placement (\`Page\` actions vs. a global \`AppShellTopbar\`), and whether there's a sidebar at all. Two dashboards for two domains should not look identical.
257
+
258
+ ### Full-height pages (chat, canvas, split views)
259
+
260
+ The content region is a **padded scroll area** by default \u2014 great for stacked \`Page\` \u2192 \`Section\` content, wrong for a surface that must fill the viewport. For full-bleed pages:
261
+
262
+ - Pass **\`contentFill\`** to \`AppShell\` \u2192 the content region becomes a bounded, non-scrolling flex column (clipped, no bottom padding).
263
+ - Pass **\`fill\`** to \`Page\` \u2192 the page becomes a \`min-h-0 flex-1\` flex column.
264
+ - Give the filling child **\`min-h-0 flex-1\`** (or \`h-full\`) so its own scroll/footer resolves \u2014 e.g. \`<TimbalChat className="min-h-0 flex-1" />\`, or a two-pane row where each pane is \`min-h-0 overflow-y-auto\`.
265
+
266
+ \`\`\`tsx
267
+ <AppShell contentFill topbar={<AppShellTopbar actions={<ModeToggle />} />}>
268
+ <Page fill> {/* headerless: omit title */}
269
+ <TimbalChat workforceId="\u2026" className="min-h-0 flex-1" />
270
+ </Page>
271
+ </AppShell>
272
+ \`\`\`
273
+
274
+ **Don't** size full-height content with \`h-[calc(100dvh-\u2026)]\` (guesses chrome height \u2192 spurious scrollbar) or \`min-h-[\u2026]\` (free-growing floor \u2192 a pinned footer like the chat composer rides down on scroll). Let \`contentFill\` + \`fill\` provide the bounded height. \`Page\` with no \`title\` renders **no header** \u2014 you don't need to abandon \`Page\` to drop a heading.
275
+
242
276
  ### Module layout (source folders)
243
277
 
244
278
  Presentational groups \u2014 import from the package root, not from these paths:
@@ -254,7 +288,7 @@ Presentational groups \u2014 import from the package root, not from these paths:
254
288
 
255
289
  Also re-exported: \`Button\`, \`TimbalChat\`, \`ChartArtifactView\`, \`APP_KIT_AGENT_INSTRUCTIONS\`.
256
290
 
257
- Theming helpers (import from the package root or \`/app\`): \`createTimbalTheme\`, \`themeToCss\`, \`applyTimbalTheme\`, \`TIMBAL_THEME_PRESETS\`, \`applyThemePreset\`, \`ThemePresetGallery\`, \`TimbalThemeStyle\`, \`THEME_AGENT_INSTRUCTIONS\`.
291
+ Theming helpers (import from the package root or \`/app\`): \`createTimbalTheme\`, \`themeToCss\`, \`applyTimbalTheme\`, \`TIMBAL_THEME_PRESETS\`, \`applyThemePreset\`, \`TimbalThemeStyle\`, \`THEME_AGENT_INSTRUCTIONS\`. Theming is **configured by the developer**, not surfaced as an end-user theme picker.
258
292
 
259
293
  ### Design guidelines (required)
260
294
 
@@ -263,8 +297,9 @@ Theming helpers (import from the package root or \`/app\`): \`createTimbalTheme\
263
297
  | **Copilot** | Use \`AppCopilotProvider\` for page context (\`useAppCopilotContext\`). Copilot is a **floating overlay** via \`AppShell\` \`chat={<AppChatPanel />}\` \u2014 not a sidebar column that shrinks main content. |
264
298
  | **Chat panel** | \`AppChatPanel\` only; \`Thread\` uses \`variant="panel"\` internally. Dismiss with **X**; trigger is a **text-only** pill (e.g. "Assistant") \u2014 **no** MessageSquare or chat icons on the shell trigger. |
265
299
  | **Context** | Do not show raw JSON context in the panel header; keep context in \`AppCopilotProvider\` only. |
266
- | **Theming** | Use semantic Tailwind tokens (\`bg-background\`, \`text-foreground\`, \`border-border\`, \`bg-elevated-from\`, etc.) from the host app's \`styles.css\`. To rebrand, **never hand-author OKLCH** \u2014 call \`createTimbalTheme({ brand })\` + \`themeToCss\`/\`applyTimbalTheme\`, or apply a catalog preset (\`TIMBAL_THEME_PRESETS\` / \`applyThemePreset\`). To offer styles, render \`ThemePresetGallery\`. See \`THEME_AGENT_INSTRUCTIONS\`. |
267
- | **Layout chrome** | \`Page\` \u2192 \`Section\` for main content hierarchy. \`AppShellTopbar\` for global actions (auth, theme). |
300
+ | **Theming** | Use semantic Tailwind tokens (\`bg-background\`, \`text-foreground\`, \`border-border\`, \`bg-elevated-from\`, etc.) from the host app's \`styles.css\`. To rebrand, **never hand-author OKLCH** \u2014 call \`createTimbalTheme({ brand })\` + \`themeToCss\`/\`applyTimbalTheme\`, or apply a catalog preset (\`TIMBAL_THEME_PRESETS\` / \`applyThemePreset\`). Apply the theme **programmatically** \u2014 do **not** add an end-user theme selector to generated apps. See \`THEME_AGENT_INSTRUCTIONS\`. |
301
+ | **Layout chrome** | \`Page\` \u2192 \`Section\` for main content hierarchy. Default to **no global topbar** \u2014 put account/theme/global actions in the \`Page\` \`actions\` slot (or the sidebar). Add \`AppShellTopbar\` only when a full-width global bar is explicitly requested. |
302
+ | **Density** | Set \`density="compact"\` on \`Page\` for tighter dashboards (full-width column, smaller section gaps, card padding, metric tiles, default chart height 220). Default is \`"default"\` (platform spacing). Wrap custom layouts with \`AppDensityProvider\` when not using \`Page\`. Per-section override: \`Section density="compact"\`. Do **not** hand-tune five layers of \`className\` padding when density covers the need. |
268
303
  | **Data** | Prefer \`DataTable\` with typed \`columns\` / \`rows\` / \`getRowKey\`; use \`ChartPanel\` with a \`ChartArtifact\` for charts (set \`chartType\` + options \u2014 see the chart catalog). Chart colors come from the theme \`--chart-1..6\` tokens; pass \`series[].color\` / \`colors\` only to override, never raw hex on every series. |
269
304
  | **Modals** | Use \`AppConfirmDialog\` for destructive/export confirmations. |
270
305
  | **Metrics** | Overview KPIs \u2192 \`MetricRow\` or \`MetricChartCard\` (not four separate heavy cards). Values use **normal** font weight, not bold. |
@@ -296,13 +331,13 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
296
331
 
297
332
  | Component | Use for |
298
333
  |-----------|---------|
299
- | \`AppShell\` | Shell: optional \`sidebar\`, \`topbar\`, main \`children\`, optional floating \`chat\`. Props: \`chatTriggerLabel\`, \`chatCollapsible\`, \`chatWidth\`, \`chatHeight\`, controlled \`chatOpen\`. |
334
+ | \`AppShell\` | Shell: optional \`sidebar\`, \`topbar\`, main \`children\`, optional floating \`chat\`. Props: \`chatTriggerLabel\`, \`chatCollapsible\`, \`chatWidth\`, \`chatHeight\`, controlled \`chatOpen\`, **\`contentFill\`** (bounded non-scrolling content region for full-bleed pages \u2014 chat/canvas/split view). |
300
335
  | \`AppShellTopbar\` | Full-width top bar: \`start\`, \`actions\` slots. |
301
336
  | \`AppCopilotProvider\` | React context for copilot-aware tools (page, filters, selection, etc.). |
302
337
  | \`AppChatPanel\` | Floating thread: \`workforceId\`, \`welcome\`, \`debug\`. |
303
338
  | \`useAppShellChat\` | Custom open/close trigger when \`hideChatTrigger\` on shell. |
304
- | \`Page\` | Page title, description, \`breadcrumbs\`, \`actions\`, children. |
305
- | \`Section\` | Titled block inside a page. |
339
+ | \`Page\` | Page title, description, \`breadcrumbs\`, \`actions\`, \`density\` (\`"default"\` | \`"compact"\`), children. **\`title\` is optional** \u2014 omit it for a headerless page (no \`<h1>\`). **\`fill\`** makes it a \`min-h-0 flex-1\` column for full-height content (pair with \`AppShell contentFill\`). |
340
+ | \`Section\` | Titled block inside a page. Optional \`density\` overrides inherited page density. |
306
341
  | \`SubNav\` | **Section switcher** (Overview / Reports pill bar): \`items\`, \`activeId\`, \`onChange\`. Never use Radix/shadcn \`Tabs\` \u2014 it is not in this package. Switch panels with state or the router. |
307
342
  | **Menus** | **Select** = short list, no search. **Combobox** = searchable (same trigger as Select). **Command** only inside \`PopoverContent variant="list"\` or Combobox \u2014 never padded default Popover. See \`examples/app-kit/src/recipes/primitives-catalog.ts\`. |
308
343
  | \`Breadcrumbs\` | Trail: \`items: [{ label, href? }]\`. |
@@ -314,7 +349,7 @@ The cause of slop is dropping **below** the curated block layer into raw primiti
314
349
  | \`SearchInput\` | Filter field with consistent app styling. |
315
350
  | \`DataTable\` | Sortable table: \`columns\`, \`rows\`, \`getRowKey\`, optional \`sort\` / \`onSortChange\`, \`emptyTitle\`, \`showRowCount\`, \`caption\`, \`truncate: true\` on columns with long text. **Scales:** \`pageSize\` (built-in client pager), \`selectable\` + \`onSelectionChange\` (checkbox column for bulk actions), \`loading\` (skeleton rows). \`onRowClick\` for row \u2192 detail (open a \`Sheet\`). |
316
351
  | \`Avatar\` / \`AvatarFallback\` | User initials: \`variant="secondary"\` (or \`primary\` / \`chart\` alias) on **both** \`Avatar\` and \`AvatarFallback\` \u2014 same chrome as catalog **Action** buttons (\`Button variant="secondary"\`: elevated gradient, \`border-border\`, \`shadow-card\`, \`text-foreground\`). Never dark primary CTA fill or raw \`bg-blue-600\`. |
317
- | \`ChartPanel\` | Same shell as \`MetricChartCard\`: title row (\`px-4 pt-4\`), flush plot (\`pt-2\` only) with **no axis ticks** \u2014 hover tooltips show category + value. Pass \`title\` + \`artifact\` (omit \`artifact.title\` to avoid duplicates) or \`children\`. \`loading\` renders a plot-height skeleton. |
352
+ | \`ChartPanel\` | Same shell as \`MetricChartCard\`: title row (\`px-4 pt-4\`), flush plot (\`pt-2\` only) with **no axis ticks** \u2014 hover tooltips show category + value. Pass \`title\` + \`artifact\` (omit \`artifact.title\` to avoid duplicates) or \`children\`. \`loading\` renders a plot-height skeleton. Default plot height follows page \`density\` (300 default, 220 compact); pass \`height\` to override. |
318
353
  | \`FieldInput\`, \`FieldTextarea\`, \`FieldSelect\`, \`FieldSwitch\` | Settings-style forms with labels and hints. |
319
354
  | \`FormSection\` | Grouped form block. |
320
355
  | \`AppConfirmDialog\` | Confirm/cancel modal: \`open\`, \`onOpenChange\`, \`title\`, \`description\`, \`onConfirm\`. |
@@ -334,7 +369,7 @@ Charts run on **recharts** with shadcn \`ChartContainer\` / \`ChartTooltipConten
334
369
  | \`Sparkline\` | Tiny inline trend (table cells): \`data\`, \`color\`, \`area\`. |
335
370
  | \`MetricTile\` | Low-level KPI cell \u2014 prefer \`MetricRow\` / \`MetricChartCard\` instead of hand-wiring tiles. |
336
371
  | \`MetricRow\` | KPI strip in one elevated card (no chart). Props: \`metrics: [{ id, label, value, unit?, trend?, trendTone? }]\`, optional \`onMetricChange\`, \`metricsAriaLabel\`, \`loading\` (skeleton tiles). |
337
- | \`MetricChartCard\` | KPI strip + flush chart; tile click swaps series. Same metrics shape + \`data\` per metric. Default chart height 300. \`loading\` renders skeleton tiles + chart. |
372
+ | \`MetricChartCard\` | KPI strip + flush chart; tile click swaps series. Same metrics shape + \`data\` per metric. Default chart height follows page \`density\` (300 / 220); pass \`height\` to override. \`loading\` renders skeleton tiles + chart. |
338
373
 
339
374
  #### Settings
340
375
 
@@ -394,10 +429,13 @@ Ready-made **section patterns** assembled from the components above. Each is a c
394
429
  - **Empty states** \u2014 no-data / no-results / first-run. Compose \`EmptyState\` + \`Card\` + \`Button\`.
395
430
  - **Sign-in card** \u2014 centered auth entry. Compose \`Card\` + \`Input\` + \`Label\` + \`Button\`.
396
431
 
397
- **Shells & theming**
432
+ **Shells & layouts**
398
433
  - **Minimal shell** \u2014 \`AppShell\` + \`Page\` (no sidebar/chat).
434
+ - **Bento dashboard** \u2014 \`Page\` + an asymmetric grid of \`SurfaceCard\` / \`ChartPanel\` / \`StatTile\` (varied spans) for overview/home screens.
435
+ - **Split view** \u2014 master\u2013detail: \`AppShell contentFill\` + \`Page fill\` + a two-pane flex row (list + detail), each pane \`min-h-0 overflow-y-auto\`.
436
+ - **Full-page chat** \u2014 \`AppShell contentFill\` + headerless \`Page fill\` + \`TimbalChat className="min-h-0 flex-1"\` (composer pinned; no \`h-[calc(...)]\`).
399
437
  - **Copilot overlay** \u2014 \`AppShell\` + floating \`AppChatPanel\`.
400
- - **Theme presets** \u2014 \`ThemePresetGallery\` + \`applyTimbalTheme\` (never hand-author OKLCH).
438
+ - **Theme presets** \u2014 apply a brand preset programmatically (\`applyThemePreset\` / \`applyTimbalTheme\`); never hand-author OKLCH and don't expose a theme picker to end users.
401
439
 
402
440
  ### Typical compositions
403
441
 
@@ -1282,8 +1320,7 @@ Each preset is a **full personality** (color + radius + shadows + font), not jus
1282
1320
  | \`folio\` | Editorial serif (Fraunces), near-sharp corners \u2014 content / docs |
1283
1321
  | \`carbon\` | Terminal monospace (JetBrains Mono), green accent \u2014 dev / infra |
1284
1322
 
1285
- - To present options visually, render \`<ThemePresetGallery value={id} onSelect={setId} />\` \u2014 each swatch previews real components (Button + metric tile) scoped via \`data-timbal-theme\`, so the live app doesn't change until the user picks.
1286
- - On selection, call \`applyThemePreset(id)\` (persists to \`localStorage\` and restores on reload).
1323
+ - Pick a preset at build/config time and apply it with \`applyThemePreset(id)\` (persists to \`localStorage\` and restores on reload). Theme selection is a **developer/config** choice \u2014 do **not** surface an end-user theme picker in generated apps.
1287
1324
 
1288
1325
  ### Rules
1289
1326
 
@@ -1317,17 +1354,142 @@ var TimbalThemeStyle = ({
1317
1354
  ] });
1318
1355
  };
1319
1356
 
1357
+ // src/design/app-classes.ts
1358
+ var appPageColumnClass = "mx-auto w-full max-w-[100rem] px-4 md:px-6 lg:px-8";
1359
+ var appShellTopbarInsetClass = "w-full px-4 md:px-6";
1360
+ var appShellInsetTopClass = "pt-4 md:pt-6";
1361
+ var appShellInsetBottomClass = "pb-8 md:pb-10";
1362
+ var appShellTopbarRowClass = cn(
1363
+ studioTopbarPillHeightClass,
1364
+ "flex w-full items-center justify-between gap-2"
1365
+ );
1366
+ var appShellTopbarStickyClass = cn(
1367
+ "shrink-0 bg-background pb-2",
1368
+ appShellInsetTopClass
1369
+ );
1370
+ var appPageHeaderClass = cn(
1371
+ "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
1372
+ "pb-4 pt-2"
1373
+ );
1374
+ var appSectionClass = "flex flex-col gap-4 py-4";
1375
+ var appSectionTitleClass = "text-lg font-semibold text-foreground";
1376
+ var appSectionDescriptionClass = "text-sm text-muted-foreground";
1377
+ var appSurfaceCardClass = cn(
1378
+ studioIntegrationCardClass,
1379
+ "p-4 md:p-5"
1380
+ );
1381
+ var appStatTileClass = cn(
1382
+ appSurfaceCardClass,
1383
+ "flex flex-col gap-1 px-4 py-3 shadow-none"
1384
+ );
1385
+ var appStatValueClass = "text-2xl font-normal tracking-tight text-foreground tabular-nums";
1386
+ var appStatLabelClass = "text-xs font-normal text-muted-foreground";
1387
+ var appFilterBarClass = "flex flex-wrap items-end gap-2";
1388
+ var appSearchInputClass = controlClass({}, "inline-flex items-center gap-2");
1389
+ var appBreadcrumbsClass = "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground";
1390
+ var appBreadcrumbLinkClass = "transition-colors hover:text-foreground";
1391
+ var appFieldClass = "flex flex-col gap-1.5";
1392
+ var appFieldLabelClass = "text-sm font-medium text-foreground";
1393
+ var appFieldHintClass = "text-xs text-muted-foreground";
1394
+ var appInputClass = controlClass({}, "w-full");
1395
+ var appEmptyStateClass = cn(
1396
+ appSurfaceCardClass,
1397
+ "flex flex-col items-center justify-center gap-2 py-12 text-center"
1398
+ );
1399
+ var appEmptyStateTitleClass = "text-base font-medium text-foreground";
1400
+ var appEmptyStateDescriptionClass = "max-w-sm text-sm text-muted-foreground";
1401
+ var appChartPanelClass = cn(appSurfaceCardClass, "flex flex-col gap-3");
1402
+
1403
+ // src/design/app-density.ts
1404
+ var APP_DENSITY_CHART_HEIGHT = {
1405
+ default: 300,
1406
+ compact: 220
1407
+ };
1408
+ var compactSurfaceCardClass = cn(studioIntegrationCardClass, "p-3");
1409
+ var compactStatTileClass = cn(
1410
+ compactSurfaceCardClass,
1411
+ "flex flex-col gap-1 px-3 py-2 shadow-none"
1412
+ );
1413
+ var compactEmptyStateClass = cn(
1414
+ compactSurfaceCardClass,
1415
+ "flex flex-col items-center justify-center gap-2 py-8 text-center"
1416
+ );
1417
+ var APP_DENSITY_CLASSES = {
1418
+ pageColumn: {
1419
+ default: appPageColumnClass,
1420
+ compact: "mx-auto w-full max-w-none px-3 md:px-4"
1421
+ },
1422
+ pageHeader: {
1423
+ default: appPageHeaderClass,
1424
+ compact: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between pb-2 pt-1"
1425
+ },
1426
+ section: {
1427
+ default: appSectionClass,
1428
+ compact: "flex flex-col gap-2 py-2"
1429
+ },
1430
+ surfaceCard: {
1431
+ default: appSurfaceCardClass,
1432
+ compact: compactSurfaceCardClass
1433
+ },
1434
+ statTile: {
1435
+ default: appStatTileClass,
1436
+ compact: compactStatTileClass
1437
+ },
1438
+ emptyState: {
1439
+ default: appEmptyStateClass,
1440
+ compact: compactEmptyStateClass
1441
+ },
1442
+ metricCardHeader: {
1443
+ default: "flex items-start justify-between gap-3 px-4 pb-1 pt-3",
1444
+ compact: "flex items-start justify-between gap-2 px-3 pb-0.5 pt-2"
1445
+ },
1446
+ metricTile: {
1447
+ default: "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal",
1448
+ compact: "relative flex min-w-0 flex-1 flex-col gap-1 px-3 py-2 text-left font-normal"
1449
+ },
1450
+ metricChartRegion: {
1451
+ default: "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 pt-2",
1452
+ compact: "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 pt-1"
1453
+ },
1454
+ metricChartPlotRegion: {
1455
+ default: "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 px-0 pt-5 pb-3",
1456
+ compact: "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 px-0 pt-3 pb-2"
1457
+ },
1458
+ chartPanelBody: {
1459
+ default: "pt-2 pb-3",
1460
+ compact: "pt-1 pb-2"
1461
+ }
1462
+ };
1463
+ function appDensityClass(key, density = "default") {
1464
+ return APP_DENSITY_CLASSES[key][density];
1465
+ }
1466
+
1467
+ // src/app/layout/app-density-context.tsx
1468
+ import { createContext, useContext } from "react";
1469
+ import { jsx as jsx2 } from "react/jsx-runtime";
1470
+ var AppDensityContext = createContext("default");
1471
+ var AppDensityProvider = ({
1472
+ density = "default",
1473
+ children
1474
+ }) => {
1475
+ return /* @__PURE__ */ jsx2(AppDensityContext.Provider, { value: density, children });
1476
+ };
1477
+ function useAppDensity() {
1478
+ return useContext(AppDensityContext);
1479
+ }
1480
+ function useAppDensityClass(key, override) {
1481
+ const inherited = useAppDensity();
1482
+ return appDensityClass(key, override ?? inherited);
1483
+ }
1484
+
1320
1485
  // src/app/data/metrics-shared.tsx
1321
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1486
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1322
1487
  var metricCardShellClass = cn(
1323
1488
  studioIntegrationCardClass,
1324
1489
  "aui-app-metric-card shadow-none",
1325
1490
  "flex flex-col overflow-hidden"
1326
1491
  );
1327
- var metricCardHeaderClass = "flex items-start justify-between gap-3 px-4 pb-1 pt-3";
1328
1492
  var metricTilesRowClass = "grid w-full min-w-0";
1329
- var metricChartRegionClass = "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 pt-2";
1330
- var metricChartPlotRegionClass = "relative min-h-0 w-full overflow-x-hidden border-t border-border/40 px-0 pt-5 pb-3";
1331
1493
  var metricCellDividerClass = "border-r border-border/40";
1332
1494
  var MetricCardHeader = ({
1333
1495
  title,
@@ -1335,13 +1497,14 @@ var MetricCardHeader = ({
1335
1497
  description,
1336
1498
  actions
1337
1499
  }) => {
1500
+ const headerClass = useAppDensityClass("metricCardHeader");
1338
1501
  if (!title && !description && !actions) return null;
1339
- return /* @__PURE__ */ jsxs2("header", { className: metricCardHeaderClass, children: [
1502
+ return /* @__PURE__ */ jsxs2("header", { className: headerClass, children: [
1340
1503
  /* @__PURE__ */ jsxs2("div", { className: "min-w-0", children: [
1341
- title ? /* @__PURE__ */ jsx2("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
1342
- description ? /* @__PURE__ */ jsx2("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
1504
+ title ? /* @__PURE__ */ jsx3("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }) : null,
1505
+ description ? /* @__PURE__ */ jsx3("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
1343
1506
  ] }),
1344
- actions ? /* @__PURE__ */ jsx2("div", { className: "shrink-0", children: actions }) : null
1507
+ actions ? /* @__PURE__ */ jsx3("div", { className: "shrink-0", children: actions }) : null
1345
1508
  ] });
1346
1509
  };
1347
1510
  function metricTilesGridColsClass(n) {
@@ -1362,15 +1525,13 @@ function metricTilesGridColsClass(n) {
1362
1525
  }
1363
1526
 
1364
1527
  // src/app/data/MetricTile.tsx
1365
- import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1528
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1366
1529
  var trendToneClass = {
1367
1530
  up: "border-border/80 bg-muted/40 text-muted-foreground",
1368
1531
  down: "border-border/80 bg-muted/40 text-muted-foreground",
1369
1532
  neutral: "border-border/80 bg-muted/30 text-muted-foreground"
1370
1533
  };
1371
- var metricTileBaseClass = "relative flex min-w-0 flex-1 flex-col gap-1 px-4 py-3 text-left font-normal";
1372
- var metricTileInteractiveClass = cn(
1373
- metricTileBaseClass,
1534
+ var metricTileInteractiveExtraClass = cn(
1374
1535
  "bg-transparent hover:bg-transparent active:bg-transparent",
1375
1536
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10"
1376
1537
  );
@@ -1386,21 +1547,22 @@ var MetricTile = ({
1386
1547
  ariaLabel,
1387
1548
  className
1388
1549
  }) => {
1550
+ const metricTileBaseClass = useAppDensityClass("metricTile");
1389
1551
  const content = /* @__PURE__ */ jsxs3(Fragment2, { children: [
1390
- active ? /* @__PURE__ */ jsx3(
1552
+ active ? /* @__PURE__ */ jsx4(
1391
1553
  "span",
1392
1554
  {
1393
1555
  "aria-hidden": true,
1394
1556
  className: "absolute inset-x-0 bottom-0 h-0.5 bg-foreground dark:bg-white"
1395
1557
  }
1396
1558
  ) : null,
1397
- /* @__PURE__ */ jsx3("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
1559
+ /* @__PURE__ */ jsx4("span", { className: "text-xs font-normal text-muted-foreground", children: label }),
1398
1560
  /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-2", children: [
1399
1561
  /* @__PURE__ */ jsxs3("span", { className: "flex items-baseline gap-1", children: [
1400
- /* @__PURE__ */ jsx3("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
1401
- unit ? /* @__PURE__ */ jsx3("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
1562
+ /* @__PURE__ */ jsx4("span", { className: "text-2xl font-normal tracking-tight text-foreground tabular-nums", children: value }),
1563
+ unit ? /* @__PURE__ */ jsx4("span", { className: "text-xs font-normal text-muted-foreground", children: unit }) : null
1402
1564
  ] }),
1403
- trend ? /* @__PURE__ */ jsx3(
1565
+ trend ? /* @__PURE__ */ jsx4(
1404
1566
  "span",
1405
1567
  {
1406
1568
  className: cn(
@@ -1414,159 +1576,38 @@ var MetricTile = ({
1414
1576
  ] });
1415
1577
  const divider = showDivider ? metricCellDividerClass : void 0;
1416
1578
  if (onSelect) {
1417
- return /* @__PURE__ */ jsx3(
1579
+ return /* @__PURE__ */ jsx4(
1418
1580
  "button",
1419
1581
  {
1420
1582
  type: "button",
1421
1583
  onClick: onSelect,
1422
1584
  "aria-pressed": active,
1423
1585
  "aria-label": ariaLabel,
1424
- className: cn(metricTileInteractiveClass, divider, className),
1586
+ className: cn(metricTileBaseClass, metricTileInteractiveExtraClass, divider, className),
1425
1587
  children: content
1426
1588
  }
1427
1589
  );
1428
1590
  }
1429
- return /* @__PURE__ */ jsx3("div", { className: cn(metricTileBaseClass, divider, className), children: content });
1591
+ return /* @__PURE__ */ jsx4("div", { className: cn(metricTileBaseClass, divider, className), children: content });
1430
1592
  };
1431
1593
 
1432
1594
  // src/app/theme/ThemePresetGallery.tsx
1433
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1434
- var ThemePresetGallery = ({
1435
- value,
1436
- onSelect,
1437
- presets,
1438
- className
1439
- }) => {
1440
- const items = presets ? TIMBAL_THEME_PRESETS.filter((p) => presets.includes(p.id)) : TIMBAL_THEME_PRESETS;
1441
- return /* @__PURE__ */ jsx4(
1442
- "div",
1443
- {
1444
- role: "radiogroup",
1445
- "aria-label": "Theme presets",
1446
- className: cn(
1447
- "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",
1448
- className
1449
- ),
1450
- children: items.map((preset) => {
1451
- const selected = value === preset.id;
1452
- return /* @__PURE__ */ jsxs4("div", { "data-timbal-theme": preset.id, children: [
1453
- /* @__PURE__ */ jsx4(TimbalThemeStyle, { preset: preset.id, scope: preset.id }),
1454
- /* @__PURE__ */ jsxs4(
1455
- "button",
1456
- {
1457
- type: "button",
1458
- role: "radio",
1459
- "aria-checked": selected,
1460
- "aria-label": `${preset.label} theme`,
1461
- onClick: () => onSelect?.(preset.id),
1462
- className: cn(
1463
- "group flex w-full flex-col gap-3 rounded-xl border bg-card p-3 text-left transition-colors",
1464
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1465
- selected ? "border-primary ring-2 ring-primary/30" : "border-border hover:border-foreground/30"
1466
- ),
1467
- children: [
1468
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-2", children: [
1469
- /* @__PURE__ */ jsxs4("span", { className: "flex items-center gap-2", children: [
1470
- /* @__PURE__ */ jsx4(
1471
- "span",
1472
- {
1473
- "aria-hidden": true,
1474
- className: "size-4 shrink-0 rounded-full ring-1 ring-black/10",
1475
- style: { background: preset.swatch }
1476
- }
1477
- ),
1478
- /* @__PURE__ */ jsx4("span", { className: "text-sm font-medium text-foreground", children: preset.label })
1479
- ] }),
1480
- selected ? /* @__PURE__ */ jsx4("span", { className: "text-xs font-medium text-primary", children: "Selected" }) : null
1481
- ] }),
1482
- /* @__PURE__ */ jsx4("p", { className: "text-xs leading-snug text-muted-foreground", children: preset.description }),
1483
- preset.font ? /* @__PURE__ */ jsxs4("span", { className: "text-[10px] uppercase tracking-wide text-muted-foreground", children: [
1484
- "Aa \xB7 ",
1485
- preset.font
1486
- ] }) : null,
1487
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-2 rounded-lg border border-border bg-background p-2", children: [
1488
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1489
- /* @__PURE__ */ jsx4(Button, { size: "xs", className: "pointer-events-none", children: "Primary" }),
1490
- /* @__PURE__ */ jsx4("span", { className: "size-5 rounded-md bg-primary", "aria-hidden": true }),
1491
- /* @__PURE__ */ jsx4("span", { className: "size-5 rounded-md bg-muted", "aria-hidden": true }),
1492
- /* @__PURE__ */ jsx4(
1493
- "span",
1494
- {
1495
- className: "size-5 rounded-md border border-border bg-accent",
1496
- "aria-hidden": true
1497
- }
1498
- )
1499
- ] }),
1500
- /* @__PURE__ */ jsx4(MetricTile, { label: "Active users", value: "1,248", trend: "+8%" })
1501
- ] })
1502
- ]
1503
- }
1504
- )
1505
- ] }, preset.id);
1506
- })
1507
- }
1508
- );
1509
- };
1510
-
1511
- // src/design/app-classes.ts
1512
- var appPageColumnClass = "mx-auto w-full max-w-6xl px-4 md:px-6";
1513
- var appShellTopbarInsetClass = "w-full px-4 md:px-6";
1514
- var appShellInsetTopClass = "pt-4 md:pt-6";
1515
- var appShellTopbarRowClass = cn(
1516
- studioTopbarPillHeightClass,
1517
- "flex w-full items-center justify-between gap-2"
1518
- );
1519
- var appShellTopbarStickyClass = cn(
1520
- "shrink-0 bg-background pb-2",
1521
- appShellInsetTopClass
1522
- );
1523
- var appPageHeaderClass = cn(
1524
- "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",
1525
- "pb-4 pt-2"
1526
- );
1527
- var appSectionClass = "flex flex-col gap-4 py-4";
1528
- var appSectionTitleClass = "text-lg font-semibold text-foreground";
1529
- var appSectionDescriptionClass = "text-sm text-muted-foreground";
1530
- var appSurfaceCardClass = cn(
1531
- studioIntegrationCardClass,
1532
- "p-4 md:p-5"
1533
- );
1534
- var appStatTileClass = cn(
1535
- appSurfaceCardClass,
1536
- "flex flex-col gap-1 px-4 py-3 shadow-none"
1537
- );
1538
- var appStatValueClass = "text-2xl font-normal tracking-tight text-foreground tabular-nums";
1539
- var appStatLabelClass = "text-xs font-normal text-muted-foreground";
1540
- var appFilterBarClass = "flex flex-wrap items-end gap-2";
1541
- var appSearchInputClass = controlClass({}, "inline-flex items-center gap-2");
1542
- var appBreadcrumbsClass = "flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground";
1543
- var appBreadcrumbLinkClass = "transition-colors hover:text-foreground";
1544
- var appFieldClass = "flex flex-col gap-1.5";
1545
- var appFieldLabelClass = "text-sm font-medium text-foreground";
1546
- var appFieldHintClass = "text-xs text-muted-foreground";
1547
- var appInputClass = controlClass({}, "w-full");
1548
- var appEmptyStateClass = cn(
1549
- appSurfaceCardClass,
1550
- "flex flex-col items-center justify-center gap-2 py-12 text-center"
1551
- );
1552
- var appEmptyStateTitleClass = "text-base font-medium text-foreground";
1553
- var appEmptyStateDescriptionClass = "max-w-sm text-sm text-muted-foreground";
1554
- var appChartPanelClass = cn(appSurfaceCardClass, "flex flex-col gap-3");
1595
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1555
1596
 
1556
1597
  // src/app/layout/app-shell-chat-context.tsx
1557
- import { createContext, useContext } from "react";
1558
- var AppShellChatContext = createContext(null);
1598
+ import { createContext as createContext2, useContext as useContext2 } from "react";
1599
+ var AppShellChatContext = createContext2(null);
1559
1600
  var AppShellChatProvider = AppShellChatContext.Provider;
1560
1601
  function useAppShellChat() {
1561
- return useContext(AppShellChatContext);
1602
+ return useContext2(AppShellChatContext);
1562
1603
  }
1563
1604
 
1564
1605
  // src/app/layout/app-shell-nav-context.tsx
1565
- import { createContext as createContext2, useContext as useContext2 } from "react";
1566
- var AppShellNavContext = createContext2(null);
1606
+ import { createContext as createContext3, useContext as useContext3 } from "react";
1607
+ var AppShellNavContext = createContext3(null);
1567
1608
  var AppShellNavProvider = AppShellNavContext.Provider;
1568
1609
  function useAppShellNav() {
1569
- return useContext2(AppShellNavContext) ?? {
1610
+ return useContext3(AppShellNavContext) ?? {
1570
1611
  open: false,
1571
1612
  setOpen: () => {
1572
1613
  },
@@ -1578,7 +1619,7 @@ function useAppShellNav() {
1578
1619
  // src/app/layout/AppShell.tsx
1579
1620
  import { motion, useReducedMotion } from "motion/react";
1580
1621
  import { useCallback, useMemo, useState } from "react";
1581
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1622
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1582
1623
  var floatingTriggerClass = cn(
1583
1624
  "aui-app-shell-chat-trigger-fixed fixed z-50 rounded-full px-5 py-2.5 text-sm font-medium shadow-card-elevated",
1584
1625
  "bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
@@ -1596,6 +1637,7 @@ var AppShellBody = ({
1596
1637
  sidebar,
1597
1638
  topbarContent,
1598
1639
  mainClassName,
1640
+ contentFill = false,
1599
1641
  insetPaddingPx,
1600
1642
  insetExpanded,
1601
1643
  children
@@ -1607,7 +1649,7 @@ var AppShellBody = ({
1607
1649
  layoutDirection
1608
1650
  );
1609
1651
  const insetPadding = sidebar ? insetPaddingPx : 0;
1610
- return /* @__PURE__ */ jsx5(
1652
+ return /* @__PURE__ */ jsx6(
1611
1653
  motion.div,
1612
1654
  {
1613
1655
  className: "aui-app-shell-body relative z-10 flex min-h-0 min-w-0 flex-1 flex-col",
@@ -1618,12 +1660,28 @@ var AppShellBody = ({
1618
1660
  "div",
1619
1661
  {
1620
1662
  className: cn(
1621
- "aui-app-shell-scroll flex min-h-0 flex-1 flex-col overflow-y-auto",
1663
+ "aui-app-shell-scroll flex min-h-0 flex-1 flex-col",
1664
+ // Padded scroll region by default; a full-bleed page (chat / canvas) owns
1665
+ // its own scroll, so clip here and let the bounded `main` fill exactly.
1666
+ contentFill ? "overflow-hidden" : "overflow-y-auto",
1622
1667
  !topbarContent && appShellInsetTopClass
1623
1668
  ),
1624
1669
  children: [
1625
- topbarContent ? /* @__PURE__ */ jsx5("header", { className: cn("aui-app-shell-topbar-region", appShellTopbarStickyClass), children: /* @__PURE__ */ jsx5("div", { className: appShellTopbarInsetClass, children: topbarContent }) }) : null,
1626
- /* @__PURE__ */ jsx5("main", { className: cn("aui-app-shell-main min-w-0 flex-1", mainClassName), children })
1670
+ topbarContent ? /* @__PURE__ */ jsx6("header", { className: cn("aui-app-shell-topbar-region", appShellTopbarStickyClass), children: /* @__PURE__ */ jsx6("div", { className: appShellTopbarInsetClass, children: topbarContent }) }) : null,
1671
+ /* @__PURE__ */ jsx6(
1672
+ "main",
1673
+ {
1674
+ className: cn(
1675
+ // Bounded flex column by default so `h-full` / `flex-1 min-h-0` children
1676
+ // (full-page chat, canvas) resolve a height without `mainClassName` surgery.
1677
+ "aui-app-shell-main flex min-h-0 min-w-0 flex-1 flex-col",
1678
+ // Bottom breathing room for scrolling content; full-bleed pages skip it.
1679
+ !contentFill && appShellInsetBottomClass,
1680
+ mainClassName
1681
+ ),
1682
+ children
1683
+ }
1684
+ )
1627
1685
  ]
1628
1686
  }
1629
1687
  )
@@ -1648,7 +1706,8 @@ var AppShell = ({
1648
1706
  defaultNavOpen = false,
1649
1707
  onNavOpenChange,
1650
1708
  className,
1651
- mainClassName
1709
+ mainClassName,
1710
+ contentFill = false
1652
1711
  }) => {
1653
1712
  const topbarContent = topbar ?? header;
1654
1713
  const hasChat = Boolean(chat);
@@ -1689,18 +1748,19 @@ var AppShell = ({
1689
1748
  setInsetPaddingPx(insetPx);
1690
1749
  }, []);
1691
1750
  const insetExpanded = insetPaddingPx >= SIDEBAR_INSET_PX_EXPANDED;
1692
- const shellBody = /* @__PURE__ */ jsx5(
1751
+ const shellBody = /* @__PURE__ */ jsx6(
1693
1752
  AppShellBody,
1694
1753
  {
1695
1754
  sidebar,
1696
1755
  topbarContent,
1697
1756
  mainClassName,
1757
+ contentFill,
1698
1758
  insetPaddingPx,
1699
1759
  insetExpanded,
1700
1760
  children
1701
1761
  }
1702
1762
  );
1703
- const tree = /* @__PURE__ */ jsx5(ShellInsetProvider, { value: sidebar ? reportShellInset : null, children: /* @__PURE__ */ jsxs5(
1763
+ const tree = /* @__PURE__ */ jsx6(ShellInsetProvider, { value: sidebar ? reportShellInset : null, children: /* @__PURE__ */ jsxs5(
1704
1764
  "div",
1705
1765
  {
1706
1766
  className: cn(
@@ -1710,7 +1770,7 @@ var AppShell = ({
1710
1770
  style: studioChromeShellStyle,
1711
1771
  children: [
1712
1772
  sidebar,
1713
- sidebar && navOpen ? /* @__PURE__ */ jsx5(
1773
+ sidebar && navOpen ? /* @__PURE__ */ jsx6(
1714
1774
  "button",
1715
1775
  {
1716
1776
  type: "button",
@@ -1720,7 +1780,7 @@ var AppShell = ({
1720
1780
  }
1721
1781
  ) : null,
1722
1782
  shellBody,
1723
- hasChat && chatOpen ? /* @__PURE__ */ jsx5(
1783
+ hasChat && chatOpen ? /* @__PURE__ */ jsx6(
1724
1784
  "div",
1725
1785
  {
1726
1786
  className: floatingPanelClass,
@@ -1733,7 +1793,7 @@ var AppShell = ({
1733
1793
  children: chat
1734
1794
  }
1735
1795
  ) : null,
1736
- hasChat && chatCollapsible && !chatOpen && !hideChatTrigger ? /* @__PURE__ */ jsx5(
1796
+ hasChat && chatCollapsible && !chatOpen && !hideChatTrigger ? /* @__PURE__ */ jsx6(
1737
1797
  "button",
1738
1798
  {
1739
1799
  type: "button",
@@ -1746,11 +1806,11 @@ var AppShell = ({
1746
1806
  ]
1747
1807
  }
1748
1808
  ) });
1749
- const withNav = /* @__PURE__ */ jsx5(AppShellNavProvider, { value: navControls, children: tree });
1809
+ const withNav = /* @__PURE__ */ jsx6(AppShellNavProvider, { value: navControls, children: tree });
1750
1810
  if (!hasChat) {
1751
1811
  return withNav;
1752
1812
  }
1753
- return /* @__PURE__ */ jsx5(
1813
+ return /* @__PURE__ */ jsx6(
1754
1814
  AppShellChatProvider,
1755
1815
  {
1756
1816
  value: {
@@ -1765,7 +1825,7 @@ var AppShell = ({
1765
1825
  };
1766
1826
 
1767
1827
  // src/app/layout/AppShellTopbar.tsx
1768
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1828
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1769
1829
  var AppShellTopbar = ({
1770
1830
  start,
1771
1831
  actions,
@@ -1777,12 +1837,12 @@ var AppShellTopbar = ({
1777
1837
  start,
1778
1838
  children
1779
1839
  ] }),
1780
- actions ? /* @__PURE__ */ jsx6("div", { className: "aui-app-shell-topbar-actions flex shrink-0 items-center gap-2", children: actions }) : null
1840
+ actions ? /* @__PURE__ */ jsx7("div", { className: "aui-app-shell-topbar-actions flex shrink-0 items-center gap-2", children: actions }) : null
1781
1841
  ] });
1782
1842
  };
1783
1843
 
1784
1844
  // src/app/layout/AppShellChatTrigger.tsx
1785
- import { jsx as jsx7 } from "react/jsx-runtime";
1845
+ import { jsx as jsx8 } from "react/jsx-runtime";
1786
1846
  var floatingPositionClass = "fixed bottom-6 right-6 z-50 max-sm:bottom-4 max-sm:right-4";
1787
1847
  var AppShellChatTrigger = ({
1788
1848
  className,
@@ -1791,7 +1851,7 @@ var AppShellChatTrigger = ({
1791
1851
  }) => {
1792
1852
  const shellChat = useAppShellChat();
1793
1853
  if (!shellChat || shellChat.open) return null;
1794
- return /* @__PURE__ */ jsx7(
1854
+ return /* @__PURE__ */ jsx8(
1795
1855
  TimbalV2Button,
1796
1856
  {
1797
1857
  type: "button",
@@ -1812,13 +1872,13 @@ var AppShellChatTrigger = ({
1812
1872
 
1813
1873
  // src/app/layout/AppShellSidebarTrigger.tsx
1814
1874
  import { MenuIcon } from "lucide-react";
1815
- import { jsx as jsx8 } from "react/jsx-runtime";
1875
+ import { jsx as jsx9 } from "react/jsx-runtime";
1816
1876
  var AppShellSidebarTrigger = ({
1817
1877
  label = "Open navigation",
1818
1878
  className
1819
1879
  }) => {
1820
1880
  const nav = useAppShellNav();
1821
- return /* @__PURE__ */ jsx8(
1881
+ return /* @__PURE__ */ jsx9(
1822
1882
  "button",
1823
1883
  {
1824
1884
  type: "button",
@@ -1830,75 +1890,114 @@ var AppShellSidebarTrigger = ({
1830
1890
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10",
1831
1891
  className
1832
1892
  ),
1833
- children: /* @__PURE__ */ jsx8(MenuIcon, { className: "size-5", "aria-hidden": true })
1893
+ children: /* @__PURE__ */ jsx9(MenuIcon, { className: "size-5", "aria-hidden": true })
1834
1894
  }
1835
1895
  );
1836
1896
  };
1837
1897
 
1838
1898
  // src/app/layout/PageHeader.tsx
1839
- import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
1899
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
1840
1900
  var PageHeader = ({
1841
1901
  title,
1842
1902
  description,
1843
1903
  actions,
1844
1904
  className
1845
1905
  }) => {
1846
- return /* @__PURE__ */ jsxs7("header", { className: cn("aui-app-page-header", appPageHeaderClass, className), children: [
1847
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
1848
- /* @__PURE__ */ jsx9("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }),
1849
- description ? /* @__PURE__ */ jsx9("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
1850
- ] }),
1851
- actions ? /* @__PURE__ */ jsx9("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1906
+ const pageHeaderClass = useAppDensityClass("pageHeader");
1907
+ if (title == null && description == null && actions == null) {
1908
+ return null;
1909
+ }
1910
+ return /* @__PURE__ */ jsxs7("header", { className: cn("aui-app-page-header", pageHeaderClass, className), children: [
1911
+ title != null || description != null ? /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
1912
+ title != null ? /* @__PURE__ */ jsx10("h1", { className: "text-2xl font-semibold tracking-tight text-foreground", children: title }) : null,
1913
+ description ? /* @__PURE__ */ jsx10("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
1914
+ ] }) : null,
1915
+ actions ? /* @__PURE__ */ jsx10("div", { className: "aui-app-page-header-actions flex shrink-0 flex-wrap items-center gap-2", children: actions }) : null
1852
1916
  ] });
1853
1917
  };
1854
1918
 
1855
1919
  // src/app/layout/Page.tsx
1856
- import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
1920
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
1921
+ var PageFrame = ({
1922
+ children,
1923
+ breadcrumbs,
1924
+ fill = false,
1925
+ className,
1926
+ ...headerProps
1927
+ }) => {
1928
+ const density = useAppDensity();
1929
+ const pageColumnClass = useAppDensityClass("pageColumn");
1930
+ return /* @__PURE__ */ jsxs8(
1931
+ "div",
1932
+ {
1933
+ className: cn(
1934
+ "aui-app-page",
1935
+ fill ? "flex min-h-0 min-w-0 flex-1 flex-col" : pageColumnClass,
1936
+ className
1937
+ ),
1938
+ "data-density": density,
1939
+ children: [
1940
+ breadcrumbs,
1941
+ /* @__PURE__ */ jsx11(PageHeader, { ...headerProps }),
1942
+ children
1943
+ ]
1944
+ }
1945
+ );
1946
+ };
1857
1947
  var Page = ({
1948
+ density = "default",
1858
1949
  children,
1859
1950
  breadcrumbs,
1951
+ fill = false,
1860
1952
  className,
1861
1953
  ...headerProps
1862
1954
  }) => {
1863
- return /* @__PURE__ */ jsxs8("div", { className: cn("aui-app-page", appPageColumnClass, className), children: [
1864
- breadcrumbs,
1865
- /* @__PURE__ */ jsx10(PageHeader, { ...headerProps }),
1866
- children
1867
- ] });
1955
+ return /* @__PURE__ */ jsx11(AppDensityProvider, { density, children: /* @__PURE__ */ jsx11(
1956
+ PageFrame,
1957
+ {
1958
+ breadcrumbs,
1959
+ fill,
1960
+ className,
1961
+ ...headerProps,
1962
+ children
1963
+ }
1964
+ ) });
1868
1965
  };
1869
1966
 
1870
1967
  // src/app/layout/Section.tsx
1871
- import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1968
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
1872
1969
  var Section = ({
1873
1970
  title,
1874
1971
  description,
1875
1972
  children,
1973
+ density,
1876
1974
  className
1877
1975
  }) => {
1878
- return /* @__PURE__ */ jsxs9("section", { className: cn("aui-app-section", appSectionClass, className), children: [
1879
- title ? /* @__PURE__ */ jsx11("h2", { className: appSectionTitleClass, children: title }) : null,
1880
- description ? /* @__PURE__ */ jsx11("p", { className: appSectionDescriptionClass, children: description }) : null,
1976
+ const sectionClass = useAppDensityClass("section", density);
1977
+ return /* @__PURE__ */ jsxs9("section", { className: cn("aui-app-section", sectionClass, className), children: [
1978
+ title ? /* @__PURE__ */ jsx12("h2", { className: appSectionTitleClass, children: title }) : null,
1979
+ description ? /* @__PURE__ */ jsx12("p", { className: appSectionDescriptionClass, children: description }) : null,
1881
1980
  children
1882
1981
  ] });
1883
1982
  };
1884
1983
 
1885
1984
  // src/app/copilot/app-copilot-context.tsx
1886
- import { createContext as createContext3, useContext as useContext3 } from "react";
1887
- import { jsx as jsx12 } from "react/jsx-runtime";
1888
- var AppCopilotContext = createContext3(null);
1985
+ import { createContext as createContext4, useContext as useContext4 } from "react";
1986
+ import { jsx as jsx13 } from "react/jsx-runtime";
1987
+ var AppCopilotContext = createContext4(null);
1889
1988
  var AppCopilotProvider = ({
1890
1989
  value,
1891
1990
  children
1892
1991
  }) => {
1893
- return /* @__PURE__ */ jsx12(AppCopilotContext.Provider, { value, children });
1992
+ return /* @__PURE__ */ jsx13(AppCopilotContext.Provider, { value, children });
1894
1993
  };
1895
1994
  function useAppCopilotContext() {
1896
- return useContext3(AppCopilotContext) ?? {};
1995
+ return useContext4(AppCopilotContext) ?? {};
1897
1996
  }
1898
1997
 
1899
1998
  // src/app/chat/AppChatPanel.tsx
1900
1999
  import { XIcon } from "lucide-react";
1901
- import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
2000
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1902
2001
  var shellClass = "aui-app-chat-panel flex h-full min-h-0 flex-col overflow-hidden";
1903
2002
  var chromeClass = cn(
1904
2003
  "aui-app-chat-panel-chrome relative z-20 flex min-h-10 shrink-0 items-center justify-end px-2 pt-2"
@@ -1944,17 +2043,17 @@ var AppChatPanel = ({
1944
2043
  }) => {
1945
2044
  const shellChat = useAppShellChat();
1946
2045
  return /* @__PURE__ */ jsxs10("div", { className: cn(shellClass, className), children: [
1947
- shellChat?.collapsible ? /* @__PURE__ */ jsx13("div", { className: chromeClass, children: /* @__PURE__ */ jsx13(
2046
+ shellChat?.collapsible ? /* @__PURE__ */ jsx14("div", { className: chromeClass, children: /* @__PURE__ */ jsx14(
1948
2047
  "button",
1949
2048
  {
1950
2049
  type: "button",
1951
2050
  className: closeButtonClass,
1952
2051
  onClick: () => shellChat.setOpen(false),
1953
2052
  "aria-label": "Close assistant",
1954
- children: /* @__PURE__ */ jsx13(XIcon, { className: "size-4", "aria-hidden": true })
2053
+ children: /* @__PURE__ */ jsx14(XIcon, { className: "size-4", "aria-hidden": true })
1955
2054
  }
1956
2055
  ) }) : null,
1957
- /* @__PURE__ */ jsx13("div", { className: bodyClass, children: /* @__PURE__ */ jsx13(
2056
+ /* @__PURE__ */ jsx14("div", { className: bodyClass, children: /* @__PURE__ */ jsx14(
1958
2057
  TimbalRuntimeProvider,
1959
2058
  {
1960
2059
  workforceId,
@@ -1964,7 +2063,7 @@ var AppChatPanel = ({
1964
2063
  attachmentsUploadUrl,
1965
2064
  attachmentsAccept,
1966
2065
  debug,
1967
- children: /* @__PURE__ */ jsx13(
2066
+ children: /* @__PURE__ */ jsx14(
1968
2067
  Thread,
1969
2068
  {
1970
2069
  variant: "panel",
@@ -1985,66 +2084,91 @@ var AppChatPanel = ({
1985
2084
  };
1986
2085
 
1987
2086
  // src/app/surfaces/SurfaceCard.tsx
1988
- import { jsx as jsx14 } from "react/jsx-runtime";
2087
+ import { jsx as jsx15 } from "react/jsx-runtime";
1989
2088
  var SurfaceCard = ({ children, className }) => {
1990
- return /* @__PURE__ */ jsx14("div", { className: cn("aui-app-surface-card", appSurfaceCardClass, className), children });
2089
+ const surfaceCardClass = useAppDensityClass("surfaceCard");
2090
+ return /* @__PURE__ */ jsx15("div", { className: cn("aui-app-surface-card", surfaceCardClass, className), children });
1991
2091
  };
1992
2092
 
1993
2093
  // src/app/surfaces/StatTile.tsx
1994
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
2094
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1995
2095
  var StatTile = ({ label, value, hint, className }) => {
1996
- return /* @__PURE__ */ jsxs11("div", { className: cn("aui-app-stat-tile", appStatTileClass, className), children: [
1997
- /* @__PURE__ */ jsx15("span", { className: appStatLabelClass, children: label }),
1998
- /* @__PURE__ */ jsx15("span", { className: appStatValueClass, children: value }),
1999
- hint ? /* @__PURE__ */ jsx15("span", { className: "text-xs text-muted-foreground", children: hint }) : null
2096
+ const statTileClass = useAppDensityClass("statTile");
2097
+ return /* @__PURE__ */ jsxs11("div", { className: cn("aui-app-stat-tile", statTileClass, className), children: [
2098
+ /* @__PURE__ */ jsx16("span", { className: appStatLabelClass, children: label }),
2099
+ /* @__PURE__ */ jsx16("span", { className: appStatValueClass, children: value }),
2100
+ hint ? /* @__PURE__ */ jsx16("span", { className: "text-xs text-muted-foreground", children: hint }) : null
2000
2101
  ] });
2001
2102
  };
2002
2103
 
2003
2104
  // src/app/surfaces/EmptyState.tsx
2004
- import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
2105
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2005
2106
  var EmptyState = ({
2006
2107
  title,
2007
2108
  description,
2008
2109
  action,
2009
2110
  className
2010
2111
  }) => {
2011
- return /* @__PURE__ */ jsxs12("div", { className: cn("aui-app-empty-state", appEmptyStateClass, className), children: [
2012
- /* @__PURE__ */ jsx16("p", { className: appEmptyStateTitleClass, children: title }),
2013
- description ? /* @__PURE__ */ jsx16("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
2112
+ const emptyStateClass = useAppDensityClass("emptyState");
2113
+ return /* @__PURE__ */ jsxs12("div", { className: cn("aui-app-empty-state", emptyStateClass, className), children: [
2114
+ /* @__PURE__ */ jsx17("p", { className: appEmptyStateTitleClass, children: title }),
2115
+ description ? /* @__PURE__ */ jsx17("p", { className: appEmptyStateDescriptionClass, children: description }) : null,
2014
2116
  action
2015
2117
  ] });
2016
2118
  };
2017
2119
 
2018
2120
  // src/app/surfaces/StatusBadge.tsx
2019
- import { jsx as jsx17 } from "react/jsx-runtime";
2121
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2020
2122
  var statusBadgeToneClass = {
2021
- default: "bg-muted text-foreground",
2022
- primary: "bg-primary/10 text-primary",
2023
- success: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
2024
- warn: "bg-amber-500/10 text-amber-600 dark:text-amber-400",
2025
- danger: "bg-destructive/10 text-destructive",
2026
- muted: "bg-muted/80 text-muted-foreground"
2123
+ default: "bg-muted text-foreground ring-border",
2124
+ primary: "bg-primary/10 text-primary ring-primary/20",
2125
+ success: "bg-emerald-500/10 text-emerald-700 ring-emerald-500/20 dark:text-emerald-400",
2126
+ warn: "bg-amber-500/10 text-amber-700 ring-amber-500/25 dark:text-amber-400",
2127
+ danger: "bg-destructive/10 text-destructive ring-destructive/20",
2128
+ muted: "bg-muted/70 text-muted-foreground ring-border/60"
2129
+ };
2130
+ var statusBadgeDotClass = {
2131
+ default: "bg-foreground/40",
2132
+ primary: "bg-primary",
2133
+ success: "bg-emerald-500",
2134
+ warn: "bg-amber-500",
2135
+ danger: "bg-destructive",
2136
+ muted: "bg-muted-foreground/60"
2027
2137
  };
2028
2138
  var StatusBadge = ({
2029
2139
  children,
2030
2140
  tone = "default",
2141
+ dot = false,
2031
2142
  className
2032
2143
  }) => {
2033
- return /* @__PURE__ */ jsx17(
2144
+ return /* @__PURE__ */ jsxs13(
2034
2145
  "span",
2035
2146
  {
2036
2147
  className: cn(
2037
- "aui-app-status-badge inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
2148
+ "aui-app-status-badge inline-flex items-center gap-1.5 rounded-full px-2 py-0.5",
2149
+ "text-xs font-medium leading-none ring-1 ring-inset",
2038
2150
  statusBadgeToneClass[tone],
2039
2151
  className
2040
2152
  ),
2041
- children
2153
+ children: [
2154
+ dot ? /* @__PURE__ */ jsx18(
2155
+ "span",
2156
+ {
2157
+ "aria-hidden": true,
2158
+ className: cn(
2159
+ "size-1.5 shrink-0 rounded-full",
2160
+ statusBadgeDotClass[tone]
2161
+ )
2162
+ }
2163
+ ) : null,
2164
+ children
2165
+ ]
2042
2166
  }
2043
2167
  );
2044
2168
  };
2045
2169
 
2046
2170
  // src/app/surfaces/AppConfirmDialog.tsx
2047
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2171
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2048
2172
  var bodyClass2 = "flex flex-col gap-4 p-6";
2049
2173
  var titleClass = "pr-8";
2050
2174
  var actionsClass = "flex flex-wrap justify-end gap-2";
@@ -2059,15 +2183,15 @@ var AppConfirmDialog = ({
2059
2183
  destructive = false,
2060
2184
  className
2061
2185
  }) => {
2062
- return /* @__PURE__ */ jsx18(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx18(
2186
+ return /* @__PURE__ */ jsx19(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx19(
2063
2187
  DialogContent,
2064
2188
  {
2065
2189
  className: cn("gap-0 p-0 sm:max-w-md", className),
2066
- children: /* @__PURE__ */ jsxs13("div", { className: bodyClass2, children: [
2067
- /* @__PURE__ */ jsx18(DialogTitle, { className: titleClass, children: title }),
2068
- description ? /* @__PURE__ */ jsx18("p", { className: "text-sm text-muted-foreground", children: description }) : null,
2069
- /* @__PURE__ */ jsxs13("div", { className: actionsClass, children: [
2070
- /* @__PURE__ */ jsx18(
2190
+ children: /* @__PURE__ */ jsxs14("div", { className: bodyClass2, children: [
2191
+ /* @__PURE__ */ jsx19(DialogTitle, { className: titleClass, children: title }),
2192
+ description ? /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: description }) : null,
2193
+ /* @__PURE__ */ jsxs14("div", { className: actionsClass, children: [
2194
+ /* @__PURE__ */ jsx19(
2071
2195
  TimbalV2Button,
2072
2196
  {
2073
2197
  type: "button",
@@ -2077,7 +2201,7 @@ var AppConfirmDialog = ({
2077
2201
  children: cancelLabel
2078
2202
  }
2079
2203
  ),
2080
- /* @__PURE__ */ jsx18(
2204
+ /* @__PURE__ */ jsx19(
2081
2205
  TimbalV2Button,
2082
2206
  {
2083
2207
  type: "button",
@@ -2097,7 +2221,7 @@ var AppConfirmDialog = ({
2097
2221
  };
2098
2222
 
2099
2223
  // src/app/surfaces/InfoCard.tsx
2100
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2224
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2101
2225
  var toneClass = {
2102
2226
  neutral: "border-border bg-muted/40",
2103
2227
  info: "border-primary/25 bg-primary/5",
@@ -2112,7 +2236,7 @@ var InfoCard = ({
2112
2236
  action,
2113
2237
  tone = "neutral",
2114
2238
  className
2115
- }) => /* @__PURE__ */ jsxs14(
2239
+ }) => /* @__PURE__ */ jsxs15(
2116
2240
  "div",
2117
2241
  {
2118
2242
  className: cn(
@@ -2121,18 +2245,18 @@ var InfoCard = ({
2121
2245
  className
2122
2246
  ),
2123
2247
  children: [
2124
- icon ? /* @__PURE__ */ jsx19("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
2125
- /* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1", children: [
2126
- title ? /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
2127
- children ? /* @__PURE__ */ jsx19("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
2248
+ icon ? /* @__PURE__ */ jsx20("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: icon }) : null,
2249
+ /* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
2250
+ title ? /* @__PURE__ */ jsx20("p", { className: "text-sm font-medium text-foreground", children: title }) : null,
2251
+ children ? /* @__PURE__ */ jsx20("div", { className: cn("text-sm text-muted-foreground", title && "mt-1"), children }) : null
2128
2252
  ] }),
2129
- action ? /* @__PURE__ */ jsx19("div", { className: "shrink-0", children: action }) : null
2253
+ action ? /* @__PURE__ */ jsx20("div", { className: "shrink-0", children: action }) : null
2130
2254
  ]
2131
2255
  }
2132
2256
  );
2133
2257
 
2134
2258
  // src/app/surfaces/StatusDot.tsx
2135
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2259
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2136
2260
  var dotClass = {
2137
2261
  online: "bg-emerald-500",
2138
2262
  busy: "bg-amber-500",
@@ -2145,9 +2269,9 @@ var StatusDot = ({
2145
2269
  label,
2146
2270
  pulse = false,
2147
2271
  className
2148
- }) => /* @__PURE__ */ jsxs15("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
2149
- /* @__PURE__ */ jsxs15("span", { className: "relative flex size-2", children: [
2150
- pulse ? /* @__PURE__ */ jsx20(
2272
+ }) => /* @__PURE__ */ jsxs16("span", { className: cn("inline-flex items-center gap-1.5", className), children: [
2273
+ /* @__PURE__ */ jsxs16("span", { className: "relative flex size-2", children: [
2274
+ pulse ? /* @__PURE__ */ jsx21(
2151
2275
  "span",
2152
2276
  {
2153
2277
  className: cn(
@@ -2156,25 +2280,25 @@ var StatusDot = ({
2156
2280
  )
2157
2281
  }
2158
2282
  ) : null,
2159
- /* @__PURE__ */ jsx20("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
2283
+ /* @__PURE__ */ jsx21("span", { className: cn("relative inline-flex size-2 rounded-full", dotClass[tone]) })
2160
2284
  ] }),
2161
- label ? /* @__PURE__ */ jsx20("span", { className: "text-xs text-muted-foreground", children: label }) : null
2285
+ label ? /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground", children: label }) : null
2162
2286
  ] });
2163
2287
 
2164
2288
  // src/app/surfaces/DescriptionList.tsx
2165
- import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2289
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2166
2290
  var DescriptionList = ({
2167
2291
  items,
2168
2292
  stacked = false,
2169
2293
  className
2170
- }) => /* @__PURE__ */ jsx21(
2294
+ }) => /* @__PURE__ */ jsx22(
2171
2295
  "dl",
2172
2296
  {
2173
2297
  className: cn(
2174
2298
  "divide-y divide-border rounded-xl border border-border bg-card",
2175
2299
  className
2176
2300
  ),
2177
- children: items.map((item, i) => /* @__PURE__ */ jsxs16(
2301
+ children: items.map((item, i) => /* @__PURE__ */ jsxs17(
2178
2302
  "div",
2179
2303
  {
2180
2304
  className: cn(
@@ -2182,8 +2306,8 @@ var DescriptionList = ({
2182
2306
  stacked ? "flex flex-col gap-0.5" : "flex items-center justify-between gap-4"
2183
2307
  ),
2184
2308
  children: [
2185
- /* @__PURE__ */ jsx21("dt", { className: "text-sm text-muted-foreground", children: item.label }),
2186
- /* @__PURE__ */ jsx21(
2309
+ /* @__PURE__ */ jsx22("dt", { className: "text-sm text-muted-foreground", children: item.label }),
2310
+ /* @__PURE__ */ jsx22(
2187
2311
  "dd",
2188
2312
  {
2189
2313
  className: cn(
@@ -2203,8 +2327,8 @@ var DescriptionList = ({
2203
2327
  // src/app/surfaces/ExpandableSection.tsx
2204
2328
  import { useId, useState as useState2 } from "react";
2205
2329
  import { AnimatePresence, motion as motion2, useReducedMotion as useReducedMotion2 } from "motion/react";
2206
- import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2207
- var Chevron = ({ open }) => /* @__PURE__ */ jsx22(
2330
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
2331
+ var Chevron = ({ open }) => /* @__PURE__ */ jsx23(
2208
2332
  "svg",
2209
2333
  {
2210
2334
  viewBox: "0 0 24 24",
@@ -2218,7 +2342,7 @@ var Chevron = ({ open }) => /* @__PURE__ */ jsx22(
2218
2342
  strokeLinecap: "round",
2219
2343
  strokeLinejoin: "round",
2220
2344
  "aria-hidden": true,
2221
- children: /* @__PURE__ */ jsx22("path", { d: "m6 9 6 6 6-6" })
2345
+ children: /* @__PURE__ */ jsx23("path", { d: "m6 9 6 6 6-6" })
2222
2346
  }
2223
2347
  );
2224
2348
  var ExpandableSection = ({
@@ -2239,8 +2363,8 @@ var ExpandableSection = ({
2239
2363
  if (openProp == null) setInternalOpen((o) => !o);
2240
2364
  onOpenChange?.(!open);
2241
2365
  };
2242
- return /* @__PURE__ */ jsxs17("div", { className: cn("border-b border-border last:border-0", className), children: [
2243
- /* @__PURE__ */ jsxs17(
2366
+ return /* @__PURE__ */ jsxs18("div", { className: cn("border-b border-border last:border-0", className), children: [
2367
+ /* @__PURE__ */ jsxs18(
2244
2368
  "button",
2245
2369
  {
2246
2370
  type: "button",
@@ -2249,16 +2373,16 @@ var ExpandableSection = ({
2249
2373
  "aria-controls": panelId,
2250
2374
  className: "flex w-full items-center justify-between gap-3 bg-transparent px-4 py-3 text-left hover:bg-transparent active:bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-foreground/10",
2251
2375
  children: [
2252
- /* @__PURE__ */ jsxs17("span", { className: "flex min-w-0 items-center gap-3", children: [
2253
- icon ? /* @__PURE__ */ jsx22("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
2254
- /* @__PURE__ */ jsx22("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
2255
- count != null ? /* @__PURE__ */ jsx22("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
2376
+ /* @__PURE__ */ jsxs18("span", { className: "flex min-w-0 items-center gap-3", children: [
2377
+ icon ? /* @__PURE__ */ jsx23("span", { className: "flex size-8 items-center justify-center rounded-lg border border-border bg-muted text-muted-foreground", children: icon }) : null,
2378
+ /* @__PURE__ */ jsx23("span", { className: "truncate text-sm font-medium text-foreground", children: title }),
2379
+ count != null ? /* @__PURE__ */ jsx23("span", { className: "rounded-full border border-border bg-muted px-2 py-0.5 text-xs text-muted-foreground", children: count }) : null
2256
2380
  ] }),
2257
- /* @__PURE__ */ jsx22(Chevron, { open })
2381
+ /* @__PURE__ */ jsx23(Chevron, { open })
2258
2382
  ]
2259
2383
  }
2260
2384
  ),
2261
- /* @__PURE__ */ jsx22(AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ jsx22(
2385
+ /* @__PURE__ */ jsx23(AnimatePresence, { initial: false, children: open ? /* @__PURE__ */ jsx23(
2262
2386
  motion2.div,
2263
2387
  {
2264
2388
  id: panelId,
@@ -2267,7 +2391,7 @@ var ExpandableSection = ({
2267
2391
  exit: reduceMotion ? void 0 : { height: 0, opacity: 0 },
2268
2392
  transition: { duration: 0.2, ease: "easeOut" },
2269
2393
  className: "overflow-hidden",
2270
- children: /* @__PURE__ */ jsx22("div", { className: "bg-muted/20", children })
2394
+ children: /* @__PURE__ */ jsx23("div", { className: "bg-muted/20", children })
2271
2395
  },
2272
2396
  "body"
2273
2397
  ) : null })
@@ -2275,7 +2399,7 @@ var ExpandableSection = ({
2275
2399
  };
2276
2400
 
2277
2401
  // src/app/surfaces/ResourceCard.tsx
2278
- import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
2402
+ import { Fragment as Fragment3, jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
2279
2403
  var resourceCardShellClass = cn(
2280
2404
  "flex min-h-[8.5rem] flex-col rounded-2xl p-4 text-left font-normal",
2281
2405
  TIMBAL_V2_ELEVATED_SURFACE
@@ -2300,35 +2424,35 @@ var ResourceCard = ({
2300
2424
  ariaLabel,
2301
2425
  className
2302
2426
  }) => {
2303
- const body = /* @__PURE__ */ jsxs18(Fragment3, { children: [
2304
- /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-3", children: [
2305
- media ? /* @__PURE__ */ jsx23("span", { className: mediaShellClass, children: media }) : null,
2306
- /* @__PURE__ */ jsxs18("div", { className: "min-w-0 flex-1 pt-0.5", children: [
2307
- /* @__PURE__ */ jsx23("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
2308
- subtitle ? /* @__PURE__ */ jsx23("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
2427
+ const body = /* @__PURE__ */ jsxs19(Fragment3, { children: [
2428
+ /* @__PURE__ */ jsxs19("div", { className: "flex items-start gap-3", children: [
2429
+ media ? /* @__PURE__ */ jsx24("span", { className: mediaShellClass, children: media }) : null,
2430
+ /* @__PURE__ */ jsxs19("div", { className: "min-w-0 flex-1 pt-0.5", children: [
2431
+ /* @__PURE__ */ jsx24("p", { className: "truncate text-sm font-normal leading-snug text-foreground", children: title }),
2432
+ subtitle ? /* @__PURE__ */ jsx24("p", { className: "mt-1 line-clamp-2 text-xs font-normal text-muted-foreground", children: subtitle }) : null
2309
2433
  ] }),
2310
- badge ? /* @__PURE__ */ jsx23("span", { className: "shrink-0 pt-0.5", children: badge }) : null
2434
+ badge ? /* @__PURE__ */ jsx24("span", { className: "shrink-0 pt-0.5", children: badge }) : null
2311
2435
  ] }),
2312
- footer || action ? /* @__PURE__ */ jsxs18("div", { className: "mt-auto flex items-center justify-between gap-3 border-t border-border/40 pt-3 text-xs font-normal text-muted-foreground", children: [
2313
- /* @__PURE__ */ jsx23("span", { className: "min-w-0 truncate", children: footer }),
2314
- action ? /* @__PURE__ */ jsx23("span", { className: "shrink-0 opacity-80", children: action }) : null
2436
+ footer || action ? /* @__PURE__ */ jsxs19("div", { className: "mt-auto flex items-center justify-between gap-3 border-t border-border/40 pt-3 text-xs font-normal text-muted-foreground", children: [
2437
+ /* @__PURE__ */ jsx24("span", { className: "min-w-0 truncate", children: footer }),
2438
+ action ? /* @__PURE__ */ jsx24("span", { className: "shrink-0 opacity-80", children: action }) : null
2315
2439
  ] }) : null
2316
2440
  ] });
2317
2441
  if (onClick) {
2318
- return /* @__PURE__ */ jsx23("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
2442
+ return /* @__PURE__ */ jsx24("button", { type: "button", onClick, "aria-label": ariaLabel, className: cn(resourceCardInteractiveClass, className), children: body });
2319
2443
  }
2320
- return /* @__PURE__ */ jsx23("article", { className: cn(resourceCardShellClass, className), children: body });
2444
+ return /* @__PURE__ */ jsx24("article", { className: cn(resourceCardShellClass, className), children: body });
2321
2445
  };
2322
2446
 
2323
2447
  // src/app/settings/SettingsSection.tsx
2324
- import { jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
2448
+ import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
2325
2449
  var SettingsSectionHeader = ({
2326
2450
  title,
2327
2451
  description,
2328
2452
  className
2329
- }) => /* @__PURE__ */ jsxs19("div", { className: cn("flex flex-col", className), children: [
2330
- /* @__PURE__ */ jsx24("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
2331
- description ? /* @__PURE__ */ jsx24("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
2453
+ }) => /* @__PURE__ */ jsxs20("div", { className: cn("flex flex-col", className), children: [
2454
+ /* @__PURE__ */ jsx25("h3", { className: "text-[17px] font-medium leading-tight text-foreground", children: title }),
2455
+ description ? /* @__PURE__ */ jsx25("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null
2332
2456
  ] });
2333
2457
  var SettingsSection = ({
2334
2458
  title,
@@ -2337,7 +2461,7 @@ var SettingsSection = ({
2337
2461
  children,
2338
2462
  noBorderTop = false,
2339
2463
  className
2340
- }) => /* @__PURE__ */ jsxs19(
2464
+ }) => /* @__PURE__ */ jsxs20(
2341
2465
  "section",
2342
2466
  {
2343
2467
  className: cn(
@@ -2346,18 +2470,18 @@ var SettingsSection = ({
2346
2470
  className
2347
2471
  ),
2348
2472
  children: [
2349
- /* @__PURE__ */ jsxs19("div", { className: "min-w-0", children: [
2350
- /* @__PURE__ */ jsx24("h2", { className: "text-sm font-medium text-foreground", children: title }),
2351
- description ? /* @__PURE__ */ jsx24("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
2352
- descriptionFooter ? /* @__PURE__ */ jsx24("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
2473
+ /* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
2474
+ /* @__PURE__ */ jsx25("h2", { className: "text-sm font-medium text-foreground", children: title }),
2475
+ description ? /* @__PURE__ */ jsx25("p", { className: "mt-1 text-sm text-muted-foreground", children: description }) : null,
2476
+ descriptionFooter ? /* @__PURE__ */ jsx25("div", { className: "mt-3 min-w-0", children: descriptionFooter }) : null
2353
2477
  ] }),
2354
- /* @__PURE__ */ jsx24("div", { className: "min-w-0 space-y-3", children })
2478
+ /* @__PURE__ */ jsx25("div", { className: "min-w-0 space-y-3", children })
2355
2479
  ]
2356
2480
  }
2357
2481
  );
2358
2482
 
2359
2483
  // src/app/settings/FieldRow.tsx
2360
- import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
2484
+ import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
2361
2485
  var FieldRow = ({
2362
2486
  label,
2363
2487
  children,
@@ -2367,7 +2491,7 @@ var FieldRow = ({
2367
2491
  className
2368
2492
  }) => {
2369
2493
  if (inline) {
2370
- return /* @__PURE__ */ jsxs20(
2494
+ return /* @__PURE__ */ jsxs21(
2371
2495
  "div",
2372
2496
  {
2373
2497
  className: cn(
@@ -2375,8 +2499,8 @@ var FieldRow = ({
2375
2499
  className
2376
2500
  ),
2377
2501
  children: [
2378
- /* @__PURE__ */ jsxs20("div", { className: "min-w-0", children: [
2379
- /* @__PURE__ */ jsx25(
2502
+ /* @__PURE__ */ jsxs21("div", { className: "min-w-0", children: [
2503
+ /* @__PURE__ */ jsx26(
2380
2504
  "label",
2381
2505
  {
2382
2506
  htmlFor,
@@ -2384,17 +2508,17 @@ var FieldRow = ({
2384
2508
  children: label
2385
2509
  }
2386
2510
  ),
2387
- description ? /* @__PURE__ */ jsx25("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
2511
+ description ? /* @__PURE__ */ jsx26("p", { className: "mt-0.5 text-xs text-muted-foreground", children: description }) : null
2388
2512
  ] }),
2389
- /* @__PURE__ */ jsx25("div", { className: "shrink-0", children })
2513
+ /* @__PURE__ */ jsx26("div", { className: "shrink-0", children })
2390
2514
  ]
2391
2515
  }
2392
2516
  );
2393
2517
  }
2394
- return /* @__PURE__ */ jsxs20("div", { className: cn("flex flex-col gap-1.5", className), children: [
2395
- /* @__PURE__ */ jsx25("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
2518
+ return /* @__PURE__ */ jsxs21("div", { className: cn("flex flex-col gap-1.5", className), children: [
2519
+ /* @__PURE__ */ jsx26("label", { htmlFor, className: "text-sm font-medium text-foreground", children: label }),
2396
2520
  children,
2397
- description ? /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted-foreground", children: description }) : null
2521
+ description ? /* @__PURE__ */ jsx26("p", { className: "text-xs text-muted-foreground", children: description }) : null
2398
2522
  ] });
2399
2523
  };
2400
2524
 
@@ -2402,7 +2526,7 @@ var FieldRow = ({
2402
2526
  import { useEffect, useState as useState3 } from "react";
2403
2527
  import { createPortal } from "react-dom";
2404
2528
  import { AnimatePresence as AnimatePresence2, motion as motion3, useReducedMotion as useReducedMotion3 } from "motion/react";
2405
- import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
2529
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
2406
2530
  var FloatingUnsavedChangesBar = ({
2407
2531
  visible,
2408
2532
  message = "Unsaved changes",
@@ -2420,7 +2544,7 @@ var FloatingUnsavedChangesBar = ({
2420
2544
  useEffect(() => setMounted(true), []);
2421
2545
  if (!mounted || typeof document === "undefined") return null;
2422
2546
  return createPortal(
2423
- /* @__PURE__ */ jsx26(AnimatePresence2, { children: visible ? /* @__PURE__ */ jsx26("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsxs21(
2547
+ /* @__PURE__ */ jsx27(AnimatePresence2, { children: visible ? /* @__PURE__ */ jsx27("div", { className: "pointer-events-none fixed inset-x-0 bottom-5 z-50 flex justify-center px-4", children: /* @__PURE__ */ jsxs22(
2424
2548
  motion3.div,
2425
2549
  {
2426
2550
  role: "region",
@@ -2434,10 +2558,10 @@ var FloatingUnsavedChangesBar = ({
2434
2558
  className
2435
2559
  ),
2436
2560
  children: [
2437
- /* @__PURE__ */ jsx26("span", { className: "text-sm text-muted-foreground", children: message }),
2438
- /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-1.5", children: [
2439
- /* @__PURE__ */ jsx26(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
2440
- /* @__PURE__ */ jsx26(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
2561
+ /* @__PURE__ */ jsx27("span", { className: "text-sm text-muted-foreground", children: message }),
2562
+ /* @__PURE__ */ jsxs22("span", { className: "flex items-center gap-1.5", children: [
2563
+ /* @__PURE__ */ jsx27(Button, { variant: "ghost", size: "sm", onClick: onDiscard, disabled: isSaving, children: discardLabel }),
2564
+ /* @__PURE__ */ jsx27(Button, { size: "sm", onClick: onSave, disabled: saveDisabled || isSaving, children: isSaving ? "Saving\u2026" : saveLabel })
2441
2565
  ] })
2442
2566
  ]
2443
2567
  }
@@ -2447,13 +2571,13 @@ var FloatingUnsavedChangesBar = ({
2447
2571
  };
2448
2572
 
2449
2573
  // src/app/settings/DangerZone.tsx
2450
- import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
2574
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
2451
2575
  var DangerZoneAction = ({
2452
2576
  title,
2453
2577
  description,
2454
2578
  action,
2455
2579
  className
2456
- }) => /* @__PURE__ */ jsxs22(
2580
+ }) => /* @__PURE__ */ jsxs23(
2457
2581
  "div",
2458
2582
  {
2459
2583
  className: cn(
@@ -2461,11 +2585,11 @@ var DangerZoneAction = ({
2461
2585
  className
2462
2586
  ),
2463
2587
  children: [
2464
- /* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
2465
- /* @__PURE__ */ jsx27("p", { className: "text-sm font-medium text-foreground", children: title }),
2466
- description ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2588
+ /* @__PURE__ */ jsxs23("div", { className: "min-w-0", children: [
2589
+ /* @__PURE__ */ jsx28("p", { className: "text-sm font-medium text-foreground", children: title }),
2590
+ description ? /* @__PURE__ */ jsx28("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2467
2591
  ] }),
2468
- /* @__PURE__ */ jsx27("div", { className: "shrink-0", children: action })
2592
+ /* @__PURE__ */ jsx28("div", { className: "shrink-0", children: action })
2469
2593
  ]
2470
2594
  }
2471
2595
  );
@@ -2474,7 +2598,7 @@ var DangerZone = ({
2474
2598
  description,
2475
2599
  children,
2476
2600
  className
2477
- }) => /* @__PURE__ */ jsxs22(
2601
+ }) => /* @__PURE__ */ jsxs23(
2478
2602
  "section",
2479
2603
  {
2480
2604
  className: cn(
@@ -2482,18 +2606,18 @@ var DangerZone = ({
2482
2606
  className
2483
2607
  ),
2484
2608
  children: [
2485
- (title || description) && /* @__PURE__ */ jsxs22("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
2486
- title ? /* @__PURE__ */ jsx27("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
2487
- description ? /* @__PURE__ */ jsx27("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2609
+ (title || description) && /* @__PURE__ */ jsxs23("header", { className: "border-b border-destructive/20 bg-destructive/5 px-4 py-3", children: [
2610
+ title ? /* @__PURE__ */ jsx28("h3", { className: "text-sm font-semibold text-destructive", children: title }) : null,
2611
+ description ? /* @__PURE__ */ jsx28("p", { className: "mt-0.5 text-sm text-muted-foreground", children: description }) : null
2488
2612
  ] }),
2489
- /* @__PURE__ */ jsx27("div", { className: "divide-y divide-border bg-card", children })
2613
+ /* @__PURE__ */ jsx28("div", { className: "divide-y divide-border bg-card", children })
2490
2614
  ]
2491
2615
  }
2492
2616
  );
2493
2617
 
2494
2618
  // src/app/integrations/IntegrationCard.tsx
2495
2619
  import { useId as useId2 } from "react";
2496
- import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
2620
+ import { Fragment as Fragment4, jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2497
2621
  var INTEGRATION_CATALOG_CARD_HEIGHT_CLASS = "h-[12.25rem] min-h-[12.25rem] max-h-[12.25rem]";
2498
2622
  var statusLabel = {
2499
2623
  available: null,
@@ -2534,12 +2658,12 @@ var IntegrationCard = ({
2534
2658
  const titleId = useId2();
2535
2659
  const locked = status === "locked";
2536
2660
  const dimmed = status === "disabled" || locked;
2537
- const body = /* @__PURE__ */ jsxs23("div", { className: "flex h-full min-h-0 flex-col", children: [
2538
- /* @__PURE__ */ jsxs23("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
2539
- logo ? /* @__PURE__ */ jsx28("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
2540
- /* @__PURE__ */ jsx28("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start justify-between gap-2", children: [
2541
- /* @__PURE__ */ jsxs23("div", { className: "min-w-0", children: [
2542
- /* @__PURE__ */ jsx28(
2661
+ const body = /* @__PURE__ */ jsxs24("div", { className: "flex h-full min-h-0 flex-col", children: [
2662
+ /* @__PURE__ */ jsxs24("div", { className: "flex shrink-0 items-start gap-3 pr-2", children: [
2663
+ logo ? /* @__PURE__ */ jsx29("span", { className: logoShellClass, "aria-hidden": Boolean(ariaLabel), children: logo }) : null,
2664
+ /* @__PURE__ */ jsx29("div", { className: "min-w-0 flex-1 pt-0.5", children: /* @__PURE__ */ jsxs24("div", { className: "flex items-start justify-between gap-2", children: [
2665
+ /* @__PURE__ */ jsxs24("div", { className: "min-w-0", children: [
2666
+ /* @__PURE__ */ jsx29(
2543
2667
  "h4",
2544
2668
  {
2545
2669
  id: onClick && !action ? void 0 : titleId,
@@ -2547,12 +2671,12 @@ var IntegrationCard = ({
2547
2671
  children: name
2548
2672
  }
2549
2673
  ),
2550
- statusLabel[status] ? /* @__PURE__ */ jsx28("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
2674
+ statusLabel[status] ? /* @__PURE__ */ jsx29("p", { className: "mt-0.5 text-xs text-muted-foreground", children: statusLabel[status] }) : null
2551
2675
  ] }),
2552
- badge ? /* @__PURE__ */ jsx28("span", { className: "shrink-0", children: badge }) : null
2676
+ badge ? /* @__PURE__ */ jsx29("span", { className: "shrink-0", children: badge }) : null
2553
2677
  ] }) })
2554
2678
  ] }),
2555
- description ? /* @__PURE__ */ jsx28(
2679
+ description ? /* @__PURE__ */ jsx29(
2556
2680
  "p",
2557
2681
  {
2558
2682
  className: cn(
@@ -2562,9 +2686,9 @@ var IntegrationCard = ({
2562
2686
  children: description
2563
2687
  }
2564
2688
  ) : null,
2565
- action ? /* @__PURE__ */ jsxs23(Fragment4, { children: [
2566
- /* @__PURE__ */ jsx28("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
2567
- /* @__PURE__ */ jsx28("div", { className: "relative mt-3 shrink-0", children: action })
2689
+ action ? /* @__PURE__ */ jsxs24(Fragment4, { children: [
2690
+ /* @__PURE__ */ jsx29("div", { className: "min-h-0 flex-1", "aria-hidden": true }),
2691
+ /* @__PURE__ */ jsx29("div", { className: "relative mt-3 shrink-0", children: action })
2568
2692
  ] }) : null
2569
2693
  ] });
2570
2694
  const shellClass3 = cn(
@@ -2574,7 +2698,7 @@ var IntegrationCard = ({
2574
2698
  className
2575
2699
  );
2576
2700
  if (onClick && !action) {
2577
- return /* @__PURE__ */ jsx28(
2701
+ return /* @__PURE__ */ jsx29(
2578
2702
  "button",
2579
2703
  {
2580
2704
  type: "button",
@@ -2591,12 +2715,12 @@ var IntegrationCard = ({
2591
2715
  }
2592
2716
  );
2593
2717
  }
2594
- return /* @__PURE__ */ jsx28("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
2718
+ return /* @__PURE__ */ jsx29("article", { className: shellClass3, "aria-labelledby": titleId, children: body });
2595
2719
  };
2596
2720
 
2597
2721
  // src/app/integrations/IntegrationsEmptyState.tsx
2598
2722
  import { useId as useId3 } from "react";
2599
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
2723
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
2600
2724
  var IntegrationsEmptyState = ({
2601
2725
  title = "No integrations yet",
2602
2726
  description = "Connect a provider to start syncing data and powering your workforce.",
@@ -2605,7 +2729,7 @@ var IntegrationsEmptyState = ({
2605
2729
  className
2606
2730
  }) => {
2607
2731
  const titleId = useId3();
2608
- return /* @__PURE__ */ jsxs24(
2732
+ return /* @__PURE__ */ jsxs25(
2609
2733
  "section",
2610
2734
  {
2611
2735
  className: cn(
@@ -2615,7 +2739,7 @@ var IntegrationsEmptyState = ({
2615
2739
  ),
2616
2740
  "aria-labelledby": titleId,
2617
2741
  children: [
2618
- icon ? /* @__PURE__ */ jsx29(
2742
+ icon ? /* @__PURE__ */ jsx30(
2619
2743
  "span",
2620
2744
  {
2621
2745
  className: cn(
@@ -2627,21 +2751,21 @@ var IntegrationsEmptyState = ({
2627
2751
  children: icon
2628
2752
  }
2629
2753
  ) : null,
2630
- /* @__PURE__ */ jsx29("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
2631
- description ? /* @__PURE__ */ jsx29("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
2632
- action ? /* @__PURE__ */ jsx29("div", { className: "mt-1", children: action }) : null
2754
+ /* @__PURE__ */ jsx30("h3", { id: titleId, className: "text-base font-normal text-foreground", children: title }),
2755
+ description ? /* @__PURE__ */ jsx30("p", { className: "max-w-sm text-sm text-muted-foreground", children: description }) : null,
2756
+ action ? /* @__PURE__ */ jsx30("div", { className: "mt-1", children: action }) : null
2633
2757
  ]
2634
2758
  }
2635
2759
  );
2636
2760
  };
2637
2761
 
2638
2762
  // src/app/integrations/PlanBadge.tsx
2639
- import { jsx as jsx30 } from "react/jsx-runtime";
2763
+ import { jsx as jsx31 } from "react/jsx-runtime";
2640
2764
  var planBadgeClass = "inline-flex h-5 max-w-full shrink-0 items-center rounded-md border border-border bg-muted/90 px-2 text-[11px] font-normal text-muted-foreground dark:border-white/10 dark:bg-white/5 dark:text-muted-foreground";
2641
- var PlanBadge = ({ children, className }) => /* @__PURE__ */ jsx30("span", { className: cn(planBadgeClass, className), children });
2765
+ var PlanBadge = ({ children, className }) => /* @__PURE__ */ jsx31("span", { className: cn(planBadgeClass, className), children });
2642
2766
 
2643
2767
  // src/app/integrations/ConnectionRow.tsx
2644
- import { Fragment as Fragment5, jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
2768
+ import { Fragment as Fragment5, jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
2645
2769
  var logoShellClass2 = cn(
2646
2770
  "flex size-9 shrink-0 items-center justify-center overflow-hidden rounded-lg",
2647
2771
  TIMBAL_V2_LOGO_TILE
@@ -2656,14 +2780,14 @@ var ConnectionRow = ({
2656
2780
  ariaLabel,
2657
2781
  className
2658
2782
  }) => {
2659
- const inner = /* @__PURE__ */ jsxs25(Fragment5, { children: [
2660
- logo ? /* @__PURE__ */ jsx31("span", { className: logoShellClass2, children: logo }) : null,
2661
- /* @__PURE__ */ jsxs25("div", { className: "min-w-0 flex-1", children: [
2662
- /* @__PURE__ */ jsx31("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
2663
- meta ? /* @__PURE__ */ jsx31("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
2783
+ const inner = /* @__PURE__ */ jsxs26(Fragment5, { children: [
2784
+ logo ? /* @__PURE__ */ jsx32("span", { className: logoShellClass2, children: logo }) : null,
2785
+ /* @__PURE__ */ jsxs26("div", { className: "min-w-0 flex-1", children: [
2786
+ /* @__PURE__ */ jsx32("p", { className: "truncate text-sm font-normal text-foreground", children: name }),
2787
+ meta ? /* @__PURE__ */ jsx32("p", { className: "truncate text-xs text-muted-foreground", children: meta }) : null
2664
2788
  ] }),
2665
- badge ? /* @__PURE__ */ jsx31("span", { className: "shrink-0", children: badge }) : null,
2666
- action ? /* @__PURE__ */ jsx31("span", { className: "shrink-0", children: action }) : null
2789
+ badge ? /* @__PURE__ */ jsx32("span", { className: "shrink-0", children: badge }) : null,
2790
+ action ? /* @__PURE__ */ jsx32("span", { className: "shrink-0", children: action }) : null
2667
2791
  ] });
2668
2792
  const rowClass2 = cn(
2669
2793
  "flex w-full items-center gap-3 px-4 py-3 text-left",
@@ -2671,7 +2795,7 @@ var ConnectionRow = ({
2671
2795
  className
2672
2796
  );
2673
2797
  if (onClick) {
2674
- return /* @__PURE__ */ jsx31(
2798
+ return /* @__PURE__ */ jsx32(
2675
2799
  "button",
2676
2800
  {
2677
2801
  type: "button",
@@ -2683,7 +2807,7 @@ var ConnectionRow = ({
2683
2807
  }
2684
2808
  );
2685
2809
  }
2686
- return /* @__PURE__ */ jsx31("div", { role: "listitem", className: rowClass2, children: inner });
2810
+ return /* @__PURE__ */ jsx32("div", { role: "listitem", className: rowClass2, children: inner });
2687
2811
  };
2688
2812
  var connectionRowListClass = cn(
2689
2813
  "overflow-hidden rounded-2xl",
@@ -2691,12 +2815,12 @@ var connectionRowListClass = cn(
2691
2815
  );
2692
2816
 
2693
2817
  // src/app/integrations/ConnectionRowList.tsx
2694
- import { jsx as jsx32 } from "react/jsx-runtime";
2818
+ import { jsx as jsx33 } from "react/jsx-runtime";
2695
2819
  var ConnectionRowList = ({
2696
2820
  children,
2697
2821
  "aria-label": ariaLabel = "Connected integrations",
2698
2822
  className
2699
- }) => /* @__PURE__ */ jsx32(
2823
+ }) => /* @__PURE__ */ jsx33(
2700
2824
  "div",
2701
2825
  {
2702
2826
  role: "list",
@@ -2707,7 +2831,7 @@ var ConnectionRowList = ({
2707
2831
  );
2708
2832
 
2709
2833
  // src/app/navigation/SubNav.tsx
2710
- import { jsx as jsx33 } from "react/jsx-runtime";
2834
+ import { jsx as jsx34 } from "react/jsx-runtime";
2711
2835
  var SubNav = ({
2712
2836
  items,
2713
2837
  activeId,
@@ -2716,7 +2840,7 @@ var SubNav = ({
2716
2840
  "aria-label": ariaLabel = "Section navigation",
2717
2841
  layoutId
2718
2842
  }) => {
2719
- return /* @__PURE__ */ jsx33("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx33(
2843
+ return /* @__PURE__ */ jsx34("nav", { className: cn("aui-app-sub-nav", className), "aria-label": ariaLabel, children: /* @__PURE__ */ jsx34(
2720
2844
  PillSegmentedTabs,
2721
2845
  {
2722
2846
  value: activeId,
@@ -2730,13 +2854,13 @@ var SubNav = ({
2730
2854
  };
2731
2855
 
2732
2856
  // src/app/navigation/Breadcrumbs.tsx
2733
- import { jsx as jsx34, jsxs as jsxs26 } from "react/jsx-runtime";
2857
+ import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2734
2858
  var Breadcrumbs = ({ items, className }) => {
2735
- return /* @__PURE__ */ jsx34("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx34("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
2859
+ return /* @__PURE__ */ jsx35("nav", { className: cn("aui-app-breadcrumbs", appBreadcrumbsClass, className), "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx35("ol", { className: "flex flex-wrap items-center gap-1.5", children: items.map((item, index) => {
2736
2860
  const isLast = index === items.length - 1;
2737
- return /* @__PURE__ */ jsxs26("li", { className: "inline-flex items-center gap-1.5", children: [
2738
- index > 0 ? /* @__PURE__ */ jsx34("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
2739
- isLast ? /* @__PURE__ */ jsx34("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx34("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ jsx34(
2861
+ return /* @__PURE__ */ jsxs27("li", { className: "inline-flex items-center gap-1.5", children: [
2862
+ index > 0 ? /* @__PURE__ */ jsx35("span", { className: "text-muted-foreground/50", "aria-hidden": true, children: "/" }) : null,
2863
+ isLast ? /* @__PURE__ */ jsx35("span", { className: "text-foreground", "aria-current": "page", children: item.label }) : item.href ? /* @__PURE__ */ jsx35("a", { href: item.href, className: appBreadcrumbLinkClass, children: item.label }) : /* @__PURE__ */ jsx35(
2740
2864
  "button",
2741
2865
  {
2742
2866
  type: "button",
@@ -2750,7 +2874,8 @@ var Breadcrumbs = ({ items, className }) => {
2750
2874
  };
2751
2875
 
2752
2876
  // src/app/forms/Field.tsx
2753
- import { jsx as jsx35, jsxs as jsxs27 } from "react/jsx-runtime";
2877
+ import { useId as useId4 } from "react";
2878
+ import { jsx as jsx36, jsxs as jsxs28 } from "react/jsx-runtime";
2754
2879
  var Field = ({
2755
2880
  label,
2756
2881
  hint,
@@ -2759,11 +2884,11 @@ var Field = ({
2759
2884
  className,
2760
2885
  htmlFor
2761
2886
  }) => {
2762
- return /* @__PURE__ */ jsxs27("div", { className: cn("aui-app-field", appFieldClass, className), children: [
2763
- /* @__PURE__ */ jsx35("label", { className: appFieldLabelClass, htmlFor, children: label }),
2887
+ return /* @__PURE__ */ jsxs28("div", { className: cn("aui-app-field", appFieldClass, className), children: [
2888
+ /* @__PURE__ */ jsx36("label", { className: appFieldLabelClass, htmlFor, children: label }),
2764
2889
  children,
2765
- hint && !error ? /* @__PURE__ */ jsx35("p", { className: appFieldHintClass, children: hint }) : null,
2766
- error ? /* @__PURE__ */ jsx35("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
2890
+ hint && !error ? /* @__PURE__ */ jsx36("p", { className: appFieldHintClass, children: hint }) : null,
2891
+ error ? /* @__PURE__ */ jsx36("p", { className: "text-xs text-destructive", role: "alert", children: error }) : null
2767
2892
  ] });
2768
2893
  };
2769
2894
  var FieldInput = ({
@@ -2775,8 +2900,9 @@ var FieldInput = ({
2775
2900
  id,
2776
2901
  ...inputProps
2777
2902
  }) => {
2778
- const inputId = id ?? inputProps.name;
2779
- return /* @__PURE__ */ jsx35(
2903
+ const autoId = useId4();
2904
+ const inputId = id ?? inputProps.name ?? autoId;
2905
+ return /* @__PURE__ */ jsx36(
2780
2906
  Field,
2781
2907
  {
2782
2908
  label,
@@ -2784,7 +2910,7 @@ var FieldInput = ({
2784
2910
  error,
2785
2911
  htmlFor: inputId,
2786
2912
  className: fieldClassName,
2787
- children: /* @__PURE__ */ jsx35(
2913
+ children: /* @__PURE__ */ jsx36(
2788
2914
  "input",
2789
2915
  {
2790
2916
  id: inputId,
@@ -2798,7 +2924,8 @@ var FieldInput = ({
2798
2924
  };
2799
2925
 
2800
2926
  // src/app/forms/FieldTextarea.tsx
2801
- import { jsx as jsx36 } from "react/jsx-runtime";
2927
+ import { useId as useId5 } from "react";
2928
+ import { jsx as jsx37 } from "react/jsx-runtime";
2802
2929
  var textareaClass = cn(
2803
2930
  appInputClass,
2804
2931
  "min-h-[5.5rem] resize-y py-2.5 leading-relaxed"
@@ -2812,8 +2939,9 @@ var FieldTextarea = ({
2812
2939
  id,
2813
2940
  ...props
2814
2941
  }) => {
2815
- const textareaId = id ?? props.name;
2816
- return /* @__PURE__ */ jsx36(
2942
+ const autoId = useId5();
2943
+ const textareaId = id ?? props.name ?? autoId;
2944
+ return /* @__PURE__ */ jsx37(
2817
2945
  Field,
2818
2946
  {
2819
2947
  label,
@@ -2821,7 +2949,7 @@ var FieldTextarea = ({
2821
2949
  error,
2822
2950
  htmlFor: textareaId,
2823
2951
  className: fieldClassName,
2824
- children: /* @__PURE__ */ jsx36(
2952
+ children: /* @__PURE__ */ jsx37(
2825
2953
  "textarea",
2826
2954
  {
2827
2955
  id: textareaId,
@@ -2835,8 +2963,9 @@ var FieldTextarea = ({
2835
2963
  };
2836
2964
 
2837
2965
  // src/app/forms/FieldSelect.tsx
2966
+ import { useId as useId6 } from "react";
2838
2967
  import { ChevronDownIcon } from "lucide-react";
2839
- import { jsx as jsx37, jsxs as jsxs28 } from "react/jsx-runtime";
2968
+ import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
2840
2969
  var selectWrapClass = "relative";
2841
2970
  var selectClass = cn(
2842
2971
  appInputClass,
@@ -2852,8 +2981,9 @@ var FieldSelect = ({
2852
2981
  id,
2853
2982
  ...props
2854
2983
  }) => {
2855
- const selectId = id ?? props.name;
2856
- return /* @__PURE__ */ jsx37(
2984
+ const autoId = useId6();
2985
+ const selectId = id ?? props.name ?? autoId;
2986
+ return /* @__PURE__ */ jsx38(
2857
2987
  Field,
2858
2988
  {
2859
2989
  label,
@@ -2861,8 +2991,8 @@ var FieldSelect = ({
2861
2991
  error,
2862
2992
  htmlFor: selectId,
2863
2993
  className: fieldClassName,
2864
- children: /* @__PURE__ */ jsxs28("div", { className: selectWrapClass, children: [
2865
- /* @__PURE__ */ jsx37(
2994
+ children: /* @__PURE__ */ jsxs29("div", { className: selectWrapClass, children: [
2995
+ /* @__PURE__ */ jsx38(
2866
2996
  "select",
2867
2997
  {
2868
2998
  id: selectId,
@@ -2872,7 +3002,7 @@ var FieldSelect = ({
2872
3002
  children
2873
3003
  }
2874
3004
  ),
2875
- /* @__PURE__ */ jsx37(
3005
+ /* @__PURE__ */ jsx38(
2876
3006
  ChevronDownIcon,
2877
3007
  {
2878
3008
  className: "pointer-events-none absolute top-1/2 right-3 size-4 -translate-y-1/2 text-muted-foreground",
@@ -2885,7 +3015,8 @@ var FieldSelect = ({
2885
3015
  };
2886
3016
 
2887
3017
  // src/app/forms/FieldSwitch.tsx
2888
- import { jsx as jsx38, jsxs as jsxs29 } from "react/jsx-runtime";
3018
+ import { useId as useId7 } from "react";
3019
+ import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
2889
3020
  var trackClass = cn(
2890
3021
  "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-[background,box-shadow,border-color] duration-200",
2891
3022
  "peer-focus-visible:ring-2 peer-focus-visible:ring-foreground/10",
@@ -2905,8 +3036,9 @@ var FieldSwitch = ({
2905
3036
  id,
2906
3037
  ...props
2907
3038
  }) => {
2908
- const inputId = id ?? props.name ?? "switch";
2909
- return /* @__PURE__ */ jsxs29(
3039
+ const autoId = useId7();
3040
+ const inputId = id ?? props.name ?? autoId;
3041
+ return /* @__PURE__ */ jsxs30(
2910
3042
  "label",
2911
3043
  {
2912
3044
  className: cn(
@@ -2915,8 +3047,8 @@ var FieldSwitch = ({
2915
3047
  ),
2916
3048
  htmlFor: inputId,
2917
3049
  children: [
2918
- /* @__PURE__ */ jsxs29("span", { className: "relative mt-0.5", children: [
2919
- /* @__PURE__ */ jsx38(
3050
+ /* @__PURE__ */ jsxs30("span", { className: "relative mt-0.5", children: [
3051
+ /* @__PURE__ */ jsx39(
2920
3052
  "input",
2921
3053
  {
2922
3054
  id: inputId,
@@ -2926,11 +3058,11 @@ var FieldSwitch = ({
2926
3058
  ...props
2927
3059
  }
2928
3060
  ),
2929
- /* @__PURE__ */ jsx38("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ jsx38("span", { className: thumbClass }) })
3061
+ /* @__PURE__ */ jsx39("span", { className: trackClass, "aria-hidden": true, children: /* @__PURE__ */ jsx39("span", { className: thumbClass }) })
2930
3062
  ] }),
2931
- /* @__PURE__ */ jsxs29("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
2932
- /* @__PURE__ */ jsx38("span", { className: "text-sm font-medium text-foreground", children: label }),
2933
- description ? /* @__PURE__ */ jsx38("span", { className: "text-xs text-muted-foreground", children: description }) : null
3063
+ /* @__PURE__ */ jsxs30("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
3064
+ /* @__PURE__ */ jsx39("span", { className: "text-sm font-medium text-foreground", children: label }),
3065
+ description ? /* @__PURE__ */ jsx39("span", { className: "text-xs text-muted-foreground", children: description }) : null
2934
3066
  ] })
2935
3067
  ]
2936
3068
  }
@@ -2939,13 +3071,13 @@ var FieldSwitch = ({
2939
3071
 
2940
3072
  // src/app/forms/SearchInput.tsx
2941
3073
  import { SearchIcon } from "lucide-react";
2942
- import { jsx as jsx39, jsxs as jsxs30 } from "react/jsx-runtime";
3074
+ import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
2943
3075
  var SearchInput = ({
2944
3076
  className,
2945
3077
  placeholder = "Search\u2026",
2946
3078
  ...props
2947
3079
  }) => {
2948
- return /* @__PURE__ */ jsxs30(
3080
+ return /* @__PURE__ */ jsxs31(
2949
3081
  "label",
2950
3082
  {
2951
3083
  className: cn(
@@ -2954,8 +3086,8 @@ var SearchInput = ({
2954
3086
  className
2955
3087
  ),
2956
3088
  children: [
2957
- /* @__PURE__ */ jsx39(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
2958
- /* @__PURE__ */ jsx39(
3089
+ /* @__PURE__ */ jsx40(SearchIcon, { className: "size-4 shrink-0 text-muted-foreground", "aria-hidden": true }),
3090
+ /* @__PURE__ */ jsx40(
2959
3091
  "input",
2960
3092
  {
2961
3093
  type: "search",
@@ -2970,18 +3102,26 @@ var SearchInput = ({
2970
3102
  };
2971
3103
 
2972
3104
  // src/app/forms/FormSection.tsx
2973
- import { jsx as jsx40, jsxs as jsxs31 } from "react/jsx-runtime";
3105
+ import { jsx as jsx41, jsxs as jsxs32 } from "react/jsx-runtime";
2974
3106
  var FormSection = ({ title, children, className }) => {
2975
- return /* @__PURE__ */ jsxs31("fieldset", { className: cn("aui-app-form-section", appSectionClass, "border-0 p-0", className), children: [
2976
- title ? /* @__PURE__ */ jsx40("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
2977
- /* @__PURE__ */ jsx40("div", { className: "flex flex-col gap-4", children })
2978
- ] });
3107
+ const density = useAppDensity();
3108
+ const sectionClass = useAppDensityClass("section");
3109
+ return /* @__PURE__ */ jsxs32(
3110
+ "fieldset",
3111
+ {
3112
+ className: cn("aui-app-form-section", sectionClass, "border-0 p-0", className),
3113
+ children: [
3114
+ title ? /* @__PURE__ */ jsx41("legend", { className: cn(appSectionTitleClass, "mb-3 px-0"), children: title }) : null,
3115
+ /* @__PURE__ */ jsx41("div", { className: cn("flex flex-col", density === "compact" ? "gap-2" : "gap-4"), children })
3116
+ ]
3117
+ }
3118
+ );
2979
3119
  };
2980
3120
 
2981
3121
  // src/app/data/FilterBar.tsx
2982
- import { jsx as jsx41 } from "react/jsx-runtime";
3122
+ import { jsx as jsx42 } from "react/jsx-runtime";
2983
3123
  var FilterBar = ({ children, className }) => {
2984
- return /* @__PURE__ */ jsx41(
3124
+ return /* @__PURE__ */ jsx42(
2985
3125
  "div",
2986
3126
  {
2987
3127
  className: cn("aui-app-filter-bar", appFilterBarClass, className),
@@ -2993,14 +3133,14 @@ var FilterBar = ({ children, className }) => {
2993
3133
  };
2994
3134
 
2995
3135
  // src/app/data/FilterField.tsx
2996
- import { jsx as jsx42, jsxs as jsxs32 } from "react/jsx-runtime";
3136
+ import { jsx as jsx43, jsxs as jsxs33 } from "react/jsx-runtime";
2997
3137
  var FilterField = ({
2998
3138
  label,
2999
3139
  children,
3000
3140
  className
3001
3141
  }) => {
3002
- return /* @__PURE__ */ jsxs32("div", { className: cn("aui-app-filter-field", appFieldClass, className), children: [
3003
- label ? /* @__PURE__ */ jsx42("span", { className: appFieldLabelClass, children: label }) : null,
3142
+ return /* @__PURE__ */ jsxs33("div", { className: cn("aui-app-filter-field", appFieldClass, className), children: [
3143
+ label ? /* @__PURE__ */ jsx43("span", { className: appFieldLabelClass, children: label }) : null,
3004
3144
  children
3005
3145
  ] });
3006
3146
  };
@@ -3014,19 +3154,20 @@ import {
3014
3154
  ChevronLeftIcon,
3015
3155
  ChevronRightIcon
3016
3156
  } from "lucide-react";
3017
- import { jsx as jsx43, jsxs as jsxs33 } from "react/jsx-runtime";
3018
- var shellClass2 = "overflow-hidden rounded-xl border border-border bg-card shadow-card";
3157
+ import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
3158
+ var shellClass2 = "overflow-hidden rounded-xl border border-border bg-gradient-to-b from-elevated-from to-elevated-to shadow-card";
3019
3159
  var tableClass = "w-full border-collapse bg-transparent text-sm";
3020
- var headCellClass = "border-b border-border/60 bg-transparent px-4 py-2.5 text-left text-xs font-medium uppercase tracking-wide text-muted-foreground";
3160
+ var headRowClass = "bg-muted/40";
3161
+ var headCellClass = "border-b border-border/70 px-4 py-2.5 text-left text-[11px] font-semibold uppercase tracking-[0.04em] text-muted-foreground/90";
3021
3162
  var bodyCellClass = "border-b border-border/40 bg-transparent px-4 py-2.5 text-foreground";
3022
- var rowClass = "bg-transparent transition-colors hover:bg-foreground/[0.03] data-[clickable=true]:cursor-pointer data-[selected=true]:bg-primary/[0.04]";
3023
- var footCellClass = "border-t border-border/60 bg-transparent px-4 py-2.5 text-xs text-muted-foreground";
3163
+ var rowClass = "bg-transparent transition-colors hover:bg-muted/40 data-[clickable=true]:cursor-pointer data-[selected=true]:bg-primary/[0.06]";
3164
+ var footCellClass = "border-t border-border/60 bg-muted/20 px-4 py-2.5 text-xs text-muted-foreground";
3024
3165
  var footInnerClass = "flex flex-wrap items-center gap-2";
3025
3166
  var emptyCellClass = "bg-transparent px-4 py-10 text-center text-sm text-muted-foreground";
3026
- var sortButtonClass = "group inline-flex min-w-0 items-center gap-1.5 rounded-md -mx-1 px-1 py-0.5 text-left font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
3027
- var stickyHeadClass = "sticky top-0 z-[1] bg-card/95 shadow-[0_1px_0_0_hsl(var(--border)/0.5)] backdrop-blur-sm [&_th]:bg-card/95";
3167
+ var sortButtonClass = "group inline-flex min-w-0 items-center gap-1.5 rounded-md -mx-1 px-1 py-0.5 text-left font-semibold text-muted-foreground/90 transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
3168
+ var stickyHeadClass = "sticky top-0 z-[1] bg-muted/95 shadow-[0_1px_0_0_hsl(var(--border)/0.6)] backdrop-blur-sm";
3028
3169
  var selectCellClass = "w-10 px-4 py-2.5 align-middle";
3029
- var pagerButtonClass = "inline-flex size-7 items-center justify-center rounded-md border border-border bg-transparent text-muted-foreground transition-colors hover:bg-foreground/[0.04] hover:text-foreground disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
3170
+ var pagerButtonClass = "inline-flex size-7 items-center justify-center rounded-md border border-border bg-gradient-to-b from-elevated-from to-elevated-to text-muted-foreground shadow-card transition-colors hover:from-secondary-fill-hover-from hover:to-secondary-fill-hover-to hover:text-foreground disabled:pointer-events-none disabled:opacity-40 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-foreground/10";
3030
3171
  var alignClass = {
3031
3172
  left: "text-left",
3032
3173
  center: "text-center",
@@ -3056,12 +3197,12 @@ function SortIndicator({
3056
3197
  }) {
3057
3198
  const iconClass = "size-3.5 shrink-0 opacity-60 group-hover:opacity-100";
3058
3199
  if (!active) {
3059
- return /* @__PURE__ */ jsx43(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
3200
+ return /* @__PURE__ */ jsx44(ArrowUpDownIcon, { className: iconClass, "aria-hidden": true });
3060
3201
  }
3061
3202
  if (direction === "desc") {
3062
- return /* @__PURE__ */ jsx43(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
3203
+ return /* @__PURE__ */ jsx44(ArrowDownIcon, { className: iconClass, "aria-hidden": true });
3063
3204
  }
3064
- return /* @__PURE__ */ jsx43(ArrowUpIcon, { className: iconClass, "aria-hidden": true });
3205
+ return /* @__PURE__ */ jsx44(ArrowUpIcon, { className: iconClass, "aria-hidden": true });
3065
3206
  }
3066
3207
  function DataTable({
3067
3208
  columns,
@@ -3159,7 +3300,7 @@ function DataTable({
3159
3300
  const headPad = dense ? "px-3 py-2" : void 0;
3160
3301
  const colSpan = columns.length + (selectable ? 1 : 0);
3161
3302
  if (!loading && rows.length === 0 && emptyMode === "replace") {
3162
- return /* @__PURE__ */ jsx43(EmptyState, { title: emptyTitle, description: emptyDescription, className });
3303
+ return /* @__PURE__ */ jsx44(EmptyState, { title: emptyTitle, description: emptyDescription, className });
3163
3304
  }
3164
3305
  const allKeys = sortedRows.map(getRowKey);
3165
3306
  const allSelected = allKeys.length > 0 && allKeys.every((k) => selectedSet.has(k));
@@ -3184,10 +3325,10 @@ function DataTable({
3184
3325
  const hasPager = paginated && !loading && sortedRows.length > 0;
3185
3326
  const hasFoot = (showRowCount || footer || hasPager) && (loading || sortedRows.length > 0);
3186
3327
  const skeletonCount = loadingRows ?? pageSize ?? 5;
3187
- return /* @__PURE__ */ jsx43("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ jsx43("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs33("table", { className: tableClass, children: [
3188
- caption ? /* @__PURE__ */ jsx43("caption", { className: "sr-only", children: caption }) : null,
3189
- /* @__PURE__ */ jsx43("thead", { className: cn(stickyHeader && stickyHeadClass), children: /* @__PURE__ */ jsxs33("tr", { children: [
3190
- selectable ? /* @__PURE__ */ jsx43("th", { scope: "col", className: cn(selectCellClass, headPad), children: /* @__PURE__ */ jsx43(
3328
+ return /* @__PURE__ */ jsx44("div", { className: cn("aui-app-data-table", shellClass2, className), children: /* @__PURE__ */ jsx44("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs34("table", { className: tableClass, children: [
3329
+ caption ? /* @__PURE__ */ jsx44("caption", { className: "sr-only", children: caption }) : null,
3330
+ /* @__PURE__ */ jsx44("thead", { className: cn(headRowClass, stickyHeader && stickyHeadClass), children: /* @__PURE__ */ jsxs34("tr", { children: [
3331
+ selectable ? /* @__PURE__ */ jsx44("th", { scope: "col", className: cn(selectCellClass, headPad), children: /* @__PURE__ */ jsx44(
3191
3332
  Checkbox,
3192
3333
  {
3193
3334
  checked: headerCheckedState,
@@ -3199,19 +3340,19 @@ function DataTable({
3199
3340
  columns.map((col) => {
3200
3341
  const isSorted = sort?.columnId === col.id;
3201
3342
  const ariaSort = col.sortable ? isSorted ? sort.direction === "asc" ? "ascending" : "descending" : "none" : void 0;
3202
- const headerContent = col.sortable ? /* @__PURE__ */ jsxs33(
3343
+ const headerContent = col.sortable ? /* @__PURE__ */ jsxs34(
3203
3344
  "button",
3204
3345
  {
3205
3346
  type: "button",
3206
3347
  className: sortButtonClass,
3207
3348
  onClick: () => setSort(nextSort(sort, col.id)),
3208
3349
  children: [
3209
- /* @__PURE__ */ jsx43("span", { className: "truncate", children: col.header }),
3210
- /* @__PURE__ */ jsx43(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
3350
+ /* @__PURE__ */ jsx44("span", { className: "truncate", children: col.header }),
3351
+ /* @__PURE__ */ jsx44(SortIndicator, { active: Boolean(isSorted), direction: sort?.direction })
3211
3352
  ]
3212
3353
  }
3213
3354
  ) : col.header;
3214
- return /* @__PURE__ */ jsx43(
3355
+ return /* @__PURE__ */ jsx44(
3215
3356
  "th",
3216
3357
  {
3217
3358
  scope: "col",
@@ -3228,9 +3369,9 @@ function DataTable({
3228
3369
  );
3229
3370
  })
3230
3371
  ] }) }),
3231
- /* @__PURE__ */ jsx43("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: loading ? Array.from({ length: skeletonCount }).map((_, rowIdx) => /* @__PURE__ */ jsxs33("tr", { className: rowClass, "aria-hidden": true, children: [
3232
- selectable ? /* @__PURE__ */ jsx43("td", { className: cn(selectCellClass, cellPad), children: /* @__PURE__ */ jsx43(Skeleton, { className: "size-4 rounded-[4px]" }) }) : null,
3233
- columns.map((col) => /* @__PURE__ */ jsx43(
3372
+ /* @__PURE__ */ jsx44("tbody", { className: cn(!hasFoot && "[&_tr:last-child_td]:border-b-0"), children: loading ? Array.from({ length: skeletonCount }).map((_, rowIdx) => /* @__PURE__ */ jsxs34("tr", { className: rowClass, "aria-hidden": true, children: [
3373
+ selectable ? /* @__PURE__ */ jsx44("td", { className: cn(selectCellClass, cellPad), children: /* @__PURE__ */ jsx44(Skeleton, { className: "size-4 rounded-[4px]" }) }) : null,
3374
+ columns.map((col) => /* @__PURE__ */ jsx44(
3234
3375
  "td",
3235
3376
  {
3236
3377
  className: cn(
@@ -3239,17 +3380,17 @@ function DataTable({
3239
3380
  col.align && alignClass[col.align],
3240
3381
  col.className
3241
3382
  ),
3242
- children: /* @__PURE__ */ jsx43(Skeleton, { className: "h-4 w-[60%]" })
3383
+ children: /* @__PURE__ */ jsx44(Skeleton, { className: "h-4 w-[60%]" })
3243
3384
  },
3244
3385
  col.id
3245
3386
  ))
3246
- ] }, `skeleton-${rowIdx}`)) : visibleRows.length === 0 ? /* @__PURE__ */ jsx43("tr", { children: /* @__PURE__ */ jsx43("td", { colSpan, className: emptyCellClass, children: /* @__PURE__ */ jsxs33("div", { className: "flex flex-col items-center gap-1", children: [
3247
- /* @__PURE__ */ jsx43("p", { className: "font-medium text-foreground", children: emptyTitle }),
3248
- emptyDescription ? /* @__PURE__ */ jsx43("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
3387
+ ] }, `skeleton-${rowIdx}`)) : visibleRows.length === 0 ? /* @__PURE__ */ jsx44("tr", { children: /* @__PURE__ */ jsx44("td", { colSpan, className: emptyCellClass, children: /* @__PURE__ */ jsxs34("div", { className: "flex flex-col items-center gap-1", children: [
3388
+ /* @__PURE__ */ jsx44("p", { className: "font-medium text-foreground", children: emptyTitle }),
3389
+ emptyDescription ? /* @__PURE__ */ jsx44("p", { className: "max-w-sm text-muted-foreground", children: emptyDescription }) : null
3249
3390
  ] }) }) }) : visibleRows.map((row) => {
3250
3391
  const key = getRowKey(row);
3251
3392
  const isSelected = selectedSet.has(key);
3252
- return /* @__PURE__ */ jsxs33(
3393
+ return /* @__PURE__ */ jsxs34(
3253
3394
  "tr",
3254
3395
  {
3255
3396
  className: rowClass,
@@ -3265,12 +3406,12 @@ function DataTable({
3265
3406
  tabIndex: onRowClick ? 0 : void 0,
3266
3407
  role: onRowClick ? "button" : void 0,
3267
3408
  children: [
3268
- selectable ? /* @__PURE__ */ jsx43(
3409
+ selectable ? /* @__PURE__ */ jsx44(
3269
3410
  "td",
3270
3411
  {
3271
3412
  className: cn(selectCellClass, cellPad),
3272
3413
  onClick: (event) => event.stopPropagation(),
3273
- children: /* @__PURE__ */ jsx43(
3414
+ children: /* @__PURE__ */ jsx44(
3274
3415
  Checkbox,
3275
3416
  {
3276
3417
  checked: isSelected,
@@ -3280,7 +3421,7 @@ function DataTable({
3280
3421
  )
3281
3422
  }
3282
3423
  ) : null,
3283
- columns.map((col) => /* @__PURE__ */ jsx43(
3424
+ columns.map((col) => /* @__PURE__ */ jsx44(
3284
3425
  "td",
3285
3426
  {
3286
3427
  className: cn(
@@ -3290,7 +3431,7 @@ function DataTable({
3290
3431
  col.align && alignClass[col.align],
3291
3432
  col.className
3292
3433
  ),
3293
- children: col.truncate ? /* @__PURE__ */ jsx43("div", { className: "truncate", children: col.cell(row) }) : col.cell(row)
3434
+ children: col.truncate ? /* @__PURE__ */ jsx44("div", { className: "truncate", children: col.cell(row) }) : col.cell(row)
3294
3435
  },
3295
3436
  col.id
3296
3437
  ))
@@ -3299,7 +3440,7 @@ function DataTable({
3299
3440
  key
3300
3441
  );
3301
3442
  }) }),
3302
- hasFoot ? /* @__PURE__ */ jsx43("tfoot", { children: /* @__PURE__ */ jsx43("tr", { children: /* @__PURE__ */ jsx43("td", { colSpan, className: footCellClass, children: /* @__PURE__ */ jsxs33(
3443
+ hasFoot ? /* @__PURE__ */ jsx44("tfoot", { children: /* @__PURE__ */ jsx44("tr", { children: /* @__PURE__ */ jsx44("td", { colSpan, className: footCellClass, children: /* @__PURE__ */ jsxs34(
3303
3444
  "div",
3304
3445
  {
3305
3446
  className: cn(
@@ -3307,18 +3448,18 @@ function DataTable({
3307
3448
  (showRowCount || footer || hasPager) && "justify-between"
3308
3449
  ),
3309
3450
  children: [
3310
- /* @__PURE__ */ jsxs33("div", { className: footInnerClass, children: [
3311
- showRowCount ? /* @__PURE__ */ jsxs33("span", { children: [
3451
+ /* @__PURE__ */ jsxs34("div", { className: footInnerClass, children: [
3452
+ showRowCount ? /* @__PURE__ */ jsxs34("span", { children: [
3312
3453
  rowCountText,
3313
3454
  selectable && selectedSet.size > 0 ? ` \xB7 ${selectedSet.size} selected` : null
3314
- ] }) : selectable && selectedSet.size > 0 ? /* @__PURE__ */ jsxs33("span", { children: [
3455
+ ] }) : selectable && selectedSet.size > 0 ? /* @__PURE__ */ jsxs34("span", { children: [
3315
3456
  selectedSet.size,
3316
3457
  " selected"
3317
3458
  ] }) : null,
3318
3459
  footer
3319
3460
  ] }),
3320
- hasPager ? /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-2", children: [
3321
- /* @__PURE__ */ jsxs33("span", { className: "tabular-nums", children: [
3461
+ hasPager ? /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
3462
+ /* @__PURE__ */ jsxs34("span", { className: "tabular-nums", children: [
3322
3463
  pageIndex * pageSize + 1,
3323
3464
  "\u2013",
3324
3465
  Math.min(
@@ -3329,8 +3470,8 @@ function DataTable({
3329
3470
  "of ",
3330
3471
  sortedRows.length
3331
3472
  ] }),
3332
- /* @__PURE__ */ jsxs33("div", { className: "flex items-center gap-1", children: [
3333
- /* @__PURE__ */ jsx43(
3473
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-1", children: [
3474
+ /* @__PURE__ */ jsx44(
3334
3475
  "button",
3335
3476
  {
3336
3477
  type: "button",
@@ -3338,10 +3479,10 @@ function DataTable({
3338
3479
  onClick: () => setPage(pageIndex - 1),
3339
3480
  disabled: pageIndex <= 0,
3340
3481
  "aria-label": "Previous page",
3341
- children: /* @__PURE__ */ jsx43(ChevronLeftIcon, { className: "size-4", "aria-hidden": true })
3482
+ children: /* @__PURE__ */ jsx44(ChevronLeftIcon, { className: "size-4", "aria-hidden": true })
3342
3483
  }
3343
3484
  ),
3344
- /* @__PURE__ */ jsx43(
3485
+ /* @__PURE__ */ jsx44(
3345
3486
  "button",
3346
3487
  {
3347
3488
  type: "button",
@@ -3349,7 +3490,7 @@ function DataTable({
3349
3490
  onClick: () => setPage(pageIndex + 1),
3350
3491
  disabled: pageIndex >= pageCount - 1,
3351
3492
  "aria-label": "Next page",
3352
- children: /* @__PURE__ */ jsx43(ChevronRightIcon, { className: "size-4", "aria-hidden": true })
3493
+ children: /* @__PURE__ */ jsx44(ChevronRightIcon, { className: "size-4", "aria-hidden": true })
3353
3494
  }
3354
3495
  )
3355
3496
  ] })
@@ -3361,29 +3502,33 @@ function DataTable({
3361
3502
  }
3362
3503
 
3363
3504
  // src/app/data/ChartPanel.tsx
3364
- import { useId as useId4 } from "react";
3365
- import { jsx as jsx44, jsxs as jsxs34 } from "react/jsx-runtime";
3505
+ import { useId as useId8 } from "react";
3506
+ import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
3366
3507
  var ChartPanel = ({
3367
3508
  title,
3368
3509
  description,
3369
3510
  artifact,
3370
3511
  children,
3371
3512
  actions,
3372
- height = 300,
3513
+ height: heightProp,
3373
3514
  loading = false,
3374
3515
  className
3375
3516
  }) => {
3376
- const titleId = useId4();
3517
+ const density = useAppDensity();
3518
+ const height = heightProp ?? APP_DENSITY_CHART_HEIGHT[density];
3519
+ const metricChartPlotRegionClass = useAppDensityClass("metricChartPlotRegion");
3520
+ const chartPanelBodyClass = useAppDensityClass("chartPanelBody");
3521
+ const titleId = useId8();
3377
3522
  const resolvedTitle = title ?? artifact?.title;
3378
3523
  const hasHeader = Boolean(resolvedTitle || description || actions);
3379
- const body = loading ? /* @__PURE__ */ jsx44(Skeleton, { className: "w-full rounded-lg", style: { height }, "aria-hidden": true }) : children ?? (artifact ? /* @__PURE__ */ jsx44(ChartArtifactView, { artifact, embedded: true, height }) : null);
3380
- return /* @__PURE__ */ jsxs34(
3524
+ const body = loading ? /* @__PURE__ */ jsx45(Skeleton, { className: "w-full rounded-lg", style: { height }, "aria-hidden": true }) : children ?? (artifact ? /* @__PURE__ */ jsx45(ChartArtifactView, { artifact, embedded: true, height }) : null);
3525
+ return /* @__PURE__ */ jsxs35(
3381
3526
  "section",
3382
3527
  {
3383
3528
  className: cn(metricCardShellClass, "aui-app-chart-panel", className),
3384
3529
  "aria-labelledby": resolvedTitle ? titleId : void 0,
3385
3530
  children: [
3386
- /* @__PURE__ */ jsx44(
3531
+ /* @__PURE__ */ jsx45(
3387
3532
  MetricCardHeader,
3388
3533
  {
3389
3534
  title: resolvedTitle,
@@ -3392,14 +3537,14 @@ var ChartPanel = ({
3392
3537
  actions
3393
3538
  }
3394
3539
  ),
3395
- /* @__PURE__ */ jsx44(
3540
+ /* @__PURE__ */ jsx45(
3396
3541
  "div",
3397
3542
  {
3398
3543
  className: cn(
3399
3544
  "relative min-h-0 w-full",
3400
- hasHeader ? metricChartPlotRegionClass : "pt-2 pb-3"
3545
+ hasHeader ? metricChartPlotRegionClass : chartPanelBodyClass
3401
3546
  ),
3402
- children: body ?? /* @__PURE__ */ jsx44(
3547
+ children: body ?? /* @__PURE__ */ jsx45(
3403
3548
  "div",
3404
3549
  {
3405
3550
  className: "flex items-center justify-center text-sm font-normal text-muted-foreground",
@@ -3416,8 +3561,8 @@ var ChartPanel = ({
3416
3561
  };
3417
3562
 
3418
3563
  // src/app/data/MetricRow.tsx
3419
- import { useId as useId5, useState as useState5 } from "react";
3420
- import { jsx as jsx45, jsxs as jsxs35 } from "react/jsx-runtime";
3564
+ import { useId as useId9, useState as useState5 } from "react";
3565
+ import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
3421
3566
  var MetricRow = ({
3422
3567
  title,
3423
3568
  description,
@@ -3430,7 +3575,8 @@ var MetricRow = ({
3430
3575
  loading = false,
3431
3576
  className
3432
3577
  }) => {
3433
- const titleId = useId5();
3578
+ const metricTileClass = useAppDensityClass("metricTile");
3579
+ const titleId = useId9();
3434
3580
  const selectable = onMetricChange != null || activeMetricId != null;
3435
3581
  const [internalId, setInternalId] = useState5(
3436
3582
  defaultActiveMetricId ?? metrics[0]?.id
@@ -3440,13 +3586,13 @@ var MetricRow = ({
3440
3586
  if (activeMetricId == null) setInternalId(id);
3441
3587
  onMetricChange?.(id);
3442
3588
  };
3443
- return /* @__PURE__ */ jsxs35(
3589
+ return /* @__PURE__ */ jsxs36(
3444
3590
  "section",
3445
3591
  {
3446
3592
  className: cn(metricCardShellClass, className),
3447
3593
  "aria-labelledby": title ? titleId : void 0,
3448
3594
  children: [
3449
- /* @__PURE__ */ jsx45(
3595
+ /* @__PURE__ */ jsx46(
3450
3596
  MetricCardHeader,
3451
3597
  {
3452
3598
  title,
@@ -3455,7 +3601,7 @@ var MetricRow = ({
3455
3601
  actions
3456
3602
  }
3457
3603
  ),
3458
- /* @__PURE__ */ jsx45(
3604
+ /* @__PURE__ */ jsx46(
3459
3605
  "div",
3460
3606
  {
3461
3607
  role: selectable ? "group" : void 0,
@@ -3466,18 +3612,18 @@ var MetricRow = ({
3466
3612
  metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
3467
3613
  (title || description || actions) && "mt-3"
3468
3614
  ),
3469
- children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs35(
3615
+ children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs36(
3470
3616
  "div",
3471
3617
  {
3472
- className: "flex min-w-0 flex-1 flex-col gap-2 px-4 py-3",
3618
+ className: cn("flex min-w-0 flex-1 flex-col gap-2", metricTileClass),
3473
3619
  "aria-hidden": true,
3474
3620
  children: [
3475
- /* @__PURE__ */ jsx45(Skeleton, { className: "h-3 w-20" }),
3476
- /* @__PURE__ */ jsx45(Skeleton, { className: "h-7 w-24" })
3621
+ /* @__PURE__ */ jsx46(Skeleton, { className: "h-3 w-20" }),
3622
+ /* @__PURE__ */ jsx46(Skeleton, { className: "h-7 w-24" })
3477
3623
  ]
3478
3624
  },
3479
3625
  `skeleton-${index}`
3480
- )) : metrics.map((m, index) => /* @__PURE__ */ jsx45(
3626
+ )) : metrics.map((m, index) => /* @__PURE__ */ jsx46(
3481
3627
  MetricTile,
3482
3628
  {
3483
3629
  label: m.label,
@@ -3499,8 +3645,8 @@ var MetricRow = ({
3499
3645
  };
3500
3646
 
3501
3647
  // src/app/data/MetricChartCard.tsx
3502
- import { useId as useId6, useState as useState6 } from "react";
3503
- import { jsx as jsx46, jsxs as jsxs36 } from "react/jsx-runtime";
3648
+ import { useId as useId10, useState as useState6 } from "react";
3649
+ import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3504
3650
  var MetricChartCard = ({
3505
3651
  title,
3506
3652
  description,
@@ -3511,7 +3657,7 @@ var MetricChartCard = ({
3511
3657
  onMetricChange,
3512
3658
  xKey = "date",
3513
3659
  variant = "area",
3514
- height = 300,
3660
+ height: heightProp,
3515
3661
  formatX,
3516
3662
  formatValue,
3517
3663
  emptyLabel = "No data yet",
@@ -3519,7 +3665,11 @@ var MetricChartCard = ({
3519
3665
  loading = false,
3520
3666
  className
3521
3667
  }) => {
3522
- const titleId = useId6();
3668
+ const density = useAppDensity();
3669
+ const height = heightProp ?? APP_DENSITY_CHART_HEIGHT[density];
3670
+ const metricChartRegionClass = useAppDensityClass("metricChartRegion");
3671
+ const metricTileClass = useAppDensityClass("metricTile");
3672
+ const titleId = useId10();
3523
3673
  const [internalId, setInternalId] = useState6(
3524
3674
  defaultActiveMetricId ?? metrics[0]?.id
3525
3675
  );
@@ -3531,13 +3681,13 @@ var MetricChartCard = ({
3531
3681
  };
3532
3682
  const hasHeader = Boolean(title || description || actions);
3533
3683
  const chartAriaLabel = typeof active?.label === "string" ? `${active.label} over time` : "Metric chart";
3534
- return /* @__PURE__ */ jsxs36(
3684
+ return /* @__PURE__ */ jsxs37(
3535
3685
  "section",
3536
3686
  {
3537
3687
  className: cn(metricCardShellClass, className),
3538
3688
  "aria-labelledby": title ? titleId : void 0,
3539
3689
  children: [
3540
- /* @__PURE__ */ jsx46(
3690
+ /* @__PURE__ */ jsx47(
3541
3691
  MetricCardHeader,
3542
3692
  {
3543
3693
  title,
@@ -3546,7 +3696,7 @@ var MetricChartCard = ({
3546
3696
  actions
3547
3697
  }
3548
3698
  ),
3549
- /* @__PURE__ */ jsx46(
3699
+ /* @__PURE__ */ jsx47(
3550
3700
  "div",
3551
3701
  {
3552
3702
  role: "group",
@@ -3557,18 +3707,18 @@ var MetricChartCard = ({
3557
3707
  metricTilesGridColsClass(loading ? metrics.length || 4 : metrics.length),
3558
3708
  hasHeader && "mt-3"
3559
3709
  ),
3560
- children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs36(
3710
+ children: loading ? Array.from({ length: metrics.length || 4 }).map((_, index) => /* @__PURE__ */ jsxs37(
3561
3711
  "div",
3562
3712
  {
3563
- className: "flex min-w-0 flex-1 flex-col gap-2 px-4 py-3",
3713
+ className: cn("flex min-w-0 flex-1 flex-col gap-2", metricTileClass),
3564
3714
  "aria-hidden": true,
3565
3715
  children: [
3566
- /* @__PURE__ */ jsx46(Skeleton, { className: "h-3 w-20" }),
3567
- /* @__PURE__ */ jsx46(Skeleton, { className: "h-7 w-24" })
3716
+ /* @__PURE__ */ jsx47(Skeleton, { className: "h-3 w-20" }),
3717
+ /* @__PURE__ */ jsx47(Skeleton, { className: "h-7 w-24" })
3568
3718
  ]
3569
3719
  },
3570
3720
  `skeleton-${index}`
3571
- )) : metrics.map((m, index) => /* @__PURE__ */ jsx46(
3721
+ )) : metrics.map((m, index) => /* @__PURE__ */ jsx47(
3572
3722
  MetricTile,
3573
3723
  {
3574
3724
  label: m.label,
@@ -3584,14 +3734,14 @@ var MetricChartCard = ({
3584
3734
  ))
3585
3735
  }
3586
3736
  ),
3587
- /* @__PURE__ */ jsx46("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: loading ? /* @__PURE__ */ jsx46(
3737
+ /* @__PURE__ */ jsx47("div", { className: metricChartRegionClass, "aria-live": "polite", "aria-atomic": "true", children: loading ? /* @__PURE__ */ jsx47(
3588
3738
  Skeleton,
3589
3739
  {
3590
3740
  className: "w-full rounded-lg",
3591
3741
  style: { height },
3592
3742
  "aria-hidden": true
3593
3743
  }
3594
- ) : active?.data && active.data.length > 0 ? /* @__PURE__ */ jsx46(
3744
+ ) : active?.data && active.data.length > 0 ? /* @__PURE__ */ jsx47(
3595
3745
  LineAreaChart,
3596
3746
  {
3597
3747
  data: active.data,
@@ -3611,7 +3761,7 @@ var MetricChartCard = ({
3611
3761
  ariaLabel: chartAriaLabel
3612
3762
  },
3613
3763
  active.id
3614
- ) : /* @__PURE__ */ jsx46(
3764
+ ) : /* @__PURE__ */ jsx47(
3615
3765
  "div",
3616
3766
  {
3617
3767
  className: "flex w-full items-center justify-center text-sm font-normal text-muted-foreground",
@@ -3716,8 +3866,8 @@ function useLiveQuery(fetcher, options = {}) {
3716
3866
  }
3717
3867
 
3718
3868
  // src/charts/sparkline.tsx
3719
- import { useId as useId7 } from "react";
3720
- import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
3869
+ import { useId as useId11 } from "react";
3870
+ import { Fragment as Fragment6, jsx as jsx48, jsxs as jsxs38 } from "react/jsx-runtime";
3721
3871
  var Sparkline = ({
3722
3872
  data,
3723
3873
  dataKey = "value",
@@ -3729,10 +3879,10 @@ var Sparkline = ({
3729
3879
  className,
3730
3880
  ariaLabel = "Trend"
3731
3881
  }) => {
3732
- const uid = useId7();
3882
+ const uid = useId11();
3733
3883
  const values = data.map((d) => typeof d === "number" ? d : toNum(d[dataKey]));
3734
3884
  if (values.length === 0) {
3735
- return /* @__PURE__ */ jsx47("span", { className: cn("inline-block", className), style: { width, height } });
3885
+ return /* @__PURE__ */ jsx48("span", { className: cn("inline-block", className), style: { width, height } });
3736
3886
  }
3737
3887
  const pad = strokeWidth + 1;
3738
3888
  const min = Math.min(...values);
@@ -3744,7 +3894,7 @@ var Sparkline = ({
3744
3894
  x: pad + (values.length > 1 ? i / (values.length - 1) * innerW : innerW / 2),
3745
3895
  y: pad + innerH - (v - min) / range * innerH
3746
3896
  }));
3747
- return /* @__PURE__ */ jsxs37(
3897
+ return /* @__PURE__ */ jsxs38(
3748
3898
  "svg",
3749
3899
  {
3750
3900
  width,
@@ -3755,14 +3905,14 @@ var Sparkline = ({
3755
3905
  "aria-label": ariaLabel,
3756
3906
  preserveAspectRatio: "none",
3757
3907
  children: [
3758
- area && /* @__PURE__ */ jsxs37(Fragment6, { children: [
3759
- /* @__PURE__ */ jsx47("defs", { children: /* @__PURE__ */ jsxs37("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
3760
- /* @__PURE__ */ jsx47("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
3761
- /* @__PURE__ */ jsx47("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
3908
+ area && /* @__PURE__ */ jsxs38(Fragment6, { children: [
3909
+ /* @__PURE__ */ jsx48("defs", { children: /* @__PURE__ */ jsxs38("linearGradient", { id: `${uid}-spark`, x1: "0", x2: "0", y1: "0", y2: "1", children: [
3910
+ /* @__PURE__ */ jsx48("stop", { offset: "0%", style: { stopColor: color, stopOpacity: 0.25 } }),
3911
+ /* @__PURE__ */ jsx48("stop", { offset: "100%", style: { stopColor: color, stopOpacity: 0 } })
3762
3912
  ] }) }),
3763
- /* @__PURE__ */ jsx47("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
3913
+ /* @__PURE__ */ jsx48("path", { d: monotoneAreaPath(points, height - pad), fill: `url(#${uid}-spark)` })
3764
3914
  ] }),
3765
- /* @__PURE__ */ jsx47(
3915
+ /* @__PURE__ */ jsx48(
3766
3916
  "path",
3767
3917
  {
3768
3918
  d: monotoneLinePath(points),
@@ -3801,8 +3951,6 @@ export {
3801
3951
  getStoredThemePreset,
3802
3952
  THEME_AGENT_INSTRUCTIONS,
3803
3953
  TimbalThemeStyle,
3804
- MetricTile,
3805
- ThemePresetGallery,
3806
3954
  appPageColumnClass,
3807
3955
  appShellTopbarInsetClass,
3808
3956
  appShellInsetTopClass,
@@ -3810,6 +3958,13 @@ export {
3810
3958
  appStatTileClass,
3811
3959
  appFilterBarClass,
3812
3960
  appSearchInputClass,
3961
+ APP_DENSITY_CHART_HEIGHT,
3962
+ APP_DENSITY_CLASSES,
3963
+ appDensityClass,
3964
+ AppDensityProvider,
3965
+ useAppDensity,
3966
+ useAppDensityClass,
3967
+ MetricTile,
3813
3968
  useAppShellChat,
3814
3969
  useAppShellNav,
3815
3970
  AppShell,