@alfadocs/ui-kit-debug 0.32.1 → 0.32.3

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.
@@ -1,7 +1,7 @@
1
1
  import { jsxs as v, jsx as r } from "react/jsx-runtime";
2
- import { forwardRef as _, useContext as k, Children as w, createContext as y } from "react";
2
+ import { forwardRef as b, useContext as k, Children as w, createContext as y } from "react";
3
3
  import { c as s } from "./index-D2ZczOXr.js";
4
- const b = [
4
+ const _ = [
5
5
  "violet",
6
6
  "purple",
7
7
  "magenta",
@@ -44,17 +44,17 @@ const b = [
44
44
  // matches Card.elevated and PublicFooter compact. The thicker
45
45
  // line reads as a deliberate boundary rather than a hairline.
46
46
  //
47
- // 0.31.9: `border-t-0` on both variants the 4px accent strip
48
- // (absolutely positioned at top:0 inside the border-box) sits
49
- // BELOW the top border, so visually you see a thin grey
50
- // hairline, then the brand strip. That dilutes the brand
51
- // marker. Dropping the top border lets the accent strip BE the
52
- // card's top edge. The 3px-and-up strip carries enough
53
- // contrast (~5:1 on white in light theme, similar in dark) to
54
- // satisfy the accessible theme's ≥3:1 boundary requirement
55
- // without the extra hairline.
56
- elevated: "ds:shadow-[var(--shadow-card)] ds:border ds:border-t-0 ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2 ds:[.theme-accessible_&]:border-t-0",
57
- outlined: "ds:border ds:border-t-0 ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2 ds:[.theme-accessible_&]:border-t-0"
47
+ // 0.32.3: restored full 4-sided border. 0.31.9 dropped
48
+ // `border-top` so the accent strip would be the card's literal
49
+ // top edge but with `border-radius: lg` on all 4 corners the
50
+ // side borders curve toward a non-existent top edge, leaving
51
+ // the top corners visually "open" (visible page-bg slivers
52
+ // where the rounded corner outline should close). The 1px
53
+ // hairline above the accent strip is the cheaper visual cost
54
+ // subtle in light theme (14% black) and matches dark-theme
55
+ // chrome where shadow alone loses contrast.
56
+ elevated: "ds:shadow-[var(--shadow-card)] ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2",
57
+ outlined: "ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2"
58
58
  }
59
59
  },
60
60
  defaultVariants: { variant: "elevated" }
@@ -153,9 +153,9 @@ const b = [
153
153
  }
154
154
  );
155
155
  function S(a, o) {
156
- return a !== "auto" ? a : o ? b[o.index % b.length] : "primary";
156
+ return a !== "auto" ? a : o ? _[o.index % _.length] : "primary";
157
157
  }
158
- const p = _(
158
+ const p = b(
159
159
  ({ columns: a = 3, children: o, className: c, ...d }, l) => {
160
160
  const i = w.toArray(o);
161
161
  return /* @__PURE__ */ r(
@@ -171,7 +171,7 @@ const p = _(
171
171
  }
172
172
  );
173
173
  p.displayName = "BenefitCard.Row";
174
- const x = _(
174
+ const x = b(
175
175
  ({
176
176
  step: a,
177
177
  icon: o,
@@ -241,4 +241,4 @@ const H = Object.assign(x, {
241
241
  export {
242
242
  H as B
243
243
  };
244
- //# sourceMappingURL=benefit-card-_Sc-MGha.js.map
244
+ //# sourceMappingURL=benefit-card-Xnxj4Gmo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benefit-card-Xnxj4Gmo.js","sources":["../../src/components/benefit-card/benefit-card.tsx"],"sourcesContent":["/* ------------------------------------------------------------------ */\n/* BenefitCard — marketing-surface card for \"benefit row\" / \"how it */\n/* works\" / \"why choose us\" sections. */\n/* */\n/* Visually distinguished from <Card> by: */\n/* 1. A 4px accent strip across the top (logical block-start). */\n/* 2. A tinted icon chip inside the body using `color-mix(in srgb, */\n/* var(--accent-token) 12%, var(--background))`. */\n/* 3. An optional zero-padded step chip (\"01\", \"02\", ...) in the */\n/* top-end corner. */\n/* 4. A hover lift (translateY -2px + --shadow-hover), gated through */\n/* `--animation-duration` so the accessible theme freezes it. */\n/* */\n/* Compound API: */\n/* <BenefitCard.Row columns={3}> */\n/* <BenefitCard step={1} icon={…} title=\"…\">…</BenefitCard> */\n/* ... */\n/* </BenefitCard.Row> */\n/* */\n/* `accent=\"auto\"` rotates through the brand palette by row index */\n/* (violet → purple → magenta → blue → green → red, then wraps). */\n/* Outside a Row, `auto` falls back to `primary`. */\n/* ------------------------------------------------------------------ */\n\nimport {\n Children,\n createContext,\n forwardRef,\n useContext,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\n\n/* ------------------------------------------------------------------ */\n/* Accent wheel — used by `accent=\"auto\"` inside a Row. */\n/* ------------------------------------------------------------------ */\n\nconst ACCENT_WHEEL = [\n 'violet',\n 'purple',\n 'magenta',\n 'blue',\n 'green',\n 'red',\n] as const;\n\ntype WheelAccent = (typeof ACCENT_WHEEL)[number];\ntype SemanticAccent = 'primary' | 'accent' | 'info' | 'success' | 'warning';\ntype ResolvedAccent = SemanticAccent | WheelAccent;\ntype AccentProp = SemanticAccent | WheelAccent | 'auto';\n\n/* ------------------------------------------------------------------ */\n/* Row context */\n/* ------------------------------------------------------------------ */\n\ninterface RowContextValue {\n index: number;\n}\n\nconst RowContext = createContext<RowContextValue | null>(null);\n\n/* ------------------------------------------------------------------ */\n/* CVA — Row grid */\n/* ------------------------------------------------------------------ */\n\nconst rowVariants = cva('ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-lg)]', {\n variants: {\n columns: {\n 1: 'ds:md:grid-cols-1',\n 2: 'ds:md:grid-cols-2',\n 3: 'ds:md:grid-cols-3',\n 4: 'ds:md:grid-cols-4',\n },\n },\n defaultVariants: { columns: 3 },\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — BenefitCard root */\n/* */\n/* The top 4px accent strip uses `border-block-start` (logical) so it */\n/* sits at the inline-start-block-start corner regardless of writing */\n/* direction. Border colour is set per-accent in the `accent` variant. */\n/* ------------------------------------------------------------------ */\n\n// Card chrome — no per-accent variant; the gradient top strip is rendered\n// as a separate sibling element so it can use a linear-gradient. The\n// hover shadow's tint comes from `hoverShadowVariants` on the same root.\nconst cardVariants = cva(\n [\n 'ds:relative ds:rounded-[var(--radius-lg)] ds:overflow-hidden',\n 'ds:flex ds:flex-col ds:h-full',\n 'ds:bg-[var(--card)] ds:text-[var(--card-foreground)]',\n // Hover lift — the transform is gated through `motion-safe:` so users\n // with `prefers-reduced-motion: reduce` see only the shadow change.\n // `--animation-duration` is pinned to 0ms in the accessible theme,\n // which collapses the transition without dropping the rule entirely.\n 'ds:transition-[transform,box-shadow] ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n 'ds:motion-safe:hover:-translate-y-1',\n ].join(' '),\n {\n variants: {\n variant: {\n // The accessible theme demands a visible boundary at ≥3:1 — shadow\n // alone doesn't clear that against the light page wash. Always\n // emit a `--card-border` outline; light/dark themes use the\n // soft 14% / 32% values (subtle but present) while accessible\n // bumps to 50% black / 50% white for the strict-AA edge weight.\n //\n // 0.31.5: accessible theme also bumps border-width 1px → 2px —\n // matches Card.elevated and PublicFooter compact. The thicker\n // line reads as a deliberate boundary rather than a hairline.\n //\n // 0.32.3: restored full 4-sided border. 0.31.9 dropped\n // `border-top` so the accent strip would be the card's literal\n // top edge — but with `border-radius: lg` on all 4 corners the\n // side borders curve toward a non-existent top edge, leaving\n // the top corners visually \"open\" (visible page-bg slivers\n // where the rounded corner outline should close). The 1px\n // hairline above the accent strip is the cheaper visual cost\n // — subtle in light theme (14% black) and matches dark-theme\n // chrome where shadow alone loses contrast.\n elevated:\n 'ds:shadow-[var(--shadow-card)] ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n outlined:\n 'ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2',\n },\n },\n defaultVariants: { variant: 'elevated' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Gradient top strip — Treatment B (Vivid). */\n/* */\n/* The strip is an absolutely-positioned `<span>` so its background can */\n/* be a `linear-gradient`. For brand-wheel accents (violet → purple → */\n/* magenta → blue → green → red) the gradient pairs with the next */\n/* wheel token. For semantic accents the gradient is a solid pair */\n/* (start=end) — same visual weight, less colour drama. */\n/* ------------------------------------------------------------------ */\n\nconst topStripVariants = cva(\n 'ds:absolute ds:inset-inline-0 ds:top-0 ds:h-[4px] ds:pointer-events-none',\n {\n variants: {\n accent: {\n primary:\n 'ds:bg-linear-to-r ds:from-[var(--primary)] ds:to-[var(--accent)]',\n accent:\n 'ds:bg-linear-to-r ds:from-[var(--accent)] ds:to-[var(--primary)]',\n info: 'ds:bg-linear-to-r ds:from-[var(--info)] ds:to-[var(--info)]',\n success:\n 'ds:bg-linear-to-r ds:from-[var(--success)] ds:to-[var(--success)]',\n warning:\n 'ds:bg-linear-to-r ds:from-[var(--warning)] ds:to-[var(--warning)]',\n violet:\n 'ds:bg-linear-to-r ds:from-[var(--color-violet-500)] ds:to-[var(--color-purple-500)]',\n purple:\n 'ds:bg-linear-to-r ds:from-[var(--color-purple-500)] ds:to-[var(--color-magenta-500)]',\n magenta:\n 'ds:bg-linear-to-r ds:from-[var(--color-magenta-500)] ds:to-[var(--color-violet-500)]',\n blue: 'ds:bg-linear-to-r ds:from-[var(--color-blue-500)] ds:to-[var(--color-green-500)]',\n green:\n 'ds:bg-linear-to-r ds:from-[var(--color-green-500)] ds:to-[var(--color-red-500)]',\n red: 'ds:bg-linear-to-r ds:from-[var(--color-red-500)] ds:to-[var(--color-blue-500)]',\n },\n },\n defaultVariants: { accent: 'primary' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Hover shadow — coloured halo on hover, tinted by accent. */\n/* ------------------------------------------------------------------ */\n\nconst hoverShadowVariants = cva('', {\n variants: {\n accent: {\n primary:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--primary)_18%,transparent)]',\n accent:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--accent)_18%,transparent)]',\n info: 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--info)_18%,transparent)]',\n success:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--success)_18%,transparent)]',\n warning:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--warning)_18%,transparent)]',\n violet:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-violet-500)_18%,transparent)]',\n purple:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-purple-500)_18%,transparent)]',\n magenta:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-magenta-500)_18%,transparent)]',\n blue: 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-blue-500)_18%,transparent)]',\n green:\n 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-green-500)_18%,transparent)]',\n red: 'ds:hover:shadow-[0_20px_40px_color-mix(in_srgb,var(--color-red-500)_18%,transparent)]',\n },\n },\n defaultVariants: { accent: 'primary' },\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — icon chip */\n/* */\n/* The chip background uses `color-mix(in srgb, <token> 12%, */\n/* var(--background))` so it stays legible across themes. The Tailwind */\n/* JIT requires underscores in arbitrary-value classes wherever */\n/* whitespace would otherwise terminate the class. */\n/* ------------------------------------------------------------------ */\n\n// Icon chip — gradient tint (Treatment B). The chip pairs the resolved\n// accent with the \"next\" wheel/semantic token so the bg reads as a soft\n// diagonal blend instead of a flat tint, picking up the energy of the\n// gradient top strip. An inset highlight (`inset 0 1px 0` half-white)\n// adds a subtle glass edge.\nconst iconChipVariants = cva(\n [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:size-14 ds:rounded-[var(--radius-md)] ds:shrink-0',\n 'ds:[&>svg]:size-7',\n 'ds:shadow-[inset_0_1px_0_color-mix(in_srgb,var(--foreground)_40%,transparent)]',\n ].join(' '),\n {\n variants: {\n accent: {\n primary:\n 'ds:text-[color:var(--primary)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--primary)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--accent)_8%,var(--background))]',\n accent:\n 'ds:text-[color:var(--accent)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--accent)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--primary)_8%,var(--background))]',\n info: 'ds:text-[color:var(--info)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--info)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--info)_8%,var(--background))]',\n success:\n 'ds:text-[color:var(--success)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--success)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--success)_8%,var(--background))]',\n warning:\n 'ds:text-[color:var(--warning)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--warning)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--warning)_8%,var(--background))]',\n violet:\n 'ds:text-[color:var(--color-violet-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-violet-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-purple-500)_8%,var(--background))]',\n purple:\n 'ds:text-[color:var(--color-purple-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-purple-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-magenta-500)_8%,var(--background))]',\n magenta:\n 'ds:text-[color:var(--color-magenta-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-magenta-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-violet-500)_8%,var(--background))]',\n blue: 'ds:text-[color:var(--color-blue-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-blue-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-green-500)_8%,var(--background))]',\n green:\n 'ds:text-[color:var(--color-green-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-green-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-red-500)_8%,var(--background))]',\n red: 'ds:text-[color:var(--color-red-500)] ds:bg-linear-to-br ds:from-[color-mix(in_srgb,var(--color-red-500)_22%,var(--background))] ds:to-[color-mix(in_srgb,var(--color-blue-500)_8%,var(--background))]',\n },\n },\n defaultVariants: { accent: 'primary' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Step chip — brand-tinted with a thin matching border. */\n/* ------------------------------------------------------------------ */\n\n// Text colour uses the -700 ramp step rather than -500 so the chip's\n// small `01` label clears WCAG AA (≥4.5:1) against its 12 %-tinted bg.\n// The brand -500 fails on the tinted surface (~4.07:1). For the\n// semantic accents we pin to the same brand-700 the kit resolves them\n// to (primary→violet-700, accent→magenta-700, etc.) so each variant\n// reads AA in light theme. In dark theme the tint surface darkens so\n// the ramp-700 text turns dark-on-dark and fails AA — we branch via\n// `[.theme-dark_&]:` to swap to the -200 ramp step (light text on the\n// dark tint), restoring comfortable contrast across both modes.\nconst stepChipVariants = cva(\n [\n 'type-eyebrow',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:py-[var(--spacing-xs)]',\n // Accessible theme: the per-variant `30% primary` border is too\n // washed out for the ≥3:1 non-text contrast bar. Swap to\n // currentColor (which resolves to the brand-700 / -200 text colour\n // of the variant — same hue, fully opaque). Descendant selector\n // outweighs the per-variant declaration via specificity.\n 'ds:[.theme-accessible_&]:[border-color:currentColor]',\n ].join(' '),\n {\n variants: {\n accent: {\n primary:\n 'ds:text-[color:var(--color-violet-700)] ds:[.theme-dark_&]:text-[color:var(--color-violet-200)] ds:bg-[color-mix(in_srgb,var(--primary)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--primary)_30%,transparent)]',\n accent:\n 'ds:text-[color:var(--color-magenta-700)] ds:[.theme-dark_&]:text-[color:var(--color-magenta-200)] ds:bg-[color-mix(in_srgb,var(--accent)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--accent)_30%,transparent)]',\n info: 'ds:text-[color:var(--color-blue-700)] ds:[.theme-dark_&]:text-[color:var(--color-blue-200)] ds:bg-[color-mix(in_srgb,var(--info)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--info)_30%,transparent)]',\n success:\n 'ds:text-[color:var(--color-green-700)] ds:[.theme-dark_&]:text-[color:var(--color-green-200)] ds:bg-[color-mix(in_srgb,var(--success)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--success)_30%,transparent)]',\n warning:\n 'ds:text-[color:var(--color-red-700)] ds:[.theme-dark_&]:text-[color:var(--color-red-200)] ds:bg-[color-mix(in_srgb,var(--warning)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--warning)_30%,transparent)]',\n violet:\n 'ds:text-[color:var(--color-violet-700)] ds:[.theme-dark_&]:text-[color:var(--color-violet-200)] ds:bg-[color-mix(in_srgb,var(--color-violet-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-violet-500)_30%,transparent)]',\n purple:\n 'ds:text-[color:var(--color-purple-700)] ds:[.theme-dark_&]:text-[color:var(--color-purple-200)] ds:bg-[color-mix(in_srgb,var(--color-purple-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-purple-500)_30%,transparent)]',\n magenta:\n 'ds:text-[color:var(--color-magenta-700)] ds:[.theme-dark_&]:text-[color:var(--color-magenta-200)] ds:bg-[color-mix(in_srgb,var(--color-magenta-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-magenta-500)_30%,transparent)]',\n blue: 'ds:text-[color:var(--color-blue-700)] ds:[.theme-dark_&]:text-[color:var(--color-blue-200)] ds:bg-[color-mix(in_srgb,var(--color-blue-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-blue-500)_30%,transparent)]',\n green:\n 'ds:text-[color:var(--color-green-700)] ds:[.theme-dark_&]:text-[color:var(--color-green-200)] ds:bg-[color-mix(in_srgb,var(--color-green-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-green-500)_30%,transparent)]',\n red: 'ds:text-[color:var(--color-red-700)] ds:[.theme-dark_&]:text-[color:var(--color-red-200)] ds:bg-[color-mix(in_srgb,var(--color-red-500)_12%,var(--background))] ds:[border:1px_solid_color-mix(in_srgb,var(--color-red-500)_30%,transparent)]',\n },\n },\n defaultVariants: { accent: 'primary' },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface BenefitCardProps extends Omit<\n HTMLAttributes<HTMLElement>,\n 'title'\n> {\n /** Step number; rendered as a zero-padded chip (\"01\", \"02\", …). Omit to hide. */\n step?: number;\n /** Icon node — usually an `<svg>` 24-32px. Rendered inside a tinted square chip. */\n icon?: ReactNode;\n /** Card heading. Always rendered inside an `<h3>` — pass only inline / phrasing content. */\n title: ReactNode;\n /** Optional CTA — usually a `<Button intent=\"link\">` or kit `<Link>`. Rendered at the block-end. */\n cta?: ReactNode;\n /** Surface treatment. */\n variant?: 'elevated' | 'outlined';\n /**\n * Accent colour. `auto` (default inside a `<BenefitCard.Row>`) rotates through the brand\n * palette by row index: violet → purple → magenta → blue → green → red, then wraps.\n * Outside a Row, `auto` falls back to `primary`.\n */\n accent?: AccentProp;\n /** Body content (description / list / inline copy). */\n children?: ReactNode;\n}\n\nexport interface BenefitCardRowProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n 'children'\n> {\n /** Number of columns at md+; defaults to 3. Collapses to 1 at < md. */\n columns?: 1 | 2 | 3 | 4;\n children?: ReactNode;\n}\n\n/* ------------------------------------------------------------------ */\n/* Accent resolution */\n/* ------------------------------------------------------------------ */\n\nfunction resolveAccent(\n accent: AccentProp,\n rowCtx: RowContextValue | null,\n): ResolvedAccent {\n if (accent !== 'auto') return accent;\n if (rowCtx) return ACCENT_WHEEL[rowCtx.index % ACCENT_WHEEL.length];\n return 'primary';\n}\n\n/* ------------------------------------------------------------------ */\n/* Row */\n/* */\n/* Wraps every child in a `RowContext.Provider` so the child can look */\n/* up its index and pick a wheel colour when `accent=\"auto\"`. */\n/* ------------------------------------------------------------------ */\n\nconst BenefitCardRow = forwardRef<HTMLDivElement, BenefitCardRowProps>(\n ({ columns = 3, children, className, ...rest }, ref) => {\n const items = Children.toArray(children);\n return (\n <div\n ref={ref}\n data-component=\"benefit-card-row\"\n className={rowVariants({ columns, className })}\n {...rest}\n >\n {items.map((child, index) => (\n <RowContext.Provider key={index} value={{ index }}>\n {child}\n </RowContext.Provider>\n ))}\n </div>\n );\n },\n);\nBenefitCardRow.displayName = 'BenefitCard.Row';\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nconst BenefitCardRoot = forwardRef<HTMLElement, BenefitCardProps>(\n (\n {\n step,\n icon,\n title,\n cta,\n variant = 'elevated',\n accent = 'auto',\n children,\n className,\n ...rest\n },\n ref,\n ) => {\n const rowCtx = useContext(RowContext);\n const resolved = resolveAccent(accent, rowCtx);\n const hasStep = typeof step === 'number';\n\n return (\n <article\n ref={ref}\n data-component=\"benefit-card\"\n data-accent={resolved}\n className={[\n cardVariants({ variant }),\n hoverShadowVariants({ accent: resolved }),\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n {/* Gradient top strip — Treatment B visual signature. Sits above\n the card body via absolute positioning. */}\n <span\n aria-hidden=\"true\"\n data-part=\"accent-strip\"\n className={topStripVariants({ accent: resolved })}\n />\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)] ds:p-[var(--spacing-lg)] ds:flex-1\">\n {(icon || hasStep) && (\n <div className=\"ds:flex ds:items-start ds:justify-between ds:gap-[var(--spacing-sm)]\">\n {icon ? (\n <span\n aria-hidden=\"true\"\n className={iconChipVariants({ accent: resolved })}\n >\n {icon}\n </span>\n ) : (\n <span aria-hidden=\"true\" />\n )}\n {hasStep ? (\n <span\n aria-hidden=\"true\"\n data-part=\"step\"\n className={stepChipVariants({ accent: resolved })}\n >\n {String(step).padStart(2, '0')}\n </span>\n ) : null}\n </div>\n )}\n <h3 className=\"type-title-card ds:text-[var(--foreground)]\">\n {title}\n </h3>\n {children ? (\n <div className=\"type-body ds:text-[var(--muted-foreground)] ds:flex-1\">\n {children}\n </div>\n ) : null}\n {cta ? <div className=\"ds:mt-[var(--spacing-xs)]\">{cta}</div> : null}\n </div>\n </article>\n );\n },\n);\nBenefitCardRoot.displayName = 'BenefitCard';\n\n/* ------------------------------------------------------------------ */\n/* Compound export */\n/* ------------------------------------------------------------------ */\n\nexport const BenefitCard = Object.assign(BenefitCardRoot, {\n Row: BenefitCardRow,\n});\n"],"names":["ACCENT_WHEEL","RowContext","createContext","rowVariants","cva","cardVariants","topStripVariants","hoverShadowVariants","iconChipVariants","stepChipVariants","resolveAccent","accent","rowCtx","BenefitCardRow","forwardRef","columns","children","className","rest","ref","items","Children","jsx","child","index","BenefitCardRoot","step","icon","title","cta","variant","useContext","resolved","hasStep","jsxs","BenefitCard"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { jsxs as z, jsx as i } from "react/jsx-runtime";
2
- import { forwardRef as Q, useId as X, useCallback as L, useRef as Z, useMemo as tt } from "react";
2
+ import { forwardRef as X, useId as Z, useCallback as O, useRef as tt, useMemo as et } from "react";
3
3
  import { c as V } from "./index-D2ZczOXr.js";
4
- import { useTranslation as U } from "react-i18next";
5
- import { u as et } from "./use-count-up-BLLetaZ8.js";
6
- const O = V("ds:flex ds:flex-col ds:h-full", {
4
+ import { useTranslation as B } from "react-i18next";
5
+ import { u as st } from "./use-count-up-BLLetaZ8.js";
6
+ const P = V("ds:flex ds:flex-col ds:h-full", {
7
7
  variants: {
8
8
  variant: {
9
9
  default: "ds:gap-[var(--spacing-xs)]",
@@ -14,14 +14,21 @@ const O = V("ds:flex ds:flex-col ds:h-full", {
14
14
  "ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]",
15
15
  "ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]"
16
16
  ].join(" "),
17
- // White card surface with the shared card shadow — matches
18
- // `Card variant="elevated"` tokens (`--card` + `--shadow-card`) so
19
- // a grid of elevated Stats reads as a set of shaded panels without
20
- // nesting a Card around each one.
17
+ // White card surface with the shared card shadow + border
18
+ // matches `Card variant="elevated"` and `BenefitCard.elevated`
19
+ // tokens (`--card`, `--card-border`, `--shadow-card`,
20
+ // `--radius-lg`) so a grid of elevated Stats reads as a set of
21
+ // shaded panels without nesting a Card around each one. The
22
+ // border is essential in dark mode: shadow alone on a dark
23
+ // surface loses contrast and the card boundary disappears.
24
+ // Accessible theme bumps to `border-2` to match Card / Benefit-
25
+ // Card's 0.31.5 accessibility uplift.
21
26
  elevated: [
22
27
  "ds:gap-[var(--spacing-xs)]",
23
28
  "ds:bg-[var(--card)]",
24
29
  "ds:text-[var(--card-foreground)]",
30
+ "ds:border ds:border-[color:var(--card-border)]",
31
+ "ds:[.theme-accessible_&]:border-2",
25
32
  "ds:shadow-[var(--shadow-card)]",
26
33
  "ds:rounded-[var(--radius-lg)]",
27
34
  "ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]",
@@ -48,7 +55,7 @@ const O = V("ds:flex ds:flex-col ds:h-full", {
48
55
  size: "md",
49
56
  align: "start"
50
57
  }
51
- }), P = V("type-metric ds:text-[var(--foreground)]", {
58
+ }), U = V("type-metric", {
52
59
  variants: {
53
60
  size: {
54
61
  sm: "ds:[--type-metric-size:var(--font-size-xl)]",
@@ -60,6 +67,22 @@ const O = V("ds:flex ds:flex-col ds:h-full", {
60
67
  outlined: "",
61
68
  elevated: "",
62
69
  compact: ""
70
+ },
71
+ // Colour of the headline metric value. Defaults to `--foreground`
72
+ // (the existing render). `primary` / `accent` are the brand intents
73
+ // — use for hero / marketing stats where the number IS the visual
74
+ // marker. `success` / `destructive` / `info` / `warning` map to the
75
+ // semantic tokens for KPI tiles that want to signal status via the
76
+ // value colour itself (e.g. revenue green, debt red). The trend
77
+ // chevron and the label colour are independent of this prop.
78
+ intent: {
79
+ foreground: "ds:text-[var(--foreground)]",
80
+ primary: "ds:text-[var(--primary)]",
81
+ accent: "ds:text-[var(--accent)]",
82
+ success: "ds:text-[var(--success)]",
83
+ destructive: "ds:text-[var(--destructive)]",
84
+ info: "ds:text-[var(--info)]",
85
+ warning: "ds:text-[var(--warning)]"
63
86
  }
64
87
  },
65
88
  compoundVariants: [
@@ -81,9 +104,10 @@ const O = V("ds:flex ds:flex-col ds:h-full", {
81
104
  ],
82
105
  defaultVariants: {
83
106
  size: "md",
84
- variant: "default"
107
+ variant: "default",
108
+ intent: "foreground"
85
109
  }
86
- }), st = V(
110
+ }), rt = V(
87
111
  "ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-label",
88
112
  {
89
113
  variants: {
@@ -97,76 +121,77 @@ const O = V("ds:flex ds:flex-col ds:h-full", {
97
121
  trend: "flat"
98
122
  }
99
123
  }
100
- ), rt = { up: "↑", down: "↓", flat: "→" }, at = {
124
+ ), at = { up: "↑", down: "↓", flat: "→" }, nt = {
101
125
  up: "stat.trend.up",
102
126
  down: "stat.trend.down",
103
127
  flat: "stat.trend.flat"
104
128
  };
105
- function nt({
129
+ function it({
106
130
  trend: d,
107
131
  delta: t,
108
132
  deltaFormat: c = "decimal",
109
133
  locale: a
110
134
  }) {
111
- const { t: e, i18n: l } = U(), o = typeof t == "string" ? t : new Intl.NumberFormat(a ?? l.language, {
135
+ const { t: e, i18n: o } = B(), l = typeof t == "string" ? t : new Intl.NumberFormat(a ?? o.language, {
112
136
  style: c === "percent" ? "percent" : "decimal"
113
137
  }).format(c === "percent" ? t / 100 : t);
114
- return /* @__PURE__ */ z("span", { className: st({ trend: d }), children: [
115
- /* @__PURE__ */ i("span", { "aria-hidden": "true", children: rt[d] }),
116
- /* @__PURE__ */ i("span", { className: "ds:sr-only", children: e(at[d]) }),
117
- o
138
+ return /* @__PURE__ */ z("span", { className: rt({ trend: d }), children: [
139
+ /* @__PURE__ */ i("span", { "aria-hidden": "true", children: at[d] }),
140
+ /* @__PURE__ */ i("span", { className: "ds:sr-only", children: e(nt[d]) }),
141
+ l
118
142
  ] });
119
143
  }
120
- function it(d, t) {
144
+ function dt(d, t) {
121
145
  const c = d.trim();
122
146
  if (c === "") return null;
123
147
  let a = "", e = c;
124
148
  e.startsWith("+") ? (a = "+", e = e.slice(1).trimStart()) : (e.startsWith("-") || e.startsWith("−")) && (a = "-", e = e.slice(1).trimStart());
125
- let l = "";
126
- const o = e.match(/[KMB]$/i);
127
- o && (l = o[0], e = e.slice(0, -1).trimEnd());
128
- let m = "", u = ".";
149
+ let o = "";
150
+ const l = e.match(/[KMB]$/i);
151
+ l && (o = l[0], e = e.slice(0, -1).trimEnd());
152
+ let u = "", m = ".";
129
153
  try {
130
154
  const b = new Intl.NumberFormat(t).formatToParts(12345.6);
131
155
  for (const n of b)
132
- n.type === "group" ? m = n.value : n.type === "decimal" && (u = n.value);
156
+ n.type === "group" ? u = n.value : n.type === "decimal" && (m = n.value);
133
157
  } catch {
134
158
  }
135
159
  const g = e.match(/^(\d+)\.(\d+)$/);
136
- if (g && !(g[2].length === 3 && m === ".")) {
160
+ if (g && !(g[2].length === 3 && u === ".")) {
137
161
  const n = Number.parseFloat(e);
138
162
  if (Number.isFinite(n))
139
- return { target: n, sign: a, suffix: l };
163
+ return { target: n, sign: a, suffix: o };
140
164
  }
141
165
  let s = e;
142
- m !== "" && (s = s.split(m).join("")), u !== "." && (s = s.split(u).join(".")), s = s.replace(/[\s\u00A0\u202F]/g, "");
166
+ u !== "" && (s = s.split(u).join("")), m !== "." && (s = s.split(m).join(".")), s = s.replace(/[\s\u00A0\u202F]/g, "");
143
167
  const v = Number.parseFloat(s);
144
- return Number.isFinite(v) ? { target: v, sign: a, suffix: l } : null;
168
+ return Number.isFinite(v) ? { target: v, sign: a, suffix: o } : null;
145
169
  }
146
- const dt = Q(
170
+ const ct = X(
147
171
  ({
148
172
  label: d,
149
173
  value: t,
150
174
  format: c,
151
175
  currency: a,
152
176
  locale: e,
153
- trend: l,
154
- delta: o,
155
- deltaFormat: m = "decimal",
156
- icon: u,
177
+ trend: o,
178
+ delta: l,
179
+ deltaFormat: u = "decimal",
180
+ icon: m,
157
181
  loading: g = !1,
158
182
  animate: s = !1,
159
183
  animateOnEveryView: v = !1,
160
184
  animateDurationMs: b = 1600,
161
185
  animateLocale: n,
162
- animateSeparators: h,
163
- variant: x = "default",
186
+ animateSeparators: x,
187
+ variant: h = "default",
164
188
  size: y = "md",
165
189
  align: I = "start",
166
- className: M,
167
- ...j
168
- }, k) => {
169
- const { i18n: B } = U(), R = X(), f = e ?? B.language, K = L(() => {
190
+ intent: M = "foreground",
191
+ className: j,
192
+ ...k
193
+ }, R) => {
194
+ const { i18n: K } = B(), T = Z(), f = e ?? K.language, _ = O(() => {
170
195
  if (typeof t == "string") return t;
171
196
  switch (c) {
172
197
  case "currency":
@@ -186,10 +211,10 @@ const dt = Q(
186
211
  return new Intl.NumberFormat(f).format(t);
187
212
  }
188
213
  }, [t, c, f, a])(), N = n ?? f;
189
- Z(!1);
190
- const r = tt(() => s ? typeof t == "number" ? Number.isFinite(t) ? { target: t, sign: "", suffix: "" } : null : it(t, N) : null, [s, t, N]), Y = s && r !== null, _ = (r == null ? void 0 : r.target) ?? 0, F = (r == null ? void 0 : r.sign) ?? "", T = (r == null ? void 0 : r.suffix) ?? "", q = L(
214
+ tt(!1);
215
+ const r = et(() => s ? typeof t == "number" ? Number.isFinite(t) ? { target: t, sign: "", suffix: "" } : null : dt(t, N) : null, [s, t, N]), Y = s && r !== null, q = (r == null ? void 0 : r.target) ?? 0, F = (r == null ? void 0 : r.sign) ?? "", $ = (r == null ? void 0 : r.suffix) ?? "", H = O(
191
216
  (w) => {
192
- const C = (() => {
217
+ const E = (() => {
193
218
  try {
194
219
  return new Intl.NumberFormat(N, {
195
220
  useGrouping: !0
@@ -199,46 +224,46 @@ const dt = Q(
199
224
  }
200
225
  })();
201
226
  let p;
202
- if (C)
203
- if (h) {
204
- const W = Math.abs(w), A = Math.trunc(W), D = W - A, H = h.thousand ?? "", S = String(A).replace(
227
+ if (E)
228
+ if (x) {
229
+ const A = Math.abs(w), D = Math.trunc(A), G = A - D, J = x.thousand ?? "", S = String(D).replace(
205
230
  /\B(?=(\d{3})+(?!\d))/g,
206
- H
231
+ J
207
232
  );
208
- if (D === 0)
233
+ if (G === 0)
209
234
  p = S;
210
235
  else {
211
- const G = D.toFixed(6).replace(/0+$/, "").slice(2), J = h.decimal ?? ".";
212
- p = G ? S + J + G : S;
236
+ const L = G.toFixed(6).replace(/0+$/, "").slice(2), Q = x.decimal ?? ".";
237
+ p = L ? S + Q + L : S;
213
238
  }
214
239
  } else
215
- p = C.format(Math.abs(w));
240
+ p = E.format(Math.abs(w));
216
241
  else
217
242
  p = String(Math.abs(w));
218
- let E = F;
219
- return F === "" && w < 0 && (E = "-"), `${E}${p}${T}`;
243
+ let W = F;
244
+ return F === "" && w < 0 && (W = "-"), `${W}${p}${$}`;
220
245
  },
221
- [N, h, F, T]
222
- ), $ = et({
223
- to: _,
246
+ [N, x, F, $]
247
+ ), C = st({
248
+ to: q,
224
249
  from: 0,
225
250
  durationMs: b,
226
251
  startOnVisible: !0,
227
252
  retriggerOnReEntry: v,
228
253
  // `formatter` is the only path we use — it owns both the locale
229
254
  // formatting and the sign/suffix re-application.
230
- formatter: q
255
+ formatter: H
231
256
  });
232
257
  return g ? /* @__PURE__ */ z(
233
258
  "div",
234
259
  {
235
- ref: k,
260
+ ref: R,
236
261
  role: "group",
237
262
  "aria-busy": "true",
238
263
  "aria-label": d,
239
264
  "data-component": "stat",
240
- className: O({ variant: x, size: y, align: I, className: M }),
241
- ...j,
265
+ className: P({ variant: h, size: y, align: I, className: j }),
266
+ ...k,
242
267
  children: [
243
268
  /* @__PURE__ */ i("div", { className: "ds:h-[var(--skeleton-label-h)] ds:w-[var(--skeleton-label-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]" }),
244
269
  /* @__PURE__ */ i("div", { className: "ds:h-[var(--skeleton-value-h)] ds:w-[var(--skeleton-value-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]" })
@@ -247,15 +272,15 @@ const dt = Q(
247
272
  ) : /* @__PURE__ */ z(
248
273
  "div",
249
274
  {
250
- ref: k,
275
+ ref: R,
251
276
  role: "group",
252
- "aria-labelledby": R,
277
+ "aria-labelledby": T,
253
278
  "data-component": "stat",
254
- className: O({ variant: x, size: y, align: I, className: M }),
255
- ...j,
279
+ className: P({ variant: h, size: y, align: I, className: j }),
280
+ ...k,
256
281
  children: [
257
282
  /* @__PURE__ */ z("span", { className: "ds:inline-flex ds:items-center", children: [
258
- u && /* @__PURE__ */ i(
283
+ m && /* @__PURE__ */ i(
259
284
  "span",
260
285
  {
261
286
  "aria-hidden": "true",
@@ -268,13 +293,13 @@ const dt = Q(
268
293
  "ds:text-[color:var(--accent)]",
269
294
  "ds:forced-colors:text-[CanvasText]"
270
295
  ].join(" "),
271
- children: u
296
+ children: m
272
297
  }
273
298
  ),
274
299
  /* @__PURE__ */ i(
275
300
  "span",
276
301
  {
277
- id: R,
302
+ id: T,
278
303
  className: "type-label ds:text-[var(--muted-foreground)]",
279
304
  children: d
280
305
  }
@@ -289,19 +314,19 @@ const dt = Q(
289
314
  /* @__PURE__ */ i(
290
315
  "span",
291
316
  {
292
- ref: $.ref,
317
+ ref: C.ref,
293
318
  "aria-live": "off",
294
- className: P({ size: y, variant: x }),
295
- children: $.value
319
+ className: U({ size: y, variant: h, intent: M }),
320
+ children: C.value
296
321
  }
297
322
  )
298
- ) : /* @__PURE__ */ i("span", { className: P({ size: y, variant: x }), children: K }),
299
- l != null && o != null && /* @__PURE__ */ i(
300
- nt,
323
+ ) : /* @__PURE__ */ i("span", { className: U({ size: y, variant: h, intent: M }), children: _ }),
324
+ o != null && l != null && /* @__PURE__ */ i(
325
+ it,
301
326
  {
302
- trend: l,
303
- delta: o,
304
- deltaFormat: m,
327
+ trend: o,
328
+ delta: l,
329
+ deltaFormat: u,
305
330
  locale: e
306
331
  }
307
332
  )
@@ -310,8 +335,8 @@ const dt = Q(
310
335
  );
311
336
  }
312
337
  );
313
- dt.displayName = "Stat";
338
+ ct.displayName = "Stat";
314
339
  export {
315
- dt as S
340
+ ct as S
316
341
  };
317
- //# sourceMappingURL=stat-EC2Papj7.js.map
342
+ //# sourceMappingURL=stat-Bs80Z6Yv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat-Bs80Z6Yv.js","sources":["../../src/components/stat/stat.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useId,\n useMemo,\n useRef,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useCountUp } from '../../hooks/use-count-up';\n\n/* ------------------------------------------------------------------ */\n/* CVA — stat root */\n/* ------------------------------------------------------------------ */\n\n// `h-full` lets Stats grow to fill a flex / grid parent's cell, so a\n// row paired with taller cards (BenefitCard, Card, etc.) reads as a\n// matching set instead of mismatched heights. In a non-stretching\n// parent (block flow, inline) it's a no-op — block-size defers to\n// content as before. The flex-col inside still pins label/icon row\n// at the top and the number below, so growing the card adds the\n// extra space below the number instead of inserting it between\n// label and value.\nconst statVariants = cva('ds:flex ds:flex-col ds:h-full', {\n variants: {\n variant: {\n default: 'ds:gap-[var(--spacing-xs)]',\n outlined: [\n 'ds:gap-[var(--spacing-xs)]',\n 'ds:border ds:border-[color:var(--border)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n ].join(' '),\n // White card surface with the shared card shadow + border —\n // matches `Card variant=\"elevated\"` and `BenefitCard.elevated`\n // tokens (`--card`, `--card-border`, `--shadow-card`,\n // `--radius-lg`) so a grid of elevated Stats reads as a set of\n // shaded panels without nesting a Card around each one. The\n // border is essential in dark mode: shadow alone on a dark\n // surface loses contrast and the card boundary disappears.\n // Accessible theme bumps to `border-2` to match Card / Benefit-\n // Card's 0.31.5 accessibility uplift.\n elevated: [\n 'ds:gap-[var(--spacing-xs)]',\n 'ds:bg-[var(--card)]',\n 'ds:text-[var(--card-foreground)]',\n 'ds:border ds:border-[color:var(--card-border)]',\n 'ds:[.theme-accessible_&]:border-2',\n 'ds:shadow-[var(--shadow-card)]',\n 'ds:rounded-[var(--radius-lg)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:pt-[var(--spacing-md)] ds:pb-[var(--spacing-md)]',\n // Forced-colors: UA strips shadow, so render a border as the\n // separation cue — mirrors Card's forced-colors behaviour.\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n compact: 'ds:gap-[var(--spacing-none)]',\n },\n size: {\n sm: '',\n md: '',\n lg: '',\n },\n align: {\n start: 'ds:items-start ds:text-start',\n center: 'ds:items-center ds:text-center',\n end: 'ds:items-end ds:text-end',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n align: 'start',\n },\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — value element */\n/* ------------------------------------------------------------------ */\n\nconst valueVariants = cva('type-metric', {\n variants: {\n size: {\n sm: 'ds:[--type-metric-size:var(--font-size-xl)]',\n md: 'ds:[--type-metric-size:var(--font-size-3xl)]',\n lg: 'ds:[--type-metric-size:var(--font-size-5xl)]',\n },\n variant: {\n default: '',\n outlined: '',\n elevated: '',\n compact: '',\n },\n // Colour of the headline metric value. Defaults to `--foreground`\n // (the existing render). `primary` / `accent` are the brand intents\n // — use for hero / marketing stats where the number IS the visual\n // marker. `success` / `destructive` / `info` / `warning` map to the\n // semantic tokens for KPI tiles that want to signal status via the\n // value colour itself (e.g. revenue green, debt red). The trend\n // chevron and the label colour are independent of this prop.\n intent: {\n foreground: 'ds:text-[var(--foreground)]',\n primary: 'ds:text-[var(--primary)]',\n accent: 'ds:text-[var(--accent)]',\n success: 'ds:text-[var(--success)]',\n destructive: 'ds:text-[var(--destructive)]',\n info: 'ds:text-[var(--info)]',\n warning: 'ds:text-[var(--warning)]',\n },\n },\n compoundVariants: [\n {\n variant: 'compact',\n size: 'sm',\n className: 'ds:[--type-metric-size:var(--font-size-lg)]',\n },\n {\n variant: 'compact',\n size: 'md',\n className: 'ds:[--type-metric-size:var(--font-size-xl)]',\n },\n {\n variant: 'compact',\n size: 'lg',\n className: 'ds:[--type-metric-size:var(--font-size-2xl)]',\n },\n ],\n defaultVariants: {\n size: 'md',\n variant: 'default',\n intent: 'foreground',\n },\n});\n\n/* ------------------------------------------------------------------ */\n/* CVA — trend element */\n/* ------------------------------------------------------------------ */\n\nconst trendVariants = cva(\n 'ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] type-label',\n {\n variants: {\n trend: {\n up: 'ds:text-[var(--success)]',\n down: 'ds:text-[var(--destructive)]',\n flat: 'ds:text-[var(--muted-foreground)]',\n },\n },\n defaultVariants: {\n trend: 'flat',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* StatTrend (internal — not exported) */\n/* ------------------------------------------------------------------ */\n\ninterface StatTrendProps {\n trend: 'up' | 'down' | 'flat';\n delta: number | string;\n deltaFormat?: 'decimal' | 'percent';\n locale?: string;\n}\n\nconst ARROW = { up: '↑', down: '↓', flat: '→' } as const;\nconst TREND_KEY = {\n up: 'stat.trend.up',\n down: 'stat.trend.down',\n flat: 'stat.trend.flat',\n} as const;\n\nfunction StatTrend({\n trend,\n delta,\n deltaFormat = 'decimal',\n locale,\n}: StatTrendProps) {\n const { t, i18n } = useTranslation();\n\n const formattedDelta =\n typeof delta === 'string'\n ? delta\n : new Intl.NumberFormat(locale ?? i18n.language, {\n style: deltaFormat === 'percent' ? 'percent' : 'decimal',\n }).format(deltaFormat === 'percent' ? delta / 100 : delta);\n\n return (\n <span className={trendVariants({ trend })}>\n <span aria-hidden=\"true\">{ARROW[trend]}</span>\n <span className=\"ds:sr-only\">{t(TREND_KEY[trend])}</span>\n {formattedDelta}\n </span>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Parse a string value into a numeric target for the count-up */\n/* ------------------------------------------------------------------ */\n\ntype ParsedValue = {\n /** Numeric target for the count-up. */\n target: number;\n /** Leading sign captured from the input string (e.g. \"+\" / \"-\"). */\n sign: '' | '+' | '-';\n /** Trailing shorthand suffix (e.g. \"K\" / \"M\" / \"B\") to re-append. */\n suffix: string;\n};\n\n/**\n * Strip locale-aware separators, a leading sign, and the K/M/B\n * shorthand suffix from a pre-formatted string so the count-up has a\n * pure numeric target to animate towards. Returns `null` for any input\n * that can't be parsed — the caller short-circuits to static rendering\n * in that case.\n */\nfunction parseStatValue(raw: string, locale: string): ParsedValue | null {\n const trimmed = raw.trim();\n if (trimmed === '') return null;\n\n // Capture leading sign so we can re-attach it every frame. Stat's\n // marketing usage (\"+500.000\", \"-12\") often relies on it.\n let sign: '' | '+' | '-' = '';\n let body = trimmed;\n if (body.startsWith('+')) {\n sign = '+';\n body = body.slice(1).trimStart();\n } else if (body.startsWith('-') || body.startsWith('−')) {\n // Hyphen-minus or the typographic minus sign — both treated as -.\n sign = '-';\n body = body.slice(1).trimStart();\n }\n\n // Trailing K / M / B shorthand (case-insensitive). Re-append verbatim\n // so \"+1.5K\" renders as \"+1.5K\" at every frame.\n let suffix = '';\n const suffixMatch = body.match(/[KMB]$/i);\n if (suffixMatch) {\n suffix = suffixMatch[0];\n body = body.slice(0, -1).trimEnd();\n }\n\n // Discover the locale's group + decimal glyphs from a probe value.\n // formatToParts is the canonical way; we fall back to `.` decimal /\n // `,` group if Intl can't tell us (no-locale envs).\n let group = '';\n let decimal = '.';\n try {\n const probe = new Intl.NumberFormat(locale).formatToParts(12345.6);\n for (const part of probe) {\n if (part.type === 'group') group = part.value;\n else if (part.type === 'decimal') decimal = part.value;\n }\n } catch {\n /* swallow — defaults already set */\n }\n\n // Heuristic for input strings that look like JS-native decimals\n // (e.g. `\"1500.25\"`) regardless of the requested locale: if the body\n // is a clean US-style decimal AND the fraction after the `.` is NOT\n // a three-digit thousands group in a locale that uses `.` as the\n // group separator, treat it as a direct numeric literal. This covers\n // the common case where a caller types `value=\"1500.25\"` and expects\n // the count-up to land on 1500.25 even though the output locale is\n // it-IT (which uses `.` for thousands).\n const usStyleMatch = body.match(/^(\\d+)\\.(\\d+)$/);\n if (usStyleMatch) {\n const fractionLen = usStyleMatch[2].length;\n if (!(fractionLen === 3 && group === '.')) {\n const direct = Number.parseFloat(body);\n if (Number.isFinite(direct)) {\n return { target: direct, sign, suffix };\n }\n }\n }\n\n // Strip every group separator we discovered, then normalise the\n // decimal separator to `.` so JS can parseFloat the result.\n // Note: when the locale's group separator is empty (e.g. some\n // numbering systems) the replace is a no-op.\n let normalised = body;\n if (group !== '') {\n normalised = normalised.split(group).join('');\n }\n if (decimal !== '.') {\n normalised = normalised.split(decimal).join('.');\n }\n\n // Defence-in-depth: strip whitespace plus NBSP (U+00A0) and NARROW\n // NO-BREAK SPACE (U+202F) that some locales (fr-FR, it-IT) use as\n // thousand separators. Hex escapes keep this source ASCII-clean.\n normalised = normalised.replace(/[\\s\\u00A0\\u202F]/g, '');\n\n const numeric = Number.parseFloat(normalised);\n if (!Number.isFinite(numeric)) return null;\n\n return { target: numeric, sign, suffix };\n}\n\n/* ------------------------------------------------------------------ */\n/* StatProps */\n/* ------------------------------------------------------------------ */\n\nexport interface StatProps\n extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof statVariants> {\n /** Metric label rendered above the value. */\n label: string;\n /** Numeric or pre-formatted string value. */\n value: number | string;\n /** Number formatting style. Omit to use default decimal formatting. */\n format?: 'decimal' | 'currency' | 'percent';\n /** ISO 4217 currency code — required when format=\"currency\". */\n currency?: string;\n /** BCP 47 locale override. Defaults to the active i18n language. */\n locale?: string;\n /** Trend direction. Requires `delta` to render the trend row. */\n trend?: 'up' | 'down' | 'flat';\n /** Trend delta magnitude, e.g. 12 for \"↑ 12%\". */\n delta?: number | string;\n /** Number formatting style for the delta. Default \"decimal\". */\n deltaFormat?: 'decimal' | 'percent';\n /** Optional leading icon rendered at the start of the label row. */\n icon?: ReactNode;\n /**\n * Colour of the headline value. Defaults to `foreground`. Brand\n * intents (`primary`, `accent`) are for hero / marketing stats where\n * the number is the visual marker. Semantic intents\n * (`success`, `destructive`, `info`, `warning`) signal status via\n * the value colour itself — e.g. revenue green, debt red on KPI\n * tiles. Trend chevron and label colour are independent.\n */\n intent?:\n | 'foreground'\n | 'primary'\n | 'accent'\n | 'success'\n | 'destructive'\n | 'info'\n | 'warning';\n /** Renders animated skeleton placeholders instead of content. */\n loading?: boolean;\n /**\n * Animate the numeric value from 0 (or from the captured leading\n * sign) to the final value when the Stat first scrolls into view.\n * Default `false`. Marketing surfaces opt in; dashboards leave it\n * off so live metrics render immediately.\n */\n animate?: boolean;\n /**\n * When `true`, the count-up re-plays every time the Stat scrolls\n * out of view and back in. Default `false` — animate once per\n * element per session, matching the booking-website hero pattern.\n * Ignored under `prefers-reduced-motion: reduce`.\n */\n animateOnEveryView?: boolean;\n /** Animation duration in milliseconds. Default 1600. */\n animateDurationMs?: number;\n /**\n * BCP 47 locale used for the per-frame count-up formatting. Falls\n * back to `locale`, then to the active i18n language.\n */\n animateLocale?: string;\n /**\n * Override the locale's thousand / decimal glyphs for the count-up.\n * Wins over locale defaults. Pass partial overrides — `decimal`\n * alone is valid; the unspecified separator stays at the locale\n * default.\n */\n animateSeparators?: {\n thousand?: string;\n decimal?: string;\n };\n}\n\n/* ------------------------------------------------------------------ */\n/* Stat */\n/* ------------------------------------------------------------------ */\n\nexport const Stat = forwardRef<HTMLDivElement, StatProps>(\n (\n {\n label,\n value,\n format,\n currency,\n locale,\n trend,\n delta,\n deltaFormat = 'decimal',\n icon,\n loading = false,\n animate = false,\n animateOnEveryView = false,\n animateDurationMs = 1600,\n animateLocale,\n animateSeparators,\n variant = 'default',\n size = 'md',\n align = 'start',\n intent = 'foreground',\n className,\n ...props\n },\n ref,\n ) => {\n const { i18n } = useTranslation();\n const labelId = useId();\n const lang = locale ?? i18n.language;\n\n /* -------------------------------------------------- */\n /* Static formatting — the value as it would appear */\n /* in the non-animated (or post-animation) state. */\n /* -------------------------------------------------- */\n\n const formatValue = useCallback((): string => {\n if (typeof value === 'string') return value;\n\n switch (format) {\n case 'currency':\n return new Intl.NumberFormat(lang, {\n style: 'currency',\n currency: currency ?? 'USD',\n }).format(value);\n case 'percent':\n return new Intl.NumberFormat(lang, { style: 'percent' }).format(\n value,\n );\n case 'decimal':\n return new Intl.NumberFormat(lang, { style: 'decimal' }).format(\n value,\n );\n default:\n return new Intl.NumberFormat(lang).format(value);\n }\n }, [value, format, lang, currency]);\n\n const staticValue = formatValue();\n\n /* -------------------------------------------------- */\n /* Parse the value into a numeric target for the */\n /* count-up. Numeric values use `value` directly; */\n /* string values are stripped of sign / shorthand / */\n /* locale separators and re-decorated each frame. */\n /* -------------------------------------------------- */\n\n const animationLocale = animateLocale ?? lang;\n const hasWarnedRef = useRef<boolean>(false);\n\n const parsed = useMemo<ParsedValue | null>(() => {\n if (!animate) return null;\n if (typeof value === 'number') {\n // Numeric: target is the number itself; no sign / suffix to\n // re-attach.\n return Number.isFinite(value)\n ? { target: value, sign: '', suffix: '' }\n : null;\n }\n return parseStatValue(value, animationLocale);\n }, [animate, value, animationLocale]);\n\n // Dev-mode warning when an animate-flagged Stat has an unparseable\n // string value. Render static, no throw — one warn per component.\n if (\n animate &&\n typeof value === 'string' &&\n parsed === null &&\n import.meta.env.DEV &&\n !hasWarnedRef.current\n ) {\n hasWarnedRef.current = true;\n console.warn(\n `Stat: value=\"${value}\" couldn't be parsed for the count-up animation. Rendering static.`,\n );\n }\n\n const shouldAnimate = animate && parsed !== null;\n\n /* -------------------------------------------------- */\n /* Wire the hook unconditionally — rules-of-hooks. */\n /* When `shouldAnimate` is false the hook still runs */\n /* but `to === from` so it's a no-op visually. */\n /* -------------------------------------------------- */\n\n const target = parsed?.target ?? 0;\n const sign = parsed?.sign ?? '';\n const suffix = parsed?.suffix ?? '';\n\n // Wrap the count-up formatter so the captured sign + suffix are\n // re-applied every frame. The hook hands us the locale-formatted\n // magnitude; we own the decoration around it.\n const formatter = useCallback(\n (n: number) => {\n // Use the absolute value for the magnitude so the captured\n // sign is the sole source of the rendered sign. Negative\n // numbers passed in (e.g. `to: -12`) come through unsigned;\n // we re-apply via `sign`. Always force `useGrouping: true` so\n // ICU's locale-default `min2` doesn't suppress the thousand\n // glyph on 4-digit values like 1.000 (it-IT). The user wrote\n // a stat value — they want it grouped.\n const magnitudeNF = (() => {\n try {\n return new Intl.NumberFormat(animationLocale, {\n useGrouping: true,\n });\n } catch {\n return null;\n }\n })();\n\n let magnitudeStr: string;\n if (magnitudeNF) {\n if (animateSeparators) {\n // Hand-build the grouped magnitude so we don't depend on\n // ICU's locale-by-locale grouping defaults (which differ\n // between engines and can drop the group at 4-digit\n // thresholds even with `useGrouping: true`). Locale only\n // influences sign handling, which we apply separately.\n const abs = Math.abs(n);\n const intPart = Math.trunc(abs);\n const fracPart = abs - intPart;\n const groupGlyph = animateSeparators.thousand ?? '';\n const intStr = String(intPart).replace(\n /\\B(?=(\\d{3})+(?!\\d))/g,\n groupGlyph,\n );\n if (fracPart === 0) {\n magnitudeStr = intStr;\n } else {\n const fracStr = fracPart.toFixed(6).replace(/0+$/, '').slice(2);\n const decimalGlyph = animateSeparators.decimal ?? '.';\n magnitudeStr = fracStr ? intStr + decimalGlyph + fracStr : intStr;\n }\n } else {\n magnitudeStr = magnitudeNF.format(Math.abs(n));\n }\n } else {\n magnitudeStr = String(Math.abs(n));\n }\n\n // Re-derive the sign every frame: the captured sign wins, but\n // a negative `to` with no leading sign in the source still\n // renders with a leading \"-\" so the final formatted output\n // matches locale conventions.\n let resolvedSign: string = sign;\n if (sign === '' && n < 0) resolvedSign = '-';\n\n return `${resolvedSign}${magnitudeStr}${suffix}`;\n },\n [animationLocale, animateSeparators, sign, suffix],\n );\n\n const countUp = useCountUp({\n to: target,\n from: 0,\n durationMs: animateDurationMs,\n startOnVisible: true,\n retriggerOnReEntry: animateOnEveryView,\n // `formatter` is the only path we use — it owns both the locale\n // formatting and the sign/suffix re-application.\n formatter,\n });\n\n /* -------------------------------------------------- */\n /* Loading state */\n /* -------------------------------------------------- */\n\n if (loading) {\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-busy=\"true\"\n aria-label={label}\n data-component=\"stat\"\n className={statVariants({ variant, size, align, className })}\n {...props}\n >\n <div className=\"ds:h-[var(--skeleton-label-h)] ds:w-[var(--skeleton-label-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]\" />\n <div className=\"ds:h-[var(--skeleton-value-h)] ds:w-[var(--skeleton-value-w)] ds:animate-pulse ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)]\" />\n </div>\n );\n }\n\n /* -------------------------------------------------- */\n /* Render */\n /* -------------------------------------------------- */\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-labelledby={labelId}\n data-component=\"stat\"\n className={statVariants({ variant, size, align, className })}\n {...props}\n >\n <span className=\"ds:inline-flex ds:items-center\">\n {icon && (\n <span\n aria-hidden=\"true\"\n className={[\n 'ds:me-[var(--spacing-xs)] ds:inline-flex ds:shrink-0',\n // Accent tint on the leading icon. The icon is decorative\n // (aria-hidden), so magenta-500's 3.2:1 contrast on white\n // is acceptable here — the Stat label + value still\n // carry the accessible name at `--foreground`.\n 'ds:text-[color:var(--accent)]',\n 'ds:forced-colors:text-[CanvasText]',\n ].join(' ')}\n >\n {icon}\n </span>\n )}\n <span\n id={labelId}\n className=\"type-label ds:text-[var(--muted-foreground)]\"\n >\n {label}\n </span>\n </span>\n {shouldAnimate ? (\n // The animated number is wrapped in an `aria-live=\"off\"` span\n // so screen readers don't announce every interpolated frame.\n // The `role=\"group\"` ancestor (with `aria-labelledby` pointing\n // at the label) carries the final accessible reading — the\n // animated frames are decorative only.\n <span\n ref={countUp.ref}\n aria-live=\"off\"\n className={valueVariants({ size, variant, intent })}\n >\n {countUp.value}\n </span>\n ) : (\n <span className={valueVariants({ size, variant, intent })}>\n {staticValue}\n </span>\n )}\n {trend != null && delta != null && (\n <StatTrend\n trend={trend}\n delta={delta}\n deltaFormat={deltaFormat}\n locale={locale}\n />\n )}\n </div>\n );\n },\n);\n\nStat.displayName = 'Stat';\n"],"names":["statVariants","cva","valueVariants","trendVariants","ARROW","TREND_KEY","StatTrend","trend","delta","deltaFormat","locale","t","i18n","useTranslation","formattedDelta","jsx","parseStatValue","raw","trimmed","sign","body","suffix","suffixMatch","group","decimal","probe","part","usStyleMatch","direct","normalised","numeric","Stat","forwardRef","label","value","format","currency","icon","loading","animate","animateOnEveryView","animateDurationMs","animateLocale","animateSeparators","variant","size","align","intent","className","props","ref","labelId","useId","lang","staticValue","useCallback","animationLocale","useRef","parsed","useMemo","shouldAnimate","target","formatter","n","magnitudeNF","magnitudeStr","abs","intPart","fracPart","groupGlyph","intStr","fracStr","decimalGlyph","resolvedSign","countUp","useCountUp","jsxs"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "0.32.1",
3
+ "packageVersion": "0.32.3",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -1,4 +1,4 @@
1
- import { B as a } from "../../_chunks/benefit-card-_Sc-MGha.js";
1
+ import { B as a } from "../../_chunks/benefit-card-Xnxj4Gmo.js";
2
2
  export {
3
3
  a as BenefitCard
4
4
  };
@@ -1,4 +1,4 @@
1
- import { S as o } from "../../_chunks/stat-EC2Papj7.js";
1
+ import { S as o } from "../../_chunks/stat-Bs80Z6Yv.js";
2
2
  export {
3
3
  o as Stat
4
4
  };
@@ -24,6 +24,15 @@ export interface StatProps extends HTMLAttributes<HTMLDivElement>, VariantProps<
24
24
  deltaFormat?: 'decimal' | 'percent';
25
25
  /** Optional leading icon rendered at the start of the label row. */
26
26
  icon?: ReactNode;
27
+ /**
28
+ * Colour of the headline value. Defaults to `foreground`. Brand
29
+ * intents (`primary`, `accent`) are for hero / marketing stats where
30
+ * the number is the visual marker. Semantic intents
31
+ * (`success`, `destructive`, `info`, `warning`) signal status via
32
+ * the value colour itself — e.g. revenue green, debt red on KPI
33
+ * tiles. Trend chevron and label colour are independent.
34
+ */
35
+ intent?: 'foreground' | 'primary' | 'accent' | 'success' | 'destructive' | 'info' | 'warning';
27
36
  /** Renders animated skeleton placeholders instead of content. */
28
37
  loading?: boolean;
29
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../../src/components/stat/stat.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAgBlE,QAAA,MAAM,YAAY;;;;8EA6ChB,CAAC;AAoNH,MAAM,WAAW,SACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,OAAO,YAAY,CAAC;IACzE,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,gEAAgE;IAChE,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAMD,eAAO,MAAM,IAAI,sGA8QhB,CAAC"}
1
+ {"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../../src/components/stat/stat.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAgBlE,QAAA,MAAM,YAAY;;;;8EAoDhB,CAAC;AAqOH,MAAM,WAAW,SACf,SAAQ,cAAc,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,OAAO,YAAY,CAAC;IACzE,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,uEAAuE;IACvE,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,gEAAgE;IAChE,WAAW,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IACpC,oEAAoE;IACpE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;OAOG;IACH,MAAM,CAAC,EACH,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,SAAS,GACT,aAAa,GACb,MAAM,GACN,SAAS,CAAC;IACd,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wDAAwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAMD,eAAO,MAAM,IAAI,sGA+QhB,CAAC"}