@affinda/wc 0.6.0 → 0.6.2

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 (66) hide show
  1. package/dist/affinda/af-client-carousel.entry.esm.js.map +1 -1
  2. package/dist/affinda/af-feature-accordion.entry.esm.js.map +1 -1
  3. package/dist/affinda/af-hero.entry.esm.js.map +1 -1
  4. package/dist/affinda/af-paperclip-decoration.entry.esm.js.map +1 -1
  5. package/dist/affinda/af-testimonial-stat.entry.esm.js.map +1 -1
  6. package/dist/affinda/affinda.esm.js +1 -1
  7. package/dist/affinda/index.esm.js +1 -1
  8. package/dist/affinda/{p-be71688c.entry.js → p-025851ca.entry.js} +2 -2
  9. package/dist/affinda/p-41160f3a.entry.js +2 -0
  10. package/dist/affinda/p-41160f3a.entry.js.map +1 -0
  11. package/dist/affinda/p-81f2ccb4.entry.js +2 -0
  12. package/dist/affinda/{p-2e67fb0d.entry.js.map → p-81f2ccb4.entry.js.map} +1 -1
  13. package/dist/affinda/{p-764601e6.entry.js → p-99ec99e1.entry.js} +2 -2
  14. package/dist/affinda/{p-0c4a59b3.entry.js → p-f5744d56.entry.js} +2 -2
  15. package/dist/affinda/{p-0c4a59b3.entry.js.map → p-f5744d56.entry.js.map} +1 -1
  16. package/dist/cjs/af-client-carousel.cjs.entry.js +1 -1
  17. package/dist/cjs/af-client-carousel.entry.cjs.js.map +1 -1
  18. package/dist/cjs/af-feature-accordion.cjs.entry.js +2 -3
  19. package/dist/cjs/af-feature-accordion.entry.cjs.js.map +1 -1
  20. package/dist/cjs/af-hero.cjs.entry.js +1 -1
  21. package/dist/cjs/af-hero.entry.cjs.js.map +1 -1
  22. package/dist/cjs/af-paperclip-decoration.cjs.entry.js +9 -5
  23. package/dist/cjs/af-paperclip-decoration.entry.cjs.js.map +1 -1
  24. package/dist/cjs/af-testimonial-stat.cjs.entry.js +1 -1
  25. package/dist/cjs/af-testimonial-stat.entry.cjs.js.map +1 -1
  26. package/dist/collection/components/af-client-carousel/af-client-carousel.css +3 -4
  27. package/dist/collection/components/af-feature-accordion/af-feature-accordion.css +26 -1
  28. package/dist/collection/components/af-feature-accordion/af-feature-accordion.js +1 -2
  29. package/dist/collection/components/af-feature-accordion/af-feature-accordion.js.map +1 -1
  30. package/dist/collection/components/af-hero/af-hero.css +10 -5
  31. package/dist/collection/components/af-paperclip-decoration/af-paperclip-decoration.js +13 -9
  32. package/dist/collection/components/af-paperclip-decoration/af-paperclip-decoration.js.map +1 -1
  33. package/dist/collection/components/af-testimonial-stat/af-testimonial-stat.css +6 -1
  34. package/dist/components/af-client-carousel.js +1 -1
  35. package/dist/components/af-client-carousel.js.map +1 -1
  36. package/dist/components/af-feature-accordion.js +2 -3
  37. package/dist/components/af-feature-accordion.js.map +1 -1
  38. package/dist/components/af-hero.js +1 -1
  39. package/dist/components/af-paperclip-decoration.js +9 -5
  40. package/dist/components/af-paperclip-decoration.js.map +1 -1
  41. package/dist/components/af-testimonial-stat.js +1 -1
  42. package/dist/components/af-testimonial-stat.js.map +1 -1
  43. package/dist/components/index.js +1 -1
  44. package/dist/components/{p-BSgEGp12.js → p-SGoxmRPn.js} +3 -3
  45. package/dist/components/p-SGoxmRPn.js.map +1 -0
  46. package/dist/esm/af-client-carousel.entry.js +1 -1
  47. package/dist/esm/af-client-carousel.entry.js.map +1 -1
  48. package/dist/esm/af-feature-accordion.entry.js +2 -3
  49. package/dist/esm/af-feature-accordion.entry.js.map +1 -1
  50. package/dist/esm/af-hero.entry.js +1 -1
  51. package/dist/esm/af-hero.entry.js.map +1 -1
  52. package/dist/esm/af-paperclip-decoration.entry.js +9 -5
  53. package/dist/esm/af-paperclip-decoration.entry.js.map +1 -1
  54. package/dist/esm/af-testimonial-stat.entry.js +1 -1
  55. package/dist/esm/af-testimonial-stat.entry.js.map +1 -1
  56. package/dist/hydrate/index.js +14 -11
  57. package/dist/hydrate/index.mjs +14 -11
  58. package/dist/types/components/af-paperclip-decoration/af-paperclip-decoration.d.ts +6 -2
  59. package/dist/types/components.d.ts +8 -8
  60. package/package.json +2 -2
  61. package/dist/affinda/p-2e67fb0d.entry.js +0 -2
  62. package/dist/affinda/p-39a40e6a.entry.js +0 -2
  63. package/dist/affinda/p-39a40e6a.entry.js.map +0 -1
  64. package/dist/components/p-BSgEGp12.js.map +0 -1
  65. /package/dist/affinda/{p-be71688c.entry.js.map → p-025851ca.entry.js.map} +0 -0
  66. /package/dist/affinda/{p-764601e6.entry.js.map → p-99ec99e1.entry.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"af-client-carousel.entry.cjs.js","sources":["src/components/af-client-carousel/af-client-carousel.css?tag=af-client-carousel&encapsulation=scoped","src/components/af-client-carousel/af-client-carousel.tsx"],"sourcesContent":[":host {\n display: block;\n width: 100%;\n}\n\n.client-carousel {\n padding: 48px 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-container {\n display: flex;\n flex-direction: column;\n gap: var(--space-4, 16px);\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-row {\n display: flex;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n.logo-track {\n display: flex;\n gap: var(--space-4, 16px);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n/* Scroll left animation */\n.scroll-left .logo-track {\n animation-name: scroll-left;\n animation-duration: 40s;\n}\n\n/* Scroll right animation */\n.scroll-right .logo-track {\n animation-name: scroll-right;\n animation-duration: 40s;\n}\n\n/* Pause animation on hover */\n:host(:hover) .logo-track {\n animation-play-state: paused;\n}\n\n/* Respect reduced motion: stop the infinite scroll and hold at a\n * stable frame so logos remain visible instead of being offscreen. */\n@media (prefers-reduced-motion: reduce) {\n .logo-track,\n .scroll-left .logo-track,\n .scroll-right .logo-track {\n animation: none;\n transform: translateX(0);\n }\n}\n\n/* ==========================================================================\n Static Mode\n ==========================================================================\n Non-animated, centred row. Used when the logo set is small enough to\n fit on screen without scrolling (the former website LogoPillRow use\n case). The clone-for-seamless-loop is skipped in TSX, so each logo\n appears exactly once here. */\n.client-carousel.mode-static .logo-track {\n animation: none;\n /* The track is what we centre — the .carousel-row is full-width so\n * it can host the overflow cue in scroll mode; in static mode we\n * centre its child track instead of fighting the row's flex default. */\n justify-content: center;\n /* Let the track grow only as wide as its content so justify-content\n * on the parent row can actually centre it horizontally. */\n flex-wrap: wrap;\n width: 100%;\n}\n\n.client-carousel.mode-static .carousel-row {\n justify-content: center;\n /* Static rows have no scrolling motion to mask, so allow the row to\n * expand content-naturally instead of clipping at viewport edges. */\n overflow: visible;\n}\n\n.client-carousel.mode-static .carousel-container {\n /* Match the row's no-clip behaviour so wrapped logos stay visible. */\n overflow: visible;\n}\n\n.client-carousel.mode-static {\n /* Keep horizontal bleed contained for consistency with scroll mode. */\n overflow: hidden;\n}\n\n@keyframes scroll-left {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n\n@keyframes scroll-right {\n 0% {\n transform: translateX(-50%);\n }\n 100% {\n transform: translateX(0);\n }\n}\n\n/* Style slotted children (originals projected through the slot) and\n * JS-appended clones as flex rows. In scoped mode Stencil keeps all\n * this in light DOM, so a direct-descendant selector covers both. */\n.logo-track > * {\n display: flex;\n flex-shrink: 0;\n gap: var(--space-4, 16px);\n align-items: center;\n}\n\n/* ==========================================================================\n Theme Variants\n ========================================================================== */\n\n/* INKWELL THEME (Default) */\n:host(.theme-inkwell),\n.client-carousel.theme-inkwell {\n background-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-well-bg: var(--colour-background-level1-dark, #203e45);\n --af-carousel-logo-color: white;\n --af-carousel-logo-filter: brightness(0) invert(1);\n}\n\n/* WHITE THEME */\n:host(.theme-white),\n.client-carousel.theme-white {\n background-color: var(--colour-brand-white, #FFFFFF);\n --af-carousel-logo-well-bg: var(--colour-background-level1, #e8eeed);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* MIST-GREEN THEME */\n:host(.theme-mist-green),\n.client-carousel.theme-mist-green {\n background-color: var(--colour-brand-mist-green, #C6D5D1);\n --af-carousel-logo-well-bg: var(--colour-mistgreen-300, #dde6e3);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* SOFT-CLAY THEME */\n:host(.theme-soft-clay),\n.client-carousel.theme-soft-clay {\n background-color: var(--colour-softclay-400, #c0ab8d);\n --af-carousel-logo-well-bg: var(--colour-softclay-200, #d5c5b0);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* WHITE-IVORY THEME */\n:host(.theme-white-ivory),\n.client-carousel.theme-white-ivory {\n background-color: var(--colour-brand-ivory-paper, #fff9ee);\n --af-carousel-logo-well-bg: var(--colour-softclay-100, #f2eadc);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* ==========================================================================\n Responsive Adjustments\n ========================================================================== */\n\n/* Tablet adjustments */\n/* ≤ tablet */\n@media (max-width: 1024px) {\n .client-carousel {\n padding: 32px 0;\n }\n}\n\n/* Mobile adjustments */\n/* ≤ mobile */\n@media (max-width: 767px) {\n .client-carousel {\n padding: 24px 0;\n }\n \n .carousel-container {\n gap: var(--space-3, 12px);\n }\n \n .logo-track {\n gap: var(--space-3, 12px);\n }\n \n ::slotted(*) {\n gap: var(--space-3, 12px);\n }\n}\n","import { Component, Element, h, Host, Prop } from '@stencil/core';\nimport type { Theme } from '../../types';\n\ntype Mode = 'scroll' | 'static';\n\n/**\n * Full-width row of client logos, either infinite-scrolling (default)\n * or a centred static row.\n *\n * This is a section-level component that spans full width.\n * Renders one or two rows; single row matches the Webflow reference,\n * two rows is the denser variant. When `mode=\"scroll\"` (default) rows\n * animate in opposite directions; when `mode=\"static\"` rows are centred\n * and the animation is disabled.\n *\n * For headlines, use a separate TypographyLockup or Heading component\n * above this carousel.\n *\n * **Seamless loop (scroll mode only):** the CSS animation translates\n * the track from 0% to -50% (or vice versa), which only looks continuous\n * if the track holds two identical copies of the content end-to-end.\n * Shadow DOM slots can only project content once, so we clone the\n * slotted nodes in `componentDidLoad` and append the copies to the track.\n * Static mode skips the clone — nothing is animating, so duplicating\n * the logos would just render them twice.\n */\n@Component({\n tag: 'af-client-carousel',\n styleUrl: 'af-client-carousel.css',\n // Scoped (not shadow) so that cloned nodes inherit the consumer's\n // external CSS (e.g. Astro-scoped `.logo-pill` on the SiteHeader\n // carousel). Shadow DOM would seal the clones off from outer styles.\n shadow: false,\n scoped: true,\n})\nexport class AfClientCarousel {\n @Element() el!: HTMLElement;\n\n /** Theme - sets background color and provides theme context to children */\n @Prop() theme: Theme = 'inkwell';\n\n /**\n * Number of rows.\n * - `1` (default) — single row, matches the Webflow reference.\n * - `2` — two rows (scroll in opposite directions, or stacked when static).\n *\n * When `rows=\"2\"`, slot `row-1` and `row-2` independently.\n * When `rows=\"1\"`, slot the default slot (unnamed) or `row-1`.\n */\n @Prop() rows: 1 | 2 = 1;\n\n /**\n * Layout mode.\n * - `scroll` (default) — infinite animated scroll; rows fill the full\n * width and are cloned for a seamless loop.\n * - `static` — no animation, logos centred horizontally. Use when the\n * logo set is small enough to fit on screen without scrolling.\n */\n @Prop() mode: Mode = 'scroll';\n\n private row1TrackRef?: HTMLElement;\n private row2TrackRef?: HTMLElement;\n\n componentDidLoad() {\n // Static mode doesn't animate, so the clone trick isn't needed —\n // skipping it avoids rendering every logo twice.\n if (this.mode === 'static') return;\n this.duplicateTrackContent(this.row1TrackRef);\n if (Number(this.rows) === 2) {\n this.duplicateTrackContent(this.row2TrackRef);\n }\n }\n\n /**\n * Append clones of every existing track child into the track so the\n * -50% translate animation loops seamlessly. Marks clones with\n * `aria-hidden` and `data-carousel-clone` so assistive tech ignores\n * them and we can skip them when re-duplicating.\n *\n * In scoped mode, slotted content is moved into the track as regular\n * children (there's no `<slot>` element to read from), so we just\n * iterate direct children that aren't themselves prior clones.\n */\n private duplicateTrackContent(track: HTMLElement | undefined) {\n if (!track) return;\n const originals = Array.from(track.children).filter(\n (child) => !(child as HTMLElement).hasAttribute('data-carousel-clone'),\n );\n originals.forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.setAttribute('data-carousel-clone', '');\n clone.setAttribute('aria-hidden', 'true');\n track.appendChild(clone);\n });\n }\n\n render() {\n const rows = Number(this.rows);\n // Direction classes are left on in static mode too — the `.mode-static`\n // CSS rule overrides `animation` to `none`, so the direction is a no-op\n // visually but keeps the markup shape consistent across modes.\n return (\n <Host class={`theme-${this.theme} mode-${this.mode}`}>\n <div class={`client-carousel theme-${this.theme} rows-${rows} mode-${this.mode}`}>\n <div class=\"carousel-container\">\n <div class=\"carousel-row scroll-left\">\n <div class=\"logo-track\" ref={(el) => (this.row1TrackRef = el)}>\n <slot name=\"row-1\">\n <slot></slot>\n </slot>\n </div>\n </div>\n\n {rows === 2 && (\n <div class=\"carousel-row scroll-right\">\n <div class=\"logo-track\" ref={(el) => (this.row2TrackRef = el)}>\n <slot name=\"row-2\"></slot>\n </div>\n </div>\n )}\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":"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"}
1
+ {"version":3,"file":"af-client-carousel.entry.cjs.js","sources":["src/components/af-client-carousel/af-client-carousel.css?tag=af-client-carousel&encapsulation=scoped","src/components/af-client-carousel/af-client-carousel.tsx"],"sourcesContent":[":host {\n display: block;\n width: 100%;\n}\n\n.client-carousel {\n padding: 48px 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-container {\n display: flex;\n flex-direction: column;\n gap: var(--space-4, 16px);\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-row {\n display: flex;\n width: 100%;\n overflow: hidden;\n position: relative;\n}\n\n.logo-track {\n display: flex;\n gap: var(--space-4, 16px);\n animation-timing-function: linear;\n animation-iteration-count: infinite;\n}\n\n/* Scroll left animation */\n.scroll-left .logo-track {\n animation-name: scroll-left;\n animation-duration: 40s;\n}\n\n/* Scroll right animation */\n.scroll-right .logo-track {\n animation-name: scroll-right;\n animation-duration: 40s;\n}\n\n/* No pause on hover — the carousel is purely decorative; pausing it on\n hover felt jittery when the cursor accidentally crossed it (and live\n affinda.com keeps it scrolling regardless). */\n\n/* Respect reduced motion: stop the infinite scroll and hold at a\n * stable frame so logos remain visible instead of being offscreen. */\n@media (prefers-reduced-motion: reduce) {\n .logo-track,\n .scroll-left .logo-track,\n .scroll-right .logo-track {\n animation: none;\n transform: translateX(0);\n }\n}\n\n/* ==========================================================================\n Static Mode\n ==========================================================================\n Non-animated, centred row. Used when the logo set is small enough to\n fit on screen without scrolling (the former website LogoPillRow use\n case). The clone-for-seamless-loop is skipped in TSX, so each logo\n appears exactly once here. */\n.client-carousel.mode-static .logo-track {\n animation: none;\n /* The track is what we centre — the .carousel-row is full-width so\n * it can host the overflow cue in scroll mode; in static mode we\n * centre its child track instead of fighting the row's flex default. */\n justify-content: center;\n /* Let the track grow only as wide as its content so justify-content\n * on the parent row can actually centre it horizontally. */\n flex-wrap: wrap;\n width: 100%;\n}\n\n.client-carousel.mode-static .carousel-row {\n justify-content: center;\n /* Static rows have no scrolling motion to mask, so allow the row to\n * expand content-naturally instead of clipping at viewport edges. */\n overflow: visible;\n}\n\n.client-carousel.mode-static .carousel-container {\n /* Match the row's no-clip behaviour so wrapped logos stay visible. */\n overflow: visible;\n}\n\n.client-carousel.mode-static {\n /* Keep horizontal bleed contained for consistency with scroll mode. */\n overflow: hidden;\n}\n\n@keyframes scroll-left {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(-50%);\n }\n}\n\n@keyframes scroll-right {\n 0% {\n transform: translateX(-50%);\n }\n 100% {\n transform: translateX(0);\n }\n}\n\n/* Style slotted children (originals projected through the slot) and\n * JS-appended clones as flex rows. In scoped mode Stencil keeps all\n * this in light DOM, so a direct-descendant selector covers both. */\n.logo-track > * {\n display: flex;\n flex-shrink: 0;\n gap: var(--space-4, 16px);\n align-items: center;\n}\n\n/* ==========================================================================\n Theme Variants\n ========================================================================== */\n\n/* INKWELL THEME (Default) */\n:host(.theme-inkwell),\n.client-carousel.theme-inkwell {\n background-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-well-bg: var(--colour-background-level1-dark, #203e45);\n --af-carousel-logo-color: white;\n --af-carousel-logo-filter: brightness(0) invert(1);\n}\n\n/* WHITE THEME */\n:host(.theme-white),\n.client-carousel.theme-white {\n background-color: var(--colour-brand-white, #FFFFFF);\n --af-carousel-logo-well-bg: var(--colour-background-level1, #e8eeed);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* MIST-GREEN THEME */\n:host(.theme-mist-green),\n.client-carousel.theme-mist-green {\n background-color: var(--colour-brand-mist-green, #C6D5D1);\n --af-carousel-logo-well-bg: var(--colour-mistgreen-300, #dde6e3);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* SOFT-CLAY THEME */\n:host(.theme-soft-clay),\n.client-carousel.theme-soft-clay {\n background-color: var(--colour-softclay-400, #c0ab8d);\n --af-carousel-logo-well-bg: var(--colour-softclay-200, #d5c5b0);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* WHITE-IVORY THEME */\n:host(.theme-white-ivory),\n.client-carousel.theme-white-ivory {\n background-color: var(--colour-brand-ivory-paper, #fff9ee);\n --af-carousel-logo-well-bg: var(--colour-softclay-100, #f2eadc);\n --af-carousel-logo-color: var(--colour-brand-inkwell, #14343B);\n --af-carousel-logo-filter: none;\n}\n\n/* ==========================================================================\n Responsive Adjustments\n ========================================================================== */\n\n/* Tablet adjustments */\n/* ≤ tablet */\n@media (max-width: 1024px) {\n .client-carousel {\n padding: 32px 0;\n }\n}\n\n/* Mobile adjustments */\n/* ≤ mobile */\n@media (max-width: 767px) {\n .client-carousel {\n padding: 24px 0;\n }\n \n .carousel-container {\n gap: var(--space-3, 12px);\n }\n \n .logo-track {\n gap: var(--space-3, 12px);\n }\n \n ::slotted(*) {\n gap: var(--space-3, 12px);\n }\n}\n","import { Component, Element, h, Host, Prop } from '@stencil/core';\nimport type { Theme } from '../../types';\n\ntype Mode = 'scroll' | 'static';\n\n/**\n * Full-width row of client logos, either infinite-scrolling (default)\n * or a centred static row.\n *\n * This is a section-level component that spans full width.\n * Renders one or two rows; single row matches the Webflow reference,\n * two rows is the denser variant. When `mode=\"scroll\"` (default) rows\n * animate in opposite directions; when `mode=\"static\"` rows are centred\n * and the animation is disabled.\n *\n * For headlines, use a separate TypographyLockup or Heading component\n * above this carousel.\n *\n * **Seamless loop (scroll mode only):** the CSS animation translates\n * the track from 0% to -50% (or vice versa), which only looks continuous\n * if the track holds two identical copies of the content end-to-end.\n * Shadow DOM slots can only project content once, so we clone the\n * slotted nodes in `componentDidLoad` and append the copies to the track.\n * Static mode skips the clone — nothing is animating, so duplicating\n * the logos would just render them twice.\n */\n@Component({\n tag: 'af-client-carousel',\n styleUrl: 'af-client-carousel.css',\n // Scoped (not shadow) so that cloned nodes inherit the consumer's\n // external CSS (e.g. Astro-scoped `.logo-pill` on the SiteHeader\n // carousel). Shadow DOM would seal the clones off from outer styles.\n shadow: false,\n scoped: true,\n})\nexport class AfClientCarousel {\n @Element() el!: HTMLElement;\n\n /** Theme - sets background color and provides theme context to children */\n @Prop() theme: Theme = 'inkwell';\n\n /**\n * Number of rows.\n * - `1` (default) — single row, matches the Webflow reference.\n * - `2` — two rows (scroll in opposite directions, or stacked when static).\n *\n * When `rows=\"2\"`, slot `row-1` and `row-2` independently.\n * When `rows=\"1\"`, slot the default slot (unnamed) or `row-1`.\n */\n @Prop() rows: 1 | 2 = 1;\n\n /**\n * Layout mode.\n * - `scroll` (default) — infinite animated scroll; rows fill the full\n * width and are cloned for a seamless loop.\n * - `static` — no animation, logos centred horizontally. Use when the\n * logo set is small enough to fit on screen without scrolling.\n */\n @Prop() mode: Mode = 'scroll';\n\n private row1TrackRef?: HTMLElement;\n private row2TrackRef?: HTMLElement;\n\n componentDidLoad() {\n // Static mode doesn't animate, so the clone trick isn't needed —\n // skipping it avoids rendering every logo twice.\n if (this.mode === 'static') return;\n this.duplicateTrackContent(this.row1TrackRef);\n if (Number(this.rows) === 2) {\n this.duplicateTrackContent(this.row2TrackRef);\n }\n }\n\n /**\n * Append clones of every existing track child into the track so the\n * -50% translate animation loops seamlessly. Marks clones with\n * `aria-hidden` and `data-carousel-clone` so assistive tech ignores\n * them and we can skip them when re-duplicating.\n *\n * In scoped mode, slotted content is moved into the track as regular\n * children (there's no `<slot>` element to read from), so we just\n * iterate direct children that aren't themselves prior clones.\n */\n private duplicateTrackContent(track: HTMLElement | undefined) {\n if (!track) return;\n const originals = Array.from(track.children).filter(\n (child) => !(child as HTMLElement).hasAttribute('data-carousel-clone'),\n );\n originals.forEach((el) => {\n const clone = el.cloneNode(true) as HTMLElement;\n clone.setAttribute('data-carousel-clone', '');\n clone.setAttribute('aria-hidden', 'true');\n track.appendChild(clone);\n });\n }\n\n render() {\n const rows = Number(this.rows);\n // Direction classes are left on in static mode too — the `.mode-static`\n // CSS rule overrides `animation` to `none`, so the direction is a no-op\n // visually but keeps the markup shape consistent across modes.\n return (\n <Host class={`theme-${this.theme} mode-${this.mode}`}>\n <div class={`client-carousel theme-${this.theme} rows-${rows} mode-${this.mode}`}>\n <div class=\"carousel-container\">\n <div class=\"carousel-row scroll-left\">\n <div class=\"logo-track\" ref={(el) => (this.row1TrackRef = el)}>\n <slot name=\"row-1\">\n <slot></slot>\n </slot>\n </div>\n </div>\n\n {rows === 2 && (\n <div class=\"carousel-row scroll-right\">\n <div class=\"logo-track\" ref={(el) => (this.row2TrackRef = el)}>\n <slot name=\"row-2\"></slot>\n </div>\n </div>\n )}\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-BuJz1C1M.js');
4
4
 
5
- const afFeatureAccordionCss = ".sc-af-feature-accordion-h{display:block;width:100%}.feature-accordion.sc-af-feature-accordion{padding:0 24px;--_heading-color:var(--af-typography-heading-primary, var(--colour-brand-inkwell, #14343b));--_body-color:var(--af-typography-body-default, var(--colour-inkwell-400, #2b484f));--_border-color:var(--af-background-border-default, rgba(20, 52, 59, 0.12))}.feature-accordion__heading.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:400;font-size:clamp(36px, 5vw, 52px);line-height:1.05;letter-spacing:-0.025em;color:var(--_heading-color);margin:0 0 56px 0}.feature-accordion__content.sc-af-feature-accordion{display:flex;gap:48px}.feature-accordion__list.sc-af-feature-accordion{display:flex;flex-direction:column;flex:1;min-width:0}.accordion-item.sc-af-feature-accordion{border-bottom:1px solid var(--_border-color)}.accordion-item.sc-af-feature-accordion:first-child{border-top:1px solid var(--_border-color)}.accordion-item__header.sc-af-feature-accordion{display:flex;align-items:center;justify-content:space-between;width:100%;padding:24px 0;background:none;border:none;cursor:pointer;text-align:left;gap:16px}.accordion-item__header.sc-af-feature-accordion:hover .accordion-item__title.sc-af-feature-accordion{color:var(--_heading-color)}.accordion-item__title.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:500;font-size:22px;line-height:1.25;color:var(--_heading-color);margin:0;flex:1;transition:color 0.2s ease}.accordion-item.sc-af-feature-accordion:not(.accordion-item--expanded) .accordion-item__title.sc-af-feature-accordion{opacity:0.7}.accordion-item__icon.sc-af-feature-accordion{flex-shrink:0;width:24px;height:24px;color:var(--_heading-color);transition:transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1))}.accordion-item__icon.sc-af-feature-accordion svg.sc-af-feature-accordion{display:block;width:100%;height:100%;overflow:visible}.accordion-item__icon-bar.sc-af-feature-accordion{transition:transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-fast, 150ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));transform-origin:12px 12px}.accordion-item--expanded.sc-af-feature-accordion .accordion-item__icon-bar--vert.sc-af-feature-accordion{transform:scaleY(0);opacity:0}.accordion-item.sc-af-feature-accordion:not(.accordion-item--expanded) .accordion-item__icon.sc-af-feature-accordion{opacity:0.5}.accordion-item__content.sc-af-feature-accordion{overflow:hidden;transition:max-height var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),\n opacity var(--motion-duration-slow, 300ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1))}@media (prefers-reduced-motion: reduce){.accordion-item__icon.sc-af-feature-accordion,.accordion-item__icon-bar.sc-af-feature-accordion,.accordion-item__content.sc-af-feature-accordion,.accordion-item__title.sc-af-feature-accordion{transition-duration:0.01ms}}.accordion-item__description.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:400;font-size:17px;line-height:1.6;color:var(--_body-color);margin:0 0 20px 0;padding-right:40px;opacity:0.85}.accordion-item__timer-track.sc-af-feature-accordion{height:3px;background-color:var(--_border-color);border-radius:2px;margin-bottom:8px;overflow:hidden;display:flex;justify-content:flex-start}.accordion-item__timer-progress.sc-af-feature-accordion{height:100%;background-color:var(--af-accent-progress, var(--colour-softclay-600, #9e8765));border-radius:2px;transition:width 0.05s linear}.feature-accordion__image-container.sc-af-feature-accordion{display:flex;align-items:center;justify-content:center;background-color:var(--af-background-level-1, var(--colour-mistgreen-300, #dde6e3));border-radius:20px;overflow:hidden;flex:1;min-width:0}.feature-accordion__image-wrapper.sc-af-feature-accordion{display:flex;align-items:center;justify-content:center;width:100%;padding:var(--af-feature-accordion-image-pad, 40px)}.feature-accordion__image.sc-af-feature-accordion{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;border-radius:12px;box-shadow:0 8px 32px rgba(0, 0, 0, 0.12)}.feature-accordion__image-placeholder.sc-af-feature-accordion{width:100%;height:100%;display:flex;align-items:center;justify-content:center}@media (max-width: 1024px){.feature-accordion__content.sc-af-feature-accordion{gap:32px}.feature-accordion__heading.sc-af-feature-accordion{margin-bottom:40px}.accordion-item__title.sc-af-feature-accordion{font-size:20px}}@media (max-width: 768px){.feature-accordion__content.sc-af-feature-accordion{flex-direction:column;gap:32px}.feature-accordion__image-container.sc-af-feature-accordion{order:-1;min-height:280px;flex:none}.feature-accordion__list.sc-af-feature-accordion{flex:none}.accordion-item__title.sc-af-feature-accordion{font-size:18px}.accordion-item__description.sc-af-feature-accordion{font-size:15px;padding-right:0}}";
5
+ const afFeatureAccordionCss = ".sc-af-feature-accordion-h{display:block;width:100%}.feature-accordion.sc-af-feature-accordion{padding:0 24px;--_heading-color:var(--af-typography-heading-primary, var(--colour-brand-inkwell, #14343b));--_body-color:var(--af-typography-body-default, var(--colour-inkwell-400, #2b484f));--_border-color:var(--af-background-border-default, rgba(20, 52, 59, 0.12))}.feature-accordion__heading.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:400;font-size:clamp(36px, 5vw, 52px);line-height:1.05;letter-spacing:-0.025em;color:var(--_heading-color);margin:0 0 56px 0}.feature-accordion__content.sc-af-feature-accordion{display:flex;gap:48px}.feature-accordion__list.sc-af-feature-accordion{display:flex;flex-direction:column;flex:1;min-width:0}.accordion-item.sc-af-feature-accordion{border-bottom:1px solid var(--_border-color)}.accordion-item.sc-af-feature-accordion:first-child{border-top:1px solid var(--_border-color)}.accordion-item__header.sc-af-feature-accordion{display:flex;align-items:center;justify-content:space-between;width:100%;padding:24px 0;background:none;border:none;cursor:pointer;text-align:left;gap:16px}.accordion-item__header.sc-af-feature-accordion:hover .accordion-item__title.sc-af-feature-accordion{color:var(--_heading-color)}.accordion-item__title.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:500;font-size:22px;line-height:1.25;color:var(--_heading-color);margin:0;flex:1;transition:color 0.2s ease}.accordion-item.sc-af-feature-accordion:not(.accordion-item--expanded) .accordion-item__title.sc-af-feature-accordion{opacity:0.7}.accordion-item__icon.sc-af-feature-accordion{flex-shrink:0;width:24px;height:24px;color:var(--_heading-color);transition:transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1))}.accordion-item__icon.sc-af-feature-accordion svg.sc-af-feature-accordion{display:block;width:100%;height:100%;overflow:visible}.accordion-item__icon-bar.sc-af-feature-accordion{transition:transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-fast, 150ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));transform-origin:12px 12px}.accordion-item--expanded.sc-af-feature-accordion .accordion-item__icon-bar--vert.sc-af-feature-accordion{transform:scaleY(0);opacity:0}.accordion-item.sc-af-feature-accordion:not(.accordion-item--expanded) .accordion-item__icon.sc-af-feature-accordion{opacity:0.5}.accordion-item__content.sc-af-feature-accordion{overflow:hidden;display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),\n opacity var(--motion-duration-slow, 300ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1))}.accordion-item--expanded.sc-af-feature-accordion .accordion-item__content.sc-af-feature-accordion{grid-template-rows:1fr}.accordion-item__content.sc-af-feature-accordion>*.sc-af-feature-accordion{min-height:0}@media (prefers-reduced-motion: reduce){.accordion-item__icon.sc-af-feature-accordion,.accordion-item__icon-bar.sc-af-feature-accordion,.accordion-item__content.sc-af-feature-accordion,.accordion-item__title.sc-af-feature-accordion{transition-duration:0.01ms}}.accordion-item__description.sc-af-feature-accordion{font-family:var(--typography-primaryfont, 'NeuSans', sans-serif);font-weight:400;font-size:17px;line-height:1.6;color:var(--_body-color);margin:0 0 20px 0;padding-right:40px;opacity:0.85}.accordion-item__timer-track.sc-af-feature-accordion{height:3px;background-color:var(--_border-color);border-radius:2px;margin-bottom:8px;overflow:hidden;display:flex;justify-content:flex-start}.accordion-item__timer-progress.sc-af-feature-accordion{height:100%;background-color:var(--af-accent-progress, var(--colour-softclay-600, #9e8765));border-radius:2px;transition:width 0.05s linear}.feature-accordion__image-container.sc-af-feature-accordion{display:flex;align-items:center;justify-content:center;background-color:var(--af-background-level-1, var(--colour-mistgreen-300, #dde6e3));border-radius:20px;overflow:hidden;flex:1;min-width:0}.feature-accordion__image-wrapper.sc-af-feature-accordion{display:flex;align-items:center;justify-content:center;width:100%;padding:var(--af-feature-accordion-image-pad, 40px)}.feature-accordion__image.sc-af-feature-accordion{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain;border-radius:12px;box-shadow:0 8px 32px rgba(0, 0, 0, 0.12)}.feature-accordion__image-placeholder.sc-af-feature-accordion{width:100%;height:100%;display:flex;align-items:center;justify-content:center}@media (max-width: 1024px){.feature-accordion__content.sc-af-feature-accordion{gap:32px}.feature-accordion__heading.sc-af-feature-accordion{margin-bottom:40px}.accordion-item__title.sc-af-feature-accordion{font-size:20px}}@media (max-width: 768px){.feature-accordion__content.sc-af-feature-accordion{flex-direction:column;gap:32px}.feature-accordion__image-container.sc-af-feature-accordion{order:-1;min-height:280px;flex:none}.feature-accordion__list.sc-af-feature-accordion{flex:none}.accordion-item__title.sc-af-feature-accordion{font-size:18px}.accordion-item__description.sc-af-feature-accordion{font-size:15px;padding-right:0}}";
6
6
 
7
7
  const AfFeatureAccordion = class {
8
8
  constructor(hostRef) {
@@ -93,9 +93,8 @@ const AfFeatureAccordion = class {
93
93
  'accordion-item': true,
94
94
  'accordion-item--expanded': this.expandedIndex === index$1
95
95
  }, key: index$1 }, index.h("button", { class: "accordion-item__header", onClick: () => this.handleItemClick(index$1), "aria-expanded": this.expandedIndex === index$1 ? 'true' : 'false' }, index.h("h4", { class: "accordion-item__title" }, item.title), index.h("span", { class: "accordion-item__icon", "aria-hidden": "true" }, index.h("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { class: "accordion-item__icon-bar", d: "M5 12H19", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("path", { class: "accordion-item__icon-bar accordion-item__icon-bar--vert", d: "M12 5V19", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" })))), index.h("div", { class: "accordion-item__content", style: {
96
- maxHeight: this.expandedIndex === index$1 ? '200px' : '0',
97
96
  opacity: this.expandedIndex === index$1 ? '1' : '0'
98
- } }, index.h("p", { class: "accordion-item__description" }, item.description), this.expandedIndex === index$1 && this.autoCycle && (index.h("div", { class: "accordion-item__timer-track" }, index.h("div", { class: "accordion-item__timer-progress", style: { width: `${this.timerProgress}%` } })))))))), index.h("div", { key: '902712779f4ff2eaae179762a7b78ff1f0784d58', class: "feature-accordion__image-container" }, index.h("div", { key: 'b741cfaf96428e786e8780cfeff90a0c315716e8', class: "feature-accordion__image-wrapper" }, currentItem?.imageUrl && (index.h("img", { key: '2a565b530441c9953139b3c0517f480a81f0a77a', src: currentItem.imageUrl, alt: currentItem.imageAlt || currentItem.title, class: "feature-accordion__image" })), !currentItem?.imageUrl && (index.h("div", { key: 'f8248c73c5dcbd6b8224ad646ee867d34004437d', class: "feature-accordion__image-placeholder" }, index.h("slot", { key: '9cbe9ee773b0acd5a1b80fa4f6dd2f293152e598', name: "image" }))))))))));
97
+ } }, index.h("p", { class: "accordion-item__description" }, item.description), this.expandedIndex === index$1 && this.autoCycle && (index.h("div", { class: "accordion-item__timer-track" }, index.h("div", { class: "accordion-item__timer-progress", style: { width: `${this.timerProgress}%` } })))))))), index.h("div", { key: '160448af8f6c8c07adcb6aebf2cfdc27e29a242a', class: "feature-accordion__image-container" }, index.h("div", { key: 'c67cb6ce37a6a737d005d445eeea242241439fd4', class: "feature-accordion__image-wrapper" }, currentItem?.imageUrl && (index.h("img", { key: '663d009d13858b56ff4f4f91e64b07d386630f95', src: currentItem.imageUrl, alt: currentItem.imageAlt || currentItem.title, class: "feature-accordion__image" })), !currentItem?.imageUrl && (index.h("div", { key: '2a1142e7e82cd7c0e0e12a6ba0b9b5bd7397f928', class: "feature-accordion__image-placeholder" }, index.h("slot", { key: '6023de60150d6eb41b27ee459b123e2f95234588', name: "image" }))))))))));
99
98
  }
100
99
  get el() { return index.getElement(this); }
101
100
  static get watchers() { return {
@@ -1 +1 @@
1
- {"version":3,"file":"af-feature-accordion.entry.cjs.js","sources":["src/components/af-feature-accordion/af-feature-accordion.css?tag=af-feature-accordion&encapsulation=scoped","src/components/af-feature-accordion/af-feature-accordion.tsx"],"sourcesContent":["/*\n * af-feature-accordion\n * ---------------------------------------------------------------------------\n * Themable CSS custom properties (safe to override from consumers):\n *\n * --af-accent-progress Colour of the per-item timer/progress bar.\n * Defaults to --colour-softclay-600 (brand\n * soft-clay). Override to retheme the accent.\n * --af-feature-accordion-image-pad\n * Padding around the accompanying image\n * inside its rounded container. Defaults to\n * 40px — tune for tighter or looser rhythm.\n *\n * The component also inherits the following theme tokens from its parent\n * <af-section> (or any ancestor setting them):\n *\n * --af-typography-heading-primary heading colour\n * --af-typography-body-default body colour\n * --af-background-border-default rule/divider colour\n * --af-background-level-1 image-container background\n */\n\n:host {\n display: block;\n width: 100%;\n}\n\n.feature-accordion {\n /* Inherits theme from parent Section via CSS custom properties */\n padding: 0 24px;\n\n /* Internal custom properties that inherit from parent Section's theme */\n --_heading-color: var(--af-typography-heading-primary, var(--colour-brand-inkwell, #14343b));\n --_body-color: var(--af-typography-body-default, var(--colour-inkwell-400, #2b484f));\n --_border-color: var(--af-background-border-default, rgba(20, 52, 59, 0.12));\n}\n\n.feature-accordion__heading {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 400;\n font-size: clamp(36px, 5vw, 52px);\n line-height: 1.05;\n letter-spacing: -0.025em;\n color: var(--_heading-color);\n margin: 0 0 56px 0;\n}\n\n.feature-accordion__content {\n display: flex;\n gap: 48px;\n}\n\n/* Accordion List */\n.feature-accordion__list {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n/* Accordion Item */\n.accordion-item {\n border-bottom: 1px solid var(--_border-color);\n}\n\n.accordion-item:first-child {\n border-top: 1px solid var(--_border-color);\n}\n\n.accordion-item__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 24px 0;\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n gap: 16px;\n}\n\n.accordion-item__header:hover .accordion-item__title {\n color: var(--_heading-color);\n}\n\n.accordion-item__title {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 500;\n font-size: 22px;\n line-height: 1.25;\n color: var(--_heading-color);\n margin: 0;\n flex: 1;\n transition: color 0.2s ease;\n}\n\n/* Collapsed items have lighter text */\n.accordion-item:not(.accordion-item--expanded) .accordion-item__title {\n opacity: 0.7;\n}\n\n.accordion-item__icon {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n color: var(--_heading-color);\n transition:\n transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n}\n\n.accordion-item__icon svg {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n\n/* Plus → minus morph: vertical bar collapses and the whole icon rotates\n 45° when expanding, giving a single, fluid gesture. */\n.accordion-item__icon-bar {\n transition:\n transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-fast, 150ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n transform-origin: 12px 12px;\n}\n\n.accordion-item--expanded .accordion-item__icon-bar--vert {\n transform: scaleY(0);\n opacity: 0;\n}\n\n.accordion-item:not(.accordion-item--expanded) .accordion-item__icon {\n opacity: 0.5;\n}\n\n.accordion-item__content {\n overflow: hidden;\n transition:\n max-height var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),\n opacity var(--motion-duration-slow, 300ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n}\n\n@media (prefers-reduced-motion: reduce) {\n .accordion-item__icon,\n .accordion-item__icon-bar,\n .accordion-item__content,\n .accordion-item__title {\n transition-duration: 0.01ms;\n }\n}\n\n.accordion-item__description {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 400;\n font-size: 17px;\n line-height: 1.6;\n color: var(--_body-color);\n margin: 0 0 20px 0;\n padding-right: 40px;\n opacity: 0.85;\n}\n\n/* Timer track - the progress bar at the bottom of expanded items */\n.accordion-item__timer-track {\n height: 3px;\n background-color: var(--_border-color);\n border-radius: 2px;\n margin-bottom: 8px;\n overflow: hidden;\n display: flex;\n justify-content: flex-start;\n}\n\n.accordion-item__timer-progress {\n height: 100%;\n background-color: var(--af-accent-progress, var(--colour-softclay-600, #9e8765));\n border-radius: 2px;\n transition: width 0.05s linear;\n}\n\n/* Image Container - stretches full height to align with accordion */\n.feature-accordion__image-container {\n display: flex;\n align-items: center;\n justify-content: center;\n /* Flows from parent Section's theme; mist-green fallback for unthemed use */\n background-color: var(--af-background-level-1, var(--colour-mistgreen-300, #dde6e3));\n border-radius: 20px;\n overflow: hidden;\n flex: 1;\n min-width: 0;\n}\n\n.feature-accordion__image-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: var(--af-feature-accordion-image-pad, 40px);\n}\n\n.feature-accordion__image {\n max-width: 100%;\n max-height: 100%;\n width: auto;\n height: auto;\n object-fit: contain;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\n}\n\n.feature-accordion__image-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Tablet */\n/* ≤ tablet */\n@media (max-width: 1024px) {\n .feature-accordion__content {\n gap: 32px;\n }\n\n .feature-accordion__heading {\n margin-bottom: 40px;\n }\n\n .accordion-item__title {\n font-size: 20px;\n }\n}\n\n/* Mobile */\n/* mobile-only */\n@media (max-width: 768px) {\n .feature-accordion__content {\n flex-direction: column;\n gap: 32px;\n }\n\n .feature-accordion__image-container {\n order: -1;\n min-height: 280px;\n flex: none;\n }\n\n .feature-accordion__list {\n flex: none;\n }\n\n .accordion-item__title {\n font-size: 18px;\n }\n\n .accordion-item__description {\n font-size: 15px;\n padding-right: 0;\n }\n}\n","import { Component, h, Host, Prop, State, Element, Watch } from '@stencil/core';\n\nexport interface FeatureAccordionItem {\n title: string;\n description: string;\n imageUrl?: string;\n imageAlt?: string;\n}\n\n/**\n * Feature accordion component with expandable items and accompanying image.\n * Used for showcasing product features with visual examples.\n * Features auto-cycling through items with a progress timer.\n * \n * **Must be wrapped in a Section component** to inherit theme styling.\n * The component automatically adapts colors based on the parent Section's theme.\n * \n * @example\n * ```tsx\n * <Section theme=\"inkwell\">\n * <FeatureAccordion heading=\"Features\" items={...} />\n * </Section>\n * ```\n */\n@Component({\n tag: 'af-feature-accordion',\n styleUrl: 'af-feature-accordion.css',\n shadow: false,\n scoped: true,\n})\nexport class AfFeatureAccordion {\n @Element() el!: HTMLElement;\n\n /** Section heading */\n @Prop() heading: string = 'Give AI agents your paperwork';\n\n /** JSON string of accordion items */\n @Prop() items: string = '[]';\n\n /** Auto-cycle interval in milliseconds (default: 6000ms = 6 seconds) */\n @Prop() cycleInterval: number = 6000;\n\n /** Whether auto-cycling is enabled */\n @Prop() autoCycle: boolean = true;\n\n /** Currently expanded item index */\n @State() expandedIndex: number = 0;\n\n /** Progress of current timer (0-100) */\n @State() timerProgress: number = 100;\n\n private progressTimer: number | null = null;\n private progressStartTime: number = 0;\n\n componentDidLoad() {\n if (this.autoCycle) {\n this.startCycling();\n }\n }\n\n disconnectedCallback() {\n this.stopCycling();\n }\n\n @Watch('autoCycle')\n handleAutoCycleChange(newValue: boolean) {\n if (newValue) {\n this.startCycling();\n } else {\n this.stopCycling();\n }\n }\n\n private getItems(): FeatureAccordionItem[] {\n try {\n return JSON.parse(this.items);\n } catch {\n return [];\n }\n }\n\n private startCycling() {\n this.stopCycling();\n this.progressStartTime = Date.now();\n this.timerProgress = 100;\n \n // Progress animation frame\n const updateProgress = () => {\n const elapsed = Date.now() - this.progressStartTime;\n const remaining = this.cycleInterval - elapsed;\n \n if (remaining <= 0) {\n this.moveToNextItem();\n } else {\n this.timerProgress = (remaining / this.cycleInterval) * 100;\n this.progressTimer = requestAnimationFrame(updateProgress);\n }\n };\n \n this.progressTimer = requestAnimationFrame(updateProgress);\n }\n\n private stopCycling() {\n if (this.progressTimer) {\n cancelAnimationFrame(this.progressTimer);\n this.progressTimer = null;\n }\n }\n\n private moveToNextItem() {\n const items = this.getItems();\n if (items.length === 0) return;\n \n this.expandedIndex = (this.expandedIndex + 1) % items.length;\n // Restart the cycling timer for the new item\n this.startCycling();\n }\n\n private handleItemClick(index: number) {\n // Reset timer when user clicks\n this.expandedIndex = index;\n // Restart the cycling timer for the clicked item\n if (this.autoCycle) {\n this.startCycling();\n }\n }\n\n render() {\n const items = this.getItems();\n const currentItem = items[this.expandedIndex];\n\n return (\n <Host>\n <div class=\"feature-accordion\">\n <div class=\"feature-accordion__container\">\n <h2 class=\"feature-accordion__heading\">{this.heading}</h2>\n \n <div class=\"feature-accordion__content\">\n {/* Left side - Accordion */}\n <div class=\"feature-accordion__list\">\n {items.map((item, index) => (\n <div \n class={{\n 'accordion-item': true,\n 'accordion-item--expanded': this.expandedIndex === index\n }}\n key={index}\n >\n <button\n class=\"accordion-item__header\"\n onClick={() => this.handleItemClick(index)}\n aria-expanded={this.expandedIndex === index ? 'true' : 'false'}\n >\n <h4 class=\"accordion-item__title\">{item.title}</h4>\n {/* Plus → minus: a single SVG with two strokes, the\n vertical one rotated-out to zero when expanded. This\n gives a fluid morph instead of swapping SVGs mid-\n animation. */}\n <span class=\"accordion-item__icon\" aria-hidden=\"true\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path class=\"accordion-item__icon-bar\" d=\"M5 12H19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path class=\"accordion-item__icon-bar accordion-item__icon-bar--vert\" d=\"M12 5V19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n </button>\n <div \n class=\"accordion-item__content\"\n style={{ \n maxHeight: this.expandedIndex === index ? '200px' : '0',\n opacity: this.expandedIndex === index ? '1' : '0'\n }}\n >\n <p class=\"accordion-item__description\">{item.description}</p>\n {this.expandedIndex === index && this.autoCycle && (\n <div class=\"accordion-item__timer-track\">\n <div \n class=\"accordion-item__timer-progress\"\n style={{ width: `${this.timerProgress}%` }}\n ></div>\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Right side - Image */}\n <div class=\"feature-accordion__image-container\">\n <div class=\"feature-accordion__image-wrapper\">\n {currentItem?.imageUrl && (\n <img \n src={currentItem.imageUrl} \n alt={currentItem.imageAlt || currentItem.title}\n class=\"feature-accordion__image\"\n />\n )}\n {!currentItem?.imageUrl && (\n <div class=\"feature-accordion__image-placeholder\">\n <slot name=\"image\"></slot>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"names":["h","Host","index"],"mappings":";;;;AAAA,MAAM,qBAAqB,GAAG,ipKAAipK;;MC8BlqK,kBAAkB,GAAA,MAAA;AAN/B,IAAA,WAAA,CAAA,OAAA,EAAA;;;AAUU,QAAA,IAAO,CAAA,OAAA,GAAW,+BAA+B;;AAGjD,QAAA,IAAK,CAAA,KAAA,GAAW,IAAI;;AAGpB,QAAA,IAAa,CAAA,aAAA,GAAW,IAAI;;AAG5B,QAAA,IAAS,CAAA,SAAA,GAAY,IAAI;;AAGxB,QAAA,IAAa,CAAA,aAAA,GAAW,CAAC;;AAGzB,QAAA,IAAa,CAAA,aAAA,GAAW,GAAG;AAE5B,QAAA,IAAa,CAAA,aAAA,GAAkB,IAAI;AACnC,QAAA,IAAiB,CAAA,iBAAA,GAAW,CAAC;AA6JtC;IA3JC,gBAAgB,GAAA;AACd,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,YAAY,EAAE;;;IAIvB,oBAAoB,GAAA;QAClB,IAAI,CAAC,WAAW,EAAE;;AAIpB,IAAA,qBAAqB,CAAC,QAAiB,EAAA;QACrC,IAAI,QAAQ,EAAE;YACZ,IAAI,CAAC,YAAY,EAAE;;aACd;YACL,IAAI,CAAC,WAAW,EAAE;;;IAId,QAAQ,GAAA;AACd,QAAA,IAAI;YACF,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;;AAC7B,QAAA,MAAM;AACN,YAAA,OAAO,EAAE;;;IAIL,YAAY,GAAA;QAClB,IAAI,CAAC,WAAW,EAAE;AAClB,QAAA,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,EAAE;AACnC,QAAA,IAAI,CAAC,aAAa,GAAG,GAAG;;QAGxB,MAAM,cAAc,GAAG,MAAK;YAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,iBAAiB;AACnD,YAAA,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,GAAG,OAAO;AAE9C,YAAA,IAAI,SAAS,IAAI,CAAC,EAAE;gBAClB,IAAI,CAAC,cAAc,EAAE;;iBAChB;AACL,gBAAA,IAAI,CAAC,aAAa,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,IAAI,GAAG;AAC3D,gBAAA,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,cAAc,CAAC;;AAE9D,SAAC;AAED,QAAA,IAAI,CAAC,aAAa,GAAG,qBAAqB,CAAC,cAAc,CAAC;;IAGpD,WAAW,GAAA;AACjB,QAAA,IAAI,IAAI,CAAC,aAAa,EAAE;AACtB,YAAA,oBAAoB,CAAC,IAAI,CAAC,aAAa,CAAC;AACxC,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI;;;IAIrB,cAAc,GAAA;AACpB,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;AAC7B,QAAA,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE;AAExB,QAAA,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM;;QAE5D,IAAI,CAAC,YAAY,EAAE;;AAGb,IAAA,eAAe,CAAC,KAAa,EAAA;;AAEnC,QAAA,IAAI,CAAC,aAAa,GAAG,KAAK;;AAE1B,QAAA,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,IAAI,CAAC,YAAY,EAAE;;;IAIvB,MAAM,GAAA;AACJ,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE;QAC7B,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;QAE7C,QACEA,QAACC,UAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACHD,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,mBAAmB,EAAA,EAC5BA,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,8BAA8B,EAAA,EACvCA,OAAA,CAAA,IAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAI,KAAK,EAAC,4BAA4B,IAAE,IAAI,CAAC,OAAO,CAAM,EAE1DA,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,4BAA4B,EAAA,EAErCA,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAC,yBAAyB,IACjC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAEE,OAAK,MACrBF,OAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAE;AACL,gBAAA,gBAAgB,EAAE,IAAI;AACtB,gBAAA,0BAA0B,EAAE,IAAI,CAAC,aAAa,KAAKE;AACpD,aAAA,EACD,GAAG,EAAEA,OAAK,EAAA,EAEVF,OAAA,CAAA,QAAA,EAAA,EACE,KAAK,EAAC,wBAAwB,EAC9B,OAAO,EAAE,MAAM,IAAI,CAAC,eAAe,CAACE,OAAK,CAAC,EAAA,eAAA,EAC3B,IAAI,CAAC,aAAa,KAAKA,OAAK,GAAG,MAAM,GAAG,OAAO,EAAA,EAE9DF,OAAA,CAAA,IAAA,EAAA,EAAI,KAAK,EAAC,uBAAuB,IAAE,IAAI,CAAC,KAAK,CAAM,EAKnDA,OAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAC,sBAAsB,EAAA,aAAA,EAAa,MAAM,EAAA,EACnDA,OAAA,CAAA,KAAA,EAAA,EAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,KAAK,EAAC,4BAA4B,EAAA,EAC5FA,OAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAC,0BAA0B,EAAC,CAAC,EAAC,UAAU,EAAC,MAAM,EAAC,cAAc,EAAA,cAAA,EAAc,GAAG,EAAA,gBAAA,EAAgB,OAAO,EAAE,CAAA,EACnHA,OAAA,CAAA,MAAA,EAAA,EAAM,KAAK,EAAC,yDAAyD,EAAC,CAAC,EAAC,UAAU,EAAC,MAAM,EAAC,cAAc,kBAAc,GAAG,EAAA,gBAAA,EAAgB,OAAO,EAAE,CAAA,CAC9I,CACD,CACA,EACTA,OAAA,CAAA,KAAA,EAAA,EACE,KAAK,EAAC,yBAAyB,EAC/B,KAAK,EAAE;AACL,gBAAA,SAAS,EAAE,IAAI,CAAC,aAAa,KAAKE,OAAK,GAAG,OAAO,GAAG,GAAG;AACvD,gBAAA,OAAO,EAAE,IAAI,CAAC,aAAa,KAAKA,OAAK,GAAG,GAAG,GAAG;AAC/C,aAAA,EAAA,EAEDF,OAAA,CAAA,GAAA,EAAA,EAAG,KAAK,EAAC,6BAA6B,IAAE,IAAI,CAAC,WAAW,CAAK,EAC5D,IAAI,CAAC,aAAa,KAAKE,OAAK,IAAI,IAAI,CAAC,SAAS,KAC7CF,OAAK,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,6BAA6B,EAAA,EACtCA,OACE,CAAA,KAAA,EAAA,EAAA,KAAK,EAAC,gCAAgC,EACtC,KAAK,EAAE,EAAE,KAAK,EAAE,CAAG,EAAA,IAAI,CAAC,aAAa,GAAG,EAAE,EACrC,CAAA,CACH,CACP,CACG,CACF,CACP,CAAC,CACE,EAGNA,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,oCAAoC,EAAA,EAC7CA,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,kCAAkC,EAAA,EAC1C,WAAW,EAAE,QAAQ,KACpBA,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,GAAG,EAAE,WAAW,CAAC,QAAQ,EACzB,GAAG,EAAE,WAAW,CAAC,QAAQ,IAAI,WAAW,CAAC,KAAK,EAC9C,KAAK,EAAC,0BAA0B,EAAA,CAChC,CACH,EACA,CAAC,WAAW,EAAE,QAAQ,KACrBA,OAAK,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAC,sCAAsC,EAAA,EAC/CA,OAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAM,IAAI,EAAC,OAAO,EAAA,CAAQ,CACtB,CACP,CACG,CACF,CACF,CACF,CACF,CACD;;;;;;;;;;;"}
1
+ {"version":3,"file":"af-feature-accordion.entry.cjs.js","sources":["src/components/af-feature-accordion/af-feature-accordion.css?tag=af-feature-accordion&encapsulation=scoped","src/components/af-feature-accordion/af-feature-accordion.tsx"],"sourcesContent":["/*\n * af-feature-accordion\n * ---------------------------------------------------------------------------\n * Themable CSS custom properties (safe to override from consumers):\n *\n * --af-accent-progress Colour of the per-item timer/progress bar.\n * Defaults to --colour-softclay-600 (brand\n * soft-clay). Override to retheme the accent.\n * --af-feature-accordion-image-pad\n * Padding around the accompanying image\n * inside its rounded container. Defaults to\n * 40px — tune for tighter or looser rhythm.\n *\n * The component also inherits the following theme tokens from its parent\n * <af-section> (or any ancestor setting them):\n *\n * --af-typography-heading-primary heading colour\n * --af-typography-body-default body colour\n * --af-background-border-default rule/divider colour\n * --af-background-level-1 image-container background\n */\n\n:host {\n display: block;\n width: 100%;\n}\n\n.feature-accordion {\n /* Inherits theme from parent Section via CSS custom properties */\n padding: 0 24px;\n\n /* Internal custom properties that inherit from parent Section's theme */\n --_heading-color: var(--af-typography-heading-primary, var(--colour-brand-inkwell, #14343b));\n --_body-color: var(--af-typography-body-default, var(--colour-inkwell-400, #2b484f));\n --_border-color: var(--af-background-border-default, rgba(20, 52, 59, 0.12));\n}\n\n.feature-accordion__heading {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 400;\n font-size: clamp(36px, 5vw, 52px);\n line-height: 1.05;\n letter-spacing: -0.025em;\n color: var(--_heading-color);\n margin: 0 0 56px 0;\n}\n\n.feature-accordion__content {\n display: flex;\n gap: 48px;\n}\n\n/* Accordion List */\n.feature-accordion__list {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 0;\n}\n\n/* Accordion Item */\n.accordion-item {\n border-bottom: 1px solid var(--_border-color);\n}\n\n.accordion-item:first-child {\n border-top: 1px solid var(--_border-color);\n}\n\n.accordion-item__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 24px 0;\n background: none;\n border: none;\n cursor: pointer;\n text-align: left;\n gap: 16px;\n}\n\n.accordion-item__header:hover .accordion-item__title {\n color: var(--_heading-color);\n}\n\n.accordion-item__title {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 500;\n font-size: 22px;\n line-height: 1.25;\n color: var(--_heading-color);\n margin: 0;\n flex: 1;\n transition: color 0.2s ease;\n}\n\n/* Collapsed items have lighter text */\n.accordion-item:not(.accordion-item--expanded) .accordion-item__title {\n opacity: 0.7;\n}\n\n.accordion-item__icon {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n color: var(--_heading-color);\n transition:\n transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n}\n\n.accordion-item__icon svg {\n display: block;\n width: 100%;\n height: 100%;\n overflow: visible;\n}\n\n/* Plus → minus morph: vertical bar collapses and the whole icon rotates\n 45° when expanding, giving a single, fluid gesture. */\n.accordion-item__icon-bar {\n transition:\n transform var(--motion-duration-base, 200ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1)),\n opacity var(--motion-duration-fast, 150ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n transform-origin: 12px 12px;\n}\n\n.accordion-item--expanded .accordion-item__icon-bar--vert {\n transform: scaleY(0);\n opacity: 0;\n}\n\n.accordion-item:not(.accordion-item--expanded) .accordion-item__icon {\n opacity: 0.5;\n}\n\n.accordion-item__content {\n overflow: hidden;\n /* Use grid-template-rows-based expansion (0fr → 1fr) so the\n transition animates the *actual* content height, not a max-height\n ceiling. Avoids the \"section height bumps for a split second\"\n jank that happens when the outgoing item's content is shorter\n than max-height: at the midpoint of a max-height transition the\n outgoing item still renders at its natural height (because\n max-height >> content) while the incoming item ALSO renders at\n its natural height — sum > steady-state for a frame, so the\n image column on the right jumps. With grid-rows, each item\n occupies its proportional fraction of its own natural height;\n incoming + outgoing always sums to one full content row.\n Reported 2026-04-27 on /au's \"Give Affinda Platform your\n paperwork\" section. */\n display: grid;\n grid-template-rows: 0fr;\n transition:\n grid-template-rows var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),\n opacity var(--motion-duration-slow, 300ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));\n}\n\n.accordion-item--expanded .accordion-item__content {\n grid-template-rows: 1fr;\n}\n\n/* Inner wrapper required for grid-template-rows interpolation:\n the direct grid child collapses to min-content otherwise. */\n.accordion-item__content > * {\n min-height: 0;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .accordion-item__icon,\n .accordion-item__icon-bar,\n .accordion-item__content,\n .accordion-item__title {\n transition-duration: 0.01ms;\n }\n}\n\n.accordion-item__description {\n font-family: var(--typography-primaryfont, 'NeuSans', sans-serif);\n font-weight: 400;\n font-size: 17px;\n line-height: 1.6;\n color: var(--_body-color);\n margin: 0 0 20px 0;\n padding-right: 40px;\n opacity: 0.85;\n}\n\n/* Timer track - the progress bar at the bottom of expanded items */\n.accordion-item__timer-track {\n height: 3px;\n background-color: var(--_border-color);\n border-radius: 2px;\n margin-bottom: 8px;\n overflow: hidden;\n display: flex;\n justify-content: flex-start;\n}\n\n.accordion-item__timer-progress {\n height: 100%;\n background-color: var(--af-accent-progress, var(--colour-softclay-600, #9e8765));\n border-radius: 2px;\n transition: width 0.05s linear;\n}\n\n/* Image Container - stretches full height to align with accordion */\n.feature-accordion__image-container {\n display: flex;\n align-items: center;\n justify-content: center;\n /* Flows from parent Section's theme; mist-green fallback for unthemed use */\n background-color: var(--af-background-level-1, var(--colour-mistgreen-300, #dde6e3));\n border-radius: 20px;\n overflow: hidden;\n flex: 1;\n min-width: 0;\n}\n\n.feature-accordion__image-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: var(--af-feature-accordion-image-pad, 40px);\n}\n\n.feature-accordion__image {\n max-width: 100%;\n max-height: 100%;\n width: auto;\n height: auto;\n object-fit: contain;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\n}\n\n.feature-accordion__image-placeholder {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Tablet */\n/* ≤ tablet */\n@media (max-width: 1024px) {\n .feature-accordion__content {\n gap: 32px;\n }\n\n .feature-accordion__heading {\n margin-bottom: 40px;\n }\n\n .accordion-item__title {\n font-size: 20px;\n }\n}\n\n/* Mobile */\n/* mobile-only */\n@media (max-width: 768px) {\n .feature-accordion__content {\n flex-direction: column;\n gap: 32px;\n }\n\n .feature-accordion__image-container {\n order: -1;\n min-height: 280px;\n flex: none;\n }\n\n .feature-accordion__list {\n flex: none;\n }\n\n .accordion-item__title {\n font-size: 18px;\n }\n\n .accordion-item__description {\n font-size: 15px;\n padding-right: 0;\n }\n}\n","import { Component, h, Host, Prop, State, Element, Watch } from '@stencil/core';\n\nexport interface FeatureAccordionItem {\n title: string;\n description: string;\n imageUrl?: string;\n imageAlt?: string;\n}\n\n/**\n * Feature accordion component with expandable items and accompanying image.\n * Used for showcasing product features with visual examples.\n * Features auto-cycling through items with a progress timer.\n * \n * **Must be wrapped in a Section component** to inherit theme styling.\n * The component automatically adapts colors based on the parent Section's theme.\n * \n * @example\n * ```tsx\n * <Section theme=\"inkwell\">\n * <FeatureAccordion heading=\"Features\" items={...} />\n * </Section>\n * ```\n */\n@Component({\n tag: 'af-feature-accordion',\n styleUrl: 'af-feature-accordion.css',\n shadow: false,\n scoped: true,\n})\nexport class AfFeatureAccordion {\n @Element() el!: HTMLElement;\n\n /** Section heading */\n @Prop() heading: string = 'Give AI agents your paperwork';\n\n /** JSON string of accordion items */\n @Prop() items: string = '[]';\n\n /** Auto-cycle interval in milliseconds (default: 6000ms = 6 seconds) */\n @Prop() cycleInterval: number = 6000;\n\n /** Whether auto-cycling is enabled */\n @Prop() autoCycle: boolean = true;\n\n /** Currently expanded item index */\n @State() expandedIndex: number = 0;\n\n /** Progress of current timer (0-100) */\n @State() timerProgress: number = 100;\n\n private progressTimer: number | null = null;\n private progressStartTime: number = 0;\n\n componentDidLoad() {\n if (this.autoCycle) {\n this.startCycling();\n }\n }\n\n disconnectedCallback() {\n this.stopCycling();\n }\n\n @Watch('autoCycle')\n handleAutoCycleChange(newValue: boolean) {\n if (newValue) {\n this.startCycling();\n } else {\n this.stopCycling();\n }\n }\n\n private getItems(): FeatureAccordionItem[] {\n try {\n return JSON.parse(this.items);\n } catch {\n return [];\n }\n }\n\n private startCycling() {\n this.stopCycling();\n this.progressStartTime = Date.now();\n this.timerProgress = 100;\n \n // Progress animation frame\n const updateProgress = () => {\n const elapsed = Date.now() - this.progressStartTime;\n const remaining = this.cycleInterval - elapsed;\n \n if (remaining <= 0) {\n this.moveToNextItem();\n } else {\n this.timerProgress = (remaining / this.cycleInterval) * 100;\n this.progressTimer = requestAnimationFrame(updateProgress);\n }\n };\n \n this.progressTimer = requestAnimationFrame(updateProgress);\n }\n\n private stopCycling() {\n if (this.progressTimer) {\n cancelAnimationFrame(this.progressTimer);\n this.progressTimer = null;\n }\n }\n\n private moveToNextItem() {\n const items = this.getItems();\n if (items.length === 0) return;\n \n this.expandedIndex = (this.expandedIndex + 1) % items.length;\n // Restart the cycling timer for the new item\n this.startCycling();\n }\n\n private handleItemClick(index: number) {\n // Reset timer when user clicks\n this.expandedIndex = index;\n // Restart the cycling timer for the clicked item\n if (this.autoCycle) {\n this.startCycling();\n }\n }\n\n render() {\n const items = this.getItems();\n const currentItem = items[this.expandedIndex];\n\n return (\n <Host>\n <div class=\"feature-accordion\">\n <div class=\"feature-accordion__container\">\n <h2 class=\"feature-accordion__heading\">{this.heading}</h2>\n \n <div class=\"feature-accordion__content\">\n {/* Left side - Accordion */}\n <div class=\"feature-accordion__list\">\n {items.map((item, index) => (\n <div \n class={{\n 'accordion-item': true,\n 'accordion-item--expanded': this.expandedIndex === index\n }}\n key={index}\n >\n <button\n class=\"accordion-item__header\"\n onClick={() => this.handleItemClick(index)}\n aria-expanded={this.expandedIndex === index ? 'true' : 'false'}\n >\n <h4 class=\"accordion-item__title\">{item.title}</h4>\n {/* Plus → minus: a single SVG with two strokes, the\n vertical one rotated-out to zero when expanded. This\n gives a fluid morph instead of swapping SVGs mid-\n animation. */}\n <span class=\"accordion-item__icon\" aria-hidden=\"true\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path class=\"accordion-item__icon-bar\" d=\"M5 12H19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n <path class=\"accordion-item__icon-bar accordion-item__icon-bar--vert\" d=\"M12 5V19\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/>\n </svg>\n </span>\n </button>\n <div\n class=\"accordion-item__content\"\n style={{\n opacity: this.expandedIndex === index ? '1' : '0'\n }}\n >\n <p class=\"accordion-item__description\">{item.description}</p>\n {this.expandedIndex === index && this.autoCycle && (\n <div class=\"accordion-item__timer-track\">\n <div \n class=\"accordion-item__timer-progress\"\n style={{ width: `${this.timerProgress}%` }}\n ></div>\n </div>\n )}\n </div>\n </div>\n ))}\n </div>\n\n {/* Right side - Image */}\n <div class=\"feature-accordion__image-container\">\n <div class=\"feature-accordion__image-wrapper\">\n {currentItem?.imageUrl && (\n <img \n src={currentItem.imageUrl} \n alt={currentItem.imageAlt || currentItem.title}\n class=\"feature-accordion__image\"\n />\n )}\n {!currentItem?.imageUrl && (\n <div class=\"feature-accordion__image-placeholder\">\n <slot name=\"image\"></slot>\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n"],"names":["h","Host","index"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-BuJz1C1M.js');
4
4
 
5
- const afHeroCss = ".sc-af-hero-h{display:block;position:relative;width:100%;--af-hero-image-lift:-260px;--af-hero-image-min-height:360px}.hero__section.sc-af-hero{position:relative;overflow:hidden}.hero__paperclip.sc-af-hero{position:absolute;top:50%;right:0;transform:translateY(-50%);pointer-events:none;z-index:0;width:655px;height:754px}@media (max-width: 991px){.hero__paperclip.sc-af-hero{width:480px;height:552px}}@media (max-width: 767px){.hero__paperclip.sc-af-hero{display:none}}.hero__inner.sc-af-hero{position:relative;z-index:1;padding-bottom:40px}.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:124px}.hero--pad-loose.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:164px}.hero--inkwell-centered.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:180px}.hero__grid.sc-af-hero{display:grid;grid-template-columns:5fr 7fr;gap:40px;align-items:center}.hero--soft-clay-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--mist-green-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr auto;gap:48px}.hero--inkwell-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr 1fr}.hero__copy.sc-af-hero{padding-left:16px}.hero--inkwell-photo.hero--pad-loose.sc-af-hero-h .hero__copy.sc-af-hero{padding-bottom:120px}.hero--inkwell-centered.sc-af-hero-h .hero__copy.sc-af-hero{padding-left:0;text-align:center}.hero__badge.sc-af-hero:not(:has(*)){display:none}.hero__badge.sc-af-hero:has(*){margin-bottom:16px}.hero__copy.sc-af-hero-s>[slot='badge'],.hero__copy .sc-af-hero-s>[slot='badge']{display:inline-block}.hero__buttons.sc-af-hero{margin-top:32px}.hero__buttons.sc-af-hero:empty{display:none}.hero--inkwell-centered.sc-af-hero-h .hero__buttons.sc-af-hero{display:flex;justify-content:center}.sc-af-hero-h{--af-hero-blob-mask:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=');--af-hero-blob-mask-mobile:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 768\"><path fill=\"%23000\" d=\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\"/></svg>')}.hero__image.sc-af-hero{min-height:var(--af-hero-image-min-height);overflow:visible;margin-top:var(--af-hero-image-lift);position:relative;z-index:1}.hero__image--masked.sc-af-hero-s>img,.hero__image--masked .sc-af-hero-s>img,.hero__image--masked.sc-af-hero-s>picture img,.hero__image--masked .sc-af-hero-s>picture img,.hero__image--masked.sc-af-hero-s>.af-hero-image,.hero__image--masked .sc-af-hero-s>.af-hero-image{display:block;width:100%;height:auto;-webkit-mask-image:var(--af-hero-blob-mask);mask-image:var(--af-hero-blob-mask);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;mask-mode:alpha}.hero__image--masked.sc-af-hero img.sc-af-hero{-webkit-mask-image:var(--af-hero-blob-mask);mask-image:var(--af-hero-blob-mask);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;mask-mode:alpha}.hero__illustration.sc-af-hero{flex:0 0 auto;width:100%;max-width:432px;line-height:0;justify-self:end}.hero__illustration.sc-af-hero-s>svg,.hero__illustration .sc-af-hero-s>svg,.hero__illustration.sc-af-hero-s>img,.hero__illustration .sc-af-hero-s>img{width:100%;height:auto;display:block;border-radius:16px}.hero--inkwell-illustration.sc-af-hero-h .hero__illustration.sc-af-hero{max-width:540px}.hero__logos.sc-af-hero{position:relative;z-index:2}.hero__logos.sc-af-hero:not(:has(*)){display:none}.hero--inkwell-photo.sc-af-hero-h .hero__logos.sc-af-hero:has(*){margin-top:-240px;padding-top:48px;padding-bottom:48px;background:var(--af-background-base, var(--colour-brand-inkwell, #14343b));border-top:1px solid\n var(--af-background-border-subtle, var(--colour-inkwell-450, #203e45))}@media (max-width: 991px){.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero,.hero--pad-loose.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:112px}.hero--inkwell-centered.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:144px}.hero__grid.sc-af-hero{grid-template-columns:1fr;gap:32px}.hero--soft-clay-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--mist-green-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--inkwell-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr}.hero__copy.sc-af-hero{padding-left:0;padding-bottom:0}.hero__illustration.sc-af-hero{max-width:360px;margin-inline:auto;justify-self:center}.hero__image.sc-af-hero{margin-top:0;min-height:auto}.sc-af-hero-h.hero--inkwell-photo .hero__image--masked.sc-af-hero-s>img,.hero__image--masked .sc-af-hero-s>img,.hero--inkwell-photo.sc-af-hero-h .hero__image--masked.sc-af-hero img.sc-af-hero{-webkit-mask-image:var(--af-hero-blob-mask-mobile);mask-image:var(--af-hero-blob-mask-mobile)}.hero--inkwell-photo.sc-af-hero-h .hero__logos.sc-af-hero:has(*){margin-top:24px;padding-top:32px;padding-bottom:32px;background:transparent;border-top:none}}";
5
+ const afHeroCss = ".sc-af-hero-h{display:block;position:relative;width:100%;--af-hero-image-lift:-260px;--af-hero-image-min-height:360px}.hero__section.sc-af-hero{position:relative;overflow:hidden}.hero__paperclip.sc-af-hero{position:absolute;top:50%;right:0;transform:translateY(-50%);pointer-events:none;z-index:0;width:520px;height:600px}@media (max-width: 991px){.hero__paperclip.sc-af-hero{width:380px;height:437px}}@media (max-width: 767px){.hero__paperclip.sc-af-hero{display:none}}.hero__inner.sc-af-hero{position:relative;z-index:1;padding-bottom:40px}.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:124px}.hero--pad-loose.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:164px}.hero--inkwell-centered.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:180px}.hero__grid.sc-af-hero{display:grid;grid-template-columns:5fr 7fr;gap:40px;align-items:center}.hero--soft-clay-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--mist-green-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr auto;gap:48px}.hero--inkwell-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr 1fr}.hero__copy.sc-af-hero{padding-left:16px}.hero--inkwell-photo.hero--pad-loose.sc-af-hero-h .hero__copy.sc-af-hero{padding-bottom:120px}.hero--inkwell-centered.sc-af-hero-h .hero__copy.sc-af-hero{padding-left:0;text-align:center}.hero__badge.sc-af-hero:not(:has(*)){display:none}.hero__badge.sc-af-hero:has(*){margin-bottom:16px}.hero__copy.sc-af-hero-s>[slot='badge'],.hero__copy .sc-af-hero-s>[slot='badge']{display:inline-block}.hero__buttons.sc-af-hero{margin-top:32px}.hero__buttons.sc-af-hero:empty{display:none}.hero--inkwell-centered.sc-af-hero-h .hero__buttons.sc-af-hero{display:flex;justify-content:center}.sc-af-hero-h{--af-hero-blob-mask:url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=');--af-hero-blob-mask-mobile:url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 768\"><path fill=\"%23000\" d=\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\"/></svg>')}.hero__image.sc-af-hero{min-height:var(--af-hero-image-min-height);overflow:visible;margin-top:var(--af-hero-image-lift);position:relative;z-index:1}.hero__image--masked.sc-af-hero-s>img,.hero__image--masked .sc-af-hero-s>img,.hero__image--masked.sc-af-hero-s>picture img,.hero__image--masked .sc-af-hero-s>picture img,.hero__image--masked.sc-af-hero-s>.af-hero-image,.hero__image--masked .sc-af-hero-s>.af-hero-image{display:block;width:100%;height:auto;-webkit-mask-image:var(--af-hero-blob-mask);mask-image:var(--af-hero-blob-mask);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;mask-mode:alpha}.hero__image--masked.sc-af-hero img.sc-af-hero{-webkit-mask-image:var(--af-hero-blob-mask);mask-image:var(--af-hero-blob-mask);-webkit-mask-size:100% 100%;mask-size:100% 100%;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-position:center;mask-position:center;mask-mode:alpha}.hero__illustration.sc-af-hero{flex:0 0 auto;width:100%;max-width:432px;line-height:0;justify-self:end}.hero__illustration.sc-af-hero-s>svg,.hero__illustration .sc-af-hero-s>svg,.hero__illustration.sc-af-hero-s>img,.hero__illustration .sc-af-hero-s>img{width:100%;height:auto;display:block;border-radius:16px}.hero--inkwell-illustration.sc-af-hero-h .hero__illustration.sc-af-hero{max-width:540px}.hero__logos.sc-af-hero{position:relative;z-index:2}.hero__logos.sc-af-hero:not(:has(*)){display:none}.hero--inkwell-photo.sc-af-hero-h .hero__logos.sc-af-hero:has(*){margin-top:-240px;padding-top:48px;padding-bottom:48px;background:var(--af-background-base, var(--colour-brand-inkwell, #14343b));border-top:1px solid\n var(--af-background-border-subtle, var(--colour-inkwell-450, #203e45))}@media (max-width: 991px){.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero,.hero--pad-loose.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:112px}.hero--inkwell-centered.hero--pad-default.sc-af-hero-h .hero__inner.sc-af-hero{padding-top:144px}.hero__grid.sc-af-hero{grid-template-columns:1fr;gap:32px}.hero--soft-clay-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--mist-green-illustration.sc-af-hero-h .hero__grid.sc-af-hero,.hero--inkwell-illustration.sc-af-hero-h .hero__grid.sc-af-hero{grid-template-columns:1fr}.hero__copy.sc-af-hero{padding-left:0;padding-bottom:0}.hero__illustration.sc-af-hero{max-width:360px;margin-inline:auto;justify-self:center}.hero__image.sc-af-hero{margin-top:0;min-height:auto}.sc-af-hero-h.hero--inkwell-photo .hero__image--masked.sc-af-hero-s>img,.hero__image--masked .sc-af-hero-s>img,.hero--inkwell-photo.sc-af-hero-h .hero__image--masked.sc-af-hero img.sc-af-hero{-webkit-mask-image:var(--af-hero-blob-mask-mobile);mask-image:var(--af-hero-blob-mask-mobile)}.hero--inkwell-photo.sc-af-hero-h .hero__logos.sc-af-hero:has(*){margin-top:24px;padding-top:32px;padding-bottom:32px;background:transparent;border-top:none}}";
6
6
 
7
7
  /**
8
8
  * Map each variant to its underlying section theme token. Keeps one source
@@ -1 +1 @@
1
- {"version":3,"file":"af-hero.entry.cjs.js","sources":["src/components/af-hero/af-hero.css?tag=af-hero&encapsulation=scoped","src/components/af-hero/af-hero.tsx"],"sourcesContent":[":host {\n display: block;\n position: relative;\n width: 100%;\n /* Image-lift custom property — consumers override per-page via inline\n style or a page-level rule. The negative value pulls the photo's\n crown above the hero top so it reads behind the floating navbar\n pill. Matches the live Webflow stack (~-260px on .page-banner). */\n --af-hero-image-lift: -260px;\n /* Blob mask container size override — rarely needed; defaults to the\n photo column's natural dimensions. */\n --af-hero-image-min-height: 360px;\n}\n\n.hero__section {\n position: relative;\n overflow: hidden;\n}\n\n/* -----------------------------------------------------------------\n Paperclip watermark slot (inkwell-centered only)\n ----------------------------------------------------------------- */\n.hero__paperclip {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n pointer-events: none;\n z-index: 0;\n /* Default size — consumers can resize the slotted decoration via its\n own width/height props. */\n width: 655px;\n height: 754px;\n}\n\n@media (max-width: 991px) {\n .hero__paperclip {\n width: 480px;\n height: 552px;\n }\n}\n\n@media (max-width: 767px) {\n .hero__paperclip {\n display: none;\n }\n}\n\n/* -----------------------------------------------------------------\n Inner wrapper — top/bottom padding\n ----------------------------------------------------------------- */\n.hero__inner {\n position: relative;\n z-index: 1;\n padding-bottom: 40px;\n}\n\n:host(.hero--pad-default) .hero__inner {\n padding-top: 124px;\n}\n\n:host(.hero--pad-loose) .hero__inner {\n padding-top: 164px;\n}\n\n/* Centered variant: leave clear breathing room under the floating navbar\n pill so the heading isn't clipped at the top. The live affinda.com\n reference at 1280 vw renders the heading roughly 180 px below the\n viewport top — pad accordingly. (Earlier value of 80 px clipped the\n heading behind the navbar; caught by qa/regression-compare in the\n site repo.) */\n:host(.hero--inkwell-centered.hero--pad-default) .hero__inner {\n padding-top: 180px;\n}\n\n/* -----------------------------------------------------------------\n Grid layout (photo + illustration variants)\n ----------------------------------------------------------------- */\n.hero__grid {\n display: grid;\n grid-template-columns: 5fr 7fr;\n gap: 40px;\n align-items: center;\n}\n\n/* Illustration variants use a looser two-column split so the art\n doesn't dominate. */\n:host(.hero--soft-clay-illustration) .hero__grid,\n:host(.hero--mist-green-illustration) .hero__grid {\n grid-template-columns: 1fr auto;\n gap: 48px;\n}\n\n/* inkwell-illustration: 50/50 split. The 5fr/7fr default tilts the\n illustration column too wide, which pinches the heading down to\n 4-6 lines at 1280 vw. Even split keeps the heading at 2-3 lines\n matching the live affinda.com reference. */\n:host(.hero--inkwell-illustration) .hero__grid {\n grid-template-columns: 1fr 1fr;\n}\n\n.hero__copy {\n /* Small inset pushes heading inward from the hard container edge —\n matches the live .page-banner-text treatment. Only applied to\n left-aligned variants. */\n padding-left: 16px;\n}\n\n:host(.hero--inkwell-photo.hero--pad-loose) .hero__copy {\n /* Mirrors ListingHero's `padding-bottom: 120px` — combined with\n `align-items: center` on the grid, this shifts the heading visually\n upward so the subtitle lines up near the image's vertical centre. */\n padding-bottom: 120px;\n}\n\n:host(.hero--inkwell-centered) .hero__copy {\n padding-left: 0;\n text-align: center;\n}\n\n.hero__badge:not(:has(*)) {\n display: none;\n}\n\n.hero__badge:has(*) {\n margin-bottom: 16px;\n}\n\n.hero__copy ::slotted([slot='badge']) {\n display: inline-block;\n}\n\n.hero__buttons {\n margin-top: 32px;\n}\n\n.hero__buttons:empty {\n display: none;\n}\n\n:host(.hero--inkwell-centered) .hero__buttons {\n display: flex;\n justify-content: center;\n}\n\n/* -----------------------------------------------------------------\n Photo (inkwell-photo)\n Blob-mask shape defined once as a CSS custom property so Stencil\n doesn't duplicate the giant base64 URL for prefixed/unprefixed pairs.\n ----------------------------------------------------------------- */\n:host {\n --af-hero-blob-mask: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=');\n --af-hero-blob-mask-mobile: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 768\"><path fill=\"%23000\" d=\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\"/></svg>');\n}\n\n.hero__image {\n min-height: var(--af-hero-image-min-height);\n overflow: visible;\n margin-top: var(--af-hero-image-lift);\n position: relative;\n z-index: 1;\n}\n\n.hero__image--masked ::slotted(img),\n.hero__image--masked ::slotted(picture img),\n.hero__image--masked ::slotted(.af-hero-image) {\n display: block;\n width: 100%;\n height: auto;\n -webkit-mask-image: var(--af-hero-blob-mask);\n mask-image: var(--af-hero-blob-mask);\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n -webkit-mask-repeat: no-repeat;\n mask-repeat: no-repeat;\n -webkit-mask-position: center;\n mask-position: center;\n mask-mode: alpha;\n}\n\n/* Fallback: some consumers slot a raw <img> wrapped in a container.\n Descendant selector per repo convention. */\n.hero__image--masked img {\n -webkit-mask-image: var(--af-hero-blob-mask);\n mask-image: var(--af-hero-blob-mask);\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n -webkit-mask-repeat: no-repeat;\n mask-repeat: no-repeat;\n -webkit-mask-position: center;\n mask-position: center;\n mask-mode: alpha;\n}\n\n/* -----------------------------------------------------------------\n Illustration (inkwell/soft-clay/mist-green -illustration)\n ----------------------------------------------------------------- */\n.hero__illustration {\n flex: 0 0 auto;\n width: 100%;\n max-width: 432px;\n line-height: 0;\n justify-self: end;\n}\n\n.hero__illustration ::slotted(svg),\n.hero__illustration ::slotted(img) {\n width: 100%;\n height: auto;\n display: block;\n border-radius: 16px;\n}\n\n/* Cap inkwell-illustration's slotted SVG so square-aspect art doesn't\n tower past the text column. 540 px matches the live treatment for\n the /industries + /integrations heroes. */\n:host(.hero--inkwell-illustration) .hero__illustration {\n max-width: 540px;\n}\n\n/* -----------------------------------------------------------------\n Logos-below overlap\n Painted in the theme's background token so the strip cleanly overlaps\n the bottom of the photo on the -photo variant. Empty = collapsed.\n ----------------------------------------------------------------- */\n.hero__logos {\n position: relative;\n z-index: 2;\n}\n\n.hero__logos:not(:has(*)) {\n display: none;\n}\n\n/* Photo variant pulls the logos row up so it covers the image's bottom\n edge — matches the ListingHero `.listing-hero__footer` treatment. */\n:host(.hero--inkwell-photo) .hero__logos:has(*) {\n margin-top: -240px;\n padding-top: 48px;\n padding-bottom: 48px;\n background: var(--af-background-base, var(--colour-brand-inkwell, #14343b));\n border-top: 1px solid\n var(--af-background-border-subtle, var(--colour-inkwell-450, #203e45));\n}\n\n/* -----------------------------------------------------------------\n Mobile / tablet\n ----------------------------------------------------------------- */\n@media (max-width: 991px) {\n :host(.hero--pad-default) .hero__inner,\n :host(.hero--pad-loose) .hero__inner {\n padding-top: 112px;\n }\n\n /* Centered variant still needs a touch more clearance under the\n navbar pill on tablet. */\n :host(.hero--inkwell-centered.hero--pad-default) .hero__inner {\n padding-top: 144px;\n }\n\n .hero__grid {\n grid-template-columns: 1fr;\n gap: 32px;\n }\n\n :host(.hero--soft-clay-illustration) .hero__grid,\n :host(.hero--mist-green-illustration) .hero__grid,\n :host(.hero--inkwell-illustration) .hero__grid {\n grid-template-columns: 1fr;\n }\n\n .hero__copy {\n padding-left: 0;\n padding-bottom: 0;\n }\n\n .hero__illustration {\n max-width: 360px;\n margin-inline: auto;\n justify-self: center;\n }\n\n /* Photo on mobile: swap the desktop blob mask for the softer D-curve\n mobile variant, and drop the lift so the image doesn't crash into\n the navbar. */\n .hero__image {\n margin-top: 0;\n min-height: auto;\n }\n\n :host(.hero--inkwell-photo) .hero__image--masked ::slotted(img),\n :host(.hero--inkwell-photo) .hero__image--masked img {\n -webkit-mask-image: var(--af-hero-blob-mask-mobile);\n mask-image: var(--af-hero-blob-mask-mobile);\n }\n\n :host(.hero--inkwell-photo) .hero__logos:has(*) {\n margin-top: 24px;\n padding-top: 32px;\n padding-bottom: 32px;\n background: transparent;\n border-top: none;\n }\n}\n","import { Component, h, Host, Prop, Element } from '@stencil/core';\n\nexport type HeroVariant =\n | 'inkwell-photo'\n | 'inkwell-illustration'\n | 'inkwell-centered'\n | 'soft-clay-illustration'\n | 'mist-green-illustration';\n\nexport type HeroTopPad = 'default' | 'loose';\n\n/**\n * Blob-shape mask used to clip hero photos on the inkwell-photo variant.\n * Extracted from the 7+ hand-rolled copies in the website so the path is\n * defined exactly once. Intrinsic viewBox: 741 × 940.\n */\nconst BLOB_MASK_URL =\n \"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=')\";\n\n/**\n * Mobile blob shape — simpler D-curve matching the live mobile banner.\n */\nconst BLOB_MASK_URL_MOBILE =\n \"url('data:image/svg+xml;utf8,<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 1024 768\\\"><path fill=\\\"%23000\\\" d=\\\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\\\"/></svg>')\";\n\n/**\n * Map each variant to its underlying section theme token. Keeps one source\n * of truth instead of having consumers spell the theme twice.\n */\nconst VARIANT_THEMES: Record<HeroVariant, 'inkwell' | 'soft-clay' | 'mist-green'> = {\n 'inkwell-photo': 'inkwell',\n 'inkwell-illustration': 'inkwell',\n 'inkwell-centered': 'inkwell',\n 'soft-clay-illustration': 'soft-clay',\n 'mist-green-illustration': 'mist-green',\n};\n\n/**\n * Unified top-of-page hero — replaces the 7+ hand-rolled hero implementations\n * the Affinda marketing site (and sibling apps) currently ship. Covers five\n * canonical patterns via the `variant` prop:\n *\n * - `inkwell-photo` — inkwell background, blob-masked photo on the right.\n * Use for: listing / archive pages (blog, case-studies, whitepapers,\n * value-creation, about-us) and industry landing pages that carry a\n * photograph instead of an illustration.\n * - `inkwell-illustration` — inkwell background, illustration on the right.\n * Use for: industry landing pages, /industries, /integrations, /platform\n * with bespoke art.\n * - `inkwell-centered` — inkwell background, centred typography lockup.\n * Slot `<af-paperclip-decoration />` into the `paperclip` slot for the\n * watermark treatment. Use for: `/`, `/au`, `/platform`.\n * - `soft-clay-illustration` — soft-clay background, illustration on the\n * right. Use for: /news, /industries overview, /security, /compare.\n * - `mist-green-illustration` — same layout as soft-clay-illustration but on\n * the mist-green theme. Reserved for future pages.\n *\n * ## Slots\n *\n * - default — heading content (use when richer markup than the `heading`\n * prop can express is needed; e.g. coloured spans or line breaks).\n * - `description` — supporting copy under the heading.\n * - `badge` — optional pre-heading label (pill, version tag).\n * - `buttons` — hero CTAs (usually an `<af-button-group>`).\n * - `image` — the photograph for the `inkwell-photo` variant. Wrapped in\n * the blob mask automatically.\n * - `illustration` — the illustration SVG for `-illustration` variants.\n * - `paperclip` — watermark for `inkwell-centered`. Consumers typically\n * slot `<af-paperclip-decoration />` here.\n * - `logos-below` — overlap row at the bottom gutter (logo carousel etc.).\n * Painted with the theme's background so it cleanly overlaps the image's\n * lower edge on the photo variant.\n *\n * ## Float-navbar handling\n *\n * When `floatNavbar` is true (the default for the inkwell variants) the\n * component sets `data-af-hero-float-navbar=\"true\"` on `<body>` via a\n * lifecycle hook, and a companion rule in `@affinda/css/base.css` applies\n * the `body > header { position: absolute }` / `main { padding-top: 0 }`\n * / navbar-spacer-transparent treatment. Consumers already import\n * `@affinda/css` so no extra import is required. The rule deactivates\n * when the hero is removed from the DOM.\n *\n * ## Image lift\n *\n * The `inkwell-photo` variant renders the photo column with\n * `margin-top: var(--af-hero-image-lift, -260px)`. Override per-page by\n * setting `--af-hero-image-lift` on the `<af-hero>` element.\n */\n@Component({\n tag: 'af-hero',\n styleUrl: 'af-hero.css',\n shadow: false,\n scoped: true,\n})\nexport class AfHero {\n @Element() el!: HTMLElement;\n\n /** Layout / theme preset. See variant docs in the component header. */\n @Prop({ reflect: true }) variant: HeroVariant = 'inkwell-photo';\n\n /** Heading text (use the default slot for richer markup). */\n @Prop() heading: string = '';\n\n /** Description text (use the `description` slot for richer markup). */\n @Prop() description: string = '';\n\n /**\n * Float the site header over the hero and paint the navbar-spacer\n * transparent so the hero background flows to the top of the viewport.\n * Defaults to true for the three inkwell variants, false for the\n * soft-clay / mist-green illustration variants (whose consumers don't\n * always want a full-bleed crown).\n */\n @Prop({ reflect: true }) floatNavbar?: boolean;\n\n /**\n * Top padding preset. `default` = 124px (matches IndustryHero /\n * IllustrationHero). `loose` = 164px (matches ListingHero — gives the\n * image a touch more breathing room above the lockup on archive pages).\n */\n @Prop() topPad: HeroTopPad = 'default';\n\n /** Typography lockup max-width (px). Defaults to 620, matching the live site. */\n @Prop() maxWidth: number = 620;\n\n /**\n * Whether to apply the blob mask to the slotted `image`. Defaults to\n * `true` for `inkwell-photo`. Set `false` if you want to slot in a\n * pre-masked raster or a custom wrapper.\n */\n @Prop() maskImage: boolean = true;\n\n private get resolvedFloatNavbar(): boolean {\n if (typeof this.floatNavbar === 'boolean') return this.floatNavbar;\n return (\n this.variant === 'inkwell-photo' ||\n this.variant === 'inkwell-illustration' ||\n this.variant === 'inkwell-centered'\n );\n }\n\n private get theme() {\n return VARIANT_THEMES[this.variant];\n }\n\n connectedCallback() {\n if (this.resolvedFloatNavbar && typeof document !== 'undefined') {\n document.body.setAttribute('data-af-hero-float-navbar', 'true');\n }\n }\n\n disconnectedCallback() {\n if (typeof document !== 'undefined' && !document.querySelector('af-hero')) {\n document.body.removeAttribute('data-af-hero-float-navbar');\n }\n }\n\n private renderCopy() {\n const alignment = this.variant === 'inkwell-centered' ? 'center' : 'left';\n return (\n <div class=\"hero__copy\">\n <div class=\"hero__badge\">\n <slot name=\"badge\"></slot>\n </div>\n <af-typography-lockup\n heading-size=\"1\"\n text-alignment={alignment}\n max-width={String(this.maxWidth)}\n >\n {this.heading ? <h1>{this.heading}</h1> : <slot></slot>}\n {this.description ? (\n <span slot=\"description\">{this.description}</span>\n ) : (\n <slot name=\"description\" slot=\"description\"></slot>\n )}\n </af-typography-lockup>\n <div class=\"hero__buttons\">\n <slot name=\"buttons\"></slot>\n </div>\n </div>\n );\n }\n\n private renderPhoto() {\n return (\n <div\n class={{\n hero__image: true,\n 'hero__image--masked': this.maskImage,\n }}\n >\n <slot name=\"image\"></slot>\n </div>\n );\n }\n\n private renderIllustration() {\n return (\n <div class=\"hero__illustration\">\n <slot name=\"illustration\"></slot>\n </div>\n );\n }\n\n render() {\n const v = this.variant;\n const centered = v === 'inkwell-centered';\n const hasImage = v === 'inkwell-photo';\n const hasIllustration =\n v === 'inkwell-illustration' ||\n v === 'soft-clay-illustration' ||\n v === 'mist-green-illustration';\n\n return (\n <Host\n class={{\n [`hero--${v}`]: true,\n [`hero--pad-${this.topPad}`]: true,\n [`hero--theme-${this.theme}`]: true,\n 'hero--float-navbar': this.resolvedFloatNavbar,\n }}\n >\n <af-section\n theme={this.theme}\n padding=\"none\"\n container={false}\n class=\"hero__section\"\n >\n {centered && (\n <div class=\"hero__paperclip\" aria-hidden=\"true\">\n <slot name=\"paperclip\"></slot>\n </div>\n )}\n <af-container class=\"hero__inner\">\n {centered ? (\n this.renderCopy()\n ) : (\n <div class=\"hero__grid\">\n {this.renderCopy()}\n {hasImage && this.renderPhoto()}\n {hasIllustration && this.renderIllustration()}\n </div>\n )}\n </af-container>\n <div class=\"hero__logos\">\n <slot name=\"logos-below\"></slot>\n </div>\n </af-section>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":"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"}
1
+ {"version":3,"file":"af-hero.entry.cjs.js","sources":["src/components/af-hero/af-hero.css?tag=af-hero&encapsulation=scoped","src/components/af-hero/af-hero.tsx"],"sourcesContent":[":host {\n display: block;\n position: relative;\n width: 100%;\n /* Image-lift custom property — consumers override per-page via inline\n style or a page-level rule. The negative value pulls the photo's\n crown above the hero top so it reads behind the floating navbar\n pill. Matches the live Webflow stack (~-260px on .page-banner). */\n --af-hero-image-lift: -260px;\n /* Blob mask container size override — rarely needed; defaults to the\n photo column's natural dimensions. */\n --af-hero-image-min-height: 360px;\n}\n\n.hero__section {\n position: relative;\n overflow: hidden;\n}\n\n/* -----------------------------------------------------------------\n Paperclip watermark slot (inkwell-centered only)\n ----------------------------------------------------------------- */\n.hero__paperclip {\n position: absolute;\n top: 50%;\n right: 0;\n transform: translateY(-50%);\n pointer-events: none;\n z-index: 0;\n /* Default size — consumers can resize the slotted decoration via its\n own width/height props. The earlier 655×754 default extended past\n the bottom edge of the hero on every page that ships a\n `logos-below` slot (home, /au, /platform), bleeding into the\n client-logo carousel and getting clipped. Trimmed to 520×600 so\n the paperclip stays inside the hero column at every common viewport\n while still reading as a watermark. */\n width: 520px;\n height: 600px;\n}\n\n@media (max-width: 991px) {\n .hero__paperclip {\n width: 380px;\n height: 437px;\n }\n}\n\n@media (max-width: 767px) {\n .hero__paperclip {\n display: none;\n }\n}\n\n/* -----------------------------------------------------------------\n Inner wrapper — top/bottom padding\n ----------------------------------------------------------------- */\n.hero__inner {\n position: relative;\n z-index: 1;\n padding-bottom: 40px;\n}\n\n:host(.hero--pad-default) .hero__inner {\n padding-top: 124px;\n}\n\n:host(.hero--pad-loose) .hero__inner {\n padding-top: 164px;\n}\n\n/* Centered variant: leave clear breathing room under the floating navbar\n pill so the heading isn't clipped at the top. The live affinda.com\n reference at 1280 vw renders the heading roughly 180 px below the\n viewport top — pad accordingly. (Earlier value of 80 px clipped the\n heading behind the navbar; caught by qa/regression-compare in the\n site repo.) */\n:host(.hero--inkwell-centered.hero--pad-default) .hero__inner {\n padding-top: 180px;\n}\n\n/* -----------------------------------------------------------------\n Grid layout (photo + illustration variants)\n ----------------------------------------------------------------- */\n.hero__grid {\n display: grid;\n grid-template-columns: 5fr 7fr;\n gap: 40px;\n align-items: center;\n}\n\n/* Illustration variants use a looser two-column split so the art\n doesn't dominate. */\n:host(.hero--soft-clay-illustration) .hero__grid,\n:host(.hero--mist-green-illustration) .hero__grid {\n grid-template-columns: 1fr auto;\n gap: 48px;\n}\n\n/* inkwell-illustration: 50/50 split. The 5fr/7fr default tilts the\n illustration column too wide, which pinches the heading down to\n 4-6 lines at 1280 vw. Even split keeps the heading at 2-3 lines\n matching the live affinda.com reference. */\n:host(.hero--inkwell-illustration) .hero__grid {\n grid-template-columns: 1fr 1fr;\n}\n\n.hero__copy {\n /* Small inset pushes heading inward from the hard container edge —\n matches the live .page-banner-text treatment. Only applied to\n left-aligned variants. */\n padding-left: 16px;\n}\n\n:host(.hero--inkwell-photo.hero--pad-loose) .hero__copy {\n /* Mirrors ListingHero's `padding-bottom: 120px` — combined with\n `align-items: center` on the grid, this shifts the heading visually\n upward so the subtitle lines up near the image's vertical centre. */\n padding-bottom: 120px;\n}\n\n:host(.hero--inkwell-centered) .hero__copy {\n padding-left: 0;\n text-align: center;\n}\n\n.hero__badge:not(:has(*)) {\n display: none;\n}\n\n.hero__badge:has(*) {\n margin-bottom: 16px;\n}\n\n.hero__copy ::slotted([slot='badge']) {\n display: inline-block;\n}\n\n.hero__buttons {\n margin-top: 32px;\n}\n\n.hero__buttons:empty {\n display: none;\n}\n\n:host(.hero--inkwell-centered) .hero__buttons {\n display: flex;\n justify-content: center;\n}\n\n/* -----------------------------------------------------------------\n Photo (inkwell-photo)\n Blob-mask shape defined once as a CSS custom property so Stencil\n doesn't duplicate the giant base64 URL for prefixed/unprefixed pairs.\n ----------------------------------------------------------------- */\n:host {\n --af-hero-blob-mask: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=');\n --af-hero-blob-mask-mobile: url('data:image/svg+xml;utf8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1024 768\"><path fill=\"%23000\" d=\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\"/></svg>');\n}\n\n.hero__image {\n min-height: var(--af-hero-image-min-height);\n overflow: visible;\n margin-top: var(--af-hero-image-lift);\n position: relative;\n z-index: 1;\n}\n\n.hero__image--masked ::slotted(img),\n.hero__image--masked ::slotted(picture img),\n.hero__image--masked ::slotted(.af-hero-image) {\n display: block;\n width: 100%;\n height: auto;\n -webkit-mask-image: var(--af-hero-blob-mask);\n mask-image: var(--af-hero-blob-mask);\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n -webkit-mask-repeat: no-repeat;\n mask-repeat: no-repeat;\n -webkit-mask-position: center;\n mask-position: center;\n mask-mode: alpha;\n}\n\n/* Fallback: some consumers slot a raw <img> wrapped in a container.\n Descendant selector per repo convention. */\n.hero__image--masked img {\n -webkit-mask-image: var(--af-hero-blob-mask);\n mask-image: var(--af-hero-blob-mask);\n -webkit-mask-size: 100% 100%;\n mask-size: 100% 100%;\n -webkit-mask-repeat: no-repeat;\n mask-repeat: no-repeat;\n -webkit-mask-position: center;\n mask-position: center;\n mask-mode: alpha;\n}\n\n/* -----------------------------------------------------------------\n Illustration (inkwell/soft-clay/mist-green -illustration)\n ----------------------------------------------------------------- */\n.hero__illustration {\n flex: 0 0 auto;\n width: 100%;\n max-width: 432px;\n line-height: 0;\n justify-self: end;\n}\n\n.hero__illustration ::slotted(svg),\n.hero__illustration ::slotted(img) {\n width: 100%;\n height: auto;\n display: block;\n border-radius: 16px;\n}\n\n/* Cap inkwell-illustration's slotted SVG so square-aspect art doesn't\n tower past the text column. 540 px matches the live treatment for\n the /industries + /integrations heroes. */\n:host(.hero--inkwell-illustration) .hero__illustration {\n max-width: 540px;\n}\n\n/* -----------------------------------------------------------------\n Logos-below overlap\n Painted in the theme's background token so the strip cleanly overlaps\n the bottom of the photo on the -photo variant. Empty = collapsed.\n ----------------------------------------------------------------- */\n.hero__logos {\n position: relative;\n z-index: 2;\n}\n\n.hero__logos:not(:has(*)) {\n display: none;\n}\n\n/* Photo variant pulls the logos row up so it covers the image's bottom\n edge — matches the ListingHero `.listing-hero__footer` treatment. */\n:host(.hero--inkwell-photo) .hero__logos:has(*) {\n margin-top: -240px;\n padding-top: 48px;\n padding-bottom: 48px;\n background: var(--af-background-base, var(--colour-brand-inkwell, #14343b));\n border-top: 1px solid\n var(--af-background-border-subtle, var(--colour-inkwell-450, #203e45));\n}\n\n/* -----------------------------------------------------------------\n Mobile / tablet\n ----------------------------------------------------------------- */\n@media (max-width: 991px) {\n :host(.hero--pad-default) .hero__inner,\n :host(.hero--pad-loose) .hero__inner {\n padding-top: 112px;\n }\n\n /* Centered variant still needs a touch more clearance under the\n navbar pill on tablet. */\n :host(.hero--inkwell-centered.hero--pad-default) .hero__inner {\n padding-top: 144px;\n }\n\n .hero__grid {\n grid-template-columns: 1fr;\n gap: 32px;\n }\n\n :host(.hero--soft-clay-illustration) .hero__grid,\n :host(.hero--mist-green-illustration) .hero__grid,\n :host(.hero--inkwell-illustration) .hero__grid {\n grid-template-columns: 1fr;\n }\n\n .hero__copy {\n padding-left: 0;\n padding-bottom: 0;\n }\n\n .hero__illustration {\n max-width: 360px;\n margin-inline: auto;\n justify-self: center;\n }\n\n /* Photo on mobile: swap the desktop blob mask for the softer D-curve\n mobile variant, and drop the lift so the image doesn't crash into\n the navbar. */\n .hero__image {\n margin-top: 0;\n min-height: auto;\n }\n\n :host(.hero--inkwell-photo) .hero__image--masked ::slotted(img),\n :host(.hero--inkwell-photo) .hero__image--masked img {\n -webkit-mask-image: var(--af-hero-blob-mask-mobile);\n mask-image: var(--af-hero-blob-mask-mobile);\n }\n\n :host(.hero--inkwell-photo) .hero__logos:has(*) {\n margin-top: 24px;\n padding-top: 32px;\n padding-bottom: 32px;\n background: transparent;\n border-top: none;\n }\n}\n","import { Component, h, Host, Prop, Element } from '@stencil/core';\n\nexport type HeroVariant =\n | 'inkwell-photo'\n | 'inkwell-illustration'\n | 'inkwell-centered'\n | 'soft-clay-illustration'\n | 'mist-green-illustration';\n\nexport type HeroTopPad = 'default' | 'loose';\n\n/**\n * Blob-shape mask used to clip hero photos on the inkwell-photo variant.\n * Extracted from the 7+ hand-rolled copies in the website so the path is\n * defined exactly once. Intrinsic viewBox: 741 × 940.\n */\nconst BLOB_MASK_URL =\n \"url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3NDEgOTQwIj48cGF0aCBkPSJNMTcwLjA2MyAxODEuOTQ1QzIzNC4xNTYgMzAuOTUxNCA0MDguNTE4IC0zOS40OTU1IDU1OS41MTIgMjQuNTk3NUM3MTAuNTA2IDg4LjY5MDQgNzgwLjk1MiAyNjMuMDUzIDcxNi44NTkgNDE0LjA0Nkw1NzAuODQ3IDc1OC4wMzFDNTA2Ljc1NCA5MDkuMDI0IDMzMi4zOTIgOTc5LjQ3MSAxODEuMzk4IDkxNS4zNzhDMzAuNDA0NSA4NTEuMjg1IC00MC4wNDI0IDY3Ni45MjMgMjQuMDUwNiA1MjUuOTI5TDE3MC4wNjMgMTgxLjk0NVoiIGZpbGw9IiMwMDAiLz48L3N2Zz4=')\";\n\n/**\n * Mobile blob shape — simpler D-curve matching the live mobile banner.\n */\nconst BLOB_MASK_URL_MOBILE =\n \"url('data:image/svg+xml;utf8,<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 1024 768\\\"><path fill=\\\"%23000\\\" d=\\\"M1024 0H384A384 384 0 0 0 384 768H1024V0Z\\\"/></svg>')\";\n\n/**\n * Map each variant to its underlying section theme token. Keeps one source\n * of truth instead of having consumers spell the theme twice.\n */\nconst VARIANT_THEMES: Record<HeroVariant, 'inkwell' | 'soft-clay' | 'mist-green'> = {\n 'inkwell-photo': 'inkwell',\n 'inkwell-illustration': 'inkwell',\n 'inkwell-centered': 'inkwell',\n 'soft-clay-illustration': 'soft-clay',\n 'mist-green-illustration': 'mist-green',\n};\n\n/**\n * Unified top-of-page hero — replaces the 7+ hand-rolled hero implementations\n * the Affinda marketing site (and sibling apps) currently ship. Covers five\n * canonical patterns via the `variant` prop:\n *\n * - `inkwell-photo` — inkwell background, blob-masked photo on the right.\n * Use for: listing / archive pages (blog, case-studies, whitepapers,\n * value-creation, about-us) and industry landing pages that carry a\n * photograph instead of an illustration.\n * - `inkwell-illustration` — inkwell background, illustration on the right.\n * Use for: industry landing pages, /industries, /integrations, /platform\n * with bespoke art.\n * - `inkwell-centered` — inkwell background, centred typography lockup.\n * Slot `<af-paperclip-decoration />` into the `paperclip` slot for the\n * watermark treatment. Use for: `/`, `/au`, `/platform`.\n * - `soft-clay-illustration` — soft-clay background, illustration on the\n * right. Use for: /news, /industries overview, /security, /compare.\n * - `mist-green-illustration` — same layout as soft-clay-illustration but on\n * the mist-green theme. Reserved for future pages.\n *\n * ## Slots\n *\n * - default — heading content (use when richer markup than the `heading`\n * prop can express is needed; e.g. coloured spans or line breaks).\n * - `description` — supporting copy under the heading.\n * - `badge` — optional pre-heading label (pill, version tag).\n * - `buttons` — hero CTAs (usually an `<af-button-group>`).\n * - `image` — the photograph for the `inkwell-photo` variant. Wrapped in\n * the blob mask automatically.\n * - `illustration` — the illustration SVG for `-illustration` variants.\n * - `paperclip` — watermark for `inkwell-centered`. Consumers typically\n * slot `<af-paperclip-decoration />` here.\n * - `logos-below` — overlap row at the bottom gutter (logo carousel etc.).\n * Painted with the theme's background so it cleanly overlaps the image's\n * lower edge on the photo variant.\n *\n * ## Float-navbar handling\n *\n * When `floatNavbar` is true (the default for the inkwell variants) the\n * component sets `data-af-hero-float-navbar=\"true\"` on `<body>` via a\n * lifecycle hook, and a companion rule in `@affinda/css/base.css` applies\n * the `body > header { position: absolute }` / `main { padding-top: 0 }`\n * / navbar-spacer-transparent treatment. Consumers already import\n * `@affinda/css` so no extra import is required. The rule deactivates\n * when the hero is removed from the DOM.\n *\n * ## Image lift\n *\n * The `inkwell-photo` variant renders the photo column with\n * `margin-top: var(--af-hero-image-lift, -260px)`. Override per-page by\n * setting `--af-hero-image-lift` on the `<af-hero>` element.\n */\n@Component({\n tag: 'af-hero',\n styleUrl: 'af-hero.css',\n shadow: false,\n scoped: true,\n})\nexport class AfHero {\n @Element() el!: HTMLElement;\n\n /** Layout / theme preset. See variant docs in the component header. */\n @Prop({ reflect: true }) variant: HeroVariant = 'inkwell-photo';\n\n /** Heading text (use the default slot for richer markup). */\n @Prop() heading: string = '';\n\n /** Description text (use the `description` slot for richer markup). */\n @Prop() description: string = '';\n\n /**\n * Float the site header over the hero and paint the navbar-spacer\n * transparent so the hero background flows to the top of the viewport.\n * Defaults to true for the three inkwell variants, false for the\n * soft-clay / mist-green illustration variants (whose consumers don't\n * always want a full-bleed crown).\n */\n @Prop({ reflect: true }) floatNavbar?: boolean;\n\n /**\n * Top padding preset. `default` = 124px (matches IndustryHero /\n * IllustrationHero). `loose` = 164px (matches ListingHero — gives the\n * image a touch more breathing room above the lockup on archive pages).\n */\n @Prop() topPad: HeroTopPad = 'default';\n\n /** Typography lockup max-width (px). Defaults to 620, matching the live site. */\n @Prop() maxWidth: number = 620;\n\n /**\n * Whether to apply the blob mask to the slotted `image`. Defaults to\n * `true` for `inkwell-photo`. Set `false` if you want to slot in a\n * pre-masked raster or a custom wrapper.\n */\n @Prop() maskImage: boolean = true;\n\n private get resolvedFloatNavbar(): boolean {\n if (typeof this.floatNavbar === 'boolean') return this.floatNavbar;\n return (\n this.variant === 'inkwell-photo' ||\n this.variant === 'inkwell-illustration' ||\n this.variant === 'inkwell-centered'\n );\n }\n\n private get theme() {\n return VARIANT_THEMES[this.variant];\n }\n\n connectedCallback() {\n if (this.resolvedFloatNavbar && typeof document !== 'undefined') {\n document.body.setAttribute('data-af-hero-float-navbar', 'true');\n }\n }\n\n disconnectedCallback() {\n if (typeof document !== 'undefined' && !document.querySelector('af-hero')) {\n document.body.removeAttribute('data-af-hero-float-navbar');\n }\n }\n\n private renderCopy() {\n const alignment = this.variant === 'inkwell-centered' ? 'center' : 'left';\n return (\n <div class=\"hero__copy\">\n <div class=\"hero__badge\">\n <slot name=\"badge\"></slot>\n </div>\n <af-typography-lockup\n heading-size=\"1\"\n text-alignment={alignment}\n max-width={String(this.maxWidth)}\n >\n {this.heading ? <h1>{this.heading}</h1> : <slot></slot>}\n {this.description ? (\n <span slot=\"description\">{this.description}</span>\n ) : (\n <slot name=\"description\" slot=\"description\"></slot>\n )}\n </af-typography-lockup>\n <div class=\"hero__buttons\">\n <slot name=\"buttons\"></slot>\n </div>\n </div>\n );\n }\n\n private renderPhoto() {\n return (\n <div\n class={{\n hero__image: true,\n 'hero__image--masked': this.maskImage,\n }}\n >\n <slot name=\"image\"></slot>\n </div>\n );\n }\n\n private renderIllustration() {\n return (\n <div class=\"hero__illustration\">\n <slot name=\"illustration\"></slot>\n </div>\n );\n }\n\n render() {\n const v = this.variant;\n const centered = v === 'inkwell-centered';\n const hasImage = v === 'inkwell-photo';\n const hasIllustration =\n v === 'inkwell-illustration' ||\n v === 'soft-clay-illustration' ||\n v === 'mist-green-illustration';\n\n return (\n <Host\n class={{\n [`hero--${v}`]: true,\n [`hero--pad-${this.topPad}`]: true,\n [`hero--theme-${this.theme}`]: true,\n 'hero--float-navbar': this.resolvedFloatNavbar,\n }}\n >\n <af-section\n theme={this.theme}\n padding=\"none\"\n container={false}\n class=\"hero__section\"\n >\n {centered && (\n <div class=\"hero__paperclip\" aria-hidden=\"true\">\n <slot name=\"paperclip\"></slot>\n </div>\n )}\n <af-container class=\"hero__inner\">\n {centered ? (\n this.renderCopy()\n ) : (\n <div class=\"hero__grid\">\n {this.renderCopy()}\n {hasImage && this.renderPhoto()}\n {hasIllustration && this.renderIllustration()}\n </div>\n )}\n </af-container>\n <div class=\"hero__logos\">\n <slot name=\"logos-below\"></slot>\n </div>\n </af-section>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":"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"}
@@ -9,14 +9,18 @@ const AfPaperclipDecoration = class {
9
9
  index.registerInstance(this, hostRef);
10
10
  /**
11
11
  * SVG width — accepts any CSS length or unitless number (pixels).
12
- * Defaults to the intrinsic viewBox width (`655`).
12
+ * Default sized so the watermark stays inside the af-hero
13
+ * inkwell-centered column without bleeding into the `logos-below`
14
+ * client-logo carousel. Override per-page via the prop if a larger
15
+ * decorative scale is wanted somewhere with no logos slot.
13
16
  */
14
- this.width = '655';
17
+ this.width = '520';
15
18
  /**
16
19
  * SVG height — accepts any CSS length or unitless number (pixels).
17
- * Defaults to the intrinsic viewBox height (`754`).
20
+ * Sized to match the trimmed `width` default; preserves the source
21
+ * SVG's 655 × 754 aspect ratio.
18
22
  */
19
- this.height = '754';
23
+ this.height = '600';
20
24
  /**
21
25
  * Fill opacity of the paperclip shape. Defaults to `0.06` to match the
22
26
  * marketing-site watermark treatment.
@@ -30,7 +34,7 @@ const AfPaperclipDecoration = class {
30
34
  this.fill = 'white';
31
35
  }
32
36
  render() {
33
- return (index.h(index.Host, { key: '2056080b6be950fecf3cd1dc43114e457dac513b' }, index.h("svg", { key: '8a054a7d2794adc1042d474cffb0e82ad686bb63', "aria-hidden": "true", width: this.width, height: this.height, viewBox: "0 0 655 754", fill: "none", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "none" }, index.h("path", { key: 'e8704baa60e7b272d3c731b104b8e93f7a7ae517', d: "M1102.14 108.279C1031.8 37.5181 939.128 -1.06817 840.61 0.447304H358.674L262.104 157.124H841.87C842.558 157.124 843.36 157.124 844.047 157.124C900.638 157.124 953.791 179.273 994 219.725C1035.24 261.225 1058.04 316.715 1058.04 376.052C1058.04 497.872 960.665 596.844 841.068 596.844H251.335C197.609 596.844 153.848 552.313 153.848 497.639C153.848 442.965 197.723 397.734 251.221 396.102H779.208L878.872 239.426H248.586C111.577 242.923 0 358.682 0 497.639C0 636.596 112.723 753.404 251.335 753.404H841.068C1045.55 753.404 1212 584.021 1212 375.935C1212 274.398 1173.05 179.39 1102.26 108.162L1102.14 108.279Z", fill: this.fill, "fill-opacity": this.opacity }))));
37
+ return (index.h(index.Host, { key: '9db0e4d35474d6c783387ed5c522943ac89f5315' }, index.h("svg", { key: 'a79d736a5ab711844bc1f2233c493edf66039fb4', "aria-hidden": "true", width: this.width, height: this.height, viewBox: "0 0 655 754", fill: "none", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "none" }, index.h("path", { key: 'c6a0f21366a159e5af9f69e324797450e4b31b15', d: "M1102.14 108.279C1031.8 37.5181 939.128 -1.06817 840.61 0.447304H358.674L262.104 157.124H841.87C842.558 157.124 843.36 157.124 844.047 157.124C900.638 157.124 953.791 179.273 994 219.725C1035.24 261.225 1058.04 316.715 1058.04 376.052C1058.04 497.872 960.665 596.844 841.068 596.844H251.335C197.609 596.844 153.848 552.313 153.848 497.639C153.848 442.965 197.723 397.734 251.221 396.102H779.208L878.872 239.426H248.586C111.577 242.923 0 358.682 0 497.639C0 636.596 112.723 753.404 251.335 753.404H841.068C1045.55 753.404 1212 584.021 1212 375.935C1212 274.398 1173.05 179.39 1102.26 108.162L1102.14 108.279Z", fill: this.fill, "fill-opacity": this.opacity }))));
34
38
  }
35
39
  };
36
40
  AfPaperclipDecoration.style = afPaperclipDecorationCss;
@@ -1 +1 @@
1
- {"version":3,"file":"af-paperclip-decoration.entry.cjs.js","sources":["src/components/af-paperclip-decoration/af-paperclip-decoration.css?tag=af-paperclip-decoration&encapsulation=shadow","src/components/af-paperclip-decoration/af-paperclip-decoration.tsx"],"sourcesContent":[":host {\n display: block;\n /* Decorative-only; host is sized/positioned by the consumer. */\n pointer-events: none;\n}\n\nsvg {\n display: block;\n /* Let the SVG honour its own width/height attributes rather than\n inheriting host dimensions. */\n}\n","import { Component, h, Host, Prop } from '@stencil/core';\n\n/**\n * Decorative paperclip vector graphic. Renders the left-half paperclip\n * silhouette (viewBox `0 0 655 754`) that the marketing site bleeds off\n * the right edge of inkwell hero sections.\n *\n * Purely decorative — the inner `<svg>` is `aria-hidden=\"true\"`. Size it\n * via the `width` / `height` props (they accept any CSS length, e.g.\n * `\"655\"`, `\"100%\"`, `\"50vw\"`) and position the host element in CSS.\n *\n * `fill` is white by default (intended for inkwell backgrounds); override\n * for other themes, e.g. `fill=\"var(--colour-brand-inkwell)\"` on a\n * mist-green section. `opacity` defaults to `0.06` to match the\n * watermark treatment used on `/`, `/au`, and `/platform`.\n *\n * @example\n * ```html\n * <af-section theme=\"inkwell\" padding=\"loose\" style=\"position:relative;overflow:hidden\">\n * <af-paperclip-decoration\n * style=\"position:absolute;bottom:-80px;right:-80px\"\n * ></af-paperclip-decoration>\n * <af-container style=\"position:relative;z-index:1\">\n * <!-- hero content -->\n * </af-container>\n * </af-section>\n * ```\n */\n@Component({\n tag: 'af-paperclip-decoration',\n styleUrl: 'af-paperclip-decoration.css',\n shadow: true\n})\nexport class AfPaperclipDecoration {\n /**\n * SVG width — accepts any CSS length or unitless number (pixels).\n * Defaults to the intrinsic viewBox width (`655`).\n */\n @Prop() width: string = '655';\n\n /**\n * SVG height — accepts any CSS length or unitless number (pixels).\n * Defaults to the intrinsic viewBox height (`754`).\n */\n @Prop() height: string = '754';\n\n /**\n * Fill opacity of the paperclip shape. Defaults to `0.06` to match the\n * marketing-site watermark treatment.\n */\n @Prop() opacity: number = 0.06;\n\n /**\n * Fill colour. Defaults to `white` (designed for inkwell backgrounds);\n * override for other themes, e.g. `var(--colour-brand-inkwell)` on a\n * mist-green section.\n */\n @Prop() fill: string = 'white';\n\n render() {\n return (\n <Host>\n <svg\n aria-hidden=\"true\"\n width={this.width}\n height={this.height}\n viewBox=\"0 0 655 754\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"none\"\n >\n <path\n d=\"M1102.14 108.279C1031.8 37.5181 939.128 -1.06817 840.61 0.447304H358.674L262.104 157.124H841.87C842.558 157.124 843.36 157.124 844.047 157.124C900.638 157.124 953.791 179.273 994 219.725C1035.24 261.225 1058.04 316.715 1058.04 376.052C1058.04 497.872 960.665 596.844 841.068 596.844H251.335C197.609 596.844 153.848 552.313 153.848 497.639C153.848 442.965 197.723 397.734 251.221 396.102H779.208L878.872 239.426H248.586C111.577 242.923 0 358.682 0 497.639C0 636.596 112.723 753.404 251.335 753.404H841.068C1045.55 753.404 1212 584.021 1212 375.935C1212 274.398 1173.05 179.39 1102.26 108.162L1102.14 108.279Z\"\n fill={this.fill}\n fill-opacity={this.opacity}\n />\n </svg>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":";;;;AAAA,MAAM,wBAAwB,GAAG,6DAA6D;;MCiCjF,qBAAqB,GAAA,MAAA;AALlC,IAAA,WAAA,CAAA,OAAA,EAAA;;AAME;;;AAGG;AACK,QAAA,IAAK,CAAA,KAAA,GAAW,KAAK;AAE7B;;;AAGG;AACK,QAAA,IAAM,CAAA,MAAA,GAAW,KAAK;AAE9B;;;AAGG;AACK,QAAA,IAAO,CAAA,OAAA,GAAW,IAAI;AAE9B;;;;AAIG;AACK,QAAA,IAAI,CAAA,IAAA,GAAW,OAAO;AAuB/B;IArBC,MAAM,GAAA;AACJ,QAAA,QACEA,QAACC,UAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACHD,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,aAAA,EACc,MAAM,EAClB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,OAAO,EAAC,aAAa,EACrB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B,EAClC,mBAAmB,EAAC,MAAM,EAAA,EAE1BA,OAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,CAAC,EAAC,imBAAimB,EACnmB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAA,cAAA,EACD,IAAI,CAAC,OAAO,GAC1B,CACE,CACD;;;;;;;"}
1
+ {"version":3,"file":"af-paperclip-decoration.entry.cjs.js","sources":["src/components/af-paperclip-decoration/af-paperclip-decoration.css?tag=af-paperclip-decoration&encapsulation=shadow","src/components/af-paperclip-decoration/af-paperclip-decoration.tsx"],"sourcesContent":[":host {\n display: block;\n /* Decorative-only; host is sized/positioned by the consumer. */\n pointer-events: none;\n}\n\nsvg {\n display: block;\n /* Let the SVG honour its own width/height attributes rather than\n inheriting host dimensions. */\n}\n","import { Component, h, Host, Prop } from '@stencil/core';\n\n/**\n * Decorative paperclip vector graphic. Renders the left-half paperclip\n * silhouette (viewBox `0 0 655 754`) that the marketing site bleeds off\n * the right edge of inkwell hero sections.\n *\n * Purely decorative — the inner `<svg>` is `aria-hidden=\"true\"`. Size it\n * via the `width` / `height` props (they accept any CSS length, e.g.\n * `\"655\"`, `\"100%\"`, `\"50vw\"`) and position the host element in CSS.\n *\n * `fill` is white by default (intended for inkwell backgrounds); override\n * for other themes, e.g. `fill=\"var(--colour-brand-inkwell)\"` on a\n * mist-green section. `opacity` defaults to `0.06` to match the\n * watermark treatment used on `/`, `/au`, and `/platform`.\n *\n * @example\n * ```html\n * <af-section theme=\"inkwell\" padding=\"loose\" style=\"position:relative;overflow:hidden\">\n * <af-paperclip-decoration\n * style=\"position:absolute;bottom:-80px;right:-80px\"\n * ></af-paperclip-decoration>\n * <af-container style=\"position:relative;z-index:1\">\n * <!-- hero content -->\n * </af-container>\n * </af-section>\n * ```\n */\n@Component({\n tag: 'af-paperclip-decoration',\n styleUrl: 'af-paperclip-decoration.css',\n shadow: true\n})\nexport class AfPaperclipDecoration {\n /**\n * SVG width — accepts any CSS length or unitless number (pixels).\n * Default sized so the watermark stays inside the af-hero\n * inkwell-centered column without bleeding into the `logos-below`\n * client-logo carousel. Override per-page via the prop if a larger\n * decorative scale is wanted somewhere with no logos slot.\n */\n @Prop() width: string = '520';\n\n /**\n * SVG height — accepts any CSS length or unitless number (pixels).\n * Sized to match the trimmed `width` default; preserves the source\n * SVG's 655 × 754 aspect ratio.\n */\n @Prop() height: string = '600';\n\n /**\n * Fill opacity of the paperclip shape. Defaults to `0.06` to match the\n * marketing-site watermark treatment.\n */\n @Prop() opacity: number = 0.06;\n\n /**\n * Fill colour. Defaults to `white` (designed for inkwell backgrounds);\n * override for other themes, e.g. `var(--colour-brand-inkwell)` on a\n * mist-green section.\n */\n @Prop() fill: string = 'white';\n\n render() {\n return (\n <Host>\n <svg\n aria-hidden=\"true\"\n width={this.width}\n height={this.height}\n viewBox=\"0 0 655 754\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n preserveAspectRatio=\"none\"\n >\n <path\n d=\"M1102.14 108.279C1031.8 37.5181 939.128 -1.06817 840.61 0.447304H358.674L262.104 157.124H841.87C842.558 157.124 843.36 157.124 844.047 157.124C900.638 157.124 953.791 179.273 994 219.725C1035.24 261.225 1058.04 316.715 1058.04 376.052C1058.04 497.872 960.665 596.844 841.068 596.844H251.335C197.609 596.844 153.848 552.313 153.848 497.639C153.848 442.965 197.723 397.734 251.221 396.102H779.208L878.872 239.426H248.586C111.577 242.923 0 358.682 0 497.639C0 636.596 112.723 753.404 251.335 753.404H841.068C1045.55 753.404 1212 584.021 1212 375.935C1212 274.398 1173.05 179.39 1102.26 108.162L1102.14 108.279Z\"\n fill={this.fill}\n fill-opacity={this.opacity}\n />\n </svg>\n </Host>\n );\n }\n}\n"],"names":["h","Host"],"mappings":";;;;AAAA,MAAM,wBAAwB,GAAG,6DAA6D;;MCiCjF,qBAAqB,GAAA,MAAA;AALlC,IAAA,WAAA,CAAA,OAAA,EAAA;;AAME;;;;;;AAMG;AACK,QAAA,IAAK,CAAA,KAAA,GAAW,KAAK;AAE7B;;;;AAIG;AACK,QAAA,IAAM,CAAA,MAAA,GAAW,KAAK;AAE9B;;;AAGG;AACK,QAAA,IAAO,CAAA,OAAA,GAAW,IAAI;AAE9B;;;;AAIG;AACK,QAAA,IAAI,CAAA,IAAA,GAAW,OAAO;AAuB/B;IArBC,MAAM,GAAA;AACJ,QAAA,QACEA,QAACC,UAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACHD,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,aAAA,EACc,MAAM,EAClB,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,OAAO,EAAC,aAAa,EACrB,IAAI,EAAC,MAAM,EACX,KAAK,EAAC,4BAA4B,EAClC,mBAAmB,EAAC,MAAM,EAAA,EAE1BA,OAAA,CAAA,MAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EACE,CAAC,EAAC,imBAAimB,EACnmB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAA,cAAA,EACD,IAAI,CAAC,OAAO,GAC1B,CACE,CACD;;;;;;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var index = require('./index-BuJz1C1M.js');
4
4
 
5
- const afTestimonialStatCss = ".sc-af-testimonial-stat-h{display:block;flex:1;min-width:0}.stat.sc-af-testimonial-stat{display:flex;flex-direction:column;gap:8px}.stat--accent.sc-af-testimonial-stat{border-left:2px solid var(--af-background-border-active, var(--colour-softclay-800, #8a7049));padding-left:16px;min-height:76px;justify-content:center}.stat-value.sc-af-testimonial-stat{--af-typography-heading-primary:var(--af-typography-heading-secondary, var(--colour-brand-soft-clay, #b09670));letter-spacing:-0.88px;white-space:nowrap;font-variant-numeric:lining-nums proportional-nums;font-feature-settings:'ss01', 'kern'}.stat-description.sc-af-testimonial-stat{--af-typography-body-default:var(--af-typography-body-dark, var(--colour-brand-inkwell, #14343b));overflow:hidden;text-overflow:ellipsis}";
5
+ const afTestimonialStatCss = ".sc-af-testimonial-stat-h{display:block;flex:1;min-width:0}.stat.sc-af-testimonial-stat{display:flex;flex-direction:column;gap:8px}.stat--accent.sc-af-testimonial-stat{border-left:2px solid var(--af-background-border-active, var(--colour-softclay-800, #8a7049));padding-left:24px;min-height:76px;justify-content:center}.stat-value.sc-af-testimonial-stat{--af-typography-heading-primary:var(--af-typography-heading-secondary, var(--colour-brand-soft-clay, #b09670));letter-spacing:-0.88px;white-space:nowrap;font-variant-numeric:lining-nums proportional-nums;font-feature-settings:'ss01', 'kern'}.stat-description.sc-af-testimonial-stat{--af-typography-body-default:var(--af-typography-body-dark, var(--colour-brand-inkwell, #14343b));overflow:hidden;text-overflow:ellipsis}";
6
6
 
7
7
  const AfTestimonialStat = class {
8
8
  constructor(hostRef) {
@@ -1 +1 @@
1
- {"version":3,"file":"af-testimonial-stat.entry.cjs.js","sources":["src/components/af-testimonial-stat/af-testimonial-stat.css?tag=af-testimonial-stat&encapsulation=scoped","src/components/af-testimonial-stat/af-testimonial-stat.tsx"],"sourcesContent":[":host {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.stat--accent {\n /* Themed active/accent border color */\n border-left: 2px solid var(--af-background-border-active, var(--colour-softclay-800, #8a7049));\n padding-left: 16px;\n min-height: 76px;\n justify-content: center;\n}\n\n/* Stat value - override af-heading to use secondary color */\n.stat-value {\n /* Override the heading color to use secondary (gold/ochre) instead of primary */\n --af-typography-heading-primary: var(--af-typography-heading-secondary, var(--colour-brand-soft-clay, #b09670));\n letter-spacing: -0.88px;\n white-space: nowrap;\n /* Lining figures so \"1B+\" / \"95%\" hit a consistent baseline and\n optical weight, matching af-stat. */\n font-variant-numeric: lining-nums proportional-nums;\n font-feature-settings: 'ss01', 'kern';\n}\n\n/* Description - override af-text to use body-dark for emphasis */\n.stat-description {\n --af-typography-body-default: var(--af-typography-body-dark, var(--colour-brand-inkwell, #14343b));\n overflow: hidden;\n text-overflow: ellipsis;\n}","import { Component, Prop, h, Host } from '@stencil/core';\n\n@Component({\n tag: 'af-testimonial-stat',\n styleUrl: 'af-testimonial-stat.css',\n shadow: false,\n scoped: true,\n})\nexport class AfTestimonialStat {\n /**\n * The statistic value (e.g., \"95%\", \"10×\", \"120,000\")\n */\n @Prop() value!: string;\n\n /**\n * Description text for the statistic\n */\n @Prop() description!: string;\n\n /**\n * Whether to show left accent border\n */\n @Prop() accentBorder: boolean = false;\n\n render() {\n return (\n <Host>\n <div class={`stat ${this.accentBorder ? 'stat--accent' : ''}`}>\n {/* Stat value uses secondary heading color via CSS override */}\n <af-heading level={2} class=\"stat-value\">{this.value}</af-heading>\n {/* Description uses af-text for proper theming */}\n <af-text variant=\"medium\" class=\"stat-description\">{this.description}</af-text>\n </div>\n </Host>\n );\n }\n}\n\n\n"],"names":["h","Host"],"mappings":";;;;AAAA,MAAM,oBAAoB,GAAG,uwBAAuwB;;MCQvxB,iBAAiB,GAAA,MAAA;AAN9B,IAAA,WAAA,CAAA,OAAA,EAAA;;AAiBE;;AAEG;AACK,QAAA,IAAY,CAAA,YAAA,GAAY,KAAK;AActC;IAZC,MAAM,GAAA;AACJ,QAAA,QACEA,QAACC,UAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACHD,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAE,QAAQ,IAAI,CAAC,YAAY,GAAG,cAAc,GAAG,EAAE,CAAE,CAAA,EAAA,EAE3DA,OAAY,CAAA,YAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAE,CAAC,EAAE,KAAK,EAAC,YAAY,EAAE,EAAA,IAAI,CAAC,KAAK,CAAc,EAElEA,OAAA,CAAA,SAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAS,OAAO,EAAC,QAAQ,EAAC,KAAK,EAAC,kBAAkB,EAAE,EAAA,IAAI,CAAC,WAAW,CAAW,CAC3E,CACD;;;;;;;"}
1
+ {"version":3,"file":"af-testimonial-stat.entry.cjs.js","sources":["src/components/af-testimonial-stat/af-testimonial-stat.css?tag=af-testimonial-stat&encapsulation=scoped","src/components/af-testimonial-stat/af-testimonial-stat.tsx"],"sourcesContent":[":host {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.stat {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.stat--accent {\n /* Themed active/accent border color */\n border-left: 2px solid var(--af-background-border-active, var(--colour-softclay-800, #8a7049));\n /* Bumped from 16 px → 24 px because the prior 16 px gave too little\n breathing room between the divider and the stat-value at narrower\n card widths — long values like \"$1.2M\" / \"95%\" intersected the\n rule on State Cover Mutual / Felix at 1024-1280 vw. Surfaced\n 2026-04-27. */\n padding-left: 24px;\n min-height: 76px;\n justify-content: center;\n}\n\n/* Stat value - override af-heading to use secondary color */\n.stat-value {\n /* Override the heading color to use secondary (gold/ochre) instead of primary */\n --af-typography-heading-primary: var(--af-typography-heading-secondary, var(--colour-brand-soft-clay, #b09670));\n letter-spacing: -0.88px;\n white-space: nowrap;\n /* Lining figures so \"1B+\" / \"95%\" hit a consistent baseline and\n optical weight, matching af-stat. */\n font-variant-numeric: lining-nums proportional-nums;\n font-feature-settings: 'ss01', 'kern';\n}\n\n/* Description - override af-text to use body-dark for emphasis */\n.stat-description {\n --af-typography-body-default: var(--af-typography-body-dark, var(--colour-brand-inkwell, #14343b));\n overflow: hidden;\n text-overflow: ellipsis;\n}","import { Component, Prop, h, Host } from '@stencil/core';\n\n@Component({\n tag: 'af-testimonial-stat',\n styleUrl: 'af-testimonial-stat.css',\n shadow: false,\n scoped: true,\n})\nexport class AfTestimonialStat {\n /**\n * The statistic value (e.g., \"95%\", \"10×\", \"120,000\")\n */\n @Prop() value!: string;\n\n /**\n * Description text for the statistic\n */\n @Prop() description!: string;\n\n /**\n * Whether to show left accent border\n */\n @Prop() accentBorder: boolean = false;\n\n render() {\n return (\n <Host>\n <div class={`stat ${this.accentBorder ? 'stat--accent' : ''}`}>\n {/* Stat value uses secondary heading color via CSS override */}\n <af-heading level={2} class=\"stat-value\">{this.value}</af-heading>\n {/* Description uses af-text for proper theming */}\n <af-text variant=\"medium\" class=\"stat-description\">{this.description}</af-text>\n </div>\n </Host>\n );\n }\n}\n\n\n"],"names":["h","Host"],"mappings":";;;;AAAA,MAAM,oBAAoB,GAAG,uwBAAuwB;;MCQvxB,iBAAiB,GAAA,MAAA;AAN9B,IAAA,WAAA,CAAA,OAAA,EAAA;;AAiBE;;AAEG;AACK,QAAA,IAAY,CAAA,YAAA,GAAY,KAAK;AActC;IAZC,MAAM,GAAA;AACJ,QAAA,QACEA,QAACC,UAAI,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,EACHD,OAAA,CAAA,KAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAK,KAAK,EAAE,QAAQ,IAAI,CAAC,YAAY,GAAG,cAAc,GAAG,EAAE,CAAE,CAAA,EAAA,EAE3DA,OAAY,CAAA,YAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAA,KAAK,EAAE,CAAC,EAAE,KAAK,EAAC,YAAY,EAAE,EAAA,IAAI,CAAC,KAAK,CAAc,EAElEA,OAAA,CAAA,SAAA,EAAA,EAAA,GAAA,EAAA,0CAAA,EAAS,OAAO,EAAC,QAAQ,EAAC,KAAK,EAAC,kBAAkB,EAAE,EAAA,IAAI,CAAC,WAAW,CAAW,CAC3E,CACD;;;;;;;"}
@@ -46,10 +46,9 @@
46
46
  animation-duration: 40s;
47
47
  }
48
48
 
49
- /* Pause animation on hover */
50
- :host(:hover) .logo-track {
51
- animation-play-state: paused;
52
- }
49
+ /* No pause on hover — the carousel is purely decorative; pausing it on
50
+ hover felt jittery when the cursor accidentally crossed it (and live
51
+ affinda.com keeps it scrolling regardless). */
53
52
 
54
53
  /* Respect reduced motion: stop the infinite scroll and hold at a
55
54
  * stable frame so logos remain visible instead of being offscreen. */
@@ -137,11 +137,36 @@
137
137
 
138
138
  .accordion-item__content {
139
139
  overflow: hidden;
140
+ /* Use grid-template-rows-based expansion (0fr → 1fr) so the
141
+ transition animates the *actual* content height, not a max-height
142
+ ceiling. Avoids the "section height bumps for a split second"
143
+ jank that happens when the outgoing item's content is shorter
144
+ than max-height: at the midpoint of a max-height transition the
145
+ outgoing item still renders at its natural height (because
146
+ max-height >> content) while the incoming item ALSO renders at
147
+ its natural height — sum > steady-state for a frame, so the
148
+ image column on the right jumps. With grid-rows, each item
149
+ occupies its proportional fraction of its own natural height;
150
+ incoming + outgoing always sums to one full content row.
151
+ Reported 2026-04-27 on /au's "Give Affinda Platform your
152
+ paperwork" section. */
153
+ display: grid;
154
+ grid-template-rows: 0fr;
140
155
  transition:
141
- max-height var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),
156
+ grid-template-rows var(--motion-duration-slow, 300ms) var(--motion-easing-emphasized, cubic-bezier(0.2, 0, 0, 1)),
142
157
  opacity var(--motion-duration-slow, 300ms) var(--motion-easing-standard, cubic-bezier(0.4, 0, 0.2, 1));
143
158
  }
144
159
 
160
+ .accordion-item--expanded .accordion-item__content {
161
+ grid-template-rows: 1fr;
162
+ }
163
+
164
+ /* Inner wrapper required for grid-template-rows interpolation:
165
+ the direct grid child collapses to min-content otherwise. */
166
+ .accordion-item__content > * {
167
+ min-height: 0;
168
+ }
169
+
145
170
  @media (prefers-reduced-motion: reduce) {
146
171
  .accordion-item__icon,
147
172
  .accordion-item__icon-bar,
@@ -102,9 +102,8 @@ export class AfFeatureAccordion {
102
102
  'accordion-item': true,
103
103
  'accordion-item--expanded': this.expandedIndex === index
104
104
  }, key: index }, h("button", { class: "accordion-item__header", onClick: () => this.handleItemClick(index), "aria-expanded": this.expandedIndex === index ? 'true' : 'false' }, h("h4", { class: "accordion-item__title" }, item.title), h("span", { class: "accordion-item__icon", "aria-hidden": "true" }, h("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { class: "accordion-item__icon-bar", d: "M5 12H19", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("path", { class: "accordion-item__icon-bar accordion-item__icon-bar--vert", d: "M12 5V19", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" })))), h("div", { class: "accordion-item__content", style: {
105
- maxHeight: this.expandedIndex === index ? '200px' : '0',
106
105
  opacity: this.expandedIndex === index ? '1' : '0'
107
- } }, h("p", { class: "accordion-item__description" }, item.description), this.expandedIndex === index && this.autoCycle && (h("div", { class: "accordion-item__timer-track" }, h("div", { class: "accordion-item__timer-progress", style: { width: `${this.timerProgress}%` } })))))))), h("div", { key: '902712779f4ff2eaae179762a7b78ff1f0784d58', class: "feature-accordion__image-container" }, h("div", { key: 'b741cfaf96428e786e8780cfeff90a0c315716e8', class: "feature-accordion__image-wrapper" }, currentItem?.imageUrl && (h("img", { key: '2a565b530441c9953139b3c0517f480a81f0a77a', src: currentItem.imageUrl, alt: currentItem.imageAlt || currentItem.title, class: "feature-accordion__image" })), !currentItem?.imageUrl && (h("div", { key: 'f8248c73c5dcbd6b8224ad646ee867d34004437d', class: "feature-accordion__image-placeholder" }, h("slot", { key: '9cbe9ee773b0acd5a1b80fa4f6dd2f293152e598', name: "image" }))))))))));
106
+ } }, h("p", { class: "accordion-item__description" }, item.description), this.expandedIndex === index && this.autoCycle && (h("div", { class: "accordion-item__timer-track" }, h("div", { class: "accordion-item__timer-progress", style: { width: `${this.timerProgress}%` } })))))))), h("div", { key: '160448af8f6c8c07adcb6aebf2cfdc27e29a242a', class: "feature-accordion__image-container" }, h("div", { key: 'c67cb6ce37a6a737d005d445eeea242241439fd4', class: "feature-accordion__image-wrapper" }, currentItem?.imageUrl && (h("img", { key: '663d009d13858b56ff4f4f91e64b07d386630f95', src: currentItem.imageUrl, alt: currentItem.imageAlt || currentItem.title, class: "feature-accordion__image" })), !currentItem?.imageUrl && (h("div", { key: '2a1142e7e82cd7c0e0e12a6ba0b9b5bd7397f928', class: "feature-accordion__image-placeholder" }, h("slot", { key: '6023de60150d6eb41b27ee459b123e2f95234588', name: "image" }))))))))));
108
107
  }
109
108
  static get is() { return "af-feature-accordion"; }
110
109
  static get encapsulation() { return "scoped"; }