@nswds/app 1.105.0 → 1.107.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
@@ -19003,6 +19003,7 @@ var DEFAULT_INITIAL_PAIR_ID4 = "nsw-blue-800:nsw-blue-200";
19003
19003
  var COLOR_PAIRING_TOOL_V4_PATH = "/core/colour/colour-pairing-tool-4";
19004
19004
  var MOBILE_RESULT_SCROLL_QUERY2 = "(max-width: 1023px)";
19005
19005
  var PERSISTENT_DRAWER_MIN_WIDTH_QUERY2 = "(min-width: 1280px)";
19006
+ var INITIAL_VISIBLE_ALTERNATIVES = 6;
19006
19007
  var COLOR_PAIRING_TOOL_DRAWER_STEPS2 = [
19007
19008
  {
19008
19009
  id: "colours",
@@ -19066,10 +19067,10 @@ function getWhiteForegroundGuidance4(pair) {
19066
19067
  }
19067
19068
  function getPreviewGuidance4(pair, isRecommended) {
19068
19069
  if (!isWhiteForegroundPair4(pair)) {
19069
- return "Use only AAA-recommended combinations across your selected primary, accent, and grey families.";
19070
+ return isRecommended ? "Use this pairing for headings, body copy, and actions on the selected background." : "Use this approved alternative when you need a different tone or stronger emphasis.";
19070
19071
  }
19071
19072
  if (isRecommended) {
19072
- return "Use white text on dark colour only when it meets AAA for headings, body copy, and calls to action.";
19073
+ return "Use white text on this background for headings, body copy, and actions only while it maintains AAA contrast.";
19073
19074
  }
19074
19075
  return getWhiteForegroundGuidance4(pair);
19075
19076
  }
@@ -19213,37 +19214,19 @@ function getRecommendationCategory2(pair, bestPair, context) {
19213
19214
  if (pair.foreground.familyKey === context.primary.key) return "primary-family";
19214
19215
  return "approved";
19215
19216
  }
19216
- function getRecommendationCategoryLabel2(category) {
19217
- switch (category) {
19218
- case "best":
19219
- return "Best recommended";
19220
- case "same-family":
19221
- return "Same family";
19222
- case "accent-family":
19223
- return "Accent family";
19224
- case "grey-option":
19225
- return "Grey option";
19226
- case "primary-family":
19227
- return "Primary family";
19228
- case "white":
19229
- return "White";
19230
- default:
19231
- return "Approved option";
19232
- }
19233
- }
19234
19217
  function getRecommendationSortRank2(category) {
19235
19218
  switch (category) {
19236
19219
  case "best":
19237
19220
  return 0;
19238
19221
  case "same-family":
19239
19222
  return 1;
19240
- case "accent-family":
19223
+ case "primary-family":
19241
19224
  return 2;
19242
- case "grey-option":
19225
+ case "accent-family":
19243
19226
  return 3;
19244
- case "white":
19227
+ case "grey-option":
19245
19228
  return 4;
19246
- case "primary-family":
19229
+ case "white":
19247
19230
  return 5;
19248
19231
  default:
19249
19232
  return 6;
@@ -19253,13 +19236,14 @@ function getRecommendationGroupId(category) {
19253
19236
  switch (category) {
19254
19237
  case "best":
19255
19238
  case "same-family":
19256
- case "accent-family":
19257
- case "grey-option":
19258
19239
  case "primary-family":
19259
- return "good-alternatives";
19240
+ return "closest";
19241
+ case "accent-family":
19260
19242
  case "white":
19261
19243
  case "approved":
19262
- return "edge-options";
19244
+ return "expressive";
19245
+ case "grey-option":
19246
+ return "neutral";
19263
19247
  default:
19264
19248
  return null;
19265
19249
  }
@@ -19275,22 +19259,29 @@ function buildRecommendationGroups(items) {
19275
19259
  return accumulator;
19276
19260
  },
19277
19261
  {
19278
- "edge-options": [],
19279
- "good-alternatives": []
19262
+ closest: [],
19263
+ expressive: [],
19264
+ neutral: []
19280
19265
  }
19281
19266
  );
19282
19267
  const groups = [
19283
19268
  {
19284
- id: "good-alternatives",
19285
- title: "Good alternatives",
19286
- description: "These pairings still meet AAA and stay close to the NSW recommendation in tone, neutrality, or emphasis.",
19287
- items: groupedItems["good-alternatives"]
19269
+ id: "closest",
19270
+ title: "Closest to default",
19271
+ description: "Stays closest to the NSW default in tone and overall treatment.",
19272
+ items: groupedItems.closest
19273
+ },
19274
+ {
19275
+ id: "expressive",
19276
+ title: "More expressive (accent)",
19277
+ description: "Brings more accent or emphasis into the foreground treatment.",
19278
+ items: groupedItems.expressive
19288
19279
  },
19289
19280
  {
19290
- id: "edge-options",
19291
- title: "Edge and less common options",
19292
- description: "These are valid AAA pairings, but they are less typical NSW defaults and should be used more deliberately.",
19293
- items: groupedItems["edge-options"]
19281
+ id: "neutral",
19282
+ title: "Neutral/system",
19283
+ description: "Uses quieter neutral contrast for system or utility treatments.",
19284
+ items: groupedItems.neutral
19294
19285
  }
19295
19286
  ];
19296
19287
  return groups.filter((group) => group.items.length > 0);
@@ -19336,6 +19327,18 @@ function getPairingCopyText2(pair) {
19336
19327
  accessibilityLine
19337
19328
  ].join("\n");
19338
19329
  }
19330
+ function getAccessibilitySummaryLine(pair) {
19331
+ if (!pair) {
19332
+ return "Contrast unavailable";
19333
+ }
19334
+ if (pair.passes.aaaText) {
19335
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (normal + large text)`;
19336
+ }
19337
+ if (pair.passes.aaaLarge) {
19338
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (large text only)`;
19339
+ }
19340
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 Not AAA compliant`;
19341
+ }
19339
19342
  function getLiveAnnouncement2(pair, background) {
19340
19343
  if (!background) {
19341
19344
  return "No approved background tones available.";
@@ -19450,65 +19453,6 @@ function BackgroundSwatchButton2({
19450
19453
  }
19451
19454
  );
19452
19455
  }
19453
- function CompactAccessibilityStatus({ label, passes }) {
19454
- const status = passes === null ? "unavailable" : passes ? "pass" : "fail";
19455
- return /* @__PURE__ */ jsxRuntime.jsxs(
19456
- "div",
19457
- {
19458
- className: cn(
19459
- "flex items-center justify-between gap-3 rounded-sm border px-4 py-3",
19460
- status === "pass" && "border-success-200 bg-success-50",
19461
- status === "fail" && "border-danger-200 bg-danger-50",
19462
- status === "unavailable" && "border-grey-200 bg-white"
19463
- ),
19464
- children: [
19465
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
19466
- /* @__PURE__ */ jsxRuntime.jsxs(
19467
- "span",
19468
- {
19469
- className: cn(
19470
- "inline-flex items-center gap-1 rounded-sm px-2.5 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
19471
- status === "pass" && "bg-success-700 text-white",
19472
- status === "fail" && "bg-danger-700 text-white",
19473
- status === "unavailable" && "bg-grey-100 text-foreground"
19474
- ),
19475
- children: [
19476
- 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" }),
19477
- status === "pass" ? "Pass" : status === "fail" ? "Fail" : "Unavailable"
19478
- ]
19479
- }
19480
- )
19481
- ]
19482
- }
19483
- );
19484
- }
19485
- function AccessibilitySummaryCard({ pair }) {
19486
- return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "gap-4 px-5 py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between", children: [
19487
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
19488
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Accessibility summary" }),
19489
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
19490
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-grey-700", children: "Contrast ratio" }),
19491
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl leading-none font-bold text-foreground", children: pair ? `${pair.contrastRatio.toFixed(2)}:1` : "N/A" })
19492
- ] })
19493
- ] }),
19494
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-3 lg:max-w-[26rem] lg:min-w-[22rem]", children: [
19495
- /* @__PURE__ */ jsxRuntime.jsx(
19496
- CompactAccessibilityStatus,
19497
- {
19498
- label: "AAA normal text",
19499
- passes: pair ? pair.passes.aaaText : null
19500
- }
19501
- ),
19502
- /* @__PURE__ */ jsxRuntime.jsx(
19503
- CompactAccessibilityStatus,
19504
- {
19505
- label: "AAA large text",
19506
- passes: pair ? pair.passes.aaaLarge : null
19507
- }
19508
- )
19509
- ] })
19510
- ] }) });
19511
- }
19512
19456
  function CurrentResultCard2({
19513
19457
  bestPair,
19514
19458
  copiedKey,
@@ -19519,8 +19463,8 @@ function CurrentResultCard2({
19519
19463
  }) {
19520
19464
  const previewForeground = pair?.foreground.hex ?? getReadableTextColor3(selectedBackground.tone);
19521
19465
  const isRecommended = pair ? pair.id === bestPair?.id : false;
19522
- const whiteForeground = pair ? isWhiteForegroundPair4(pair) : false;
19523
19466
  const pairingLabel = getMainPairingLabel(pair, bestPair);
19467
+ const accessibilitySummary = getAccessibilitySummaryLine(pair);
19524
19468
  const fauxButtonStyle = pair ? {
19525
19469
  "--btn-bg": pair.foreground.hex,
19526
19470
  "--btn-border": pair.foreground.hex,
@@ -19528,74 +19472,79 @@ function CurrentResultCard2({
19528
19472
  "--btn-icon": pair.background.hex,
19529
19473
  "--btn-hover-overlay": pair.background.hex
19530
19474
  } : null;
19531
- return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: cn("gap-0 overflow-hidden py-0", isRecommended && "border-primary-200"), children: [
19532
- /* @__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: "flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between", children: [
19533
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-3", children: [
19534
- /* @__PURE__ */ jsxRuntime.jsxs(
19535
- "span",
19536
- {
19537
- className: cn(
19538
- "inline-flex items-center gap-2 rounded-sm px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
19539
- isRecommended ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
19540
- ),
19541
- children: [
19542
- isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
19543
- pairingLabel
19544
- ]
19545
- }
19546
- ),
19547
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
19548
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName4(pair.foreground)} on ${getPairingColorDisplayName4(pair.background)}` : `${getPairingColorDisplayName4(selectedBackground)} selected` }),
19549
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: supportText })
19550
- ] })
19551
- ] }),
19552
- pair ? /* @__PURE__ */ jsxRuntime.jsx(
19553
- Button2,
19554
- {
19555
- color: "primary",
19556
- className: "w-full justify-center lg:w-auto lg:min-w-48",
19557
- onClick: onCopyPairing,
19558
- children: copiedKey === "current-pairing" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19559
- /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
19560
- "Pairing copied"
19561
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19562
- /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
19563
- "Copy pairing"
19564
- ] })
19565
- }
19566
- ) : null
19567
- ] }) }),
19568
- /* @__PURE__ */ jsxRuntime.jsx(
19569
- "div",
19570
- {
19571
- className: "p-4 sm:min-h-[26rem] sm:p-8",
19572
- style: {
19573
- backgroundColor: selectedBackground.hex,
19574
- color: previewForeground
19575
- },
19576
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[18rem] flex-col justify-center gap-6 sm:min-h-[22rem]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4", children: [
19577
- /* @__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" }),
19578
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
19579
- /* @__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." }),
19580
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-full text-base/6 sm:max-w-md sm:text-base/7", children: pair ? getPreviewGuidance4(pair, isRecommended) : "This approved background tone does not currently have a recommended AAA foreground in this tool. Choose another approved background tone to continue." }),
19581
- pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
19475
+ return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("gap-0 overflow-hidden py-0", isRecommended && "border-primary-200"), children: /* @__PURE__ */ jsxRuntime.jsx(
19476
+ "div",
19477
+ {
19478
+ className: "p-4 sm:min-h-[24rem] sm:p-8",
19479
+ style: {
19480
+ backgroundColor: selectedBackground.hex,
19481
+ color: previewForeground
19482
+ },
19483
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[18rem] flex-col justify-between gap-8 sm:min-h-[20rem]", children: [
19484
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-3xl rounded-sm bg-white px-4 py-4 text-foreground sm:px-6 sm:py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between", children: [
19485
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-4", children: [
19486
+ /* @__PURE__ */ jsxRuntime.jsxs(
19582
19487
  "span",
19583
19488
  {
19584
- "aria-hidden": "true",
19585
- "data-variant": "solid",
19586
19489
  className: cn(
19587
- buttonVariants({ variant: "solid", size: "default" }),
19588
- "pointer-events-none cursor-default px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
19490
+ "inline-flex items-center gap-2 rounded-sm px-3 py-1 text-[0.72rem] font-semibold tracking-[0.12em] uppercase",
19491
+ isRecommended ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
19589
19492
  ),
19590
- style: fauxButtonStyle,
19591
- children: "Get started"
19493
+ children: [
19494
+ isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
19495
+ pairingLabel
19496
+ ]
19592
19497
  }
19593
- ) : null
19594
- ] })
19595
- ] }) })
19596
- }
19597
- )
19598
- ] });
19498
+ ),
19499
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
19500
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName4(pair.foreground)} on ${getPairingColorDisplayName4(pair.background)}` : `${getPairingColorDisplayName4(selectedBackground)} selected` }),
19501
+ pair ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: [
19502
+ pair.foreground.token,
19503
+ " on ",
19504
+ pair.background.token
19505
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: selectedBackground.token }),
19506
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: accessibilitySummary }),
19507
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: supportText })
19508
+ ] })
19509
+ ] }),
19510
+ pair ? /* @__PURE__ */ jsxRuntime.jsx(
19511
+ Button2,
19512
+ {
19513
+ color: "primary",
19514
+ className: "w-full justify-center lg:w-auto lg:min-w-48",
19515
+ onClick: onCopyPairing,
19516
+ children: copiedKey === "current-pairing" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19517
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
19518
+ "Pairing copied"
19519
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19520
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
19521
+ "Copy pairing"
19522
+ ] })
19523
+ }
19524
+ ) : null
19525
+ ] }) }),
19526
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4", children: [
19527
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
19528
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-3xl leading-tight font-bold text-current sm:text-4xl", children: "Example heading" }),
19529
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-base/7", children: pair ? getPreviewGuidance4(pair, isRecommended) : "This approved background does not currently have an AAA foreground in this tool. Choose another approved background to continue." })
19530
+ ] }),
19531
+ pair && fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
19532
+ "span",
19533
+ {
19534
+ "aria-hidden": "true",
19535
+ "data-variant": "solid",
19536
+ className: cn(
19537
+ buttonVariants({ variant: "solid", size: "default" }),
19538
+ "pointer-events-none cursor-default self-start px-6 text-[16px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
19539
+ ),
19540
+ style: fauxButtonStyle,
19541
+ children: "Primary action"
19542
+ }
19543
+ ) : null
19544
+ ] })
19545
+ ] })
19546
+ }
19547
+ ) });
19599
19548
  }
19600
19549
  function RecommendationCard2({
19601
19550
  copiedKey,
@@ -19609,8 +19558,8 @@ function RecommendationCard2({
19609
19558
  "div",
19610
19559
  {
19611
19560
  className: cn(
19612
- "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",
19613
- isSelected ? "border-primary-800 bg-primary-50/60 ring-1 ring-primary-700" : "border-grey-200 hover:border-primary-500 hover:bg-grey-50"
19561
+ "relative rounded-sm border bg-white px-3 py-2.5 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
19562
+ isSelected ? "border-primary-800 bg-primary-50/40" : "border-grey-200 hover:border-grey-400"
19614
19563
  ),
19615
19564
  children: [
19616
19565
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -19623,65 +19572,45 @@ function RecommendationCard2({
19623
19572
  className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
19624
19573
  }
19625
19574
  ),
19626
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10", children: [
19627
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
19628
- /* @__PURE__ */ jsxRuntime.jsxs(
19629
- "span",
19630
- {
19631
- className: cn(
19632
- "inline-flex items-center gap-2 rounded-sm px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.12em] uppercase",
19633
- item.category === "best" ? "bg-primary-800 text-white" : "border border-grey-300 bg-grey-50 text-foreground"
19634
- ),
19635
- children: [
19636
- 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" }),
19637
- item.categoryLabel
19638
- ]
19639
- }
19640
- ),
19641
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsxs(
19642
- Button2,
19643
- {
19644
- variant: "ghost",
19645
- color: "grey",
19646
- size: "sm",
19647
- onClick: onCopyPairing,
19648
- "aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
19649
- children: [
19650
- /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
19651
- copiedKey === `pair:${pair.id}` ? "Copied" : "Copy"
19652
- ]
19653
- }
19654
- ) })
19575
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10 flex items-start gap-3", children: [
19576
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-0.5 w-12 shrink-0 overflow-hidden rounded-[2px] border border-black/10", children: [
19577
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-9 w-full", style: { backgroundColor: pair.background.hex } }),
19578
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2.5 w-full", style: { backgroundColor: pair.foreground.hex } })
19655
19579
  ] }),
19656
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
19657
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 sm:grid-cols-[7.5rem_minmax(0,1fr)]", children: [
19658
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-[2px] border border-black/10", children: [
19659
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-20 w-full", style: { backgroundColor: pair.background.hex } }),
19660
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-full", style: { backgroundColor: pair.foreground.hex } })
19580
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
19581
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19582
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-semibold text-foreground", children: [
19583
+ getPairingColorDisplayName4(pair.foreground),
19584
+ " on",
19585
+ " ",
19586
+ getPairingColorDisplayName4(pair.background)
19661
19587
  ] }),
19662
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-2", children: [
19663
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
19664
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base font-semibold text-foreground", children: getPairingColorDisplayName4(pair.foreground) }),
19665
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.74rem] break-all text-muted-foreground", children: pair.foreground.token })
19666
- ] }),
19667
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
19668
- pair.foreground.familyLabel,
19669
- " on ",
19670
- pair.background.familyLabel
19671
- ] })
19672
- ] })
19588
+ item.category === "best" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm bg-primary-800 px-2 py-1 text-[0.68rem] font-semibold tracking-[0.12em] text-white uppercase", children: "Default" }) : null,
19589
+ isSelected ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm border border-primary-800 px-2 py-1 text-[0.68rem] font-semibold tracking-[0.12em] text-primary-800 uppercase", children: "Current" }) : null
19673
19590
  ] }),
19674
- /* @__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: [
19675
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
19676
- /* @__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: [
19677
- pair.contrastRatio.toFixed(2),
19678
- ":1"
19679
- ] }),
19680
- /* @__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" })
19681
- ] }),
19682
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-primary-800", children: isSelected ? "Selected answer" : "Use pairing" })
19591
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.72rem] break-all text-muted-foreground", children: [
19592
+ pair.foreground.token,
19593
+ " on ",
19594
+ pair.background.token
19595
+ ] }),
19596
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
19597
+ pair.contrastRatio.toFixed(2),
19598
+ ":1 contrast"
19683
19599
  ] })
19684
- ] })
19600
+ ] }),
19601
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(
19602
+ Button2,
19603
+ {
19604
+ variant: "ghost",
19605
+ color: "grey",
19606
+ size: "icon",
19607
+ className: "size-8 text-muted-foreground hover:text-foreground",
19608
+ onClick: onCopyPairing,
19609
+ "aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
19610
+ title: copiedKey === `pair:${pair.id}` ? "Copied" : "Copy pairing",
19611
+ children: copiedKey === `pair:${pair.id}` ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-4" })
19612
+ }
19613
+ ) })
19685
19614
  ] })
19686
19615
  ]
19687
19616
  }
@@ -19692,20 +19621,14 @@ function RecommendationGroupSection({
19692
19621
  description,
19693
19622
  title
19694
19623
  }) {
19695
- return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
19696
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
19624
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
19625
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
19697
19626
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
19698
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: description })
19627
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: description })
19699
19628
  ] }),
19700
19629
  children
19701
19630
  ] });
19702
19631
  }
19703
- function DrawerSummaryItem({ label, value }) {
19704
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-t border-grey-200 pt-3 first:border-t-0 first:pt-0", children: [
19705
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: label }),
19706
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: value })
19707
- ] });
19708
- }
19709
19632
  function TechnicalDetailsPanel2({
19710
19633
  color: color2,
19711
19634
  copiedKey,
@@ -19815,11 +19738,12 @@ function ColorPairingToolV4Content({
19815
19738
  const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
19816
19739
  const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
19817
19740
  const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
19741
+ const [isShowingAllAlternatives, setIsShowingAllAlternatives] = React5.useState(false);
19742
+ const [isTechnicalDetailsOpen, setIsTechnicalDetailsOpen] = React5.useState(false);
19818
19743
  const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
19819
19744
  const [copiedKey, setCopiedKey] = React5.useState(null);
19820
19745
  const copiedKeyTimeoutRef = React5.useRef(null);
19821
19746
  const resultSectionRef = React5.useRef(null);
19822
- const technicalDetailsSectionRef = React5.useRef(null);
19823
19747
  const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
19824
19748
  const technicalDetailsViewedRef = React5.useRef(false);
19825
19749
  const emitAnalyticsEvent = React5.useCallback(
@@ -19902,7 +19826,6 @@ function ColorPairingToolV4Content({
19902
19826
  const category = getRecommendationCategory2(pair, bestRecommendedPair, context);
19903
19827
  return {
19904
19828
  category,
19905
- categoryLabel: getRecommendationCategoryLabel2(category),
19906
19829
  pair
19907
19830
  };
19908
19831
  }).sort(
@@ -19915,6 +19838,37 @@ function ColorPairingToolV4Content({
19915
19838
  ),
19916
19839
  [recommendationItems, selectedPair?.id]
19917
19840
  );
19841
+ const visibleAlternativeRecommendationGroups = React5.useMemo(() => {
19842
+ if (isShowingAllAlternatives) {
19843
+ return alternativeRecommendationGroups;
19844
+ }
19845
+ let remaining = INITIAL_VISIBLE_ALTERNATIVES;
19846
+ return alternativeRecommendationGroups.reduce((groups, group) => {
19847
+ if (remaining <= 0) {
19848
+ return groups;
19849
+ }
19850
+ const items = group.items.slice(0, remaining);
19851
+ if (items.length > 0) {
19852
+ groups.push({
19853
+ ...group,
19854
+ items
19855
+ });
19856
+ remaining -= items.length;
19857
+ }
19858
+ return groups;
19859
+ }, []);
19860
+ }, [alternativeRecommendationGroups, isShowingAllAlternatives]);
19861
+ const hiddenAlternativeCount = React5.useMemo(() => {
19862
+ const totalAlternatives = alternativeRecommendationGroups.reduce(
19863
+ (count, group) => count + group.items.length,
19864
+ 0
19865
+ );
19866
+ const visibleAlternatives = visibleAlternativeRecommendationGroups.reduce(
19867
+ (count, group) => count + group.items.length,
19868
+ 0
19869
+ );
19870
+ return Math.max(0, totalAlternatives - visibleAlternatives);
19871
+ }, [alternativeRecommendationGroups, visibleAlternativeRecommendationGroups]);
19918
19872
  const liveAnnouncement = React5.useMemo(
19919
19873
  () => getLiveAnnouncement2(previewPair, selectedBackground),
19920
19874
  [previewPair, selectedBackground]
@@ -20022,6 +19976,7 @@ function ColorPairingToolV4Content({
20022
19976
  selectedBackgroundToken,
20023
19977
  null
20024
19978
  );
19979
+ setIsShowingAllAlternatives(false);
20025
19980
  applyResolvedSelection(nextState);
20026
19981
  emitAnalyticsEvent({
20027
19982
  name: "palette_change",
@@ -20041,6 +19996,7 @@ function ColorPairingToolV4Content({
20041
19996
  selectedBackgroundToken,
20042
19997
  null
20043
19998
  );
19999
+ setIsShowingAllAlternatives(false);
20044
20000
  applyResolvedSelection(nextState);
20045
20001
  emitAnalyticsEvent({
20046
20002
  name: "primary_change",
@@ -20060,6 +20016,7 @@ function ColorPairingToolV4Content({
20060
20016
  selectedBackgroundToken,
20061
20017
  null
20062
20018
  );
20019
+ setIsShowingAllAlternatives(false);
20063
20020
  applyResolvedSelection(nextState);
20064
20021
  emitAnalyticsEvent({
20065
20022
  name: "accent_change",
@@ -20080,6 +20037,7 @@ function ColorPairingToolV4Content({
20080
20037
  selectedPairId: nextSelectedPairId,
20081
20038
  themeCategory
20082
20039
  };
20040
+ setIsShowingAllAlternatives(false);
20083
20041
  applyResolvedSelection(nextState);
20084
20042
  emitAnalyticsEvent({
20085
20043
  name: "background_selection",
@@ -20153,50 +20111,17 @@ function ColorPairingToolV4Content({
20153
20111
  themeCategory
20154
20112
  ]);
20155
20113
  React5.useEffect(() => {
20156
- if (technicalDetailsViewedRef.current) {
20114
+ if (!isTechnicalDetailsOpen || technicalDetailsViewedRef.current) {
20157
20115
  return;
20158
20116
  }
20159
- const section = technicalDetailsSectionRef.current;
20160
- if (!section) {
20161
- return;
20162
- }
20163
- const emitViewedEvent = () => {
20164
- if (technicalDetailsViewedRef.current) {
20165
- return;
20166
- }
20167
- technicalDetailsViewedRef.current = true;
20168
- emitAnalyticsEvent({
20169
- name: "technical_details_viewed",
20170
- ...buildAnalyticsContext({
20171
- source: "details"
20172
- })
20173
- });
20174
- };
20175
- if (typeof IntersectionObserver === "undefined") {
20176
- const rect = section.getBoundingClientRect();
20177
- const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
20178
- if (rect.top < viewportHeight && rect.bottom > 0) {
20179
- emitViewedEvent();
20180
- }
20181
- return;
20182
- }
20183
- const observer = new IntersectionObserver(
20184
- (entries) => {
20185
- const [entry] = entries;
20186
- if (entry?.isIntersecting) {
20187
- emitViewedEvent();
20188
- observer.disconnect();
20189
- }
20190
- },
20191
- {
20192
- threshold: 0.2
20193
- }
20194
- );
20195
- observer.observe(section);
20196
- return () => {
20197
- observer.disconnect();
20198
- };
20199
- }, [buildAnalyticsContext, emitAnalyticsEvent]);
20117
+ technicalDetailsViewedRef.current = true;
20118
+ emitAnalyticsEvent({
20119
+ name: "technical_details_viewed",
20120
+ ...buildAnalyticsContext({
20121
+ source: "details"
20122
+ })
20123
+ });
20124
+ }, [buildAnalyticsContext, emitAnalyticsEvent, isTechnicalDetailsOpen]);
20200
20125
  if (!selectedBackground) {
20201
20126
  return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
20202
20127
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
@@ -20342,36 +20267,10 @@ function ColorPairingToolV4Content({
20342
20267
  },
20343
20268
  group.key
20344
20269
  )) }) }),
20345
- /* @__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: [
20346
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-4 py-4", children: [
20347
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
20348
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Current configuration" }),
20349
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The drawer only sets the palette, families, and background. The result panel is where the pairing is shown and, if needed, overridden." })
20350
- ] }),
20351
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-5 space-y-3", children: [
20352
- /* @__PURE__ */ jsxRuntime.jsx(
20353
- DrawerSummaryItem,
20354
- {
20355
- label: "Palette",
20356
- value: themeCategory === "brand" ? "Brand palette" : "Aboriginal palette"
20357
- }
20358
- ),
20359
- /* @__PURE__ */ jsxRuntime.jsx(DrawerSummaryItem, { label: "Primary family", value: context.primary.label }),
20360
- /* @__PURE__ */ jsxRuntime.jsx(DrawerSummaryItem, { label: "Accent family", value: context.accent.label }),
20361
- /* @__PURE__ */ jsxRuntime.jsx(
20362
- DrawerSummaryItem,
20363
- {
20364
- label: "Background",
20365
- value: getPairingColorDisplayName4(selectedBackground)
20366
- }
20367
- )
20368
- ] })
20369
- ] }),
20370
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-sm border border-grey-200 bg-grey-50 px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
20371
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Review the result on the right" }),
20372
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The right panel always shows the current NSW default pairing for this selection. Alternative AAA options stay there as a secondary override path." })
20373
- ] }) })
20374
- ] }) })
20270
+ /* @__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: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-sm border border-grey-200 bg-grey-50 px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
20271
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Review the result on the right" }),
20272
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The right panel shows one recommended pairing first. Use approved alternatives there only when you need a different tone or emphasis." })
20273
+ ] }) }) }) })
20375
20274
  ]
20376
20275
  }
20377
20276
  ) }),
@@ -20409,7 +20308,7 @@ function ColorPairingToolV4Content({
20409
20308
  /* @__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: [
20410
20309
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
20411
20310
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
20412
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the drawer to change palette, colour families, or background. The result panel always shows the current NSW pairing for this selection." }),
20311
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the drawer to set palette, colour families, and background. The result panel shows the NSW recommendation first." }),
20413
20312
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
20414
20313
  ] }),
20415
20314
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -20464,53 +20363,99 @@ function ColorPairingToolV4Content({
20464
20363
  }
20465
20364
  )
20466
20365
  ] }),
20467
- /* @__PURE__ */ jsxRuntime.jsx("section", { children: /* @__PURE__ */ jsxRuntime.jsx(AccessibilitySummaryCard, { pair: previewPair }) }),
20468
- bestRecommendedPair || alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-6", children: [
20469
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
20470
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Alternative AAA options" }),
20471
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "These approved alternatives can be used when a different tone, stronger emphasis, or a more neutral system treatment is needed." })
20366
+ bestRecommendedPair || alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
20367
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
20368
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Approved alternatives" }),
20369
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: "These are approved alternatives for different tone or emphasis." })
20472
20370
  ] }),
20473
- alternativeRecommendationGroups.length > 0 ? alternativeRecommendationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
20474
- RecommendationGroupSection,
20475
- {
20476
- title: group.title,
20477
- description: group.description,
20478
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
20479
- RecommendationCard2,
20480
- {
20481
- copiedKey,
20482
- item,
20483
- isSelected: item.pair.id === selectedPair?.id,
20484
- onCopyPairing: () => copyValue(
20485
- `pair:${item.pair.id}`,
20486
- getPairingCopyText2(item.pair),
20487
- "Pairing copied",
20488
- item.pair.id === bestRecommendedPair?.id ? {
20489
- name: "best_recommendation_copied",
20490
- ...buildAnalyticsContext({
20491
- foregroundToken: item.pair.foreground.token,
20492
- pairId: item.pair.id,
20493
- source: "recommendations-list"
20494
- })
20495
- } : void 0
20496
- ),
20497
- onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
20498
- },
20499
- item.pair.id
20500
- )) })
20501
- },
20502
- group.id
20503
- )) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
20371
+ alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
20372
+ visibleAlternativeRecommendationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
20373
+ RecommendationGroupSection,
20374
+ {
20375
+ title: group.title,
20376
+ description: group.description,
20377
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
20378
+ RecommendationCard2,
20379
+ {
20380
+ copiedKey,
20381
+ item,
20382
+ isSelected: item.pair.id === selectedPair?.id,
20383
+ onCopyPairing: () => copyValue(
20384
+ `pair:${item.pair.id}`,
20385
+ getPairingCopyText2(item.pair),
20386
+ "Pairing copied",
20387
+ item.pair.id === bestRecommendedPair?.id ? {
20388
+ name: "best_recommendation_copied",
20389
+ ...buildAnalyticsContext({
20390
+ foregroundToken: item.pair.foreground.token,
20391
+ pairId: item.pair.id,
20392
+ source: "recommendations-list"
20393
+ })
20394
+ } : void 0
20395
+ ),
20396
+ onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
20397
+ },
20398
+ item.pair.id
20399
+ )) })
20400
+ },
20401
+ group.id
20402
+ )),
20403
+ hiddenAlternativeCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
20404
+ Button2,
20405
+ {
20406
+ variant: "ghost",
20407
+ color: "grey",
20408
+ className: "w-full justify-center border border-grey-200 bg-white sm:w-auto",
20409
+ onClick: () => setIsShowingAllAlternatives(true),
20410
+ children: [
20411
+ "Show ",
20412
+ hiddenAlternativeCount,
20413
+ " more"
20414
+ ]
20415
+ }
20416
+ ) : null
20417
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
20504
20418
  /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "No other AAA alternatives" }),
20505
20419
  /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "The NSW recommended pairing is the only AAA-compliant foreground option for this background." })
20506
20420
  ] })
20507
20421
  ] }) : null,
20508
- /* @__PURE__ */ jsxRuntime.jsx("section", { ref: technicalDetailsSectionRef, className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
20509
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 border-b border-grey-200 px-4 py-4 sm:px-5", children: [
20510
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
20511
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Token, tone, HEX, RGB, HSL, and OKLCH values for the current selection." })
20512
- ] }),
20513
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-4 sm:px-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
20422
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "space-y-3", children: /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { open: isTechnicalDetailsOpen, onOpenChange: setIsTechnicalDetailsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
20423
+ /* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
20424
+ "button",
20425
+ {
20426
+ type: "button",
20427
+ className: "flex w-full items-center justify-between gap-4 px-4 py-4 text-left transition-colors hover:bg-grey-50 focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden sm:px-5",
20428
+ children: [
20429
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
20430
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
20431
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: "Token, tone, HEX, RGB, HSL, and OKLCH values for advanced use." })
20432
+ ] }),
20433
+ /* @__PURE__ */ jsxRuntime.jsxs(
20434
+ "span",
20435
+ {
20436
+ className: cn(
20437
+ "inline-flex items-center gap-2 text-sm font-semibold text-primary-800",
20438
+ isTechnicalDetailsOpen && "text-foreground"
20439
+ ),
20440
+ children: [
20441
+ isTechnicalDetailsOpen ? "Hide" : "Show",
20442
+ /* @__PURE__ */ jsxRuntime.jsx(
20443
+ Icons.keyboard_arrow_down,
20444
+ {
20445
+ "data-slot": "icon",
20446
+ className: cn(
20447
+ "size-5 transition-transform",
20448
+ isTechnicalDetailsOpen && "rotate-180"
20449
+ )
20450
+ }
20451
+ )
20452
+ ]
20453
+ }
20454
+ )
20455
+ ]
20456
+ }
20457
+ ) }),
20458
+ /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-grey-200 px-4 py-4 sm:px-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
20514
20459
  /* @__PURE__ */ jsxRuntime.jsx(
20515
20460
  TechnicalDetailsPanel2,
20516
20461
  {
@@ -20531,20 +20476,20 @@ function ColorPairingToolV4Content({
20531
20476
  onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
20532
20477
  }
20533
20478
  )
20534
- ] }) })
20535
- ] }) }),
20536
- /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
20537
- /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "mb-4 text-foreground", trim: "normal", children: "Share colour pairing" }),
20538
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white p-4", children: [
20539
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row items-center justify-between", children: [
20540
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy this URL to share your current colour pairing:" }),
20479
+ ] }) }) })
20480
+ ] }) }) }),
20481
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
20482
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "Share colour pairing" }),
20483
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-4 py-4", children: [
20484
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
20485
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy a link to this current result." }),
20541
20486
  /* @__PURE__ */ jsxRuntime.jsx(
20542
20487
  Button2,
20543
20488
  {
20544
20489
  variant: "ghost",
20545
20490
  color: "grey",
20546
20491
  size: "sm",
20547
- className: "shrink-0 self-center",
20492
+ className: "shrink-0 self-start sm:self-center",
20548
20493
  onClick: () => copyValue(
20549
20494
  "share-url",
20550
20495
  typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
@@ -20582,6 +20527,1623 @@ function ColorPairingToolV4({
20582
20527
  }
20583
20528
  ) });
20584
20529
  }
20530
+ var PREFERRED_BACKGROUND_TONES5 = [400, 600, 200, 800, 100, 50];
20531
+ var DEFAULT_VISIBLE_FORMATS5 = ["hex", "rgb", "hsl", "oklch"];
20532
+ var DEFAULT_INITIAL_BACKGROUND_TOKEN5 = "nsw-blue-800";
20533
+ var DEFAULT_INITIAL_PAIR_ID5 = "nsw-blue-800:nsw-blue-200";
20534
+ var COLOR_PAIRING_TOOL_V5_PATH = "/core/colour/colour-pairing-tool-5";
20535
+ var MOBILE_RESULT_SCROLL_QUERY3 = "(max-width: 1023px)";
20536
+ var PERSISTENT_DRAWER_MIN_WIDTH_QUERY3 = "(min-width: 1280px)";
20537
+ var INITIAL_VISIBLE_ALTERNATIVES2 = 6;
20538
+ var COLOR_PAIRING_TOOL_DRAWER_STEPS3 = [
20539
+ {
20540
+ id: "colours",
20541
+ title: "Choose colours",
20542
+ eyebrow: "Step 1 of 3",
20543
+ description: "Select the palette, primary family, and accent family."
20544
+ },
20545
+ {
20546
+ id: "backgrounds",
20547
+ title: "Choose background",
20548
+ eyebrow: "Step 2 of 3",
20549
+ description: "Pick the background tone that you want to pair."
20550
+ },
20551
+ {
20552
+ id: "refine",
20553
+ title: "Refine or override recommendation",
20554
+ eyebrow: "Step 3 of 3",
20555
+ description: "Use the result panel to review the NSW default pairing and override it only when a different approved option is needed."
20556
+ }
20557
+ ];
20558
+ var COLOR_PAIRING_TOOL_V5_ANALYTICS_EVENT = "nsw-colour-pairing-tool-v5";
20559
+ function getToneFromToken5(token) {
20560
+ if (!token) return null;
20561
+ const match = token.match(/-(\d+)$/);
20562
+ return match ? Number.parseInt(match[1], 10) : null;
20563
+ }
20564
+ function getFamilySwatchColor5(family, preferredTone = 600) {
20565
+ const exactMatch = family.colors.find((color2) => color2.tone === preferredTone);
20566
+ if (exactMatch) {
20567
+ return exactMatch.hex;
20568
+ }
20569
+ const closestMatch = [...family.colors].sort(
20570
+ (left, right) => Math.abs(left.tone - preferredTone) - Math.abs(right.tone - preferredTone)
20571
+ )[0];
20572
+ return closestMatch?.hex ?? "transparent";
20573
+ }
20574
+ function getFamilySelectorLabel5(family, themeCategory, selectionRole) {
20575
+ if (themeCategory !== "aboriginal") {
20576
+ return family.label;
20577
+ }
20578
+ const preferredTone = selectionRole === "primary colour" ? 800 : 600;
20579
+ return family.colors.find((color2) => color2.tone === preferredTone)?.name ?? family.label;
20580
+ }
20581
+ function getPairingColorDisplayName5(color2) {
20582
+ return color2.name ?? `${color2.familyLabel} ${color2.tone}`;
20583
+ }
20584
+ function isWhiteForegroundPair5(pair) {
20585
+ return pair.foreground.token === "white";
20586
+ }
20587
+ function isLargeTextOnlyPair3(pair) {
20588
+ return pair.passes.aaaLarge && !pair.passes.aaaText;
20589
+ }
20590
+ function getWhiteForegroundGuidance5(pair) {
20591
+ if (pair.passes.aaaText) {
20592
+ return "White is approved for headings, body copy, and calls to action on this background.";
20593
+ }
20594
+ if (pair.passes.aaaLarge) {
20595
+ 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.";
20596
+ }
20597
+ return "Do not use white on this background. Choose one of the recommended foregrounds below instead.";
20598
+ }
20599
+ function getPreviewGuidance5(pair, isRecommended) {
20600
+ if (!isWhiteForegroundPair5(pair)) {
20601
+ return isRecommended ? "Use this pairing for headings, body copy, and actions on the selected background." : "Use this approved alternative when you need a different tone or stronger emphasis.";
20602
+ }
20603
+ if (isRecommended) {
20604
+ return "Use white text on this background for headings, body copy, and actions only while it maintains AAA contrast.";
20605
+ }
20606
+ return getWhiteForegroundGuidance5(pair);
20607
+ }
20608
+ function getPreferredPairForBackground5(pairs, preferredPairId) {
20609
+ if (preferredPairId) {
20610
+ const preferredPair = pairs.find((pair) => pair.id === preferredPairId);
20611
+ if (preferredPair) {
20612
+ return preferredPair;
20613
+ }
20614
+ }
20615
+ return pairs.find((pair) => !isWhiteForegroundPair5(pair)) ?? pairs[0] ?? null;
20616
+ }
20617
+ function getDefaultBackgroundToken5(context) {
20618
+ for (const tone of PREFERRED_BACKGROUND_TONES5) {
20619
+ for (const group of context.backgroundGroups) {
20620
+ const match = group.backgrounds.find(
20621
+ (background) => background.tone === tone && (context.pairsByBackground[background.token]?.length ?? 0) > 0
20622
+ );
20623
+ if (match) {
20624
+ return match.token;
20625
+ }
20626
+ }
20627
+ }
20628
+ for (const tone of PREFERRED_BACKGROUND_TONES5) {
20629
+ for (const group of context.backgroundGroups) {
20630
+ const match = group.backgrounds.find((background) => background.tone === tone);
20631
+ if (match) {
20632
+ return match.token;
20633
+ }
20634
+ }
20635
+ }
20636
+ return context.backgrounds[0]?.token ?? "";
20637
+ }
20638
+ function resolveBackgroundToken5(context, preferredToken, preferredTone) {
20639
+ if (preferredToken && context.backgrounds.some((background) => background.token === preferredToken)) {
20640
+ return preferredToken;
20641
+ }
20642
+ if (preferredTone !== null && preferredTone !== void 0) {
20643
+ for (const group of context.backgroundGroups) {
20644
+ const match = group.backgrounds.find((background) => background.tone === preferredTone);
20645
+ if (match) {
20646
+ return match.token;
20647
+ }
20648
+ }
20649
+ }
20650
+ return getDefaultBackgroundToken5(context);
20651
+ }
20652
+ function getInitialPairingState5(searchParams) {
20653
+ const paletteParam = searchParams.get("palette");
20654
+ const primaryParam = searchParams.get("primary");
20655
+ const accentParam = searchParams.get("accent");
20656
+ const pairParam = searchParams.get("pair");
20657
+ const backgroundParam = searchParams.get("background");
20658
+ const themeCategory = paletteParam === "brand" || paletteParam === "aboriginal" ? paletteParam : "brand";
20659
+ const context = getPairingContext(themeCategory, primaryParam, accentParam);
20660
+ const shouldUseDefaultBrandExample = !backgroundParam && !pairParam && themeCategory === "brand" && context.primary.key === "blue" && context.accent.key === "red";
20661
+ const defaultBackgroundToken = shouldUseDefaultBrandExample ? context.backgrounds.some(
20662
+ (background) => background.token === DEFAULT_INITIAL_BACKGROUND_TOKEN5
20663
+ ) ? DEFAULT_INITIAL_BACKGROUND_TOKEN5 : null : null;
20664
+ const defaultPairId = shouldUseDefaultBrandExample && defaultBackgroundToken && context.pairsByBackground[defaultBackgroundToken]?.some(
20665
+ (pair) => pair.id === DEFAULT_INITIAL_PAIR_ID5
20666
+ ) ? DEFAULT_INITIAL_PAIR_ID5 : null;
20667
+ const pairBackgroundToken = context.recommendedPairs.find((pair) => pair.id === pairParam)?.background.token ?? null;
20668
+ const selectedBackgroundToken = resolveBackgroundToken5(
20669
+ context,
20670
+ backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken,
20671
+ getToneFromToken5(backgroundParam ?? pairBackgroundToken ?? defaultBackgroundToken)
20672
+ );
20673
+ const selectedPairId = getPreferredPairForBackground5(
20674
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
20675
+ pairParam ?? defaultPairId
20676
+ )?.id ?? "";
20677
+ return {
20678
+ accentKey: context.accent.key,
20679
+ primaryKey: context.primary.key,
20680
+ selectedBackgroundToken,
20681
+ selectedPairId,
20682
+ themeCategory
20683
+ };
20684
+ }
20685
+ function getReadableTextColor4(tone) {
20686
+ return tone >= 600 ? "#ffffff" : "#002664";
20687
+ }
20688
+ function getBackgroundOptionName3(background) {
20689
+ return background.name ?? `${background.familyLabel} ${background.tone}`;
20690
+ }
20691
+ function getMainPairingLabel2(pair, bestPair) {
20692
+ if (!pair) {
20693
+ return "No AAA pairing available";
20694
+ }
20695
+ if (pair.id === bestPair?.id) {
20696
+ return "NSW recommended pairing";
20697
+ }
20698
+ if (isWhiteForegroundPair5(pair) && isLargeTextOnlyPair3(pair)) {
20699
+ return "Large-text example only";
20700
+ }
20701
+ if (isWhiteForegroundPair5(pair) && !pair.passes.aaaLarge) {
20702
+ return "Example only";
20703
+ }
20704
+ return "Approved alternative";
20705
+ }
20706
+ function getMainPairingSupportCopy2(pair, bestPair, context) {
20707
+ if (!pair) {
20708
+ return "No AAA-compliant foreground available for this background.";
20709
+ }
20710
+ if (pair.id === bestPair?.id) {
20711
+ return getBestRecommendationReason3(pair, context);
20712
+ }
20713
+ if (isWhiteForegroundPair5(pair) && isLargeTextOnlyPair3(pair)) {
20714
+ return "White works here for large text only. Use the NSW default for standard body copy and smaller interface text.";
20715
+ }
20716
+ if (isWhiteForegroundPair5(pair) && !pair.passes.aaaLarge) {
20717
+ return "White does not meet AAA on this background. Choose a different approved background or foreground.";
20718
+ }
20719
+ return "Approved AAA alternative when a different tone or emphasis is needed.";
20720
+ }
20721
+ function getBestRecommendationReason3(pair, context) {
20722
+ if (isWhiteForegroundPair5(pair)) {
20723
+ return "Recommended because this background is dark enough to support white text at AAA contrast.";
20724
+ }
20725
+ if (pair.foreground.familyKey === pair.background.familyKey) {
20726
+ return "Recommended because it stays within the same colour family while keeping clear AAA contrast.";
20727
+ }
20728
+ if (pair.foreground.familyKey === context.grey.key) {
20729
+ return "Recommended because grey provides a strong neutral contrast without competing with the background.";
20730
+ }
20731
+ if (pair.foreground.familyKey === context.accent.key) {
20732
+ return "Recommended because the selected accent family adds emphasis while preserving AAA contrast.";
20733
+ }
20734
+ if (pair.foreground.familyKey === context.primary.key) {
20735
+ return "Recommended because the selected primary family gives the clearest AAA-compliant contrast for this background.";
20736
+ }
20737
+ return "Recommended because it is the clearest NSW-approved AAA pairing for this background.";
20738
+ }
20739
+ function getRecommendationCategory3(pair, bestPair, context) {
20740
+ if (pair.id === bestPair?.id) return "best";
20741
+ if (isWhiteForegroundPair5(pair)) return "white";
20742
+ if (pair.foreground.familyKey === pair.background.familyKey) return "same-family";
20743
+ if (pair.foreground.familyKey === context.accent.key) return "accent-family";
20744
+ if (pair.foreground.familyKey === context.grey.key) return "grey-option";
20745
+ if (pair.foreground.familyKey === context.primary.key) return "primary-family";
20746
+ return "approved";
20747
+ }
20748
+ function getRecommendationSortRank3(category) {
20749
+ switch (category) {
20750
+ case "best":
20751
+ return 0;
20752
+ case "same-family":
20753
+ return 1;
20754
+ case "primary-family":
20755
+ return 2;
20756
+ case "accent-family":
20757
+ return 3;
20758
+ case "grey-option":
20759
+ return 4;
20760
+ case "white":
20761
+ return 5;
20762
+ default:
20763
+ return 6;
20764
+ }
20765
+ }
20766
+ function getRecommendationGroupId2(category) {
20767
+ switch (category) {
20768
+ case "best":
20769
+ case "same-family":
20770
+ case "primary-family":
20771
+ return "closest";
20772
+ case "accent-family":
20773
+ case "white":
20774
+ case "approved":
20775
+ return "expressive";
20776
+ case "grey-option":
20777
+ return "neutral";
20778
+ default:
20779
+ return null;
20780
+ }
20781
+ }
20782
+ function buildRecommendationGroups2(items) {
20783
+ const groupedItems = items.reduce(
20784
+ (accumulator, item) => {
20785
+ const groupId = getRecommendationGroupId2(item.category);
20786
+ if (!groupId) {
20787
+ return accumulator;
20788
+ }
20789
+ accumulator[groupId].push(item);
20790
+ return accumulator;
20791
+ },
20792
+ {
20793
+ closest: [],
20794
+ expressive: [],
20795
+ neutral: []
20796
+ }
20797
+ );
20798
+ const groups = [
20799
+ {
20800
+ id: "closest",
20801
+ title: "Closest to default",
20802
+ description: "Stays closest to the NSW default in tone and overall treatment.",
20803
+ items: groupedItems.closest
20804
+ },
20805
+ {
20806
+ id: "expressive",
20807
+ title: "More expressive (accent)",
20808
+ description: "Brings more accent or emphasis into the foreground treatment.",
20809
+ items: groupedItems.expressive
20810
+ },
20811
+ {
20812
+ id: "neutral",
20813
+ title: "Neutral/system",
20814
+ description: "Uses quieter neutral contrast for system or utility treatments.",
20815
+ items: groupedItems.neutral
20816
+ }
20817
+ ];
20818
+ return groups.filter((group) => group.items.length > 0);
20819
+ }
20820
+ function getAvailabilityMeta3(isSelected, hasPairs) {
20821
+ if (isSelected && hasPairs) {
20822
+ return {
20823
+ description: "Selected background with AAA foreground options.",
20824
+ icon: Icons.check_circle,
20825
+ label: "Selected",
20826
+ tone: "selected"
20827
+ };
20828
+ }
20829
+ if (isSelected) {
20830
+ return {
20831
+ description: "Selected background with no AAA-compliant foreground available.",
20832
+ icon: Icons.warning,
20833
+ label: "Selected, no AAA",
20834
+ tone: "unavailable"
20835
+ };
20836
+ }
20837
+ if (hasPairs) {
20838
+ return {
20839
+ description: "AAA foreground options available.",
20840
+ icon: Icons.radio_button_checked,
20841
+ label: "Available",
20842
+ tone: "available"
20843
+ };
20844
+ }
20845
+ return {
20846
+ description: "No AAA-compliant foreground available for this background.",
20847
+ icon: Icons.close,
20848
+ label: "No AAA",
20849
+ tone: "unavailable"
20850
+ };
20851
+ }
20852
+ function getPairingCopyText3(pair) {
20853
+ const accessibilityLine = pair.passes.aaaText ? "Accessibility: Meets AAA for normal and large text" : pair.passes.aaaLarge ? "Accessibility: Meets AAA for large text only" : "Accessibility: Fails AAA for normal and large text";
20854
+ return [
20855
+ `Background: ${pair.background.token} (${pair.background.hex})`,
20856
+ `Foreground: ${pair.foreground.token} (${pair.foreground.hex})`,
20857
+ `Contrast ratio: ${pair.contrastRatio.toFixed(2)}:1`,
20858
+ accessibilityLine
20859
+ ].join("\n");
20860
+ }
20861
+ function getAccessibilitySummaryLine2(pair) {
20862
+ if (!pair) {
20863
+ return "Contrast unavailable";
20864
+ }
20865
+ if (pair.passes.aaaText) {
20866
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (normal + large text)`;
20867
+ }
20868
+ if (pair.passes.aaaLarge) {
20869
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 AAA compliant (large text only)`;
20870
+ }
20871
+ return `${pair.contrastRatio.toFixed(2)}:1 \u2014 Not AAA compliant`;
20872
+ }
20873
+ function getLiveAnnouncement3(pair, background) {
20874
+ if (!background) {
20875
+ return "No approved background tones available.";
20876
+ }
20877
+ if (!pair) {
20878
+ return `${background.token} selected. No AAA-compliant foreground options available for this selection.`;
20879
+ }
20880
+ if (isWhiteForegroundPair5(pair) && isLargeTextOnlyPair3(pair)) {
20881
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for large text only.`;
20882
+ }
20883
+ if (isWhiteForegroundPair5(pair) && !pair.passes.aaaLarge) {
20884
+ return `${background.token} with white. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Fails AAA for normal and large text.`;
20885
+ }
20886
+ return `${background.token} with ${pair.foreground.token}. Contrast ratio ${pair.contrastRatio.toFixed(2)} to 1. Meets AAA for normal and large text.`;
20887
+ }
20888
+ function formatValueRows3(color2, visibleFormats) {
20889
+ const hasDisplayTone = color2.token !== "white";
20890
+ return [
20891
+ { key: "token", label: "Token", value: color2.token, copyable: true },
20892
+ {
20893
+ key: "tone",
20894
+ label: "Tone",
20895
+ value: hasDisplayTone ? String(color2.tone) : "Not applicable",
20896
+ copyable: hasDisplayTone
20897
+ },
20898
+ ...visibleFormats.map((format) => ({
20899
+ key: format,
20900
+ label: format.toUpperCase(),
20901
+ value: color2[format],
20902
+ copyable: true
20903
+ }))
20904
+ ];
20905
+ }
20906
+ function SelectorButton3({
20907
+ description,
20908
+ isSelected,
20909
+ label,
20910
+ onClick,
20911
+ swatch
20912
+ }) {
20913
+ return /* @__PURE__ */ jsxRuntime.jsx(
20914
+ "button",
20915
+ {
20916
+ type: "button",
20917
+ "aria-pressed": isSelected,
20918
+ onClick,
20919
+ className: cn(
20920
+ "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",
20921
+ isSelected ? "border-primary-800 bg-primary-50" : "border-grey-300 bg-white hover:border-primary-500 hover:bg-grey-50"
20922
+ ),
20923
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
20924
+ swatch ? /* @__PURE__ */ jsxRuntime.jsx(
20925
+ "span",
20926
+ {
20927
+ "aria-hidden": "true",
20928
+ className: "mt-0.5 size-4 shrink-0 rounded-full border border-black/10",
20929
+ style: { backgroundColor: swatch }
20930
+ }
20931
+ ) : null,
20932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1", children: [
20933
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: label }),
20934
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs/5 text-muted-foreground", children: description }) : null
20935
+ ] })
20936
+ ] })
20937
+ }
20938
+ );
20939
+ }
20940
+ function BackgroundSwatchButton3({
20941
+ background,
20942
+ hasPairs,
20943
+ isSelected,
20944
+ onClick
20945
+ }) {
20946
+ const status = getAvailabilityMeta3(isSelected, hasPairs);
20947
+ const StatusIcon = status.icon;
20948
+ return /* @__PURE__ */ jsxRuntime.jsxs(
20949
+ "button",
20950
+ {
20951
+ type: "button",
20952
+ "aria-pressed": isSelected,
20953
+ "aria-label": `Select ${background.token} background. ${status.description}`,
20954
+ onClick,
20955
+ className: cn(
20956
+ "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",
20957
+ 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"
20958
+ ),
20959
+ children: [
20960
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
20961
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
20962
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: getBackgroundOptionName3(background) }),
20963
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 font-mono text-[0.72rem] break-all text-muted-foreground", children: background.token })
20964
+ ] }),
20965
+ /* @__PURE__ */ jsxRuntime.jsxs(
20966
+ "span",
20967
+ {
20968
+ className: cn(
20969
+ "inline-flex items-center gap-1 rounded-sm border px-2 py-1 text-[0.68rem] font-semibold uppercase",
20970
+ status.tone === "selected" && "border-primary-800 bg-primary-800 text-white dark:border-primary-500 dark:bg-primary-500",
20971
+ status.tone === "available" && "border-grey-300 bg-grey-50 text-foreground",
20972
+ 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"
20973
+ ),
20974
+ children: [
20975
+ /* @__PURE__ */ jsxRuntime.jsx(StatusIcon, { "data-slot": "icon", className: "size-4" }),
20976
+ status.label
20977
+ ]
20978
+ }
20979
+ )
20980
+ ] }),
20981
+ /* @__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 } }) }),
20982
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-3 text-xs/5 text-muted-foreground", children: status.description })
20983
+ ]
20984
+ }
20985
+ );
20986
+ }
20987
+ function CurrentResultCard3({
20988
+ bestPair,
20989
+ copiedKey,
20990
+ familySummary,
20991
+ onCopyPairing,
20992
+ pair,
20993
+ supportText,
20994
+ selectedBackground
20995
+ }) {
20996
+ const previewForeground = pair?.foreground.hex ?? getReadableTextColor4(selectedBackground.tone);
20997
+ const isRecommended = pair ? pair.id === bestPair?.id : false;
20998
+ const pairingLabel = getMainPairingLabel2(pair, bestPair);
20999
+ const accessibilitySummary = getAccessibilitySummaryLine2(pair);
21000
+ const whiteForeground = pair ? isWhiteForegroundPair5(pair) : false;
21001
+ const fauxButtonStyle = pair ? {
21002
+ "--btn-bg": pair.foreground.hex,
21003
+ "--btn-border": pair.foreground.hex,
21004
+ "--btn-text": pair.background.hex,
21005
+ "--btn-icon": pair.background.hex,
21006
+ "--btn-hover-overlay": pair.background.hex
21007
+ } : null;
21008
+ return /* @__PURE__ */ jsxRuntime.jsx(
21009
+ Card,
21010
+ {
21011
+ className: cn(
21012
+ "gap-0 overflow-hidden border-grey-200 bg-white py-0",
21013
+ isRecommended && "border-primary-100"
21014
+ ),
21015
+ children: /* @__PURE__ */ jsxRuntime.jsx(
21016
+ "div",
21017
+ {
21018
+ className: "p-3 sm:min-h-[21rem] sm:p-5",
21019
+ style: {
21020
+ backgroundColor: selectedBackground.hex,
21021
+ color: previewForeground
21022
+ },
21023
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[16rem] flex-col gap-5 sm:min-h-[17.5rem] sm:gap-6", children: [
21024
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[42rem] rounded-sm bg-white/92 px-4 py-3.5 text-foreground sm:px-5 sm:py-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between", children: [
21025
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-3", children: [
21026
+ /* @__PURE__ */ jsxRuntime.jsxs(
21027
+ "span",
21028
+ {
21029
+ className: cn(
21030
+ "inline-flex items-center gap-2 rounded-sm border px-2.5 py-1 text-[0.68rem] font-semibold tracking-[0.1em] uppercase",
21031
+ isRecommended ? "border-primary-200 bg-primary-50 text-primary-900" : "border-grey-300 bg-white text-foreground"
21032
+ ),
21033
+ children: [
21034
+ isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.info, { "data-slot": "icon", className: "size-4" }),
21035
+ pairingLabel
21036
+ ]
21037
+ }
21038
+ ),
21039
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
21040
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 4, className: "text-foreground", trim: "normal", children: pair ? `${getPairingColorDisplayName5(pair.foreground)} on ${getPairingColorDisplayName5(pair.background)}` : `${getPairingColorDisplayName5(selectedBackground)} selected` }),
21041
+ pair ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: [
21042
+ pair.foreground.token,
21043
+ " on ",
21044
+ pair.background.token
21045
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-[0.74rem] break-all text-muted-foreground", children: selectedBackground.token }),
21046
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.95rem] font-semibold text-foreground", children: accessibilitySummary }),
21047
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "max-w-3xl text-grey-700", children: supportText })
21048
+ ] })
21049
+ ] }),
21050
+ pair ? /* @__PURE__ */ jsxRuntime.jsx(
21051
+ Button2,
21052
+ {
21053
+ variant: "outline",
21054
+ color: "grey",
21055
+ size: "sm",
21056
+ className: "w-full justify-center bg-white/90 lg:w-auto lg:min-w-40",
21057
+ onClick: onCopyPairing,
21058
+ children: copiedKey === "current-pairing" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21059
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
21060
+ "Pairing copied"
21061
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21062
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
21063
+ "Copy pairing"
21064
+ ] })
21065
+ }
21066
+ ) : null
21067
+ ] }) }),
21068
+ pair ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[12rem] flex-col justify-between gap-5", children: [
21069
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
21070
+ /* @__PURE__ */ jsxRuntime.jsxs(
21071
+ "span",
21072
+ {
21073
+ className: "inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[0.72rem] font-semibold tracking-[0.16em] uppercase",
21074
+ style: {
21075
+ borderColor: pair.foreground.hex,
21076
+ backgroundColor: pair.foreground.hex,
21077
+ color: pair.background.hex
21078
+ },
21079
+ children: [
21080
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.palette, { "data-slot": "icon", className: "size-4" }),
21081
+ familySummary
21082
+ ]
21083
+ }
21084
+ ),
21085
+ /* @__PURE__ */ jsxRuntime.jsxs(
21086
+ "span",
21087
+ {
21088
+ className: "inline-flex rounded-full border px-3 py-1 text-[0.72rem] font-semibold tracking-[0.16em] uppercase",
21089
+ style: {
21090
+ borderColor: pair.foreground.hex
21091
+ },
21092
+ children: [
21093
+ pair.rating,
21094
+ " ",
21095
+ pair.contrastRatio.toFixed(2),
21096
+ ":1"
21097
+ ]
21098
+ }
21099
+ )
21100
+ ] }),
21101
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-xl space-y-4 pb-8 sm:pb-10", children: [
21102
+ /* @__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" }),
21103
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
21104
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-[2.8rem] leading-none font-bold text-current sm:text-[4rem]", children: "Pair colour with confidence." }),
21105
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-[0.96rem]/7 sm:text-base/7", children: getPreviewGuidance5(pair, isRecommended) }),
21106
+ fauxButtonStyle ? /* @__PURE__ */ jsxRuntime.jsx(
21107
+ "span",
21108
+ {
21109
+ "aria-hidden": "true",
21110
+ "data-variant": "solid",
21111
+ className: cn(
21112
+ buttonVariants({ variant: "solid", size: "default" }),
21113
+ "pointer-events-none cursor-default px-5 text-[15px] font-[700] select-none sm:px-6 sm:text-[16px] sm:font-[700]"
21114
+ ),
21115
+ style: fauxButtonStyle,
21116
+ children: "Get started"
21117
+ }
21118
+ ) : null
21119
+ ] })
21120
+ ] }),
21121
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
21122
+ /* @__PURE__ */ jsxRuntime.jsxs(
21123
+ "span",
21124
+ {
21125
+ className: "inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm font-semibold",
21126
+ style: {
21127
+ backgroundColor: pair.foreground.hex,
21128
+ color: pair.background.hex
21129
+ },
21130
+ children: [
21131
+ "Pass",
21132
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" })
21133
+ ]
21134
+ }
21135
+ ),
21136
+ /* @__PURE__ */ jsxRuntime.jsxs(
21137
+ "span",
21138
+ {
21139
+ className: "inline-flex rounded-full border px-4 py-2 text-sm",
21140
+ style: {
21141
+ borderColor: pair.foreground.hex
21142
+ },
21143
+ children: [
21144
+ pair.background.token,
21145
+ " / ",
21146
+ pair.foreground.token
21147
+ ]
21148
+ }
21149
+ )
21150
+ ] })
21151
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-lg space-y-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
21152
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "max-w-lg text-[1.9rem] leading-tight font-bold text-current sm:text-[2.25rem]", children: "No AAA combination available." }),
21153
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-md text-[0.96rem]/7 sm:text-base/7", children: "This approved background does not currently have an AAA foreground in this tool. Choose another approved background to continue." })
21154
+ ] }) })
21155
+ ] })
21156
+ }
21157
+ )
21158
+ }
21159
+ );
21160
+ }
21161
+ function RecommendationCard3({
21162
+ copiedKey,
21163
+ isSelected,
21164
+ item,
21165
+ onCopyPairing,
21166
+ onSelect
21167
+ }) {
21168
+ const { pair } = item;
21169
+ return /* @__PURE__ */ jsxRuntime.jsxs(
21170
+ "div",
21171
+ {
21172
+ className: cn(
21173
+ "relative rounded-sm border bg-white/95 px-3 py-2 text-left transition-colors focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
21174
+ isSelected ? "border-primary-700 bg-primary-50/30" : "border-grey-200 hover:border-grey-300"
21175
+ ),
21176
+ children: [
21177
+ /* @__PURE__ */ jsxRuntime.jsx(
21178
+ "button",
21179
+ {
21180
+ type: "button",
21181
+ "aria-pressed": isSelected,
21182
+ "aria-label": `Use ${pair.foreground.token} on ${pair.background.token}`,
21183
+ onClick: onSelect,
21184
+ className: "absolute inset-0 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden"
21185
+ }
21186
+ ),
21187
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pointer-events-none relative z-10 flex items-start gap-2.5", children: [
21188
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-0.5 w-10 shrink-0 overflow-hidden rounded-[2px] border border-black/10", children: [
21189
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 w-full", style: { backgroundColor: pair.background.hex } }),
21190
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-full", style: { backgroundColor: pair.foreground.hex } })
21191
+ ] }),
21192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [
21193
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [
21194
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.94rem] leading-6 font-semibold text-foreground", children: [
21195
+ getPairingColorDisplayName5(pair.foreground),
21196
+ " on",
21197
+ " ",
21198
+ getPairingColorDisplayName5(pair.background)
21199
+ ] }),
21200
+ item.category === "best" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm border border-primary-200 bg-primary-50 px-1.5 py-0.5 text-[0.64rem] font-semibold tracking-[0.1em] text-primary-900 uppercase", children: "Default" }) : null,
21201
+ isSelected ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex rounded-sm border border-primary-700 px-1.5 py-0.5 text-[0.64rem] font-semibold tracking-[0.1em] text-primary-800 uppercase", children: "Current" }) : null
21202
+ ] }),
21203
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-[0.72rem] break-all text-muted-foreground", children: [
21204
+ pair.foreground.token,
21205
+ " on ",
21206
+ pair.background.token
21207
+ ] }),
21208
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.82rem] text-muted-foreground", children: [
21209
+ pair.contrastRatio.toFixed(2),
21210
+ ":1 contrast"
21211
+ ] })
21212
+ ] }),
21213
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto shrink-0 self-start", children: /* @__PURE__ */ jsxRuntime.jsx(
21214
+ Button2,
21215
+ {
21216
+ variant: "ghost",
21217
+ color: "grey",
21218
+ size: "icon",
21219
+ className: "size-7 text-muted-foreground hover:text-foreground",
21220
+ onClick: onCopyPairing,
21221
+ "aria-label": `Copy pairing ${pair.background.token} and ${pair.foreground.token}`,
21222
+ title: copiedKey === `pair:${pair.id}` ? "Copied" : "Copy pairing",
21223
+ children: copiedKey === `pair:${pair.id}` ? /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-4" })
21224
+ }
21225
+ ) })
21226
+ ] })
21227
+ ]
21228
+ }
21229
+ );
21230
+ }
21231
+ function RecommendationGroupSection2({
21232
+ children,
21233
+ description,
21234
+ title
21235
+ }) {
21236
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-1.5", children: [
21237
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
21238
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
21239
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-grey-600", children: description })
21240
+ ] }),
21241
+ children
21242
+ ] });
21243
+ }
21244
+ function TechnicalDetailsPanel3({
21245
+ color: color2,
21246
+ copiedKey,
21247
+ onCopyValue,
21248
+ title,
21249
+ visibleFormats
21250
+ }) {
21251
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white", children: [
21252
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-4 py-3.5 sm:px-5", children: [
21253
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: title }),
21254
+ color2 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21255
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: getPairingColorDisplayName5(color2) }),
21256
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3.5 overflow-hidden rounded-sm border border-black/10 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-16 w-full sm:h-20", style: { backgroundColor: color2.hex } }) })
21257
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "No AAA foreground available." })
21258
+ ] }),
21259
+ color2 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-grey-200", children: formatValueRows3(color2, visibleFormats).map((row) => {
21260
+ const copyKey = `${title}-${row.key}`;
21261
+ return /* @__PURE__ */ jsxRuntime.jsxs(
21262
+ "div",
21263
+ {
21264
+ className: "flex flex-col items-start gap-3 px-4 py-3.5 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:px-5",
21265
+ children: [
21266
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
21267
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.72rem] font-semibold tracking-[0.12em] text-muted-foreground uppercase", children: row.label }),
21268
+ /* @__PURE__ */ jsxRuntime.jsx(
21269
+ "p",
21270
+ {
21271
+ className: cn(
21272
+ "mt-2 text-sm text-foreground",
21273
+ row.key !== "tone" && "font-mono break-all"
21274
+ ),
21275
+ children: row.value
21276
+ }
21277
+ )
21278
+ ] }),
21279
+ row.copyable ? /* @__PURE__ */ jsxRuntime.jsx(
21280
+ Button2,
21281
+ {
21282
+ variant: "ghost",
21283
+ color: "grey",
21284
+ size: "sm",
21285
+ className: "self-start",
21286
+ onClick: () => onCopyValue(copyKey, row.value, `${row.label} copied`),
21287
+ "aria-label": `Copy ${title.toLowerCase()} ${row.label.toLowerCase()}`,
21288
+ children: copiedKey === copyKey ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21289
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check_circle, { "data-slot": "icon", className: "size-5" }),
21290
+ "Copied"
21291
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21292
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
21293
+ "Copy"
21294
+ ] })
21295
+ }
21296
+ ) : null
21297
+ ]
21298
+ },
21299
+ row.key
21300
+ );
21301
+ }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4", 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." }) })
21302
+ ] });
21303
+ }
21304
+ function resolveSelectionState3(nextThemeCategory, nextPrimaryKey, nextAccentKey, preferredBackgroundToken, preferredPairId) {
21305
+ const context = getPairingContext(nextThemeCategory, nextPrimaryKey, nextAccentKey);
21306
+ const selectedBackgroundToken = resolveBackgroundToken5(
21307
+ context,
21308
+ preferredBackgroundToken,
21309
+ getToneFromToken5(preferredBackgroundToken)
21310
+ );
21311
+ const selectedPairId = getPreferredPairForBackground5(
21312
+ context.pairsByBackground[selectedBackgroundToken] ?? [],
21313
+ preferredPairId
21314
+ )?.id ?? "";
21315
+ return {
21316
+ accentKey: context.accent.key,
21317
+ context,
21318
+ primaryKey: context.primary.key,
21319
+ selectedBackgroundToken,
21320
+ selectedPairId,
21321
+ themeCategory: nextThemeCategory
21322
+ };
21323
+ }
21324
+ function ColorPairingToolV5Loading() {
21325
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
21326
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
21327
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-52 rounded-sm border border-grey-200 bg-grey-50" }),
21328
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[32rem] rounded-sm border border-grey-200 bg-grey-50" })
21329
+ ] }),
21330
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
21331
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-96 rounded-sm border border-grey-200 bg-grey-50" }),
21332
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-64 rounded-sm border border-grey-200 bg-grey-50" }),
21333
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72 rounded-sm border border-grey-200 bg-grey-50" })
21334
+ ] })
21335
+ ] });
21336
+ }
21337
+ function ColorPairingToolV5Content({
21338
+ onAnalyticsEvent,
21339
+ visibleFormats
21340
+ }) {
21341
+ const searchParams = navigation.useSearchParams();
21342
+ const stickyOffset = useStickyOffset(24);
21343
+ const [initialState] = React5.useState(() => getInitialPairingState5(searchParams));
21344
+ const [themeCategory, setThemeCategory] = React5.useState(initialState.themeCategory);
21345
+ const [primaryFamilyKey, setPrimaryFamilyKey] = React5.useState(initialState.primaryKey);
21346
+ const [accentFamilyKey, setAccentFamilyKey] = React5.useState(initialState.accentKey);
21347
+ const [selectedBackgroundToken, setSelectedBackgroundToken] = React5.useState(
21348
+ initialState.selectedBackgroundToken
21349
+ );
21350
+ const [selectedPairId, setSelectedPairId] = React5.useState(initialState.selectedPairId);
21351
+ const [drawerStepIndex, setDrawerStepIndex] = React5.useState(0);
21352
+ const [isCompactControlsOpen, setIsCompactControlsOpen] = React5.useState(false);
21353
+ const [isShowingAllAlternatives, setIsShowingAllAlternatives] = React5.useState(false);
21354
+ const [isTechnicalDetailsOpen, setIsTechnicalDetailsOpen] = React5.useState(false);
21355
+ const [, copyToClipboardRaw] = usehooks.useCopyToClipboard();
21356
+ const [copiedKey, setCopiedKey] = React5.useState(null);
21357
+ const copiedKeyTimeoutRef = React5.useRef(null);
21358
+ const resultSectionRef = React5.useRef(null);
21359
+ const noValidStateRef = React5.useRef(/* @__PURE__ */ new Set());
21360
+ const technicalDetailsViewedRef = React5.useRef(false);
21361
+ const emitAnalyticsEvent = React5.useCallback(
21362
+ (event) => {
21363
+ onAnalyticsEvent(event);
21364
+ if (typeof window !== "undefined") {
21365
+ window.dispatchEvent(
21366
+ new CustomEvent(COLOR_PAIRING_TOOL_V5_ANALYTICS_EVENT, {
21367
+ detail: event
21368
+ })
21369
+ );
21370
+ }
21371
+ },
21372
+ [onAnalyticsEvent]
21373
+ );
21374
+ React5.useEffect(() => {
21375
+ return () => {
21376
+ if (copiedKeyTimeoutRef.current) {
21377
+ clearTimeout(copiedKeyTimeoutRef.current);
21378
+ }
21379
+ };
21380
+ }, []);
21381
+ React5.useEffect(() => {
21382
+ if (typeof window === "undefined") {
21383
+ return;
21384
+ }
21385
+ const mediaQuery = window.matchMedia(PERSISTENT_DRAWER_MIN_WIDTH_QUERY3);
21386
+ const handleChange = (event) => {
21387
+ if (event?.matches ?? mediaQuery.matches) {
21388
+ setIsCompactControlsOpen(false);
21389
+ }
21390
+ };
21391
+ handleChange();
21392
+ mediaQuery.addEventListener("change", handleChange);
21393
+ return () => {
21394
+ mediaQuery.removeEventListener("change", handleChange);
21395
+ };
21396
+ }, []);
21397
+ const themeFamilies = React5.useMemo(() => getPairingFamilies(themeCategory), [themeCategory]);
21398
+ const context = React5.useMemo(
21399
+ () => getPairingContext(themeCategory, primaryFamilyKey, accentFamilyKey),
21400
+ [themeCategory, primaryFamilyKey, accentFamilyKey]
21401
+ );
21402
+ const selectableFamilies = React5.useMemo(
21403
+ () => themeFamilies.filter((family) => family.key !== context.grey.key),
21404
+ [themeFamilies, context.grey.key]
21405
+ );
21406
+ const selectableAccentFamilies = React5.useMemo(
21407
+ () => selectableFamilies.filter((family) => family.key !== context.primary.key),
21408
+ [selectableFamilies, context.primary.key]
21409
+ );
21410
+ const selectedBackground = React5.useMemo(
21411
+ () => context.backgrounds.find((background) => background.token === selectedBackgroundToken) ?? context.backgrounds[0] ?? null,
21412
+ [context.backgrounds, selectedBackgroundToken]
21413
+ );
21414
+ const selectedBackgroundPairs = React5.useMemo(
21415
+ () => selectedBackground ? context.pairsByBackground[selectedBackground.token] ?? [] : [],
21416
+ [context.pairsByBackground, selectedBackground]
21417
+ );
21418
+ const bestRecommendedPair = React5.useMemo(
21419
+ () => getPreferredPairForBackground5(selectedBackgroundPairs),
21420
+ [selectedBackgroundPairs]
21421
+ );
21422
+ const selectedPair = React5.useMemo(
21423
+ () => getPreferredPairForBackground5(selectedBackgroundPairs, selectedPairId),
21424
+ [selectedBackgroundPairs, selectedPairId]
21425
+ );
21426
+ const whiteForegroundExample = React5.useMemo(
21427
+ () => selectedBackground && supportsWhiteForegroundPreview(selectedBackground) ? getWhiteForegroundPair(selectedBackground) : null,
21428
+ [selectedBackground]
21429
+ );
21430
+ const previewPair = selectedPair ?? whiteForegroundExample ?? null;
21431
+ const detailForeground = selectedPair?.foreground ?? whiteForegroundExample?.foreground ?? null;
21432
+ const currentPairSupportText = React5.useMemo(
21433
+ () => getMainPairingSupportCopy2(previewPair, bestRecommendedPair, context),
21434
+ [bestRecommendedPair, context, previewPair]
21435
+ );
21436
+ const recommendationItems = React5.useMemo(() => {
21437
+ return selectedBackgroundPairs.map((pair) => {
21438
+ const category = getRecommendationCategory3(pair, bestRecommendedPair, context);
21439
+ return {
21440
+ category,
21441
+ pair
21442
+ };
21443
+ }).sort(
21444
+ (left, right) => getRecommendationSortRank3(left.category) - getRecommendationSortRank3(right.category)
21445
+ );
21446
+ }, [bestRecommendedPair, context, selectedBackgroundPairs]);
21447
+ const alternativeRecommendationGroups = React5.useMemo(
21448
+ () => buildRecommendationGroups2(
21449
+ recommendationItems.filter((item) => item.pair.id !== selectedPair?.id)
21450
+ ),
21451
+ [recommendationItems, selectedPair?.id]
21452
+ );
21453
+ const visibleAlternativeRecommendationGroups = React5.useMemo(() => {
21454
+ if (isShowingAllAlternatives) {
21455
+ return alternativeRecommendationGroups;
21456
+ }
21457
+ let remaining = INITIAL_VISIBLE_ALTERNATIVES2;
21458
+ return alternativeRecommendationGroups.reduce((groups, group) => {
21459
+ if (remaining <= 0) {
21460
+ return groups;
21461
+ }
21462
+ const items = group.items.slice(0, remaining);
21463
+ if (items.length > 0) {
21464
+ groups.push({
21465
+ ...group,
21466
+ items
21467
+ });
21468
+ remaining -= items.length;
21469
+ }
21470
+ return groups;
21471
+ }, []);
21472
+ }, [alternativeRecommendationGroups, isShowingAllAlternatives]);
21473
+ const hiddenAlternativeCount = React5.useMemo(() => {
21474
+ const totalAlternatives = alternativeRecommendationGroups.reduce(
21475
+ (count, group) => count + group.items.length,
21476
+ 0
21477
+ );
21478
+ const visibleAlternatives = visibleAlternativeRecommendationGroups.reduce(
21479
+ (count, group) => count + group.items.length,
21480
+ 0
21481
+ );
21482
+ return Math.max(0, totalAlternatives - visibleAlternatives);
21483
+ }, [alternativeRecommendationGroups, visibleAlternativeRecommendationGroups]);
21484
+ const liveAnnouncement = React5.useMemo(
21485
+ () => getLiveAnnouncement3(previewPair, selectedBackground),
21486
+ [previewPair, selectedBackground]
21487
+ );
21488
+ const familySummary = React5.useMemo(
21489
+ () => [context.primary.label, context.accent.label, context.grey.label].join(" + "),
21490
+ [context.accent.label, context.grey.label, context.primary.label]
21491
+ );
21492
+ const shareBackgroundToken = selectedBackground?.token ?? selectedBackgroundToken;
21493
+ const shareUrl = React5.useMemo(() => {
21494
+ const params = new URLSearchParams();
21495
+ params.set("palette", themeCategory);
21496
+ params.set("primary", context.primary.key);
21497
+ params.set("accent", context.accent.key);
21498
+ if (shareBackgroundToken) {
21499
+ params.set("background", shareBackgroundToken);
21500
+ }
21501
+ if (selectedPairId) {
21502
+ params.set("pair", selectedPairId);
21503
+ }
21504
+ const query = params.toString();
21505
+ return `${COLOR_PAIRING_TOOL_V5_PATH}${query ? `?${query}` : ""}`;
21506
+ }, [context.accent.key, context.primary.key, shareBackgroundToken, selectedPairId, themeCategory]);
21507
+ const activeDrawerStep = COLOR_PAIRING_TOOL_DRAWER_STEPS3[drawerStepIndex];
21508
+ const isFirstDrawerStep = drawerStepIndex === 0;
21509
+ const isLastDrawerStep = drawerStepIndex === COLOR_PAIRING_TOOL_DRAWER_STEPS3.length - 1;
21510
+ const desktopSidebarStyle = React5.useMemo(
21511
+ () => ({
21512
+ "--tool-sidebar-max-height": `calc(100vh - ${stickyOffset}px)`,
21513
+ "--tool-sidebar-top": `${stickyOffset}px`
21514
+ }),
21515
+ [stickyOffset]
21516
+ );
21517
+ const goToDrawerStep = React5.useCallback((stepIndex) => {
21518
+ setDrawerStepIndex(Math.max(0, Math.min(stepIndex, COLOR_PAIRING_TOOL_DRAWER_STEPS3.length - 1)));
21519
+ }, []);
21520
+ const goToNextDrawerStep = React5.useCallback(() => {
21521
+ setDrawerStepIndex(
21522
+ (currentStep) => Math.min(currentStep + 1, COLOR_PAIRING_TOOL_DRAWER_STEPS3.length - 1)
21523
+ );
21524
+ }, []);
21525
+ const goToPreviousDrawerStep = React5.useCallback(() => {
21526
+ setDrawerStepIndex((currentStep) => Math.max(currentStep - 1, 0));
21527
+ }, []);
21528
+ const updateUrlParams = React5.useCallback((nextState) => {
21529
+ const params = new URLSearchParams(window.location.search);
21530
+ params.delete("family");
21531
+ params.set("palette", nextState.themeCategory);
21532
+ params.set("primary", nextState.primaryKey);
21533
+ params.set("accent", nextState.accentKey);
21534
+ params.set("background", nextState.selectedBackgroundToken);
21535
+ if (nextState.selectedPairId) {
21536
+ params.set("pair", nextState.selectedPairId);
21537
+ } else {
21538
+ params.delete("pair");
21539
+ }
21540
+ window.history.replaceState(
21541
+ null,
21542
+ "",
21543
+ `${window.location.pathname}?${params.toString()}${window.location.hash}`
21544
+ );
21545
+ }, []);
21546
+ const applyResolvedSelection = React5.useCallback(
21547
+ (nextState) => {
21548
+ setThemeCategory(nextState.themeCategory);
21549
+ setPrimaryFamilyKey(nextState.primaryKey);
21550
+ setAccentFamilyKey(nextState.accentKey);
21551
+ setSelectedBackgroundToken(nextState.selectedBackgroundToken);
21552
+ setSelectedPairId(nextState.selectedPairId);
21553
+ updateUrlParams(nextState);
21554
+ },
21555
+ [updateUrlParams]
21556
+ );
21557
+ const buildAnalyticsContext = React5.useCallback(
21558
+ (overrides) => ({
21559
+ accentKey: context.accent.key,
21560
+ backgroundToken: selectedBackground?.token,
21561
+ foregroundToken: selectedPair?.foreground.token,
21562
+ pairId: selectedPair?.id,
21563
+ palette: themeCategory,
21564
+ primaryKey: context.primary.key,
21565
+ ...overrides
21566
+ }),
21567
+ [context.accent.key, context.primary.key, selectedBackground, selectedPair, themeCategory]
21568
+ );
21569
+ const copyValue = React5.useCallback(
21570
+ (copyKey, value, toastLabel, analyticsEvent) => {
21571
+ copyToClipboardRaw(value);
21572
+ setCopiedKey(copyKey);
21573
+ sonner.toast(toastLabel, { duration: 2e3 });
21574
+ if (analyticsEvent) {
21575
+ emitAnalyticsEvent(analyticsEvent);
21576
+ }
21577
+ if (copiedKeyTimeoutRef.current) {
21578
+ clearTimeout(copiedKeyTimeoutRef.current);
21579
+ }
21580
+ copiedKeyTimeoutRef.current = setTimeout(() => {
21581
+ setCopiedKey(null);
21582
+ copiedKeyTimeoutRef.current = null;
21583
+ }, 2e3);
21584
+ },
21585
+ [copyToClipboardRaw, emitAnalyticsEvent]
21586
+ );
21587
+ const handleThemeCategoryChange = (nextThemeCategory) => {
21588
+ const nextState = resolveSelectionState3(
21589
+ nextThemeCategory,
21590
+ primaryFamilyKey,
21591
+ accentFamilyKey,
21592
+ selectedBackgroundToken,
21593
+ null
21594
+ );
21595
+ setIsShowingAllAlternatives(false);
21596
+ applyResolvedSelection(nextState);
21597
+ emitAnalyticsEvent({
21598
+ name: "palette_change",
21599
+ accentKey: nextState.accentKey,
21600
+ backgroundToken: nextState.selectedBackgroundToken,
21601
+ pairId: nextState.selectedPairId,
21602
+ palette: nextState.themeCategory,
21603
+ primaryKey: nextState.primaryKey
21604
+ });
21605
+ };
21606
+ const handlePrimaryColorChange = (nextPrimaryKey) => {
21607
+ const nextAccentKey = nextPrimaryKey === accentFamilyKey ? getDefaultAccentFamilyKey(themeCategory, nextPrimaryKey) : accentFamilyKey;
21608
+ const nextState = resolveSelectionState3(
21609
+ themeCategory,
21610
+ nextPrimaryKey,
21611
+ nextAccentKey,
21612
+ selectedBackgroundToken,
21613
+ null
21614
+ );
21615
+ setIsShowingAllAlternatives(false);
21616
+ applyResolvedSelection(nextState);
21617
+ emitAnalyticsEvent({
21618
+ name: "primary_change",
21619
+ accentKey: nextState.accentKey,
21620
+ backgroundToken: nextState.selectedBackgroundToken,
21621
+ pairId: nextState.selectedPairId,
21622
+ palette: nextState.themeCategory,
21623
+ primaryKey: nextState.primaryKey
21624
+ });
21625
+ };
21626
+ const handleAccentColorChange = (nextAccentKey) => {
21627
+ if (nextAccentKey === primaryFamilyKey) return;
21628
+ const nextState = resolveSelectionState3(
21629
+ themeCategory,
21630
+ primaryFamilyKey,
21631
+ nextAccentKey,
21632
+ selectedBackgroundToken,
21633
+ null
21634
+ );
21635
+ setIsShowingAllAlternatives(false);
21636
+ applyResolvedSelection(nextState);
21637
+ emitAnalyticsEvent({
21638
+ name: "accent_change",
21639
+ accentKey: nextState.accentKey,
21640
+ backgroundToken: nextState.selectedBackgroundToken,
21641
+ pairId: nextState.selectedPairId,
21642
+ palette: nextState.themeCategory,
21643
+ primaryKey: nextState.primaryKey
21644
+ });
21645
+ };
21646
+ const handleBackgroundChange = (nextSelectedBackgroundToken) => {
21647
+ const nextSelectedPairId = getPreferredPairForBackground5(context.pairsByBackground[nextSelectedBackgroundToken] ?? [])?.id ?? "";
21648
+ const nextState = {
21649
+ accentKey: context.accent.key,
21650
+ context,
21651
+ primaryKey: context.primary.key,
21652
+ selectedBackgroundToken: nextSelectedBackgroundToken,
21653
+ selectedPairId: nextSelectedPairId,
21654
+ themeCategory
21655
+ };
21656
+ setIsShowingAllAlternatives(false);
21657
+ applyResolvedSelection(nextState);
21658
+ emitAnalyticsEvent({
21659
+ name: "background_selection",
21660
+ ...buildAnalyticsContext({
21661
+ backgroundToken: nextSelectedBackgroundToken,
21662
+ foregroundToken: context.pairsByBackground[nextSelectedBackgroundToken]?.find(
21663
+ (pair) => pair.id === nextSelectedPairId
21664
+ )?.foreground.token,
21665
+ pairId: nextSelectedPairId
21666
+ })
21667
+ });
21668
+ if (typeof window !== "undefined" && window.matchMedia(MOBILE_RESULT_SCROLL_QUERY3).matches) {
21669
+ requestAnimationFrame(() => {
21670
+ resultSectionRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
21671
+ });
21672
+ }
21673
+ };
21674
+ const handlePairChange = (nextSelectedPairId, source) => {
21675
+ if (!selectedBackground) return;
21676
+ const nextPair = selectedBackgroundPairs.find((pair) => pair.id === nextSelectedPairId) ?? null;
21677
+ setSelectedPairId(nextSelectedPairId);
21678
+ updateUrlParams({
21679
+ accentKey: context.accent.key,
21680
+ context,
21681
+ primaryKey: context.primary.key,
21682
+ selectedBackgroundToken: selectedBackground.token,
21683
+ selectedPairId: nextSelectedPairId,
21684
+ themeCategory
21685
+ });
21686
+ emitAnalyticsEvent({
21687
+ name: "foreground_selection",
21688
+ ...buildAnalyticsContext({
21689
+ foregroundToken: nextPair?.foreground.token,
21690
+ pairId: nextSelectedPairId,
21691
+ source
21692
+ })
21693
+ });
21694
+ if (bestRecommendedPair && nextSelectedPairId !== bestRecommendedPair.id) {
21695
+ emitAnalyticsEvent({
21696
+ name: "alternative_combination_selected",
21697
+ ...buildAnalyticsContext({
21698
+ foregroundToken: nextPair?.foreground.token,
21699
+ pairId: nextSelectedPairId,
21700
+ source
21701
+ })
21702
+ });
21703
+ }
21704
+ };
21705
+ React5.useEffect(() => {
21706
+ if (!selectedBackground || selectedBackgroundPairs.length > 0) {
21707
+ return;
21708
+ }
21709
+ const key = `${themeCategory}:${context.primary.key}:${context.accent.key}:${selectedBackground.token}`;
21710
+ if (noValidStateRef.current.has(key)) {
21711
+ return;
21712
+ }
21713
+ noValidStateRef.current.add(key);
21714
+ emitAnalyticsEvent({
21715
+ name: "no_valid_combination_state",
21716
+ ...buildAnalyticsContext({
21717
+ backgroundToken: selectedBackground.token
21718
+ })
21719
+ });
21720
+ }, [
21721
+ buildAnalyticsContext,
21722
+ context.accent.key,
21723
+ context.primary.key,
21724
+ emitAnalyticsEvent,
21725
+ selectedBackground,
21726
+ selectedBackgroundPairs.length,
21727
+ themeCategory
21728
+ ]);
21729
+ React5.useEffect(() => {
21730
+ if (!isTechnicalDetailsOpen || technicalDetailsViewedRef.current) {
21731
+ return;
21732
+ }
21733
+ technicalDetailsViewedRef.current = true;
21734
+ emitAnalyticsEvent({
21735
+ name: "technical_details_viewed",
21736
+ ...buildAnalyticsContext({
21737
+ source: "details"
21738
+ })
21739
+ });
21740
+ }, [buildAnalyticsContext, emitAnalyticsEvent, isTechnicalDetailsOpen]);
21741
+ if (!selectedBackground) {
21742
+ return /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
21743
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "No approved background tones available" }),
21744
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "No approved tones are available for the current palette and colour selection." })
21745
+ ] });
21746
+ }
21747
+ const compactControlsSummary = `${themeCategory === "brand" ? "Brand" : "Aboriginal"} palette, ${context.primary.label} primary, ${context.accent.label} accent, ${getPairingColorDisplayName5(
21748
+ selectedBackground
21749
+ )} background.`;
21750
+ const renderControlsPanel = (isOverlay = false) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21751
+ /* @__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: [
21752
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
21753
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
21754
+ !isFirstDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { variant: "ghost", color: "grey", size: "sm", onClick: goToPreviousDrawerStep, children: [
21755
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.west, { "data-slot": "icon", className: "size-5" }),
21756
+ "Back"
21757
+ ] }) : null,
21758
+ isOverlay ? /* @__PURE__ */ jsxRuntime.jsx(
21759
+ Button2,
21760
+ {
21761
+ variant: "ghost",
21762
+ color: "grey",
21763
+ size: "icon",
21764
+ onClick: () => setIsCompactControlsOpen(false),
21765
+ "aria-label": "Close configuration",
21766
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icons.close, { "data-slot": "icon", className: "size-5" })
21767
+ }
21768
+ ) : null
21769
+ ] })
21770
+ ] }) }),
21771
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-grey-200 px-5 py-4", children: [
21772
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
21773
+ COLOR_PAIRING_TOOL_DRAWER_STEPS3.map((step, index) => /* @__PURE__ */ jsxRuntime.jsx(
21774
+ "button",
21775
+ {
21776
+ type: "button",
21777
+ "aria-current": index === drawerStepIndex ? "step" : void 0,
21778
+ "aria-label": `${step.eyebrow}: ${step.title}`,
21779
+ onClick: () => goToDrawerStep(index),
21780
+ className: "flex-1 rounded-sm focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden",
21781
+ children: /* @__PURE__ */ jsxRuntime.jsx(
21782
+ "span",
21783
+ {
21784
+ className: cn(
21785
+ "block h-1.5 rounded-full transition-colors",
21786
+ index <= drawerStepIndex ? "bg-primary-800" : "bg-grey-200"
21787
+ )
21788
+ }
21789
+ )
21790
+ },
21791
+ step.id
21792
+ )),
21793
+ /* @__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 })
21794
+ ] }),
21795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
21796
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 5, className: "text-foreground", trim: "normal", children: activeDrawerStep.title }),
21797
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: activeDrawerStep.description })
21798
+ ] })
21799
+ ] }),
21800
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs(
21801
+ "div",
21802
+ {
21803
+ className: "flex h-full transition-transform duration-300 ease-out",
21804
+ style: { transform: `translateX(-${drawerStepIndex * 100}%)` },
21805
+ children: [
21806
+ /* @__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: [
21807
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
21808
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Palette" }),
21809
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: ["brand", "aboriginal"].map((palette) => {
21810
+ const isSelected = themeCategory === palette;
21811
+ const label = palette === "brand" ? "Brand palette" : "Aboriginal palette";
21812
+ return /* @__PURE__ */ jsxRuntime.jsx(
21813
+ SelectorButton3,
21814
+ {
21815
+ label,
21816
+ isSelected,
21817
+ onClick: () => handleThemeCategoryChange(palette)
21818
+ },
21819
+ palette
21820
+ );
21821
+ }) })
21822
+ ] }),
21823
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
21824
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Primary colour family" }),
21825
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableFamilies.map((family) => {
21826
+ const label = getFamilySelectorLabel5(family, themeCategory, "primary colour");
21827
+ return /* @__PURE__ */ jsxRuntime.jsx(
21828
+ SelectorButton3,
21829
+ {
21830
+ label,
21831
+ isSelected: family.key === context.primary.key,
21832
+ onClick: () => handlePrimaryColorChange(family.key),
21833
+ swatch: getFamilySwatchColor5(family, 800)
21834
+ },
21835
+ family.key
21836
+ );
21837
+ }) })
21838
+ ] }),
21839
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
21840
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "mb-3 text-foreground", trim: "normal", children: "Accent colour family" }),
21841
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-2", children: selectableAccentFamilies.map((family) => {
21842
+ const label = getFamilySelectorLabel5(family, themeCategory, "accent colour");
21843
+ return /* @__PURE__ */ jsxRuntime.jsx(
21844
+ SelectorButton3,
21845
+ {
21846
+ label,
21847
+ isSelected: family.key === context.accent.key,
21848
+ onClick: () => handleAccentColorChange(family.key),
21849
+ swatch: getFamilySwatchColor5(family, 600)
21850
+ },
21851
+ family.key
21852
+ );
21853
+ }) })
21854
+ ] }),
21855
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-grey-200 pt-4", children: [
21856
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: "Grey is always included" }),
21857
+ /* @__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." })
21858
+ ] })
21859
+ ] }) }),
21860
+ /* @__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(
21861
+ "section",
21862
+ {
21863
+ className: cn("space-y-3", index > 0 && "border-t border-grey-200 pt-6"),
21864
+ children: [
21865
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
21866
+ /* @__PURE__ */ jsxRuntime.jsxs(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: [
21867
+ group.family.label,
21868
+ " backgrounds"
21869
+ ] }),
21870
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: group.label })
21871
+ ] }),
21872
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3", children: group.backgrounds.map((background) => /* @__PURE__ */ jsxRuntime.jsx(
21873
+ BackgroundSwatchButton3,
21874
+ {
21875
+ background,
21876
+ hasPairs: (context.pairsByBackground[background.token]?.length ?? 0) > 0,
21877
+ isSelected: selectedBackground.token === background.token,
21878
+ onClick: () => handleBackgroundChange(background.token)
21879
+ },
21880
+ background.token
21881
+ )) })
21882
+ ]
21883
+ },
21884
+ group.key
21885
+ )) }) }),
21886
+ /* @__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: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-sm border border-grey-200 bg-grey-50 px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
21887
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 4, size: 6, className: "text-foreground", trim: "normal", children: "Review the result on the right" }),
21888
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "The right panel shows one recommended pairing first. Use approved alternatives there only when you need a different tone or emphasis." })
21889
+ ] }) }) }) })
21890
+ ]
21891
+ }
21892
+ ) }),
21893
+ /* @__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: [
21894
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-10 flex-1", children: isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Review the NSW recommendation in the result panel. Use alternatives there only if you need a different approved treatment." }) : null }),
21895
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 sm:w-auto sm:flex-none", children: [
21896
+ isOverlay && isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsx(
21897
+ Button2,
21898
+ {
21899
+ color: "primary",
21900
+ className: "w-full sm:w-auto sm:min-w-40",
21901
+ onClick: () => setIsCompactControlsOpen(false),
21902
+ children: "Review result"
21903
+ }
21904
+ ) : null,
21905
+ !isLastDrawerStep ? /* @__PURE__ */ jsxRuntime.jsxs(Button2, { color: "primary", className: "w-full sm:w-auto", onClick: goToNextDrawerStep, children: [
21906
+ "Continue",
21907
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.east, { "data-slot": "icon", className: "size-5" })
21908
+ ] }) : null
21909
+ ] })
21910
+ ] }) })
21911
+ ] });
21912
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 xl:grid-cols-[minmax(18rem,24rem)_minmax(0,1fr)]", children: [
21913
+ /* @__PURE__ */ jsxRuntime.jsx(
21914
+ "div",
21915
+ {
21916
+ "data-slot": "tool-sidebar",
21917
+ className: "hidden xl:sticky xl:top-[var(--tool-sidebar-top)] xl:block xl:self-start",
21918
+ style: desktopSidebarStyle,
21919
+ children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "h-[40rem] max-h-[40rem] gap-0 overflow-hidden border-grey-200 bg-grey-50/60 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() })
21920
+ }
21921
+ ),
21922
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-slot": "tool-results", className: "space-y-5", children: [
21923
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4 xl:hidden", children: [
21924
+ /* @__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: [
21925
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
21926
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 5, className: "text-foreground", trim: "normal", children: "Configuration" }),
21927
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, children: "Open the drawer to set palette, colour families, and background. The result panel shows the NSW recommendation first." }),
21928
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: compactControlsSummary })
21929
+ ] }),
21930
+ /* @__PURE__ */ jsxRuntime.jsxs(
21931
+ Button2,
21932
+ {
21933
+ color: "primary",
21934
+ className: "w-full sm:w-auto",
21935
+ onClick: () => setIsCompactControlsOpen(true),
21936
+ children: [
21937
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.edit_square, { "data-slot": "icon", className: "size-5" }),
21938
+ "Open configuration"
21939
+ ]
21940
+ }
21941
+ )
21942
+ ] }) }),
21943
+ /* @__PURE__ */ jsxRuntime.jsx(Sheet, { open: isCompactControlsOpen, onOpenChange: setIsCompactControlsOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
21944
+ SheetContent,
21945
+ {
21946
+ side: "left",
21947
+ showClose: false,
21948
+ className: "w-[30rem] max-w-[90vw] overflow-hidden p-0",
21949
+ children: [
21950
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Colour pairing configuration" }),
21951
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full flex-col bg-background", children: renderControlsPanel(true) })
21952
+ ]
21953
+ }
21954
+ ) })
21955
+ ] }),
21956
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { ref: resultSectionRef, className: "space-y-5", "aria-label": "Current result", children: [
21957
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sr-only", "aria-live": "polite", children: liveAnnouncement }),
21958
+ /* @__PURE__ */ jsxRuntime.jsx(
21959
+ CurrentResultCard3,
21960
+ {
21961
+ bestPair: bestRecommendedPair,
21962
+ copiedKey,
21963
+ familySummary,
21964
+ onCopyPairing: () => previewPair ? copyValue(
21965
+ "current-pairing",
21966
+ getPairingCopyText3(previewPair),
21967
+ "Pairing copied",
21968
+ previewPair.id === bestRecommendedPair?.id ? {
21969
+ name: "best_recommendation_copied",
21970
+ ...buildAnalyticsContext({
21971
+ foregroundToken: previewPair.foreground.token,
21972
+ pairId: previewPair.id,
21973
+ source: "current-result"
21974
+ })
21975
+ } : void 0
21976
+ ) : void 0,
21977
+ pair: previewPair,
21978
+ supportText: currentPairSupportText,
21979
+ selectedBackground
21980
+ }
21981
+ )
21982
+ ] }),
21983
+ bestRecommendedPair || alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-3", children: [
21984
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
21985
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Approved alternatives" }),
21986
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-grey-600", children: "These are approved alternatives for different tone or emphasis." })
21987
+ ] }),
21988
+ alternativeRecommendationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21989
+ visibleAlternativeRecommendationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
21990
+ RecommendationGroupSection2,
21991
+ {
21992
+ title: group.title,
21993
+ description: group.description,
21994
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
21995
+ RecommendationCard3,
21996
+ {
21997
+ copiedKey,
21998
+ item,
21999
+ isSelected: item.pair.id === selectedPair?.id,
22000
+ onCopyPairing: () => copyValue(
22001
+ `pair:${item.pair.id}`,
22002
+ getPairingCopyText3(item.pair),
22003
+ "Pairing copied",
22004
+ item.pair.id === bestRecommendedPair?.id ? {
22005
+ name: "best_recommendation_copied",
22006
+ ...buildAnalyticsContext({
22007
+ foregroundToken: item.pair.foreground.token,
22008
+ pairId: item.pair.id,
22009
+ source: "recommendations-list"
22010
+ })
22011
+ } : void 0
22012
+ ),
22013
+ onSelect: () => handlePairChange(item.pair.id, "recommendations-list")
22014
+ },
22015
+ item.pair.id
22016
+ )) })
22017
+ },
22018
+ group.id
22019
+ )),
22020
+ hiddenAlternativeCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
22021
+ Button2,
22022
+ {
22023
+ variant: "ghost",
22024
+ color: "grey",
22025
+ className: "w-full justify-center border border-grey-200 bg-white sm:w-auto",
22026
+ onClick: () => setIsShowingAllAlternatives(true),
22027
+ children: [
22028
+ "Show ",
22029
+ hiddenAlternativeCount,
22030
+ " more"
22031
+ ]
22032
+ }
22033
+ ) : null
22034
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "px-6 py-6", children: [
22035
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "No other AAA alternatives" }),
22036
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "mt-3", children: "The NSW recommended pairing is the only AAA-compliant foreground option for this background." })
22037
+ ] })
22038
+ ] }) : null,
22039
+ /* @__PURE__ */ jsxRuntime.jsx("section", { className: "space-y-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Collapsible, { open: isTechnicalDetailsOpen, onOpenChange: setIsTechnicalDetailsOpen, children: [
22040
+ /* @__PURE__ */ jsxRuntime.jsx(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
22041
+ "button",
22042
+ {
22043
+ type: "button",
22044
+ className: "flex w-full items-center justify-between gap-4 rounded-sm border border-grey-200 bg-white px-4 py-3.5 text-left transition-colors hover:bg-grey-50 focus-visible:ring-2 focus-visible:ring-primary-700 focus-visible:ring-offset-2 focus-visible:outline-hidden sm:px-5",
22045
+ children: [
22046
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
22047
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 2, size: 6, className: "text-foreground", trim: "normal", children: "Technical colour values" }),
22048
+ /* @__PURE__ */ jsxRuntime.jsx(Text, { size: 2, className: "text-muted-foreground", children: "Token, tone, HEX, RGB, HSL, and OKLCH values for advanced use." })
22049
+ ] }),
22050
+ /* @__PURE__ */ jsxRuntime.jsxs(
22051
+ "span",
22052
+ {
22053
+ className: cn(
22054
+ "inline-flex items-center gap-2 text-sm font-semibold text-primary-800",
22055
+ isTechnicalDetailsOpen && "text-foreground"
22056
+ ),
22057
+ children: [
22058
+ isTechnicalDetailsOpen ? "Hide" : "Show",
22059
+ /* @__PURE__ */ jsxRuntime.jsx(
22060
+ Icons.keyboard_arrow_down,
22061
+ {
22062
+ "data-slot": "icon",
22063
+ className: cn(
22064
+ "size-5 transition-transform",
22065
+ isTechnicalDetailsOpen && "rotate-180"
22066
+ )
22067
+ }
22068
+ )
22069
+ ]
22070
+ }
22071
+ )
22072
+ ]
22073
+ }
22074
+ ) }),
22075
+ /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [
22076
+ /* @__PURE__ */ jsxRuntime.jsx(
22077
+ TechnicalDetailsPanel3,
22078
+ {
22079
+ title: "Background values",
22080
+ color: selectedBackground,
22081
+ visibleFormats,
22082
+ copiedKey,
22083
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
22084
+ }
22085
+ ),
22086
+ /* @__PURE__ */ jsxRuntime.jsx(
22087
+ TechnicalDetailsPanel3,
22088
+ {
22089
+ title: "Foreground values",
22090
+ color: detailForeground,
22091
+ visibleFormats,
22092
+ copiedKey,
22093
+ onCopyValue: (copyKey, value, toastLabel) => copyValue(copyKey, value, toastLabel)
22094
+ }
22095
+ )
22096
+ ] }) }) })
22097
+ ] }) }),
22098
+ /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-1.5", children: [
22099
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { level: 3, size: 6, className: "text-foreground", trim: "normal", children: "Share colour pairing" }),
22100
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-sm border border-grey-200 bg-white px-4 py-3.5", children: [
22101
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
22102
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Copy a link to this current result." }),
22103
+ /* @__PURE__ */ jsxRuntime.jsx(
22104
+ Button2,
22105
+ {
22106
+ variant: "ghost",
22107
+ color: "grey",
22108
+ size: "sm",
22109
+ className: "shrink-0 self-start sm:self-center",
22110
+ onClick: () => copyValue(
22111
+ "share-url",
22112
+ typeof window === "undefined" ? shareUrl : new URL(shareUrl, window.location.origin).toString(),
22113
+ "Colour pairing link copied"
22114
+ ),
22115
+ "aria-label": copiedKey === "share-url" ? "Colour pairing URL copied to clipboard" : "Copy colour pairing URL to clipboard",
22116
+ title: copiedKey === "share-url" ? "Copied" : "Copy URL",
22117
+ children: copiedKey === "share-url" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
22118
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.check, { "data-slot": "icon", className: "size-5" }),
22119
+ "Copied"
22120
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
22121
+ /* @__PURE__ */ jsxRuntime.jsx(Icons.content_copy, { "data-slot": "icon", className: "size-5" }),
22122
+ "Copy URL"
22123
+ ] })
22124
+ }
22125
+ )
22126
+ ] }),
22127
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "mt-2.5 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 })
22128
+ ] })
22129
+ ] })
22130
+ ] })
22131
+ ] });
22132
+ }
22133
+ function ColorPairingToolV5({
22134
+ onAnalyticsEvent = () => {
22135
+ },
22136
+ visibleFormats = DEFAULT_VISIBLE_FORMATS5
22137
+ } = {}) {
22138
+ const normalizedVisibleFormats = [...new Set(visibleFormats)];
22139
+ return /* @__PURE__ */ jsxRuntime.jsx(React5.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(ColorPairingToolV5Loading, {}), children: /* @__PURE__ */ jsxRuntime.jsx(
22140
+ ColorPairingToolV5Content,
22141
+ {
22142
+ onAnalyticsEvent,
22143
+ visibleFormats: normalizedVisibleFormats
22144
+ }
22145
+ ) });
22146
+ }
20585
22147
  function ColorSwatches({ theme: theme2, format, viewMode }) {
20586
22148
  return /* @__PURE__ */ jsxRuntime.jsx(
20587
22149
  "div",
@@ -23206,7 +24768,7 @@ function FormatToggle({ format, setFormat }) {
23206
24768
 
23207
24769
  // package.json
23208
24770
  var package_default = {
23209
- version: "1.104.0"};
24771
+ version: "1.105.0"};
23210
24772
  function Logo(props) {
23211
24773
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
23212
24774
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "NSW Government" }),
@@ -39190,6 +40752,7 @@ exports.ColorPairingTool = ColorPairingTool;
39190
40752
  exports.ColorPairingToolV2 = ColorPairingToolV2;
39191
40753
  exports.ColorPairingToolV3 = ColorPairingToolV3;
39192
40754
  exports.ColorPairingToolV4 = ColorPairingToolV4;
40755
+ exports.ColorPairingToolV5 = ColorPairingToolV5;
39193
40756
  exports.ColorSwatches = ColorSwatches;
39194
40757
  exports.ColourScale = ColourScale;
39195
40758
  exports.ComboChart = ComboChart;