@sankhyatronics/sankhya-cms 0.1.4 → 0.1.6

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 (68) hide show
  1. package/custom-elements.json +997 -905
  2. package/dist/bento-grid/index.d.ts +5 -1
  3. package/dist/bento-grid/index.js +1 -1
  4. package/dist/carousel/index.d.ts +7 -2
  5. package/dist/carousel/index.js +1 -1
  6. package/dist/{chunk-OEX5FDMR.js → chunk-2JGWWXEI.js} +4 -2
  7. package/dist/chunk-2JGWWXEI.js.map +1 -0
  8. package/dist/{chunk-USNFT4DU.js → chunk-6H262SG6.js} +8 -6
  9. package/dist/chunk-6H262SG6.js.map +1 -0
  10. package/dist/{chunk-E52WO7R7.js → chunk-BQTDFQ4V.js} +5 -3
  11. package/dist/chunk-BQTDFQ4V.js.map +1 -0
  12. package/dist/{chunk-74MILER4.js → chunk-EMVHNAID.js} +5 -3
  13. package/dist/chunk-EMVHNAID.js.map +1 -0
  14. package/dist/{chunk-3ERKQNZT.js → chunk-HGJT24UG.js} +7 -5
  15. package/dist/chunk-HGJT24UG.js.map +1 -0
  16. package/dist/{chunk-MLF6L3KM.js → chunk-HGTC3LCW.js} +6 -4
  17. package/dist/chunk-HGTC3LCW.js.map +1 -0
  18. package/dist/{chunk-47RPYNFG.js → chunk-HPIQSECE.js} +10 -3
  19. package/dist/chunk-HPIQSECE.js.map +1 -0
  20. package/dist/{chunk-2VZFHTBC.js → chunk-MW43OS47.js} +5 -3
  21. package/dist/chunk-MW43OS47.js.map +1 -0
  22. package/dist/{chunk-N63TVWK3.js → chunk-NN3OCPDV.js} +23 -19
  23. package/dist/chunk-NN3OCPDV.js.map +1 -0
  24. package/dist/{chunk-KHPJ5FAJ.js → chunk-URC5XBTL.js} +32 -1
  25. package/dist/{chunk-KHPJ5FAJ.js.map → chunk-URC5XBTL.js.map} +1 -1
  26. package/dist/{chunk-IMACP7HN.js → chunk-UVNBZD7R.js} +5 -3
  27. package/dist/chunk-UVNBZD7R.js.map +1 -0
  28. package/dist/{chunk-5REZSZCK.js → chunk-VRRBMOUP.js} +5 -3
  29. package/dist/chunk-VRRBMOUP.js.map +1 -0
  30. package/dist/{chunk-S4ARRDAI.js → chunk-ZRXYWH6C.js} +5 -3
  31. package/dist/chunk-ZRXYWH6C.js.map +1 -0
  32. package/dist/cms-theme.css +11 -0
  33. package/dist/content-block/index.d.ts +2 -0
  34. package/dist/content-block/index.js +1 -1
  35. package/dist/cookie-consent/index.d.ts +2 -0
  36. package/dist/cookie-consent/index.js +1 -1
  37. package/dist/feature-split/index.d.ts +5 -1
  38. package/dist/feature-split/index.js +1 -1
  39. package/dist/features-section/index.d.ts +2 -0
  40. package/dist/features-section/index.js +1 -1
  41. package/dist/index.js +26 -26
  42. package/dist/items-accordion/index.d.ts +5 -1
  43. package/dist/items-accordion/index.js +1 -1
  44. package/dist/mega-menu/index.d.ts +1 -0
  45. package/dist/mega-menu/index.js +1 -1
  46. package/dist/menu-item/index.d.ts +4 -3
  47. package/dist/menu-item/index.js +1 -1
  48. package/dist/promo-banner/index.d.ts +3 -0
  49. package/dist/promo-banner/index.js +1 -1
  50. package/dist/section/index.d.ts +1 -0
  51. package/dist/section/index.js +1 -1
  52. package/dist/stats/index.d.ts +6 -1
  53. package/dist/stats/index.js +1 -1
  54. package/dist/testimonials/index.d.ts +1 -0
  55. package/dist/testimonials/index.js +1 -1
  56. package/package.json +4 -13
  57. package/dist/chunk-2VZFHTBC.js.map +0 -1
  58. package/dist/chunk-3ERKQNZT.js.map +0 -1
  59. package/dist/chunk-47RPYNFG.js.map +0 -1
  60. package/dist/chunk-5REZSZCK.js.map +0 -1
  61. package/dist/chunk-74MILER4.js.map +0 -1
  62. package/dist/chunk-E52WO7R7.js.map +0 -1
  63. package/dist/chunk-IMACP7HN.js.map +0 -1
  64. package/dist/chunk-MLF6L3KM.js.map +0 -1
  65. package/dist/chunk-N63TVWK3.js.map +0 -1
  66. package/dist/chunk-OEX5FDMR.js.map +0 -1
  67. package/dist/chunk-S4ARRDAI.js.map +0 -1
  68. package/dist/chunk-USNFT4DU.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ItemsAccordion
3
- } from "../chunk-74MILER4.js";
3
+ } from "../chunk-EMVHNAID.js";
4
4
  import "../chunk-3VE6VFJ4.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -59,6 +59,7 @@ declare class MegaMenu extends LitElement {
59
59
  * @csspart description - The line under the heading.
60
60
  * @csspart items - The box holding the links.
61
61
  * @csspart cta - The pill button.
62
+ * @cssprop --st-mega-menu-column-padding - Overrides the padding of a `card`/`accent` column.
62
63
  */
63
64
  declare class MegaMenuColumn extends LitElement {
64
65
  static styles: lit.CSSResult;
@@ -2,7 +2,7 @@ import {
2
2
  MegaMenu,
3
3
  MegaMenuColumn,
4
4
  MegaMenuFeature
5
- } from "../chunk-MLF6L3KM.js";
5
+ } from "../chunk-HGTC3LCW.js";
6
6
  import "../chunk-PB7ZPPLP.js";
7
7
  import "../chunk-RHAOQ6K4.js";
8
8
  import "../chunk-EUXUH3YW.js";
@@ -36,9 +36,10 @@ declare class MenuItem extends LitElement {
36
36
  showDescription: boolean;
37
37
  /** `target` for the `<a>` (source default `_self`). */
38
38
  target: string;
39
- /** `default` (a row with a hover box) or `link` (a plain text link, as in `st-mega-menu-column`;
40
- * marked with an arrow when it opens a new tab). */
41
- variant: 'default' | 'link';
39
+ /** `default` (a row with a hover box), `link` (a plain text link, as in `st-mega-menu-column`;
40
+ * marked with an arrow when it opens a new tab) or `bar` (a top-level item in a header bar,
41
+ * shaped like a mega `st-dropdown`'s trigger pill so it lines up with the dropdowns beside it). */
42
+ variant: 'default' | 'link' | 'bar';
42
43
  /** Whether `slot="icon"` has content, so an omitted icon leaves no empty box. */
43
44
  private hasIcon;
44
45
  private onIconSlotChange;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MenuItem
3
- } from "../chunk-KHPJ5FAJ.js";
3
+ } from "../chunk-URC5XBTL.js";
4
4
  import "../chunk-PB7ZPPLP.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -5,6 +5,9 @@ import { LitElement } from 'lit';
5
5
  * Rounded call-to-action banner (title, subtitle, one outlined button) on a dark panel or a
6
6
  * background image. Port of `SankhyaUI`'s React `PromoBanner`; the button fires an `action` event
7
7
  * (detail `{ href }`, empty unless set) in place of `onAction`.
8
+ *
9
+ * @cssprop --st-promo-banner-margin - Overrides the banner's margin.
10
+ * @cssprop --st-promo-banner-padding - Overrides the banner's padding.
8
11
  */
9
12
  declare class PromoBanner extends LitElement {
10
13
  static styles: lit.CSSResult;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PromoBanner
3
- } from "../chunk-3ERKQNZT.js";
3
+ } from "../chunk-HGJT24UG.js";
4
4
  import "../chunk-3VE6VFJ4.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -9,6 +9,7 @@ import { LitElement } from 'lit';
9
9
  *
10
10
  * @slot - The section's content.
11
11
  * @cssprop --st-section-bg - Overrides the background colour picked by `background`.
12
+ * @cssprop --st-section-padding-inline - Overrides the left/right padding (not with `width="full"`).
12
13
  * @csspart inner - The width-limited content box.
13
14
  * @csspart header - The heading block.
14
15
  */
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Section
3
- } from "../chunk-N63TVWK3.js";
3
+ } from "../chunk-NN3OCPDV.js";
4
4
  import "../chunk-3VE6VFJ4.js";
5
5
  import "../chunk-RHAOQ6K4.js";
6
6
  import "../chunk-EUXUH3YW.js";
@@ -6,7 +6,12 @@ interface StatItem {
6
6
  label: string;
7
7
  description?: string;
8
8
  }
9
- /** Responsive grid of headline numbers with a label and optional description. Port of React `Stats`. */
9
+ /**
10
+ * Responsive grid of headline numbers with a label and optional description. Port of React `Stats`.
11
+ * `inverted` puts it on the dark band (`--st-cms-band-dark-bg`), which stays dark in the dark theme.
12
+ *
13
+ * @cssprop --st-stats-padding - Overrides the block's padding.
14
+ */
10
15
  declare class Stats extends LitElement {
11
16
  static styles: lit.CSSResult;
12
17
  items: StatItem[];
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Stats
3
- } from "../chunk-USNFT4DU.js";
3
+ } from "../chunk-6H262SG6.js";
4
4
  import "../chunk-RHAOQ6K4.js";
5
5
  import "../chunk-EUXUH3YW.js";
6
6
  export {
@@ -40,6 +40,7 @@ interface TestimonialItem {
40
40
  * (e.g. "Explore customer stories").
41
41
  *
42
42
  * @fires testimonials-link - Cancelable, before following a story or section link. Detail `{ href }`.
43
+ * @cssprop --st-testimonials-padding - Overrides the section's padding.
43
44
  */
44
45
  declare class Testimonials extends LitElement {
45
46
  static styles: lit.CSSResult;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Testimonials
3
- } from "../chunk-S4ARRDAI.js";
3
+ } from "../chunk-ZRXYWH6C.js";
4
4
  import "../chunk-PB7ZPPLP.js";
5
5
  import "../chunk-3VE6VFJ4.js";
6
6
  import "../chunk-RHAOQ6K4.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sankhyatronics/sankhya-cms",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sankhyatronics/SankhyaCMS.git",
@@ -142,7 +142,9 @@
142
142
  "clean": "rimraf dist",
143
143
  "test": "vitest run",
144
144
  "migrate-json": "node scripts/migrate-json.mjs",
145
- "analyze": "cem analyze"
145
+ "analyze": "cem analyze",
146
+ "prepack": "node ../../scripts/resolve-workspace-deps.mjs",
147
+ "postpack": "node ../../scripts/resolve-workspace-deps.mjs --restore"
146
148
  },
147
149
  "dependencies": {
148
150
  "dompurify": "^3.4.16",
@@ -150,17 +152,6 @@
150
152
  "lit": "^3.3.3",
151
153
  "marked": "^18.1.0"
152
154
  },
153
- "devDependencies": {
154
- "@sankhyatronics/oxlint-config": "workspace:*",
155
- "@sankhyatronics/typescript-config": "workspace:*",
156
- "oxlint": "catalog:",
157
- "rimraf": "catalog:",
158
- "tsup": "catalog:",
159
- "typescript": "catalog:",
160
- "vitest": "catalog:",
161
- "@types/node": "catalog:",
162
- "@custom-elements-manifest/analyzer": "catalog:"
163
- },
164
155
  "keywords": [
165
156
  "web-components",
166
157
  "lit",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cookie-consent/CookieConsent.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\n\r\nimport { buttonResetStyles, controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\nimport type { CookieConsentEventDetail, CookieConsentStatus } from './CookieConsentEvents';\r\n\r\nconst DEFAULT_STORAGE_KEY = 'sankhya_ui_cookie_consent';\r\n\r\n/**\r\n * Fixed bottom consent bar. The source read/wrote consent through a React `UserContext`; here the\r\n * element persists the choice itself in localStorage (`storage-key`, default the source's\r\n * `sankhya_ui_cookie_consent`; storage errors are ignored) and renders nothing once a choice\r\n * exists. Fires `cookie-consent-accept` / `cookie-consent-refuse` (detail `{ status }`). The\r\n * default slot replaces the message text.\r\n */\r\n@customElement('st-cookie-consent')\r\nexport class CookieConsent extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n @keyframes st-cookie-slide-up {\r\n from {\r\n transform: translateY(100%);\r\n }\r\n to {\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n :host {\r\n position: fixed;\r\n bottom: 0;\r\n left: 0;\r\n width: 100%;\r\n box-sizing: border-box;\r\n z-index: 9999;\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-16);\r\n padding: var(--st-space-24);\r\n background: var(--st-color-surface);\r\n color: var(--st-color-text);\r\n border-top: 1px solid var(--st-color-border);\r\n box-shadow: 0 -4px 10px var(--st-shadow-color-sm);\r\n animation: st-cookie-slide-up 0.3s ease-out;\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n .content {\r\n flex: 1;\r\n }\r\n\r\n .message {\r\n margin: 0;\r\n font-size: var(--st-text-md);\r\n line-height: 1.5;\r\n }\r\n\r\n .link {\r\n color: var(--st-color-accent-text);\r\n text-decoration: underline;\r\n margin-left: var(--st-space-4);\r\n }\r\n\r\n .link:hover {\r\n text-decoration: none;\r\n }\r\n\r\n .actions {\r\n display: flex;\r\n gap: var(--st-space-12);\r\n flex-shrink: 0;\r\n }\r\n\r\n .btn {\r\n ${buttonResetStyles}\r\n padding: var(--st-space-8) var(--st-space-16);\r\n border: 1px solid transparent;\r\n border-radius: var(--st-radius-xs);\r\n font-weight: var(--st-font-weight-medium);\r\n font-size: var(--st-text-md);\r\n transition:\r\n background-color 0.2s ease,\r\n color 0.2s ease;\r\n }\r\n\r\n .accept {\r\n background: var(--st-button-primary-bg);\r\n color: var(--st-button-primary-color);\r\n }\r\n\r\n .accept:hover {\r\n opacity: 0.9;\r\n }\r\n\r\n .refuse {\r\n border-color: var(--st-color-border);\r\n color: var(--st-color-text-muted);\r\n }\r\n\r\n .refuse:hover {\r\n background: var(--st-color-hover);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n @media (min-width: 768px) {\r\n :host {\r\n flex-direction: row;\r\n align-items: center;\r\n justify-content: space-between;\r\n padding: var(--st-space-16) var(--st-space-32);\r\n }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n :host {\r\n animation: none;\r\n }\r\n .btn {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n message = '';\r\n\r\n @property({ type: String, attribute: 'accept-button-text' })\r\n acceptButtonText = 'Accept';\r\n\r\n @property({ type: String, attribute: 'refuse-button-text' })\r\n refuseButtonText = 'Refuse';\r\n\r\n @property({ type: String, attribute: 'privacy-policy-link' })\r\n privacyPolicyLink = '';\r\n\r\n @property({ type: String, attribute: 'privacy-policy-text' })\r\n privacyPolicyText = 'Privacy Policy';\r\n\r\n @property({ type: String, attribute: 'storage-key' })\r\n storageKey = DEFAULT_STORAGE_KEY;\r\n\r\n /** The stored choice, or `null` while undecided (the bar is only shown then). */\r\n @state() private consent: CookieConsentStatus | null = null;\r\n\r\n connectedCallback(): void {\r\n super.connectedCallback();\r\n this.consent = this.readStored();\r\n }\r\n\r\n private readStored(): CookieConsentStatus | null {\r\n try {\r\n const saved = localStorage.getItem(this.storageKey);\r\n return saved === 'accepted' || saved === 'refused' ? saved : null;\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n private choose(status: CookieConsentStatus): void {\r\n this.consent = status;\r\n try {\r\n localStorage.setItem(this.storageKey, status);\r\n } catch {\r\n // Storage unavailable (private mode, blocked): the choice just doesn't persist.\r\n }\r\n this.dispatchEvent(\r\n new CustomEvent<CookieConsentEventDetail>(status === 'accepted' ? 'cookie-consent-accept' : 'cookie-consent-refuse', {\r\n detail: { status },\r\n bubbles: true,\r\n composed: true\r\n })\r\n );\r\n }\r\n\r\n render() {\r\n if (this.consent !== null) return nothing;\r\n return html`\r\n <div class=\"content\" part=\"content\">\r\n <p class=\"message\" part=\"message\">\r\n <slot>\r\n ${this.message || 'We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.'}\r\n ${this.privacyPolicyLink\r\n ? html`<a class=\"link\" part=\"link\" href=${this.privacyPolicyLink} target=\"_blank\" rel=\"noopener noreferrer\">${this.privacyPolicyText}</a>`\r\n : nothing}\r\n </slot>\r\n </p>\r\n </div>\r\n <div class=\"actions\" part=\"actions\">\r\n <button class=\"btn refuse\" part=\"refuse\" type=\"button\" @click=${() => this.choose('refused')}>${this.refuseButtonText}</button>\r\n <button class=\"btn accept\" part=\"accept\" type=\"button\" @click=${() => this.choose('accepted')}>${this.acceptButtonText}</button>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/promo-banner/PromoBanner.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { buttonResetStyles, controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\nimport { ctaLinkStyles, sectionSubtitleStyles, sectionTitleStyles } from '../shared/section-styles';\r\nimport type { HeroActionEventDetail } from '../hero/HeroEvents';\r\n\r\n/**\r\n * Rounded call-to-action banner (title, subtitle, one outlined button) on a dark panel or a\r\n * background image. Port of `SankhyaUI`'s React `PromoBanner`; the button fires an `action` event\r\n * (detail `{ href }`, empty unless set) in place of `onAction`.\r\n */\r\n@customElement('st-promo-banner')\r\nexport class PromoBanner extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n width: calc(100% - 48px);\r\n max-width: var(--st-cms-container-max);\r\n margin: var(--st-space-40) auto;\r\n padding: 100px var(--st-space-24);\r\n border-radius: var(--st-space-24);\r\n background-color: var(--st-color-text-strong);\r\n background-size: cover;\r\n background-position: center;\r\n color: var(--st-color-on-solid);\r\n text-align: center;\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background-color: var(--st-color-subtle);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: 800px;\r\n margin: 0 auto;\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n gap: var(--st-space-32);\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n color: inherit;\r\n margin: 0;\r\n letter-spacing: -0.02em;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n color: inherit;\r\n opacity: 0.8;\r\n margin: 0;\r\n }\r\n\r\n .actions {\r\n margin-top: var(--st-space-16);\r\n }\r\n\r\n .cta {\r\n ${buttonResetStyles}\r\n ${ctaLinkStyles}\r\n border: 1px solid currentColor;\r\n color: inherit;\r\n }\r\n\r\n .cta:hover {\r\n transform: scale(1.05);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n width: auto;\r\n margin: var(--st-space-24);\r\n padding: 60px var(--st-space-24);\r\n border-radius: var(--st-radius-lg);\r\n }\r\n .actions,\r\n .cta {\r\n width: 100%;\r\n }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .cta {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n protected willUpdate(): void {\r\n this.style.backgroundImage = this.imageSrc ? `url(${JSON.stringify(this.imageSrc)})` : '';\r\n }\r\n\r\n private onAction = (): void => {\r\n this.dispatchEvent(\r\n new CustomEvent<HeroActionEventDetail>('action', { detail: { href: this.href }, bubbles: true, composed: true })\r\n );\r\n };\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n <h2 class=\"title\" part=\"title\">${this.title}</h2>\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n <slot></slot>\r\n ${this.actionLabel\r\n ? html`<div class=\"actions\" part=\"actions\">\r\n <button class=\"cta\" part=\"action\" type=\"button\" @click=${this.onAction}>${this.actionLabel}</button>\r\n </div>`\r\n : nothing}\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAYjC,IAAM,cAAN,cAA0B,WAAW;AAAA,EAArC;AAAA;AAoFL,iBAAQ;AAGR,oBAAW;AAGX,uBAAc;AAGd,gBAAO;AAGP,oBAAW;AAGX,oBAAW;AAMX,SAAQ,WAAW,MAAY;AAC7B,WAAK;AAAA,QACH,IAAI,YAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,MACjH;AAAA,IACF;AAAA;AAAA,EARU,aAAmB;AAC3B,SAAK,MAAM,kBAAkB,KAAK,WAAW,OAAO,KAAK,UAAU,KAAK,QAAQ,CAAC,MAAM;AAAA,EACzF;AAAA,EAQA,SAAS;AACP,WAAO;AAAA;AAAA,yCAE8B,KAAK,KAAK;AAAA,UACzC,KAAK,WAAW,2CAA2C,KAAK,QAAQ,SAAS,OAAO;AAAA;AAAA,UAExF,KAAK,cACH;AAAA,uEAC2D,KAAK,QAAQ,IAAI,KAAK,WAAW;AAAA,sBAE5F,OAAO;AAAA;AAAA;AAAA,EAGjB;AACF;AA7Ha,YACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAef,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkBpB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOlB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWrB,iBAAiB;AAAA,QACjB,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;AA8BnB;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAnFf,YAoFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAtFf,YAuFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,eAAe,CAAC;AAAA,GAzF1C,YA0FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA5Ff,YA6FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GA/FvC,YAgGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAlG/B,YAmGX;AAnGW,cAAN;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/carousel/Carousel.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { buttonResetStyles, controlBaseStyles } from '../shared/styles';\nimport { reducedMotionStyles } from '../shared/section-styles';\nimport type { CarouselChangeEventDetail } from './CarouselEvents';\n\n/**\n * Cycles through its slotted children, one visible at a time, with optional autoplay, arrows and\n * dot indicators. The incoming slide slides in from the travel direction (CSS keyframes in place\n * of the source's framer-motion spring), or fades in with `transition=\"fade\"`. Autoplay pauses\n * while hovered or focused and stops when the element is disconnected; a paused slide keeps the\n * time it had left.\n *\n * `indicator-style=\"tabs\"` replaces the dots with a row of labelled tabs along the bottom, each\n * with a progress bar that fills while its slide is showing, plus a pause button — the tabbed hero\n * carousel layout (put `st-hero`s in it). Tab labels come from `tab-labels`, else each slide's\n * `data-tab-label` attribute, else its `title`.\n *\n * @fires carousel-change - Detail `{ index }`, when the visible slide changes.\n * @cssprop --st-carousel-tab-color - Tab text and progress colour (default: light, for slides with a dark image).\n * @cssprop --st-carousel-tabs-space - Room kept free under each slide's content for the tabs (default `6rem`).\n * @csspart tabs - The tab row.\n * @csspart tab - One tab button.\n * @csspart progress - A tab's progress bar.\n */\n@customElement('st-carousel')\nexport class Carousel extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n ::slotted(*) {\n display: none !important;\n }\n\n ::slotted([data-st-active]) {\n display: block !important;\n animation: st-carousel-in-next 0.4s ease both;\n }\n\n :host([data-direction='prev']) ::slotted([data-st-active]) {\n animation-name: st-carousel-in-prev;\n }\n\n :host([transition='fade']) ::slotted([data-st-active]),\n :host([transition='fade'][data-direction]) ::slotted([data-st-active]) {\n animation: st-carousel-fade 0.7s ease both;\n }\n\n @keyframes st-carousel-in-next {\n from {\n transform: translateX(10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-in-prev {\n from {\n transform: translateX(-10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .nav {\n ${buttonResetStyles}\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-38);\n height: var(--st-size-38);\n border-radius: var(--st-radius-circle);\n border: 1px solid var(--st-color-border);\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: var(--st-text-xl);\n opacity: 0.8;\n transition:\n opacity 0.3s ease,\n transform 0.3s ease;\n }\n\n .nav:hover {\n opacity: 1;\n transform: translateY(-50%) scale(1.1);\n }\n\n .prev {\n left: var(--st-space-12);\n }\n\n .next {\n right: var(--st-space-12);\n }\n\n .indicators {\n position: absolute;\n bottom: var(--st-space-24);\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n gap: var(--st-space-12);\n }\n\n .dot {\n ${buttonResetStyles}\n width: var(--st-space-12);\n height: var(--st-space-12);\n padding: 0;\n border-radius: var(--st-radius-circle);\n background: var(--st-color-border-strong);\n transition:\n background 0.3s ease,\n transform 0.3s ease;\n }\n\n .dot:hover {\n background: var(--st-color-text-muted);\n }\n\n .dot.active {\n background: var(--st-color-text-strong);\n transform: scale(1.2);\n }\n\n /* ---- indicator-style=\"tabs\" ---- */\n\n :host([indicator-style='tabs']) ::slotted(*) {\n padding-bottom: var(--st-carousel-tabs-space, 6rem);\n }\n\n .tabs {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10;\n color: var(--st-carousel-tab-color, var(--st-color-on-solid));\n }\n\n .tabs-inner {\n display: flex;\n align-items: flex-start;\n gap: var(--st-space-24);\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n box-sizing: border-box;\n padding: 0 var(--st-space-24) var(--st-space-24);\n }\n\n .tablist {\n flex: 1;\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: minmax(0, 1fr);\n gap: var(--st-space-24);\n }\n\n .tab {\n ${buttonResetStyles}\n display: flex;\n flex-direction: column;\n gap: var(--st-space-12);\n padding: var(--st-space-12) 0;\n color: inherit;\n text-align: left;\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n .tab:hover,\n .tab.active {\n opacity: 1;\n }\n\n .tab:focus-visible,\n .play:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 4px;\n }\n\n .progress {\n position: relative;\n display: block;\n height: 3px;\n border-radius: 2px;\n overflow: hidden;\n background: color-mix(in oklch, currentColor 30%, transparent);\n }\n\n .fill {\n position: absolute;\n inset: 0;\n background: currentColor;\n transform: scaleX(0);\n transform-origin: left center;\n }\n\n .tab.active .fill {\n transform: scaleX(1);\n }\n\n .tab.active.running .fill {\n animation: st-carousel-progress var(--st-carousel-interval, 5000ms) linear both;\n }\n\n :host([data-paused]) .tab.active.running .fill {\n animation-play-state: paused;\n }\n\n @keyframes st-carousel-progress {\n from {\n transform: scaleX(0);\n }\n to {\n transform: scaleX(1);\n }\n }\n\n .play {\n ${buttonResetStyles}\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-32);\n height: var(--st-size-32);\n margin-top: var(--st-space-4);\n border-radius: var(--st-radius-circle);\n color: inherit;\n box-shadow: inset 0 0 0 1.5px color-mix(in oklch, currentColor 60%, transparent);\n }\n\n .play:hover {\n background: color-mix(in oklch, currentColor 15%, transparent);\n }\n\n .tab-current {\n display: none;\n }\n\n @media (max-width: 768px) {\n .tablist {\n gap: var(--st-space-8);\n }\n\n .tab-label {\n display: none;\n }\n\n .tab-current {\n display: block;\n margin: 0 0 var(--st-space-4);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n }\n\n .tabs-inner {\n flex-wrap: wrap;\n align-items: center;\n }\n }\n\n @media (min-width: 1024px) {\n .tabs-inner {\n padding: 0 var(--st-space-32) var(--st-space-32);\n }\n }\n\n ${reducedMotionStyles}\n @media (prefers-reduced-motion: reduce) {\n ::slotted([data-st-active]) {\n animation: none;\n }\n .tab.active.running .fill {\n animation: none;\n }\n }\n `;\n\n @property({ type: Boolean, attribute: 'auto-play' })\n autoPlay = true;\n\n /** Autoplay delay in milliseconds. */\n @property({ type: Number })\n interval = 5000;\n\n @property({ type: Boolean, attribute: 'show-arrows' })\n showArrows = true;\n\n @property({ type: Boolean, attribute: 'show-indicators' })\n showIndicators = true;\n\n /** `dots` (default) or `tabs`: labelled tabs with progress bars along the bottom. */\n @property({ type: String, reflect: true, attribute: 'indicator-style' })\n indicatorStyle: 'dots' | 'tabs' = 'dots';\n\n /** `slide` (default) or `fade`. */\n @property({ type: String, reflect: true })\n transition: 'slide' | 'fade' = 'slide';\n\n /** Tab labels, one per slide, for `indicator-style=\"tabs\"`. Missing entries fall back to the slide's `data-tab-label`, then its `title`. */\n @property({ attribute: false })\n tabLabels: string[] = [];\n\n @state() private index = 0;\n @state() private count = 0;\n @state() private slideLabels: string[] = [];\n /** Paused with the pause button; stays paused until the button is pressed again. */\n @state() private userPaused = false;\n /** Paused while hovered or focused. */\n private paused = false;\n private timer?: ReturnType<typeof setTimeout>;\n /** Time left on the current slide, so a pause resumes where it stopped. */\n private remaining = 0;\n private startedAt = 0;\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener('mouseenter', this.pause);\n this.addEventListener('mouseleave', this.resume);\n this.addEventListener('focusin', this.pause);\n this.addEventListener('focusout', this.resume);\n }\n\n disconnectedCallback() {\n this.stopTimer();\n this.removeEventListener('mouseenter', this.pause);\n this.removeEventListener('mouseleave', this.resume);\n this.removeEventListener('focusin', this.pause);\n this.removeEventListener('focusout', this.resume);\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: Map<string, unknown>) {\n if (changed.has('interval')) this.style.setProperty('--st-carousel-interval', `${this.interval}ms`);\n }\n\n protected updated(changed: Map<string, unknown>) {\n if (changed.has('index') || changed.has('count') || changed.has('indicatorStyle') || changed.has('tabLabels')) this.syncSlides();\n if (changed.has('autoPlay') || changed.has('interval') || changed.has('count')) this.restartTimer();\n }\n\n private get halted(): boolean {\n return this.paused || this.userPaused;\n }\n\n /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */\n private hold(update: () => void) {\n const was = this.halted;\n update();\n const now = this.halted;\n if (was === now) return;\n this.toggleAttribute('data-paused', now);\n if (now) {\n if (this.timer !== undefined) this.remaining -= performance.now() - this.startedAt;\n this.stopTimer();\n } else {\n this.startTimer();\n }\n }\n\n private pause = () => this.hold(() => (this.paused = true));\n\n private resume = () => this.hold(() => (this.paused = false));\n\n private togglePlay = () => this.hold(() => (this.userPaused = !this.userPaused));\n\n private get slides(): Element[] {\n return this.shadowRoot?.querySelector('slot')?.assignedElements({ flatten: true }) ?? [];\n }\n\n private labelFor(i: number): string {\n return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;\n }\n\n private syncSlides() {\n const tabs = this.indicatorStyle === 'tabs';\n this.slides.forEach((el, i) => {\n el.toggleAttribute('data-st-active', i === this.index);\n if (tabs) {\n el.setAttribute('role', 'tabpanel');\n el.setAttribute('aria-label', this.labelFor(i));\n } else if (el.getAttribute('role') === 'tabpanel') {\n el.removeAttribute('role');\n el.removeAttribute('aria-label');\n }\n });\n }\n\n private onSlotChange() {\n const slides = this.slides;\n this.count = slides.length;\n this.slideLabels = slides.map(el => (el as HTMLElement).dataset.tabLabel || (el as HTMLElement).title || '');\n if (this.index >= this.count) this.index = 0;\n this.syncSlides();\n }\n\n private stopTimer() {\n if (this.timer !== undefined) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private startTimer() {\n this.stopTimer();\n if (!this.autoPlay || this.count < 2 || this.halted) return;\n this.startedAt = performance.now();\n this.timer = setTimeout(() => this.go(this.index + 1, 'next'), Math.max(0, this.remaining));\n }\n\n private restartTimer() {\n this.remaining = this.interval;\n this.startTimer();\n }\n\n private go(target: number, direction: 'next' | 'prev') {\n if (this.count === 0) return;\n this.setAttribute('data-direction', direction);\n this.index = (target + this.count) % this.count;\n this.dispatchEvent(\n new CustomEvent<CarouselChangeEventDetail>('carousel-change', {\n detail: { index: this.index },\n bubbles: true,\n composed: true,\n }),\n );\n this.restartTimer();\n }\n\n private onTabKeydown(event: KeyboardEvent) {\n const step = { ArrowRight: 1, ArrowLeft: -1 }[event.key];\n let target: number | undefined;\n if (step !== undefined) target = this.index + step;\n else if (event.key === 'Home') target = 0;\n else if (event.key === 'End') target = this.count - 1;\n if (target === undefined) return;\n event.preventDefault();\n this.go(target, step === -1 || target < this.index ? 'prev' : 'next');\n void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>('.tab.active')?.focus());\n }\n\n private renderTabs() {\n const running = this.autoPlay && this.count > 1;\n return html`<div class=\"tabs\" part=\"tabs\">\n <div class=\"tabs-inner\">\n <p class=\"tab-current\" aria-hidden=\"true\">${this.labelFor(this.index)}</p>\n <div class=\"tablist\" role=\"tablist\" aria-label=\"Slides\" @keydown=${this.onTabKeydown}>\n ${Array.from({ length: this.count }, (_, i) => {\n const active = i === this.index;\n return html`\n <button\n part=\"tab\"\n type=\"button\"\n role=\"tab\"\n class=\"tab ${active ? 'active' : ''} ${running ? 'running' : ''}\"\n aria-selected=${active ? 'true' : 'false'}\n tabindex=${active ? 0 : -1}\n @click=${() => active || this.go(i, i > this.index ? 'next' : 'prev')}\n >\n <span class=\"progress\" part=\"progress\"><span class=\"fill\"></span></span>\n <span class=\"tab-label\">${this.labelFor(i)}</span>\n </button>\n `;\n })}\n </div>\n ${running\n ? html`<button\n part=\"play-button\"\n type=\"button\"\n class=\"play\"\n aria-label=${this.userPaused ? 'Play slides' : 'Pause slides'}\n @click=${this.togglePlay}\n >\n ${this.userPaused\n ? html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M3 1.5v9l7.5-4.5z\" fill=\"currentColor\" /></svg>`\n : html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M2.5 1.5h2.5v9H2.5zM7 1.5h2.5v9H7z\" fill=\"currentColor\" /></svg>`}\n </button>`\n : nothing}\n </div>\n </div>`;\n }\n\n private renderDots() {\n return html`<div class=\"indicators\" part=\"indicators\">\n ${Array.from(\n { length: this.count },\n (_, i) => html`\n <button\n part=\"dot\"\n class=\"dot ${i === this.index ? 'active' : ''}\"\n aria-label=\"Go to slide ${i + 1}\"\n aria-current=${i === this.index ? 'true' : 'false'}\n @click=${() => this.go(i, i > this.index ? 'next' : 'prev')}\n ></button>\n `,\n )}\n </div>`;\n }\n\n render() {\n const multiple = this.count > 1;\n return html`\n <slot @slotchange=${this.onSlotChange}></slot>\n ${this.showArrows && multiple\n ? html`\n <button part=\"nav-button prev\" class=\"nav prev\" aria-label=\"Previous Slide\" @click=${() => this.go(this.index - 1, 'prev')}>&#10094;</button>\n <button part=\"nav-button next\" class=\"nav next\" aria-label=\"Next Slide\" @click=${() => this.go(this.index + 1, 'next')}>&#10095;</button>\n `\n : nothing}\n ${this.showIndicators && multiple ? (this.indicatorStyle === 'tabs' ? this.renderTabs() : this.renderDots()) : nothing}\n `;\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA2Df,iBAAiB;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,QA6CjB,iBAAiB;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,QAsDjB,iBAAiB;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,QAgEjB,iBAAiB;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,MAiDnB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,YAAY,CAAC;AAAA,GA5RxC,SA6RX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAhSf,SAiSX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,cAAc,CAAC;AAAA,GAnS1C,SAoSX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,kBAAkB,CAAC;AAAA,GAtS9C,SAuSX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,kBAAkB,CAAC;AAAA,GA1S5D,SA2SX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA9S9B,SA+SX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAlTnB,SAmTX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GArTI,SAqTM;AACA;AAAA,EAAhB,MAAM;AAAA,GAtTI,SAsTM;AACA;AAAA,EAAhB,MAAM;AAAA,GAvTI,SAuTM;AAEA;AAAA,EAAhB,MAAM;AAAA,GAzTI,SAyTM;AAzTN,WAAN;AAAA,EADN,cAAc,aAAa;AAAA,GACf;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/feature-split/FeatureSplit.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, ctaButtonStyles, fontFamilyStyles } from '../shared/styles';\r\nimport '../markdown';\r\nimport {\r\n cardTitleStyles,\r\n iconTileStyles,\r\n reducedMotionStyles,\r\n sectionTitleStyles,\r\n} from '../shared/section-styles';\r\nimport type { FeatureSplitActionEventDetail } from './FeatureSplitEvents';\r\n\r\nexport interface FeatureSplitItem {\r\n /** Iconify icon name, e.g. `mdi:check`. */\r\n icon?: string;\r\n title: string;\r\n /** Markdown. */\r\n description: string;\r\n}\r\n\r\nexport type FeatureSplitImagePosition = 'left' | 'right' | 'top';\r\n\r\n/** A title/markdown-subtitle/feature-list block beside (or under) an image. */\r\n@customElement('st-feature-split')\r\nexport class FeatureSplit extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n padding: var(--st-space-24);\r\n background: var(--st-color-page);\r\n ${fontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n display: grid;\r\n grid-template-columns: 1fr 1fr;\r\n gap: var(--st-space-48);\r\n align-items: center;\r\n }\r\n\r\n :host([image-position='left']) .container {\r\n direction: rtl;\r\n }\r\n\r\n :host([image-position='left']) .content {\r\n direction: ltr;\r\n }\r\n\r\n :host([image-position='top']) .container {\r\n grid-template-columns: 1fr;\r\n text-align: center;\r\n }\r\n\r\n :host([image-position='top']) .content {\r\n align-items: center;\r\n }\r\n\r\n :host([image-position='top']) .image-wrapper {\r\n order: -1;\r\n max-width: 800px;\r\n margin: 0 auto;\r\n }\r\n\r\n .content {\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-32);\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .subtitle {\r\n color: var(--st-color-text-muted);\r\n font-size: var(--st-text-base);\r\n line-height: 1.6;\r\n }\r\n\r\n .list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-24);\r\n margin-top: var(--st-space-16);\r\n }\r\n\r\n .item {\r\n display: flex;\r\n gap: var(--st-space-16);\r\n align-items: flex-start;\r\n text-align: left;\r\n }\r\n\r\n .icon {\r\n ${iconTileStyles}\r\n width: var(--st-space-48);\r\n height: var(--st-space-48);\r\n font-size: 24px;\r\n }\r\n\r\n .item-title {\r\n ${cardTitleStyles}\r\n }\r\n\r\n .item-description {\r\n color: var(--st-color-text-muted);\r\n font-size: var(--st-text-sm);\r\n line-height: 1.5;\r\n }\r\n\r\n .action {\r\n ${ctaButtonStyles}\r\n justify-self: start;\r\n padding: var(--st-space-16);\r\n border-radius: var(--st-radius-lg);\r\n }\r\n\r\n .image-wrapper {\r\n width: 100%;\r\n height: 100%;\r\n min-height: 400px;\r\n border-radius: var(--st-space-24);\r\n overflow: hidden;\r\n box-shadow: 0 20px 40px -12px var(--st-shadow-color-md);\r\n }\r\n\r\n .image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n transition: transform 0.5s ease;\r\n }\r\n\r\n .image:hover {\r\n transform: scale(1.02);\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .item-title {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([inverted]) .subtitle,\r\n :host([inverted]) .item-description {\r\n color: var(--st-color-border);\r\n }\r\n\r\n :host([inverted]) .icon {\r\n background: var(--st-color-text);\r\n color: var(--st-color-border);\r\n }\r\n\r\n @media (max-width: 1024px) {\r\n .container {\r\n gap: var(--st-space-40);\r\n }\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-48) var(--st-space-24);\r\n }\r\n\r\n .container {\r\n grid-template-columns: 1fr;\r\n direction: ltr !important;\r\n }\r\n\r\n .image-wrapper {\r\n min-height: 300px;\r\n order: -1;\r\n }\r\n }\r\n\r\n ${reducedMotionStyles}\r\n `;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n /** Markdown. */\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ attribute: false })\r\n items: FeatureSplitItem[] = [];\r\n\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n @property({ type: String, attribute: 'image-alt' })\r\n imageAlt = '';\r\n\r\n @property({ type: String, attribute: 'image-position', reflect: true })\r\n imagePosition: FeatureSplitImagePosition = 'right';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n private onAction() {\r\n const event = new CustomEvent<FeatureSplitActionEventDetail>('feature-split-action', {\r\n detail: { href: this.href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true,\r\n });\r\n if (this.dispatchEvent(event)) window.location.href = this.href;\r\n }\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n <div class=\"content\" part=\"content\">\r\n <h2 class=\"title\" part=\"title\">${this.title}</h2>\r\n ${this.subtitle\r\n ? html`<div class=\"subtitle\" part=\"subtitle\"><st-markdown .content=${this.subtitle}></st-markdown></div>`\r\n : nothing}\r\n ${this.items.length > 0\r\n ? html`<div class=\"list\" part=\"list\">\r\n ${this.items.map(\r\n (item) => html`\r\n <div class=\"item\" part=\"item\">\r\n ${item.icon\r\n ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${item.icon}></iconify-icon></div>`\r\n : nothing}\r\n <div>\r\n <h3 class=\"item-title\" part=\"item-title\">${item.title}</h3>\r\n <div class=\"item-description\" part=\"item-description\">\r\n <st-markdown .content=${item.description}></st-markdown>\r\n </div>\r\n </div>\r\n </div>\r\n `,\r\n )}\r\n </div>`\r\n : nothing}\r\n ${this.actionLabel && this.href\r\n ? html`<button class=\"action\" part=\"action\" type=\"button\" @click=${this.onAction}>${this.actionLabel}</button>`\r\n : nothing}\r\n </div>\r\n <div class=\"image-wrapper\" part=\"image-wrapper\">\r\n <img class=\"image\" part=\"image\" src=${this.imageSrc} alt=${this.imageAlt || this.title} />\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/items-accordion/ItemsAccordion.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { buttonResetStyles, controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport {\r\n reducedMotionStyles,\r\n sectionHeaderStyles,\r\n sectionSubtitleStyles,\r\n sectionTitleStyles,\r\n} from '../shared/section-styles';\r\nimport type { AccordionToggleEventDetail } from './ItemsAccordionEvents';\r\n\r\nexport interface AccordionItem {\r\n id: string;\r\n title: string;\r\n content: string;\r\n}\r\n\r\n/** A vertical list of collapsible title/content rows; one open at a time unless `allow-multiple`. */\r\n@customElement('st-items-accordion')\r\nexport class ItemsAccordion extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n padding: var(--st-cms-section-padding) var(--st-space-24);\r\n background: var(--st-color-page);\r\n ${fontFamilyStyles}\r\n }\r\n\r\n .container {\r\n max-width: 800px;\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n font-size: var(--st-text-2xl);\r\n margin-bottom: var(--st-space-12);\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n font-size: var(--st-text-base);\r\n margin: 0;\r\n }\r\n\r\n .list {\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-16);\r\n }\r\n\r\n .item {\r\n border: 1px solid var(--st-color-border);\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-surface);\r\n overflow: hidden;\r\n transition:\r\n border-color 0.2s ease,\r\n box-shadow 0.2s ease;\r\n }\r\n\r\n .item.open {\r\n border-color: var(--st-color-border-strong);\r\n box-shadow: 0 4px 6px -1px var(--st-shadow-color-sm);\r\n }\r\n\r\n .trigger {\r\n ${buttonResetStyles}\r\n width: 100%;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n padding: var(--st-space-24);\r\n text-align: left;\r\n font-size: var(--st-text-lg);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .trigger:hover {\r\n background: var(--st-color-hover);\r\n }\r\n\r\n .chevron {\r\n flex-shrink: 0;\r\n margin-left: var(--st-space-16);\r\n font-size: 24px;\r\n color: var(--st-color-text-faint);\r\n transition: transform 0.3s ease;\r\n }\r\n\r\n .open .chevron {\r\n transform: rotate(180deg);\r\n }\r\n\r\n .content {\r\n display: grid;\r\n grid-template-rows: 0fr;\r\n transition: grid-template-rows 0.3s ease;\r\n }\r\n\r\n .open .content {\r\n grid-template-rows: 1fr;\r\n }\r\n\r\n .content-clip {\r\n overflow: hidden;\r\n min-height: 0;\r\n }\r\n\r\n .content-inner {\r\n padding: 0 var(--st-space-24) var(--st-space-24);\r\n color: var(--st-color-text);\r\n line-height: 1.6;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-48) var(--st-space-20);\r\n }\r\n\r\n .title {\r\n font-size: var(--st-text-xl);\r\n }\r\n }\r\n\r\n ${reducedMotionStyles}\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ attribute: false })\r\n items: AccordionItem[] = [];\r\n\r\n @property({ type: Boolean, attribute: 'allow-multiple' })\r\n allowMultiple = false;\r\n\r\n @state() private openIds = new Set<string>();\r\n\r\n private toggle(id: string) {\r\n const wasOpen = this.openIds.has(id);\r\n const next = new Set(this.allowMultiple ? this.openIds : []);\r\n if (wasOpen) next.delete(id);\r\n else next.add(id);\r\n this.openIds = next;\r\n this.dispatchEvent(\r\n new CustomEvent<AccordionToggleEventDetail>('accordion-toggle', {\r\n detail: { id, open: !wasOpen },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n ${this.title || this.subtitle\r\n ? html`<div class=\"header\" part=\"header\">\r\n ${this.title ? html`<h2 class=\"title\" part=\"title\">${this.title}</h2>` : nothing}\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n </div>`\r\n : nothing}\r\n <div class=\"list\" part=\"list\">\r\n ${this.items.map((item) => {\r\n const open = this.openIds.has(item.id);\r\n return html`\r\n <div class=\"item ${open ? 'open' : ''}\" part=\"item\">\r\n <button\r\n class=\"trigger\"\r\n part=\"trigger\"\r\n type=\"button\"\r\n aria-expanded=${open ? 'true' : 'false'}\r\n aria-controls=\"content-${item.id}\"\r\n @click=${() => this.toggle(item.id)}\r\n >\r\n <span>${item.title}</span>\r\n <iconify-icon class=\"chevron\" icon=\"mdi:chevron-down\"></iconify-icon>\r\n </button>\r\n <div class=\"content\" id=\"content-${item.id}\" part=\"content\" role=\"region\" ?inert=${!open}>\r\n <div class=\"content-clip\">\r\n <div class=\"content-inner\">${item.content}</div>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n })}\r\n </div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/features-section/FeaturesSection.ts","../src/features-section/FeatureItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { sectionSubtitleStyles, sectionTitleStyles, sectionHeaderStyles } from '../shared/section-styles';\r\nimport './FeatureItem';\r\n\r\n/** Data for one tile when using the `items` property (mirrors `st-feature-item`'s properties). */\r\nexport interface FeatureItemData {\r\n icon?: string;\r\n title: string;\r\n description: string;\r\n href?: string;\r\n}\r\n\r\n/**\r\n * A titled grid of feature tiles. Ports `SankhyaUI`'s React `FeaturesSection`: tiles come from the\r\n * `items` property, from slotted `st-feature-item` elements (the source's `children`), or both\r\n * (slotted first). `columns` sets the grid width (default 2; one column below 768px). `inverted`\r\n * is passed on to the `items` tiles; slotted tiles need their own `inverted` attribute.\r\n */\r\n@customElement('st-features-section')\r\nexport class FeaturesSection extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n padding: var(--st-cms-section-padding) var(--st-space-24);\r\n background: var(--st-color-surface);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n margin: 0 auto;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .subtitle {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--features-columns, 2), 1fr);\r\n gap: var(--st-space-32);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-48) var(--st-space-16);\r\n }\r\n\r\n .grid {\r\n grid-template-columns: 1fr;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n /** Applied to every tile built from `items`. */\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Number })\r\n columns = 0;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n /** Tiles to render (property only). */\r\n @property({ attribute: false })\r\n items: FeatureItemData[] = [];\r\n\r\n render() {\r\n const gridStyle = this.columns ? `--features-columns: ${this.columns}` : nothing;\r\n return html`\r\n <section class=\"container\" part=\"container\">\r\n <div class=\"header\" part=\"header\">\r\n <div class=\"title\" part=\"title\">${this.title}</div>\r\n ${this.subtitle ? html`<div class=\"subtitle\" part=\"subtitle\">${this.subtitle}</div>` : nothing}\r\n </div>\r\n <div class=\"grid\" part=\"grid\" style=${gridStyle}>\r\n <slot></slot>\r\n ${this.items.map(\r\n (item) => html`\r\n <st-feature-item\r\n .icon=${item.icon ?? ''}\r\n .title=${item.title}\r\n .description=${item.description}\r\n .href=${item.href ?? ''}\r\n .actionLabel=${this.actionLabel}\r\n ?inverted=${this.inverted}\r\n ></st-feature-item>\r\n `\r\n )}\r\n </div>\r\n </section>\r\n `;\r\n }\r\n}\r\n","import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { cardDescriptionStyles, cardTitleStyles } from '../shared/section-styles';\r\nimport '../card';\r\nimport '../markdown';\r\n\r\n/**\r\n * One feature tile for `st-features-section`: optional icon, title, Markdown description and an\r\n * optional \"Learn more\" link, rendered on an `st-card`. `icon` is an Iconify name (e.g.\r\n * `mdi:rocket`). The link is a plain `<a>` (the source used react-router's `Link` for non-http\r\n * hrefs; there is no Lit equivalent). The click is composed, so an SPA router can intercept it\r\n * (e.g. via `event.composedPath()`) and navigate client-side; `http(s)` links open in a new tab.\r\n */\r\n@customElement('st-feature-item')\r\nexport class FeatureItem extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n st-card {\r\n height: 100%;\r\n }\r\n\r\n .content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: var(--st-space-16);\r\n height: 100%;\r\n }\r\n\r\n .icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 48px;\r\n height: 48px;\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-subtle);\r\n color: var(--st-color-text-strong);\r\n margin-bottom: var(--st-space-8);\r\n font-size: 24px;\r\n }\r\n\r\n :host([inverted]) .icon {\r\n background: var(--st-color-text-muted);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .title {\r\n ${cardTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .description {\r\n ${cardDescriptionStyles}\r\n margin: 0;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .description {\r\n color: inherit;\r\n }\r\n\r\n .link {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--st-space-4);\r\n margin-top: auto;\r\n color: var(--st-color-text-muted);\r\n font-weight: var(--st-font-weight-medium);\r\n font-size: var(--st-text-md);\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .link:hover {\r\n color: var(--st-color-text-strong);\r\n text-decoration: underline;\r\n }\r\n\r\n :host([inverted]) .link,\r\n :host([inverted]) .link:hover {\r\n color: inherit;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .link {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n /** Iconify icon name, e.g. `mdi:rocket`. */\r\n @property({ type: String })\r\n icon = '';\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n /** Markdown. */\r\n @property({ type: String })\r\n description = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n const external = this.href.startsWith('http');\r\n return html`\r\n <st-card hoverable elevation=\"sm\" ?inverted=${this.inverted} part=\"card\">\r\n <div class=\"content\" part=\"content\">\r\n ${this.icon\r\n ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${this.icon}></iconify-icon></div>`\r\n : nothing}\r\n <h3 class=\"title\" part=\"title\">${this.title}</h3>\r\n <st-markdown class=\"description\" part=\"description\" .content=${this.description}></st-markdown>\r\n ${this.href\r\n ? html`\r\n <a\r\n class=\"link\"\r\n part=\"link\"\r\n href=${this.href}\r\n target=${external ? '_blank' : '_self'}\r\n rel=${external ? 'noopener noreferrer' : nothing}\r\n >\r\n ${this.actionLabel} <span>&rarr;</span>\r\n </a>\r\n `\r\n : nothing}\r\n </div>\r\n </st-card>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":["LitElement","css","html","nothing","customElement","property","LitElement","nothing","html","css","property","customElement"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/content-block/ContentBlock.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { sectionSubtitleStyles, sectionTitleStyles, sectionHeaderStyles } from '../shared/section-styles';\r\nimport '../markdown';\r\n\r\n/**\r\n * A long-form article section: centered title/subtitle, an optional featured image with caption,\r\n * then Markdown body text. Ports `SankhyaUI`'s React `ContentBlock`. The body comes from\r\n * `content-src` (a Markdown URL, as in the source) or an inline `content` string (added so the\r\n * block works without a fetch); `content-src` wins when both are set.\r\n */\r\n@customElement('st-content-block')\r\nexport class ContentBlock extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n padding: var(--st-space-24);\r\n background: var(--st-color-surface);\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n padding: 0 var(--st-space-48);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n line-height: 1.1;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .subtitle {\r\n color: inherit;\r\n }\r\n\r\n .featured-image {\r\n margin: 0 0 var(--st-space-48);\r\n border-radius: var(--st-radius-lg);\r\n overflow: hidden;\r\n }\r\n\r\n .featured-image img {\r\n width: 100%;\r\n height: auto;\r\n display: block;\r\n }\r\n\r\n figcaption {\r\n padding: var(--st-space-12);\r\n text-align: center;\r\n color: var(--st-color-text-muted);\r\n font-size: var(--st-text-xs);\r\n }\r\n\r\n st-markdown {\r\n color: var(--st-color-text);\r\n font-size: var(--st-text-xl);\r\n }\r\n\r\n :host([inverted]) st-markdown {\r\n color: inherit;\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-48) var(--st-space-24);\r\n }\r\n\r\n .container {\r\n padding: 0;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n /** URL of a Markdown file. */\r\n @property({ type: String, attribute: 'content-src' })\r\n contentSrc = '';\r\n\r\n /** Inline Markdown, used when `content-src` is not set. */\r\n @property({ type: String })\r\n content = '';\r\n\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n @property({ type: String, attribute: 'image-alt' })\r\n imageAlt = '';\r\n\r\n @property({ type: String, attribute: 'image-caption' })\r\n imageCaption = '';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n return html`\r\n <section class=\"container\" part=\"container\">\r\n <div class=\"header\" part=\"header\">\r\n ${this.title ? html`<div class=\"title\" part=\"title\">${this.title}</div>` : nothing}\r\n ${this.subtitle ? html`<div class=\"subtitle\" part=\"subtitle\">${this.subtitle}</div>` : nothing}\r\n </div>\r\n ${this.imageSrc\r\n ? html`\r\n <figure class=\"featured-image\" part=\"image\">\r\n <img src=${this.imageSrc} alt=${this.imageAlt || this.title} />\r\n ${this.imageCaption ? html`<figcaption>${this.imageCaption}</figcaption>` : nothing}\r\n </figure>\r\n `\r\n : nothing}\r\n <st-markdown part=\"body\" .src=${this.contentSrc} .content=${this.content}></st-markdown>\r\n </section>\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAajC,IAAM,eAAN,cAA2B,WAAW;AAAA,EAAtC;AAAA;AAiFL,iBAAQ;AAGR,oBAAW;AAIX,sBAAa;AAIb,mBAAU;AAGV,oBAAW;AAGX,oBAAW;AAGX,wBAAe;AAGf,oBAAW;AAAA;AAAA,EAEX,SAAS;AACP,WAAO;AAAA;AAAA;AAAA,YAGC,KAAK,QAAQ,uCAAuC,KAAK,KAAK,WAAW,OAAO;AAAA,YAChF,KAAK,WAAW,6CAA6C,KAAK,QAAQ,WAAW,OAAO;AAAA;AAAA,UAE9F,KAAK,WACH;AAAA;AAAA,2BAEe,KAAK,QAAQ,QAAQ,KAAK,YAAY,KAAK,KAAK;AAAA,kBACzD,KAAK,eAAe,mBAAmB,KAAK,YAAY,kBAAkB,OAAO;AAAA;AAAA,gBAGvF,OAAO;AAAA,wCACqB,KAAK,UAAU,aAAa,KAAK,OAAO;AAAA;AAAA;AAAA,EAG9E;AACF;AA7Ha,aACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA,QAIf,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAkBhB,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAInB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKlB,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;AAgD3B;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAhFf,aAiFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAnFf,aAoFX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,cAAc,CAAC;AAAA,GAvFzC,aAwFX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA3Ff,aA4FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GA9FvC,aA+FX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,YAAY,CAAC;AAAA,GAjGvC,aAkGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,gBAAgB,CAAC;AAAA,GApG3C,aAqGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAvG/B,aAwGX;AAxGW,eAAN;AAAA,EADN,cAAc,kBAAkB;AAAA,GACpB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mega-menu/MegaMenu.ts","../src/mega-menu/MegaMenuColumn.ts","../src/mega-menu/MegaMenuFeature.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\n\n/**\n * The rich layout of a mega-menu panel, after okta.com: an optional intro column on the left (a\n * large `heading`, a `description` and, under a divider, quick links in `slot=\"intro\"`), then the\n * link columns side by side (`st-mega-menu-column`s in the default slot), then an optional\n * featured column on the right (`featured-heading` over the `st-mega-menu-feature` cards in\n * `slot=\"featured\"`). Slot it into an `st-dropdown` with `mega` set.\n *\n * The layout follows the width it is given, not the viewport (a container query): side by side\n * when there is room; intro and featured column above/below two link columns on a medium panel;\n * everything stacked in the narrow drill-down panel `st-header` shows on a phone (where the intro\n * heading is left out — the drill-down already shows the section's name).\n *\n * @slot - The link columns (`st-mega-menu-column`s, or any blocks).\n * @slot intro - Quick links under the intro text, e.g. `st-menu-item`s with an icon.\n * @slot featured - Promo cards (`st-mega-menu-feature`s), stacked.\n * @csspart inner - The grid holding every area.\n * @csspart intro - The intro column.\n * @csspart columns - The grid holding the link columns.\n * @csspart featured - The featured column.\n */\n@customElement('st-mega-menu')\nexport class MegaMenu extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n container-type: inline-size;\n ${fontFamilyStyles}\n }\n\n .inner {\n display: grid;\n gap: 3rem;\n padding: 3rem 3.5rem;\n box-sizing: border-box;\n }\n\n .columns {\n display: grid;\n grid-template-columns: repeat(var(--st-mega-menu-columns, 3), minmax(0, 1fr));\n gap: 3rem;\n align-items: stretch;\n }\n\n .intro,\n .featured {\n display: flex;\n flex-direction: column;\n min-width: 0;\n }\n\n .intro-heading {\n margin: 0 0 1rem;\n font-size: 2rem;\n font-weight: 400;\n line-height: 1.15;\n color: var(--st-color-text-strong);\n }\n\n .intro-description {\n margin: 0;\n font-size: 1rem;\n line-height: 1.55;\n color: var(--st-color-text);\n }\n\n .intro-links {\n display: flex;\n flex-direction: column;\n gap: 2px;\n margin-top: 2.5rem;\n padding-top: 2rem;\n border-top: 1px solid var(--st-color-border);\n }\n\n .intro-links.no-text {\n margin-top: 0;\n padding-top: 0;\n border-top: 0;\n }\n\n .featured-heading {\n margin: 0 0 1rem;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.35;\n color: var(--st-color-text-strong);\n }\n\n .featured-items {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n }\n\n [hidden] {\n display: none !important;\n }\n\n /* Medium panel: intro on top, two link columns, featured cards side by side underneath. */\n @container (max-width: 960px) {\n .inner {\n grid-template-columns: minmax(0, 1fr) !important;\n gap: 2rem;\n padding: 2rem;\n }\n\n .columns {\n grid-template-columns: repeat(var(--st-mega-menu-columns-md, 2), minmax(0, 1fr));\n gap: 2rem;\n }\n\n .intro-links {\n margin-top: 1.5rem;\n padding-top: 1.5rem;\n }\n\n .featured-items {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));\n }\n }\n\n /* Narrow panel (the phone drill-down): everything stacked. */\n @container (max-width: 560px) {\n .inner {\n gap: 1.75rem;\n padding: 0.5rem 0 1.5rem;\n }\n\n .columns {\n grid-template-columns: minmax(0, 1fr);\n gap: 1.75rem;\n }\n\n .intro-heading {\n display: none;\n }\n }\n `;\n\n /** Large title of the intro column. */\n @property({ type: String })\n heading = '';\n\n /** Text under the intro title. */\n @property({ type: String })\n description = '';\n\n /** Heading over the featured cards. */\n @property({ type: String, attribute: 'featured-heading' })\n featuredHeading = '';\n\n /** Number of link columns side by side at full width. `0` (the default) uses one per slotted column. */\n @property({ type: Number })\n columns = 0;\n\n @state() private columnCount = 1;\n @state() private hasIntroLinks = false;\n @state() private hasFeatured = false;\n\n private onColumnsSlotChange = (event: Event): void => {\n this.columnCount = Math.max(1, (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length);\n };\n\n private onIntroSlotChange = (event: Event): void => {\n this.hasIntroLinks = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n };\n\n private onFeaturedSlotChange = (event: Event): void => {\n this.hasFeatured = (event.target as HTMLSlotElement).assignedElements({ flatten: true }).length > 0;\n };\n\n render() {\n const columns = Math.min(6, Math.max(1, Math.round(this.columns) || this.columnCount));\n const hasIntroText = !!(this.heading || this.description);\n const hasIntro = hasIntroText || this.hasIntroLinks;\n const hasFeatured = this.hasFeatured || !!this.featuredHeading;\n // Every column — intro, each link column, featured — gets the same share of the width.\n const tracks = [hasIntro ? 'minmax(0, 1fr)' : '', `minmax(0, ${columns}fr)`, hasFeatured ? 'minmax(0, 1fr)' : '']\n .filter(Boolean)\n .join(' ');\n return html`\n <div\n part=\"inner\"\n class=\"inner\"\n style=\"grid-template-columns:${tracks};--st-mega-menu-columns:${columns};--st-mega-menu-columns-md:${Math.min(2, columns)}\"\n >\n <div part=\"intro\" class=\"intro\" ?hidden=${!hasIntro}>\n ${this.heading ? html`<p part=\"heading\" class=\"intro-heading\">${this.heading}</p>` : nothing}\n ${this.description ? html`<p part=\"description\" class=\"intro-description\">${this.description}</p>` : nothing}\n <div part=\"intro-links\" class=\"intro-links ${hasIntroText ? '' : 'no-text'}\" ?hidden=${!this.hasIntroLinks}>\n <slot name=\"intro\" @slotchange=${this.onIntroSlotChange}></slot>\n </div>\n </div>\n <div part=\"columns\" class=\"columns\"><slot @slotchange=${this.onColumnsSlotChange}></slot></div>\n <div part=\"featured\" class=\"featured\" ?hidden=${!hasFeatured}>\n ${this.featuredHeading ? html`<p part=\"featured-heading\" class=\"featured-heading\">${this.featuredHeading}</p>` : nothing}\n <div class=\"featured-items\"><slot name=\"featured\" @slotchange=${this.onFeaturedSlotChange}></slot></div>\n </div>\n </div>\n `;\n }\n}\n","import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { arrowUpRightIcon } from '../shared/icons';\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport type { MegaMenuSelectEventDetail } from './MegaMenuEvents';\n\n/**\n * One column (or one group within a column) of an `st-mega-menu`: a heading, an optional line of\n * description, then its links stacked — usually `st-menu-item`s with `variant=\"link\"`. Nest\n * columns to stack several headed groups in one column, as okta.com does.\n *\n * `variant=\"card\"` puts the column on a tinted rounded tile and `variant=\"accent\"` on a solid\n * accent tile with light text; both suit a row of equal columns without intro or featured area.\n * `cta-label` + `cta-href` add a pill button at the bottom of the column.\n *\n * The heading (when `href` is set) and the button fire a *cancelable* `mega-menu-select` event\n * (detail: `{ href }`) before navigating; a host doing client-side routing calls\n * `event.preventDefault()` on it.\n *\n * @slot - The column's links, or nested `st-mega-menu-column` groups.\n * @fires mega-menu-select - The heading link or the button was clicked (cancelable; detail `{ href }`).\n * @csspart heading - The heading text or link.\n * @csspart description - The line under the heading.\n * @csspart items - The box holding the links.\n * @csspart cta - The pill button.\n */\n@customElement('st-mega-menu-column')\nexport class MegaMenuColumn extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: flex;\n flex-direction: column;\n min-width: 0;\n box-sizing: border-box;\n ${fontFamilyStyles}\n }\n\n :host([variant='card']),\n :host([variant='accent']) {\n padding: 2rem 1.75rem 1.75rem;\n border-radius: 20px;\n background: color-mix(in oklch, var(--st-color-text-strong) 5%, var(--st-color-surface));\n }\n\n :host([variant='accent']) {\n background: var(--st-color-accent);\n color: var(--st-color-on-solid);\n /* Read by the st-menu-item links inside. */\n --st-nav-color: var(--st-color-on-solid);\n --st-nav-hover-bg: transparent;\n }\n\n .heading {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin: 0 0 0.75rem;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.35;\n color: var(--st-color-text-strong);\n text-decoration: none;\n }\n\n :host([variant='card']) .heading,\n :host([variant='accent']) .heading {\n font-size: 1.375rem;\n }\n\n :host([variant='accent']) .heading {\n color: inherit;\n }\n\n a.heading:hover,\n a.heading:focus-visible {\n text-decoration: underline;\n text-underline-offset: 4px;\n }\n\n .description {\n margin: -0.25rem 0 0.75rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--st-color-text-muted);\n }\n\n :host([variant='accent']) .description {\n color: inherit;\n opacity: 0.85;\n }\n\n .items {\n display: flex;\n flex-direction: column;\n gap: 2px;\n }\n\n /* Nested groups stack with room between them. */\n ::slotted(st-mega-menu-column:not(:first-child)) {\n margin-top: 2rem;\n }\n\n .cta {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 0.875rem 1.5rem;\n border-radius: 9999px;\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: 1rem;\n font-weight: 500;\n text-align: center;\n text-decoration: none;\n transition: box-shadow 0.2s ease;\n }\n\n .cta-spacer {\n flex: 1;\n min-height: 1.75rem;\n }\n\n .cta:hover,\n .cta:focus-visible {\n box-shadow: 0 0 0 2px currentColor;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cta {\n transition: none;\n }\n }\n `;\n\n @property({ type: String })\n heading = '';\n\n /** Makes the heading a link (e.g. to the section's overview page). */\n @property({ type: String })\n href = '';\n\n @property({ type: String })\n description = '';\n\n /** `plain` (default), `card` (tinted tile) or `accent` (solid accent tile, light text). */\n @property({ type: String, reflect: true })\n variant: 'plain' | 'card' | 'accent' = 'plain';\n\n /** Text of a pill button at the bottom of the column; needs `cta-href`. */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n @property({ type: String, attribute: 'cta-href' })\n ctaHref = '';\n\n private select(event: MouseEvent, href: string): void {\n if (href.startsWith('http')) return;\n const selectEvent = new CustomEvent<MegaMenuSelectEventDetail>('mega-menu-select', {\n detail: { href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(selectEvent);\n if (selectEvent.defaultPrevented) event.preventDefault();\n }\n\n private renderHeading() {\n if (!this.heading) return nothing;\n return this.href\n ? html`<a part=\"heading\" class=\"heading\" href=${this.href} @click=${(event: MouseEvent) => this.select(event, this.href)}\n >${this.heading}</a\n >`\n : html`<p part=\"heading\" class=\"heading\">${this.heading}</p>`;\n }\n\n private renderCta() {\n if (!this.ctaLabel || !this.ctaHref) return nothing;\n const external = this.ctaHref.startsWith('http');\n return html`\n <span class=\"cta-spacer\"></span>\n <a\n part=\"cta\"\n class=\"cta\"\n href=${this.ctaHref}\n target=${external ? '_blank' : '_self'}\n rel=${external ? 'noopener noreferrer' : nothing}\n @click=${(event: MouseEvent) => this.select(event, this.ctaHref)}\n >${this.ctaLabel} ${external ? arrowUpRightIcon(14) : nothing}</a\n >\n `;\n }\n\n render() {\n return html`\n ${this.renderHeading()}\n ${this.description ? html`<p part=\"description\" class=\"description\">${this.description}</p>` : nothing}\n <div part=\"items\" class=\"items\" role=\"group\" aria-label=${this.heading || nothing}><slot></slot></div>\n ${this.renderCta()}\n `;\n }\n}\n","import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\nimport type { MegaMenuSelectEventDetail } from './MegaMenuEvents';\n\n/**\n * A promo card for the featured column of an `st-mega-menu` (`slot=\"featured\"`). The whole card\n * is one link. Two looks, after okta.com:\n *\n * - `story` (default): a rounded image on top, then the description and an underlined\n * call-to-action line — a customer story or announcement.\n * - `overlay`: a tile with light text over `image-url` (darkened), or over an accent gradient when\n * there is no image — an optional `logo-url` top left, the title and description at the bottom.\n *\n * An `http(s)` `href` opens in a new tab unless `target` says otherwise. Any other `href` fires a\n * *cancelable* `mega-menu-select` event (detail: `{ href }`) first; a host doing client-side\n * routing calls `event.preventDefault()` on it.\n *\n * @fires mega-menu-select - The card was clicked (cancelable; detail `{ href }`).\n * @csspart card - The card link.\n * @csspart image - The image (`story`).\n * @csspart logo - The logo (`overlay`).\n * @csspart eyebrow - The small label above the title.\n * @csspart title - The title.\n * @csspart description - The description.\n * @csspart cta - The call-to-action line.\n * @cssprop --st-mega-menu-feature-from - Start colour of the `overlay` gradient (default: the accent colour).\n * @cssprop --st-mega-menu-feature-to - End colour of the `overlay` gradient.\n */\n@customElement('st-mega-menu-feature')\nexport class MegaMenuFeature extends LitElement {\n /** `focus()` on the element focuses its link, so `st-dropdown` can arrow-key to it. */\n static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };\n\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n ${fontFamilyStyles}\n }\n\n .card {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n box-sizing: border-box;\n color: var(--st-color-text-strong);\n text-decoration: none;\n }\n\n .image {\n display: block;\n width: 100%;\n aspect-ratio: 9 / 8;\n object-fit: cover;\n border-radius: 20px;\n transition: transform 0.3s ease;\n }\n\n .card:hover .image {\n transform: scale(1.015);\n }\n\n .eyebrow {\n font-size: 0.75rem;\n font-weight: 600;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--st-color-accent-text);\n }\n\n .title {\n margin: 0;\n font-size: 1.125rem;\n font-weight: 500;\n line-height: 1.3;\n }\n\n .description {\n margin: 0;\n font-size: 0.9375rem;\n line-height: 1.5;\n }\n\n .cta {\n align-self: flex-start;\n margin-top: 0.75rem;\n font-size: 0.9375rem;\n font-weight: 500;\n text-decoration: underline;\n text-underline-offset: 5px;\n text-decoration-thickness: 1px;\n }\n\n .card:hover .cta,\n .card:focus-visible .cta {\n text-decoration-thickness: 2px;\n }\n\n /* overlay */\n :host([variant='overlay']) .card {\n justify-content: flex-end;\n gap: 0.5rem;\n min-height: 15rem;\n padding: 1.75rem;\n border-radius: 20px;\n color: #fff;\n background-color: var(--st-color-accent);\n background-image:\n linear-gradient(to top, rgb(0 0 0 / 0.55), rgb(0 0 0 / 0.05)),\n var(--st-mega-menu-feature-image, linear-gradient(160deg, var(--st-mega-menu-feature-from, var(--st-color-accent)), var(--st-mega-menu-feature-to, oklch(0.25 0.12 280))));\n background-size: cover;\n background-position: center;\n transition: transform 0.2s ease;\n }\n\n :host([variant='overlay']) .card:hover {\n transform: translateY(-2px);\n }\n\n :host([variant='overlay']) .logo {\n height: 2.25rem;\n width: auto;\n max-width: 70%;\n margin-bottom: auto;\n align-self: flex-start;\n object-fit: contain;\n }\n\n :host([variant='overlay']) .title {\n font-size: 1.75rem;\n font-weight: 400;\n }\n\n :host([variant='overlay']) .eyebrow,\n :host([variant='overlay']) .cta {\n color: inherit;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .image,\n :host([variant='overlay']) .card {\n transition: none;\n }\n }\n `;\n\n /** `story` (default) or `overlay` — see the element description. */\n @property({ type: String, reflect: true })\n variant: 'story' | 'overlay' = 'story';\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n description = '';\n\n /** Small label above the title, e.g. \"New\" or \"Report\". */\n @property({ type: String })\n eyebrow = '';\n\n @property({ type: String })\n href = '';\n\n /** `target` for the link. Defaults to `_blank` for an `http(s)` `href`, `_self` otherwise. */\n @property({ type: String })\n target = '';\n\n /** Image on top (`story`) or behind the text (`overlay`). */\n @property({ type: String, attribute: 'image-url' })\n imageUrl = '';\n\n @property({ type: String, attribute: 'image-alt' })\n imageAlt = '';\n\n /** Logo at the top of an `overlay` card. */\n @property({ type: String, attribute: 'logo-url' })\n logoUrl = '';\n\n @property({ type: String, attribute: 'logo-alt' })\n logoAlt = '';\n\n /** Call-to-action text at the bottom of the card; empty hides it. */\n @property({ type: String, attribute: 'cta-label' })\n ctaLabel = '';\n\n private get isExternal(): boolean {\n return this.href.startsWith('http');\n }\n\n private onClick = (event: MouseEvent): void => {\n if (this.isExternal) return;\n const selectEvent = new CustomEvent<MegaMenuSelectEventDetail>('mega-menu-select', {\n detail: { href: this.href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(selectEvent);\n if (selectEvent.defaultPrevented) event.preventDefault();\n };\n\n render() {\n const target = this.target || (this.isExternal ? '_blank' : '_self');\n const overlay = this.variant === 'overlay';\n const style = overlay && this.imageUrl ? `--st-mega-menu-feature-image:url(${JSON.stringify(this.imageUrl)})` : '';\n return html`\n <a\n part=\"card\"\n class=\"card\"\n style=${style}\n href=${this.href || nothing}\n target=${target}\n rel=${target === '_blank' ? 'noopener noreferrer' : nothing}\n @click=${this.onClick}\n >\n ${overlay && this.logoUrl ? html`<img part=\"logo\" class=\"logo\" src=${this.logoUrl} alt=${this.logoAlt} />` : nothing}\n ${!overlay && this.imageUrl\n ? html`<img part=\"image\" class=\"image\" src=${this.imageUrl} alt=${this.imageAlt} loading=\"lazy\" />`\n : nothing}\n ${this.eyebrow ? html`<span part=\"eyebrow\" class=\"eyebrow\">${this.eyebrow}</span>` : nothing}\n ${this.title ? html`<p part=\"title\" class=\"title\">${this.title}</p>` : nothing}\n ${this.description ? html`<p part=\"description\" class=\"description\">${this.description}</p>` : nothing}\n ${this.ctaLabel ? html`<span part=\"cta\" class=\"cta\">${this.ctaLabel}</span>` : nothing}\n </a>\n `;\n }\n}\n"],"mappings":"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","names":["LitElement","css","html","nothing","customElement","property","LitElement","nothing","html","css","property","customElement","LitElement","css","html","nothing","customElement","property","LitElement","html","nothing","css","property","customElement"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/section/Section.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\nimport { sectionSubtitleStyles, sectionTitleStyles } from '../shared/section-styles';\n\n/**\n * A page band that holds other content: sets the background, the spacing above and below, and\n * the content width, with an optional eyebrow/title/subtitle heading over its slotted children.\n * Use it to give a run of components one dark or tinted backdrop and a consistent vertical rhythm,\n * the way enterprise marketing pages stack full-width sections.\n *\n * @slot - The section's content.\n * @cssprop --st-section-bg - Overrides the background colour picked by `background`.\n * @csspart inner - The width-limited content box.\n * @csspart header - The heading block.\n */\n@customElement('st-section')\nexport class Section extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n --st-section-space-none: 0;\n --st-section-space-s: var(--st-space-24);\n --st-section-space-m: var(--st-space-48);\n --st-section-space-l: 4.5rem;\n --st-section-space-xl: 6rem;\n --st-section-space-xxl: 8rem;\n\n display: block;\n box-sizing: border-box;\n width: 100%;\n padding: var(--st-section-space-m) var(--st-space-24);\n background: var(--st-section-bg, var(--st-color-surface));\n color: var(--st-color-text-strong);\n ${rootFontFamilyStyles}\n }\n\n :host([background='subtle']) {\n background: var(--st-section-bg, var(--st-color-subtle));\n }\n\n :host([background='dark']) {\n background: var(--st-section-bg, var(--st-color-text-strong));\n color: var(--st-color-on-solid);\n }\n\n :host([background='accent']) {\n background: var(--st-section-bg, var(--st-color-accent));\n color: var(--st-color-on-solid);\n }\n\n :host([background='transparent']) {\n background: var(--st-section-bg, transparent);\n }\n\n :host([spacing-above='none']) { padding-top: var(--st-section-space-none); }\n :host([spacing-above='s']) { padding-top: var(--st-section-space-s); }\n :host([spacing-above='l']) { padding-top: var(--st-section-space-l); }\n :host([spacing-above='xl']) { padding-top: var(--st-section-space-xl); }\n :host([spacing-above='xxl']) { padding-top: var(--st-section-space-xxl); }\n\n :host([spacing-below='none']) { padding-bottom: var(--st-section-space-none); }\n :host([spacing-below='s']) { padding-bottom: var(--st-section-space-s); }\n :host([spacing-below='l']) { padding-bottom: var(--st-section-space-l); }\n :host([spacing-below='xl']) { padding-bottom: var(--st-section-space-xl); }\n :host([spacing-below='xxl']) { padding-bottom: var(--st-section-space-xxl); }\n\n :host([width='full']) {\n padding-left: 0;\n padding-right: 0;\n }\n\n .inner {\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n }\n\n :host([width='narrow']) .inner {\n max-width: 800px;\n }\n\n :host([width='full']) .inner {\n max-width: none;\n }\n\n .header {\n margin-bottom: var(--st-space-48);\n }\n\n :host([text-alignment='center']) .header {\n text-align: center;\n }\n\n :host([text-alignment='center']) .subtitle {\n margin-inline: auto;\n }\n\n :host([width='full']) .header {\n max-width: var(--st-cms-container-max);\n margin-inline: auto;\n padding-inline: var(--st-space-24);\n box-sizing: border-box;\n }\n\n .eyebrow {\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-text-muted);\n }\n\n .title {\n ${sectionTitleStyles}\n color: inherit;\n letter-spacing: -0.02em;\n max-width: 24ch;\n }\n\n :host([text-alignment='center']) .title {\n margin-inline: auto;\n }\n\n .subtitle {\n ${sectionSubtitleStyles}\n max-width: 60ch;\n margin-bottom: 0;\n }\n\n :host([background='dark']) .eyebrow,\n :host([background='dark']) .subtitle,\n :host([background='accent']) .eyebrow,\n :host([background='accent']) .subtitle {\n color: color-mix(in oklch, var(--st-color-on-solid) 80%, transparent);\n }\n\n @media (max-width: 768px) {\n :host {\n --st-section-space-l: 3.5rem;\n --st-section-space-xl: 4.5rem;\n --st-section-space-xxl: 5.5rem;\n padding-left: var(--st-space-20);\n padding-right: var(--st-space-20);\n }\n }\n `;\n\n @property({ type: String })\n eyebrow = '';\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n subtitle = '';\n\n /** `default` (page surface), `subtle`, `dark`, `accent` or `transparent`. */\n @property({ type: String, reflect: true })\n background: 'default' | 'subtle' | 'dark' | 'accent' | 'transparent' = 'default';\n\n /** Space above the content: `none`, `s`, `m` (default), `l`, `xl` or `xxl`. */\n @property({ type: String, reflect: true, attribute: 'spacing-above' })\n spacingAbove: 'none' | 's' | 'm' | 'l' | 'xl' | 'xxl' = 'm';\n\n /** Space below the content: `none`, `s`, `m` (default), `l`, `xl` or `xxl`. */\n @property({ type: String, reflect: true, attribute: 'spacing-below' })\n spacingBelow: 'none' | 's' | 'm' | 'l' | 'xl' | 'xxl' = 'm';\n\n /** `contained` (default, the page container width), `narrow` (reading width) or `full` (edge to edge). */\n @property({ type: String, reflect: true })\n width: 'contained' | 'narrow' | 'full' = 'contained';\n\n /** Alignment of the heading. */\n @property({ type: String, reflect: true, attribute: 'text-alignment' })\n textAlignment: 'left' | 'center' = 'left';\n\n render() {\n const heading = this.eyebrow || this.title || this.subtitle;\n return html`\n <div class=\"inner\" part=\"inner\">\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 <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAiBjC,IAAM,UAAN,cAAsB,WAAW;AAAA,EAAjC;AAAA;AAqIL,mBAAU;AAGV,iBAAQ;AAGR,oBAAW;AAIX,sBAAuE;AAIvE,wBAAwD;AAIxD,wBAAwD;AAIxD,iBAAyC;AAIzC,yBAAmC;AAAA;AAAA,EAEnC,SAAS;AACP,UAAM,UAAU,KAAK,WAAW,KAAK,SAAS,KAAK;AACnD,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;AAAA;AAAA;AAAA,EAIjB;AACF;AAhLa,QACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAgBf,oBAAoB;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,QAgFpB,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWlB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwB3B;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GApIf,QAqIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GAvIf,QAwIX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA1If,QA2IX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA9I9B,QA+IX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,gBAAgB,CAAC;AAAA,GAlJ1D,QAmJX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,gBAAgB,CAAC;AAAA,GAtJ1D,QAuJX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA1J9B,QA2JX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,iBAAiB,CAAC;AAAA,GA9J3D,QA+JX;AA/JW,UAAN;AAAA,EADN,cAAc,YAAY;AAAA,GACd;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/bento-grid/BentoGrid.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport {\r\n cardTitleStyles,\r\n iconTileStyles,\r\n reducedMotionStyles,\r\n sectionHeaderStyles,\r\n sectionSubtitleStyles,\r\n sectionTitleStyles, invertedSectionTextStyles } from '../shared/section-styles';\r\n\r\nexport interface BentoGridItem {\r\n title: string;\r\n description?: string;\r\n /** Iconify icon name, e.g. `mdi:home`. */\r\n icon?: string;\r\n imageSrc?: string;\r\n imageAlt?: string;\r\n colSpan?: 1 | 2 | 3 | 4;\r\n rowSpan?: 1 | 2;\r\n /** Turns the card into a link. */\r\n href?: string;\r\n}\r\n\r\n/** A responsive 4-column bento grid of icon/image cards. Items are set via the `items` property. */\r\n@customElement('st-bento-grid')\r\nexport class BentoGrid extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n padding: var(--st-cms-section-padding) var(--st-space-24);\r\n background: var(--st-color-page);\r\n ${fontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n margin-bottom: 0;\r\n }\r\n\r\n ${invertedSectionTextStyles}\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: repeat(4, 1fr);\r\n grid-auto-rows: minmax(240px, auto);\r\n gap: var(--st-space-24);\r\n }\r\n\r\n .card {\r\n position: relative;\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n border: 1px solid var(--st-color-border);\r\n border-radius: var(--st-space-24);\r\n background: var(--st-color-surface);\r\n color: inherit;\r\n text-decoration: none;\r\n transition:\r\n transform 0.3s ease,\r\n box-shadow 0.3s ease;\r\n }\r\n\r\n :host([inverted]) .card {\r\n background: var(--st-color-text-strong);\r\n border-color: var(--st-color-text);\r\n }\r\n\r\n .card:hover {\r\n transform: translateY(-4px);\r\n box-shadow: 0 12px 24px -10px var(--st-shadow-color-lg);\r\n z-index: 1;\r\n }\r\n\r\n .image-wrapper {\r\n position: absolute;\r\n inset: 0;\r\n }\r\n\r\n .image-wrapper::after {\r\n content: '';\r\n position: absolute;\r\n inset: 0;\r\n background: linear-gradient(to bottom, transparent 0%, var(--st-shadow-color-xl) 100%);\r\n }\r\n\r\n .image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n transition: transform 0.5s ease;\r\n }\r\n\r\n .card:hover .image {\r\n transform: scale(1.05);\r\n }\r\n\r\n .content {\r\n position: relative;\r\n z-index: 1;\r\n margin-top: auto;\r\n padding: var(--st-space-24);\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--st-space-16);\r\n }\r\n\r\n .icon {\r\n ${iconTileStyles}\r\n width: var(--st-size-40);\r\n height: var(--st-size-40);\r\n font-size: 24px;\r\n }\r\n\r\n .text {\r\n padding: var(--st-space-16);\r\n border-radius: var(--st-radius-md);\r\n }\r\n\r\n .card-title {\r\n ${cardTitleStyles}\r\n font-size: var(--st-text-lg);\r\n }\r\n\r\n .card-description {\r\n margin: 0;\r\n font-size: var(--st-text-md);\r\n color: var(--st-color-text-muted);\r\n }\r\n\r\n :host([inverted]) .card-title {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([inverted]) .card-description {\r\n color: var(--st-color-border);\r\n }\r\n\r\n .card.has-image .card-title,\r\n .card.has-image .card-description {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .card.has-image .icon {\r\n background: var(--st-shadow-color-lg);\r\n color: var(--st-color-on-solid);\r\n backdrop-filter: blur(4px);\r\n }\r\n\r\n .col-1 { grid-column: span 1; }\r\n .col-2 { grid-column: span 2; }\r\n .col-3 { grid-column: span 3; }\r\n .col-4 { grid-column: span 4; }\r\n .row-1 { grid-row: span 1; }\r\n .row-2 { grid-row: span 2; }\r\n\r\n @media (max-width: 1024px) {\r\n .grid {\r\n grid-template-columns: repeat(2, 1fr);\r\n }\r\n .col-3,\r\n .col-4 {\r\n grid-column: span 2;\r\n }\r\n }\r\n\r\n @media (max-width: 640px) {\r\n .grid {\r\n grid-template-columns: 1fr;\r\n }\r\n .col-1,\r\n .col-2,\r\n .col-3,\r\n .col-4 {\r\n grid-column: span 1;\r\n }\r\n }\r\n\r\n ${reducedMotionStyles}\r\n `;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n @property({ attribute: false })\r\n items: BentoGridItem[] = [];\r\n\r\n private renderCard(item: BentoGridItem) {\r\n const classes = `card col-${item.colSpan ?? 1} row-${item.rowSpan ?? 1} ${item.imageSrc ? 'has-image' : ''}`;\r\n const body = html`\r\n ${item.imageSrc\r\n ? html`<div class=\"image-wrapper\" part=\"image-wrapper\">\r\n <img class=\"image\" part=\"image\" src=${item.imageSrc} alt=${item.imageAlt ?? item.title} />\r\n </div>`\r\n : nothing}\r\n <div class=\"content\" part=\"content\">\r\n ${item.icon ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${item.icon}></iconify-icon></div>` : nothing}\r\n <div class=\"text\">\r\n <h3 class=\"card-title\" part=\"card-title\">${item.title}</h3>\r\n ${item.description ? html`<p class=\"card-description\" part=\"card-description\">${item.description}</p>` : nothing}\r\n </div>\r\n </div>\r\n `;\r\n return item.href\r\n ? html`<a part=\"card\" class=${classes} href=${item.href}>${body}</a>`\r\n : html`<div part=\"card\" class=${classes}>${body}</div>`;\r\n }\r\n\r\n render() {\r\n return html`\r\n <div class=\"container\" part=\"container\">\r\n ${this.title || this.subtitle\r\n ? html`<div class=\"header\" part=\"header\">\r\n ${this.title ? html`<h2 class=\"title\" part=\"title\">${this.title}</h2>` : nothing}\r\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\r\n </div>`\r\n : nothing}\r\n <div class=\"grid\" part=\"grid\">${this.items.map((item) => this.renderCard(item))}</div>\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/testimonials/Testimonials.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport 'iconify-icon';\n\nimport { chevronIcon } from '../shared/icons';\nimport { buttonResetStyles, cardShellStyles, controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\nimport { sectionSubtitleStyles, sectionTitleStyles, invertedSectionTextStyles, sectionHeaderStyles, reducedMotionStyles } from '../shared/section-styles';\nimport type { TestimonialsLinkEventDetail } from './TestimonialsEvents';\n\nexport interface TestimonialMetric {\n /** The figure, e.g. `100M` or `85%`. */\n value: string;\n label: string;\n}\n\nexport interface TestimonialItem {\n id?: string;\n name?: string;\n role?: string;\n company?: string;\n /** Author photo. */\n imageSrc?: string;\n quote?: string;\n /** Number of stars. Default: 5 for a plain quote card; no stars on a story card (one with a `headline` or `logoSrc`). `0` hides them. */\n rating?: number;\n /** Customer logo, shown at the top of the card body. */\n logoSrc?: string;\n /** Wide image across the top of the card. */\n mediaSrc?: string;\n /** Story headline, e.g. \"Acme gives 100 million users a seamless sign-in\". */\n headline?: string;\n /** Key results, shown as large figures. */\n metrics?: TestimonialMetric[];\n /** Link to the full story. */\n href?: string;\n /** Text of the story link; defaults to the section's `link-label`. */\n linkLabel?: string;\n}\n\n/**\n * Section heading plus customer quotes or stories. Port of React `Testimonials`.\n *\n * Each card shows whatever its item has: a cover image, the customer logo, a story headline, a\n * quote with star rating, result metrics, the author and a \"See full story\" link. `layout=\"grid\"`\n * (default) lays the cards out in a grid; `layout=\"carousel\"` puts them on one horizontally\n * scrolling, snapping row with previous/next buttons next to the heading — the customer-story\n * carousel of enterprise marketing pages. `action-label`/`action-href` add a section-level link\n * (e.g. \"Explore customer stories\").\n *\n * @fires testimonials-link - Cancelable, before following a story or section link. Detail `{ href }`.\n */\n@customElement('st-testimonials')\nexport class Testimonials extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n box-sizing: border-box;\n padding: var(--st-space-48) var(--st-space-24);\n background-color: var(--st-color-subtle);\n ${rootFontFamilyStyles}\n }\n\n :host([inverted]) {\n background-color: var(--st-color-text-strong);\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 .title {\n ${sectionTitleStyles}\n margin-bottom: var(--st-space-16);\n letter-spacing: -0.02em;\n }\n\n .subtitle {\n ${sectionSubtitleStyles}\n margin: 0 auto;\n }\n\n ${invertedSectionTextStyles}\n\n .grid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));\n gap: var(--st-space-32);\n }\n\n .card {\n ${cardShellStyles}\n display: flex;\n flex-direction: column;\n margin: 0;\n overflow: hidden;\n box-shadow: 0 1px 3px var(--st-shadow-color-sm);\n }\n\n .media {\n aspect-ratio: 16 / 9;\n background: var(--st-color-divider);\n }\n\n .media img {\n display: block;\n width: 100%;\n height: 100%;\n object-fit: cover;\n transition: transform 0.4s ease;\n }\n\n .card:hover .media img {\n transform: scale(1.03);\n }\n\n .body {\n flex: 1;\n display: flex;\n flex-direction: column;\n gap: var(--st-space-24);\n padding: var(--st-space-24);\n }\n\n .logo {\n display: block;\n height: 32px;\n width: auto;\n max-width: 60%;\n object-fit: contain;\n object-position: left center;\n }\n\n .headline {\n margin: 0;\n font-size: var(--st-text-xl);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.35;\n color: var(--st-color-text-strong);\n }\n\n .stars {\n display: flex;\n gap: var(--st-space-4);\n color: var(--st-favorite-accent);\n font-size: var(--st-size-20);\n }\n\n .quote {\n font-size: var(--st-text-md);\n line-height: 1.6;\n color: var(--st-color-text);\n font-style: italic;\n margin: 0;\n }\n\n .metrics {\n display: flex;\n flex-wrap: wrap;\n gap: var(--st-space-16) var(--st-space-32);\n margin: 0;\n padding-top: var(--st-space-16);\n border-top: 1px solid var(--st-color-border);\n }\n\n .metric {\n display: flex;\n flex-direction: column-reverse;\n min-width: 6rem;\n }\n\n .metric dt {\n font-size: var(--st-text-sm);\n color: var(--st-color-text-muted);\n line-height: 1.4;\n }\n\n .metric dd {\n margin: 0;\n font-size: var(--st-cms-text-4xl);\n font-weight: var(--st-font-weight-bold);\n letter-spacing: -0.02em;\n line-height: 1.1;\n color: var(--st-color-text-strong);\n }\n\n .author {\n display: flex;\n align-items: center;\n gap: var(--st-space-12);\n margin-top: auto;\n }\n\n .avatar {\n width: var(--st-space-48);\n height: var(--st-space-48);\n border-radius: var(--st-radius-circle);\n object-fit: cover;\n background-color: var(--st-color-divider);\n flex-shrink: 0;\n }\n\n .avatar-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--st-color-text-muted);\n font-weight: var(--st-font-weight-semibold);\n font-size: var(--st-text-xl);\n }\n\n .author-info {\n display: flex;\n flex-direction: column;\n }\n\n .name {\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n font-size: var(--st-text-xl);\n }\n\n .role {\n font-size: var(--st-text-sm);\n color: var(--st-color-text-faint);\n }\n\n .link {\n display: inline-flex;\n align-items: center;\n gap: var(--st-space-8);\n margin-top: auto;\n font-weight: var(--st-font-weight-semibold);\n color: var(--st-color-text-strong);\n text-decoration: none;\n }\n\n .author + .link {\n margin-top: 0;\n }\n\n .link:hover {\n text-decoration: underline;\n text-underline-offset: 3px;\n }\n\n .link svg {\n transition: transform 0.2s ease;\n }\n\n .link:hover svg {\n transform: translateX(3px);\n }\n\n /* ---- layout=\"carousel\" ---- */\n\n :host([layout='carousel']) .header {\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n gap: var(--st-space-24);\n text-align: left;\n margin-bottom: var(--st-space-32);\n }\n\n :host([layout='carousel']) .subtitle {\n margin: 0;\n }\n\n .controls {\n display: flex;\n align-items: center;\n gap: var(--st-space-12);\n flex: none;\n }\n\n .section-link {\n margin-right: var(--st-space-12);\n }\n\n :host([inverted]) .section-link {\n color: var(--st-color-on-solid);\n }\n\n .arrow {\n ${buttonResetStyles}\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-40);\n height: var(--st-size-40);\n border-radius: var(--st-radius-circle);\n border: 1px solid var(--st-color-border-strong);\n color: var(--st-color-text-strong);\n background: var(--st-color-surface);\n transition:\n background 0.2s ease,\n opacity 0.2s ease;\n }\n\n .arrow:hover:not(:disabled) {\n background: var(--st-color-hover);\n }\n\n .arrow:disabled {\n opacity: 0.4;\n cursor: default;\n }\n\n .track {\n display: flex;\n gap: var(--st-space-24);\n overflow-x: auto;\n scroll-snap-type: x mandatory;\n scroll-behavior: smooth;\n scrollbar-width: none;\n /* Room for the cards' shadow and focus rings. */\n padding: var(--st-space-4) var(--st-space-4) var(--st-space-12);\n margin: calc(-1 * var(--st-space-4));\n }\n\n .track::-webkit-scrollbar {\n display: none;\n }\n\n .track > .card {\n flex: 0 0 min(380px, 85%);\n scroll-snap-align: start;\n }\n\n /* The section link sits under the grid; in the carousel it is next to the arrows instead, and\n only drops below the row on a narrow screen. */\n .section-footer {\n margin-top: var(--st-space-32);\n text-align: center;\n }\n\n :host([inverted]) .section-footer .link {\n color: var(--st-color-on-solid);\n }\n\n :host([layout='carousel']) .section-footer {\n margin-top: 0;\n text-align: left;\n }\n\n .footer-link {\n display: none;\n }\n\n @media (max-width: 768px) {\n :host {\n padding: var(--st-space-40) var(--st-space-20);\n }\n .grid {\n grid-template-columns: 1fr;\n }\n :host([layout='carousel']) .header {\n flex-direction: column;\n align-items: flex-start;\n }\n .section-link {\n display: none;\n }\n .footer-link {\n display: inline-flex;\n margin-top: var(--st-space-24);\n }\n }\n\n ${reducedMotionStyles}\n @media (prefers-reduced-motion: reduce) {\n .track {\n scroll-behavior: auto;\n }\n }\n `;\n\n @property({ type: String })\n title = '';\n\n @property({ type: String })\n subtitle = '';\n\n @property({ attribute: false })\n items: TestimonialItem[] = [];\n\n @property({ type: Boolean, reflect: true })\n inverted = false;\n\n /** `grid` (default) or `carousel`: one scrolling row with previous/next buttons. */\n @property({ type: String, reflect: true })\n layout: 'grid' | 'carousel' = 'grid';\n\n /** Default text of each card's story link. */\n @property({ type: String, attribute: 'link-label' })\n linkLabel = 'See full story';\n\n /** Section-level link text, e.g. \"Explore customer stories\". */\n @property({ type: String, attribute: 'action-label' })\n actionLabel = '';\n\n @property({ type: String, attribute: 'action-href' })\n actionHref = '';\n\n @state() private atStart = true;\n @state() private atEnd = false;\n\n private get track(): HTMLElement | null {\n return this.renderRoot.querySelector('.track');\n }\n\n private resizeObserver?: ResizeObserver;\n\n protected updated(changed: Map<string, unknown>): void {\n if (changed.has('layout') || changed.has('items')) {\n this.resizeObserver?.disconnect();\n const track = this.track;\n if (track) {\n this.resizeObserver = new ResizeObserver(this.syncArrows);\n this.resizeObserver.observe(track);\n }\n this.syncArrows();\n }\n }\n\n disconnectedCallback(): void {\n this.resizeObserver?.disconnect();\n super.disconnectedCallback();\n }\n\n private syncArrows = (): void => {\n const track = this.track;\n if (!track) return;\n this.atStart = track.scrollLeft <= 1;\n this.atEnd = track.scrollLeft + track.clientWidth >= track.scrollWidth - 1;\n };\n\n private scrollByCard(direction: 1 | -1): void {\n const track = this.track;\n const card = track?.querySelector<HTMLElement>('.card');\n if (!track || !card) return;\n const gap = parseFloat(getComputedStyle(track).columnGap) || 0;\n track.scrollBy({ left: direction * (card.offsetWidth + gap) });\n }\n\n private onLinkClick(event: MouseEvent, href: string): void {\n const link = new CustomEvent<TestimonialsLinkEventDetail>('testimonials-link', {\n detail: { href },\n bubbles: true,\n composed: true,\n cancelable: true\n });\n this.dispatchEvent(link);\n if (link.defaultPrevented) event.preventDefault();\n }\n\n private renderLink(label: string, href: string, className: string, part: string) {\n return html`<a class=\"link ${className}\" part=${part} href=${href} @click=${(event: MouseEvent) => this.onLinkClick(event, href)}>\n ${label} ${chevronIcon('right', 14)}\n </a>`;\n }\n\n private renderItem(item: TestimonialItem) {\n const story = !!(item.headline || item.logoSrc);\n const rating = item.rating ?? (item.quote && !story ? 5 : 0);\n const metrics = item.metrics ?? [];\n return html`\n <article class=\"card\" part=\"card\">\n ${item.mediaSrc ? html`<div class=\"media\" part=\"media\"><img src=${item.mediaSrc} alt=\"\" loading=\"lazy\" /></div>` : nothing}\n <div class=\"body\" part=\"body\">\n ${item.logoSrc ? html`<img class=\"logo\" part=\"logo\" src=${item.logoSrc} alt=${item.company || item.name || ''} />` : nothing}\n ${item.headline ? html`<h3 class=\"headline\" part=\"headline\">${item.headline}</h3>` : nothing}\n ${rating > 0\n ? html`<div class=\"stars\" part=\"stars\" role=\"img\" aria-label=\"${rating} / 5\">\n ${Array.from({ length: rating }, () => html`<iconify-icon icon=\"mdi:star\"></iconify-icon>`)}\n </div>`\n : nothing}\n ${item.quote ? html`<blockquote class=\"quote\" part=\"quote\">\"${item.quote}\"</blockquote>` : nothing}\n ${metrics.length\n ? html`<dl class=\"metrics\" part=\"metrics\">\n ${metrics.map(metric => html`<div class=\"metric\"><dt>${metric.label}</dt><dd>${metric.value}</dd></div>`)}\n </dl>`\n : nothing}\n ${item.name\n ? html`<div class=\"author\" part=\"author\">\n ${item.imageSrc\n ? html`<img class=\"avatar\" part=\"avatar\" src=${item.imageSrc} alt=${item.name} />`\n : html`<div class=\"avatar avatar-placeholder\" part=\"avatar\">${item.name.charAt(0)}</div>`}\n <span class=\"author-info\">\n <span class=\"name\" part=\"name\">${item.name}</span>\n ${item.role || item.company\n ? html`<span class=\"role\" part=\"role\">${[item.role, item.company].filter(Boolean).join(' at ')}</span>`\n : nothing}\n </span>\n </div>`\n : nothing}\n ${item.href ? this.renderLink(item.linkLabel || this.linkLabel, item.href, '', 'link') : nothing}\n </div>\n </article>\n `;\n }\n\n render() {\n const carousel = this.layout === 'carousel';\n const sectionLink = this.actionLabel && this.actionHref;\n return html`\n <div class=\"container\" part=\"container\">\n <div class=\"header\" part=\"header\">\n <div>\n <h2 class=\"title\" part=\"title\">${this.title}</h2>\n ${this.subtitle ? html`<p class=\"subtitle\" part=\"subtitle\">${this.subtitle}</p>` : nothing}\n </div>\n ${carousel\n ? html`<div class=\"controls\" part=\"controls\">\n ${sectionLink ? this.renderLink(this.actionLabel, this.actionHref, 'section-link', 'action') : nothing}\n <button class=\"arrow\" part=\"arrow prev\" type=\"button\" aria-label=\"Previous\" ?disabled=${this.atStart} @click=${() => this.scrollByCard(-1)}>\n ${chevronIcon('left', 16)}\n </button>\n <button class=\"arrow\" part=\"arrow next\" type=\"button\" aria-label=\"Next\" ?disabled=${this.atEnd} @click=${() => this.scrollByCard(1)}>\n ${chevronIcon('right', 16)}\n </button>\n </div>`\n : nothing}\n </div>\n ${carousel\n ? html`<div class=\"track\" part=\"track\" role=\"region\" aria-label=${this.title || 'Stories'} tabindex=\"0\" @scroll=${this.syncArrows}>\n ${this.items.map(item => this.renderItem(item))}\n </div>`\n : html`<div class=\"grid\" part=\"grid\">${this.items.map(item => this.renderItem(item))}</div>`}\n ${sectionLink\n ? html`<div class=\"section-footer\">${this.renderLink(this.actionLabel, this.actionHref, carousel ? 'footer-link' : '', 'action')}</div>`\n : nothing}\n </div>\n `;\n }\n}\n"],"mappings":"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AAA;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,QAkMf,iBAAiB;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,MAqFnB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASvB;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA5Uf,aA6UX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA/Uf,aAgVX;AAGA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAlVnB,aAmVX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GArV/B,aAsVX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GAzV9B,aA0VX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,aAAa,CAAC;AAAA,GA7VxC,aA8VX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,eAAe,CAAC;AAAA,GAjW1C,aAkWX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,WAAW,cAAc,CAAC;AAAA,GApWzC,aAqWX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GAvWI,aAuWM;AACA;AAAA,EAAhB,MAAM;AAAA,GAxWI,aAwWM;AAxWN,eAAN;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/stats/Stats.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\n\r\nexport interface StatItem {\r\n value: string;\r\n label: string;\r\n description?: string;\r\n}\r\n\r\n/** Responsive grid of headline numbers with a label and optional description. Port of React `Stats`. */\r\n@customElement('st-stats')\r\nexport class Stats extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n box-sizing: border-box;\r\n padding: var(--st-space-48) var(--st-space-24);\r\n background-color: var(--st-color-surface);\r\n border-top: 1px solid var(--st-color-divider);\r\n border-bottom: 1px solid var(--st-color-divider);\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n :host([inverted]) {\r\n background-color: var(--st-color-text-strong);\r\n border-color: transparent;\r\n }\r\n\r\n .grid {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n display: grid;\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n gap: var(--st-space-40);\r\n }\r\n\r\n .item {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: center;\r\n text-align: center;\r\n gap: var(--st-space-8);\r\n }\r\n\r\n .value {\r\n font-size: var(--st-cms-text-3xl);\r\n font-weight: var(--st-font-weight-bold);\r\n color: var(--st-color-text-strong);\r\n line-height: 1;\r\n letter-spacing: -0.02em;\r\n }\r\n\r\n .label {\r\n font-size: var(--st-text-xl);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-muted);\r\n text-transform: uppercase;\r\n letter-spacing: var(--st-tracking-wide);\r\n }\r\n\r\n .description {\r\n font-size: var(--st-text-sm);\r\n color: var(--st-color-text-faint);\r\n max-width: 200px;\r\n }\r\n\r\n :host([inverted]) .value {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([inverted]) .label,\r\n :host([inverted]) .description {\r\n color: var(--st-color-border);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-40) var(--st-space-24);\r\n }\r\n .grid {\r\n grid-template-columns: repeat(2, 1fr);\r\n gap: var(--st-space-24);\r\n }\r\n .value {\r\n font-size: var(--st-cms-text-xl);\r\n }\r\n }\r\n `;\r\n\r\n @property({ attribute: false })\r\n items: StatItem[] = [];\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n return html`\r\n <div class=\"grid\" part=\"grid\">\r\n ${this.items.map(\r\n (stat) => html`\r\n <div class=\"item\" part=\"item\">\r\n <span class=\"value\" part=\"value\">${stat.value}</span>\r\n <span class=\"label\" part=\"label\">${stat.label}</span>\r\n ${stat.description ? html`<span class=\"description\" part=\"description\">${stat.description}</span>` : nothing}\r\n </div>\r\n `\r\n )}\r\n </div>\r\n `;\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;AAAA,SAAS,YAAY,KAAK,MAAM,eAAe;AAC/C,SAAS,eAAe,gBAAgB;AAYjC,IAAM,QAAN,cAAoB,WAAW;AAAA,EAA/B;AAAA;AAiFL,iBAAoB,CAAC;AAGrB,oBAAW;AAAA;AAAA,EAEX,SAAS;AACP,WAAO;AAAA;AAAA,UAED,KAAK,MAAM;AAAA,MACX,CAAC,SAAS;AAAA;AAAA,iDAE6B,KAAK,KAAK;AAAA,iDACV,KAAK,KAAK;AAAA,gBAC3C,KAAK,cAAc,oDAAoD,KAAK,WAAW,YAAY,OAAO;AAAA;AAAA;AAAA,IAGlH,CAAC;AAAA;AAAA;AAAA,EAGP;AACF;AArGa,MACJ,SAAS;AAAA,MACZ,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASf,oBAAoB;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;AAsE1B;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAhFnB,MAiFX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,SAAS,KAAK,CAAC;AAAA,GAnF/B,MAoFX;AApFW,QAAN;AAAA,EADN,cAAc,UAAU;AAAA,GACZ;","names":[]}