@thewhatmatters/wmds 0.4.34 → 0.4.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/colors.css +23 -8
  3. package/dist/components/molecules/CalEmbed/CalEmbed.d.ts +6 -6
  4. package/dist/components/molecules/CalEmbed/CalEmbed.d.ts.map +1 -1
  5. package/dist/components/molecules/CalEmbed/CalEmbed.js +20 -15
  6. package/dist/components/molecules/IntakeForm/IntakeHoneypot.d.ts +17 -0
  7. package/dist/components/molecules/IntakeForm/IntakeHoneypot.d.ts.map +1 -0
  8. package/dist/components/molecules/IntakeForm/IntakeHoneypot.js +29 -0
  9. package/dist/components/organisms/IntakeConfirmation/IntakeConfirmation.d.ts +14 -2
  10. package/dist/components/organisms/IntakeConfirmation/IntakeConfirmation.d.ts.map +1 -1
  11. package/dist/components/organisms/IntakeConfirmation/IntakeConfirmation.js +38 -33
  12. package/dist/components/organisms/IntakeConfirmation/intakeConfirmationStyles.d.ts +6 -2
  13. package/dist/components/organisms/IntakeConfirmation/intakeConfirmationStyles.d.ts.map +1 -1
  14. package/dist/components/organisms/IntakeConfirmation/intakeConfirmationStyles.js +3 -3
  15. package/dist/components/organisms/IntakeModal/IntakeModal.d.ts +11 -2
  16. package/dist/components/organisms/IntakeModal/IntakeModal.d.ts.map +1 -1
  17. package/dist/components/organisms/IntakeModal/IntakeModal.js +91 -59
  18. package/dist/components/organisms/IntakeModal/intakeModalStyles.d.ts +3 -3
  19. package/dist/components/organisms/IntakeModal/intakeModalStyles.d.ts.map +1 -1
  20. package/dist/components/organisms/IntakeModal/intakeModalStyles.js +1 -1
  21. package/dist/components/organisms/IntakeModal/useIntakeUrlState.d.ts +12 -0
  22. package/dist/components/organisms/IntakeModal/useIntakeUrlState.d.ts.map +1 -0
  23. package/dist/components/organisms/IntakeModal/useIntakeUrlState.js +16 -0
  24. package/dist/index.d.ts +3 -1
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +82 -80
  27. package/dist/stateColors.css +5 -5
  28. package/dist/styles.css +1 -1
  29. package/dist/theme.css +3 -1
  30. package/docs/components.md +1 -1
  31. package/docs/exports.json +2 -2
  32. package/docs/patterns/components-accordion--flush.tsx +1 -1
  33. package/docs/patterns/components-appshell--portal-dashboard-pattern.tsx +1 -1
  34. package/docs/patterns/components-avatar--dropdown-row.tsx +1 -1
  35. package/docs/patterns/components-badge--outline-tags.tsx +1 -1
  36. package/docs/patterns/components-badge--status-pill.tsx +1 -1
  37. package/docs/patterns/components-badge--with-avatar.tsx +1 -1
  38. package/docs/patterns/components-band--page-in-bands.tsx +1 -1
  39. package/docs/patterns/components-breadcrumb--editorial.tsx +1 -1
  40. package/docs/patterns/components-breadcrumb--long-path.tsx +1 -1
  41. package/docs/patterns/components-breadcrumb--path.tsx +1 -1
  42. package/docs/patterns/components-breadcrumb--router-links.tsx +1 -1
  43. package/docs/patterns/components-button-button--copy-button.tsx +1 -1
  44. package/docs/patterns/components-button-button--destructive-action.tsx +1 -1
  45. package/docs/patterns/components-button-button--external-link.tsx +1 -1
  46. package/docs/patterns/components-button-button--ghost-action.tsx +1 -1
  47. package/docs/patterns/components-button-button--inverse-action.tsx +1 -1
  48. package/docs/patterns/components-button-button--link-render.tsx +1 -1
  49. package/docs/patterns/components-button-button--multi-state-badge.tsx +1 -1
  50. package/docs/patterns/components-button-button--outline-mono.tsx +1 -1
  51. package/docs/patterns/components-button-button--primary-action.tsx +1 -1
  52. package/docs/patterns/components-button-button--row-hug.tsx +1 -1
  53. package/docs/patterns/components-button-button--row-layout.tsx +1 -1
  54. package/docs/patterns/components-button-button--secondary-action.tsx +1 -1
  55. package/docs/patterns/components-button-button--suggestion-pills.tsx +1 -1
  56. package/docs/patterns/components-button-button--with-count.tsx +1 -1
  57. package/docs/patterns/components-button-button--with-icon.tsx +1 -1
  58. package/docs/patterns/components-button-floatingactionbutton--vertical-actions.tsx +1 -1
  59. package/docs/patterns/components-calembed--pattern-skip-above.tsx +16 -0
  60. package/docs/patterns/components-card-card--body-slot-occupancy-history.tsx +1 -1
  61. package/docs/patterns/components-card-card--headerless-media.tsx +1 -1
  62. package/docs/patterns/components-card-card--outlined-layout.tsx +1 -1
  63. package/docs/patterns/components-card-card--pinned-height.tsx +1 -1
  64. package/docs/patterns/components-card-card--terminal-frame.tsx +1 -1
  65. package/docs/patterns/components-card-selectablecard--selectable-cards-pattern.tsx +1 -1
  66. package/docs/patterns/components-carousel--image-carousel.tsx +1 -1
  67. package/docs/patterns/components-chart--audience-activity-heatmap.tsx +1 -1
  68. package/docs/patterns/components-chart--cartesian-no-data-gaps.tsx +1 -1
  69. package/docs/patterns/components-chart--occupancy-history-in-card.tsx +1 -1
  70. package/docs/patterns/components-chart--occupancy-in-card.tsx +1 -1
  71. package/docs/patterns/components-chart--post-reach-distribution.tsx +1 -1
  72. package/docs/patterns/components-chart--ranked-audience-breakdown.tsx +1 -1
  73. package/docs/patterns/components-chart--revenue-by-line.tsx +1 -1
  74. package/docs/patterns/components-chart--segmented-ring-pattern.tsx +1 -1
  75. package/docs/patterns/components-chart--unit-grid-composition.tsx +1 -1
  76. package/docs/patterns/components-chatdock--pattern-chat-dock.tsx +1 -1
  77. package/docs/patterns/components-chatdock--pattern-start-project-gate.tsx +1 -1
  78. package/docs/patterns/components-chatqa--pattern-qa-with-reply.tsx +1 -1
  79. package/docs/patterns/components-checkbox-checkbox--default.tsx +1 -1
  80. package/docs/patterns/components-checkbox-checkbox--with-count.tsx +1 -1
  81. package/docs/patterns/components-checkbox-checkbox--with-description.tsx +1 -1
  82. package/docs/patterns/components-checkbox-checkboxgroup--default.tsx +1 -1
  83. package/docs/patterns/components-checkbox-checkboxgroup--option-counts.tsx +1 -1
  84. package/docs/patterns/components-copyfield--clipboard-blocked.tsx +1 -1
  85. package/docs/patterns/components-copyfield--copied.tsx +1 -1
  86. package/docs/patterns/components-copyfield--copy-key.tsx +1 -1
  87. package/docs/patterns/components-copyfield--on-navy.tsx +1 -1
  88. package/docs/patterns/components-descriptionlist--details.tsx +1 -1
  89. package/docs/patterns/components-descriptionlist--post-metadata.tsx +1 -1
  90. package/docs/patterns/components-dialog--alert-dialog-destructive.tsx +1 -1
  91. package/docs/patterns/components-dialog--alert-dialog-typed-confirmation.tsx +1 -1
  92. package/docs/patterns/components-dialog--default-dialog.tsx +1 -1
  93. package/docs/patterns/components-dialog--form-dialog.tsx +1 -1
  94. package/docs/patterns/components-displaycontrols--page-utilities.tsx +1 -1
  95. package/docs/patterns/components-displaycontrols--theme-switch.tsx +1 -1
  96. package/docs/patterns/components-errorsummary--contact-form.tsx +1 -1
  97. package/docs/patterns/components-field--horizontal-input.tsx +1 -1
  98. package/docs/patterns/components-field--horizontal-text-area.tsx +1 -1
  99. package/docs/patterns/components-field--multi-control.tsx +1 -1
  100. package/docs/patterns/components-filterpanel--panel.tsx +1 -1
  101. package/docs/patterns/components-footerreveal--marketing-hero-pattern.tsx +1 -1
  102. package/docs/patterns/components-footerreveal--marketing-hero-ruled-pattern.tsx +1 -1
  103. package/docs/patterns/components-footerreveal--marketing-hero-with-gallery-intro.tsx +1 -1
  104. package/docs/patterns/components-footerreveal--marketing-page-pattern.tsx +1 -1
  105. package/docs/patterns/components-footerreveal--ruled-grid-footer-pattern.tsx +1 -1
  106. package/docs/patterns/components-footerreveal--sequenced-marketing-hero.tsx +1 -1
  107. package/docs/patterns/components-herointro--two-line-intro.tsx +1 -1
  108. package/docs/patterns/components-herointro--with-actions.tsx +1 -1
  109. package/docs/patterns/components-herotilestack--marketing-hero-pattern.tsx +1 -1
  110. package/docs/patterns/components-herotilestack--marketing-hero-text-sequence.tsx +1 -1
  111. package/docs/patterns/components-herotilestack--marketing-hero-with-gallery-intro.tsx +1 -1
  112. package/docs/patterns/components-indexlist--post-index.tsx +1 -1
  113. package/docs/patterns/components-intakeconfirmation--booked-pattern.tsx +1 -1
  114. package/docs/patterns/components-intakeconfirmation--emailed-pattern.tsx +8 -2
  115. package/docs/patterns/components-intakeform--about-you-pattern.tsx +1 -1
  116. package/docs/patterns/components-intakeform--short-form-pattern.tsx +1 -1
  117. package/docs/patterns/components-intakemodal--intake-modal-pattern.tsx +2 -2
  118. package/docs/patterns/components-kbd--command-row.tsx +1 -1
  119. package/docs/patterns/components-kbd--numbered-choices.tsx +1 -1
  120. package/docs/patterns/components-kbd--shortcut.tsx +1 -1
  121. package/docs/patterns/components-linktile--resource-tile.tsx +1 -1
  122. package/docs/patterns/components-linktile--router-link.tsx +1 -1
  123. package/docs/patterns/components-logview--detail-pane.tsx +1 -1
  124. package/docs/patterns/components-logview--log-viewer.tsx +1 -1
  125. package/docs/patterns/components-moremenu--action-menu.tsx +1 -1
  126. package/docs/patterns/components-moremenu--in-card-header.tsx +1 -1
  127. package/docs/patterns/components-navlist--app-sidebar.tsx +1 -1
  128. package/docs/patterns/components-navlist--side-nav-settings.tsx +1 -1
  129. package/docs/patterns/components-pageheader--app-header-pattern.tsx +1 -1
  130. package/docs/patterns/components-pageheader--page-section-header.tsx +1 -1
  131. package/docs/patterns/components-pageheader--toolbar-header.tsx +1 -1
  132. package/docs/patterns/components-panel--end-detail-rail.tsx +1 -1
  133. package/docs/patterns/components-pillgroup--pill-group-pattern.tsx +1 -1
  134. package/docs/patterns/components-promptbar--pattern-prompt-bar.tsx +1 -1
  135. package/docs/patterns/components-prose--article-body.tsx +1 -1
  136. package/docs/patterns/components-radio-radiogroup--default.tsx +1 -1
  137. package/docs/patterns/components-scrollhorizontal--project-gallery-pattern.tsx +1 -1
  138. package/docs/patterns/components-scrollhorizontal--with-intro.tsx +1 -1
  139. package/docs/patterns/components-sectioncaption--column-caption.tsx +1 -1
  140. package/docs/patterns/components-sectioncaption--with-action.tsx +1 -1
  141. package/docs/patterns/components-sheet--bottom-sheet.tsx +1 -1
  142. package/docs/patterns/components-sheet--end-sheet.tsx +1 -1
  143. package/docs/patterns/components-sheet--side-sheet-header-actions.tsx +1 -1
  144. package/docs/patterns/components-sheet--side-sheet-url-deep-link.tsx +1 -1
  145. package/docs/patterns/components-sheet--side-sheet.tsx +1 -1
  146. package/docs/patterns/components-sitenav--brand-and-cta.tsx +1 -1
  147. package/docs/patterns/components-sitenav--centered-links.tsx +1 -1
  148. package/docs/patterns/components-sitenav--compact.tsx +1 -1
  149. package/docs/patterns/components-sitenav--marketing-header.tsx +1 -1
  150. package/docs/patterns/components-sitenav--mega-menu.tsx +1 -1
  151. package/docs/patterns/components-stat--hero-stat.tsx +1 -1
  152. package/docs/patterns/components-stat--insights-row.tsx +1 -1
  153. package/docs/patterns/components-stepprogress--step-progress-pattern.tsx +1 -1
  154. package/docs/patterns/components-switch--default.tsx +1 -1
  155. package/docs/patterns/components-switch--settings-row.tsx +1 -1
  156. package/docs/patterns/components-tab--settings-pages.tsx +1 -1
  157. package/docs/patterns/components-table--approvals-with-sheet.tsx +1 -1
  158. package/docs/patterns/components-table--approvals.tsx +1 -1
  159. package/docs/patterns/components-table--basic.tsx +1 -1
  160. package/docs/patterns/components-taskrows--action-details.tsx +1 -1
  161. package/docs/patterns/components-taskrows--capsules.tsx +1 -1
  162. package/docs/patterns/components-taskrows--card-with-status-rows.tsx +1 -1
  163. package/docs/patterns/components-taskrows--controlled-expand.tsx +1 -1
  164. package/docs/patterns/components-taskrows--custom-slots.tsx +1 -1
  165. package/docs/patterns/components-taskrows--needs-you-table.tsx +1 -1
  166. package/docs/patterns/components-taskrows--status-list.tsx +1 -1
  167. package/docs/patterns/components-taskrows--tag-chips.tsx +1 -1
  168. package/docs/patterns/components-textarea--save-status.tsx +1 -1
  169. package/docs/patterns/components-textlink--external-destination.tsx +1 -1
  170. package/docs/patterns/components-textlink--inline-prose.tsx +1 -1
  171. package/docs/patterns/components-textlink--quiet-title.tsx +1 -1
  172. package/docs/patterns/components-textlink--supporting-copy.tsx +1 -1
  173. package/docs/patterns/components-textsequence--default.tsx +1 -1
  174. package/docs/patterns/components-textsequence--reduced-motion.tsx +1 -1
  175. package/docs/patterns/components-textsequence--shapes.tsx +1 -1
  176. package/docs/patterns/components-tilegrid--masonry.tsx +1 -1
  177. package/docs/patterns/components-toast--stacked-notifications.tsx +1 -1
  178. package/docs/patterns/components-tooltip--controlled.tsx +1 -1
  179. package/docs/patterns/components-tooltip--disabled-control.tsx +1 -1
  180. package/docs/patterns/components-tooltip--icon-action.tsx +1 -1
  181. package/docs/patterns/components-tooltip--keyboard-shortcut.tsx +1 -1
  182. package/docs/patterns/components-tooltip--placement.tsx +1 -1
  183. package/docs/patterns/foundations-scroll-fade--horizontal-rail.tsx +1 -1
  184. package/docs/patterns/foundations-scroll-fade--overflowing-list.tsx +1 -1
  185. package/docs/patterns/guides-chart-explorations--comparison-gallery.tsx +1 -1
  186. package/docs/patterns/guides-filter-panel--filtered-grid.tsx +1 -1
  187. package/docs/patterns/guides-filter-panel--filtered-index.tsx +1 -1
  188. package/docs/patterns/guides-overlay-flows--notification-preferences.tsx +1 -1
  189. package/docs/patterns/guides-post-page--post-page.tsx +1 -1
  190. package/docs/patterns/guides-profile-typography--editorial-profile.tsx +1 -1
  191. package/docs/patterns/guides-resource-detail--detail.tsx +1 -1
  192. package/docs/patterns/index.json +5 -5
  193. package/package.json +1 -1
  194. package/docs/patterns/components-calembed--pattern-skip-in-footer.tsx +0 -25
package/CHANGELOG.md CHANGED
@@ -7,6 +7,47 @@ Every release of `@thewhatmatters/wmds` is listed here, newest first.
7
7
  - **Pasted patterns:** when a release changes a **Pattern — …** story's Show code, it is named under Consumer actions so apps re-copy it.
8
8
  - **How to add an entry** (contributors): add your change to the top entry. If that version is already on npm (`npm view @thewhatmatters/wmds versions`), start a new entry above it and bump `version` in `package.json` to match. `npm run check:changelog` enforces the format.
9
9
 
10
+ ## 0.4.36
11
+
12
+ **Colour fixes from building every component in light and dark: fills that vanished, the navy on the dark body, invalid hovers, and a primary Button on a band.**
13
+
14
+ - **`--color-accent-muted`** (and `--color-secondary`, which reads it): `#ebebeb` light (was the body's `#f8f8f8`), `#363636` dark (was the surface's `#262626`). The selected NavList pill, empty StepProgress segments, secondary Badges and Buttons, the AppShell avatar, Chips, and the Dropdown and Select item hover now show on the body and the surface.
15
+ - **`--color-brand` in dark** is `#5566e0`, the navy's hue lifted (was `#011272`, 1.09:1 on the dark body): 3.58:1 on the body, 3.14:1 on the surface, white on it 4.81:1. The PromptBar send button, the selected SelectableCard border, the filled StepProgress segment, FooterReveal, TextSequence and TextSequenceShape marks now read in dark. **`--color-brand-surface` defaults to `#011272` itself** (it was `var(--color-brand)`), so `tone="inverse"` bands keep the deep navy in dark, and a client's own brand surface still wins.
16
+ - **Dark status hovers:** `--color-{error,success,warning,info}-hover` mixed `108%` with white, which is invalid, so the browser dropped them. They're `88%` with white now, the same lift as the primary.
17
+ - **Primary on a field band:** inside `tone="field"`, `--color-primary` inverts to the field's ink with the field colour as its label (Randy, 2026-10-29). A primary Button on a field band was the band's own colour, since the field defaults to the primary. Inverse bands are unchanged (they take the dark, or the client's dark, primary).
18
+ - **Type scale metadata:** `astryxTypeScale` lists display line heights 1.05 / 1.1 / 1.15, matching typography.css (it said 1.15 / 1.2 / 1.24).
19
+ - **FooterReveal.Ruled** in dark keeps the deep navy ink on its white field.
20
+ - Tests: no `color-mix` above 100%; the secondary fill separates from body and surface in both themes; the dark brand's contrast; the field primary inversion; the type metadata matches the CSS.
21
+
22
+ ### Consumer actions
23
+
24
+ - None required. Look at dark mode where you use `bg-brand` / `text-brand` as a large field: it's the lighter `#5566e0` now. Use `--color-brand-surface` (or a `tone="inverse"` Band) for a deep navy section in dark.
25
+ - If your brand stylesheet sets `--color-brand` for dark, keep it at 3:1 or more on `--color-background-body` and white at 4.5:1 or more on it.
26
+
27
+ ## 0.4.35
28
+
29
+ **Contact and booking forms: two steps, booking after the request, a way out above the calendar, and nothing lost on close.**
30
+
31
+ - **IntakeModal** (Contact and booking forms T7, T9):
32
+ - Two steps by default (`steps` was 4): details, then the optional booking. The confirmation isn't counted.
33
+ - New `hasAnswers`: with typed answers, Close and Escape ask "Discard your answers?" (Keep editing, focused / Discard).
34
+ - New **useIntakeUrlState**: keeps `?sketch` in the URL while the modal is open. The link can be shared, a refresh reopens it, and Back closes it.
35
+ - **CalEmbed** (T8): the "Skip, just email me" link sits **above** the calendar, so on a phone it's visible without scrolling past the month. With no embed (not set up, or it failed), the email route shows inside the empty state straight away.
36
+ - **CalEmbed stories:** "Pattern — skip in footer" is replaced by **Pattern — skip above the calendar** (`CalEmbed.Skip` in `Card.Header`). The pasted pattern id changes, so `wmds-check` reports `pattern-removed` for copies of the old one: move the skip above the calendar.
37
+ - **IntakeConfirmation** (T2, T3): one "what happens next and when" sentence: `email` and `replyWithin` (default "within one business day") give "We'll email you at {email} within one business day with a few times that fit."; the booked variant names `bookingTime` in it. `summary` shows as "You told us: “…”". Then `contact`, then Done. New export `intakeConfirmationReplyWithin`.
38
+ - **IntakeModal**: no Back on step 1; the WM mark and wordmark take the ink in dark mode (navy on near-black failed 3:1).
39
+ - **IntakeHoneypot** and `isIntakeHoneypotFilled` (new, T4): a spam trap people never see or reach (`aria-hidden`, `tabindex="-1"`, no autofill). Drop requests where it's filled, on the server, with rate limits. No CAPTCHA.
40
+ - Stories **Components/IntakeModal → Pattern — sketch request** (details → optional booking → confirmation; "Send my request"; reply time under the form; contact details on the confirmation) and **Pattern — send failed** (answers kept, Try again, email route; T5, T6). Interaction tests cover the URL, the discard question, both steps, Back keeping answers, the skip above the calendar, the failure and the honeypot.
41
+
42
+ ### Consumer actions
43
+
44
+ - Pass `steps={2}` or drop `steps`, and move the booking after the details are sent.
45
+ - Pass `hasAnswers` while the visitor has typed something, and keep answers in your state.
46
+ - Open the modal with `useIntakeUrlState`, and give the form its own page too (see wmds-patterns Contact — Sketch Page).
47
+ - Add **IntakeHoneypot** and check it on the server.
48
+ - On the confirmation, pass `summary` and `contact`. Pass `email` so the sentence names it, and change `replyWithin` if one business day isn't true for you.
49
+ - If you placed `CalEmbed.Skip` after the calendar (for example in `Card.Footer`), move it to `Card.Header`, above the calendar.
50
+
10
51
  ## 0.4.34
11
52
 
12
53
  **Required and optional fields: mark the exception, read the badge with the field, never on autofill. Field width and form layout: widths that hint at the answer, a State select, side labels only on wide screens, and counters that don't cut text. Dropdowns, radios and checkboxes: a native Select for forms, bigger boxes with visible borders, and errors on Continue.**
package/dist/colors.css CHANGED
@@ -28,7 +28,12 @@
28
28
 
29
29
  /* Accent (neutral UI chrome — not brand) */
30
30
  --color-accent: #262626;
31
- --color-accent-muted: #f8f8f8;
31
+ /*
32
+ * `--color-secondary` (selected pills, empty progress segments, secondary badges, item hover).
33
+ * It must differ from both the body (#f8f8f8) and the surface (#fff), or those fills vanish:
34
+ * #ebebeb is 1.12:1 on the body and 1.19:1 on the surface.
35
+ */
36
+ --color-accent-muted: #ebebeb;
32
37
  --color-on-accent: #ffffff;
33
38
 
34
39
  /* Overlays & neutral fills */
@@ -114,7 +119,8 @@
114
119
  * - field: a saturated section colour (`tone="field"`). Default: the primary.
115
120
  * `*-muted` is the secondary text step on that colour; it must clear 4.5:1 too.
116
121
  */
117
- --color-brand-surface: var(--color-brand);
122
+ /* The navy itself, not var(--color-brand): the dark brand is lifted for dark grounds, and a dark section stays deep. */
123
+ --color-brand-surface: #011272;
118
124
  --color-on-brand-surface: var(--color-on-brand);
119
125
  --color-field: var(--color-primary);
120
126
  --color-on-field: var(--color-on-primary);
@@ -189,7 +195,8 @@
189
195
  --color-text-accent: #ebebeb;
190
196
 
191
197
  --color-accent: #ebebeb;
192
- --color-accent-muted: #262626;
198
+ /* Off the body (#1b1b1b, 1.43:1) and the surface (#262626, 1.26:1), so fills and item hover show on both. */
199
+ --color-accent-muted: #363636;
193
200
  --color-on-accent: #171717;
194
201
 
195
202
  --color-neutral: #ffffff1a;
@@ -226,11 +233,11 @@
226
233
  --color-on-primary: #fafaf8;
227
234
 
228
235
  /*
229
- * The field stays #011272. That navy on #1b1b1b is 1.09:1 and on #262626 is 1.04:1,
230
- * so it cannot be the hand outline. `--color-brand-outline` is 45% navy / 55% white
231
- * (about #8d94c0): 5.1:1 on #262626 and 5.8:1 on #1b1b1b.
236
+ * #011272 on #1b1b1b is 1.09:1, so the dark brand is the same navy hue lifted to #5566e0:
237
+ * 3.58:1 on the body and 3.14:1 on the surface (marks, borders, fills), and white on it is 4.81:1
238
+ * (send button, selected pill). Inverse bands keep the deep navy (`--color-brand-surface` is #011272 on :root).
232
239
  */
233
- --color-brand: #011272;
240
+ --color-brand: #5566e0;
234
241
  --color-on-brand: #ffffff;
235
242
  --color-brand-outline: color-mix(in srgb, var(--color-brand) 45%, white);
236
243
  --color-brand-soft: color-mix(in srgb, var(--color-on-brand) 40%, var(--color-brand));
@@ -338,7 +345,15 @@
338
345
  /* Default: the ink itself, since a lighter step on a mid-tone field would fall under 4.5:1. */
339
346
  --tone-muted: var(--color-on-field-muted, var(--color-on-field));
340
347
  /* A tinted card would pull a mid-tone field under 4.5:1, so cards sit flat on the field. */
341
- --tone-raised: var(--tone-bg);
348
+ --tone-raised: var(--tone-bg); /*
349
+ * The field defaults to the primary, so a primary Button would vanish into it. On a field the primary
350
+ * inverts: the field's ink as the fill, the field colour as the label (Randy, 2026-10-29).
351
+ * Inverse bands keep the primary: they carry data-theme="dark", so it takes the dark (or client's dark) value.
352
+ */
353
+ --color-primary: var(--tone-fg);
354
+ --color-on-primary: var(--tone-bg);
355
+ --color-primary-hover: color-mix(in srgb, var(--tone-fg) 88%, var(--tone-bg));
356
+ --color-primary-active: color-mix(in srgb, var(--tone-fg) 80%, var(--tone-bg));
342
357
  }
343
358
 
344
359
  [data-tone="inverse"],
@@ -4,7 +4,7 @@ export type CalEmbedLayoutClassName = string;
4
4
  export declare const calEmbedSkipHref = "#email";
5
5
  export declare const calEmbedSkipLabel = "Skip, just email me";
6
6
  export declare const calEmbedEmptyTitle = "Booking isn\u2019t available right now";
7
- export declare const calEmbedEmptyDescription = "Skip this step and we\u2019ll follow up by email.";
7
+ export declare const calEmbedEmptyDescription = "We\u2019ll follow up by email with a few times instead.";
8
8
  export interface CalEmbedSkipProps {
9
9
  /** Skip destination. Default `#email`. */
10
10
  skipHref?: string;
@@ -26,10 +26,10 @@ export interface CalEmbedProps {
26
26
  /** Empty-state supporting line. Default points visitors at the skip. */
27
27
  emptyDescription?: ReactNode;
28
28
  /**
29
- * Skip slot. Omit to render the default **TextLink** after the frame.
30
- * Pass `false` or **CalEmbed.Skip** when you place the skip yourself
31
- * (typically **Card.Footer**). CalEmbed does not render an in-body skip
32
- * when this slot is used.
29
+ * Skip slot. Omit to render the default **TextLink** above the frame (or inside the empty state).
30
+ * Pass `false` or **CalEmbed.Skip** when you place the skip yourself. Keep it visible without
31
+ * scrolling past the calendar at 390 (T8): above the frame or in a pinned footer, not after a month
32
+ * grid. CalEmbed does not render an in-body skip when this slot is used.
33
33
  */
34
34
  skip?: ReactNode | false;
35
35
  /** Skip destination when the in-body skip is shown. Default `#email`. */
@@ -41,7 +41,7 @@ export interface CalEmbedProps {
41
41
  className?: CalEmbedLayoutClassName;
42
42
  }
43
43
  /**
44
- * Same **TextLink** CalEmbed uses after the frame. Place it in **Card.Footer**
44
+ * Same **TextLink** CalEmbed uses above the frame. Place it in **Card.Header** (above the calendar, T8)
45
45
  * and pass `skip={false}` (or `skip={<CalEmbed.Skip />}`) so the in-body link is omitted.
46
46
  */
47
47
  export declare function CalEmbedSkip({ skipHref, skipLabel, onSkip, className, }: CalEmbedSkipProps): import("react").JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"CalEmbed.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/CalEmbed/CalEmbed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,OAAO,CAAC;AAUnD,qCAAqC;AACrC,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AACvD,eAAO,MAAM,kBAAkB,2CAAsC,CAAC;AACtE,eAAO,MAAM,wBAAwB,sDAAiD,CAAC;AAEvF,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAA2B,EAC3B,SAA6B,EAC7B,MAAM,EACN,SAAS,GACV,EAAE,iBAAiB,+BAWnB;AAED;;;;GAIG;AACH,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,UAA+B,EAC/B,gBAA2C,EAC3C,IAAI,EACJ,QAA2B,EAC3B,SAA6B,EAC7B,MAAM,EACN,SAAS,GACV,EAAE,aAAa,+BAkBf;AAED,eAAO,MAAM,QAAQ;;CAEnB,CAAC"}
1
+ {"version":3,"file":"CalEmbed.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/CalEmbed/CalEmbed.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,OAAO,CAAC;AAUnD,qCAAqC;AACrC,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE7C,eAAO,MAAM,gBAAgB,WAAW,CAAC;AACzC,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AACvD,eAAO,MAAM,kBAAkB,2CAAsC,CAAC;AACtE,eAAO,MAAM,wBAAwB,4DAAuD,CAAC;AAE7F,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAED,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iGAAiG;IACjG,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IACzB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,uBAAuB,CAAC;CACrC;AAcD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAA2B,EAC3B,SAA6B,EAC7B,MAAM,EACN,SAAS,GACV,EAAE,iBAAiB,+BAWnB;AAED;;;;GAIG;AACH,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,UAA+B,EAC/B,gBAA2C,EAC3C,IAAI,EACJ,QAA2B,EAC3B,SAA6B,EAC7B,MAAM,EACN,SAAS,GACV,EAAE,aAAa,+BAsBf;AAED,eAAO,MAAM,QAAQ;;CAEnB,CAAC"}
@@ -5,7 +5,7 @@ import { TextLink as n } from "../../atoms/TextLink/TextLink.js";
5
5
  import { calEmbedClasses as r, calEmbedEmptyClasses as i, calEmbedFrameClasses as a } from "./calEmbedStyles.js";
6
6
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
7
  //#region src/components/molecules/CalEmbed/CalEmbed.tsx
8
- var c = "#email", l = "Skip, just email me", u = "Booking isn’t available right now", d = "Skip this step and we’ll follow up by email.";
8
+ var c = "#email", l = "Skip, just email me", u = "Booking isn’t available right now", d = "We’ll follow up by email with a few times instead.";
9
9
  function f(e) {
10
10
  return e != null && e !== !1 && e !== "";
11
11
  }
@@ -22,27 +22,32 @@ function m({ skipHref: e = c, skipLabel: t = l, onSkip: r, className: i }) {
22
22
  });
23
23
  }
24
24
  function h({ children: n, emptyTitle: p = u, emptyDescription: h = d, skip: g, skipHref: _ = c, skipLabel: v = l, onSkip: y, className: b }) {
25
+ let x = f(n), S = g === void 0 ? /* @__PURE__ */ o(m, {
26
+ skipHref: _,
27
+ skipLabel: v,
28
+ onSkip: y
29
+ }) : null;
25
30
  return /* @__PURE__ */ s("div", {
26
31
  className: e(r, b),
27
32
  "data-cal-embed": "",
28
- children: [/* @__PURE__ */ o("div", {
33
+ children: [x ? S : null, /* @__PURE__ */ o("div", {
29
34
  className: a,
30
- children: f(n) ? n : /* @__PURE__ */ s("div", {
35
+ children: x ? n : /* @__PURE__ */ s("div", {
31
36
  className: i,
32
37
  "data-cal-embed-empty": "",
33
- children: [/* @__PURE__ */ o("p", {
34
- className: t("subheading"),
35
- children: p
36
- }), /* @__PURE__ */ o("p", {
37
- className: e(t("caption"), "text-muted"),
38
- children: h
39
- })]
38
+ children: [
39
+ /* @__PURE__ */ o("p", {
40
+ className: t("subheading"),
41
+ children: p
42
+ }),
43
+ /* @__PURE__ */ o("p", {
44
+ className: e(t("caption"), "text-muted"),
45
+ children: h
46
+ }),
47
+ S
48
+ ]
40
49
  })
41
- }), g === void 0 ? /* @__PURE__ */ o(m, {
42
- skipHref: _,
43
- skipLabel: v,
44
- onSkip: y
45
- }) : null]
50
+ })]
46
51
  });
47
52
  }
48
53
  var g = Object.assign(h, { Skip: m });
@@ -0,0 +1,17 @@
1
+ /** Props for **IntakeHoneypot**. */
2
+ export interface IntakeHoneypotProps {
3
+ /** Field name the server checks. Default `fax`: plausible to a bot, never a real question here. */
4
+ name?: string;
5
+ value: string;
6
+ onChange: (value: string) => void;
7
+ }
8
+ /**
9
+ * Contact and booking forms T4: spam checks without a puzzle. A field people never see or reach, hidden
10
+ * from screen readers too (`aria-hidden`, `tabindex="-1"`, no autofill), that bots fill in. Drop any
11
+ * request where it has a value, on the server, alongside rate limits and a time-to-submit check. Never
12
+ * a CAPTCHA.
13
+ */
14
+ export declare function IntakeHoneypot({ name, value, onChange }: IntakeHoneypotProps): import("react").JSX.Element;
15
+ /** True when the honeypot was filled: treat the request as spam (check this on the server too). */
16
+ export declare function isIntakeHoneypotFilled(value: string | null | undefined): boolean;
17
+ //# sourceMappingURL=IntakeHoneypot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntakeHoneypot.d.ts","sourceRoot":"","sources":["../../../../src/components/molecules/IntakeForm/IntakeHoneypot.tsx"],"names":[],"mappings":"AAEA,oCAAoC;AACpC,MAAM,WAAW,mBAAmB;IAClC,mGAAmG;IACnG,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,+BAgBpF;AAED,mGAAmG;AACnG,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEhF"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { useId as e } from "react";
3
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
4
+ //#region src/components/molecules/IntakeForm/IntakeHoneypot.tsx
5
+ function r({ name: r = "fax", value: i, onChange: a }) {
6
+ let o = e();
7
+ return /* @__PURE__ */ n("div", {
8
+ "aria-hidden": "true",
9
+ className: "absolute -left-[9999px] size-px overflow-hidden",
10
+ "data-intake-honeypot": "",
11
+ children: [/* @__PURE__ */ t("label", {
12
+ htmlFor: o,
13
+ children: "Leave this empty"
14
+ }), /* @__PURE__ */ t("input", {
15
+ id: o,
16
+ name: r,
17
+ type: "text",
18
+ tabIndex: -1,
19
+ autoComplete: "off",
20
+ value: i,
21
+ onChange: (e) => a(e.target.value)
22
+ })]
23
+ });
24
+ }
25
+ function i(e) {
26
+ return (e ?? "").trim().length > 0;
27
+ }
28
+ //#endregion
29
+ export { r as IntakeHoneypot, i as isIntakeHoneypotFilled };
@@ -1,5 +1,6 @@
1
+ import type { ReactNode } from "react";
1
2
  import { type IntakeConfirmationVariant } from "./intakeConfirmationStyles";
2
- export { intakeConfirmationCopy, intakeConfirmationVariants, intakeConfettiColors, type IntakeConfirmationVariant, } from "./intakeConfirmationStyles";
3
+ export { intakeConfirmationCopy, intakeConfirmationReplyWithin, intakeConfirmationVariants, intakeConfettiColors, type IntakeConfirmationVariant, } from "./intakeConfirmationStyles";
3
4
  /** Layout-only — width or margin. */
4
5
  export type IntakeConfirmationLayoutClassName = string;
5
6
  export interface IntakeConfirmationProps {
@@ -21,6 +22,17 @@ export interface IntakeConfirmationProps {
21
22
  icsHref?: string;
22
23
  /** Label for the `.ics` action. Default `Download .ics`. */
23
24
  icsLabel?: string;
25
+ /** Where we'll reply (`emailed`): "We'll email you at {email} …". */
26
+ email?: string;
27
+ /**
28
+ * When we'll reply (Contact and booking forms T3), part of the one "what happens next" sentence. Default
29
+ * "within one business day". Never promise what you don't keep.
30
+ */
31
+ replyWithin?: string;
32
+ /** What we got: a short recap of their request, shown as "You told us: “…”" (e.g. "A new site before spring"). */
33
+ summary?: ReactNode;
34
+ /** How to reach us meanwhile: phone, email, hours (T1, T3). */
35
+ contact?: ReactNode;
24
36
  className?: IntakeConfirmationLayoutClassName;
25
37
  }
26
38
  /**
@@ -29,5 +41,5 @@ export interface IntakeConfirmationProps {
29
41
  * Optional booking actions reuse **TextLink** and **Button** — no new confirmation style.
30
42
  * Mount **ConfettiProvider** above this component.
31
43
  */
32
- export declare function IntakeConfirmation({ variant, onDone, bookingTime, videoHref, videoLabel, googleCalendarHref, googleCalendarLabel, icsHref, icsLabel, className, }: IntakeConfirmationProps): import("react").JSX.Element;
44
+ export declare function IntakeConfirmation({ variant, onDone, bookingTime, videoHref, videoLabel, googleCalendarHref, googleCalendarLabel, icsHref, icsLabel, email, replyWithin, summary, contact, className, }: IntakeConfirmationProps): import("react").JSX.Element;
33
45
  //# sourceMappingURL=IntakeConfirmation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IntakeConfirmation.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeConfirmation/IntakeConfirmation.tsx"],"names":[],"mappings":"AAOA,OAAO,EAQL,KAAK,yBAAyB,EAC/B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,4BAA4B,CAAC;AAEpC,qCAAqC;AACrC,MAAM,MAAM,iCAAiC,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,OAAO,EAAE,yBAAyB,CAAC;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,iCAAiC,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,UAA8B,EAC9B,kBAAkB,EAClB,mBAA8C,EAC9C,OAAO,EACP,QAA0B,EAC1B,SAAS,GACV,EAAE,uBAAuB,+BA0DzB"}
1
+ {"version":3,"file":"IntakeConfirmation.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeConfirmation/IntakeConfirmation.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,OAAO,EASL,KAAK,yBAAyB,EAC/B,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,oBAAoB,EACpB,KAAK,yBAAyB,GAC/B,MAAM,4BAA4B,CAAC;AAEpC,qCAAqC;AACrC,MAAM,MAAM,iCAAiC,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,OAAO,EAAE,yBAAyB,CAAC;IACnC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kHAAkH;IAClH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,iCAAiC,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,EACT,UAA8B,EAC9B,kBAAkB,EAClB,mBAA8C,EAC9C,OAAO,EACP,QAA0B,EAC1B,KAAK,EACL,WAA2C,EAC3C,OAAO,EACP,OAAO,EACP,SAAS,GACV,EAAE,uBAAuB,+BAmEzB"}
@@ -5,11 +5,11 @@ import { Badge as t } from "../../atoms/Badge/Badge.js";
5
5
  import { Button as n } from "../../atoms/Button/Button.js";
6
6
  import { TextLink as r } from "../../atoms/TextLink/TextLink.js";
7
7
  import { useConfettiOnMount as i } from "../Confetti/Confetti.js";
8
- import { intakeConfettiColors as a, intakeConfirmationActionsClasses as o, intakeConfirmationBodyClasses as s, intakeConfirmationClasses as c, intakeConfirmationCopy as l, intakeConfirmationMetaClasses as u, intakeConfirmationTitleClasses as d, intakeConfirmationVariants as f } from "./intakeConfirmationStyles.js";
9
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
8
+ import { intakeConfettiColors as a, intakeConfirmationActionsClasses as o, intakeConfirmationBodyClasses as s, intakeConfirmationClasses as c, intakeConfirmationCopy as l, intakeConfirmationMetaClasses as u, intakeConfirmationReplyWithin as d, intakeConfirmationTitleClasses as f, intakeConfirmationVariants as p } from "./intakeConfirmationStyles.js";
9
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
10
10
  //#region src/components/organisms/IntakeConfirmation/IntakeConfirmation.tsx
11
- function h({ variant: f, onDone: h, bookingTime: g, videoHref: _, videoLabel: v = "Join video call", googleCalendarHref: y, googleCalendarLabel: b = "Add to Google Calendar", icsHref: x, icsLabel: S = "Download .ics", className: C }) {
12
- let w = l[f], T = g != null || _ != null || y != null || x != null;
11
+ function g({ variant: p, onDone: g, bookingTime: _, videoHref: v, videoLabel: y = "Join video call", googleCalendarHref: b, googleCalendarLabel: x = "Add to Google Calendar", icsHref: S, icsLabel: C = "Download .ics", email: w, replyWithin: T = d, summary: E, contact: D, className: O }) {
12
+ let k = l[p], A = p === "emailed" ? `We'll email you${w ? ` at ${w}` : ""} ${T} with a few times that fit.` : _ == null ? k.body : `We'll see you on ${_}, and we'll email a short note before so you know what to bring.`, j = v != null || b != null || S != null;
13
13
  return i({
14
14
  particleCount: 90,
15
15
  spread: 180,
@@ -19,59 +19,64 @@ function h({ variant: f, onDone: h, bookingTime: g, videoHref: _, videoLabel: v
19
19
  x: typeof window > "u" ? 0 : window.innerWidth / 2,
20
20
  y: 0
21
21
  }
22
- }), /* @__PURE__ */ m("div", {
23
- className: e(c, C),
24
- "data-intake-confirmation": f,
22
+ }), /* @__PURE__ */ h("div", {
23
+ className: e(c, O),
24
+ "data-intake-confirmation": p,
25
25
  children: [
26
- /* @__PURE__ */ p(t, {
27
- variant: f === "booked" ? "neutral" : "info",
26
+ /* @__PURE__ */ m(t, {
27
+ variant: p === "booked" ? "neutral" : "info",
28
28
  emphasis: "muted",
29
- children: w.badge
29
+ children: k.badge
30
30
  }),
31
- /* @__PURE__ */ p("h2", {
32
- className: d,
33
- children: w.title
31
+ /* @__PURE__ */ m("h2", {
32
+ className: f,
33
+ children: k.title
34
34
  }),
35
- /* @__PURE__ */ p("p", {
35
+ /* @__PURE__ */ m("p", {
36
36
  className: s,
37
- children: w.body
37
+ children: A
38
38
  }),
39
- T ? /* @__PURE__ */ m("div", {
39
+ E == null ? null : /* @__PURE__ */ h("p", {
40
+ className: u,
41
+ "data-intake-summary": "",
42
+ children: ["You told us: ", /* @__PURE__ */ m("q", { children: E })]
43
+ }),
44
+ j ? /* @__PURE__ */ h("div", {
40
45
  className: o,
41
46
  children: [
42
- g == null ? null : /* @__PURE__ */ p("p", {
43
- className: u,
44
- children: g
45
- }),
46
- _ == null ? null : /* @__PURE__ */ p(r, {
47
- href: _,
47
+ v == null ? null : /* @__PURE__ */ m(r, {
48
+ href: v,
48
49
  external: !0,
49
- children: v
50
+ children: y
50
51
  }),
51
- y == null ? null : /* @__PURE__ */ p(r, {
52
- href: y,
52
+ b == null ? null : /* @__PURE__ */ m(r, {
53
+ href: b,
53
54
  external: !0,
54
- children: b
55
+ children: x
55
56
  }),
56
- x == null ? null : /* @__PURE__ */ p(n, {
57
+ S == null ? null : /* @__PURE__ */ m(n, {
57
58
  role: "secondary",
58
59
  size: "md",
59
- render: /* @__PURE__ */ p("a", {
60
- href: x,
60
+ render: /* @__PURE__ */ m("a", {
61
+ href: S,
61
62
  download: !0
62
63
  }),
63
- children: S
64
+ children: C
64
65
  })
65
66
  ]
66
67
  }) : null,
67
- h == null ? null : /* @__PURE__ */ p(n, {
68
+ D == null ? null : /* @__PURE__ */ m("div", {
69
+ className: u,
70
+ children: D
71
+ }),
72
+ g == null ? null : /* @__PURE__ */ m(n, {
68
73
  role: "primary",
69
74
  type: "button",
70
- onClick: h,
75
+ onClick: g,
71
76
  children: "Done"
72
77
  })
73
78
  ]
74
79
  });
75
80
  }
76
81
  //#endregion
77
- export { h as IntakeConfirmation, a as intakeConfettiColors, l as intakeConfirmationCopy, f as intakeConfirmationVariants };
82
+ export { g as IntakeConfirmation, a as intakeConfettiColors, l as intakeConfirmationCopy, d as intakeConfirmationReplyWithin, p as intakeConfirmationVariants };
@@ -1,15 +1,19 @@
1
1
  /**
2
- * Brand colors for the intake burst. `--color-brand` is #011272 in both themes.
2
+ * Brand colors for the intake burst. `--color-brand` is #011272 (light) and #5566e0 (dark).
3
3
  * Passed to the existing Confetti `colors` option — not a second palette token.
4
4
  */
5
5
  export declare const intakeConfettiColors: readonly ["var(--color-brand)", "var(--color-brand-soft)", "var(--color-primary)", "var(--color-info-muted)", "var(--color-accent)", "var(--color-chart-categorical-1)", "var(--color-chart-categorical-4)"];
6
6
  export declare const intakeConfirmationVariants: readonly ["booked", "emailed"];
7
7
  export type IntakeConfirmationVariant = (typeof intakeConfirmationVariants)[number];
8
+ /** T2, T3: when the reply comes. Keep it true for your team. */
9
+ /** When we reply, inside the confirmation's one "what happens next" sentence (T3). */
10
+ export declare const intakeConfirmationReplyWithin = "within one business day";
8
11
  export declare const intakeConfirmationCopy: Record<IntakeConfirmationVariant, {
9
12
  badge: string;
10
13
  title: string;
11
14
  body: string;
12
15
  }>;
16
+ /** Left on phones, where the next-step sentence with an email runs 3 lines; centred from md (Headings H8). */
13
17
  export declare const intakeConfirmationClasses: string;
14
18
  /** Existing display-2 — the confirmation headline, larger than the step titles. */
15
19
  export declare const intakeConfirmationTitleClasses = "type-display-2 text-balance text-fg";
@@ -19,5 +23,5 @@ export declare const intakeConfirmationBodyClasses = "type-large max-w-2xl text-
19
23
  /** Booked time under the body — supporting muted type. */
20
24
  export declare const intakeConfirmationMetaClasses = "type-body text-balance text-muted";
21
25
  /** Optional booking actions — **TextLink** / **Button** stack, same center column. */
22
- export declare const intakeConfirmationActionsClasses = "flex w-full max-w-md flex-col items-center gap-3";
26
+ export declare const intakeConfirmationActionsClasses = "flex w-full max-w-md flex-col items-start gap-3 md:items-center";
23
27
  //# sourceMappingURL=intakeConfirmationStyles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intakeConfirmationStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeConfirmation/intakeConfirmationStyles.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,8MAQvB,CAAC;AAEX,eAAO,MAAM,0BAA0B,gCAAiC,CAAC;AAEzE,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CACzC,yBAAyB,EACzB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAY/C,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAErC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,8BAA8B,wCAAwC,CAAC;AAEpF,yEAAyE;AACzE,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,8CAA8C,CAAC;AAEzF,0DAA0D;AAC1D,eAAO,MAAM,6BAA6B,sCAAsC,CAAC;AAEjF,sFAAsF;AACtF,eAAO,MAAM,gCAAgC,qDACO,CAAC"}
1
+ {"version":3,"file":"intakeConfirmationStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeConfirmation/intakeConfirmationStyles.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,eAAO,MAAM,oBAAoB,8MAQvB,CAAC;AAEX,eAAO,MAAM,0BAA0B,gCAAiC,CAAC;AAEzE,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpF,gEAAgE;AAChE,sFAAsF;AACtF,eAAO,MAAM,6BAA6B,4BAA4B,CAAC;AAEvE,eAAO,MAAM,sBAAsB,EAAE,MAAM,CACzC,yBAAyB,EACzB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAY/C,CAAC;AAEF,8GAA8G;AAC9G,eAAO,MAAM,yBAAyB,QAErC,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,8BAA8B,wCAAwC,CAAC;AAEpF,yEAAyE;AACzE,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,8CAA8C,CAAC;AAEzF,0DAA0D;AAC1D,eAAO,MAAM,6BAA6B,sCAAsC,CAAC;AAEjF,sFAAsF;AACtF,eAAO,MAAM,gCAAgC,oEACsB,CAAC"}
@@ -9,7 +9,7 @@ var t = [
9
9
  "var(--color-accent)",
10
10
  "var(--color-chart-categorical-1)",
11
11
  "var(--color-chart-categorical-4)"
12
- ], n = ["booked", "emailed"], r = {
12
+ ], n = ["booked", "emailed"], r = "within one business day", i = {
13
13
  booked: {
14
14
  badge: "Booked",
15
15
  title: "You're booked",
@@ -20,6 +20,6 @@ var t = [
20
20
  title: "We'll be in touch",
21
21
  body: "No calendar needed. We'll reply by email with a few times that fit."
22
22
  }
23
- }, i = e("flex w-full max-w-3xl flex-col items-center gap-8 text-center"), a = "type-display-2 text-balance text-fg", o = "type-large max-w-2xl text-balance text-fg", s = "type-body text-balance text-muted", c = "flex w-full max-w-md flex-col items-center gap-3";
23
+ }, a = e("flex w-full max-w-3xl flex-col items-start gap-8 text-left md:items-center md:text-center"), o = "type-display-2 text-balance text-fg", s = "type-large max-w-2xl text-balance text-fg", c = "type-body text-balance text-muted", l = "flex w-full max-w-md flex-col items-start gap-3 md:items-center";
24
24
  //#endregion
25
- export { t as intakeConfettiColors, c as intakeConfirmationActionsClasses, o as intakeConfirmationBodyClasses, i as intakeConfirmationClasses, r as intakeConfirmationCopy, s as intakeConfirmationMetaClasses, a as intakeConfirmationTitleClasses, n as intakeConfirmationVariants };
25
+ export { t as intakeConfettiColors, l as intakeConfirmationActionsClasses, s as intakeConfirmationBodyClasses, a as intakeConfirmationClasses, i as intakeConfirmationCopy, c as intakeConfirmationMetaClasses, r as intakeConfirmationReplyWithin, o as intakeConfirmationTitleClasses, n as intakeConfirmationVariants };
@@ -6,7 +6,10 @@ export interface IntakeModalProps {
6
6
  onOpenChange: (open: boolean) => void;
7
7
  /** Current step, 1-based. Shown when `showProgress` is set. */
8
8
  step?: number;
9
- /** Segment count. Default 4. */
9
+ /**
10
+ * Segment count. Default 2: details, then the optional booking; the confirmation isn't counted
11
+ * (Contact and booking forms T7: at most 3 steps, and only when a later step depends on earlier ones).
12
+ */
10
13
  steps?: number;
11
14
  /** Accessible name. Default `Start a project`. */
12
15
  title?: string;
@@ -29,6 +32,12 @@ export interface IntakeModalProps {
29
32
  * (the Close button still closes). Default `true`.
30
33
  */
31
34
  dismissOnEscape?: boolean;
35
+ /**
36
+ * The visitor has typed answers. Close and Escape then ask "Discard your answers?" before closing
37
+ * (Contact and booking forms T9). Keep the answers in the caller's state, so an accidental close
38
+ * that's undone, or reopening, finds them still there.
39
+ */
40
+ hasAnswers?: boolean;
32
41
  children?: ReactNode;
33
42
  className?: IntakeModalLayoutClassName;
34
43
  }
@@ -37,5 +46,5 @@ export interface IntakeModalProps {
37
46
  * Wordmark, close, step progress, and a pinned footer.
38
47
  * Focus trap, Escape, scroll lock, and `aria-modal`.
39
48
  */
40
- export declare function IntakeModal({ open, onOpenChange, step, steps, title, showProgress, hideFooter, hideContinue, onBack, onContinue, backDisabled, continueDisabled, continueLabel, dismissOnEscape, children, className, }: IntakeModalProps): import("react").ReactPortal | null;
49
+ export declare function IntakeModal({ open, onOpenChange, step, steps, title, showProgress, hideFooter, hideContinue, onBack, onContinue, backDisabled, continueDisabled, continueLabel, dismissOnEscape, hasAnswers, children, className, }: IntakeModalProps): import("react").ReactPortal | null;
41
50
  //# sourceMappingURL=IntakeModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IntakeModal.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeModal/IntakeModal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA8B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAuBnE,wDAAwD;AACxD,MAAM,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,IAAQ,EACR,KAAS,EACT,KAAyB,EACzB,YAAmB,EACnB,UAAkB,EAClB,YAAoB,EACpB,MAAM,EACN,UAAU,EACV,YAAoB,EACpB,gBAAwB,EACxB,aAA0B,EAC1B,eAAsB,EACtB,QAAQ,EACR,SAAS,GACV,EAAE,gBAAgB,sCA8FlB"}
1
+ {"version":3,"file":"IntakeModal.d.ts","sourceRoot":"","sources":["../../../../src/components/organisms/IntakeModal/IntakeModal.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAwBxF,wDAAwD;AACxD,MAAM,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qFAAqF;IACrF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACxC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,YAAY,EACZ,IAAQ,EACR,KAAS,EACT,KAAyB,EACzB,YAAmB,EACnB,UAAkB,EAClB,YAAoB,EACpB,MAAM,EACN,UAAU,EACV,YAAoB,EACpB,gBAAwB,EACxB,aAA0B,EAC1B,eAAsB,EACtB,UAAkB,EAClB,QAAQ,EACR,SAAS,GACV,EAAE,gBAAgB,sCAqIlB"}