@nswds/app 1.102.0 → 1.104.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.
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var AccordionPrimitive = require('@radix-ui/react-accordion');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
- var clsx12 = require('clsx');
5
+ var clsx13 = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var classVarianceAuthority = require('class-variance-authority');
8
8
  var AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
@@ -40,8 +40,8 @@ var LabelPrimitive = require('@radix-ui/react-label');
40
40
  var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
41
41
  var TabsPrimitives = require('@radix-ui/react-tabs');
42
42
  var CollapsiblePrimitive = require('@radix-ui/react-collapsible');
43
+ var SheetPrimitive = require('@radix-ui/react-dialog');
43
44
  var cmdk = require('cmdk');
44
- var DialogPrimitive = require('@radix-ui/react-dialog');
45
45
  var ContextMenuPrimitive = require('@radix-ui/react-context-menu');
46
46
  var reactTable = require('@tanstack/react-table');
47
47
  var SeparatorPrimitive = require('@radix-ui/react-separator');
@@ -89,7 +89,7 @@ function _interopNamespace(e) {
89
89
  }
90
90
 
91
91
  var AccordionPrimitive__namespace = /*#__PURE__*/_interopNamespace(AccordionPrimitive);
92
- var clsx12__default = /*#__PURE__*/_interopDefault(clsx12);
92
+ var clsx13__default = /*#__PURE__*/_interopDefault(clsx13);
93
93
  var AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(AlertDialogPrimitive);
94
94
  var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
95
95
  var Headless4__namespace = /*#__PURE__*/_interopNamespace(Headless4);
@@ -110,7 +110,7 @@ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
110
110
  var RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(RadioGroupPrimitive);
111
111
  var TabsPrimitives__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitives);
112
112
  var CollapsiblePrimitive__namespace = /*#__PURE__*/_interopNamespace(CollapsiblePrimitive);
113
- var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespace(DialogPrimitive);
113
+ var SheetPrimitive__namespace = /*#__PURE__*/_interopNamespace(SheetPrimitive);
114
114
  var ContextMenuPrimitive__namespace = /*#__PURE__*/_interopNamespace(ContextMenuPrimitive);
115
115
  var SeparatorPrimitive__namespace = /*#__PURE__*/_interopNamespace(SeparatorPrimitive);
116
116
  var ToggleGroupPrimitive__namespace = /*#__PURE__*/_interopNamespace(ToggleGroupPrimitive);
@@ -4054,7 +4054,7 @@ var Icons = {
4054
4054
  zoom_out_map: (props) => /* @__PURE__ */ jsxRuntime.jsx("svg", { fill: "currentColor", "data-slot": "icon", viewBox: "0 -960 960 960", ...props, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M256-200h64q17 0 28.5 11.5T360-160q0 17-11.5 28.5T320-120H160q-17 0-28.5-11.5T120-160v-160q0-17 11.5-28.5T160-360q17 0 28.5 11.5T200-320v64l96-96q11-11 28-11t28 11q11 11 11 28t-11 28l-96 96Zm448 0-96-96q-11-11-11-28t11-28q11-11 28-11t28 11l96 96v-64q0-17 11.5-28.5T800-360q17 0 28.5 11.5T840-320v160q0 17-11.5 28.5T800-120H640q-17 0-28.5-11.5T600-160q0-17 11.5-28.5T640-200h64ZM200-704v64q0 17-11.5 28.5T160-600q-17 0-28.5-11.5T120-640v-160q0-17 11.5-28.5T160-840h160q17 0 28.5 11.5T360-800q0 17-11.5 28.5T320-760h-64l96 96q11 11 11 28t-11 28q-11 11-28 11t-28-11l-96-96Zm560 0-96 96q-11 11-28 11t-28-11q-11-11-11-28t11-28l96-96h-64q-17 0-28.5-11.5T600-800q0-17 11.5-28.5T640-840h160q17 0 28.5 11.5T840-800v160q0 17-11.5 28.5T800-600q-17 0-28.5-11.5T760-640v-64Z" }) })
4055
4055
  };
4056
4056
  function cn(...inputs) {
4057
- return tailwindMerge.twMerge(clsx12.clsx(inputs));
4057
+ return tailwindMerge.twMerge(clsx13.clsx(inputs));
4058
4058
  }
4059
4059
  function truncate(text, maxLength) {
4060
4060
  if (text.length <= maxLength) {
@@ -4553,7 +4553,7 @@ var Button2 = React5.forwardRef(function Button3({ className, variant, color: co
4553
4553
  {
4554
4554
  "data-variant": variant,
4555
4555
  ...props,
4556
- className: clsx12__default.default(classes, "cursor-pointer"),
4556
+ className: clsx13__default.default(classes, "cursor-pointer"),
4557
4557
  ref,
4558
4558
  children: /* @__PURE__ */ jsxRuntime.jsx(TouchTarget, { children })
4559
4559
  }
@@ -6012,7 +6012,7 @@ var BadgeButton = React5.forwardRef(function BadgeButton2({
6012
6012
  children,
6013
6013
  ...props
6014
6014
  }, ref) {
6015
- const classes = clsx12__default.default(className, focusOutline[color2], [
6015
+ const classes = clsx13__default.default(className, focusOutline[color2], [
6016
6016
  // Base
6017
6017
  "group relative inline-flex rounded-sm",
6018
6018
  // Focus
@@ -6034,7 +6034,7 @@ var BadgeButton = React5.forwardRef(function BadgeButton2({
6034
6034
  {
6035
6035
  "data-variant": variant,
6036
6036
  ...props,
6037
- className: clsx12__default.default(classes, "cursor-pointer"),
6037
+ className: clsx13__default.default(classes, "cursor-pointer"),
6038
6038
  ref,
6039
6039
  children: /* @__PURE__ */ jsxRuntime.jsx(TouchTarget, { children: /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant, color: color2, size, children }) })
6040
6040
  }
@@ -14676,7 +14676,7 @@ function CodePreview({
14676
14676
  children: /* @__PURE__ */ jsxRuntime.jsx(
14677
14677
  "div",
14678
14678
  {
14679
- className: clsx12.clsx(
14679
+ className: clsx13.clsx(
14680
14680
  "group mx-auto bg-white bg-gradient-to-r dark:bg-grey-900",
14681
14681
  view === "desktop" && "w-full",
14682
14682
  view === "tablet" && "max-w-lg",
@@ -14944,7 +14944,7 @@ function ColorCard({ name, token, hex: hex2, rgb: rgb2, hsl, oklch: oklch2, form
14944
14944
  {
14945
14945
  className: "flex h-24 w-full items-center justify-center",
14946
14946
  style: { backgroundColor: hex2 },
14947
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: clsx12.clsx("font-medium", isLightColor(hex2) ? "text-primary-950" : "text-white"), children: name })
14947
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: clsx13.clsx("font-medium", isLightColor(hex2) ? "text-primary-950" : "text-white"), children: name })
14948
14948
  }
14949
14949
  ),
14950
14950
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
@@ -15277,7 +15277,7 @@ function Heading({
15277
15277
  ...props,
15278
15278
  id: computedId,
15279
15279
  "data-anchor": true,
15280
- className: clsx12__default.default(
15280
+ className: clsx13__default.default(
15281
15281
  className,
15282
15282
  trimClasses[trim],
15283
15283
  "m-0",
@@ -16357,6 +16357,2611 @@ function ColorPairingTool({
16357
16357
  const normalizedVisibleFormats = [...new Set(visibleFormats)];
16358
16358
  return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolLoading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolContent, { visibleFormats: normalizedVisibleFormats }) });
16359
16359
  }
16360
+ function Text({ className, trim = "normal", size = 2, label = false, ...props }) {
16361
+ const textSizeClasses = {
16362
+ 1: "text-[length:var(--font-size-1)] leading-[var(--line-height-28)] tracking-[var(--letter-spacing-0)]",
16363
+ 2: "text-[length:var(--font-size-2)] leading-[var(--line-height-24)] tracking-[var(--letter-spacing-0)]",
16364
+ 3: "text-[length:var(--font-size-3)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]",
16365
+ 4: "text-[length:var(--font-size-4)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]"
16366
+ };
16367
+ const labelSizeClasses = {
16368
+ 1: "text-[length:var(--font-size-1)] leading-[var(--line-height-24)] tracking-[var(--letter-spacing-0)]",
16369
+ 2: "text-[length:var(--font-size-2)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]",
16370
+ 3: "text-[length:var(--font-size-3)] leading-[var(--line-height-16)] tracking-[var(--letter-spacing-0)]",
16371
+ 4: "text-[length:var(--font-size-4)] leading-[var(--line-height-16)] tracking-[var(--letter-spacing-0)]"
16372
+ };
16373
+ const sizeClass = label ? labelSizeClasses[size] : textSizeClasses[size];
16374
+ const trimClasses = {
16375
+ normal: ["before:content-none after:content-none"],
16376
+ start: [
16377
+ 'before:content-[""] before:table after:content-none',
16378
+ "before:mb-[calc(var(--leading-trim-start,var(--default-leading-trim-start))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
16379
+ ],
16380
+ end: [
16381
+ 'before:content-none after:content-[""] after:table',
16382
+ "after:mt-[calc(var(--leading-trim-end,var(--default-leading-trim-end))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
16383
+ ],
16384
+ both: [
16385
+ 'before:content-[""] before:table after:content-[""] after:table',
16386
+ "before:mb-[calc(var(--leading-trim-start,var(--default-leading-trim-start))-var(--line-height,calc(1em*var(--default-line-height)))/2)]",
16387
+ "after:mt-[calc(var(--leading-trim-end,var(--default-leading-trim-end))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
16388
+ ]
16389
+ };
16390
+ return /* @__PURE__ */ jsxRuntime.jsx(
16391
+ "p",
16392
+ {
16393
+ "data-slot": "text",
16394
+ ...props,
16395
+ className: clsx13__default.default(className, trimClasses[trim], "text-grey-800 dark:text-grey-400", sizeClass)
16396
+ }
16397
+ );
16398
+ }
16399
+ function TextLink({ className, ...props }) {
16400
+ return /* @__PURE__ */ jsxRuntime.jsx(
16401
+ Link,
16402
+ {
16403
+ ...props,
16404
+ className: clsx13__default.default(
16405
+ className,
16406
+ "text-primary-800 underline decoration-primary-800/50 data-hover:decoration-primary-800 dark:text-white dark:decoration-white/50 dark:data-hover:decoration-white"
16407
+ )
16408
+ }
16409
+ );
16410
+ }
16411
+ function Strong({ className, ...props }) {
16412
+ return /* @__PURE__ */ jsxRuntime.jsx("strong", { ...props, className: clsx13__default.default(className, "font-medium text-grey-950 dark:text-white") });
16413
+ }
16414
+ function Code({ className, ...props }) {
16415
+ const hasLanguageClass = typeof className === "string" && className.includes("language-");
16416
+ return /* @__PURE__ */ jsxRuntime.jsx(
16417
+ "code",
16418
+ {
16419
+ ...props,
16420
+ className: clsx13__default.default(
16421
+ className,
16422
+ !hasLanguageClass && "language-plaintext",
16423
+ "text-sm sm:text-[0.8125rem]"
16424
+ )
16425
+ }
16426
+ );
16427
+ }
16428
+ var PREFERRED_BACKGROUND_TONES2 = [400, 600, 200, 800, 100, 50];
16429
+ var DEFAULT_VISIBLE_FORMATS2 = ["hex", "rgb", "hsl", "oklch"];
16430
+ var DEFAULT_INITIAL_BACKGROUND_TOKEN2 = "nsw-blue-800";
16431
+ var DEFAULT_INITIAL_PAIR_ID2 = "nsw-blue-800:nsw-blue-200";
16432
+ function getToneFromToken2(token) {
16433
+ if (!token) return null;
16434
+ const match = token.match(/-(\d+)$/);
16435
+ return match ? Number.parseInt(match[1], 10) : null;
16436
+ }
16437
+ function getFamilySwatchColor2(family, preferredTone = 600) {
16438
+ const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
16439
+ if (exactMatch) {
16440
+ return exactMatch.hex;
16441
+ }
16442
+ const closestMatch = [...family.colors].sort(
16443
+ (left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
16444
+ )[0];
16445
+ return closestMatch?.hex ?? "transparent";
16446
+ }
16447
+ function getFamilySelectorLabel2(family, themeCategory, selectionRole) {
16448
+ if (themeCategory !== "aboriginal") {
16449
+ return family.label;
16450
+ }
16451
+ const preferredTone = selectionRole === "primary colour" ? 800 : 600;
16452
+ return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
16453
+ }
16454
+ function getPairingColorDisplayName2(color2) {
16455
+ return color2.name ?? color2.token;
16456
+ }
16457
+ function isWhiteForegroundPair2(pair) {
16458
+ return pair.foreground.token === "white";
16459
+ }
16460
+ function getWhiteForegroundGuidance2(pair) {
16461
+ if (pair.passes.aaaText) {
16462
+ return "White is approved for headings, body copy, and calls to action on this background.";
16463
+ }
16464
+ if (pair.passes.aaaLarge) {
16465
+ return "Use white only for WCAG large text on this background, such as headings at 24px+ or bold text at 18.5px+. Keep sentence-case body copy at 16px+ and use a darker recommended foreground instead.";
16466
+ }
16467
+ return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
16468
+ }
16469
+ function getPreviewGuidance2(pair, isRecommended) {
16470
+ if (!isWhiteForegroundPair2(pair)) {
16471
+ return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
16472
+ }
16473
+ if (isRecommended) {
16474
+ return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
16475
+ }
16476
+ return getWhiteForegroundGuidance2(pair);
16477
+ }
16478
+ function getReadableTextColor(tone) {
16479
+ return tone >= 600 ? "#ffffff" : "#002664";
16480
+ }
16481
+ function getPreferredPairForBackground2(pairs, preferredPairId) {
16482
+ if (preferredPairId) {
16483
+ const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
16484
+ if (preferredPair) {
16485
+ return preferredPair;
16486
+ }
16487
+ }
16488
+ return pairs.find((pair) => !isWhiteForegroundPair2(pair)) ?? pairs[0] ?? null;
16489
+ }
16490
+ function getDefaultBackgroundToken2(context) {
16491
+ for (const tone of PREFERRED_BACKGROUND_TONES2) {
16492
+ for (const group of context.backgroundGroups) {
16493
+ const match = group.backgrounds.find(
16494
+ (background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
16495
+ );
16496
+ if (match) {
16497
+ return match.token;
16498
+ }
16499
+ }
16500
+ }
16501
+ for (const tone of PREFERRED_BACKGROUND_TONES2) {
16502
+ for (const group of context.backgroundGroups) {
16503
+ const match = group.backgrounds.find((background) => background.tone === tone);
16504
+ if (match) {
16505
+ return match.token;
16506
+ }
16507
+ }
16508
+ }
16509
+ return context.backgrounds[0]?.token ?? "";
16510
+ }
16511
+ function resolveBackgroundToken2(context, preferredToken, preferredTone) {
16512
+ if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
16513
+ return preferredToken;
16514
+ }
16515
+ if (preferredTone !== null && preferredTone !== void 0) {
16516
+ for (const group of context.backgroundGroups) {
16517
+ const match = group.backgrounds.find((background) => background.tone === preferredTone);
16518
+ if (match) {
16519
+ return match.token;
16520
+ }
16521
+ }
16522
+ }
16523
+ return getDefaultBackgroundToken2(context);
16524
+ }
16525
+ function getInitialPairingState2(searchParams) {
16526
+ const paletteParam = searchParams.get("palette");
16527
+ const primaryParam = searchParams.get("primary");
16528
+ const accentParam = searchParams.get("accent");
16529
+ const pairParam = searchParams.get("pair");
16530
+ const backgroundParam = searchParams.get("background");
16531
+ const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
16532
+ const context = getPairingContext(themeCategory, primaryParam, accentParam);
16533
+ const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
16534
+ const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
16535
+ (background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN2
16536
+ ) ? DEFAULT_INITIAL_BACKGROUND_TOKEN2 : null : null;
16537
+ const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
16538
+ (pair) => pair.id === DEFAULT_INITIAL_PAIR_ID2
16539
+ ) ? DEFAULT_INITIAL_PAIR_ID2 : null;
16540
+ const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
16541
+ const selectedBackgroundToken = resolveBackgroundToken2(
16542
+ context,
16543
+ backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
16544
+ getToneFromToken2(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
16545
+ );
16546
+ const selectedPairId = getPreferredPairForBackground2(
16547
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
16548
+ pairParam ?? defaultPairId
16549
+ )?.id ?? "";
16550
+ return {
16551
+ accentKey: context.accent.key,
16552
+ primaryKey: context.primary.key,
16553
+ selectedBackgroundToken,
16554
+ selectedPairId,
16555
+ themeCategory
16556
+ };
16557
+ }
16558
+ function ColorPairingToolV2Loading() {
16559
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 lg:grid-cols-[18rem_minmax(0,1fr)]", children: [
16560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 bg-grey-50/70 p-6", children: [
16561
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 rounded-sm bg-grey-100" }),
16562
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-40 rounded-sm bg-grey-100" }),
16563
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm bg-grey-100" })
16564
+ ] }),
16565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
16566
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 rounded-sm bg-grey-100" }),
16567
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm bg-grey-100" }),
16568
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-40 rounded-sm bg-grey-100" }),
16569
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-3", children: [
16570
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-44 rounded-sm bg-grey-100" }),
16571
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-44 rounded-sm bg-grey-100" }),
16572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-44 rounded-sm bg-grey-100" })
16573
+ ] })
16574
+ ] })
16575
+ ] });
16576
+ }
16577
+ function SidebarStep({
16578
+ children,
16579
+ description,
16580
+ step,
16581
+ title
16582
+ }) {
16583
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
16584
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
16585
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: [
16586
+ "Step ",
16587
+ step
16588
+ ] }),
16589
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
16590
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm/6 text-muted-foreground", children: description }) : null
16591
+ ] }),
16592
+ children
16593
+ ] });
16594
+ }
16595
+ function PreviewHeroCard({
16596
+ familySummary,
16597
+ isRecommended,
16598
+ pair
16599
+ }) {
16600
+ const whiteForeground = isWhiteForegroundPair2(pair);
16601
+ const statusLabel = isRecommended ? "Pass" : pair.passes.aaaLarge ? "Large text only" : "Example only";
16602
+ const StatusIcon = isRecommended ? Icons.check : Icons.info;
16603
+ const fauxButtonStyle = {
16604
+ "--btn-bg": pair.foreground.hex,
16605
+ "--btn-border": pair.foreground.hex,
16606
+ "--btn-text": pair.background.hex,
16607
+ "--btn-icon": pair.background.hex,
16608
+ "--btn-hover-overlay": pair.background.hex
16609
+ };
16610
+ return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-0 overflow-hidden py-0", children: /* @__PURE__ */ jsxRuntime.jsx(
16611
+ "div",
16612
+ {
16613
+ className: "p-6 sm:min-h-[26rem] sm:p-8",
16614
+ style: {
16615
+ backgroundColor: pair.background.hex,
16616
+ color: pair.foreground.hex
16617
+ },
16618
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[22rem] flex-col justify-between gap-8", children: [
16619
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
16620
+ /* @__PURE__ */ jsxRuntime.jsxs(
16621
+ "span",
16622
+ {
16623
+ className: "inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[0.72rem] font-semibold tracking-[0.16em] uppercase",
16624
+ style: {
16625
+ borderColor: pair.foreground.hex,
16626
+ backgroundColor: pair.foreground.hex,
16627
+ color: pair.background.hex
16628
+ },
16629
+ children: [
16630
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.palette, { "data-slot": "icon", className: "size-4" }),
16631
+ familySummary
16632
+ ]
16633
+ }
16634
+ ),
16635
+ /* @__PURE__ */ jsxRuntime.jsxs(
16636
+ "span",
16637
+ {
16638
+ className: "inline-flex rounded-full border px-3 py-1 text-[0.72rem] font-semibold tracking-[0.16em] uppercase",
16639
+ style: {
16640
+ borderColor: pair.foreground.hex
16641
+ },
16642
+ children: [
16643
+ pair.rating,
16644
+ " ",
16645
+ pair.contrastRatio.toFixed(2),
16646
+ ":1"
16647
+ ]
16648
+ }
16649
+ )
16650
+ ] }),
16651
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4 pb-12 sm:pb-16", children: [
16652
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold tracking-[0.22em] uppercase", children: whiteForeground && !isRecommended ? "White on colour example" : whiteForeground ? "White on colour" : "Colour on colour" }),
16653
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
16654
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-4xl leading-none font-bold text-current sm:text-5xl", children: "Pair colour with confidence." }),
16655
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-base/6 sm:text-base/7", children: getPreviewGuidance2(pair, isRecommended) }),
16656
+ /* @__PURE__ */ jsxRuntime.jsx(
16657
+ "span",
16658
+ {
16659
+ "aria-hidden": "true",
16660
+ "data-variant": "solid",
16661
+ className: cn(
16662
+ buttonVariants({ variant: "solid", size: "default" }),
16663
+ "pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
16664
+ ),
16665
+ style: fauxButtonStyle,
16666
+ children: "Get started"
16667
+ }
16668
+ )
16669
+ ] })
16670
+ ] }),
16671
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
16672
+ /* @__PURE__ */ jsxRuntime.jsxs(
16673
+ "span",
16674
+ {
16675
+ className: "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold",
16676
+ style: {
16677
+ backgroundColor: pair.foreground.hex,
16678
+ color: pair.background.hex
16679
+ },
16680
+ children: [
16681
+ statusLabel,
16682
+ /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" })
16683
+ ]
16684
+ }
16685
+ ),
16686
+ /* @__PURE__ */ jsxRuntime.jsxs(
16687
+ "span",
16688
+ {
16689
+ className: "inline-flex rounded-full border px-4 py-2 text-sm",
16690
+ style: {
16691
+ borderColor: pair.foreground.hex
16692
+ },
16693
+ children: [
16694
+ pair.background.token,
16695
+ " / ",
16696
+ pair.foreground.token
16697
+ ]
16698
+ }
16699
+ )
16700
+ ] })
16701
+ ] })
16702
+ }
16703
+ ) });
16704
+ }
16705
+ function PreviewFallbackCard2({ background }) {
16706
+ return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-0 overflow-hidden py-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
16707
+ "div",
16708
+ {
16709
+ className: "space-y-6 px-6 py-7 sm:px-8 sm:py-8",
16710
+ style: {
16711
+ backgroundColor: background.hex,
16712
+ color: getReadableTextColor(background.tone)
16713
+ },
16714
+ children: [
16715
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold", children: "Hero preview" }),
16716
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4", children: [
16717
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold sm:text-4xl", children: "No AAA combination available." }),
16718
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-lg text-base/7", children: "This background tone is approved, but there are no recommended AAA foreground pairings available for it in the current tool." })
16719
+ ] })
16720
+ ]
16721
+ }
16722
+ ) });
16723
+ }
16724
+ function PairDetailCard2({
16725
+ color: color2,
16726
+ role,
16727
+ visibleFormats
16728
+ }) {
16729
+ const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
16730
+ const [copiedField, setCopiedField] = React5.useState(null);
16731
+ const copiedFieldTimeoutRef = React5.useRef(null);
16732
+ const hasDisplayTone = color2.token !== "white";
16733
+ const formatRows = visibleFormats.map((format) => ({
16734
+ key: format,
16735
+ label: format.toUpperCase(),
16736
+ value: color2[format],
16737
+ mono: true,
16738
+ copyable: true
16739
+ }));
16740
+ const valueRows = [
16741
+ { key: "token", label: "Token", value: color2.token, mono: true, copyable: true },
16742
+ {
16743
+ key: "tone",
16744
+ label: "Tone",
16745
+ value: hasDisplayTone ? String(color2.tone) : "Not applicable",
16746
+ mono: false,
16747
+ copyable: hasDisplayTone
16748
+ },
16749
+ ...formatRows
16750
+ ];
16751
+ React5.useEffect(() => {
16752
+ return () => {
16753
+ if (copiedFieldTimeoutRef.current) {
16754
+ clearTimeout(copiedFieldTimeoutRef.current);
16755
+ }
16756
+ };
16757
+ }, []);
16758
+ const copyField = (field) => {
16759
+ if (field === "tone" && !hasDisplayTone) {
16760
+ return;
16761
+ }
16762
+ const fieldValue = valueRows.find((row) => row.key === field)?.value;
16763
+ if (!fieldValue) return;
16764
+ copyToClipboardRaw(fieldValue);
16765
+ setCopiedField(field);
16766
+ const toastLabel = valueRows.find((row) => row.key === field)?.label ?? "Value";
16767
+ sonner.toast(`${toastLabel} copied to clipboard`, {
16768
+ duration: 2e3
16769
+ });
16770
+ if (copiedFieldTimeoutRef.current) {
16771
+ clearTimeout(copiedFieldTimeoutRef.current);
16772
+ }
16773
+ copiedFieldTimeoutRef.current = setTimeout(() => {
16774
+ setCopiedField(null);
16775
+ copiedFieldTimeoutRef.current = null;
16776
+ }, 2e3);
16777
+ };
16778
+ const renderCopyButton = (field, srLabel, className) => /* @__PURE__ */ jsxRuntime.jsxs(
16779
+ Button2,
16780
+ {
16781
+ variant: "ghost",
16782
+ size: "icon",
16783
+ className: cn("shrink-0", className),
16784
+ onClick: () => copyField(field),
16785
+ children: [
16786
+ copiedField === field ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
16787
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: srLabel })
16788
+ ]
16789
+ }
16790
+ );
16791
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-0 pb-0", children: [
16792
+ /* @__PURE__ */ jsxRuntime.jsxs(CardHeader, { className: "gap-4 border-b", children: [
16793
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
16794
+ /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { children: role }),
16795
+ /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: color2.name ?? color2.token })
16796
+ ] }),
16797
+ /* @__PURE__ */ jsxRuntime.jsx(
16798
+ "div",
16799
+ {
16800
+ className: "h-14 w-full rounded-sm border border-grey-200 shadow-sm dark:border-grey-700",
16801
+ style: { backgroundColor: color2.hex }
16802
+ }
16803
+ )
16804
+ ] }),
16805
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "px-0 pb-3", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-100 dark:divide-grey-800", children: valueRows.map((row) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4 px-6 py-3", children: [
16806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
16807
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold tracking-[0.16em] text-muted-foreground uppercase", children: row.label }),
16808
+ /* @__PURE__ */ jsxRuntime.jsx(
16809
+ "p",
16810
+ {
16811
+ className: cn(
16812
+ "mt-2 min-w-0 text-base text-foreground",
16813
+ row.mono && "font-mono text-sm break-all sm:text-base"
16814
+ ),
16815
+ children: row.value
16816
+ }
16817
+ )
16818
+ ] }),
16819
+ row.copyable ? renderCopyButton(
16820
+ row.key,
16821
+ `Copy ${role.toLowerCase()} ${row.label.toLowerCase()}`,
16822
+ "mt-0.5"
16823
+ ) : null
16824
+ ] }, row.key)) }) })
16825
+ ] });
16826
+ }
16827
+ function AccessibilityScoreCard({ pair }) {
16828
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-0 py-0", children: [
16829
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 px-6 py-6 sm:flex-row sm:items-end sm:justify-between", children: [
16830
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
16831
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Accessibility score" }),
16832
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
16833
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-5xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" }),
16834
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base text-muted-foreground", children: "Contrast ratio" })
16835
+ ] })
16836
+ ] }),
16837
+ /* @__PURE__ */ jsxRuntime.jsx(
16838
+ "span",
16839
+ {
16840
+ className: cn(
16841
+ "inline-flex items-center gap-2 rounded-full px-4 py-2 text-base font-semibold",
16842
+ pair ? "bg-success-700 text-white" : "border border-grey-300 bg-background text-foreground"
16843
+ ),
16844
+ children: pair ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16845
+ "Pass AAA",
16846
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" })
16847
+ ] }) : "No AAA result"
16848
+ }
16849
+ )
16850
+ ] }),
16851
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-6 py-4 dark:border-grey-700", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: pair ? "Meets WCAG 2.1 AAA standards for large and normal text." : "Choose a different approved background tone to review recommended AAA pairings." }) })
16852
+ ] });
16853
+ }
16854
+ function RecommendedPairCard({
16855
+ isSelected,
16856
+ onSelect,
16857
+ pair
16858
+ }) {
16859
+ return /* @__PURE__ */ jsxRuntime.jsxs(
16860
+ "button",
16861
+ {
16862
+ type: "button",
16863
+ "aria-label": `Use ${getPairingColorDisplayName2(pair.foreground)} on ${getPairingColorDisplayName2(pair.background)}`,
16864
+ "aria-pressed": isSelected,
16865
+ onClick: onSelect,
16866
+ className: cn(
16867
+ "overflow-hidden rounded-sm border bg-background text-left transition-colors",
16868
+ isSelected ? "border-primary-700 ring-2 ring-primary-700 ring-offset-2 ring-offset-background" : "border-grey-200 hover:border-grey-400 dark:border-grey-700 dark:hover:border-grey-500"
16869
+ ),
16870
+ children: [
16871
+ /* @__PURE__ */ jsxRuntime.jsxs(
16872
+ "div",
16873
+ {
16874
+ className: "min-h-32 space-y-3 px-4 py-4",
16875
+ style: {
16876
+ backgroundColor: pair.background.hex,
16877
+ color: pair.foreground.hex
16878
+ },
16879
+ children: [
16880
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.68rem] font-semibold tracking-[0.12em] uppercase opacity-90", children: [
16881
+ pair.background.token,
16882
+ " / ",
16883
+ pair.foreground.token
16884
+ ] }),
16885
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
16886
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-2xl leading-tight font-bold", children: getPairingColorDisplayName2(pair.foreground) }),
16887
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm/6 opacity-90", children: [
16888
+ pair.foreground.familyLabel,
16889
+ " on ",
16890
+ pair.background.familyLabel
16891
+ ] })
16892
+ ] })
16893
+ ]
16894
+ }
16895
+ ),
16896
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4 px-4 py-3", children: [
16897
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold text-foreground", children: [
16898
+ pair.contrastRatio.toFixed(2),
16899
+ ":1"
16900
+ ] }),
16901
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center gap-1 rounded-full bg-success-50 px-2.5 py-1 text-xs font-semibold text-success-800 dark:bg-success-950/30 dark:text-success-200", children: "AAA" })
16902
+ ] })
16903
+ ]
16904
+ }
16905
+ );
16906
+ }
16907
+ function ColorPairingToolV2Content({ visibleFormats }) {
16908
+ const searchParams = navigation.useSearchParams();
16909
+ const [initialState] = React5.useState(() => getInitialPairingState2(searchParams));
16910
+ const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
16911
+ const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
16912
+ const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
16913
+ const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
16914
+ initialState.selectedBackgroundToken
16915
+ );
16916
+ const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
16917
+ const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
16918
+ const context = React5.useMemo(
16919
+ () => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
16920
+ [themeCategory, primaryFamilyKey, accentFamilyKey]
16921
+ );
16922
+ const selectableFamilies = React5.useMemo(
16923
+ () => themeFamilies.filter((family) => family.key !== context.grey.key),
16924
+ [themeFamilies, context.grey.key]
16925
+ );
16926
+ const selectableAccentFamilies = React5.useMemo(
16927
+ () => selectableFamilies.filter((family) => family.key !== context.primary.key),
16928
+ [selectableFamilies, context.primary.key]
16929
+ );
16930
+ const selectedBackground = React5.useMemo(
16931
+ () => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
16932
+ [context.backgrounds, selectedBackgroundToken]
16933
+ );
16934
+ const selectedBackgroundPairs = React5.useMemo(
16935
+ () => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
16936
+ [context.pairsByBackground, selectedBackground]
16937
+ );
16938
+ const selectedPair = React5.useMemo(
16939
+ () => getPreferredPairForBackground2(selectedBackgroundPairs, selectedPairId),
16940
+ [selectedBackgroundPairs, selectedPairId]
16941
+ );
16942
+ const detailForeground = selectedPair?.foreground ?? null;
16943
+ const familySummary = React5.useMemo(
16944
+ () => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
16945
+ [context.primary.label, context.accent.label, context.grey.label]
16946
+ );
16947
+ const updateUrlParams = (nextThemeCategory, nextPrimaryKey, nextAccentKey, nextSelectedBackgroundToken, nextSelectedPairId) => {
16948
+ const params = new URLSearchParams(window.location.search);
16949
+ params.delete("family");
16950
+ params.set("palette", nextThemeCategory);
16951
+ params.set("primary", nextPrimaryKey);
16952
+ params.set("accent", nextAccentKey);
16953
+ params.set("background", nextSelectedBackgroundToken);
16954
+ if (nextSelectedPairId) {
16955
+ params.set("pair", nextSelectedPairId);
16956
+ } else {
16957
+ params.delete("pair");
16958
+ }
16959
+ window.history.replaceState(
16960
+ null,
16961
+ "",
16962
+ `${window.location.pathname}?${params.toString()}${window.location.hash}`
16963
+ );
16964
+ };
16965
+ const syncSelection = (nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) => {
16966
+ const nextContext = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
16967
+ const nextSelectedBackgroundToken = resolveBackgroundToken2(
16968
+ nextContext,
16969
+ preferredBackgroundToken,
16970
+ getToneFromToken2(preferredBackgroundToken)
16971
+ );
16972
+ const nextSelectedPairId = getPreferredPairForBackground2(
16973
+ nextContext.pairsByBackground[nextSelectedBackgroundToken] ?? [],
16974
+ preferredPairId
16975
+ )?.id ?? "";
16976
+ setThemeCategory(nextThemeCategory);
16977
+ setPrimaryFamilyKey(nextContext.primary.key);
16978
+ setAccentFamilyKey(nextContext.accent.key);
16979
+ setSelectedBackgroundToken(nextSelectedBackgroundToken);
16980
+ setSelectedPairId(nextSelectedPairId);
16981
+ updateUrlParams(
16982
+ nextThemeCategory,
16983
+ nextContext.primary.key,
16984
+ nextContext.accent.key,
16985
+ nextSelectedBackgroundToken,
16986
+ nextSelectedPairId
16987
+ );
16988
+ };
16989
+ const handleThemeCategoryChange = (nextThemeCategory) => {
16990
+ syncSelection(
16991
+ nextThemeCategory,
16992
+ primaryFamilyKey,
16993
+ accentFamilyKey,
16994
+ selectedBackgroundToken,
16995
+ selectedPairId
16996
+ );
16997
+ };
16998
+ const handlePrimaryColorChange = (nextPrimaryKey) => {
16999
+ const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
17000
+ syncSelection(
17001
+ themeCategory,
17002
+ nextPrimaryKey,
17003
+ nextAccentKey,
17004
+ selectedBackgroundToken,
17005
+ selectedPairId
17006
+ );
17007
+ };
17008
+ const handleAccentColorChange = (nextAccentKey) => {
17009
+ if (nextAccentKey === primaryFamilyKey) return;
17010
+ syncSelection(
17011
+ themeCategory,
17012
+ primaryFamilyKey,
17013
+ nextAccentKey,
17014
+ selectedBackgroundToken,
17015
+ selectedPairId
17016
+ );
17017
+ };
17018
+ const handleBackgroundChange = (nextSelectedBackgroundToken) => {
17019
+ const nextSelectedPairId = getPreferredPairForBackground2(
17020
+ context.pairsByBackground[nextSelectedBackgroundToken] ?? [],
17021
+ selectedPairId
17022
+ )?.id ?? "";
17023
+ setSelectedBackgroundToken(nextSelectedBackgroundToken);
17024
+ setSelectedPairId(nextSelectedPairId);
17025
+ updateUrlParams(
17026
+ themeCategory,
17027
+ context.primary.key,
17028
+ context.accent.key,
17029
+ nextSelectedBackgroundToken,
17030
+ nextSelectedPairId
17031
+ );
17032
+ };
17033
+ const handlePairChange = (nextSelectedPairId) => {
17034
+ if (!selectedBackground) return;
17035
+ setSelectedPairId(nextSelectedPairId);
17036
+ updateUrlParams(
17037
+ themeCategory,
17038
+ context.primary.key,
17039
+ context.accent.key,
17040
+ selectedBackground.token,
17041
+ nextSelectedPairId
17042
+ );
17043
+ };
17044
+ if (!selectedBackground) {
17045
+ return /* @__PURE__ */ jsxRuntime.jsx(Card, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6", children: [
17046
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
17047
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base text-muted-foreground", children: "No approved tones are available for the current palette." })
17048
+ ] }) });
17049
+ }
17050
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 lg:grid-cols-[18rem_minmax(0,1fr)]", children: [
17051
+ /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "bg-grey-50/60 p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
17052
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
17053
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
17054
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Choose a palette, set your primary and accent families, then select an approved background." })
17055
+ ] }),
17056
+ /* @__PURE__ */ jsxRuntime.jsx(SidebarStep, { step: 1, title: "Select your palette", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-2", children: ["brand", "aboriginal"].map((palette) => {
17057
+ const isSelected = themeCategory === palette;
17058
+ const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
17059
+ return /* @__PURE__ */ jsxRuntime.jsx(
17060
+ "button",
17061
+ {
17062
+ type: "button",
17063
+ "aria-label": `Select ${label}`,
17064
+ "aria-pressed": isSelected,
17065
+ onClick: () => handleThemeCategoryChange(palette),
17066
+ className: cn(
17067
+ "rounded-sm border px-3 py-2.5 text-left text-sm font-semibold transition-colors",
17068
+ isSelected ? "border-primary-800 bg-primary-800 text-white" : "border-grey-300 bg-background text-foreground hover:border-primary-800 hover:bg-primary-50"
17069
+ ),
17070
+ children: label
17071
+ },
17072
+ palette
17073
+ );
17074
+ }) }) }),
17075
+ /* @__PURE__ */ jsxRuntime.jsx(
17076
+ SidebarStep,
17077
+ {
17078
+ step: 2,
17079
+ title: "Choose your colours",
17080
+ description: "Grey is added automatically from the selected palette.",
17081
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
17082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
17083
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Primary colour" }),
17084
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: selectableFamilies.map((family) => {
17085
+ const swatchTone = 800;
17086
+ const isSelected = family.key === context.primary.key;
17087
+ const label = getFamilySelectorLabel2(family, themeCategory, "primary colour");
17088
+ return /* @__PURE__ */ jsxRuntime.jsx(
17089
+ "button",
17090
+ {
17091
+ type: "button",
17092
+ "aria-label": `Select ${label} as primary colour`,
17093
+ "aria-pressed": isSelected,
17094
+ onClick: () => handlePrimaryColorChange(family.key),
17095
+ className: cn(
17096
+ "min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
17097
+ isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
17098
+ ),
17099
+ style: {
17100
+ backgroundColor: getFamilySwatchColor2(family, swatchTone),
17101
+ color: getReadableTextColor(swatchTone),
17102
+ borderColor: "rgba(0, 0, 0, 0.12)"
17103
+ },
17104
+ title: label,
17105
+ children: label
17106
+ },
17107
+ family.key
17108
+ );
17109
+ }) })
17110
+ ] }),
17111
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
17112
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Accent colour" }),
17113
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: selectableAccentFamilies.map((family) => {
17114
+ const swatchTone = 600;
17115
+ const isSelected = family.key === context.accent.key;
17116
+ const label = getFamilySelectorLabel2(family, themeCategory, "accent colour");
17117
+ return /* @__PURE__ */ jsxRuntime.jsx(
17118
+ "button",
17119
+ {
17120
+ type: "button",
17121
+ "aria-label": `Select ${label} as accent colour`,
17122
+ "aria-pressed": isSelected,
17123
+ onClick: () => handleAccentColorChange(family.key),
17124
+ className: cn(
17125
+ "min-h-11 rounded-sm border px-2 py-2 text-center text-[0.8rem] leading-5 font-semibold transition-transform",
17126
+ isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px"
17127
+ ),
17128
+ style: {
17129
+ backgroundColor: getFamilySwatchColor2(family, swatchTone),
17130
+ color: getReadableTextColor(swatchTone),
17131
+ borderColor: "rgba(0, 0, 0, 0.12)"
17132
+ },
17133
+ title: label,
17134
+ children: label
17135
+ },
17136
+ family.key
17137
+ );
17138
+ }) })
17139
+ ] })
17140
+ ] })
17141
+ }
17142
+ ),
17143
+ /* @__PURE__ */ jsxRuntime.jsx(SidebarStep, { step: 3, title: "Pick a background", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
17144
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
17145
+ "Selected:",
17146
+ " ",
17147
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: selectedBackground.token })
17148
+ ] }),
17149
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-4 gap-2", children: context.backgrounds.map((background) => {
17150
+ const hasPairs = (context.pairsByBackground[background.token]?.length ?? 0) > 0;
17151
+ const isSelected = selectedBackground.token === background.token;
17152
+ return /* @__PURE__ */ jsxRuntime.jsx(
17153
+ "button",
17154
+ {
17155
+ type: "button",
17156
+ "aria-label": hasPairs ? `Select ${background.token} background` : `Select ${background.token} background with no AAA pairings`,
17157
+ "aria-pressed": isSelected,
17158
+ onClick: () => handleBackgroundChange(background.token),
17159
+ className: cn(
17160
+ "relative aspect-square rounded-sm border transition-transform",
17161
+ isSelected ? "ring-2 ring-primary-700 ring-offset-2 ring-offset-grey-50/60" : "hover:-translate-y-px",
17162
+ !hasPairs && "opacity-80"
17163
+ ),
17164
+ style: {
17165
+ backgroundColor: background.hex,
17166
+ borderColor: "rgba(0, 0, 0, 0.14)"
17167
+ },
17168
+ title: background.token,
17169
+ children: !hasPairs ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute top-1/2 left-1/2 h-0.5 w-5 -translate-x-1/2 -translate-y-1/2 rotate-45 rounded-full bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.28)]" }) : null
17170
+ },
17171
+ background.token
17172
+ );
17173
+ }) })
17174
+ ] }) })
17175
+ ] }) }),
17176
+ /* @__PURE__ */ jsxRuntime.jsxs("main", { className: "space-y-8", children: [
17177
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
17178
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Live Preview & Results" }),
17179
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Review the selected pairing in context, then compare the available AAA combinations for your chosen background." })
17180
+ ] }),
17181
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
17182
+ selectedPair ? /* @__PURE__ */ jsxRuntime.jsx(
17183
+ PreviewHeroCard,
17184
+ {
17185
+ familySummary,
17186
+ isRecommended: Boolean(selectedPair),
17187
+ pair: selectedPair
17188
+ }
17189
+ ) : /* @__PURE__ */ jsxRuntime.jsx(PreviewFallbackCard2, { background: selectedBackground }),
17190
+ /* @__PURE__ */ jsxRuntime.jsx(AccessibilityScoreCard, { pair: selectedPair })
17191
+ ] }),
17192
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
17193
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
17194
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: "Recommended Combinations" }),
17195
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-base text-muted-foreground", children: [
17196
+ "AAA-recommended foregrounds for",
17197
+ " ",
17198
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: selectedBackground.token }),
17199
+ "."
17200
+ ] })
17201
+ ] }),
17202
+ selectedBackgroundPairs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-3", children: selectedBackgroundPairs.map((pair) => /* @__PURE__ */ jsxRuntime.jsx(
17203
+ RecommendedPairCard,
17204
+ {
17205
+ pair,
17206
+ isSelected: selectedPair?.id === pair.id,
17207
+ onSelect: () => handlePairChange(pair.id)
17208
+ },
17209
+ pair.id
17210
+ )) }) : /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-0 py-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-6", children: [
17211
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No recommended combinations" }),
17212
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base text-muted-foreground", children: "Choose another approved background tone to review available AAA pairings." })
17213
+ ] }) })
17214
+ ] }),
17215
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
17216
+ /* @__PURE__ */ jsxRuntime.jsx(
17217
+ PairDetailCard2,
17218
+ {
17219
+ color: selectedBackground,
17220
+ role: "Background",
17221
+ visibleFormats
17222
+ }
17223
+ ),
17224
+ detailForeground ? /* @__PURE__ */ jsxRuntime.jsx(
17225
+ PairDetailCard2,
17226
+ {
17227
+ color: detailForeground,
17228
+ role: "Foreground",
17229
+ visibleFormats
17230
+ }
17231
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-4", children: [
17232
+ /* @__PURE__ */ jsxRuntime.jsx(CardHeader, { className: "gap-3 border-b", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
17233
+ /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { children: "Foreground" }),
17234
+ /* @__PURE__ */ jsxRuntime.jsx(CardDescription, { children: "No recommended foreground available" })
17235
+ ] }) }),
17236
+ /* @__PURE__ */ jsxRuntime.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Choose another approved tone or review the recommended foregrounds for the same background." }) })
17237
+ ] })
17238
+ ] })
17239
+ ] })
17240
+ ] });
17241
+ }
17242
+ function ColorPairingToolV2({
17243
+ visibleFormats = DEFAULT_VISIBLE_FORMATS2
17244
+ } = {}) {
17245
+ const normalizedVisibleFormats = [...new Set(visibleFormats)];
17246
+ return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV2Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV2Content, { visibleFormats: normalizedVisibleFormats }) });
17247
+ }
17248
+ function Sheet({ ...props }) {
17249
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Root, { "data-slot": "sheet", ...props });
17250
+ }
17251
+ function SheetTrigger({ ...props }) {
17252
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Trigger, { "data-slot": "sheet-trigger", ...props });
17253
+ }
17254
+ function SheetClose({ ...props }) {
17255
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "sheet-close", ...props });
17256
+ }
17257
+ function SheetPortal({ ...props }) {
17258
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Portal, { "data-slot": "sheet-portal", ...props });
17259
+ }
17260
+ function SheetOverlay({
17261
+ className,
17262
+ ...props
17263
+ }) {
17264
+ return /* @__PURE__ */ jsxRuntime.jsx(
17265
+ SheetPrimitive__namespace.Overlay,
17266
+ {
17267
+ "data-slot": "sheet-overlay",
17268
+ className: cn(
17269
+ "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
17270
+ className
17271
+ ),
17272
+ ...props
17273
+ }
17274
+ );
17275
+ }
17276
+ function SheetContent({
17277
+ className,
17278
+ children,
17279
+ side = "right",
17280
+ showClose = true,
17281
+ ...props
17282
+ }) {
17283
+ return /* @__PURE__ */ jsxRuntime.jsxs(SheetPortal, { children: [
17284
+ /* @__PURE__ */ jsxRuntime.jsx(SheetOverlay, {}),
17285
+ /* @__PURE__ */ jsxRuntime.jsxs(
17286
+ SheetPrimitive__namespace.Content,
17287
+ {
17288
+ "data-slot": "sheet-content",
17289
+ className: cn(
17290
+ "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
17291
+ side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
17292
+ side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
17293
+ side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
17294
+ side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
17295
+ className
17296
+ ),
17297
+ ...props,
17298
+ children: [
17299
+ children,
17300
+ showClose && /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
17301
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
17302
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
17303
+ ] }) })
17304
+ ]
17305
+ }
17306
+ )
17307
+ ] });
17308
+ }
17309
+ function SheetHeader({ className, ...props }) {
17310
+ return /* @__PURE__ */ jsxRuntime.jsx(
17311
+ "div",
17312
+ {
17313
+ "data-slot": "sheet-header",
17314
+ className: cn("flex flex-col gap-1.5 p-4", className),
17315
+ ...props
17316
+ }
17317
+ );
17318
+ }
17319
+ function SheetFooter({ className, ...props }) {
17320
+ return /* @__PURE__ */ jsxRuntime.jsx(
17321
+ "div",
17322
+ {
17323
+ "data-slot": "sheet-footer",
17324
+ className: cn("mt-auto flex flex-col gap-2 p-4", className),
17325
+ ...props
17326
+ }
17327
+ );
17328
+ }
17329
+ function SheetTitle({ className, ...props }) {
17330
+ return /* @__PURE__ */ jsxRuntime.jsx(
17331
+ SheetPrimitive__namespace.Title,
17332
+ {
17333
+ "data-slot": "sheet-title",
17334
+ className: cn("font-semibold text-foreground", className),
17335
+ ...props
17336
+ }
17337
+ );
17338
+ }
17339
+ function SheetDescription({
17340
+ className,
17341
+ ...props
17342
+ }) {
17343
+ return /* @__PURE__ */ jsxRuntime.jsx(
17344
+ SheetPrimitive__namespace.Description,
17345
+ {
17346
+ "data-slot": "sheet-description",
17347
+ className: cn("text-sm text-muted-foreground", className),
17348
+ ...props
17349
+ }
17350
+ );
17351
+ }
17352
+ function useSelectorHeight(selector = "header") {
17353
+ const [height, setHeight] = React5.useState(0);
17354
+ const elementRef = React5.useRef(null);
17355
+ const resizeObserverRef = React5.useRef(null);
17356
+ React5.useEffect(() => {
17357
+ const element = document.querySelector(selector);
17358
+ if (!element) return;
17359
+ elementRef.current = element;
17360
+ const resizeObserver = new ResizeObserver((entries) => {
17361
+ const entry = entries[0];
17362
+ const target = entry?.target ?? elementRef.current;
17363
+ if (!target) return;
17364
+ setHeight(target.offsetHeight);
17365
+ });
17366
+ resizeObserverRef.current = resizeObserver;
17367
+ resizeObserver.observe(element);
17368
+ return () => {
17369
+ resizeObserverRef.current?.disconnect();
17370
+ };
17371
+ }, [selector]);
17372
+ return height;
17373
+ }
17374
+
17375
+ // src/hooks/useStickyOffset.ts
17376
+ function useStickyOffset(extraPadding = 0) {
17377
+ const headerHeight = useSelectorHeight("#nsw-header");
17378
+ const navigationHeight = useSelectorHeight("#nsw-main-navigation");
17379
+ return React5.useMemo(() => {
17380
+ const total = headerHeight + navigationHeight + extraPadding;
17381
+ return total > 0 ? total : 0;
17382
+ }, [extraPadding, headerHeight, navigationHeight]);
17383
+ }
17384
+ var PREFERRED_BACKGROUND_TONES3 = [400, 600, 200, 800, 100, 50];
17385
+ var DEFAULT_VISIBLE_FORMATS3 = ["hex", "rgb", "hsl", "oklch"];
17386
+ var DEFAULT_INITIAL_BACKGROUND_TOKEN3 = "nsw-blue-800";
17387
+ var DEFAULT_INITIAL_PAIR_ID3 = "nsw-blue-800:nsw-blue-200";
17388
+ var COLOR_PAIRING_TOOL_V3_PATH = "/core/colour/colour-pairing-tool-3";
17389
+ var AAA_NORMAL_TEXT_THRESHOLD2 = "7.0:1 for text below the WCAG large-text threshold. Sentence-case body copy should generally stay at 16px+ unless it is microcopy.";
17390
+ var AAA_LARGE_TEXT_THRESHOLD2 = "4.5:1 for WCAG large text: 24px+, or 18.5px+ bold";
17391
+ var MOBILE_RESULT_SCROLL_QUERY = "(max-width: 1023px)";
17392
+ var PERSISTENT_DRAWER_MIN_WIDTH_QUERY = "(min-width: 1280px)";
17393
+ var COLOR_PAIRING_TOOL_DRAWER_STEPS = [
17394
+ {
17395
+ id: "colours",
17396
+ title: "Choose colours",
17397
+ eyebrow: "Step 1 of 3",
17398
+ description: "Select the palette, primary family, and accent family."
17399
+ },
17400
+ {
17401
+ id: "backgrounds",
17402
+ title: "Choose background",
17403
+ eyebrow: "Step 2 of 3",
17404
+ description: "Pick the background tone that you want to pair."
17405
+ },
17406
+ {
17407
+ id: "combinations",
17408
+ title: "Choose recommended combinations",
17409
+ eyebrow: "Step 3 of 3",
17410
+ description: "Select the foreground pairing that should drive the example."
17411
+ }
17412
+ ];
17413
+ var COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v3";
17414
+ function getToneFromToken3(token) {
17415
+ if (!token) return null;
17416
+ const match = token.match(/-(\d+)$/);
17417
+ return match ? Number.parseInt(match[1], 10) : null;
17418
+ }
17419
+ function getFamilySwatchColor3(family, preferredTone = 600) {
17420
+ const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
17421
+ if (exactMatch) {
17422
+ return exactMatch.hex;
17423
+ }
17424
+ const closestMatch = [...family.colors].sort(
17425
+ (left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
17426
+ )[0];
17427
+ return closestMatch?.hex ?? "transparent";
17428
+ }
17429
+ function getFamilySelectorLabel3(family, themeCategory, selectionRole) {
17430
+ if (themeCategory !== "aboriginal") {
17431
+ return family.label;
17432
+ }
17433
+ const preferredTone = selectionRole === "primary colour" ? 800 : 600;
17434
+ return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
17435
+ }
17436
+ function getPairingColorDisplayName3(color2) {
17437
+ return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
17438
+ }
17439
+ function isWhiteForegroundPair3(pair) {
17440
+ return pair.foreground.token === "white";
17441
+ }
17442
+ function isLargeTextOnlyPair(pair) {
17443
+ return pair.passes.aaaLarge && !pair.passes.aaaText;
17444
+ }
17445
+ function getWhiteForegroundGuidance3(pair) {
17446
+ if (pair.passes.aaaText) {
17447
+ return "White is approved for headings, body copy, and calls to action on this background.";
17448
+ }
17449
+ if (pair.passes.aaaLarge) {
17450
+ return "Use white only for WCAG large text on this background, such as headings at 24px+ or bold text at 18.5px+. Keep sentence-case body copy at 16px+ and use a darker recommended foreground instead.";
17451
+ }
17452
+ return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
17453
+ }
17454
+ function getPreviewGuidance3(pair, isRecommended) {
17455
+ if (!isWhiteForegroundPair3(pair)) {
17456
+ return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
17457
+ }
17458
+ if (isRecommended) {
17459
+ return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
17460
+ }
17461
+ return getWhiteForegroundGuidance3(pair);
17462
+ }
17463
+ function getPreferredPairForBackground3(pairs, preferredPairId) {
17464
+ if (preferredPairId) {
17465
+ const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
17466
+ if (preferredPair) {
17467
+ return preferredPair;
17468
+ }
17469
+ }
17470
+ return pairs.find((pair) => !isWhiteForegroundPair3(pair)) ?? pairs[0] ?? null;
17471
+ }
17472
+ function getDefaultBackgroundToken3(context) {
17473
+ for (const tone of PREFERRED_BACKGROUND_TONES3) {
17474
+ for (const group of context.backgroundGroups) {
17475
+ const match = group.backgrounds.find(
17476
+ (background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
17477
+ );
17478
+ if (match) {
17479
+ return match.token;
17480
+ }
17481
+ }
17482
+ }
17483
+ for (const tone of PREFERRED_BACKGROUND_TONES3) {
17484
+ for (const group of context.backgroundGroups) {
17485
+ const match = group.backgrounds.find((background) => background.tone === tone);
17486
+ if (match) {
17487
+ return match.token;
17488
+ }
17489
+ }
17490
+ }
17491
+ return context.backgrounds[0]?.token ?? "";
17492
+ }
17493
+ function resolveBackgroundToken3(context, preferredToken, preferredTone) {
17494
+ if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
17495
+ return preferredToken;
17496
+ }
17497
+ if (preferredTone !== null && preferredTone !== void 0) {
17498
+ for (const group of context.backgroundGroups) {
17499
+ const match = group.backgrounds.find((background) => background.tone === preferredTone);
17500
+ if (match) {
17501
+ return match.token;
17502
+ }
17503
+ }
17504
+ }
17505
+ return getDefaultBackgroundToken3(context);
17506
+ }
17507
+ function getInitialPairingState3(searchParams) {
17508
+ const paletteParam = searchParams.get("palette");
17509
+ const primaryParam = searchParams.get("primary");
17510
+ const accentParam = searchParams.get("accent");
17511
+ const pairParam = searchParams.get("pair");
17512
+ const backgroundParam = searchParams.get("background");
17513
+ const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
17514
+ const context = getPairingContext(themeCategory, primaryParam, accentParam);
17515
+ const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
17516
+ const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
17517
+ (background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN3
17518
+ ) ? DEFAULT_INITIAL_BACKGROUND_TOKEN3 : null : null;
17519
+ const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
17520
+ (pair) => pair.id === DEFAULT_INITIAL_PAIR_ID3
17521
+ ) ? DEFAULT_INITIAL_PAIR_ID3 : null;
17522
+ const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
17523
+ const selectedBackgroundToken = resolveBackgroundToken3(
17524
+ context,
17525
+ backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
17526
+ getToneFromToken3(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
17527
+ );
17528
+ const selectedPairId = getPreferredPairForBackground3(
17529
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
17530
+ pairParam ?? defaultPairId
17531
+ )?.id ?? "";
17532
+ return {
17533
+ accentKey: context.accent.key,
17534
+ primaryKey: context.primary.key,
17535
+ selectedBackgroundToken,
17536
+ selectedPairId,
17537
+ themeCategory
17538
+ };
17539
+ }
17540
+ function getReadableTextColor2(tone) {
17541
+ return tone >= 600 ? "#ffffff" : "#002664";
17542
+ }
17543
+ function getBackgroundOptionName(background) {
17544
+ return background.name ?? `${background.familyLabel} ${background.tone}`;
17545
+ }
17546
+ function getResultExplanation(pair, bestPair) {
17547
+ if (!pair) {
17548
+ return "No AAA-compliant foreground options available for this selection.";
17549
+ }
17550
+ if (pair.id === bestPair?.id) {
17551
+ return "Meets AAA for normal and large text. This is the NSW-recommended starting point for this background.";
17552
+ }
17553
+ if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
17554
+ return "White meets AAA for large text on this background only. Use a darker foreground for standard body copy and smaller interface text.";
17555
+ }
17556
+ if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
17557
+ return "White does not meet AAA for normal or large text on this background. Use another approved background or a darker foreground where one is available.";
17558
+ }
17559
+ return "Meets AAA for normal and large text. This is a valid alternative, while the recommended pairing remains the clearest default.";
17560
+ }
17561
+ function getBestRecommendationReason(pair, context) {
17562
+ if (isWhiteForegroundPair3(pair)) {
17563
+ return "Recommended because this background is dark enough to support white text at AAA contrast.";
17564
+ }
17565
+ if (pair.foreground.familyKey === pair.background.familyKey) {
17566
+ return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
17567
+ }
17568
+ if (pair.foreground.familyKey === context.grey.key) {
17569
+ return "Recommended because grey provides a strong neutral contrast without competing with the background.";
17570
+ }
17571
+ if (pair.foreground.familyKey === context.accent.key) {
17572
+ return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
17573
+ }
17574
+ if (pair.foreground.familyKey === context.primary.key) {
17575
+ return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
17576
+ }
17577
+ return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
17578
+ }
17579
+ function getRecommendationCategory(pair, bestPair, context) {
17580
+ if (pair.id === bestPair?.id) return "best";
17581
+ if (isWhiteForegroundPair3(pair)) return "white";
17582
+ if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
17583
+ if (pair.foreground.familyKey === context.accent.key) return "accent-family";
17584
+ if (pair.foreground.familyKey === context.grey.key) return "grey-option";
17585
+ if (pair.foreground.familyKey === context.primary.key) return "primary-family";
17586
+ return "approved";
17587
+ }
17588
+ function getRecommendationCategoryLabel(category) {
17589
+ switch (category) {
17590
+ case "best":
17591
+ return "Best recommended";
17592
+ case "same-family":
17593
+ return "Same family";
17594
+ case "accent-family":
17595
+ return "Accent family";
17596
+ case "grey-option":
17597
+ return "Grey option";
17598
+ case "primary-family":
17599
+ return "Primary family";
17600
+ case "white":
17601
+ return "White";
17602
+ default:
17603
+ return "Approved option";
17604
+ }
17605
+ }
17606
+ function getRecommendationSortRank(category) {
17607
+ switch (category) {
17608
+ case "best":
17609
+ return 0;
17610
+ case "same-family":
17611
+ return 1;
17612
+ case "accent-family":
17613
+ return 2;
17614
+ case "grey-option":
17615
+ return 3;
17616
+ case "white":
17617
+ return 4;
17618
+ case "primary-family":
17619
+ return 5;
17620
+ default:
17621
+ return 6;
17622
+ }
17623
+ }
17624
+ function getAvailabilityMeta(isSelected, hasPairs) {
17625
+ if (isSelected && hasPairs) {
17626
+ return {
17627
+ description: "Selected background with AAA foreground options.",
17628
+ icon: Icons.check_circle,
17629
+ label: "Selected",
17630
+ tone: "selected"
17631
+ };
17632
+ }
17633
+ if (isSelected) {
17634
+ return {
17635
+ description: "Selected background with no AAA foreground options.",
17636
+ icon: Icons.warning,
17637
+ label: "Selected, no AAA",
17638
+ tone: "unavailable"
17639
+ };
17640
+ }
17641
+ if (hasPairs) {
17642
+ return {
17643
+ description: "AAA foreground options available.",
17644
+ icon: Icons.radio_button_checked,
17645
+ label: "Available",
17646
+ tone: "available"
17647
+ };
17648
+ }
17649
+ return {
17650
+ description: "No AAA foreground available.",
17651
+ icon: Icons.close,
17652
+ label: "No AAA",
17653
+ tone: "unavailable"
17654
+ };
17655
+ }
17656
+ function getPairingCopyText(pair) {
17657
+ return [
17658
+ `Background: ${pair.background.token} (${pair.background.hex})`,
17659
+ `Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
17660
+ `Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
17661
+ "Accessibility: Meets AAA for normal and large text"
17662
+ ].join("\n");
17663
+ }
17664
+ function getLiveAnnouncement(pair, background) {
17665
+ if (!background) {
17666
+ return "No approved background tones available.";
17667
+ }
17668
+ if (!pair) {
17669
+ return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
17670
+ }
17671
+ if (isWhiteForegroundPair3(pair) && isLargeTextOnlyPair(pair)) {
17672
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
17673
+ }
17674
+ if (isWhiteForegroundPair3(pair) && !pair.passes.aaaLarge) {
17675
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
17676
+ }
17677
+ return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
17678
+ }
17679
+ function formatValueRows(color2, visibleFormats) {
17680
+ const hasDisplayTone = color2.token !== "white";
17681
+ return [
17682
+ { key: "token", label: "Token", value: color2.token, copyable: true },
17683
+ {
17684
+ key: "tone",
17685
+ label: "Tone",
17686
+ value: hasDisplayTone ? String(color2.tone) : "Not applicable",
17687
+ copyable: hasDisplayTone
17688
+ },
17689
+ ...visibleFormats.map((format) => ({
17690
+ key: format,
17691
+ label: format.toUpperCase(),
17692
+ value: color2[format],
17693
+ copyable: true
17694
+ }))
17695
+ ];
17696
+ }
17697
+ function SelectorButton({
17698
+ description,
17699
+ isSelected,
17700
+ label,
17701
+ onClick,
17702
+ swatch
17703
+ }) {
17704
+ return /* @__PURE__ */ jsxRuntime.jsx(
17705
+ "button",
17706
+ {
17707
+ type: "button",
17708
+ "aria-pressed": isSelected,
17709
+ onClick,
17710
+ className: cn(
17711
+ "w-full rounded-sm border px-3 py-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
17712
+ isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
17713
+ ),
17714
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
17715
+ swatch ? /* @__PURE__ */ jsxRuntime.jsx(
17716
+ "span",
17717
+ {
17718
+ "aria-hidden": "true",
17719
+ className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
17720
+ style: { backgroundColor: swatch }
17721
+ }
17722
+ ) : null,
17723
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
17724
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
17725
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
17726
+ ] })
17727
+ ] })
17728
+ }
17729
+ );
17730
+ }
17731
+ function BackgroundSwatchButton({
17732
+ background,
17733
+ hasPairs,
17734
+ isSelected,
17735
+ onClick
17736
+ }) {
17737
+ const status = getAvailabilityMeta(isSelected, hasPairs);
17738
+ const StatusIcon = status.icon;
17739
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17740
+ "button",
17741
+ {
17742
+ type: "button",
17743
+ "aria-pressed": isSelected,
17744
+ "aria-label": `Select ${background.token} background. ${status.description}`,
17745
+ onClick,
17746
+ className: cn(
17747
+ "w-full rounded-sm border bg-white p-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
17748
+ isSelected ? "border-primary-800 bg-primary-50" : hasPairs ? "border-grey-300 hover:border-primary-500 hover:bg-grey-50" : "border-grey-300 hover:border-grey-500"
17749
+ ),
17750
+ children: [
17751
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
17752
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
17753
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName(background) }),
17754
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
17755
+ ] }),
17756
+ /* @__PURE__ */ jsxRuntime.jsxs(
17757
+ "span",
17758
+ {
17759
+ className: cn(
17760
+ "inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
17761
+ status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
17762
+ status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
17763
+ status.tone === "unavailable" && "border-danger-300 bg-danger-50 text-danger-900 dark:border-danger-800 dark:bg-danger-950/20 dark:text-danger-200"
17764
+ ),
17765
+ children: [
17766
+ /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
17767
+ status.label
17768
+ ]
17769
+ }
17770
+ )
17771
+ ] }),
17772
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 overflow-hidden rounded-[2px] border border-black/10", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-14 w-full", style: { backgroundColor: background.hex } }) }),
17773
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
17774
+ ]
17775
+ }
17776
+ );
17777
+ }
17778
+ function ResultSummaryTile({
17779
+ children,
17780
+ className,
17781
+ label
17782
+ }) {
17783
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("rounded-sm border border-grey-200 bg-white px-4 py-4 sm:px-5", className), children: [
17784
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-grey-700", children: label }),
17785
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children })
17786
+ ] });
17787
+ }
17788
+ function AccessibilityCheckTile({
17789
+ className,
17790
+ label,
17791
+ passes,
17792
+ threshold
17793
+ }) {
17794
+ const status = passes === null ? "unavailable" : passes ? "pass" : "fail";
17795
+ return /* @__PURE__ */ jsxRuntime.jsx(
17796
+ "div",
17797
+ {
17798
+ className: cn(
17799
+ "rounded-sm border px-4 py-4 sm:px-5",
17800
+ className,
17801
+ status === "pass" && "border-success-200 bg-success-50",
17802
+ status === "fail" && "border-danger-200 bg-danger-50",
17803
+ status === "unavailable" && "border-grey-200 bg-white"
17804
+ ),
17805
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between sm:gap-4", children: [
17806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
17807
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
17808
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm/6 text-muted-foreground", children: status === "unavailable" ? "No contrast ratio available for this result." : threshold })
17809
+ ] }),
17810
+ /* @__PURE__ */ jsxRuntime.jsxs(
17811
+ "span",
17812
+ {
17813
+ className: cn(
17814
+ "inline-flex items-center gap-1 rounded-sm px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
17815
+ status === "pass" && "bg-success-700 text-white",
17816
+ status === "fail" && "bg-danger-700 text-white",
17817
+ status === "unavailable" && "bg-grey-100 text-foreground"
17818
+ ),
17819
+ children: [
17820
+ status === "pass" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : status === "fail" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
17821
+ status === "pass" ? "Pass" : status === "fail" ? "Fail" : "Unavailable"
17822
+ ]
17823
+ }
17824
+ )
17825
+ ] })
17826
+ }
17827
+ );
17828
+ }
17829
+ function ResultColorSummary({
17830
+ color: color2,
17831
+ fallbackLabel
17832
+ }) {
17833
+ if (!color2) {
17834
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: fallbackLabel ?? "Not available" });
17835
+ }
17836
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-4", children: [
17837
+ /* @__PURE__ */ jsxRuntime.jsx(
17838
+ "span",
17839
+ {
17840
+ "aria-hidden": "true",
17841
+ className: "mt-1 size-6 shrink-0 rounded-full border border-black/10",
17842
+ style: { backgroundColor: color2.hex }
17843
+ }
17844
+ ),
17845
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
17846
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "leading-7 font-semibold text-foreground", children: getPairingColorDisplayName3(color2) }),
17847
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-sm break-all text-muted-foreground", children: color2.token })
17848
+ ] })
17849
+ ] });
17850
+ }
17851
+ function CurrentResultCard({
17852
+ bestPair,
17853
+ familySummary,
17854
+ pair,
17855
+ selectedBackground
17856
+ }) {
17857
+ const previewForeground = pair?.foreground.hex ?? getReadableTextColor2(selectedBackground.tone);
17858
+ const isRecommended = pair ? pair.id === bestPair?.id : false;
17859
+ const whiteForeground = pair ? isWhiteForegroundPair3(pair) : false;
17860
+ const statusLabel = pair ? pair.passes.aaaText ? "Pass" : pair.passes.aaaLarge ? "Large text only" : "Example only" : "No recommendation";
17861
+ const fauxButtonStyle = pair ? {
17862
+ "--btn-bg": pair.foreground.hex,
17863
+ "--btn-border": pair.foreground.hex,
17864
+ "--btn-text": pair.background.hex,
17865
+ "--btn-icon": pair.background.hex,
17866
+ "--btn-hover-overlay": pair.background.hex
17867
+ } : null;
17868
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-0 overflow-hidden py-0", children: [
17869
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-6 sm:py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
17870
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
17871
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: "Current result" }),
17872
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName3(pair.foreground)} on ${getPairingColorDisplayName3(pair.background)}` : `${getPairingColorDisplayName3(selectedBackground)} selected` })
17873
+ ] }),
17874
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: getResultExplanation(pair, bestPair) })
17875
+ ] }) }),
17876
+ /* @__PURE__ */ jsxRuntime.jsx(
17877
+ "div",
17878
+ {
17879
+ className: "p-4 sm:min-h-[26rem] sm:p-8",
17880
+ style: {
17881
+ backgroundColor: selectedBackground.hex,
17882
+ color: previewForeground
17883
+ },
17884
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[18rem] flex-col justify-between gap-6 sm:min-h-[22rem] sm:gap-8", children: [
17885
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
17886
+ /* @__PURE__ */ jsxRuntime.jsxs(
17887
+ "span",
17888
+ {
17889
+ className: "inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
17890
+ style: {
17891
+ borderColor: pair ? pair.foreground.hex : "currentColor",
17892
+ backgroundColor: pair ? pair.foreground.hex : "transparent",
17893
+ color: pair ? pair.background.hex : "currentColor"
17894
+ },
17895
+ children: [
17896
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.palette, { "data-slot": "icon", className: "size-4" }),
17897
+ familySummary
17898
+ ]
17899
+ }
17900
+ ),
17901
+ pair ? /* @__PURE__ */ jsxRuntime.jsxs(
17902
+ "span",
17903
+ {
17904
+ className: "inline-flex rounded-full border px-3 py-1 text-[0.68rem] font-semibold tracking-[0.16em] uppercase sm:text-[0.72rem]",
17905
+ style: {
17906
+ borderColor: pair.foreground.hex
17907
+ },
17908
+ children: [
17909
+ pair.rating,
17910
+ " ",
17911
+ pair.contrastRatio.toFixed(2),
17912
+ ":1"
17913
+ ]
17914
+ }
17915
+ ) : null
17916
+ ] }),
17917
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4 pb-8 sm:pb-16", children: [
17918
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold tracking-[0.22em] uppercase", children: pair ? whiteForeground && !isRecommended ? "White on colour example" : whiteForeground ? "White on colour" : "Colour on colour" : "Approved background" }),
17919
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
17920
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold text-current sm:text-5xl sm:leading-none", children: "Pair colour with confidence." }),
17921
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full text-base/6 sm:max-w-md sm:text-base/7", children: pair ? getPreviewGuidance3(pair, isRecommended) : "This approved background tone does not currently have a recommended AAA foreground in this tool. Choose another approved background tone to continue." }),
17922
+ pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
17923
+ "span",
17924
+ {
17925
+ "aria-hidden": "true",
17926
+ "data-variant": "solid",
17927
+ className: cn(
17928
+ buttonVariants({ variant: "solid", size: "default" }),
17929
+ "pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
17930
+ ),
17931
+ style: fauxButtonStyle,
17932
+ children: "Get started"
17933
+ }
17934
+ ) : null
17935
+ ] })
17936
+ ] }),
17937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
17938
+ /* @__PURE__ */ jsxRuntime.jsxs(
17939
+ "span",
17940
+ {
17941
+ className: "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold",
17942
+ style: pair ? {
17943
+ backgroundColor: pair.foreground.hex,
17944
+ color: pair.background.hex
17945
+ } : {
17946
+ backgroundColor: "rgb(255 255 255 / 0.14)",
17947
+ color: "currentColor"
17948
+ },
17949
+ children: [
17950
+ statusLabel,
17951
+ pair && pair.passes.aaaText ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" })
17952
+ ]
17953
+ }
17954
+ ),
17955
+ /* @__PURE__ */ jsxRuntime.jsx(
17956
+ "span",
17957
+ {
17958
+ className: "inline-flex max-w-full rounded-full border px-4 py-2 text-[0.82rem] break-all sm:text-sm",
17959
+ style: {
17960
+ borderColor: pair ? pair.foreground.hex : "currentColor"
17961
+ },
17962
+ children: pair ? `${pair.background.token} / ${pair.foreground.token}` : selectedBackground.token
17963
+ }
17964
+ )
17965
+ ] })
17966
+ ] })
17967
+ }
17968
+ ),
17969
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-5 border-t border-grey-200 bg-grey-50 px-4 py-5 sm:px-6 sm:py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
17970
+ /* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: selectedBackground }) }),
17971
+ /* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsxRuntime.jsx(
17972
+ ResultColorSummary,
17973
+ {
17974
+ color: pair?.foreground,
17975
+ fallbackLabel: "No AAA foreground available"
17976
+ }
17977
+ ) }),
17978
+ /* @__PURE__ */ jsxRuntime.jsxs(ResultSummaryTile, { label: "Contrast ratio", className: "lg:col-span-2", children: [
17979
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" }),
17980
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: pair ? pair.passes.aaaText ? "Meets AAA accessibility" : pair.passes.aaaLarge ? "Meets AAA for large text only" : "Does not meet accessibility requirements" : "Does not meet accessibility requirements" })
17981
+ ] }),
17982
+ /* @__PURE__ */ jsxRuntime.jsx(
17983
+ AccessibilityCheckTile,
17984
+ {
17985
+ className: "lg:col-span-2",
17986
+ label: "AAA normal text",
17987
+ passes: pair ? pair.passes.aaaText : null,
17988
+ threshold: AAA_NORMAL_TEXT_THRESHOLD2
17989
+ }
17990
+ ),
17991
+ /* @__PURE__ */ jsxRuntime.jsx(
17992
+ AccessibilityCheckTile,
17993
+ {
17994
+ className: "lg:col-span-2",
17995
+ label: "AAA large text",
17996
+ passes: pair ? pair.passes.aaaLarge : null,
17997
+ threshold: AAA_LARGE_TEXT_THRESHOLD2
17998
+ }
17999
+ )
18000
+ ] }) })
18001
+ ] });
18002
+ }
18003
+ function BestRecommendationCard({
18004
+ copiedKey,
18005
+ isCurrentSelection,
18006
+ onCopyPairing,
18007
+ onUsePairing,
18008
+ pair,
18009
+ reason
18010
+ }) {
18011
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "gap-5 border-primary-200 bg-primary-50/60 px-6 py-6", children: [
18012
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
18013
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
18014
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
18015
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2 rounded-sm bg-primary-800 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: [
18016
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }),
18017
+ "Best recommended pairing"
18018
+ ] }),
18019
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex rounded-sm border border-primary-300 px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-primary-900 uppercase", children: [
18020
+ pair.contrastRatio.toFixed(2),
18021
+ ":1"
18022
+ ] })
18023
+ ] }),
18024
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
18025
+ /* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: [
18026
+ pair.background.token,
18027
+ " / ",
18028
+ pair.foreground.token
18029
+ ] }),
18030
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: reason })
18031
+ ] })
18032
+ ] }),
18033
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:flex-wrap sm:items-center", children: [
18034
+ isCurrentSelection ? null : /* @__PURE__ */ jsxRuntime.jsx(
18035
+ Button2,
18036
+ {
18037
+ className: "w-full justify-center sm:w-auto sm:min-w-56",
18038
+ color: "primary",
18039
+ onClick: onUsePairing,
18040
+ "aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
18041
+ children: "Use best recommendation"
18042
+ }
18043
+ ),
18044
+ /* @__PURE__ */ jsxRuntime.jsxs(
18045
+ Button2,
18046
+ {
18047
+ className: "w-full justify-center sm:w-auto sm:min-w-48",
18048
+ variant: "outline",
18049
+ color: "grey",
18050
+ onClick: onCopyPairing,
18051
+ children: [
18052
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18053
+ copiedKey === "best-pairing" ? "Pairing copied" : "Copy pairing"
18054
+ ]
18055
+ }
18056
+ )
18057
+ ] })
18058
+ ] }),
18059
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [
18060
+ /* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Background", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: pair.background }) }),
18061
+ /* @__PURE__ */ jsxRuntime.jsx(ResultSummaryTile, { label: "Foreground", children: /* @__PURE__ */ jsxRuntime.jsx(ResultColorSummary, { color: pair.foreground }) }),
18062
+ /* @__PURE__ */ jsxRuntime.jsxs(ResultSummaryTile, { label: "Accessibility", className: "md:col-span-2", children: [
18063
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl leading-8 font-semibold text-foreground", children: "Meets AAA accessibility" }),
18064
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-base/7 text-muted-foreground", children: "Best NSW default for this background." })
18065
+ ] })
18066
+ ] })
18067
+ ] });
18068
+ }
18069
+ function RecommendationCard({
18070
+ copiedKey,
18071
+ isSelected,
18072
+ item,
18073
+ onCopyPairing,
18074
+ onSelect
18075
+ }) {
18076
+ const { pair } = item;
18077
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18078
+ "div",
18079
+ {
18080
+ className: cn(
18081
+ "relative rounded-sm border bg-white p-4 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
18082
+ isSelected ? "border-primary-800 bg-primary-50/50" : "border-grey-200 hover:border-primary-500 hover:bg-grey-50"
18083
+ ),
18084
+ children: [
18085
+ /* @__PURE__ */ jsxRuntime.jsx(
18086
+ "button",
18087
+ {
18088
+ type: "button",
18089
+ "aria-pressed": isSelected,
18090
+ "aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
18091
+ onClick: onSelect,
18092
+ className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
18093
+ }
18094
+ ),
18095
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10", children: [
18096
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
18097
+ /* @__PURE__ */ jsxRuntime.jsxs(
18098
+ "span",
18099
+ {
18100
+ className: cn(
18101
+ "inline-flex items-center gap-2 rounded-sm px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.12em] uppercase",
18102
+ item.category === "best" ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
18103
+ ),
18104
+ children: [
18105
+ item.category === "best" ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
18106
+ item.categoryLabel
18107
+ ]
18108
+ }
18109
+ ),
18110
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsxs(
18111
+ Button2,
18112
+ {
18113
+ variant: "ghost",
18114
+ color: "grey",
18115
+ size: "sm",
18116
+ onClick: onCopyPairing,
18117
+ "aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
18118
+ children: [
18119
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18120
+ copiedKey === `pair:${pair.id}` ? "Copied" : "Copy"
18121
+ ]
18122
+ }
18123
+ ) })
18124
+ ] }),
18125
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
18126
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-[4rem_minmax(0,1fr)]", children: [
18127
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-[2px] border border-black/10", children: [
18128
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16 w-full", style: { backgroundColor: pair.background.hex } }),
18129
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-full", style: { backgroundColor: pair.foreground.hex } })
18130
+ ] }),
18131
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-2", children: [
18132
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
18133
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold text-foreground", children: getPairingColorDisplayName3(pair.foreground) }),
18134
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.74rem] break-all text-muted-foreground", children: pair.foreground.token })
18135
+ ] }),
18136
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
18137
+ pair.foreground.familyLabel,
18138
+ " on ",
18139
+ pair.background.familyLabel
18140
+ ] })
18141
+ ] })
18142
+ ] }),
18143
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-col items-start gap-3 sm:flex-row sm:flex-wrap sm:items-center sm:justify-between", children: [
18144
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
18145
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex rounded-sm border border-grey-300 px-2.5 py-1 text-sm font-semibold text-foreground", children: [
18146
+ pair.contrastRatio.toFixed(2),
18147
+ ":1"
18148
+ ] }),
18149
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm bg-success-700 px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] text-white uppercase", children: "AAA" })
18150
+ ] }),
18151
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-primary-800", children: isSelected ? "Selected" : "Use pairing" })
18152
+ ] })
18153
+ ] })
18154
+ ] })
18155
+ ]
18156
+ }
18157
+ );
18158
+ }
18159
+ function TechnicalDetailsPanel({
18160
+ color: color2,
18161
+ copiedKey,
18162
+ onCopyValue,
18163
+ title,
18164
+ visibleFormats
18165
+ }) {
18166
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
18167
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-4 py-4 sm:px-5", children: [
18168
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
18169
+ color2 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18170
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName3(color2) }),
18171
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 overflow-hidden rounded-sm border border-black/10 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-20 w-full sm:h-24", style: { backgroundColor: color2.hex } }) })
18172
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
18173
+ ] }),
18174
+ color2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows(color2, visibleFormats).map((row) => {
18175
+ const copyKey = `${title}-${row.key}`;
18176
+ return /* @__PURE__ */ jsxRuntime.jsxs(
18177
+ "div",
18178
+ {
18179
+ className: "flex flex-col items-start gap-3 px-4 py-4 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:px-5",
18180
+ children: [
18181
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
18182
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
18183
+ /* @__PURE__ */ jsxRuntime.jsx(
18184
+ "p",
18185
+ {
18186
+ className: cn(
18187
+ "mt-2 text-sm text-foreground",
18188
+ row.key !== "tone" && "font-mono break-all"
18189
+ ),
18190
+ children: row.value
18191
+ }
18192
+ )
18193
+ ] }),
18194
+ row.copyable ? /* @__PURE__ */ jsxRuntime.jsx(
18195
+ Button2,
18196
+ {
18197
+ variant: "ghost",
18198
+ color: "grey",
18199
+ size: "sm",
18200
+ className: "self-start",
18201
+ onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
18202
+ "aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
18203
+ children: copiedKey === copyKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18204
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
18205
+ "Copied"
18206
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18207
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18208
+ "Copy"
18209
+ ] })
18210
+ }
18211
+ ) : null
18212
+ ]
18213
+ },
18214
+ row.key
18215
+ );
18216
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "No technical values are shown because there is no AAA-compliant foreground for this background." }) })
18217
+ ] });
18218
+ }
18219
+ function resolveSelectionState(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
18220
+ const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
18221
+ const selectedBackgroundToken = resolveBackgroundToken3(
18222
+ context,
18223
+ preferredBackgroundToken,
18224
+ getToneFromToken3(preferredBackgroundToken)
18225
+ );
18226
+ const selectedPairId = getPreferredPairForBackground3(
18227
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
18228
+ preferredPairId
18229
+ )?.id ?? "";
18230
+ return {
18231
+ accentKey: context.accent.key,
18232
+ context,
18233
+ primaryKey: context.primary.key,
18234
+ selectedBackgroundToken,
18235
+ selectedPairId,
18236
+ themeCategory: nextThemeCategory
18237
+ };
18238
+ }
18239
+ function ColorPairingToolV3Loading() {
18240
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
18241
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
18242
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
18243
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
18244
+ ] }),
18245
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
18246
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
18247
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
18248
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
18249
+ ] })
18250
+ ] });
18251
+ }
18252
+ function ColorPairingToolV3Content({
18253
+ onAnalyticsEvent,
18254
+ visibleFormats
18255
+ }) {
18256
+ const searchParams = navigation.useSearchParams();
18257
+ const stickyOffset = useStickyOffset(24);
18258
+ const [initialState] = React5.useState(() => getInitialPairingState3(searchParams));
18259
+ const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
18260
+ const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
18261
+ const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
18262
+ const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
18263
+ initialState.selectedBackgroundToken
18264
+ );
18265
+ const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
18266
+ const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
18267
+ const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
18268
+ const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
18269
+ const [copiedKey, setCopiedKey] = React5.useState(null);
18270
+ const copiedKeyTimeoutRef = React5.useRef(null);
18271
+ const resultSectionRef = React5.useRef(null);
18272
+ const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
18273
+ const technicalDetailsOpenedRef = React5.useRef(false);
18274
+ const emitAnalyticsEvent = React5.useCallback(
18275
+ (event) => {
18276
+ onAnalyticsEvent(event);
18277
+ if (typeof window !== "undefined") {
18278
+ window.dispatchEvent(
18279
+ new CustomEvent(COLOR_PAIRING_TOOL_V3_ANALYTICS_EVENT, {
18280
+ detail: event
18281
+ })
18282
+ );
18283
+ }
18284
+ },
18285
+ [onAnalyticsEvent]
18286
+ );
18287
+ React5.useEffect(() => {
18288
+ return () => {
18289
+ if (copiedKeyTimeoutRef.current) {
18290
+ clearTimeout(copiedKeyTimeoutRef.current);
18291
+ }
18292
+ };
18293
+ }, []);
18294
+ React5.useEffect(() => {
18295
+ if (typeof window === "undefined") {
18296
+ return;
18297
+ }
18298
+ const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY);
18299
+ const handleChange = (event) => {
18300
+ if (event?.matches ?? mediaQuery.matches) {
18301
+ setIsCompactControlsOpen(false);
18302
+ }
18303
+ };
18304
+ handleChange();
18305
+ mediaQuery.addEventListener("change", handleChange);
18306
+ return () => {
18307
+ mediaQuery.removeEventListener("change", handleChange);
18308
+ };
18309
+ }, []);
18310
+ const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
18311
+ const context = React5.useMemo(
18312
+ () => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
18313
+ [themeCategory, primaryFamilyKey, accentFamilyKey]
18314
+ );
18315
+ const selectableFamilies = React5.useMemo(
18316
+ () => themeFamilies.filter((family) => family.key !== context.grey.key),
18317
+ [themeFamilies, context.grey.key]
18318
+ );
18319
+ const selectableAccentFamilies = React5.useMemo(
18320
+ () => selectableFamilies.filter((family) => family.key !== context.primary.key),
18321
+ [selectableFamilies, context.primary.key]
18322
+ );
18323
+ const selectedBackground = React5.useMemo(
18324
+ () => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
18325
+ [context.backgrounds, selectedBackgroundToken]
18326
+ );
18327
+ const selectedBackgroundPairs = React5.useMemo(
18328
+ () => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
18329
+ [context.pairsByBackground, selectedBackground]
18330
+ );
18331
+ const bestRecommendedPair = React5.useMemo(
18332
+ () => getPreferredPairForBackground3(selectedBackgroundPairs),
18333
+ [selectedBackgroundPairs]
18334
+ );
18335
+ const selectedPair = React5.useMemo(
18336
+ () => getPreferredPairForBackground3(selectedBackgroundPairs, selectedPairId),
18337
+ [selectedBackgroundPairs, selectedPairId]
18338
+ );
18339
+ const whiteForegroundExample = React5.useMemo(
18340
+ () => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
18341
+ [selectedBackground]
18342
+ );
18343
+ const previewPair = selectedPair ?? whiteForegroundExample ?? null;
18344
+ const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
18345
+ const familySummary = React5.useMemo(
18346
+ () => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
18347
+ [context.accent.label, context.grey.label, context.primary.label]
18348
+ );
18349
+ const recommendationItems = React5.useMemo(() => {
18350
+ return selectedBackgroundPairs.map((pair) => {
18351
+ const category = getRecommendationCategory(pair, bestRecommendedPair, context);
18352
+ return {
18353
+ category,
18354
+ categoryLabel: getRecommendationCategoryLabel(category),
18355
+ pair
18356
+ };
18357
+ }).sort(
18358
+ (left, right) => getRecommendationSortRank(left.category) - getRecommendationSortRank(right.category)
18359
+ );
18360
+ }, [bestRecommendedPair, context, selectedBackgroundPairs]);
18361
+ const liveAnnouncement = React5.useMemo(
18362
+ () => getLiveAnnouncement(previewPair, selectedBackground),
18363
+ [previewPair, selectedBackground]
18364
+ );
18365
+ const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
18366
+ const shareUrl = React5.useMemo(() => {
18367
+ const params = new URLSearchParams();
18368
+ params.set("palette", themeCategory);
18369
+ params.set("primary", context.primary.key);
18370
+ params.set("accent", context.accent.key);
18371
+ if (shareBackgroundToken) {
18372
+ params.set("background", shareBackgroundToken);
18373
+ }
18374
+ if (selectedPairId) {
18375
+ params.set("pair", selectedPairId);
18376
+ }
18377
+ const query = params.toString();
18378
+ return `${COLOR_PAIRING_TOOL_V3_PATH}${query ? `?${query}` : ""}`;
18379
+ }, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
18380
+ const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS[drawerStepIndex];
18381
+ const isFirstDrawerStep = drawerStepIndex === 0;
18382
+ const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1;
18383
+ const desktopSidebarStyle = React5.useMemo(
18384
+ () => ({
18385
+ "--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
18386
+ "--tool-sidebar-top": `${stickyOffset}px`
18387
+ }),
18388
+ [stickyOffset]
18389
+ );
18390
+ const goToDrawerStep = React5.useCallback((stepIndex) => {
18391
+ setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)));
18392
+ }, []);
18393
+ const goToNextDrawerStep = React5.useCallback(() => {
18394
+ setDrawerStepIndex(
18395
+ (currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS.length - 1)
18396
+ );
18397
+ }, []);
18398
+ const goToPreviousDrawerStep = React5.useCallback(() => {
18399
+ setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
18400
+ }, []);
18401
+ const updateUrlParams = React5.useCallback((nextState) => {
18402
+ const params = new URLSearchParams(window.location.search);
18403
+ params.delete("family");
18404
+ params.set("palette", nextState.themeCategory);
18405
+ params.set("primary", nextState.primaryKey);
18406
+ params.set("accent", nextState.accentKey);
18407
+ params.set("background", nextState.selectedBackgroundToken);
18408
+ if (nextState.selectedPairId) {
18409
+ params.set("pair", nextState.selectedPairId);
18410
+ } else {
18411
+ params.delete("pair");
18412
+ }
18413
+ window.history.replaceState(
18414
+ null,
18415
+ "",
18416
+ `${window.location.pathname}?${params.toString()}${window.location.hash}`
18417
+ );
18418
+ }, []);
18419
+ const applyResolvedSelection = React5.useCallback(
18420
+ (nextState) => {
18421
+ setThemeCategory(nextState.themeCategory);
18422
+ setPrimaryFamilyKey(nextState.primaryKey);
18423
+ setAccentFamilyKey(nextState.accentKey);
18424
+ setSelectedBackgroundToken(nextState.selectedBackgroundToken);
18425
+ setSelectedPairId(nextState.selectedPairId);
18426
+ updateUrlParams(nextState);
18427
+ },
18428
+ [updateUrlParams]
18429
+ );
18430
+ const buildAnalyticsContext = React5.useCallback(
18431
+ (overrides) => ({
18432
+ accentKey: context.accent.key,
18433
+ backgroundToken: selectedBackground?.token,
18434
+ foregroundToken: selectedPair?.foreground.token,
18435
+ pairId: selectedPair?.id,
18436
+ palette: themeCategory,
18437
+ primaryKey: context.primary.key,
18438
+ ...overrides
18439
+ }),
18440
+ [context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
18441
+ );
18442
+ const copyValue = React5.useCallback(
18443
+ (copyKey, value, toastLabel, analyticsEvent) => {
18444
+ copyToClipboardRaw(value);
18445
+ setCopiedKey(copyKey);
18446
+ sonner.toast(toastLabel, { duration: 2e3 });
18447
+ if (analyticsEvent) {
18448
+ emitAnalyticsEvent(analyticsEvent);
18449
+ }
18450
+ if (copiedKeyTimeoutRef.current) {
18451
+ clearTimeout(copiedKeyTimeoutRef.current);
18452
+ }
18453
+ copiedKeyTimeoutRef.current = setTimeout(() => {
18454
+ setCopiedKey(null);
18455
+ copiedKeyTimeoutRef.current = null;
18456
+ }, 2e3);
18457
+ },
18458
+ [copyToClipboardRaw, emitAnalyticsEvent]
18459
+ );
18460
+ const handleThemeCategoryChange = (nextThemeCategory) => {
18461
+ const nextState = resolveSelectionState(
18462
+ nextThemeCategory,
18463
+ primaryFamilyKey,
18464
+ accentFamilyKey,
18465
+ selectedBackgroundToken,
18466
+ selectedPairId
18467
+ );
18468
+ applyResolvedSelection(nextState);
18469
+ emitAnalyticsEvent({
18470
+ name: "palette_change",
18471
+ accentKey: nextState.accentKey,
18472
+ backgroundToken: nextState.selectedBackgroundToken,
18473
+ pairId: nextState.selectedPairId,
18474
+ palette: nextState.themeCategory,
18475
+ primaryKey: nextState.primaryKey
18476
+ });
18477
+ };
18478
+ const handlePrimaryColorChange = (nextPrimaryKey) => {
18479
+ const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
18480
+ const nextState = resolveSelectionState(
18481
+ themeCategory,
18482
+ nextPrimaryKey,
18483
+ nextAccentKey,
18484
+ selectedBackgroundToken,
18485
+ selectedPairId
18486
+ );
18487
+ applyResolvedSelection(nextState);
18488
+ emitAnalyticsEvent({
18489
+ name: "primary_change",
18490
+ accentKey: nextState.accentKey,
18491
+ backgroundToken: nextState.selectedBackgroundToken,
18492
+ pairId: nextState.selectedPairId,
18493
+ palette: nextState.themeCategory,
18494
+ primaryKey: nextState.primaryKey
18495
+ });
18496
+ };
18497
+ const handleAccentColorChange = (nextAccentKey) => {
18498
+ if (nextAccentKey === primaryFamilyKey) return;
18499
+ const nextState = resolveSelectionState(
18500
+ themeCategory,
18501
+ primaryFamilyKey,
18502
+ nextAccentKey,
18503
+ selectedBackgroundToken,
18504
+ selectedPairId
18505
+ );
18506
+ applyResolvedSelection(nextState);
18507
+ emitAnalyticsEvent({
18508
+ name: "accent_change",
18509
+ accentKey: nextState.accentKey,
18510
+ backgroundToken: nextState.selectedBackgroundToken,
18511
+ pairId: nextState.selectedPairId,
18512
+ palette: nextState.themeCategory,
18513
+ primaryKey: nextState.primaryKey
18514
+ });
18515
+ };
18516
+ const handleBackgroundChange = (nextSelectedBackgroundToken) => {
18517
+ const nextSelectedPairId = getPreferredPairForBackground3(
18518
+ context.pairsByBackground[nextSelectedBackgroundToken] ?? [],
18519
+ selectedPairId
18520
+ )?.id ?? "";
18521
+ const nextState = {
18522
+ accentKey: context.accent.key,
18523
+ context,
18524
+ primaryKey: context.primary.key,
18525
+ selectedBackgroundToken: nextSelectedBackgroundToken,
18526
+ selectedPairId: nextSelectedPairId,
18527
+ themeCategory
18528
+ };
18529
+ applyResolvedSelection(nextState);
18530
+ emitAnalyticsEvent({
18531
+ name: "background_selection",
18532
+ ...buildAnalyticsContext({
18533
+ backgroundToken: nextSelectedBackgroundToken,
18534
+ foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
18535
+ (pair) => pair.id === nextSelectedPairId
18536
+ )?.foreground.token,
18537
+ pairId: nextSelectedPairId
18538
+ })
18539
+ });
18540
+ if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY).matches) {
18541
+ requestAnimationFrame(() => {
18542
+ resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
18543
+ });
18544
+ }
18545
+ };
18546
+ const handlePairChange = (nextSelectedPairId, source) => {
18547
+ if (!selectedBackground) return;
18548
+ const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
18549
+ setSelectedPairId(nextSelectedPairId);
18550
+ updateUrlParams({
18551
+ accentKey: context.accent.key,
18552
+ context,
18553
+ primaryKey: context.primary.key,
18554
+ selectedBackgroundToken: selectedBackground.token,
18555
+ selectedPairId: nextSelectedPairId,
18556
+ themeCategory
18557
+ });
18558
+ emitAnalyticsEvent({
18559
+ name: "foreground_selection",
18560
+ ...buildAnalyticsContext({
18561
+ foregroundToken: nextPair?.foreground.token,
18562
+ pairId: nextSelectedPairId,
18563
+ source
18564
+ })
18565
+ });
18566
+ if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
18567
+ emitAnalyticsEvent({
18568
+ name: "alternative_combination_selected",
18569
+ ...buildAnalyticsContext({
18570
+ foregroundToken: nextPair?.foreground.token,
18571
+ pairId: nextSelectedPairId,
18572
+ source
18573
+ })
18574
+ });
18575
+ }
18576
+ };
18577
+ React5.useEffect(() => {
18578
+ if (!selectedBackground || selectedBackgroundPairs.length > 0) {
18579
+ return;
18580
+ }
18581
+ const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
18582
+ if (noValidStateRef.current.has(key)) {
18583
+ return;
18584
+ }
18585
+ noValidStateRef.current.add(key);
18586
+ emitAnalyticsEvent({
18587
+ name: "no_valid_combination_state",
18588
+ ...buildAnalyticsContext({
18589
+ backgroundToken: selectedBackground.token
18590
+ })
18591
+ });
18592
+ }, [
18593
+ buildAnalyticsContext,
18594
+ context.accent.key,
18595
+ context.primary.key,
18596
+ emitAnalyticsEvent,
18597
+ selectedBackground,
18598
+ selectedBackgroundPairs.length,
18599
+ themeCategory
18600
+ ]);
18601
+ React5.useEffect(() => {
18602
+ if (technicalDetailsOpenedRef.current) {
18603
+ return;
18604
+ }
18605
+ technicalDetailsOpenedRef.current = true;
18606
+ emitAnalyticsEvent({
18607
+ name: "technical_details_opened",
18608
+ ...buildAnalyticsContext({
18609
+ source: "details"
18610
+ })
18611
+ });
18612
+ }, [buildAnalyticsContext, emitAnalyticsEvent]);
18613
+ if (!selectedBackground) {
18614
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
18615
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
18616
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
18617
+ ] });
18618
+ }
18619
+ const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName3(
18620
+ selectedBackground
18621
+ )} background.`;
18622
+ const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18623
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
18624
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
18625
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
18626
+ !isFirstDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", color: "grey", size: "sm", onClick: goToPreviousDrawerStep, children: [
18627
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.west, { "data-slot": "icon", className: "size-5" }),
18628
+ "Back"
18629
+ ] }) : null,
18630
+ isOverlay ? /* @__PURE__ */ jsxRuntime.jsx(
18631
+ Button2,
18632
+ {
18633
+ variant: "ghost",
18634
+ color: "grey",
18635
+ size: "icon",
18636
+ onClick: () => setIsCompactControlsOpen(false),
18637
+ "aria-label": "Close configuration",
18638
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-5" })
18639
+ }
18640
+ ) : null
18641
+ ] })
18642
+ ] }) }),
18643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
18644
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
18645
+ COLOR_PAIRING_TOOL_DRAWER_STEPS.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
18646
+ "button",
18647
+ {
18648
+ type: "button",
18649
+ "aria-current": index === drawerStepIndex ? "step" : void 0,
18650
+ "aria-label": `${step.eyebrow}: ${step.title}`,
18651
+ onClick: () => goToDrawerStep(index),
18652
+ className: "flex-1 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
18653
+ children: /* @__PURE__ */ jsxRuntime.jsx(
18654
+ "span",
18655
+ {
18656
+ className: cn(
18657
+ "block h-1.5 rounded-full transition-colors",
18658
+ index <= drawerStepIndex ? "bg-primary-800" : "bg-grey-200"
18659
+ )
18660
+ }
18661
+ )
18662
+ },
18663
+ step.id
18664
+ )),
18665
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-2 basis-full text-[0.68rem] font-semibold tracking-[0.12em] text-primary-800 uppercase sm:mt-0 sm:ml-2 sm:basis-auto sm:text-[0.72rem]", children: activeDrawerStep.eyebrow })
18666
+ ] }),
18667
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
18668
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: activeDrawerStep.title }),
18669
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: activeDrawerStep.description })
18670
+ ] })
18671
+ ] }),
18672
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
18673
+ "div",
18674
+ {
18675
+ className: "flex h-full transition-transform duration-300 ease-out",
18676
+ style: { transform: `translateX(-${drawerStepIndex * 100}%)` },
18677
+ children: [
18678
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 pr-1", children: [
18679
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
18680
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Palette" }),
18681
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: ["brand", "aboriginal"].map((palette) => {
18682
+ const isSelected = themeCategory === palette;
18683
+ const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
18684
+ return /* @__PURE__ */ jsxRuntime.jsx(
18685
+ SelectorButton,
18686
+ {
18687
+ label,
18688
+ isSelected,
18689
+ onClick: () => handleThemeCategoryChange(palette)
18690
+ },
18691
+ palette
18692
+ );
18693
+ }) })
18694
+ ] }),
18695
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
18696
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
18697
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
18698
+ const label = getFamilySelectorLabel3(family, themeCategory, "primary colour");
18699
+ return /* @__PURE__ */ jsxRuntime.jsx(
18700
+ SelectorButton,
18701
+ {
18702
+ label,
18703
+ isSelected: family.key === context.primary.key,
18704
+ onClick: () => handlePrimaryColorChange(family.key),
18705
+ swatch: getFamilySwatchColor3(family, 800)
18706
+ },
18707
+ family.key
18708
+ );
18709
+ }) })
18710
+ ] }),
18711
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
18712
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
18713
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
18714
+ const label = getFamilySelectorLabel3(family, themeCategory, "accent colour");
18715
+ return /* @__PURE__ */ jsxRuntime.jsx(
18716
+ SelectorButton,
18717
+ {
18718
+ label,
18719
+ isSelected: family.key === context.accent.key,
18720
+ onClick: () => handleAccentColorChange(family.key),
18721
+ swatch: getFamilySwatchColor3(family, 600)
18722
+ },
18723
+ family.key
18724
+ );
18725
+ }) })
18726
+ ] }),
18727
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-grey-200 pt-4", children: [
18728
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Grey is always included" }),
18729
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Neutral grey options are automatically added so every selection includes a practical fallback family." })
18730
+ ] })
18731
+ ] }) }),
18732
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 pr-1", children: context.backgroundGroups.map((group, index) => /* @__PURE__ */ jsxRuntime.jsxs(
18733
+ "section",
18734
+ {
18735
+ className: cn("space-y-3", index > 0 && "border-t border-grey-200 pt-6"),
18736
+ children: [
18737
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
18738
+ /* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: [
18739
+ group.family.label,
18740
+ " backgrounds"
18741
+ ] }),
18742
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
18743
+ ] }),
18744
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
18745
+ BackgroundSwatchButton,
18746
+ {
18747
+ background,
18748
+ hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
18749
+ isSelected: selectedBackground.token === background.token,
18750
+ onClick: () => handleBackgroundChange(background.token)
18751
+ },
18752
+ background.token
18753
+ )) })
18754
+ ]
18755
+ },
18756
+ group.key
18757
+ )) }) }),
18758
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "h-full w-full shrink-0 overflow-y-auto px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 pr-1", children: recommendationItems.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: recommendationItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
18759
+ RecommendationCard,
18760
+ {
18761
+ copiedKey,
18762
+ item,
18763
+ isSelected: item.pair.id === selectedPair?.id,
18764
+ onCopyPairing: () => copyValue(
18765
+ `pair:${item.pair.id}`,
18766
+ getPairingCopyText(item.pair),
18767
+ "Pairing copied",
18768
+ item.pair.id === bestRecommendedPair?.id ? {
18769
+ name: "best_recommendation_copied",
18770
+ ...buildAnalyticsContext({
18771
+ foregroundToken: item.pair.foreground.token,
18772
+ pairId: item.pair.id,
18773
+ source: "recommendations-list"
18774
+ })
18775
+ } : void 0
18776
+ ),
18777
+ onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
18778
+ },
18779
+ item.pair.id
18780
+ )) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-5 py-5", children: [
18781
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "No valid combinations available" }),
18782
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options are available for this background." })
18783
+ ] }) }) })
18784
+ ]
18785
+ }
18786
+ ) }),
18787
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-5 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
18788
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Select a combination to update the result immediately." }) : null }),
18789
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
18790
+ isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
18791
+ Button2,
18792
+ {
18793
+ color: "primary",
18794
+ className: "w-full sm:w-auto sm:min-w-40",
18795
+ onClick: () => setIsCompactControlsOpen(false),
18796
+ children: "Review result"
18797
+ }
18798
+ ) : null,
18799
+ !isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { color: "primary", className: "w-full sm:w-auto", onClick: goToNextDrawerStep, children: [
18800
+ "Continue",
18801
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.east, { "data-slot": "icon", className: "size-5" })
18802
+ ] }) : null
18803
+ ] })
18804
+ ] }) })
18805
+ ] });
18806
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
18807
+ /* @__PURE__ */ jsxRuntime.jsx(
18808
+ "div",
18809
+ {
18810
+ "data-slot": "tool-sidebar",
18811
+ className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
18812
+ style: desktopSidebarStyle,
18813
+ children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "h-[40rem] max-h-[40rem] gap-0 overflow-hidden py-0 sm:h-[44rem] sm:max-h-[44rem] xl:h-[var(--tool-sidebar-max-height)] xl:max-h-[var(--tool-sidebar-max-height)]", children: renderControlsPanel() })
18814
+ }
18815
+ ),
18816
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-6", children: [
18817
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4 xl:hidden", children: [
18818
+ /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between", children: [
18819
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
18820
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
18821
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the colour pairing drawer to change palette, background, and recommended combinations." }),
18822
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
18823
+ ] }),
18824
+ /* @__PURE__ */ jsxRuntime.jsxs(
18825
+ Button2,
18826
+ {
18827
+ color: "primary",
18828
+ className: "w-full sm:w-auto",
18829
+ onClick: () => setIsCompactControlsOpen(true),
18830
+ children: [
18831
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.edit_square, { "data-slot": "icon", className: "size-5" }),
18832
+ "Open configuration"
18833
+ ]
18834
+ }
18835
+ )
18836
+ ] }) }),
18837
+ /* @__PURE__ */ jsxRuntime.jsx(Sheet, { open: isCompactControlsOpen, onOpenChange: setIsCompactControlsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
18838
+ SheetContent,
18839
+ {
18840
+ side: "left",
18841
+ showClose: false,
18842
+ className: "w-[30rem] max-w-[90vw] overflow-hidden p-0",
18843
+ children: [
18844
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Colour pairing configuration" }),
18845
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full flex-col bg-background", children: renderControlsPanel(true) })
18846
+ ]
18847
+ }
18848
+ ) })
18849
+ ] }),
18850
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-6", "aria-label": "Current result", children: [
18851
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
18852
+ /* @__PURE__ */ jsxRuntime.jsx(
18853
+ CurrentResultCard,
18854
+ {
18855
+ bestPair: bestRecommendedPair,
18856
+ familySummary,
18857
+ pair: previewPair,
18858
+ selectedBackground
18859
+ }
18860
+ )
18861
+ ] }),
18862
+ bestRecommendedPair ? /* @__PURE__ */ jsxRuntime.jsx("section", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsx(
18863
+ BestRecommendationCard,
18864
+ {
18865
+ copiedKey,
18866
+ isCurrentSelection: selectedPair?.id === bestRecommendedPair.id,
18867
+ pair: bestRecommendedPair,
18868
+ reason: getBestRecommendationReason(bestRecommendedPair, context),
18869
+ onCopyPairing: () => copyValue(
18870
+ "best-pairing",
18871
+ getPairingCopyText(bestRecommendedPair),
18872
+ "Pairing copied",
18873
+ {
18874
+ name: "best_recommendation_copied",
18875
+ ...buildAnalyticsContext({
18876
+ foregroundToken: bestRecommendedPair.foreground.token,
18877
+ pairId: bestRecommendedPair.id,
18878
+ source: "best-recommendation"
18879
+ })
18880
+ }
18881
+ ),
18882
+ onUsePairing: () => handlePairChange(bestRecommendedPair.id, "best-recommendation")
18883
+ }
18884
+ ) }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
18885
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Best recommended pairing" }),
18886
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No AAA-compliant foreground options available for this selection." })
18887
+ ] }),
18888
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
18889
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
18890
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
18891
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
18892
+ ] }),
18893
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
18894
+ /* @__PURE__ */ jsxRuntime.jsx(
18895
+ TechnicalDetailsPanel,
18896
+ {
18897
+ title: "Background values",
18898
+ color: selectedBackground,
18899
+ visibleFormats,
18900
+ copiedKey,
18901
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
18902
+ }
18903
+ ),
18904
+ /* @__PURE__ */ jsxRuntime.jsx(
18905
+ TechnicalDetailsPanel,
18906
+ {
18907
+ title: "Foreground values",
18908
+ color: detailForeground,
18909
+ visibleFormats,
18910
+ copiedKey,
18911
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
18912
+ }
18913
+ )
18914
+ ] }),
18915
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
18916
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Share colour pairing" }),
18917
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white p-4", children: [
18918
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
18919
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy this URL to share your current colour pairing:" }),
18920
+ /* @__PURE__ */ jsxRuntime.jsx(
18921
+ Button2,
18922
+ {
18923
+ variant: "ghost",
18924
+ color: "grey",
18925
+ size: "sm",
18926
+ className: "shrink-0",
18927
+ onClick: () => copyValue(
18928
+ "share-url",
18929
+ typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
18930
+ "Colour pairing link copied"
18931
+ ),
18932
+ "aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
18933
+ title: copiedKey === "share-url" ? "Copied" : "Copy URL",
18934
+ children: copiedKey === "share-url" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18935
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
18936
+ "Copied"
18937
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18938
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
18939
+ "Copy URL"
18940
+ ] })
18941
+ }
18942
+ )
18943
+ ] }),
18944
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "mt-3 block w-full rounded-sm border border-grey-200 bg-background px-3 py-2 font-mono text-[11px] break-all text-foreground sm:text-xs", children: shareUrl })
18945
+ ] })
18946
+ ] })
18947
+ ] })
18948
+ ] })
18949
+ ] });
18950
+ }
18951
+ function ColorPairingToolV3({
18952
+ onAnalyticsEvent = () => {
18953
+ },
18954
+ visibleFormats = DEFAULT_VISIBLE_FORMATS3
18955
+ } = {}) {
18956
+ const normalizedVisibleFormats = [...new Set(visibleFormats)];
18957
+ return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV3Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
18958
+ ColorPairingToolV3Content,
18959
+ {
18960
+ onAnalyticsEvent,
18961
+ visibleFormats: normalizedVisibleFormats
18962
+ }
18963
+ ) });
18964
+ }
16360
18965
  function ColorSwatches({ theme: theme2, format, viewMode }) {
16361
18966
  return /* @__PURE__ */ jsxRuntime.jsx(
16362
18967
  "div",
@@ -17270,23 +19875,23 @@ var ComboChart = React5__namespace.default.forwardRef((props, forwardedRef) => {
17270
19875
  });
17271
19876
  ComboChart.displayName = "ComboChart";
17272
19877
  function Dialog({ ...props }) {
17273
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { "data-slot": "dialog", ...props });
19878
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Root, { "data-slot": "dialog", ...props });
17274
19879
  }
17275
19880
  function DialogTrigger({ ...props }) {
17276
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Trigger, { "data-slot": "dialog-trigger", ...props });
19881
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Trigger, { "data-slot": "dialog-trigger", ...props });
17277
19882
  }
17278
19883
  function DialogPortal({ ...props }) {
17279
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { "data-slot": "dialog-portal", ...props });
19884
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Portal, { "data-slot": "dialog-portal", ...props });
17280
19885
  }
17281
19886
  function DialogClose({ ...props }) {
17282
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "dialog-close", ...props });
19887
+ return /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { "data-slot": "dialog-close", ...props });
17283
19888
  }
17284
19889
  function DialogOverlay({
17285
19890
  className,
17286
19891
  ...props
17287
19892
  }) {
17288
19893
  return /* @__PURE__ */ jsxRuntime.jsx(
17289
- DialogPrimitive__namespace.Overlay,
19894
+ SheetPrimitive__namespace.Overlay,
17290
19895
  {
17291
19896
  "data-slot": "dialog-overlay",
17292
19897
  className: cn(
@@ -17306,7 +19911,7 @@ function DialogContent({
17306
19911
  return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
17307
19912
  /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
17308
19913
  /* @__PURE__ */ jsxRuntime.jsxs(
17309
- DialogPrimitive__namespace.Content,
19914
+ SheetPrimitive__namespace.Content,
17310
19915
  {
17311
19916
  "data-slot": "dialog-content",
17312
19917
  className: cn(
@@ -17316,7 +19921,7 @@ function DialogContent({
17316
19921
  ...props,
17317
19922
  children: [
17318
19923
  children,
17319
- showClose && /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { className: "absolute top-1 right-1", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
19924
+ showClose && /* @__PURE__ */ jsxRuntime.jsx(SheetPrimitive__namespace.Close, { className: "absolute top-1 right-1", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
17320
19925
  /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
17321
19926
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
17322
19927
  ] }) })
@@ -17347,7 +19952,7 @@ function DialogFooter({ className, ...props }) {
17347
19952
  }
17348
19953
  function DialogTitle({ className, ...props }) {
17349
19954
  return /* @__PURE__ */ jsxRuntime.jsx(
17350
- DialogPrimitive__namespace.Title,
19955
+ SheetPrimitive__namespace.Title,
17351
19956
  {
17352
19957
  "data-slot": "dialog-title",
17353
19958
  className: cn("text-lg leading-none font-semibold", className),
@@ -17360,7 +19965,7 @@ function DialogDescription({
17360
19965
  ...props
17361
19966
  }) {
17362
19967
  return /* @__PURE__ */ jsxRuntime.jsx(
17363
- DialogPrimitive__namespace.Description,
19968
+ SheetPrimitive__namespace.Description,
17364
19969
  {
17365
19970
  "data-slot": "dialog-description",
17366
19971
  className: cn("text-sm text-muted-foreground", className),
@@ -18132,7 +20737,7 @@ function DescriptionList({ className, ...props }) {
18132
20737
  "dl",
18133
20738
  {
18134
20739
  ...props,
18135
- className: clsx12__default.default(
20740
+ className: clsx13__default.default(
18136
20741
  className,
18137
20742
  "grid grid-cols-1 text-base/6 sm:grid-cols-[min(50%,--spacing(80))_auto] sm:text-sm/6"
18138
20743
  )
@@ -18144,7 +20749,7 @@ function DescriptionTerm({ className, ...props }) {
18144
20749
  "dt",
18145
20750
  {
18146
20751
  ...props,
18147
- className: clsx12__default.default(
20752
+ className: clsx13__default.default(
18148
20753
  className,
18149
20754
  "col-start-1 border-t border-grey-950/5 pt-3 text-grey-600 first:border-none sm:border-t sm:border-grey-950/5 sm:py-3 dark:border-white/5 dark:text-grey-400 sm:dark:border-white/5"
18150
20755
  )
@@ -18156,7 +20761,7 @@ function DescriptionDetails({ className, ...props }) {
18156
20761
  "dd",
18157
20762
  {
18158
20763
  ...props,
18159
- className: clsx12__default.default(
20764
+ className: clsx13__default.default(
18160
20765
  className,
18161
20766
  "pt-1 pb-3 text-grey-950 sm:border-t sm:border-grey-950/5 sm:py-3 sm:nth-2:border-none dark:text-white dark:sm:border-white/5"
18162
20767
  )
@@ -18570,7 +21175,7 @@ function Fieldset2({
18570
21175
  Headless4__namespace.Fieldset,
18571
21176
  {
18572
21177
  ...props,
18573
- className: clsx12__default.default(className, "*:data-[slot=text]:mt-1 [&>*+[data-slot=control]]:mt-6")
21178
+ className: clsx13__default.default(className, "*:data-[slot=text]:mt-1 [&>*+[data-slot=control]]:mt-6")
18574
21179
  }
18575
21180
  );
18576
21181
  }
@@ -18583,7 +21188,7 @@ function Legend6({
18583
21188
  {
18584
21189
  "data-slot": "legend",
18585
21190
  ...props,
18586
- className: clsx12__default.default(
21191
+ className: clsx13__default.default(
18587
21192
  className,
18588
21193
  "text-base/6 font-semibold text-zinc-950 data-disabled:opacity-50 sm:text-sm/6 dark:text-white"
18589
21194
  )
@@ -18591,7 +21196,7 @@ function Legend6({
18591
21196
  );
18592
21197
  }
18593
21198
  function FieldGroup({ className, ...props }) {
18594
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "control", ...props, className: clsx12__default.default(className, "space-y-8") });
21199
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "control", ...props, className: clsx13__default.default(className, "space-y-8") });
18595
21200
  }
18596
21201
  function Field2({
18597
21202
  className,
@@ -18601,7 +21206,7 @@ function Field2({
18601
21206
  Headless4__namespace.Field,
18602
21207
  {
18603
21208
  ...props,
18604
- className: clsx12__default.default(
21209
+ className: clsx13__default.default(
18605
21210
  className,
18606
21211
  "[&>[data-slot=label]+[data-slot=control]]:mt-3",
18607
21212
  "[&>[data-slot=label]+[data-slot=description]]:mt-1",
@@ -18622,14 +21227,14 @@ function FieldLabel({
18622
21227
  {
18623
21228
  "data-slot": "label",
18624
21229
  ...props,
18625
- className: clsx12__default.default(
21230
+ className: clsx13__default.default(
18626
21231
  className,
18627
21232
  "text-base/6 text-zinc-950 select-none data-disabled:opacity-50 sm:text-sm/6 dark:text-white"
18628
21233
  )
18629
21234
  }
18630
21235
  );
18631
21236
  }
18632
- function Description4({
21237
+ function Description5({
18633
21238
  className,
18634
21239
  ...props
18635
21240
  }) {
@@ -18638,7 +21243,7 @@ function Description4({
18638
21243
  {
18639
21244
  "data-slot": "description",
18640
21245
  ...props,
18641
- className: clsx12__default.default(
21246
+ className: clsx13__default.default(
18642
21247
  className,
18643
21248
  "text-base/6 text-zinc-500 data-disabled:opacity-50 sm:text-sm/6 dark:text-zinc-400"
18644
21249
  )
@@ -18654,7 +21259,7 @@ function ErrorMessage({
18654
21259
  {
18655
21260
  "data-slot": "error",
18656
21261
  ...props,
18657
- className: clsx12__default.default(
21262
+ className: clsx13__default.default(
18658
21263
  className,
18659
21264
  "text-base/6 text-red-600 data-disabled:opacity-50 sm:text-sm/6 dark:text-red-500"
18660
21265
  )
@@ -18878,7 +21483,7 @@ var toggleVariants = classVarianceAuthority.cva(styles3.base, {
18878
21483
  variants: {
18879
21484
  variant: {
18880
21485
  ghost: "",
18881
- outline: clsx12__default.default(styles3.outline)
21486
+ outline: clsx13__default.default(styles3.outline)
18882
21487
  },
18883
21488
  size: {
18884
21489
  default: "h-9 px-2 min-w-9",
@@ -18981,7 +21586,7 @@ function FormatToggle({ format, setFormat }) {
18981
21586
 
18982
21587
  // package.json
18983
21588
  var package_default = {
18984
- version: "1.101.0"};
21589
+ version: "1.103.0"};
18985
21590
  function Logo(props) {
18986
21591
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18987
21592
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "NSW Government" }),
@@ -19131,7 +21736,7 @@ function Header2({
19131
21736
  "data-slot": "header",
19132
21737
  "data-scrolled": isScrolled,
19133
21738
  id: "nsw-header",
19134
- className: clsx12__default.default(
21739
+ className: clsx13__default.default(
19135
21740
  "sticky top-0 z-50 hidden bg-white px-4 py-5 transition duration-500 sm:px-6 lg:flex lg:flex-none lg:flex-wrap lg:items-center lg:justify-between lg:px-12",
19136
21741
  !hideShadow && "shadow-md shadow-slate-900/5 dark:shadow-none",
19137
21742
  isScrolled ? "dark:bg-slate-900/95 dark:backdrop-blur-sm dark:[@supports(backdrop-filter:blur(0))]:bg-slate-900/75" : "dark:bg-transparent"
@@ -19985,7 +22590,7 @@ var LineChart = React5__namespace.default.forwardRef((props, ref) => {
19985
22590
  });
19986
22591
  LineChart.displayName = "LineChart";
19987
22592
  function cn2(...inputs) {
19988
- return tailwindMerge.twMerge(clsx12.clsx(inputs));
22593
+ return tailwindMerge.twMerge(clsx13.clsx(inputs));
19989
22594
  }
19990
22595
  var sizeStyles = {
19991
22596
  sm: "text-sm",
@@ -20047,7 +22652,7 @@ function Listbox2({
20047
22652
  autoFocus,
20048
22653
  "data-slot": "control",
20049
22654
  "aria-label": ariaLabel,
20050
- className: clsx12__default.default([
22655
+ className: clsx13__default.default([
20051
22656
  className,
20052
22657
  // Basic layout
20053
22658
  "group relative block w-full",
@@ -20071,7 +22676,7 @@ function Listbox2({
20071
22676
  as: "span",
20072
22677
  options,
20073
22678
  placeholder: placeholder && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-grey-500", children: placeholder }),
20074
- className: clsx12__default.default([
22679
+ className: clsx13__default.default([
20075
22680
  "cursor-pointer",
20076
22681
  // Basic layout
20077
22682
  "relative block w-full appearance-none rounded-sm py-[calc(--spacing(4.5)-1px)] sm:py-[calc(--spacing(3.5)-1px)]",
@@ -20101,7 +22706,7 @@ function Listbox2({
20101
22706
  {
20102
22707
  transition: true,
20103
22708
  anchor: "selection start",
20104
- className: clsx12__default.default(
22709
+ className: clsx13__default.default(
20105
22710
  // Anchor positioning
20106
22711
  "[--anchor-offset:-1.625rem] [--anchor-padding:--spacing(4)] sm:[--anchor-offset:-1.375rem]",
20107
22712
  // Base styles
@@ -20127,7 +22732,7 @@ function ListboxOption2({
20127
22732
  className,
20128
22733
  ...props
20129
22734
  }) {
20130
- const sharedClasses = clsx12__default.default(
22735
+ const sharedClasses = clsx13__default.default(
20131
22736
  // Base
20132
22737
  "flex min-w-0 items-center",
20133
22738
  // Icons
@@ -20139,12 +22744,12 @@ function ListboxOption2({
20139
22744
  );
20140
22745
  return /* @__PURE__ */ jsxRuntime.jsx(Headless4__namespace.ListboxOption, { as: React5.Fragment, ...props, children: ({ selectedOption }) => {
20141
22746
  if (selectedOption) {
20142
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx12__default.default(className, sharedClasses), children });
22747
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx13__default.default(className, sharedClasses), children });
20143
22748
  }
20144
22749
  return /* @__PURE__ */ jsxRuntime.jsxs(
20145
22750
  "div",
20146
22751
  {
20147
- className: clsx12__default.default(
22752
+ className: clsx13__default.default(
20148
22753
  // Basic layout
20149
22754
  "group/option grid cursor-pointer grid-cols-[--spacing(5)_1fr] items-baseline gap-x-2 rounded-sm py-2.5 pr-3.5 pl-2 sm:grid-cols-[--spacing(4)_1fr] sm:py-1.5 sm:pr-3 sm:pl-1.5",
20150
22755
  // Typography
@@ -20175,7 +22780,7 @@ function ListboxOption2({
20175
22780
  )
20176
22781
  }
20177
22782
  ),
20178
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx12__default.default(className, sharedClasses, "col-start-2"), children })
22783
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx13__default.default(className, sharedClasses, "col-start-2"), children })
20179
22784
  ]
20180
22785
  }
20181
22786
  );
@@ -20186,7 +22791,7 @@ function ListboxLabel({ className, ...props }) {
20186
22791
  "span",
20187
22792
  {
20188
22793
  ...props,
20189
- className: clsx12__default.default(className, "ml-2.5 truncate first:ml-0 sm:ml-2 sm:first:ml-0")
22794
+ className: clsx13__default.default(className, "ml-2.5 truncate first:ml-0 sm:ml-2 sm:first:ml-0")
20190
22795
  }
20191
22796
  );
20192
22797
  }
@@ -20199,7 +22804,7 @@ function ListboxDescription({
20199
22804
  "span",
20200
22805
  {
20201
22806
  ...props,
20202
- className: clsx12__default.default(
22807
+ className: clsx13__default.default(
20203
22808
  className,
20204
22809
  "flex flex-1 overflow-hidden text-grey-500 group-data-focus/option:text-white before:w-2 before:min-w-0 before:shrink dark:text-grey-400"
20205
22810
  ),
@@ -20247,102 +22852,12 @@ function Spinner({ className, size = "md", ...props }) {
20247
22852
  }
20248
22853
  ) });
20249
22854
  }
20250
- function Text({ className, trim = "normal", size = 2, label = false, ...props }) {
20251
- const textSizeClasses = {
20252
- 1: "text-[length:var(--font-size-1)] leading-[var(--line-height-28)] tracking-[var(--letter-spacing-0)]",
20253
- 2: "text-[length:var(--font-size-2)] leading-[var(--line-height-24)] tracking-[var(--letter-spacing-0)]",
20254
- 3: "text-[length:var(--font-size-3)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]",
20255
- 4: "text-[length:var(--font-size-4)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]"
20256
- };
20257
- const labelSizeClasses = {
20258
- 1: "text-[length:var(--font-size-1)] leading-[var(--line-height-24)] tracking-[var(--letter-spacing-0)]",
20259
- 2: "text-[length:var(--font-size-2)] leading-[var(--line-height-20)] tracking-[var(--letter-spacing-0)]",
20260
- 3: "text-[length:var(--font-size-3)] leading-[var(--line-height-16)] tracking-[var(--letter-spacing-0)]",
20261
- 4: "text-[length:var(--font-size-4)] leading-[var(--line-height-16)] tracking-[var(--letter-spacing-0)]"
20262
- };
20263
- const sizeClass = label ? labelSizeClasses[size] : textSizeClasses[size];
20264
- const trimClasses = {
20265
- normal: ["before:content-none after:content-none"],
20266
- start: [
20267
- 'before:content-[""] before:table after:content-none',
20268
- "before:mb-[calc(var(--leading-trim-start,var(--default-leading-trim-start))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
20269
- ],
20270
- end: [
20271
- 'before:content-none after:content-[""] after:table',
20272
- "after:mt-[calc(var(--leading-trim-end,var(--default-leading-trim-end))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
20273
- ],
20274
- both: [
20275
- 'before:content-[""] before:table after:content-[""] after:table',
20276
- "before:mb-[calc(var(--leading-trim-start,var(--default-leading-trim-start))-var(--line-height,calc(1em*var(--default-line-height)))/2)]",
20277
- "after:mt-[calc(var(--leading-trim-end,var(--default-leading-trim-end))-var(--line-height,calc(1em*var(--default-line-height)))/2)]"
20278
- ]
20279
- };
20280
- return /* @__PURE__ */ jsxRuntime.jsx(
20281
- "p",
20282
- {
20283
- "data-slot": "text",
20284
- ...props,
20285
- className: clsx12__default.default(className, trimClasses[trim], "text-grey-800 dark:text-grey-400", sizeClass)
20286
- }
20287
- );
20288
- }
20289
- function TextLink({ className, ...props }) {
20290
- return /* @__PURE__ */ jsxRuntime.jsx(
20291
- Link,
20292
- {
20293
- ...props,
20294
- className: clsx12__default.default(
20295
- className,
20296
- "text-primary-800 underline decoration-primary-800/50 data-hover:decoration-primary-800 dark:text-white dark:decoration-white/50 dark:data-hover:decoration-white"
20297
- )
20298
- }
20299
- );
20300
- }
20301
- function Strong({ className, ...props }) {
20302
- return /* @__PURE__ */ jsxRuntime.jsx("strong", { ...props, className: clsx12__default.default(className, "font-medium text-grey-950 dark:text-white") });
20303
- }
20304
- function Code({ className, ...props }) {
20305
- const hasLanguageClass = typeof className === "string" && className.includes("language-");
20306
- return /* @__PURE__ */ jsxRuntime.jsx(
20307
- "code",
20308
- {
20309
- ...props,
20310
- className: clsx12__default.default(
20311
- className,
20312
- !hasLanguageClass && "language-plaintext",
20313
- "text-sm sm:text-[0.8125rem]"
20314
- )
20315
- }
20316
- );
20317
- }
20318
22855
  function Loading() {
20319
22856
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-screen items-center justify-center gap-4 bg-grey-50 dark:bg-grey-900", children: [
20320
22857
  /* @__PURE__ */ jsxRuntime.jsx(Spinner, { "aria-label": "Loading...", size: "lg" }),
20321
22858
  /* @__PURE__ */ jsxRuntime.jsx(Text, { children: "Loading..." })
20322
22859
  ] });
20323
22860
  }
20324
- function useSelectorHeight(selector = "header") {
20325
- const [height, setHeight] = React5.useState(0);
20326
- const elementRef = React5.useRef(null);
20327
- const resizeObserverRef = React5.useRef(null);
20328
- React5.useEffect(() => {
20329
- const element = document.querySelector(selector);
20330
- if (!element) return;
20331
- elementRef.current = element;
20332
- const resizeObserver = new ResizeObserver((entries) => {
20333
- const entry = entries[0];
20334
- const target = entry?.target ?? elementRef.current;
20335
- if (!target) return;
20336
- setHeight(target.offsetHeight);
20337
- });
20338
- resizeObserverRef.current = resizeObserver;
20339
- resizeObserver.observe(element);
20340
- return () => {
20341
- resizeObserverRef.current?.disconnect();
20342
- };
20343
- }, [selector]);
20344
- return height;
20345
- }
20346
22861
  function MainNavigation({ navigation }) {
20347
22862
  const headerHeight = useSelectorHeight();
20348
22863
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -20874,7 +23389,7 @@ function MultiLevelPushMenu({
20874
23389
  {
20875
23390
  href: item.href,
20876
23391
  onClick: (e) => handleItemClick(item, e),
20877
- className: clsx12__default.default(
23392
+ className: clsx13__default.default(
20878
23393
  "relative flex w-full cursor-pointer items-center justify-between gap-x-6 border-l p-4 transition-colors hover:border-primary-800 hover:bg-primary-800/10",
20879
23394
  pathname === item.href ? "border-primary-800 bg-primary-800/10 font-semibold text-primary-800" : "border-transparent text-grey-800",
20880
23395
  isAnimating && "pointer-events-none"
@@ -20886,7 +23401,7 @@ function MultiLevelPushMenu({
20886
23401
  {
20887
23402
  onClick: (e) => handleItemClick(item, e),
20888
23403
  disabled: isAnimating,
20889
- className: clsx12__default.default(
23404
+ className: clsx13__default.default(
20890
23405
  "relative flex w-full cursor-pointer items-center justify-between gap-x-6 border-l p-4 transition-colors hover:border-primary-800 hover:bg-primary-800/10",
20891
23406
  pathname === item.href ? "border-primary-800 bg-primary-800/10 font-semibold text-primary-800" : "border-transparent text-grey-800",
20892
23407
  isAnimating && "pointer-events-none"
@@ -20953,7 +23468,7 @@ function MobileHeader({
20953
23468
  /* @__PURE__ */ jsxRuntime.jsxs(
20954
23469
  "div",
20955
23470
  {
20956
- className: clsx12__default.default(
23471
+ className: clsx13__default.default(
20957
23472
  "relative flex w-full items-center py-4",
20958
23473
  menu && !search && "justify-start",
20959
23474
  search && "justify-between",
@@ -20969,7 +23484,7 @@ function MobileHeader({
20969
23484
  {
20970
23485
  href: "/",
20971
23486
  "aria-label": "Home page",
20972
- className: clsx12__default.default(
23487
+ className: clsx13__default.default(
20973
23488
  "flex items-center",
20974
23489
  menu && !search && "justify-start",
20975
23490
  search && !menu && "flex-row justify-between",
@@ -20980,7 +23495,7 @@ function MobileHeader({
20980
23495
  /* @__PURE__ */ jsxRuntime.jsxs(
20981
23496
  "div",
20982
23497
  {
20983
- className: clsx12__default.default(
23498
+ className: clsx13__default.default(
20984
23499
  "flex flex-wrap items-center",
20985
23500
  menu && !search && "justify-center text-left",
20986
23501
  search && !menu && "justify-center text-left",
@@ -28991,7 +31506,7 @@ var featureBundle = {
28991
31506
  // node_modules/framer-motion/dist/es/render/components/motion/proxy.mjs
28992
31507
  var motion = /* @__PURE__ */ createMotionProxy(featureBundle, createDomVisualElement);
28993
31508
  function Navbar({ className, ...props }) {
28994
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { ...props, className: clsx12__default.default(className, "flex flex-1 items-center gap-4 py-2.5") });
31509
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { ...props, className: clsx13__default.default(className, "flex flex-1 items-center gap-4 py-2.5") });
28995
31510
  }
28996
31511
  function NavbarDivider({ className, ...props }) {
28997
31512
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -28999,16 +31514,16 @@ function NavbarDivider({ className, ...props }) {
28999
31514
  {
29000
31515
  "aria-hidden": "true",
29001
31516
  ...props,
29002
- className: clsx12__default.default(className, "h-6 w-px bg-zinc-950/10 dark:bg-white/10")
31517
+ className: clsx13__default.default(className, "h-6 w-px bg-zinc-950/10 dark:bg-white/10")
29003
31518
  }
29004
31519
  );
29005
31520
  }
29006
31521
  function NavbarSection({ className, ...props }) {
29007
31522
  const id3 = React5.useId();
29008
- return /* @__PURE__ */ jsxRuntime.jsx(LayoutGroup, { id: id3, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, className: clsx12__default.default(className, "flex items-center gap-3") }) });
31523
+ return /* @__PURE__ */ jsxRuntime.jsx(LayoutGroup, { id: id3, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ...props, className: clsx13__default.default(className, "flex items-center gap-3") }) });
29009
31524
  }
29010
31525
  function NavbarSpacer({ className, ...props }) {
29011
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", ...props, className: clsx12__default.default(className, "-ml-4 flex-1") });
31526
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": "true", ...props, className: clsx13__default.default(className, "-ml-4 flex-1") });
29012
31527
  }
29013
31528
  var NavbarItem = React5.forwardRef(function NavbarItem2({
29014
31529
  current,
@@ -29016,7 +31531,7 @@ var NavbarItem = React5.forwardRef(function NavbarItem2({
29016
31531
  children,
29017
31532
  ...props
29018
31533
  }, ref) {
29019
- const classes = clsx12__default.default(
31534
+ const classes = clsx13__default.default(
29020
31535
  // Base
29021
31536
  "relative flex min-w-0 items-center gap-3 rounded-lg p-2 text-left text-base/6 font-medium text-zinc-950 sm:text-sm/5",
29022
31537
  // Leading icon/icon-only
@@ -29034,7 +31549,7 @@ var NavbarItem = React5.forwardRef(function NavbarItem2({
29034
31549
  "dark:data-hover:bg-white/5 dark:data-hover:*:data-[slot=icon]:fill-white",
29035
31550
  "dark:data-active:bg-white/5 dark:data-active:*:data-[slot=icon]:fill-white"
29036
31551
  );
29037
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: clsx12__default.default(className, "relative"), children: [
31552
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: clsx13__default.default(className, "relative"), children: [
29038
31553
  current && /* @__PURE__ */ jsxRuntime.jsx(
29039
31554
  motion.span,
29040
31555
  {
@@ -29055,7 +31570,7 @@ var NavbarItem = React5.forwardRef(function NavbarItem2({
29055
31570
  Headless4__namespace.Button,
29056
31571
  {
29057
31572
  ...props,
29058
- className: clsx12__default.default("cursor-default", classes),
31573
+ className: clsx13__default.default("cursor-default", classes),
29059
31574
  "data-current": current ? "true" : void 0,
29060
31575
  ref,
29061
31576
  children: /* @__PURE__ */ jsxRuntime.jsx(TouchTarget, { children })
@@ -29064,14 +31579,14 @@ var NavbarItem = React5.forwardRef(function NavbarItem2({
29064
31579
  ] });
29065
31580
  });
29066
31581
  function NavbarLabel({ className, ...props }) {
29067
- return /* @__PURE__ */ jsxRuntime.jsx("span", { ...props, className: clsx12__default.default(className, "truncate") });
31582
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ...props, className: clsx13__default.default(className, "truncate") });
29068
31583
  }
29069
31584
  function Navigation({
29070
31585
  className,
29071
31586
  onLinkClick,
29072
31587
  navigation
29073
31588
  }) {
29074
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx12__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "flex flex-col gap-9", children: navigation.map((section, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
31589
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx13__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "flex flex-col gap-9", children: navigation.map((section, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
29075
31590
  section.links ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-display font-medium text-grey-800 dark:text-white", children: section.title }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "mt-2 flex flex-col gap-2 border-l lg:mt-4", children: /* @__PURE__ */ jsxRuntime.jsx("li", { className: "-ml-px flex flex-col items-start gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
29076
31591
  NavigationLink,
29077
31592
  {
@@ -29094,7 +31609,7 @@ function NavigationLink({
29094
31609
  {
29095
31610
  href,
29096
31611
  onClick,
29097
- className: clsx12__default.default(
31612
+ className: clsx13__default.default(
29098
31613
  "inline-block w-full cursor-pointer rounded-r-sm border-l py-1 pr-2 pl-4 text-left text-base/8 sm:text-sm/6",
29099
31614
  "hover:border-grey-950 hover:bg-primary-800/10 hover:font-semibold hover:text-grey-950",
29100
31615
  "dark:text-grey-400 dark:hover:border-grey-400 dark:hover:text-white",
@@ -29567,7 +32082,7 @@ function Wrapper({
29567
32082
  return /* @__PURE__ */ jsxRuntime.jsx(
29568
32083
  "div",
29569
32084
  {
29570
- className: clsx12__default.default("max-w-8xl mx-auto space-y-8 px-4 py-6 sm:px-6 lg:px-12", className),
32085
+ className: clsx13__default.default("max-w-8xl mx-auto space-y-8 px-4 py-6 sm:px-6 lg:px-12", className),
29571
32086
  ...props,
29572
32087
  children
29573
32088
  }
@@ -29581,7 +32096,7 @@ function PageHeading({
29581
32096
  return /* @__PURE__ */ jsxRuntime.jsx(
29582
32097
  "header",
29583
32098
  {
29584
- className: clsx12__default.default(
32099
+ className: clsx13__default.default(
29585
32100
  "border-b border-grey-300 bg-white dark:border-grey-700 dark:bg-grey-900",
29586
32101
  className
29587
32102
  ),
@@ -29608,7 +32123,7 @@ function Pagination({
29608
32123
  children,
29609
32124
  ...props
29610
32125
  }) {
29611
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": ariaLabel, className: clsx12__default.default(containerStyles[variant], className), ...props, children: /* @__PURE__ */ jsxRuntime.jsx(PaginationVariantContext.Provider, { value: variant, children }) });
32126
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": ariaLabel, className: clsx13__default.default(containerStyles[variant], className), ...props, children: /* @__PURE__ */ jsxRuntime.jsx(PaginationVariantContext.Provider, { value: variant, children }) });
29612
32127
  }
29613
32128
  function PaginationPrevious({ href = null, className, children = "Previous" }) {
29614
32129
  const variant = React5__namespace.useContext(PaginationVariantContext);
@@ -29631,7 +32146,7 @@ function PaginationPrevious({ href = null, className, children = "Previous" }) {
29631
32146
  }
29632
32147
  ) });
29633
32148
  }
29634
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx12__default.default(className, "grow basis-0"), children: /* @__PURE__ */ jsxRuntime.jsxs(
32149
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx13__default.default(className, "grow basis-0"), children: /* @__PURE__ */ jsxRuntime.jsxs(
29635
32150
  Button2,
29636
32151
  {
29637
32152
  ...href === null ? { disabled: true } : { href },
@@ -29665,7 +32180,7 @@ function PaginationNext({ href = null, className, children = "Next" }) {
29665
32180
  }
29666
32181
  ) });
29667
32182
  }
29668
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx12__default.default(className, "flex grow basis-0 justify-end"), children: /* @__PURE__ */ jsxRuntime.jsxs(
32183
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx13__default.default(className, "flex grow basis-0 justify-end"), children: /* @__PURE__ */ jsxRuntime.jsxs(
29669
32184
  Button2,
29670
32185
  {
29671
32186
  ...href === null ? { disabled: true } : { href },
@@ -29681,9 +32196,9 @@ function PaginationNext({ href = null, className, children = "Next" }) {
29681
32196
  function PaginationList({ className, ...props }) {
29682
32197
  const variant = React5__namespace.useContext(PaginationVariantContext);
29683
32198
  if (variant === "line") {
29684
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx12__default.default(listStyles.line, className), ...props });
32199
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx13__default.default(listStyles.line, className), ...props });
29685
32200
  }
29686
- return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx12__default.default(listStyles.default, className), ...props });
32201
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: clsx13__default.default(listStyles.default, className), ...props });
29687
32202
  }
29688
32203
  function PaginationPage({
29689
32204
  href,
@@ -29715,7 +32230,7 @@ function PaginationPage({
29715
32230
  "aria-current": current ? "page" : void 0,
29716
32231
  variant: current ? "solid" : "ghost",
29717
32232
  color: current ? "accent" : "light",
29718
- className: clsx12__default.default(
32233
+ className: clsx13__default.default(
29719
32234
  className,
29720
32235
  "leading-none before:absolute before:-inset-px before:rounded-sm",
29721
32236
  "min-h-8 min-w-8 sm:px-[calc(--spacing(4))] sm:py-[calc(--spacing(3))]",
@@ -29736,7 +32251,7 @@ function PaginationGap({
29736
32251
  "span",
29737
32252
  {
29738
32253
  "aria-hidden": "true",
29739
- className: clsx12__default.default(
32254
+ className: clsx13__default.default(
29740
32255
  "inline-flex items-center border-t-2 border-transparent px-4 pt-4 text-sm font-medium text-grey-800 select-none",
29741
32256
  className
29742
32257
  ),
@@ -29750,7 +32265,7 @@ function PaginationGap({
29750
32265
  {
29751
32266
  "aria-hidden": "true",
29752
32267
  ...props,
29753
- className: clsx12__default.default(
32268
+ className: clsx13__default.default(
29754
32269
  className,
29755
32270
  "w-9 text-center text-sm/6 font-semibold text-grey-950 select-none dark:text-white"
29756
32271
  ),
@@ -29770,7 +32285,7 @@ function PrevNextLinksPageLink({
29770
32285
  Link13__default.default,
29771
32286
  {
29772
32287
  href,
29773
- className: clsx12__default.default(
32288
+ className: clsx13__default.default(
29774
32289
  "flex items-center gap-x-1 text-base font-semibold text-slate-500 hover:text-slate-600 dark:text-slate-400 dark:hover:text-slate-300",
29775
32290
  dir === "previous" && "flex-row-reverse"
29776
32291
  ),
@@ -29779,7 +32294,7 @@ function PrevNextLinksPageLink({
29779
32294
  /* @__PURE__ */ jsxRuntime.jsx(
29780
32295
  Icons.east,
29781
32296
  {
29782
- className: clsx12__default.default("size-5 flex-none fill-current", dir === "previous" && "-scale-x-100")
32297
+ className: clsx13__default.default("size-5 flex-none fill-current", dir === "previous" && "-scale-x-100")
29783
32298
  }
29784
32299
  )
29785
32300
  ]
@@ -30053,7 +32568,7 @@ function Prose({
30053
32568
  return /* @__PURE__ */ jsxRuntime.jsx(
30054
32569
  Component2,
30055
32570
  {
30056
- className: clsx12__default.default(
32571
+ className: clsx13__default.default(
30057
32572
  className,
30058
32573
  "prose max-w-none dark:!prose-invert",
30059
32574
  // headings
@@ -30107,110 +32622,6 @@ function ResizableHandle({
30107
32622
  }
30108
32623
  );
30109
32624
  }
30110
- function Sheet({ ...props }) {
30111
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { "data-slot": "sheet", ...props });
30112
- }
30113
- function SheetTrigger({ ...props }) {
30114
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Trigger, { "data-slot": "sheet-trigger", ...props });
30115
- }
30116
- function SheetClose({ ...props }) {
30117
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "sheet-close", ...props });
30118
- }
30119
- function SheetPortal({ ...props }) {
30120
- return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { "data-slot": "sheet-portal", ...props });
30121
- }
30122
- function SheetOverlay({
30123
- className,
30124
- ...props
30125
- }) {
30126
- return /* @__PURE__ */ jsxRuntime.jsx(
30127
- DialogPrimitive__namespace.Overlay,
30128
- {
30129
- "data-slot": "sheet-overlay",
30130
- className: cn(
30131
- "fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
30132
- className
30133
- ),
30134
- ...props
30135
- }
30136
- );
30137
- }
30138
- function SheetContent({
30139
- className,
30140
- children,
30141
- side = "right",
30142
- showClose = true,
30143
- ...props
30144
- }) {
30145
- return /* @__PURE__ */ jsxRuntime.jsxs(SheetPortal, { children: [
30146
- /* @__PURE__ */ jsxRuntime.jsx(SheetOverlay, {}),
30147
- /* @__PURE__ */ jsxRuntime.jsxs(
30148
- DialogPrimitive__namespace.Content,
30149
- {
30150
- "data-slot": "sheet-content",
30151
- className: cn(
30152
- "fixed z-50 flex flex-col gap-4 bg-background shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=closed]:animate-out data-[state=open]:duration-500 data-[state=open]:animate-in",
30153
- side === "right" && "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
30154
- side === "left" && "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
30155
- side === "top" && "inset-x-0 top-0 h-auto border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
30156
- side === "bottom" && "inset-x-0 bottom-0 h-auto border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
30157
- className
30158
- ),
30159
- ...props,
30160
- children: [
30161
- children,
30162
- showClose && /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "sheet-close", className: "absolute top-4 right-4", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", size: "icon", children: [
30163
- /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { className: "size-6", "aria-hidden": "true" }),
30164
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
30165
- ] }) })
30166
- ]
30167
- }
30168
- )
30169
- ] });
30170
- }
30171
- function SheetHeader({ className, ...props }) {
30172
- return /* @__PURE__ */ jsxRuntime.jsx(
30173
- "div",
30174
- {
30175
- "data-slot": "sheet-header",
30176
- className: cn("flex flex-col gap-1.5 p-4", className),
30177
- ...props
30178
- }
30179
- );
30180
- }
30181
- function SheetFooter({ className, ...props }) {
30182
- return /* @__PURE__ */ jsxRuntime.jsx(
30183
- "div",
30184
- {
30185
- "data-slot": "sheet-footer",
30186
- className: cn("mt-auto flex flex-col gap-2 p-4", className),
30187
- ...props
30188
- }
30189
- );
30190
- }
30191
- function SheetTitle({ className, ...props }) {
30192
- return /* @__PURE__ */ jsxRuntime.jsx(
30193
- DialogPrimitive__namespace.Title,
30194
- {
30195
- "data-slot": "sheet-title",
30196
- className: cn("font-semibold text-foreground", className),
30197
- ...props
30198
- }
30199
- );
30200
- }
30201
- function SheetDescription({
30202
- className,
30203
- ...props
30204
- }) {
30205
- return /* @__PURE__ */ jsxRuntime.jsx(
30206
- DialogPrimitive__namespace.Description,
30207
- {
30208
- "data-slot": "sheet-description",
30209
- className: cn("text-sm text-muted-foreground", className),
30210
- ...props
30211
- }
30212
- );
30213
- }
30214
32625
  function Skeleton({ className, ...props }) {
30215
32626
  return /* @__PURE__ */ jsxRuntime.jsx(
30216
32627
  "div",
@@ -30825,7 +33236,7 @@ function SidebarNavigation({
30825
33236
  navigation: navigation$1
30826
33237
  }) {
30827
33238
  const pathname = navigation.usePathname();
30828
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx12__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "flex flex-col gap-9", children: navigation$1.map((section, sectionIndex) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
33239
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx13__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "flex flex-col gap-9", children: navigation$1.map((section, sectionIndex) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
30829
33240
  section.links ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-display font-medium text-foreground dark:text-white", children: section.title }) : /* @__PURE__ */ jsxRuntime.jsx(
30830
33241
  "ul",
30831
33242
  {
@@ -30860,7 +33271,7 @@ function SidebarLink({ link, pathname, onLinkClick, depth }) {
30860
33271
  const hasChildren = Array.isArray(link.links) && link.links.length > 0;
30861
33272
  const isActive = pathname === link.href;
30862
33273
  const isActiveOrHasActiveDescendant = isLinkOrDescendantActive(link, pathname);
30863
- const baseLinkClasses = clsx12__default.default(
33274
+ const baseLinkClasses = clsx13__default.default(
30864
33275
  "w-full cursor-pointer rounded-r-sm border-l py-1 pr-2 pl-4 text-left text-base/8 sm:text-sm/6",
30865
33276
  "hover:border-grey-950 hover:bg-primary-800/10 hover:font-semibold hover:text-grey-950",
30866
33277
  "dark:text-grey-400 dark:hover:border-grey-400 dark:hover:text-white",
@@ -30870,13 +33281,13 @@ function SidebarLink({ link, pathname, onLinkClick, depth }) {
30870
33281
  /* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
30871
33282
  "button",
30872
33283
  {
30873
- className: clsx12__default.default(baseLinkClasses, "group flex items-center justify-between gap-1"),
33284
+ className: clsx13__default.default(baseLinkClasses, "group flex items-center justify-between gap-1"),
30874
33285
  children: [
30875
33286
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: link.title }),
30876
33287
  /* @__PURE__ */ jsxRuntime.jsx(
30877
33288
  Icons.chevron_right,
30878
33289
  {
30879
- className: clsx12__default.default(
33290
+ className: clsx13__default.default(
30880
33291
  "ml-2 size-5 transition-transform duration-200",
30881
33292
  "group-data-[state=open]:rotate-90"
30882
33293
  )
@@ -30885,7 +33296,7 @@ function SidebarLink({ link, pathname, onLinkClick, depth }) {
30885
33296
  ]
30886
33297
  }
30887
33298
  ) }),
30888
- /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: clsx12__default.default("mt-2 ml-5 flex flex-col gap-1 border-l pl-0"), children: link.links && link.links.map((childLink) => /* @__PURE__ */ jsxRuntime.jsx(
33299
+ /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: clsx13__default.default("mt-2 ml-5 flex flex-col gap-1 border-l pl-0"), children: link.links && link.links.map((childLink) => /* @__PURE__ */ jsxRuntime.jsx(
30889
33300
  SidebarLink,
30890
33301
  {
30891
33302
  link: childLink,
@@ -31214,7 +33625,7 @@ var StepIndicator = React5__namespace.forwardRef(
31214
33625
  return /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", ref, className: cn("w-full", className), ...props, children: array.map((step, stepIdx) => /* @__PURE__ */ jsxRuntime.jsx(
31215
33626
  "li",
31216
33627
  {
31217
- className: clsx12__default.default(stepIdx !== array.length - 1 ? "pb-3" : "", "relative"),
33628
+ className: clsx13__default.default(stepIdx !== array.length - 1 ? "pb-3" : "", "relative"),
31218
33629
  children: step.href === pathname && !(step.status === "completed" || step.status === "error" || step.status === "saved" || step.status === "cannot-start") ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: step.status === "in-progress" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
31219
33630
  stepIdx !== array.length - 1 ? /* @__PURE__ */ jsxRuntime.jsx(
31220
33631
  "div",
@@ -31460,7 +33871,7 @@ function StepNavigation({
31460
33871
  })),
31461
33872
  [navigation, formStatus, getStatus]
31462
33873
  );
31463
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx12__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "space-y-9", children: navigationWithStatus.map((section) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
33874
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: clsx13__default.default("text-base lg:text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "list", className: "space-y-9", children: navigationWithStatus.map((section) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
31464
33875
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-display font-medium text-slate-900 dark:text-white", children: section.title }),
31465
33876
  /* @__PURE__ */ jsxRuntime.jsx(StepIndicator, { className: "mt-2 lg:mt-4", array: section.links })
31466
33877
  ] }, section.title)) }) });
@@ -31488,7 +33899,7 @@ function SwitchGroup({ className, ...props }) {
31488
33899
  {
31489
33900
  "data-slot": "control",
31490
33901
  ...props,
31491
- className: clsx12__default.default(
33902
+ className: clsx13__default.default(
31492
33903
  className,
31493
33904
  // Basic groups
31494
33905
  "space-y-3 **:data-[slot=label]:font-normal",
@@ -31507,7 +33918,7 @@ function SwitchField({
31507
33918
  {
31508
33919
  "data-slot": "field",
31509
33920
  ...props,
31510
- className: clsx12__default.default(
33921
+ className: clsx13__default.default(
31511
33922
  className,
31512
33923
  // Base layout
31513
33924
  "grid grid-cols-[1fr_auto] gap-x-8 gap-y-1 sm:grid-cols-[1fr_auto]",
@@ -31571,7 +33982,7 @@ function Switch2({
31571
33982
  {
31572
33983
  "data-slot": "control",
31573
33984
  ...props,
31574
- className: clsx12__default.default(
33985
+ className: clsx13__default.default(
31575
33986
  className,
31576
33987
  // Base styles
31577
33988
  "group relative isolate inline-flex h-6 w-10 cursor-default rounded-full p-[3px] sm:h-5 sm:w-8",
@@ -31598,7 +34009,7 @@ function Switch2({
31598
34009
  "span",
31599
34010
  {
31600
34011
  "aria-hidden": "true",
31601
- className: clsx12__default.default(
34012
+ className: clsx13__default.default(
31602
34013
  // Basic layout
31603
34014
  "pointer-events-none relative inline-block size-4.5 rounded-full sm:size-3.5",
31604
34015
  // Transition
@@ -31707,7 +34118,7 @@ function TableOfContents({ tableOfContents }) {
31707
34118
  "ol",
31708
34119
  {
31709
34120
  role: "list",
31710
- className: clsx12__default.default(
34121
+ className: clsx13__default.default(
31711
34122
  "mt-3 flex flex-col gap-2",
31712
34123
  "border-l border-grey-900/10 dark:border-white/10",
31713
34124
  "text-sm/6 text-grey-700 dark:text-grey-400"
@@ -31718,7 +34129,7 @@ function TableOfContents({ tableOfContents }) {
31718
34129
  {
31719
34130
  href: `#${section.id}`,
31720
34131
  prefetch: false,
31721
- className: clsx12__default.default(
34132
+ className: clsx13__default.default(
31722
34133
  "-ml-px inline-block border-l pl-4",
31723
34134
  "hover:border-primary-800 dark:hover:border-white",
31724
34135
  isActive(section) ? "border-primary-800 font-semibold text-primary-800 dark:border-white dark:text-white" : "border-transparent"
@@ -31731,7 +34142,7 @@ function TableOfContents({ tableOfContents }) {
31731
34142
  {
31732
34143
  href: `#${subSection.id}`,
31733
34144
  prefetch: false,
31734
- className: clsx12__default.default(
34145
+ className: clsx13__default.default(
31735
34146
  "-ml-px inline-block border-l pl-8",
31736
34147
  "hover:border-primary-800 dark:hover:border-white",
31737
34148
  isActive(subSection) ? "border-primary-800 font-semibold text-primary-800 dark:border-white dark:text-white" : "border-transparent"
@@ -34938,13 +37349,24 @@ function getHeadings(slugify$1 = slugify.slugifyWithCounter()) {
34938
37349
  });
34939
37350
  return result;
34940
37351
  }
34941
- function usePageHeadings() {
37352
+ function areHeadingTreesEqual(left, right) {
37353
+ return JSON.stringify(left) === JSON.stringify(right);
37354
+ }
37355
+ function usePageHeadings(enabled = true) {
34942
37356
  const [headings, setHeadings] = React5.useState([]);
34943
37357
  const pathname = navigation.usePathname();
34944
37358
  const observerRef = React5.useRef(null);
34945
37359
  const observedElRef = React5.useRef(null);
34946
37360
  React5.useEffect(() => {
34947
- const update = () => setHeadings(getHeadings());
37361
+ if (!enabled) {
37362
+ return;
37363
+ }
37364
+ const update = () => {
37365
+ const nextHeadings = getHeadings();
37366
+ setHeadings(
37367
+ (currentHeadings) => areHeadingTreesEqual(currentHeadings, nextHeadings) ? currentHeadings : nextHeadings
37368
+ );
37369
+ };
34948
37370
  const attachToCurrentArticle = () => {
34949
37371
  const article = document.querySelector("article");
34950
37372
  if (!article || observedElRef.current === article) return;
@@ -34991,16 +37413,8 @@ function usePageHeadings() {
34991
37413
  observerRef.current = null;
34992
37414
  observedElRef.current = null;
34993
37415
  };
34994
- }, [pathname]);
34995
- return headings;
34996
- }
34997
- function useStickyOffset(extraPadding = 0) {
34998
- const headerHeight = useSelectorHeight("#nsw-header");
34999
- const navigationHeight = useSelectorHeight("#nsw-main-navigation");
35000
- return React5.useMemo(() => {
35001
- const total = headerHeight + navigationHeight + extraPadding;
35002
- return total > 0 ? total : 0;
35003
- }, [extraPadding, headerHeight, navigationHeight]);
37416
+ }, [enabled, pathname]);
37417
+ return enabled ? headings : [];
35004
37418
  }
35005
37419
  function createFormStore(opts) {
35006
37420
  const { storageKey, initialFormData, initialFormStatus } = opts;
@@ -35141,6 +37555,8 @@ exports.CollapsibleContent = CollapsibleContent2;
35141
37555
  exports.CollapsibleTrigger = CollapsibleTrigger2;
35142
37556
  exports.ColorCard = ColorCard;
35143
37557
  exports.ColorPairingTool = ColorPairingTool;
37558
+ exports.ColorPairingToolV2 = ColorPairingToolV2;
37559
+ exports.ColorPairingToolV3 = ColorPairingToolV3;
35144
37560
  exports.ColorSwatches = ColorSwatches;
35145
37561
  exports.ColourScale = ColourScale;
35146
37562
  exports.ComboChart = ComboChart;
@@ -35188,7 +37604,7 @@ exports.DataTableFacetedFilter = DataTableFacetedFilter;
35188
37604
  exports.DataTablePagination = DataTablePagination;
35189
37605
  exports.DataTableToolbar = DataTableToolbar;
35190
37606
  exports.DataTableViewOptions = DataTableViewOptions;
35191
- exports.Description = Description4;
37607
+ exports.Description = Description5;
35192
37608
  exports.DescriptionDetails = DescriptionDetails;
35193
37609
  exports.DescriptionList = DescriptionList;
35194
37610
  exports.DescriptionTerm = DescriptionTerm;