@conduction/docusaurus-preset 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/MISSING_COMPONENTS.md +109 -0
  2. package/README.md +171 -0
  3. package/package.json +59 -0
  4. package/src/components/AgentTrace/AgentTrace.jsx +128 -0
  5. package/src/components/AgentTrace/AgentTrace.module.css +115 -0
  6. package/src/components/AppMock/AppMock.jsx +86 -0
  7. package/src/components/AppMock/AppMock.module.css +629 -0
  8. package/src/components/AppMock/variants/DeciDeskMock.jsx +71 -0
  9. package/src/components/AppMock/variants/DocuDeskMock.jsx +69 -0
  10. package/src/components/AppMock/variants/LarpingAppMock.jsx +59 -0
  11. package/src/components/AppMock/variants/MyDashBiMock.jsx +135 -0
  12. package/src/components/AppMock/variants/MyDashMock.jsx +96 -0
  13. package/src/components/AppMock/variants/MyDashTilesMock.jsx +103 -0
  14. package/src/components/AppMock/variants/MyDashWidgetsMock.jsx +123 -0
  15. package/src/components/AppMock/variants/NLDesignMock.jsx +70 -0
  16. package/src/components/AppMock/variants/OpenCatalogiMock.jsx +61 -0
  17. package/src/components/AppMock/variants/OpenConnectorMock.jsx +83 -0
  18. package/src/components/AppMock/variants/OpenRegisterMock.jsx +100 -0
  19. package/src/components/AppMock/variants/OpenWooMock.jsx +61 -0
  20. package/src/components/AppMock/variants/PipelinQMock.jsx +88 -0
  21. package/src/components/AppMock/variants/ProcestMock.jsx +87 -0
  22. package/src/components/AppMock/variants/SoftwareCatalogMock.jsx +71 -0
  23. package/src/components/AppMock/variants/ZaakAfhandelAppMock.jsx +71 -0
  24. package/src/components/AppsGrid/AppsGrid.jsx +84 -0
  25. package/src/components/AppsGrid/AppsGrid.module.css +46 -0
  26. package/src/components/AppsPreview/AppsPreview.jsx +85 -0
  27. package/src/components/AppsPreview/AppsPreview.module.css +128 -0
  28. package/src/components/Clients/Clients.jsx +205 -0
  29. package/src/components/Clients/Clients.module.css +166 -0
  30. package/src/components/ComposeBlock/ComposeBlock.jsx +70 -0
  31. package/src/components/ComposeBlock/ComposeBlock.module.css +74 -0
  32. package/src/components/ConductionBg/ConductionBg.jsx +150 -0
  33. package/src/components/ConductionBg/ConductionBg.module.css +41 -0
  34. package/src/components/ContentCard/ContentCard.jsx +126 -0
  35. package/src/components/ContentCard/ContentCard.module.css +84 -0
  36. package/src/components/ContentDetailHero/ContentDetailHero.jsx +136 -0
  37. package/src/components/ContentDetailHero/ContentDetailHero.module.css +96 -0
  38. package/src/components/ContentTypeFilter/ContentTypeFilter.jsx +103 -0
  39. package/src/components/ContentTypeFilter/ContentTypeFilter.module.css +60 -0
  40. package/src/components/ContentTypeFilter/contentTypes.js +58 -0
  41. package/src/components/CookieCli/CookieCli.jsx +223 -0
  42. package/src/components/CookieCli/CookieCli.module.css +166 -0
  43. package/src/components/CtaBanner/CtaBanner.jsx +61 -0
  44. package/src/components/CtaBanner/CtaBanner.module.css +65 -0
  45. package/src/components/DetailHero/DetailHero.jsx +143 -0
  46. package/src/components/DetailHero/DetailHero.module.css +154 -0
  47. package/src/components/Diagrams/Diagrams.jsx +148 -0
  48. package/src/components/EmployeeCard/EmployeeCard.jsx +127 -0
  49. package/src/components/EmployeeCard/EmployeeCard.module.css +144 -0
  50. package/src/components/ExternalAppShelf/ExternalAppShelf.jsx +61 -0
  51. package/src/components/ExternalAppShelf/ExternalAppShelf.module.css +90 -0
  52. package/src/components/FAQ/FAQ.jsx +42 -0
  53. package/src/components/FAQ/FAQ.module.css +74 -0
  54. package/src/components/FacetedFilters/FacetedFilters.jsx +125 -0
  55. package/src/components/FacetedFilters/FacetedFilters.module.css +133 -0
  56. package/src/components/FeatureGrid/FeatureGrid.jsx +94 -0
  57. package/src/components/FeatureGrid/FeatureGrid.module.css +114 -0
  58. package/src/components/FeatureList/FeatureList.jsx +54 -0
  59. package/src/components/FeatureList/FeatureList.module.css +52 -0
  60. package/src/components/FeaturedCard/FeaturedCard.jsx +101 -0
  61. package/src/components/FeaturedCard/FeaturedCard.module.css +98 -0
  62. package/src/components/GameModal/GameModal.jsx +197 -0
  63. package/src/components/GameModal/GameModal.module.css +184 -0
  64. package/src/components/Hero/Hero.jsx +101 -0
  65. package/src/components/Hero/Hero.module.css +95 -0
  66. package/src/components/HexBackground/HexBackground.jsx +56 -0
  67. package/src/components/HexBackground/HexBackground.module.css +73 -0
  68. package/src/components/HexNetwork/HexNetwork.jsx +141 -0
  69. package/src/components/HexNetwork/HexNetwork.module.css +187 -0
  70. package/src/components/HexRain/HexRain.jsx +81 -0
  71. package/src/components/HowSteps/HowSteps.jsx +57 -0
  72. package/src/components/HowSteps/HowSteps.module.css +52 -0
  73. package/src/components/ManagedCommonGround/ManagedCommonGround.jsx +78 -0
  74. package/src/components/ManagedCommonGround/ManagedCommonGround.module.css +16 -0
  75. package/src/components/NewsletterCta/NewsletterCta.jsx +83 -0
  76. package/src/components/NewsletterCta/NewsletterCta.module.css +103 -0
  77. package/src/components/PairCard/PairCard.jsx +58 -0
  78. package/src/components/PairCard/PairCard.module.css +54 -0
  79. package/src/components/PartnerCard/PartnerCard.jsx +130 -0
  80. package/src/components/PartnerCard/PartnerCard.module.css +198 -0
  81. package/src/components/PartnerDirectory/PartnerDirectory.jsx +122 -0
  82. package/src/components/PartnerDirectory/PartnerDirectory.module.css +25 -0
  83. package/src/components/PartnerSidecard/PartnerSidecard.jsx +116 -0
  84. package/src/components/PartnerSidecard/PartnerSidecard.module.css +185 -0
  85. package/src/components/Pipeline/Pipeline.jsx +198 -0
  86. package/src/components/Pipeline/Pipeline.module.css +206 -0
  87. package/src/components/PlatformDiagram/PlatformDiagram.jsx +110 -0
  88. package/src/components/PlatformOverview/PlatformOverview.jsx +68 -0
  89. package/src/components/PlatformOverview/PlatformOverview.module.css +71 -0
  90. package/src/components/ReferenceCard/ReferenceCard.jsx +44 -0
  91. package/src/components/ReferenceCard/ReferenceCard.module.css +57 -0
  92. package/src/components/RelatedPosts/RelatedPosts.jsx +58 -0
  93. package/src/components/RelatedPosts/RelatedPosts.module.css +51 -0
  94. package/src/components/RotatingCards/RotatingCards.jsx +98 -0
  95. package/src/components/RotatingCards/RotatingCards.module.css +153 -0
  96. package/src/components/Showcase/Showcase.jsx +129 -0
  97. package/src/components/Showcase/Showcase.module.css +168 -0
  98. package/src/components/SolutionCard/SolutionCard.jsx +83 -0
  99. package/src/components/SolutionCard/SolutionCard.module.css +99 -0
  100. package/src/components/StatsStrip/StatsStrip.jsx +38 -0
  101. package/src/components/StatsStrip/StatsStrip.module.css +53 -0
  102. package/src/components/WidgetShelf/WidgetShelf.jsx +67 -0
  103. package/src/components/WidgetShelf/WidgetShelf.module.css +73 -0
  104. package/src/components/index.js +96 -0
  105. package/src/components/primitives/AuthorByline.jsx +85 -0
  106. package/src/components/primitives/AuthorByline.module.css +57 -0
  107. package/src/components/primitives/BrandCitation.jsx +71 -0
  108. package/src/components/primitives/Button.jsx +46 -0
  109. package/src/components/primitives/Button.module.css +88 -0
  110. package/src/components/primitives/Card.jsx +42 -0
  111. package/src/components/primitives/Card.module.css +42 -0
  112. package/src/components/primitives/Eyebrow.jsx +37 -0
  113. package/src/components/primitives/Eyebrow.module.css +19 -0
  114. package/src/components/primitives/HexBullet.jsx +37 -0
  115. package/src/components/primitives/HexBullet.module.css +16 -0
  116. package/src/components/primitives/HexThumbnail.jsx +70 -0
  117. package/src/components/primitives/HexThumbnail.module.css +45 -0
  118. package/src/components/primitives/Pill.jsx +42 -0
  119. package/src/components/primitives/Pill.module.css +30 -0
  120. package/src/components/primitives/Section.jsx +51 -0
  121. package/src/components/primitives/Section.module.css +31 -0
  122. package/src/components/primitives/SectionHead.jsx +36 -0
  123. package/src/components/primitives/SectionHead.module.css +43 -0
  124. package/src/components/primitives/index.js +22 -0
  125. package/src/css/brand.css +158 -0
  126. package/src/css/tokens.css +12 -0
  127. package/src/data/app-downloads.js +42 -0
  128. package/src/diagrams/README.md +74 -0
  129. package/src/diagrams/cn-domain-tree.js +105 -0
  130. package/src/diagrams/cn-hex-prism.js +163 -0
  131. package/src/diagrams/cn-hex.js +181 -0
  132. package/src/diagrams/cn-honeycomb-bg.js +135 -0
  133. package/src/diagrams/cn-pipeline.js +150 -0
  134. package/src/diagrams/cn-platform.js +156 -0
  135. package/src/diagrams/cn-side-box.js +104 -0
  136. package/src/diagrams/index.js +28 -0
  137. package/src/index.js +183 -0
  138. package/src/theme/Footer/index.jsx +516 -0
  139. package/src/theme/MDXPage/index.jsx +134 -0
  140. package/src/theme/Navbar/index.jsx +120 -0
  141. package/src/theme/Navbar/styles.module.css +114 -0
  142. package/src/theme/brand.jsx +63 -0
  143. package/src/theme.js +45 -0
  144. package/src/utils/lazyScript.js +37 -0
  145. package/static/img/favicon.svg +14 -0
  146. package/static/img/honeycomb-scatter.svg +23 -0
  147. package/static/img/honeycomb-watermark.svg +108 -0
  148. package/static/img/logo-dark.svg +11 -0
  149. package/static/img/logo.svg +14 -0
  150. package/static/img/nextcloud-logo.svg +5 -0
  151. package/static/lib/canal-footer.css +418 -0
  152. package/static/lib/canal-footer.js +499 -0
  153. package/static/lib/clients-flow.js +317 -0
  154. package/static/lib/conduction-bg.css +50 -0
  155. package/static/lib/conduction-bg.js +122 -0
  156. package/static/lib/hex-rain.css +128 -0
  157. package/static/lib/hex-rain.js +284 -0
  158. package/static/lib/kade-cyclist.css +264 -0
  159. package/static/lib/kade-cyclist.js +420 -0
  160. package/static/lib/logo-memory.css +219 -0
  161. package/static/lib/logo-memory.js +540 -0
  162. package/static/lib/platform-diagram.css +458 -0
  163. package/static/lib/platform-diagram.js +414 -0
@@ -0,0 +1,516 @@
1
+ /**
2
+ * Brand Footer swizzle — canal scene + brand block + link grid.
3
+ *
4
+ * Replaces Docusaurus's default footer with the full Conduction canal
5
+ * footer pattern from preview/components/footer.html: a randomised
6
+ * Amsterdam trapgevel skyline, a gray kade with bikes and cars drifting
7
+ * along it, and a cobalt-900 canal with orange boats, a swimmer, a
8
+ * hovercraft, and a hidden mini-game. The brand block + link grid ride
9
+ * inside the canal so the wave layer reads behind the type.
10
+ *
11
+ * The visual scaffolding is JSX with global class names exactly matching
12
+ * the rules in canal-footer.css (loaded site-side via the connext
13
+ * customCss). The hidden <template> elements at the bottom are cloned
14
+ * by canal-footer.js to populate the skyline and to spawn boats during
15
+ * the mini-game.
16
+ *
17
+ * The structure is intentionally close to the source HTML so updates
18
+ * to the kit can flow through with minimal translation work.
19
+ */
20
+
21
+ import React, {useEffect} from 'react';
22
+ import Link from '@docusaurus/Link';
23
+ import Head from '@docusaurus/Head';
24
+ import {useLocation} from '@docusaurus/router';
25
+ import {useThemeConfig} from '@docusaurus/theme-common';
26
+ import useIsBrowser from '@docusaurus/useIsBrowser';
27
+ import {brandFor} from '../brand.jsx';
28
+ import {useLazyScript} from '../../utils/lazyScript';
29
+ import GameModal from '../../components/GameModal/GameModal';
30
+
31
+ function FooterLink({label, href, to}) {
32
+ if (href) {
33
+ const external = href.startsWith('http');
34
+ return (
35
+ <a
36
+ href={href}
37
+ target={external ? '_blank' : undefined}
38
+ rel={external ? 'noopener noreferrer' : undefined}
39
+ >
40
+ {label}
41
+ </a>
42
+ );
43
+ }
44
+ return <Link to={to}>{label}</Link>;
45
+ }
46
+
47
+ export default function Footer() {
48
+ const {footer, navbar} = useThemeConfig();
49
+ const location = useLocation();
50
+ /* Brand switch follows the pathname: /connext or /commonground sections
51
+ show their styled wordmark and slot themselves into the triad row.
52
+ Outside sub-brand sections the wordmark falls back to the navbar
53
+ title (the parent brand, typically "Conduction"). */
54
+ const brand = brandFor(location.pathname, navbar?.title);
55
+ const wordmark = brand ? brand.wordmark : (navbar?.title || 'Conduction');
56
+
57
+ /* canal-footer.js is loaded post-hydration so its DOM mutations
58
+ (filling .skyline, animating boats) don't trip React hydration
59
+ mismatches. See docs in utils/lazyScript.js. */
60
+ useLazyScript('/lib/canal-footer.js', 'canal-footer');
61
+
62
+ /* kade-cyclist.js is the second hidden footer minigame. It listens for
63
+ clicks on .ki-bike-1 / .ki-bike-2 inside the kade strip and runs a
64
+ dodge-the-traffic round in parallel with the boat game. */
65
+ useLazyScript('/lib/kade-cyclist.js', 'kade-cyclist');
66
+
67
+ /* Re-hydrate the canal-footer + kade-cyclist runtimes on every mount,
68
+ including SPA route changes that re-render this Footer component.
69
+ Both runtimes ship as IIFE scripts that run once at script-load and
70
+ bind to the first .canal-footer they find. Without a re-hydrate
71
+ call here, internal navigation leaves the new footer with an empty
72
+ .skyline (no trapgevel houses) and unwired boats / bikes (the
73
+ mini-games refuse to start until a hard reload). Each runtime
74
+ exposes window.<Name>.hydrate() once it has loaded; we poll one
75
+ rAF at a time until both appear, then call them. */
76
+ const isBrowser = useIsBrowser();
77
+ useEffect(() => {
78
+ if (!isBrowser) return;
79
+ let cancelled = false;
80
+ function tryHydrate() {
81
+ if (cancelled) return;
82
+ const canalReady = !!window.CanalFooter?.hydrate;
83
+ const kadeReady = !!window.KadeCyclist?.hydrate;
84
+ if (canalReady) window.CanalFooter.hydrate();
85
+ if (kadeReady) window.KadeCyclist.hydrate();
86
+ if (!canalReady || !kadeReady) requestAnimationFrame(tryHydrate);
87
+ }
88
+ tryHydrate();
89
+ return () => { cancelled = true; };
90
+ }, [isBrowser, location.pathname]);
91
+
92
+ if (!footer) return null;
93
+ const {links = [], copyright} = footer;
94
+
95
+ return (
96
+ <>
97
+ <Head>
98
+ <link rel="stylesheet" href="/lib/canal-footer.css" />
99
+ <link rel="stylesheet" href="/lib/kade-cyclist.css" />
100
+ </Head>
101
+
102
+ <footer className="canal-footer" aria-label="Site footer">
103
+ {/* Skyline placeholder — canal-footer.js fills it with cloned house templates */}
104
+ <div className="skyline" role="presentation" />
105
+
106
+ {/* Kade (gray quay) with bikes + cars drifting along it */}
107
+ <div className="kade">
108
+ <div className="kade-items">
109
+ <svg className="ki ki-bike-1" width="22" height="16" viewBox="0 -2 22 18" aria-hidden="true">
110
+ <g stroke="var(--c-cobalt-900)" strokeWidth="1.4" fill="none" strokeLinecap="round">
111
+ <circle cx="4" cy="12" r="3"/>
112
+ <circle cx="18" cy="12" r="3"/>
113
+ <line x1="4" y1="12" x2="11" y2="6"/>
114
+ <line x1="11" y1="6" x2="18" y2="12"/>
115
+ <line x1="11" y1="6" x2="14" y2="12"/>
116
+ <line x1="11" y1="6" x2="11" y2="3"/>
117
+ <line x1="11" y1="3" x2="14" y2="6"/>
118
+ </g>
119
+ <circle cx="11" cy="1.5" r="1.6" fill="var(--c-cobalt-900)"/>
120
+ </svg>
121
+ <svg className="ki ki-car-1" width="38" height="16" viewBox="0 0 38 16" aria-hidden="true">
122
+ <rect x="0" y="6" width="38" height="6" rx="2" fill="#C8482F"/>
123
+ <path d="M 5,6 L 9,2 L 29,2 L 33,6 Z" fill="#C8482F"/>
124
+ <rect x="11" y="3" width="6" height="3" fill="rgba(255,255,255,0.5)"/>
125
+ <rect x="20" y="3" width="6" height="3" fill="rgba(255,255,255,0.5)"/>
126
+ <circle cx="9" cy="13" r="2" fill="var(--c-cobalt-900)"/>
127
+ <circle cx="29" cy="13" r="2" fill="var(--c-cobalt-900)"/>
128
+ </svg>
129
+ <svg className="ki ki-bike-2" width="22" height="16" viewBox="0 -2 22 18" aria-hidden="true">
130
+ <g stroke="var(--c-cobalt-900)" strokeWidth="1.4" fill="none" strokeLinecap="round">
131
+ <circle cx="4" cy="12" r="3"/>
132
+ <circle cx="18" cy="12" r="3"/>
133
+ <line x1="4" y1="12" x2="11" y2="6"/>
134
+ <line x1="11" y1="6" x2="18" y2="12"/>
135
+ <line x1="11" y1="6" x2="14" y2="12"/>
136
+ <line x1="11" y1="6" x2="11" y2="3"/>
137
+ <line x1="11" y1="3" x2="14" y2="6"/>
138
+ </g>
139
+ <circle cx="11" cy="1.5" r="1.6" fill="var(--c-cobalt-900)"/>
140
+ </svg>
141
+ <svg className="ki ki-car-2" width="38" height="16" viewBox="0 0 38 16" aria-hidden="true">
142
+ <rect x="0" y="6" width="38" height="6" rx="2" fill="var(--c-cobalt-900)"/>
143
+ <path d="M 5,6 L 9,2 L 29,2 L 33,6 Z" fill="var(--c-cobalt-900)"/>
144
+ <rect x="11" y="3" width="6" height="3" fill="rgba(255,255,255,0.4)"/>
145
+ <rect x="20" y="3" width="6" height="3" fill="rgba(255,255,255,0.4)"/>
146
+ <circle cx="9" cy="13" r="2" fill="#C8482F"/>
147
+ <circle cx="29" cy="13" r="2" fill="#C8482F"/>
148
+ </svg>
149
+ </div>
150
+ </div>
151
+
152
+ <div className="water">
153
+ {/* Canal items: orange boats, swimmer, periscope, whale, hovercraft */}
154
+ <div className="canal-items">
155
+ <svg className="ci ci-cruise" width="120" height="28" viewBox="0 -10 120 28" aria-hidden="true">
156
+ <line x1="2" y1="14" x2="2" y2="-9" stroke="var(--c-orange-knvb)" strokeWidth="0.9"/>
157
+ <rect x="2.5" y="-9" width="9" height="2" fill="#AE1C28"/>
158
+ <rect x="2.5" y="-7" width="9" height="2" fill="#FFFFFF"/>
159
+ <rect x="2.5" y="-5" width="9" height="2" fill="#21468B"/>
160
+ <path d="M 0,16 L 6,18 L 114,18 L 120,16 L 120,11 L 0,11 Z" fill="var(--c-orange-knvb)"/>
161
+ <rect x="8" y="5" width="104" height="6" fill="var(--c-orange-knvb)"/>
162
+ <path d="M 8,5 Q 60,0 112,5 L 8,5 Z" fill="var(--c-orange-knvb)"/>
163
+ <g fill="rgba(255,247,210,0.85)">
164
+ <rect x="14" y="7" width="6" height="3"/><rect x="22" y="7" width="6" height="3"/>
165
+ <rect x="30" y="7" width="6" height="3"/><rect x="38" y="7" width="6" height="3"/>
166
+ <rect x="46" y="7" width="6" height="3"/><rect x="54" y="7" width="6" height="3"/>
167
+ <rect x="62" y="7" width="6" height="3"/><rect x="70" y="7" width="6" height="3"/>
168
+ <rect x="78" y="7" width="6" height="3"/><rect x="86" y="7" width="6" height="3"/>
169
+ <rect x="94" y="7" width="6" height="3"/><rect x="102" y="7" width="6" height="3"/>
170
+ </g>
171
+ </svg>
172
+ <svg className="ci ci-sloep" width="50" height="20" viewBox="0 -2 50 20" aria-hidden="true">
173
+ <path d="M 0,12 L 4,16 L 46,16 L 50,12 L 50,8 L 0,8 Z" fill="var(--c-orange-knvb)"/>
174
+ <rect x="20" y="2" width="12" height="6" rx="1" fill="var(--c-orange-knvb)"/>
175
+ <circle cx="26" cy="0" r="1.4" fill="var(--c-orange-knvb)"/>
176
+ </svg>
177
+ <svg className="ci ci-row" width="44" height="16" viewBox="-2 0 48 16" aria-hidden="true">
178
+ <path d="M 0,10 L 4,14 L 40,14 L 44,10 Z" fill="var(--c-orange-knvb)"/>
179
+ <line x1="8" y1="10" x2="0" y2="3" stroke="var(--c-orange-knvb)" strokeWidth="1.2" strokeLinecap="round"/>
180
+ <line x1="36" y1="10" x2="44" y2="3" stroke="var(--c-orange-knvb)" strokeWidth="1.2" strokeLinecap="round"/>
181
+ <circle cx="22" cy="7" r="1.6" fill="var(--c-orange-knvb)"/>
182
+ </svg>
183
+ <svg className="ci ci-swim" width="26" height="10" viewBox="-3 0 30 10" aria-hidden="true">
184
+ <ellipse cx="13" cy="6" rx="7" ry="1.4" fill="var(--c-orange-knvb)"/>
185
+ <circle cx="17" cy="4" r="1.7" fill="var(--c-orange-knvb)"/>
186
+ <line x1="13" y1="5" x2="11" y2="3" stroke="var(--c-orange-knvb)" strokeWidth="1" strokeLinecap="round"/>
187
+ <line x1="-3" y1="6" x2="2" y2="6" stroke="var(--c-orange-knvb)" strokeWidth="0.7" opacity="0.55"/>
188
+ <line x1="0" y1="8" x2="3" y2="8" stroke="var(--c-orange-knvb)" strokeWidth="0.7" opacity="0.4"/>
189
+ </svg>
190
+ <svg className="ci ci-periscope" width="14" height="26" viewBox="-3 -2 18 28" aria-hidden="true">
191
+ <rect x="4" y="4" width="2" height="18" fill="var(--c-orange-knvb)"/>
192
+ <rect x="0" y="0" width="9" height="3" fill="var(--c-orange-knvb)"/>
193
+ <rect x="4" y="3" width="2" height="2" fill="var(--c-orange-knvb)"/>
194
+ <ellipse cx="5" cy="24" rx="7" ry="0.9" fill="var(--c-orange-knvb)" opacity="0.5"/>
195
+ </svg>
196
+ <svg className="ci ci-whale" width="76" height="18" viewBox="-3 -4 82 22" aria-hidden="true">
197
+ <path d="M 0,12 Q 0,4 26,3 Q 54,2 64,7 L 72,4 L 68,9 L 72,14 L 64,11 Q 54,14 26,14 Q 6,14 0,12 Z" fill="var(--c-orange-knvb)"/>
198
+ <g opacity="0.55" stroke="var(--c-orange-knvb)" strokeWidth="1" strokeLinecap="round">
199
+ <line x1="22" y1="2" x2="20" y2="-3"/>
200
+ <line x1="25" y1="2" x2="25" y2="-4"/>
201
+ <line x1="28" y1="2" x2="30" y2="-3"/>
202
+ </g>
203
+ </svg>
204
+ <svg className="ci ci-hover" width="74" height="26" viewBox="0 -4 74 28" aria-hidden="true">
205
+ <ellipse cx="37" cy="22" rx="37" ry="2.5" fill="var(--c-orange-knvb)" opacity="0.4"/>
206
+ <path d="M 6,18 L 10,10 L 64,10 L 68,18 Z" fill="var(--c-orange-knvb)"/>
207
+ <path d="M 14,10 Q 37,-4 60,10 L 14,10 Z" fill="var(--c-orange-knvb)"/>
208
+ <ellipse cx="37" cy="4" rx="16" ry="3.2" fill="rgba(255,247,210,0.7)"/>
209
+ <polygon points="37,11 42,13.5 42,16.5 37,19 32,16.5 32,13.5" fill="#FFFFFF"/>
210
+ <text x="37" y="17.4" fontSize="4" textAnchor="middle" fill="var(--c-orange-knvb)" fontFamily="sans-serif" fontWeight="900">C</text>
211
+ <g stroke="var(--c-orange-knvb)" strokeWidth="0.7" opacity="0.6">
212
+ <line x1="8" y1="22" x2="12" y2="22"/>
213
+ <line x1="16" y1="22" x2="20" y2="22"/>
214
+ <line x1="26" y1="22" x2="30" y2="22"/>
215
+ <line x1="36" y1="22" x2="40" y2="22"/>
216
+ <line x1="46" y1="22" x2="50" y2="22"/>
217
+ <line x1="56" y1="22" x2="60" y2="22"/>
218
+ </g>
219
+ </svg>
220
+ </div>
221
+
222
+ {/* Mini-game HUD: timer + counter */}
223
+ <div className="game-hud" aria-live="polite" aria-label="Boat-sinking mini game">
224
+ <div className="hud-block hud-counter">
225
+ <span className="hud-num" data-counter="">100</span>
226
+ <span className="hud-label">Boats left</span>
227
+ </div>
228
+ <div className="hud-block hud-timer">
229
+ <span className="hud-num" data-timer="">60</span>
230
+ <span className="hud-label">Seconds</span>
231
+ </div>
232
+ </div>
233
+
234
+ <div className="game-over" role="dialog" aria-label="Mini game over">
235
+ <p className="go-title" data-go-title="">Time's up</p>
236
+ <p className="go-stat"><span data-go-sunk="">0</span> sunk</p>
237
+ <button type="button" data-restart="">Play again</button>
238
+ </div>
239
+
240
+ <svg className="canal-waves" viewBox="0 0 1400 500" preserveAspectRatio="none" aria-hidden="true">
241
+ <path className="w1" d="M 0,96 L 140,82 L 280,96 L 420,82 L 560,96 L 700,82 L 840,96 L 980,82 L 1120,96 L 1260,82 L 1400,96"/>
242
+ <path className="w2" d="M 0,206 L 180,182 L 360,206 L 540,182 L 720,206 L 900,182 L 1080,206 L 1260,182 L 1400,200"/>
243
+ <path className="w3" d="M 0,362 L 220,332 L 440,362 L 660,332 L 880,362 L 1100,332 L 1320,362 L 1400,348"/>
244
+ </svg>
245
+
246
+ <div className="footer-grid">
247
+ <div className="brand">
248
+ <div className="wm">{wordmark}</div>
249
+ <p>
250
+ Open-source apps for <span className="next-blue">Nextcloud</span>. Built and
251
+ maintained by Conduction in Amsterdam, released under EUPL-1.2.
252
+ </p>
253
+ <div className="triad">
254
+ <span>
255
+ <span className="h"></span>
256
+ Conduction{brand && <> · {brand.label}</>} · <span className="next-blue">Nextcloud</span>
257
+ </span>
258
+ </div>
259
+ <div className="socials">
260
+ <a href="https://github.com/ConductionNL" aria-label="GitHub" target="_blank" rel="noopener noreferrer">
261
+ <svg viewBox="0 0 24 24" aria-hidden="true">
262
+ <path className="filled" d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.78.6-3.37-1.34-3.37-1.34-.45-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.61.07-.61 1 .07 1.53 1.04 1.53 1.04.9 1.53 2.36 1.09 2.93.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02a9.6 9.6 0 0 1 5 0c1.91-1.29 2.75-1.02 2.75-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.84-2.34 4.69-4.57 4.93.36.31.68.92.68 1.86v2.76c0 .27.18.58.69.48A10 10 0 0 0 12 2z"/>
263
+ </svg>
264
+ </a>
265
+ <a href="https://www.linkedin.com/company/conduction" aria-label="LinkedIn" target="_blank" rel="noopener noreferrer">
266
+ <svg viewBox="0 0 24 24" aria-hidden="true">
267
+ <path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-4 0v7h-4v-7a6 6 0 0 1 6-6z"/>
268
+ <rect x="2" y="9" width="4" height="12"/>
269
+ <circle className="filled" cx="4" cy="4" r="2"/>
270
+ </svg>
271
+ </a>
272
+ <a href="mailto:info@conduction.nl" aria-label="Email info@conduction.nl">
273
+ <svg viewBox="0 0 24 24" aria-hidden="true">
274
+ <rect x="3" y="5" width="18" height="14" rx="2"/>
275
+ <path d="M3 7l9 6 9-6"/>
276
+ </svg>
277
+ </a>
278
+ <a href="tel:+31853036840" aria-label="Phone +31 (0)85 303 6840">
279
+ <svg viewBox="0 0 24 24" aria-hidden="true">
280
+ <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.72 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.35 1.85.59 2.81.72A2 2 0 0 1 22 16.92z"/>
281
+ </svg>
282
+ </a>
283
+ <a href="https://maps.google.com/?q=Lauriergracht+14h+Amsterdam" aria-label="Lauriergracht 14h, Amsterdam, open in Google Maps" target="_blank" rel="noopener noreferrer">
284
+ <svg viewBox="0 0 24 24" aria-hidden="true">
285
+ <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/>
286
+ <circle cx="12" cy="10" r="3"/>
287
+ </svg>
288
+ </a>
289
+ </div>
290
+ </div>
291
+
292
+ {links.map((column, i) => (
293
+ <div key={i}>
294
+ {column.title && <h4>{column.title}</h4>}
295
+ <ul>
296
+ {(column.items || []).map((item, j) => (
297
+ <li key={j}><FooterLink {...item} /></li>
298
+ ))}
299
+ </ul>
300
+ </div>
301
+ ))}
302
+ </div>
303
+
304
+ {copyright && (
305
+ <div className="legal-bar">
306
+ <div className="left">
307
+ <span>{copyright}</span>
308
+ <span className="legal-links">
309
+ <Link to="/privacy">Privacy</Link>
310
+ <span className="sep">·</span>
311
+ <Link to="/terms">Terms</Link>
312
+ <span className="sep">·</span>
313
+ <Link to="/iso">ISO</Link>
314
+ </span>
315
+ </div>
316
+ <div className="right">
317
+ <Link to="/iso" className="iso-badge" aria-label="ISO 9001:2015 certified, see details">
318
+ <span className="iso-mark">ISO</span>
319
+ <span className="iso-num">9001:2015</span>
320
+ </Link>
321
+ <Link to="/iso" className="iso-badge" aria-label="ISO 27001:2022 certified, see details">
322
+ <span className="iso-mark">ISO</span>
323
+ <span className="iso-num">27001:2022</span>
324
+ </Link>
325
+ </div>
326
+ </div>
327
+ )}
328
+ </div>
329
+ </footer>
330
+
331
+ {/* Hidden templates cloned by canal-footer.js to populate the
332
+ skyline (5 trapgevel variants) and to spawn boats during the
333
+ mini-game (sailing ship, cargo, frigate, battleship boss). */}
334
+ <FooterTemplates />
335
+
336
+ {/* Cross-game completion dialog. Listens for connext:gameend (HexRain,
337
+ canal mini-game) and reports the result with replay + cross-game
338
+ progress. Position: fixed via CSS module so it overlays the page. */}
339
+ <GameModal />
340
+ </>
341
+ );
342
+ }
343
+
344
+ /* The five trapgevel + four boat templates are large blocks of static
345
+ SVG markup; isolating them keeps the main JSX legible. They render
346
+ as <template> elements which canal-footer.js queries by id and clones
347
+ via .content. Because JSX puts children directly under the template
348
+ instead of in its .content DocumentFragment, we inject the templates
349
+ as raw HTML so the browser's HTML parser slots them correctly. */
350
+ function FooterTemplates() {
351
+ return (
352
+ <div
353
+ style={{display: 'none'}}
354
+ aria-hidden="true"
355
+ dangerouslySetInnerHTML={{__html: TEMPLATES_HTML}}
356
+ />
357
+ );
358
+ }
359
+
360
+ const TEMPLATES_HTML = `
361
+ <template id="tpl-h-a">
362
+ <svg class="house h-a" viewBox="0 -2 80 202" xmlns="http://www.w3.org/2000/svg">
363
+ <path d="M 0,200 L 0,38 L 8,38 L 8,26 L 16,26 L 16,14 L 24,14 L 24,8 L 56,8 L 56,14 L 64,14 L 64,26 L 72,26 L 72,38 L 80,38 L 80,200 Z" fill="var(--c-orange-knvb)"/>
364
+ <rect x="22" y="68" width="10" height="16" fill="rgba(255,247,210,0.95)"/>
365
+ <rect x="48" y="68" width="10" height="16" fill="rgba(11,32,73,0.35)"/>
366
+ <rect x="22" y="98" width="10" height="16" fill="rgba(11,32,73,0.35)"/>
367
+ <rect x="48" y="98" width="10" height="16" fill="rgba(255,247,210,0.6)"/>
368
+ <rect x="22" y="128" width="10" height="16" fill="rgba(11,32,73,0.35)"/>
369
+ <rect x="48" y="128" width="10" height="16" fill="rgba(11,32,73,0.35)"/>
370
+ <rect x="32" y="160" width="16" height="34" fill="rgba(11,32,73,0.55)"/>
371
+ </svg>
372
+ </template>
373
+ <template id="tpl-h-b">
374
+ <svg class="house h-b" viewBox="0 0 100 220" xmlns="http://www.w3.org/2000/svg">
375
+ <path d="M 0,220 L 0,58 L 8,58 L 8,47 L 16,47 L 16,36 L 24,36 L 24,25 L 32,25 L 32,14 L 50,4 L 68,14 L 68,25 L 76,25 L 76,36 L 84,36 L 84,47 L 92,47 L 92,58 L 100,58 L 100,220 Z" fill="var(--c-orange-knvb)"/>
376
+ <rect x="14" y="80" width="14" height="20" fill="rgba(255,247,210,0.85)"/>
377
+ <rect x="43" y="80" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
378
+ <rect x="72" y="80" width="14" height="20" fill="rgba(255,247,210,0.55)"/>
379
+ <rect x="14" y="115" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
380
+ <rect x="43" y="115" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
381
+ <rect x="72" y="115" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
382
+ <rect x="14" y="150" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
383
+ <rect x="43" y="150" width="14" height="20" fill="rgba(255,247,210,0.7)"/>
384
+ <rect x="72" y="150" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
385
+ <rect x="42" y="180" width="16" height="34" fill="rgba(11,32,73,0.55)"/>
386
+ </svg>
387
+ </template>
388
+ <template id="tpl-h-c">
389
+ <svg class="house h-c" viewBox="0 0 70 240" xmlns="http://www.w3.org/2000/svg">
390
+ <path d="M 0,240 L 0,48 L 5,48 L 5,41 L 10,41 L 10,34 L 15,34 L 15,27 L 20,27 L 20,20 L 25,20 L 25,15 L 45,15 L 45,20 L 50,20 L 50,27 L 55,27 L 55,34 L 60,34 L 60,41 L 65,41 L 65,48 L 70,48 L 70,240 Z" fill="var(--c-orange-knvb)"/>
391
+ <rect x="14" y="70" width="12" height="18" fill="rgba(255,247,210,0.55)"/>
392
+ <rect x="44" y="70" width="12" height="18" fill="rgba(255,247,210,0.85)"/>
393
+ <rect x="14" y="100" width="12" height="18" fill="rgba(11,32,73,0.35)"/>
394
+ <rect x="44" y="100" width="12" height="18" fill="rgba(11,32,73,0.35)"/>
395
+ <rect x="14" y="130" width="12" height="18" fill="rgba(255,247,210,0.7)"/>
396
+ <rect x="44" y="130" width="12" height="18" fill="rgba(11,32,73,0.35)"/>
397
+ <rect x="14" y="160" width="12" height="18" fill="rgba(11,32,73,0.35)"/>
398
+ <rect x="44" y="160" width="12" height="18" fill="rgba(11,32,73,0.35)"/>
399
+ <rect x="27" y="200" width="16" height="34" fill="rgba(11,32,73,0.55)"/>
400
+ </svg>
401
+ </template>
402
+ <template id="tpl-h-d">
403
+ <svg class="house h-d" viewBox="0 -10 90 180" xmlns="http://www.w3.org/2000/svg">
404
+ <path d="M 0,170 L 0,30 L 8,30 L 8,20 L 16,20 L 16,10 L 24,10 L 24,4 L 66,4 L 66,10 L 74,10 L 74,20 L 82,20 L 82,30 L 90,30 L 90,170 Z" fill="var(--c-orange-knvb)"/>
405
+ <rect x="12" y="60" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
406
+ <rect x="38" y="60" width="14" height="20" fill="rgba(255,247,210,0.85)"/>
407
+ <rect x="64" y="60" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
408
+ <rect x="12" y="100" width="14" height="20" fill="rgba(255,247,210,0.6)"/>
409
+ <rect x="38" y="100" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
410
+ <rect x="64" y="100" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
411
+ <rect x="37" y="130" width="16" height="34" fill="rgba(11,32,73,0.55)"/>
412
+ </svg>
413
+ </template>
414
+ <template id="tpl-h-e">
415
+ <svg class="house h-e" viewBox="0 0 95 210" xmlns="http://www.w3.org/2000/svg">
416
+ <path d="M 0,210 L 0,55 L 8,55 L 8,44 L 16,44 L 16,33 L 24,33 L 24,22 L 32,22 L 32,11 L 35,11 L 35,6 L 59,6 L 59,11 L 63,11 L 63,22 L 71,22 L 71,33 L 79,33 L 79,44 L 87,44 L 87,55 L 95,55 L 95,210 Z" fill="var(--c-orange-knvb)"/>
417
+ <rect x="13" y="75" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
418
+ <rect x="40" y="75" width="14" height="20" fill="rgba(255,247,210,0.65)"/>
419
+ <rect x="68" y="75" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
420
+ <rect x="13" y="110" width="14" height="20" fill="rgba(255,247,210,0.8)"/>
421
+ <rect x="40" y="110" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
422
+ <rect x="68" y="110" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
423
+ <rect x="13" y="145" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
424
+ <rect x="40" y="145" width="14" height="20" fill="rgba(11,32,73,0.35)"/>
425
+ <rect x="68" y="145" width="14" height="20" fill="rgba(255,247,210,0.55)"/>
426
+ <rect x="39.5" y="175" width="16" height="34" fill="rgba(11,32,73,0.55)"/>
427
+ </svg>
428
+ </template>
429
+
430
+ <template id="tpl-ship-sailing">
431
+ <svg class="ci ci-sailing" width="100" height="60" viewBox="-4 -42 108 60" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
432
+ <path d="M 0,12 L 6,16 L 90,16 L 96,12 L 96,8 L 0,8 Z" fill="var(--c-orange-knvb)"/>
433
+ <line x1="0" y1="11" x2="-4" y2="6" stroke="var(--c-orange-knvb)" stroke-width="1.6" stroke-linecap="round"/>
434
+ <line x1="48" y1="8" x2="48" y2="-40" stroke="#3a4553" stroke-width="1.4"/>
435
+ <rect x="44.5" y="-30" width="7" height="2.5" fill="#3a4553"/>
436
+ <line x1="22" y1="-12" x2="74" y2="-12" stroke="#3a4553" stroke-width="0.9"/>
437
+ <path d="M 24,-12 Q 48,-7 72,-12 L 72,4 Q 48,8 24,4 Z" fill="rgba(255,247,210,0.92)"/>
438
+ <line x1="24" y1="-26" x2="72" y2="-26" stroke="#3a4553" stroke-width="0.9"/>
439
+ <path d="M 26,-26 Q 48,-22 70,-26 L 70,-13 Q 48,-9 26,-13 Z" fill="rgba(255,247,210,0.92)"/>
440
+ <line x1="34" y1="-38" x2="62" y2="-38" stroke="#3a4553" stroke-width="0.9"/>
441
+ <path d="M 35,-38 Q 48,-35 61,-38 L 61,-28 Q 48,-25 35,-28 Z" fill="rgba(255,247,210,0.92)"/>
442
+ <path d="M 48,-40 L 58,-39 L 56,-37 L 58,-35 L 48,-36 Z" fill="#AE1C28"/>
443
+ </svg>
444
+ </template>
445
+ <template id="tpl-ship-cargo">
446
+ <svg class="ci ci-cargo" width="180" height="44" viewBox="0 -28 180 44" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
447
+ <path d="M 0,14 L 6,16 L 174,16 L 180,14 L 180,10 L 0,10 Z" fill="var(--c-orange-knvb)"/>
448
+ <g>
449
+ <rect x="14" y="0" width="14" height="9" fill="#C8482F"/>
450
+ <rect x="30" y="0" width="14" height="9" fill="var(--c-cobalt-900)"/>
451
+ <rect x="46" y="0" width="14" height="9" fill="rgba(255,247,210,0.9)"/>
452
+ <rect x="62" y="0" width="14" height="9" fill="#C8482F"/>
453
+ <rect x="78" y="0" width="14" height="9" fill="var(--c-cobalt-900)"/>
454
+ <rect x="94" y="0" width="14" height="9" fill="rgba(255,247,210,0.9)"/>
455
+ <rect x="110" y="0" width="14" height="9" fill="#C8482F"/>
456
+ <rect x="14" y="-9" width="14" height="9" fill="var(--c-cobalt-900)"/>
457
+ <rect x="30" y="-9" width="14" height="9" fill="rgba(255,247,210,0.9)"/>
458
+ <rect x="62" y="-9" width="14" height="9" fill="var(--c-cobalt-900)"/>
459
+ <rect x="94" y="-9" width="14" height="9" fill="#C8482F"/>
460
+ <rect x="14" y="-18" width="14" height="9" fill="rgba(255,247,210,0.9)"/>
461
+ <rect x="62" y="-18" width="14" height="9" fill="#C8482F"/>
462
+ </g>
463
+ <rect x="138" y="-18" width="22" height="27" fill="#5a6573"/>
464
+ <rect x="142" y="-14" width="14" height="3" fill="rgba(255,247,210,0.85)"/>
465
+ <rect x="142" y="-9" width="14" height="3" fill="rgba(255,247,210,0.6)"/>
466
+ <rect x="142" y="-4" width="14" height="3" fill="rgba(255,247,210,0.6)"/>
467
+ <rect x="146" y="-26" width="8" height="8" fill="#3a4553"/>
468
+ <rect x="146" y="-22" width="8" height="2" fill="var(--c-orange-knvb)"/>
469
+ </svg>
470
+ </template>
471
+ <template id="tpl-ship-frigate">
472
+ <svg class="ci ci-frigate" width="130" height="36" viewBox="0 -20 130 36" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
473
+ <path d="M 0,14 L 6,16 L 124,16 L 130,14 L 130,10 L 0,10 Z" fill="#5a6573"/>
474
+ <rect x="0" y="9" width="130" height="1.4" fill="var(--c-orange-knvb)"/>
475
+ <rect x="14" y="6" width="14" height="4" rx="1.5" fill="#6a7583"/>
476
+ <line x1="21" y1="8" x2="40" y2="6" stroke="#3a4553" stroke-width="1.6" stroke-linecap="round"/>
477
+ <rect x="42" y="-2" width="48" height="12" fill="#6a7583"/>
478
+ <rect x="58" y="-12" width="16" height="10" fill="#7a8593"/>
479
+ <rect x="60" y="-9" width="12" height="2.5" fill="rgba(255,247,210,0.85)"/>
480
+ <line x1="66" y1="-12" x2="66" y2="-18" stroke="#3a4553" stroke-width="1"/>
481
+ <rect x="82" y="-7" width="6" height="5" fill="#3a4553"/>
482
+ <rect x="82" y="-5" width="6" height="1.5" fill="var(--c-orange-knvb)"/>
483
+ <rect x="100" y="6" width="14" height="4" rx="1.5" fill="#6a7583"/>
484
+ </svg>
485
+ </template>
486
+ <template id="tpl-battleship">
487
+ <svg class="ci ci-battleship boss" width="220" height="56" viewBox="0 -22 220 56" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
488
+ <path d="M 0,18 L 8,28 L 212,28 L 220,18 L 220,12 L 0,12 Z" fill="#4a5663"/>
489
+ <rect x="0" y="11" width="220" height="2" fill="var(--c-orange-knvb)"/>
490
+ <rect x="50" y="0" width="120" height="12" fill="#5a6573"/>
491
+ <rect x="92" y="-12" width="36" height="12" fill="#6a7583"/>
492
+ <rect x="96" y="-9" width="28" height="3" fill="rgba(255,247,210,0.85)"/>
493
+ <rect x="138" y="-7" width="10" height="7" fill="#3a4553"/>
494
+ <rect x="138" y="-4" width="10" height="2" fill="var(--c-orange-knvb)"/>
495
+ <line x1="110" y1="-12" x2="110" y2="-20" stroke="#3a4553" stroke-width="1.4"/>
496
+ <rect x="22" y="6" width="22" height="6" rx="2" fill="#6a7583"/>
497
+ <line x1="32" y1="9" x2="56" y2="6" stroke="#3a4553" stroke-width="2.2" stroke-linecap="round"/>
498
+ <line x1="32" y1="9" x2="8" y2="6" stroke="#3a4553" stroke-width="2.2" stroke-linecap="round"/>
499
+ <rect x="176" y="6" width="22" height="6" rx="2" fill="#6a7583"/>
500
+ <line x1="186" y1="9" x2="210" y2="6" stroke="#3a4553" stroke-width="2.2" stroke-linecap="round"/>
501
+ <line x1="186" y1="9" x2="162" y2="6" stroke="#3a4553" stroke-width="2.2" stroke-linecap="round"/>
502
+ <g class="hp-pips" transform="translate(58, -18)">
503
+ <circle class="pip" cx="0" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
504
+ <circle class="pip" cx="11" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
505
+ <circle class="pip" cx="22" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
506
+ <circle class="pip" cx="33" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
507
+ <circle class="pip" cx="44" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
508
+ <circle class="pip" cx="55" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
509
+ <circle class="pip" cx="66" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
510
+ <circle class="pip" cx="77" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
511
+ <circle class="pip" cx="88" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
512
+ <circle class="pip" cx="99" cy="0" r="2.4" fill="var(--c-orange-knvb)"/>
513
+ </g>
514
+ </svg>
515
+ </template>
516
+ `;