@sankhyatronics/sankhya-cms 0.2.0 → 0.3.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.
Files changed (209) hide show
  1. package/custom-elements.json +10968 -3080
  2. package/dist/attention-panel/index.js +2 -2
  3. package/dist/bar-chart/index.js +2 -2
  4. package/dist/bento-grid/index.d.ts +25 -0
  5. package/dist/bento-grid/index.js +4 -4
  6. package/dist/booking/index.d.ts +309 -0
  7. package/dist/booking/index.js +20 -0
  8. package/dist/booking/index.js.map +1 -0
  9. package/dist/card/index.js +2 -2
  10. package/dist/carousel/index.d.ts +20 -6
  11. package/dist/carousel/index.js +3 -3
  12. package/dist/chip/index.js +2 -2
  13. package/dist/{chunk-OLA35A2O.js → chunk-2GTR37PU.js} +2 -2
  14. package/dist/{chunk-7NIWQWTA.js → chunk-2HMOX253.js} +128 -25
  15. package/dist/chunk-2HMOX253.js.map +1 -0
  16. package/dist/{chunk-DH53HZPB.js → chunk-37KFBKPD.js} +32 -4
  17. package/dist/chunk-37KFBKPD.js.map +1 -0
  18. package/dist/{chunk-EE6PAN3B.js → chunk-4XPKKYVZ.js} +23 -15
  19. package/dist/chunk-4XPKKYVZ.js.map +1 -0
  20. package/dist/chunk-535QAZ6A.js +236 -0
  21. package/dist/chunk-535QAZ6A.js.map +1 -0
  22. package/dist/{chunk-AKJQ345O.js → chunk-5AWGZQWU.js} +2 -2
  23. package/dist/chunk-6OZKZG5J.js +300 -0
  24. package/dist/chunk-6OZKZG5J.js.map +1 -0
  25. package/dist/chunk-AYNT7G3J.js +805 -0
  26. package/dist/chunk-AYNT7G3J.js.map +1 -0
  27. package/dist/chunk-BEWX3E6P.js +32 -0
  28. package/dist/chunk-BEWX3E6P.js.map +1 -0
  29. package/dist/chunk-CZUGPKXV.js +275 -0
  30. package/dist/chunk-CZUGPKXV.js.map +1 -0
  31. package/dist/{chunk-2DXHPEB5.js → chunk-DJFWZOZM.js} +107 -11
  32. package/dist/chunk-DJFWZOZM.js.map +1 -0
  33. package/dist/chunk-DPANTC3O.js +1714 -0
  34. package/dist/chunk-DPANTC3O.js.map +1 -0
  35. package/dist/chunk-EKZFFY45.js +426 -0
  36. package/dist/chunk-EKZFFY45.js.map +1 -0
  37. package/dist/chunk-ER7MCPDV.js +7 -0
  38. package/dist/chunk-ER7MCPDV.js.map +1 -0
  39. package/dist/chunk-EW2RK5Y6.js +383 -0
  40. package/dist/chunk-EW2RK5Y6.js.map +1 -0
  41. package/dist/{chunk-BLQV2YMO.js → chunk-EZOKT7NJ.js} +2 -2
  42. package/dist/chunk-FF2LWEF3.js +386 -0
  43. package/dist/chunk-FF2LWEF3.js.map +1 -0
  44. package/dist/chunk-FOUK3NHR.js +7 -0
  45. package/dist/chunk-FOUK3NHR.js.map +1 -0
  46. package/dist/{chunk-O4FCRKDX.js → chunk-GB4NGCZI.js} +6 -3
  47. package/dist/chunk-GB4NGCZI.js.map +1 -0
  48. package/dist/{chunk-5F5PTVWR.js → chunk-GOFSMD6W.js} +9 -10
  49. package/dist/chunk-GOFSMD6W.js.map +1 -0
  50. package/dist/{chunk-6D6ROU7X.js → chunk-IGMVF3KK.js} +2 -2
  51. package/dist/{chunk-INMSEYT6.js → chunk-IVPVYVWG.js} +2 -2
  52. package/dist/{chunk-ZRC5BVDX.js → chunk-JURCF4OD.js} +174 -12
  53. package/dist/chunk-JURCF4OD.js.map +1 -0
  54. package/dist/{chunk-FZ36KL73.js → chunk-KZ7PMFWS.js} +11 -1
  55. package/dist/chunk-KZ7PMFWS.js.map +1 -0
  56. package/dist/{chunk-EMCQBT3S.js → chunk-LO6TZBGD.js} +129 -35
  57. package/dist/chunk-LO6TZBGD.js.map +1 -0
  58. package/dist/chunk-MFRGAT6D.js +860 -0
  59. package/dist/chunk-MFRGAT6D.js.map +1 -0
  60. package/dist/chunk-MIBVQXRU.js +1098 -0
  61. package/dist/chunk-MIBVQXRU.js.map +1 -0
  62. package/dist/{chunk-35TX3AOA.js → chunk-NABSRUXG.js} +2 -2
  63. package/dist/{chunk-2FJDNJ7R.js → chunk-NXKDZWS7.js} +44 -6
  64. package/dist/chunk-NXKDZWS7.js.map +1 -0
  65. package/dist/{chunk-KMU6ABQF.js → chunk-NXUS2CH7.js} +14 -1
  66. package/dist/chunk-NXUS2CH7.js.map +1 -0
  67. package/dist/{chunk-GJO3RGOB.js → chunk-OCPGOLVF.js} +56 -11
  68. package/dist/chunk-OCPGOLVF.js.map +1 -0
  69. package/dist/chunk-OEOE6IFY.js +628 -0
  70. package/dist/chunk-OEOE6IFY.js.map +1 -0
  71. package/dist/{chunk-OELI3IWC.js → chunk-PV6OCXXN.js} +2 -2
  72. package/dist/{chunk-5C6C6K5U.js → chunk-Q66CJO3P.js} +200 -12
  73. package/dist/chunk-Q66CJO3P.js.map +1 -0
  74. package/dist/{chunk-MG2VTZA4.js → chunk-QS3ANOWN.js} +2 -2
  75. package/dist/{chunk-3OEEOBHB.js → chunk-QSJ543V2.js} +2 -2
  76. package/dist/{chunk-FML6AG2V.js → chunk-RANC3OI6.js} +2 -2
  77. package/dist/chunk-T4BIN37Q.js +32 -0
  78. package/dist/chunk-T4BIN37Q.js.map +1 -0
  79. package/dist/{chunk-YVTFQHVY.js → chunk-TEAZZPDQ.js} +2 -2
  80. package/dist/chunk-TJK55CJ2.js +49 -0
  81. package/dist/chunk-TJK55CJ2.js.map +1 -0
  82. package/dist/chunk-UKIVLF7S.js +32 -0
  83. package/dist/chunk-UKIVLF7S.js.map +1 -0
  84. package/dist/chunk-V4R7PYP5.js +905 -0
  85. package/dist/chunk-V4R7PYP5.js.map +1 -0
  86. package/dist/{chunk-AG2COC64.js → chunk-VVYQ2DDS.js} +2 -2
  87. package/dist/chunk-WAMOAAMN.js +16 -0
  88. package/dist/chunk-WAMOAAMN.js.map +1 -0
  89. package/dist/chunk-WAYHHL4J.js +1234 -0
  90. package/dist/chunk-WAYHHL4J.js.map +1 -0
  91. package/dist/{chunk-PHEGSCOM.js → chunk-WH6HE6SY.js} +10 -4
  92. package/dist/chunk-WH6HE6SY.js.map +1 -0
  93. package/dist/{chunk-5MY6OWMK.js → chunk-XP6DI3VY.js} +59 -4
  94. package/dist/chunk-XP6DI3VY.js.map +1 -0
  95. package/dist/{chunk-QLA4BH2B.js → chunk-XS6LNTSH.js} +73 -11
  96. package/dist/chunk-XS6LNTSH.js.map +1 -0
  97. package/dist/{chunk-WT4OATGP.js → chunk-ZKFCDVB4.js} +16 -7
  98. package/dist/chunk-ZKFCDVB4.js.map +1 -0
  99. package/dist/cms-theme.css +22 -0
  100. package/dist/contact-form/index.d.ts +220 -0
  101. package/dist/contact-form/index.js +16 -0
  102. package/dist/contact-form/index.js.map +1 -0
  103. package/dist/content-block/index.d.ts +39 -3
  104. package/dist/content-block/index.js +8 -5
  105. package/dist/cookie-consent/index.d.ts +60 -12
  106. package/dist/cookie-consent/index.js +3 -2
  107. package/dist/date-tile/index.js +2 -2
  108. package/dist/dropdown/index.d.ts +22 -1
  109. package/dist/dropdown/index.js +4 -2
  110. package/dist/feature-split/index.d.ts +6 -1
  111. package/dist/feature-split/index.js +5 -5
  112. package/dist/features-section/index.d.ts +49 -5
  113. package/dist/features-section/index.js +6 -6
  114. package/dist/flow/index.js +2 -2
  115. package/dist/footer/index.d.ts +13 -0
  116. package/dist/footer/index.js +2 -2
  117. package/dist/header/index.d.ts +127 -1
  118. package/dist/header/index.js +3 -2
  119. package/dist/hero/index.d.ts +75 -6
  120. package/dist/hero/index.js +6 -3
  121. package/dist/icon-button/index.d.ts +5 -3
  122. package/dist/icon-button/index.js +2 -2
  123. package/dist/index.d.ts +9 -3
  124. package/dist/index.js +118 -57
  125. package/dist/items-accordion/index.d.ts +5 -1
  126. package/dist/items-accordion/index.js +4 -4
  127. package/dist/kpi-card/index.js +2 -2
  128. package/dist/markdown/index.d.ts +18 -0
  129. package/dist/markdown/index.js +3 -3
  130. package/dist/mega-menu/index.d.ts +95 -7
  131. package/dist/mega-menu/index.js +7 -2
  132. package/dist/menu-grid/index.js +2 -2
  133. package/dist/menu-grid-item/index.js +2 -2
  134. package/dist/menu-item/index.d.ts +6 -0
  135. package/dist/menu-item/index.js +3 -2
  136. package/dist/plan-cards/index.d.ts +69 -0
  137. package/dist/plan-cards/index.js +13 -0
  138. package/dist/plan-cards/index.js.map +1 -0
  139. package/dist/product-nav/index.d.ts +127 -0
  140. package/dist/product-nav/index.js +11 -0
  141. package/dist/product-nav/index.js.map +1 -0
  142. package/dist/promo-banner/index.d.ts +34 -7
  143. package/dist/promo-banner/index.js +6 -3
  144. package/dist/quote-dialog/index.d.ts +174 -0
  145. package/dist/quote-dialog/index.js +22 -0
  146. package/dist/quote-dialog/index.js.map +1 -0
  147. package/dist/schema/index.d.ts +8 -0
  148. package/dist/schema/index.js +6 -0
  149. package/dist/schema/index.js.map +1 -1
  150. package/dist/screenshot-tour/index.d.ts +54 -0
  151. package/dist/screenshot-tour/index.js +9 -0
  152. package/dist/screenshot-tour/index.js.map +1 -0
  153. package/dist/section/index.js +3 -3
  154. package/dist/segmented-control/index.js +2 -2
  155. package/dist/select/index.js +2 -2
  156. package/dist/shared/styles.d.ts +7 -1
  157. package/dist/shared/styles.js +3 -1
  158. package/dist/stats/index.js +2 -2
  159. package/dist/steps/index.d.ts +12 -0
  160. package/dist/steps/index.js +4 -3
  161. package/dist/tag-strip/index.d.ts +7 -0
  162. package/dist/tag-strip/index.js +2 -2
  163. package/dist/testimonials/index.d.ts +9 -1
  164. package/dist/testimonials/index.js +3 -3
  165. package/dist/tooltip/index.js +2 -2
  166. package/package.json +26 -2
  167. package/dist/chunk-2DXHPEB5.js.map +0 -1
  168. package/dist/chunk-2FJDNJ7R.js.map +0 -1
  169. package/dist/chunk-4AFOKKSU.js +0 -158
  170. package/dist/chunk-4AFOKKSU.js.map +0 -1
  171. package/dist/chunk-5C6C6K5U.js.map +0 -1
  172. package/dist/chunk-5F5PTVWR.js.map +0 -1
  173. package/dist/chunk-5MY6OWMK.js.map +0 -1
  174. package/dist/chunk-7NIWQWTA.js.map +0 -1
  175. package/dist/chunk-DH53HZPB.js.map +0 -1
  176. package/dist/chunk-EE6PAN3B.js.map +0 -1
  177. package/dist/chunk-EMCQBT3S.js.map +0 -1
  178. package/dist/chunk-FZ36KL73.js.map +0 -1
  179. package/dist/chunk-GJO3RGOB.js.map +0 -1
  180. package/dist/chunk-HMUZON6I.js +0 -202
  181. package/dist/chunk-HMUZON6I.js.map +0 -1
  182. package/dist/chunk-J6EO4R73.js +0 -633
  183. package/dist/chunk-J6EO4R73.js.map +0 -1
  184. package/dist/chunk-KMU6ABQF.js.map +0 -1
  185. package/dist/chunk-MSSH3HFK.js +0 -205
  186. package/dist/chunk-MSSH3HFK.js.map +0 -1
  187. package/dist/chunk-O4FCRKDX.js.map +0 -1
  188. package/dist/chunk-PHEGSCOM.js.map +0 -1
  189. package/dist/chunk-QLA4BH2B.js.map +0 -1
  190. package/dist/chunk-SQ3OZO32.js +0 -486
  191. package/dist/chunk-SQ3OZO32.js.map +0 -1
  192. package/dist/chunk-UAIUBPDN.js +0 -11
  193. package/dist/chunk-UAIUBPDN.js.map +0 -1
  194. package/dist/chunk-WT4OATGP.js.map +0 -1
  195. package/dist/chunk-XUGEXERO.js +0 -708
  196. package/dist/chunk-XUGEXERO.js.map +0 -1
  197. package/dist/chunk-ZRC5BVDX.js.map +0 -1
  198. /package/dist/{chunk-OLA35A2O.js.map → chunk-2GTR37PU.js.map} +0 -0
  199. /package/dist/{chunk-AKJQ345O.js.map → chunk-5AWGZQWU.js.map} +0 -0
  200. /package/dist/{chunk-BLQV2YMO.js.map → chunk-EZOKT7NJ.js.map} +0 -0
  201. /package/dist/{chunk-6D6ROU7X.js.map → chunk-IGMVF3KK.js.map} +0 -0
  202. /package/dist/{chunk-INMSEYT6.js.map → chunk-IVPVYVWG.js.map} +0 -0
  203. /package/dist/{chunk-35TX3AOA.js.map → chunk-NABSRUXG.js.map} +0 -0
  204. /package/dist/{chunk-OELI3IWC.js.map → chunk-PV6OCXXN.js.map} +0 -0
  205. /package/dist/{chunk-MG2VTZA4.js.map → chunk-QS3ANOWN.js.map} +0 -0
  206. /package/dist/{chunk-3OEEOBHB.js.map → chunk-QSJ543V2.js.map} +0 -0
  207. /package/dist/{chunk-FML6AG2V.js.map → chunk-RANC3OI6.js.map} +0 -0
  208. /package/dist/{chunk-YVTFQHVY.js.map → chunk-TEAZZPDQ.js.map} +0 -0
  209. /package/dist/{chunk-AG2COC64.js.map → chunk-VVYQ2DDS.js.map} +0 -0
@@ -1,12 +1,16 @@
1
1
  import {
2
+ renderMarkdown
3
+ } from "./chunk-TJK55CJ2.js";
4
+ import {
5
+ sectionEyebrowStyles,
2
6
  sectionHeaderStyles,
3
7
  sectionSubtitleStyles,
4
8
  sectionTitleStyles
5
- } from "./chunk-FZ36KL73.js";
9
+ } from "./chunk-KZ7PMFWS.js";
6
10
  import {
7
11
  controlBaseStyles,
8
12
  fontFamilyStyles
9
- } from "./chunk-KMU6ABQF.js";
13
+ } from "./chunk-NXUS2CH7.js";
10
14
  import {
11
15
  __decorateClass
12
16
  } from "./chunk-EUXUH3YW.js";
@@ -14,6 +18,7 @@ import {
14
18
  // src/steps/Steps.ts
15
19
  import { LitElement, css, html, nothing } from "lit";
16
20
  import { customElement, property } from "lit/decorators.js";
21
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
17
22
  var Steps = class extends LitElement {
18
23
  constructor() {
19
24
  super(...arguments);
@@ -23,6 +28,20 @@ var Steps = class extends LitElement {
23
28
  this.items = [];
24
29
  this.highlightLast = false;
25
30
  this.inverted = false;
31
+ this.variant = "default";
32
+ this.markdown = false;
33
+ }
34
+ renderDescription(step) {
35
+ if (!step.description) return nothing;
36
+ return this.markdown ? html`<div class="description" part="description">${unsafeHTML(renderMarkdown(step.description))}</div>` : html`<p class="description" part="description">${step.description}</p>`;
37
+ }
38
+ renderTitle(step) {
39
+ const title = html`<h3 class="card-title" part="card-title">${step.title}</h3>`;
40
+ if (!step.badge) return title;
41
+ return html`<div class="title-row">
42
+ ${title}
43
+ <span class="badge" part="badge">${step.badge}</span>
44
+ </div>`;
26
45
  }
27
46
  render() {
28
47
  const heading = this.eyebrow || this.title || this.subtitle;
@@ -39,8 +58,8 @@ var Steps = class extends LitElement {
39
58
  (step, index) => html`
40
59
  <li class="card ${this.highlightLast && index === last ? "highlight" : ""}" part="card">
41
60
  <span class="number" part="number" aria-hidden="true">${String(index + 1).padStart(2, "0")}</span>
42
- <h3 class="card-title" part="card-title">${step.title}</h3>
43
- ${step.description ? html`<p class="description" part="description">${step.description}</p>` : nothing}
61
+ ${this.renderTitle(step)}
62
+ ${this.renderDescription(step)}
44
63
  </li>
45
64
  `
46
65
  )}
@@ -51,7 +70,10 @@ var Steps = class extends LitElement {
51
70
  };
52
71
  Steps.styles = css`
53
72
  ${controlBaseStyles}
54
- ${fontFamilyStyles}
73
+ /* fontFamilyStyles is a bare declaration: it must sit inside a rule, or it swallows the next one. */
74
+ :host {
75
+ ${fontFamilyStyles}
76
+ }
55
77
 
56
78
  :host {
57
79
  display: block;
@@ -76,12 +98,7 @@ Steps.styles = css`
76
98
  }
77
99
 
78
100
  .eyebrow {
79
- margin: 0 0 var(--st-space-12);
80
- font-size: var(--st-text-sm);
81
- font-weight: var(--st-font-weight-bold);
82
- letter-spacing: 0.12em;
83
- text-transform: uppercase;
84
- color: var(--st-color-text-muted);
101
+ ${sectionEyebrowStyles}
85
102
  }
86
103
 
87
104
  .title {
@@ -182,6 +199,145 @@ Steps.styles = css`
182
199
  color: color-mix(in oklch, var(--st-cms-on-dark) 80%, transparent);
183
200
  }
184
201
 
202
+ /* variant="band": a white full-width band with hairline borders; light blue cards, azure numbers.
203
+ The heading block is left-aligned in a 720px column (label, 36px title, 18px lead). */
204
+ :host([variant='band']) {
205
+ padding: 0 !important;
206
+ background: var(--st-color-surface, #ffffff);
207
+ border-top: 1px solid var(--st-cms-primary-100);
208
+ border-bottom: 1px solid var(--st-cms-primary-100);
209
+ }
210
+
211
+ /* The band's section rhythm and gutters sit on the container (inside the shadow root, so a page
212
+ reset cannot zero them), which is a 1200px box centred on the page. */
213
+ :host([variant='band']) .container {
214
+ box-sizing: border-box;
215
+ /* The side gutter sits inside the box, so the content itself still gets the full container width. */
216
+ max-width: calc(var(--st-cms-container-max) + 2 * var(--st-space-24));
217
+ padding: var(--st-cms-section-padding, 5rem) var(--st-space-24);
218
+ }
219
+
220
+ .description p {
221
+ margin: 0;
222
+ }
223
+
224
+ .description code {
225
+ font-family: ui-monospace, Menlo, monospace;
226
+ font-size: 13px;
227
+ }
228
+
229
+ :host([variant='band']) .header {
230
+ max-width: 720px;
231
+ margin-bottom: var(--st-space-48);
232
+ text-align: left;
233
+ }
234
+
235
+ :host([variant='band']) .eyebrow {
236
+ margin-bottom: var(--st-space-12);
237
+ font-size: 12px;
238
+ font-weight: var(--st-font-weight-semibold);
239
+ letter-spacing: 0.05em;
240
+ color: var(--st-cms-eyebrow, #0c64c5);
241
+ }
242
+
243
+ :host([variant='band']) .title {
244
+ font-size: 36px;
245
+ line-height: 1.2;
246
+ font-weight: var(--st-font-weight-bold);
247
+ }
248
+
249
+ :host([variant='band']) .subtitle {
250
+ max-width: none;
251
+ margin: 0;
252
+ font-size: 18px;
253
+ line-height: 1.6;
254
+ color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));
255
+ }
256
+
257
+ :host([variant='band']) .card {
258
+ gap: var(--st-space-12);
259
+ padding: var(--st-space-24);
260
+ border: 1px solid var(--st-cms-primary-100);
261
+ border-radius: 12px;
262
+ background: var(--st-cms-surface-soft);
263
+ color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));
264
+ }
265
+
266
+ :host([variant='band']) .number {
267
+ font-size: 32px;
268
+ font-weight: var(--st-font-weight-bold);
269
+ color: var(--st-cms-brand-azure);
270
+ }
271
+
272
+ :host([variant='band']) .card-title {
273
+ margin: 0;
274
+ font-size: 20px;
275
+ font-weight: var(--st-font-weight-semibold);
276
+ line-height: 1.3;
277
+ }
278
+
279
+ :host([variant='band']) .description {
280
+ font-size: 14px;
281
+ line-height: 1.5;
282
+ color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));
283
+ }
284
+
285
+ .title-row {
286
+ display: flex;
287
+ flex-wrap: wrap;
288
+ align-items: center;
289
+ gap: var(--st-space-8) var(--st-space-12);
290
+ margin-top: var(--st-space-8);
291
+ }
292
+
293
+ .title-row .card-title {
294
+ margin: 0;
295
+ }
296
+
297
+ .badge {
298
+ display: inline-flex;
299
+ align-items: center;
300
+ padding: 4px 10px;
301
+ border-radius: var(--st-radius-full);
302
+ background: var(--st-cms-primary-100);
303
+ color: var(--st-cms-navy);
304
+ font-size: var(--st-text-xs);
305
+ font-weight: var(--st-font-weight-bold);
306
+ line-height: 1.4;
307
+ white-space: nowrap;
308
+ }
309
+
310
+ .card.highlight .badge {
311
+ background: var(--st-cms-highlight);
312
+ color: var(--st-cms-navy);
313
+ }
314
+
315
+ /* band: the highlighted card stays a dark call-out (the band's light card rules would hide its
316
+ white title). Declared last, with the .card.highlight selector, so it wins over the band rules. */
317
+ :host([variant='band']) .card.highlight {
318
+ background: var(--st-cms-navy);
319
+ border-color: var(--st-cms-primary-200);
320
+ color: var(--st-cms-primary-100);
321
+ }
322
+
323
+ :host([variant='band']) .card.highlight .number {
324
+ color: var(--st-cms-highlight);
325
+ }
326
+
327
+ :host([variant='band']) .card.highlight .card-title {
328
+ color: var(--st-cms-on-dark);
329
+ }
330
+
331
+ :host([variant='band']) .card.highlight .description {
332
+ color: var(--st-cms-primary-100);
333
+ }
334
+
335
+ :host([variant='band']) .badge {
336
+ padding: 2px 8px;
337
+ font-size: 12px;
338
+ font-weight: var(--st-font-weight-semibold);
339
+ }
340
+
185
341
  @media (max-width: 600px) {
186
342
  :host {
187
343
  padding: var(--st-steps-padding, var(--st-space-40) var(--st-space-20)) !important;
@@ -209,6 +365,12 @@ __decorateClass([
209
365
  __decorateClass([
210
366
  property({ type: Boolean, reflect: true })
211
367
  ], Steps.prototype, "inverted", 2);
368
+ __decorateClass([
369
+ property({ type: String, reflect: true })
370
+ ], Steps.prototype, "variant", 2);
371
+ __decorateClass([
372
+ property({ type: Boolean, reflect: true })
373
+ ], Steps.prototype, "markdown", 2);
212
374
  Steps = __decorateClass([
213
375
  customElement("st-steps")
214
376
  ], Steps);
@@ -216,4 +378,4 @@ Steps = __decorateClass([
216
378
  export {
217
379
  Steps
218
380
  };
219
- //# sourceMappingURL=chunk-ZRC5BVDX.js.map
381
+ //# sourceMappingURL=chunk-JURCF4OD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/steps/Steps.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { unsafeHTML } from 'lit/directives/unsafe-html.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport { renderMarkdown } from '../shared/markdown';\nimport { sectionEyebrowStyles, sectionHeaderStyles, sectionSubtitleStyles, sectionTitleStyles } from '../shared/section-styles';\n\nexport interface StepItem {\n title: string;\n /** Plain text, or Markdown when the block has `markdown` set (for inline `code`). */\n description?: string;\n /** Small pill beside the title (e.g. \"Included\"). On the highlighted last card it turns cyan. */\n badge?: string;\n}\n\n/**\n * A numbered process: a responsive grid of cards, each with an automatic \"01\", \"02\", ... number, a\n * title and a description. `highlightLast` makes the final card a dark navy call-out, the way\n * enterprise pages close a how-it-works sequence. `inverted` puts the whole block on the dark band.\n * `variant=\"band\"` sets the block on a white full-width band with hairline top and bottom borders;\n * the cards sit on a light blue surface and the numbers are large azure.\n *\n * @cssprop --st-steps-padding - Overrides the block's padding.\n * @csspart header - The eyebrow/title/subtitle block.\n * @csspart card - Each step card (an `li`).\n * @csspart number - The step number.\n * @csspart badge - The pill beside a step's title.\n */\n@customElement('st-steps')\nexport class Steps extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n /* fontFamilyStyles is a bare declaration: it must sit inside a rule, or it swallows the next one. */\n :host {\n ${fontFamilyStyles}\n }\n\n :host {\n display: block;\n box-sizing: border-box;\n /* !important: a page-level reset (e.g. Tailwind Preflight) otherwise zeroes a shadow host's\n padding; override with --st-steps-padding instead. */\n padding: var(--st-steps-padding, var(--st-cms-section-padding) var(--st-space-24)) !important;\n background: var(--st-color-page);\n }\n\n :host([inverted]) {\n background: var(--st-cms-band-dark-bg);\n }\n\n .container {\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n }\n\n .header {\n ${sectionHeaderStyles}\n }\n\n .eyebrow {\n ${sectionEyebrowStyles}\n }\n\n .title {\n ${sectionTitleStyles}\n color: inherit;\n letter-spacing: -0.02em;\n }\n\n .subtitle {\n ${sectionSubtitleStyles}\n max-width: 60ch;\n margin: 0 auto;\n }\n\n .grid {\n list-style: none;\n margin: 0;\n padding: 0;\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));\n gap: var(--st-space-24);\n }\n\n .card {\n display: flex;\n flex-direction: column;\n gap: var(--st-space-12);\n box-sizing: border-box;\n margin: 0;\n padding: var(--st-space-32);\n border: 1px solid var(--st-color-border);\n border-radius: var(--st-radius-lg);\n background: var(--st-color-surface);\n color: var(--st-color-text);\n }\n\n .number {\n font-size: var(--st-cms-text-3xl);\n font-weight: var(--st-font-weight-bold);\n line-height: 1;\n letter-spacing: -0.02em;\n color: var(--st-color-accent);\n font-variant-numeric: tabular-nums;\n }\n\n .card-title {\n margin: var(--st-space-8) 0 0;\n font-size: var(--st-text-xl);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n color: var(--st-color-text-strong);\n }\n\n .description {\n margin: 0;\n font-size: var(--st-text-md);\n line-height: 1.6;\n color: var(--st-color-text-muted);\n }\n\n /* inverted: a dark band with light cards; the number moves to the cyan highlight so it reads on navy. */\n :host([inverted]) .card {\n background: color-mix(in oklch, var(--st-cms-band-dark-color) 6%, transparent);\n border-color: color-mix(in oklch, var(--st-cms-band-dark-color) 16%, transparent);\n }\n\n :host([inverted]) .number {\n color: var(--st-cms-highlight);\n }\n\n :host([inverted]) .title,\n :host([inverted]) .card-title {\n color: var(--st-cms-band-dark-color);\n }\n\n :host([inverted]) .eyebrow,\n :host([inverted]) .subtitle,\n :host([inverted]) .description {\n color: color-mix(in oklch, var(--st-cms-band-dark-color) 75%, transparent);\n }\n\n /* highlightLast: the final card is the dark call-out. Declared after the inverted rules so it wins. */\n .card.highlight {\n background: var(--st-cms-navy);\n border-color: var(--st-cms-navy);\n color: var(--st-cms-on-dark);\n }\n\n .card.highlight .number {\n color: var(--st-cms-highlight);\n }\n\n .card.highlight .card-title {\n color: var(--st-cms-on-dark);\n }\n\n .card.highlight .description {\n color: color-mix(in oklch, var(--st-cms-on-dark) 80%, transparent);\n }\n\n /* variant=\"band\": a white full-width band with hairline borders; light blue cards, azure numbers.\n The heading block is left-aligned in a 720px column (label, 36px title, 18px lead). */\n :host([variant='band']) {\n padding: 0 !important;\n background: var(--st-color-surface, #ffffff);\n border-top: 1px solid var(--st-cms-primary-100);\n border-bottom: 1px solid var(--st-cms-primary-100);\n }\n\n /* The band's section rhythm and gutters sit on the container (inside the shadow root, so a page\n reset cannot zero them), which is a 1200px box centred on the page. */\n :host([variant='band']) .container {\n box-sizing: border-box;\n /* The side gutter sits inside the box, so the content itself still gets the full container width. */\n max-width: calc(var(--st-cms-container-max) + 2 * var(--st-space-24));\n padding: var(--st-cms-section-padding, 5rem) var(--st-space-24);\n }\n\n .description p {\n margin: 0;\n }\n\n .description code {\n font-family: ui-monospace, Menlo, monospace;\n font-size: 13px;\n }\n\n :host([variant='band']) .header {\n max-width: 720px;\n margin-bottom: var(--st-space-48);\n text-align: left;\n }\n\n :host([variant='band']) .eyebrow {\n margin-bottom: var(--st-space-12);\n font-size: 12px;\n font-weight: var(--st-font-weight-semibold);\n letter-spacing: 0.05em;\n color: var(--st-cms-eyebrow, #0c64c5);\n }\n\n :host([variant='band']) .title {\n font-size: 36px;\n line-height: 1.2;\n font-weight: var(--st-font-weight-bold);\n }\n\n :host([variant='band']) .subtitle {\n max-width: none;\n margin: 0;\n font-size: 18px;\n line-height: 1.6;\n color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));\n }\n\n :host([variant='band']) .card {\n gap: var(--st-space-12);\n padding: var(--st-space-24);\n border: 1px solid var(--st-cms-primary-100);\n border-radius: 12px;\n background: var(--st-cms-surface-soft);\n color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));\n }\n\n :host([variant='band']) .number {\n font-size: 32px;\n font-weight: var(--st-font-weight-bold);\n color: var(--st-cms-brand-azure);\n }\n\n :host([variant='band']) .card-title {\n margin: 0;\n font-size: 20px;\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n }\n\n :host([variant='band']) .description {\n font-size: 14px;\n line-height: 1.5;\n color: var(--st-cms-text, var(--st-cms-navy-2, #03346b));\n }\n\n .title-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--st-space-8) var(--st-space-12);\n margin-top: var(--st-space-8);\n }\n\n .title-row .card-title {\n margin: 0;\n }\n\n .badge {\n display: inline-flex;\n align-items: center;\n padding: 4px 10px;\n border-radius: var(--st-radius-full);\n background: var(--st-cms-primary-100);\n color: var(--st-cms-navy);\n font-size: var(--st-text-xs);\n font-weight: var(--st-font-weight-bold);\n line-height: 1.4;\n white-space: nowrap;\n }\n\n .card.highlight .badge {\n background: var(--st-cms-highlight);\n color: var(--st-cms-navy);\n }\n\n /* band: the highlighted card stays a dark call-out (the band's light card rules would hide its\n white title). Declared last, with the .card.highlight selector, so it wins over the band rules. */\n :host([variant='band']) .card.highlight {\n background: var(--st-cms-navy);\n border-color: var(--st-cms-primary-200);\n color: var(--st-cms-primary-100);\n }\n\n :host([variant='band']) .card.highlight .number {\n color: var(--st-cms-highlight);\n }\n\n :host([variant='band']) .card.highlight .card-title {\n color: var(--st-cms-on-dark);\n }\n\n :host([variant='band']) .card.highlight .description {\n color: var(--st-cms-primary-100);\n }\n\n :host([variant='band']) .badge {\n padding: 2px 8px;\n font-size: 12px;\n font-weight: var(--st-font-weight-semibold);\n }\n\n @media (max-width: 600px) {\n :host {\n padding: var(--st-steps-padding, var(--st-space-40) var(--st-space-20)) !important;\n }\n .card {\n padding: var(--st-space-24);\n }\n }\n `;\n\n /** Small uppercase label above the title. */\n @property({ type: String })\n eyebrow = '';\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n subtitle = '';\n\n /** The steps, in order. */\n @property({ attribute: false })\n items: StepItem[] = [];\n\n /** Renders the last step as a dark navy call-out card. */\n @property({ type: Boolean, reflect: true, attribute: 'highlight-last' })\n highlightLast = false;\n\n /** Puts the block on the dark band (`--st-cms-band-dark-bg`), which stays dark in the dark theme. */\n @property({ type: Boolean, reflect: true })\n inverted = false;\n\n /** `default` is the bordered card grid; `band` is a white full-width band with light blue cards. */\n @property({ type: String, reflect: true })\n variant: 'default' | 'band' = 'default';\n\n /** Renders each step's description as Markdown (inline `code`, links). Off by default: descriptions are plain text. */\n @property({ type: Boolean, reflect: true })\n markdown = false;\n\n private renderDescription(step: StepItem) {\n if (!step.description) return nothing;\n return this.markdown\n ? html`<div class=\"description\" part=\"description\">${unsafeHTML(renderMarkdown(step.description))}</div>`\n : html`<p class=\"description\" part=\"description\">${step.description}</p>`;\n }\n\n private renderTitle(step: StepItem) {\n const title = html`<h3 class=\"card-title\" part=\"card-title\">${step.title}</h3>`;\n if (!step.badge) return title;\n return html`<div class=\"title-row\">\n ${title}\n <span class=\"badge\" part=\"badge\">${step.badge}</span>\n </div>`;\n }\n\n render() {\n const heading = this.eyebrow || this.title || this.subtitle;\n const last = this.items.length - 1;\n return html`\n <div class=\"container\" part=\"container\">\n ${heading\n ? html`<div class=\"header\" part=\"header\">\n ${this.eyebrow ? html`<p class=\"eyebrow\" part=\"eyebrow\">${this.eyebrow}</p>` : nothing}\n ${this.title ? html`<h2 class=\"title\" part=\"title\">${this.title}</h2>` : nothing}\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\n </div>`\n : nothing}\n <ol class=\"grid\" part=\"grid\" aria-label=${this.title || nothing}>\n ${this.items.map(\n (step, index) => html`\n <li class=\"card ${this.highlightLast && index === last ? 'highlight' : ''}\" part=\"card\">\n <span class=\"number\" part=\"number\" aria-hidden=\"true\">${String(index + 1).padStart(2, '0')}</span>\n ${this.renderTitle(step)}\n ${this.renderDescription(step)}\n </li>\n `\n )}\n </ol>\n </div>\n `;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AACxC,SAAS,kBAAkB;AA4BpB,IAAM,QAAN,cAAoB,WAAW;AAAA,EAA/B;AAAA;AA2RL,mBAAU;AAGV,iBAAQ;AAGR,oBAAW;AAIX,iBAAoB,CAAC;AAIrB,yBAAgB;AAIhB,oBAAW;AAIX,mBAA8B;AAI9B,oBAAW;AAAA;AAAA,EAEH,kBAAkB,MAAgB;AACxC,QAAI,CAAC,KAAK,YAAa,QAAO;AAC9B,WAAO,KAAK,WACR,mDAAmD,WAAW,eAAe,KAAK,WAAW,CAAC,CAAC,WAC/F,iDAAiD,KAAK,WAAW;AAAA,EACvE;AAAA,EAEQ,YAAY,MAAgB;AAClC,UAAM,QAAQ,gDAAgD,KAAK,KAAK;AACxE,QAAI,CAAC,KAAK,MAAO,QAAO;AACxB,WAAO;AAAA,QACH,KAAK;AAAA,yCAC4B,KAAK,KAAK;AAAA;AAAA,EAEjD;AAAA,EAEA,SAAS;AACP,UAAM,UAAU,KAAK,WAAW,KAAK,SAAS,KAAK;AACnD,UAAM,OAAO,KAAK,MAAM,SAAS;AACjC,WAAO;AAAA;AAAA,UAED,UACE;AAAA,gBACI,KAAK,UAAU,yCAAyC,KAAK,OAAO,SAAS,OAAO;AAAA,gBACpF,KAAK,QAAQ,sCAAsC,KAAK,KAAK,UAAU,OAAO;AAAA,gBAC9E,KAAK,WAAW,2CAA2C,KAAK,QAAQ,SAAS,OAAO;AAAA,sBAE5F,OAAO;AAAA,kDAC+B,KAAK,SAAS,OAAO;AAAA,YAC3D,KAAK,MAAM;AAAA,MACX,CAAC,MAAM,UAAU;AAAA,gCACG,KAAK,iBAAiB,UAAU,OAAO,cAAc,EAAE;AAAA,wEACf,OAAO,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,kBACxF,KAAK,YAAY,IAAI,CAAC;AAAA,kBACtB,KAAK,kBAAkB,IAAI,CAAC;AAAA;AAAA;AAAA,IAGpC,CAAC;AAAA;AAAA;AAAA;AAAA,EAIT;AACF;AAjWa,MACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA,QAGf,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsBhB,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAInB,oBAAoB;AAAA;AAAA;AAAA;AAAA,QAIpB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMlB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkP3B;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA1Rf,MA2RX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA7Rf,MA8RX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAhSf,MAiSX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GApSnB,MAqSX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,MAAM,WAAW,iBAAiB,CAAC;AAAA,GAxS5D,MAySX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GA5S/B,MA6SX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAhT9B,MAiTX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GApT/B,MAqTX;AArTW,QAAN;AAAA,EADN,cAAc,UAAU;AAAA,GACZ;","names":[]}
@@ -24,8 +24,17 @@ var cardDescriptionStyles = css`
24
24
  color: var(--st-color-text-muted);
25
25
  line-height: 1.5;
26
26
  `;
27
+ var sectionEyebrowStyles = css`
28
+ margin: 0 0 var(--st-space-12);
29
+ font-size: var(--st-text-sm);
30
+ font-weight: var(--st-font-weight-bold);
31
+ letter-spacing: 0.12em;
32
+ text-transform: uppercase;
33
+ color: var(--st-color-accent-text);
34
+ `;
27
35
  var ctaLinkStyles = css`
28
36
  display: inline-block;
37
+ box-sizing: border-box;
29
38
  padding: 12px 24px;
30
39
  border-radius: var(--st-radius-sm);
31
40
  font: inherit;
@@ -77,6 +86,7 @@ export {
77
86
  sectionSubtitleStyles,
78
87
  cardTitleStyles,
79
88
  cardDescriptionStyles,
89
+ sectionEyebrowStyles,
80
90
  ctaLinkStyles,
81
91
  paddingScaleStyles,
82
92
  sectionHeaderStyles,
@@ -84,4 +94,4 @@ export {
84
94
  reducedMotionStyles,
85
95
  invertedSectionTextStyles
86
96
  };
87
- //# sourceMappingURL=chunk-FZ36KL73.js.map
97
+ //# sourceMappingURL=chunk-KZ7PMFWS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/section-styles.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * CSS fragments shared by the CMS section components (hero, features, stats, ...), replacing the\n * source React library's global `Common.css` classes (`.section-title`, `.theme-inverted`, ...)\n * so each Lit component composes them into its own shadow root instead of re-declaring them.\n */\n\n/** Section heading + subheading typography. Use on `.title` / `.subtitle` selectors. */\nexport const sectionTitleStyles = css`\n font-size: var(--st-cms-text-4xl);\n font-weight: var(--st-font-weight-bold);\n color: var(--st-color-text-strong);\n margin: 0 0 var(--st-space-16);\n line-height: 1.2;\n`;\n\nexport const sectionSubtitleStyles = css`\n font-size: var(--st-cms-text-lg);\n color: var(--st-color-text-muted);\n line-height: 1.6;\n margin: 0 0 var(--st-space-28);\n`;\n\n/** Card heading + body typography. */\nexport const cardTitleStyles = css`\n font-size: var(--st-text-2xl);\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n margin: 0 0 var(--st-space-8);\n`;\n\nexport const cardDescriptionStyles = css`\n font-size: var(--st-text-md);\n color: var(--st-color-text-muted);\n line-height: 1.5;\n`;\n\n/**\n * Small uppercase, letter-spaced accent label above a section or content heading (\"HOW IT WORKS\").\n * Shared by `st-steps`, `st-section`, `st-content-block` and `st-features-section`. Inverted/dark\n * surfaces override the colour locally.\n */\nexport const sectionEyebrowStyles = css`\n margin: 0 0 var(--st-space-12);\n font-size: var(--st-text-sm);\n font-weight: var(--st-font-weight-bold);\n letter-spacing: 0.12em;\n text-transform: uppercase;\n color: var(--st-color-accent-text);\n`;\n\n/**\n * Outlined call-to-action link/button used by hero, promo banner, features, ... Applies to both\n * `<a>` (when the CTA has an `href`) and `<button>`: `box-sizing` is pinned so an anchor sizes like\n * a button with the same padding.\n */\nexport const ctaLinkStyles = css`\n display: inline-block;\n box-sizing: border-box;\n padding: 12px 24px;\n border-radius: var(--st-radius-sm);\n font: inherit;\n text-align: center;\n text-decoration: none;\n cursor: pointer;\n transition: transform 0.2s ease;\n`;\n\n/** Maps the source's `padding` prop (none|small|medium|large) to `:host([padding=...])` rules. */\nexport const paddingScaleStyles = css`\n :host([padding='small']) { padding: var(--st-space-16); }\n :host([padding='medium']) { padding: var(--st-space-24); }\n :host([padding='large']) { padding: var(--st-space-32); }\n`;\n\n/** Centered title/subtitle block above a section's content. Use on a `.header` wrapper. */\nexport const sectionHeaderStyles = css`\n text-align: center;\n margin-bottom: var(--st-space-48);\n`;\n\n/** Rounded icon tile (holds an `<iconify-icon>`) used by bento cards, feature lists, ... */\nexport const iconTileStyles = css`\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border-radius: var(--st-radius-lg);\n background: var(--st-color-subtle);\n color: var(--st-color-text-muted);\n`;\n\n/** Collapses CSS transitions/animations for users who prefer reduced motion. */\nexport const reducedMotionStyles = css`\n @media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n transition-duration: 0.01ms !important;\n animation-duration: 0.01ms !important;\n }\n }\n`;\n\n/** Light-on-dark title/subtitle for an `inverted` section host. Place inside the host's `static styles`. */\nexport const invertedSectionTextStyles = css`\n :host([inverted]) .title {\n color: var(--st-color-on-solid);\n }\n\n :host([inverted]) .subtitle {\n color: var(--st-color-border);\n }\n`;\n"],"mappings":";AAAA,SAAS,WAAW;AASb,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ3B,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAQ9B,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAOxB,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAW9B,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAc7B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAatB,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAO3B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAM5B,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWvB,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAY5B,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;","names":[]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  reducedMotionStyles
3
- } from "./chunk-FZ36KL73.js";
3
+ } from "./chunk-KZ7PMFWS.js";
4
4
  import {
5
5
  buttonResetStyles,
6
6
  controlBaseStyles
7
- } from "./chunk-KMU6ABQF.js";
7
+ } from "./chunk-NXUS2CH7.js";
8
8
  import {
9
9
  __decorateClass
10
10
  } from "./chunk-EUXUH3YW.js";
@@ -12,6 +12,7 @@ import {
12
12
  // src/carousel/Carousel.ts
13
13
  import { LitElement, css, html, nothing } from "lit";
14
14
  import { customElement, property, state } from "lit/decorators.js";
15
+ var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
15
16
  var Carousel = class extends LitElement {
16
17
  constructor() {
17
18
  super(...arguments);
@@ -27,42 +28,62 @@ var Carousel = class extends LitElement {
27
28
  this.count = 0;
28
29
  this.slideLabels = [];
29
30
  this.userPaused = false;
30
- /** Paused while hovered or focused. */
31
- this.paused = false;
31
+ this.hovered = false;
32
+ this.focused = false;
33
+ this.turned = false;
32
34
  /** Time left on the current slide, so a pause resumes where it stopped. */
33
35
  this.remaining = 0;
34
36
  this.startedAt = 0;
35
- this.pause = () => this.hold(() => this.paused = true);
36
- this.pauseOnEnter = () => {
37
- if (this.pauseOnHover) this.pause();
37
+ this.onReducedMotionChange = (event) => {
38
+ if (event.matches) this.hold(() => this.userPaused = true);
38
39
  };
39
- this.resume = () => this.hold(() => this.paused = false);
40
- this.togglePlay = () => this.hold(() => this.userPaused = !this.userPaused);
40
+ this.onPointerEnter = () => {
41
+ if (this.pauseOnHover) this.hold(() => this.hovered = true);
42
+ };
43
+ this.onPointerLeave = () => this.hold(() => this.hovered = false);
44
+ /** Focus inside the carousel pauses it (WCAG 2.2.2), but focusing the play button does not, so pressing play starts it. */
45
+ this.onFocusIn = (event) => {
46
+ const target = event.composedPath()[0];
47
+ const onPlay = target instanceof Element && target.classList.contains("play");
48
+ this.hold(() => this.focused = !onPlay);
49
+ };
50
+ this.onFocusOut = () => this.hold(() => this.focused = false);
51
+ this.togglePlay = () => this.hold(() => {
52
+ this.userPaused = !this.userPaused;
53
+ this.hovered = false;
54
+ });
41
55
  }
42
56
  connectedCallback() {
43
57
  super.connectedCallback();
44
- this.addEventListener("mouseenter", this.pauseOnEnter);
45
- this.addEventListener("mouseleave", this.resume);
46
- this.addEventListener("focusin", this.pause);
47
- this.addEventListener("focusout", this.resume);
58
+ if (!this.hasAttribute("role")) this.setAttribute("role", "region");
59
+ this.setAttribute("aria-roledescription", "carousel");
60
+ this.reducedMotion = typeof window !== "undefined" && window.matchMedia ? window.matchMedia(REDUCED_MOTION_QUERY) : void 0;
61
+ if (this.reducedMotion?.matches) this.hold(() => this.userPaused = true);
62
+ this.reducedMotion?.addEventListener("change", this.onReducedMotionChange);
63
+ this.addEventListener("mouseenter", this.onPointerEnter);
64
+ this.addEventListener("mouseleave", this.onPointerLeave);
65
+ this.addEventListener("focusin", this.onFocusIn);
66
+ this.addEventListener("focusout", this.onFocusOut);
48
67
  }
49
68
  disconnectedCallback() {
50
69
  this.stopTimer();
51
- this.removeEventListener("mouseenter", this.pauseOnEnter);
52
- this.removeEventListener("mouseleave", this.resume);
53
- this.removeEventListener("focusin", this.pause);
54
- this.removeEventListener("focusout", this.resume);
70
+ this.reducedMotion?.removeEventListener("change", this.onReducedMotionChange);
71
+ this.reducedMotion = void 0;
72
+ this.removeEventListener("mouseenter", this.onPointerEnter);
73
+ this.removeEventListener("mouseleave", this.onPointerLeave);
74
+ this.removeEventListener("focusin", this.onFocusIn);
75
+ this.removeEventListener("focusout", this.onFocusOut);
55
76
  super.disconnectedCallback();
56
77
  }
57
78
  willUpdate(changed) {
58
79
  if (changed.has("interval")) this.style.setProperty("--st-carousel-interval", `${this.interval}ms`);
59
80
  }
60
81
  updated(changed) {
61
- if (changed.has("index") || changed.has("count") || changed.has("indicatorStyle") || changed.has("tabLabels")) this.syncSlides();
82
+ if (changed.has("index") || changed.has("count") || changed.has("indicatorStyle") || changed.has("tabLabels") || changed.has("turned")) this.syncSlides();
62
83
  if (changed.has("autoPlay") || changed.has("interval") || changed.has("count")) this.restartTimer();
63
84
  }
64
85
  get halted() {
65
- return this.paused || this.userPaused;
86
+ return this.hovered || this.focused || this.userPaused;
66
87
  }
67
88
  /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */
68
89
  hold(update) {
@@ -85,16 +106,14 @@ var Carousel = class extends LitElement {
85
106
  return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;
86
107
  }
87
108
  syncSlides() {
88
- const tabs = this.indicatorStyle === "tabs";
89
- this.slides.forEach((el, i) => {
90
- el.toggleAttribute("data-st-active", i === this.index);
91
- if (tabs) {
92
- el.setAttribute("role", "tabpanel");
93
- el.setAttribute("aria-label", this.labelFor(i));
94
- } else if (el.getAttribute("role") === "tabpanel") {
95
- el.removeAttribute("role");
96
- el.removeAttribute("aria-label");
97
- }
109
+ const slides = this.slides;
110
+ slides.forEach((el, i) => {
111
+ const active = i === this.index;
112
+ el.toggleAttribute("data-st-active", active);
113
+ el.toggleAttribute("data-st-still", active && !this.turned);
114
+ el.setAttribute("role", "group");
115
+ el.setAttribute("aria-roledescription", "slide");
116
+ el.setAttribute("aria-label", `${i + 1} of ${slides.length}`);
98
117
  });
99
118
  }
100
119
  onSlotChange() {
@@ -102,8 +121,25 @@ var Carousel = class extends LitElement {
102
121
  this.count = slides.length;
103
122
  this.slideLabels = slides.map((el) => el.dataset.tabLabel || el.title || "");
104
123
  if (this.index >= this.count) this.index = 0;
124
+ this.preloadImage(slides[0]);
105
125
  this.syncSlides();
106
126
  }
127
+ /**
128
+ * The first slide's image is the one visitors see first, so it is preloaded at high priority. The
129
+ * other slides are display:none (their CSS backgrounds are not fetched) until they are shown.
130
+ */
131
+ preloadImage(slide) {
132
+ const src = slide?.imageSrc || slide?.getAttribute("image-src");
133
+ if (!src) return;
134
+ const preloaded = Array.from(document.head.querySelectorAll('link[rel="preload"]')).some((link2) => link2.getAttribute("href") === src);
135
+ if (preloaded) return;
136
+ const link = document.createElement("link");
137
+ link.rel = "preload";
138
+ link.as = "image";
139
+ link.href = src;
140
+ link.setAttribute("fetchpriority", "high");
141
+ document.head.append(link);
142
+ }
107
143
  stopTimer() {
108
144
  if (this.timer !== void 0) clearTimeout(this.timer);
109
145
  this.timer = void 0;
@@ -120,6 +156,7 @@ var Carousel = class extends LitElement {
120
156
  }
121
157
  go(target, direction) {
122
158
  if (this.count === 0) return;
159
+ this.turned = true;
123
160
  this.setAttribute("data-direction", direction);
124
161
  this.index = (target + this.count) % this.count;
125
162
  this.dispatchEvent(
@@ -155,6 +192,7 @@ var Carousel = class extends LitElement {
155
192
  part="tab"
156
193
  type="button"
157
194
  role="tab"
195
+ aria-label=${this.labelFor(i)}
158
196
  class="tab ${active ? "active" : ""} ${running ? "running" : ""}"
159
197
  aria-selected=${active ? "true" : "false"}
160
198
  tabindex=${active ? 0 : -1}
@@ -197,7 +235,10 @@ var Carousel = class extends LitElement {
197
235
  render() {
198
236
  const multiple = this.count > 1;
199
237
  return html`
200
- <slot @slotchange=${this.onSlotChange}></slot>
238
+ <div class="viewport" part="viewport">
239
+ <slot @slotchange=${this.onSlotChange}></slot>
240
+ </div>
241
+ ${multiple ? html`<div class="sr-only" aria-live=${this.halted ? "polite" : "off"} aria-atomic="true">${this.index + 1} of ${this.count}</div>` : nothing}
201
242
  ${this.showArrows && multiple ? html`
202
243
  <button part="nav-button prev" class="nav prev" aria-label="Previous Slide" @click=${() => this.go(this.index - 1, "prev")}>&#10094;</button>
203
244
  <button part="nav-button next" class="nav next" aria-label="Next Slide" @click=${() => this.go(this.index + 1, "next")}>&#10095;</button>
@@ -218,22 +259,51 @@ Carousel.styles = css`
218
259
 
219
260
  ::slotted(*) {
220
261
  display: none !important;
262
+ box-sizing: border-box;
263
+ width: 100%;
264
+ min-width: 100%;
265
+ max-width: 100%;
266
+ }
267
+
268
+ /* The slides sit in a clipping viewport and each is exactly the carousel's width, so the next
269
+ slide never shows at the edge; the slide animations move inside the viewport. */
270
+ .viewport {
271
+ position: relative;
272
+ width: 100%;
273
+ overflow: hidden;
221
274
  }
222
275
 
223
276
  ::slotted([data-st-active]) {
224
277
  display: block !important;
278
+ }
279
+
280
+ /* data-st-still (set on the first slide until the first change) keeps the entrance off on first
281
+ paint, so the copy is there at once; later changes animate. */
282
+ ::slotted([data-st-active]:not([data-st-still])) {
225
283
  animation: st-carousel-in-next 0.4s ease both;
226
284
  }
227
285
 
228
- :host([data-direction='prev']) ::slotted([data-st-active]) {
286
+ :host([data-direction='prev']) ::slotted([data-st-active]:not([data-st-still])) {
229
287
  animation-name: st-carousel-in-prev;
230
288
  }
231
289
 
232
- :host([transition='fade']) ::slotted([data-st-active]),
233
- :host([transition='fade'][data-direction]) ::slotted([data-st-active]) {
290
+ :host([transition='fade']) ::slotted([data-st-active]:not([data-st-still])),
291
+ :host([transition='fade'][data-direction]) ::slotted([data-st-active]:not([data-st-still])) {
234
292
  animation: st-carousel-fade 0.7s ease both;
235
293
  }
236
294
 
295
+ .sr-only {
296
+ position: absolute;
297
+ width: 1px;
298
+ height: 1px;
299
+ margin: -1px;
300
+ padding: 0;
301
+ overflow: hidden;
302
+ clip: rect(0 0 0 0);
303
+ white-space: nowrap;
304
+ border: 0;
305
+ }
306
+
237
307
  @keyframes st-carousel-in-next {
238
308
  from {
239
309
  transform: translateX(10%);
@@ -366,6 +436,7 @@ Carousel.styles = css`
366
436
 
367
437
  .tab {
368
438
  ${buttonResetStyles}
439
+ position: relative;
369
440
  display: flex;
370
441
  flex-direction: column;
371
442
  gap: var(--st-space-12);
@@ -390,6 +461,19 @@ Carousel.styles = css`
390
461
  outline-offset: 4px;
391
462
  }
392
463
 
464
+ /* Touch targets: the tab and the pause button keep their look; a pseudo-element extends the tap
465
+ area to at least 44x44 CSS px. */
466
+ .tab::after,
467
+ .play::after {
468
+ content: '';
469
+ position: absolute;
470
+ top: 50%;
471
+ left: 50%;
472
+ width: max(100%, 44px);
473
+ height: max(100%, 44px);
474
+ transform: translate(-50%, -50%);
475
+ }
476
+
393
477
  .progress {
394
478
  position: relative;
395
479
  display: block;
@@ -430,6 +514,7 @@ Carousel.styles = css`
430
514
 
431
515
  .play {
432
516
  ${buttonResetStyles}
517
+ position: relative;
433
518
  flex: none;
434
519
  display: inline-flex;
435
520
  align-items: center;
@@ -481,7 +566,7 @@ Carousel.styles = css`
481
566
  ${reducedMotionStyles}
482
567
  @media (prefers-reduced-motion: reduce) {
483
568
  ::slotted([data-st-active]) {
484
- animation: none;
569
+ animation: none !important;
485
570
  }
486
571
  .tab.active.running .fill {
487
572
  animation: none;
@@ -524,6 +609,15 @@ __decorateClass([
524
609
  __decorateClass([
525
610
  state()
526
611
  ], Carousel.prototype, "userPaused", 2);
612
+ __decorateClass([
613
+ state()
614
+ ], Carousel.prototype, "hovered", 2);
615
+ __decorateClass([
616
+ state()
617
+ ], Carousel.prototype, "focused", 2);
618
+ __decorateClass([
619
+ state()
620
+ ], Carousel.prototype, "turned", 2);
527
621
  Carousel = __decorateClass([
528
622
  customElement("st-carousel")
529
623
  ], Carousel);
@@ -531,4 +625,4 @@ Carousel = __decorateClass([
531
625
  export {
532
626
  Carousel
533
627
  };
534
- //# sourceMappingURL=chunk-EMCQBT3S.js.map
628
+ //# sourceMappingURL=chunk-LO6TZBGD.js.map