@brandlab-digital/site-next 3.13.0 → 3.15.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 (274) hide show
  1. package/README.md +79 -0
  2. package/dist/analytics.d.ts +1 -1
  3. package/dist/analytics.d.ts.map +1 -1
  4. package/dist/analytics.js +2 -0
  5. package/dist/analytics.js.map +1 -1
  6. package/dist/contact/delivery.d.ts +81 -0
  7. package/dist/contact/delivery.d.ts.map +1 -0
  8. package/dist/contact/delivery.js +138 -0
  9. package/dist/contact/delivery.js.map +1 -0
  10. package/dist/contact/resend-webhook.d.ts +72 -0
  11. package/dist/contact/resend-webhook.d.ts.map +1 -0
  12. package/dist/contact/resend-webhook.js +300 -0
  13. package/dist/contact/resend-webhook.js.map +1 -0
  14. package/dist/contact/route-handler.d.ts +16 -0
  15. package/dist/contact/route-handler.d.ts.map +1 -1
  16. package/dist/contact/route-handler.js +8 -0
  17. package/dist/contact/route-handler.js.map +1 -1
  18. package/dist/contact/server-entry.d.ts +2 -0
  19. package/dist/contact/server-entry.d.ts.map +1 -1
  20. package/dist/contact/server-entry.js +2 -0
  21. package/dist/contact/server-entry.js.map +1 -1
  22. package/dist/contact/server.d.ts +26 -0
  23. package/dist/contact/server.d.ts.map +1 -1
  24. package/dist/contact/server.js +48 -3
  25. package/dist/contact/server.js.map +1 -1
  26. package/dist/navigation/constants.d.ts +11 -2
  27. package/dist/navigation/constants.d.ts.map +1 -1
  28. package/dist/navigation/constants.js +11 -2
  29. package/dist/navigation/constants.js.map +1 -1
  30. package/dist/navigation/index.d.ts +1 -1
  31. package/dist/navigation/index.d.ts.map +1 -1
  32. package/dist/navigation/index.js +1 -1
  33. package/dist/navigation/index.js.map +1 -1
  34. package/dist/navigation/use-back-to-top.d.ts.map +1 -1
  35. package/dist/navigation/use-back-to-top.js +12 -4
  36. package/dist/navigation/use-back-to-top.js.map +1 -1
  37. package/dist/navigation/use-header-metrics.d.ts +1 -1
  38. package/dist/navigation/use-header-metrics.js +1 -1
  39. package/dist/navigation/use-header-metrics.js.map +1 -1
  40. package/dist/navigation/use-sticky-call-bar.d.ts +2 -1
  41. package/dist/navigation/use-sticky-call-bar.d.ts.map +1 -1
  42. package/dist/navigation/use-sticky-call-bar.js +11 -2
  43. package/dist/navigation/use-sticky-call-bar.js.map +1 -1
  44. package/dist/next-config.d.ts +17 -1
  45. package/dist/next-config.d.ts.map +1 -1
  46. package/dist/next-config.js +36 -2
  47. package/dist/next-config.js.map +1 -1
  48. package/dist/ui-kit/brandlab-skin.d.ts +50 -1
  49. package/dist/ui-kit/brandlab-skin.d.ts.map +1 -1
  50. package/dist/ui-kit/brandlab-skin.js.map +1 -1
  51. package/dist/ui-kit/form/photo-upload.d.ts +4 -1
  52. package/dist/ui-kit/form/photo-upload.d.ts.map +1 -1
  53. package/dist/ui-kit/form/photo-upload.js +4 -4
  54. package/dist/ui-kit/form/photo-upload.js.map +1 -1
  55. package/dist/ui-kit/form/quote-form.d.ts +4 -1
  56. package/dist/ui-kit/form/quote-form.d.ts.map +1 -1
  57. package/dist/ui-kit/form/quote-form.js.map +1 -1
  58. package/dist/ui-kit/form/thank-you.d.ts +4 -1
  59. package/dist/ui-kit/form/thank-you.d.ts.map +1 -1
  60. package/dist/ui-kit/form/thank-you.js +2 -2
  61. package/dist/ui-kit/form/thank-you.js.map +1 -1
  62. package/dist/ui-kit/icon-glyphs.d.ts +41 -0
  63. package/dist/ui-kit/icon-glyphs.d.ts.map +1 -0
  64. package/dist/ui-kit/icon-glyphs.js +138 -0
  65. package/dist/ui-kit/icon-glyphs.js.map +1 -0
  66. package/dist/ui-kit/icon-sprite.d.ts +19 -0
  67. package/dist/ui-kit/icon-sprite.d.ts.map +1 -0
  68. package/dist/ui-kit/icon-sprite.js +44 -0
  69. package/dist/ui-kit/icon-sprite.js.map +1 -0
  70. package/dist/ui-kit/icons.d.ts +38 -3
  71. package/dist/ui-kit/icons.d.ts.map +1 -1
  72. package/dist/ui-kit/icons.js +47 -64
  73. package/dist/ui-kit/icons.js.map +1 -1
  74. package/dist/ui-kit/prefetch.d.ts +19 -10
  75. package/dist/ui-kit/prefetch.d.ts.map +1 -1
  76. package/dist/ui-kit/prefetch.js +23 -10
  77. package/dist/ui-kit/prefetch.js.map +1 -1
  78. package/dist/ui-kit/primitives/badge.d.ts +25 -0
  79. package/dist/ui-kit/primitives/badge.d.ts.map +1 -0
  80. package/dist/ui-kit/primitives/badge.js +21 -0
  81. package/dist/ui-kit/primitives/badge.js.map +1 -0
  82. package/dist/ui-kit/primitives/breadcrumbs.d.ts +27 -0
  83. package/dist/ui-kit/primitives/breadcrumbs.d.ts.map +1 -0
  84. package/dist/ui-kit/primitives/breadcrumbs.js +40 -0
  85. package/dist/ui-kit/primitives/breadcrumbs.js.map +1 -0
  86. package/dist/ui-kit/primitives/button.d.ts +32 -0
  87. package/dist/ui-kit/primitives/button.d.ts.map +1 -0
  88. package/dist/ui-kit/primitives/button.js +8 -0
  89. package/dist/ui-kit/primitives/button.js.map +1 -0
  90. package/dist/ui-kit/primitives/card.d.ts +40 -0
  91. package/dist/ui-kit/primitives/card.d.ts.map +1 -0
  92. package/dist/ui-kit/primitives/card.js +8 -0
  93. package/dist/ui-kit/primitives/card.js.map +1 -0
  94. package/dist/ui-kit/primitives/index.d.ts +11 -2
  95. package/dist/ui-kit/primitives/index.d.ts.map +1 -1
  96. package/dist/ui-kit/primitives/index.js +11 -2
  97. package/dist/ui-kit/primitives/index.js.map +1 -1
  98. package/dist/ui-kit/primitives/layout.d.ts +12 -0
  99. package/dist/ui-kit/primitives/layout.d.ts.map +1 -1
  100. package/dist/ui-kit/primitives/layout.js +20 -2
  101. package/dist/ui-kit/primitives/layout.js.map +1 -1
  102. package/dist/ui-kit/primitives/links.d.ts +15 -0
  103. package/dist/ui-kit/primitives/links.d.ts.map +1 -1
  104. package/dist/ui-kit/primitives/links.js +6 -2
  105. package/dist/ui-kit/primitives/links.js.map +1 -1
  106. package/dist/ui-kit/primitives/lists.d.ts +51 -0
  107. package/dist/ui-kit/primitives/lists.d.ts.map +1 -0
  108. package/dist/ui-kit/primitives/lists.js +34 -0
  109. package/dist/ui-kit/primitives/lists.js.map +1 -0
  110. package/dist/ui-kit/primitives/media-frame.d.ts +28 -0
  111. package/dist/ui-kit/primitives/media-frame.d.ts.map +1 -0
  112. package/dist/ui-kit/primitives/media-frame.js +58 -0
  113. package/dist/ui-kit/primitives/media-frame.js.map +1 -0
  114. package/dist/ui-kit/primitives/media.d.ts +38 -0
  115. package/dist/ui-kit/primitives/media.d.ts.map +1 -0
  116. package/dist/ui-kit/primitives/media.js +9 -0
  117. package/dist/ui-kit/primitives/media.js.map +1 -0
  118. package/dist/ui-kit/primitives/quote-button.d.ts +25 -2
  119. package/dist/ui-kit/primitives/quote-button.d.ts.map +1 -1
  120. package/dist/ui-kit/primitives/quote-button.js +25 -3
  121. package/dist/ui-kit/primitives/quote-button.js.map +1 -1
  122. package/dist/ui-kit/primitives/stat.d.ts +25 -0
  123. package/dist/ui-kit/primitives/stat.d.ts.map +1 -0
  124. package/dist/ui-kit/primitives/stat.js +7 -0
  125. package/dist/ui-kit/primitives/stat.js.map +1 -0
  126. package/dist/ui-kit/repeated-slots.d.ts +153 -0
  127. package/dist/ui-kit/repeated-slots.d.ts.map +1 -0
  128. package/dist/ui-kit/repeated-slots.js +97 -0
  129. package/dist/ui-kit/repeated-slots.js.map +1 -0
  130. package/dist/ui-kit/sections/accordion.d.ts +4 -1
  131. package/dist/ui-kit/sections/accordion.d.ts.map +1 -1
  132. package/dist/ui-kit/sections/accordion.js +2 -2
  133. package/dist/ui-kit/sections/accordion.js.map +1 -1
  134. package/dist/ui-kit/sections/area-map.d.ts +64 -0
  135. package/dist/ui-kit/sections/area-map.d.ts.map +1 -0
  136. package/dist/ui-kit/sections/area-map.js +142 -0
  137. package/dist/ui-kit/sections/area-map.js.map +1 -0
  138. package/dist/ui-kit/sections/before-after.d.ts +59 -0
  139. package/dist/ui-kit/sections/before-after.d.ts.map +1 -0
  140. package/dist/ui-kit/sections/before-after.js +42 -0
  141. package/dist/ui-kit/sections/before-after.js.map +1 -0
  142. package/dist/ui-kit/sections/contact-block.d.ts +4 -1
  143. package/dist/ui-kit/sections/contact-block.d.ts.map +1 -1
  144. package/dist/ui-kit/sections/contact-block.js +3 -3
  145. package/dist/ui-kit/sections/contact-block.js.map +1 -1
  146. package/dist/ui-kit/sections/council-rules.d.ts +64 -0
  147. package/dist/ui-kit/sections/council-rules.d.ts.map +1 -0
  148. package/dist/ui-kit/sections/council-rules.js +46 -0
  149. package/dist/ui-kit/sections/council-rules.js.map +1 -0
  150. package/dist/ui-kit/sections/coverage.d.ts +53 -0
  151. package/dist/ui-kit/sections/coverage.d.ts.map +1 -0
  152. package/dist/ui-kit/sections/coverage.js +57 -0
  153. package/dist/ui-kit/sections/coverage.js.map +1 -0
  154. package/dist/ui-kit/sections/emergency-band.d.ts +60 -0
  155. package/dist/ui-kit/sections/emergency-band.d.ts.map +1 -0
  156. package/dist/ui-kit/sections/emergency-band.js +43 -0
  157. package/dist/ui-kit/sections/emergency-band.js.map +1 -0
  158. package/dist/ui-kit/sections/faqs.d.ts +4 -1
  159. package/dist/ui-kit/sections/faqs.d.ts.map +1 -1
  160. package/dist/ui-kit/sections/faqs.js +4 -5
  161. package/dist/ui-kit/sections/faqs.js.map +1 -1
  162. package/dist/ui-kit/sections/gallery.d.ts +60 -0
  163. package/dist/ui-kit/sections/gallery.d.ts.map +1 -0
  164. package/dist/ui-kit/sections/gallery.js +39 -0
  165. package/dist/ui-kit/sections/gallery.js.map +1 -0
  166. package/dist/ui-kit/sections/hero.d.ts +118 -0
  167. package/dist/ui-kit/sections/hero.d.ts.map +1 -0
  168. package/dist/ui-kit/sections/hero.js +58 -0
  169. package/dist/ui-kit/sections/hero.js.map +1 -0
  170. package/dist/ui-kit/sections/index.d.ts +16 -1
  171. package/dist/ui-kit/sections/index.d.ts.map +1 -1
  172. package/dist/ui-kit/sections/index.js +16 -1
  173. package/dist/ui-kit/sections/index.js.map +1 -1
  174. package/dist/ui-kit/sections/licences.d.ts +72 -0
  175. package/dist/ui-kit/sections/licences.d.ts.map +1 -0
  176. package/dist/ui-kit/sections/licences.js +46 -0
  177. package/dist/ui-kit/sections/licences.js.map +1 -0
  178. package/dist/ui-kit/sections/local-facts.d.ts +78 -0
  179. package/dist/ui-kit/sections/local-facts.d.ts.map +1 -0
  180. package/dist/ui-kit/sections/local-facts.js +32 -0
  181. package/dist/ui-kit/sections/local-facts.js.map +1 -0
  182. package/dist/ui-kit/sections/nearby-areas.d.ts +50 -0
  183. package/dist/ui-kit/sections/nearby-areas.d.ts.map +1 -0
  184. package/dist/ui-kit/sections/nearby-areas.js +49 -0
  185. package/dist/ui-kit/sections/nearby-areas.js.map +1 -0
  186. package/dist/ui-kit/sections/nearby-jobs.d.ts +66 -0
  187. package/dist/ui-kit/sections/nearby-jobs.d.ts.map +1 -0
  188. package/dist/ui-kit/sections/nearby-jobs.js +49 -0
  189. package/dist/ui-kit/sections/nearby-jobs.js.map +1 -0
  190. package/dist/ui-kit/sections/price-guide.d.ts +4 -1
  191. package/dist/ui-kit/sections/price-guide.d.ts.map +1 -1
  192. package/dist/ui-kit/sections/price-guide.js +3 -3
  193. package/dist/ui-kit/sections/price-guide.js.map +1 -1
  194. package/dist/ui-kit/sections/price-table.d.ts +7 -9
  195. package/dist/ui-kit/sections/price-table.d.ts.map +1 -1
  196. package/dist/ui-kit/sections/price-table.js +8 -8
  197. package/dist/ui-kit/sections/price-table.js.map +1 -1
  198. package/dist/ui-kit/sections/projects.d.ts +79 -0
  199. package/dist/ui-kit/sections/projects.d.ts.map +1 -0
  200. package/dist/ui-kit/sections/projects.js +69 -0
  201. package/dist/ui-kit/sections/projects.js.map +1 -0
  202. package/dist/ui-kit/sections/proof-strip.d.ts +4 -1
  203. package/dist/ui-kit/sections/proof-strip.d.ts.map +1 -1
  204. package/dist/ui-kit/sections/proof-strip.js +2 -2
  205. package/dist/ui-kit/sections/proof-strip.js.map +1 -1
  206. package/dist/ui-kit/sections/quote-checklist.d.ts +43 -0
  207. package/dist/ui-kit/sections/quote-checklist.d.ts.map +1 -0
  208. package/dist/ui-kit/sections/quote-checklist.js +19 -0
  209. package/dist/ui-kit/sections/quote-checklist.js.map +1 -0
  210. package/dist/ui-kit/sections/related-services.d.ts +41 -0
  211. package/dist/ui-kit/sections/related-services.d.ts.map +1 -0
  212. package/dist/ui-kit/sections/related-services.js +52 -0
  213. package/dist/ui-kit/sections/related-services.js.map +1 -0
  214. package/dist/ui-kit/sections/reviews-band.d.ts +16 -2
  215. package/dist/ui-kit/sections/reviews-band.d.ts.map +1 -1
  216. package/dist/ui-kit/sections/reviews-band.js +13 -2
  217. package/dist/ui-kit/sections/reviews-band.js.map +1 -1
  218. package/dist/ui-kit/sections/services-grid.d.ts +82 -0
  219. package/dist/ui-kit/sections/services-grid.d.ts.map +1 -0
  220. package/dist/ui-kit/sections/services-grid.js +90 -0
  221. package/dist/ui-kit/sections/services-grid.js.map +1 -0
  222. package/dist/ui-kit/sections/site-footer.d.ts +4 -1
  223. package/dist/ui-kit/sections/site-footer.d.ts.map +1 -1
  224. package/dist/ui-kit/sections/site-footer.js +6 -6
  225. package/dist/ui-kit/sections/site-footer.js.map +1 -1
  226. package/dist/ui-kit/sections/work-photos.d.ts +15 -0
  227. package/dist/ui-kit/sections/work-photos.d.ts.map +1 -0
  228. package/dist/ui-kit/sections/work-photos.js +24 -0
  229. package/dist/ui-kit/sections/work-photos.js.map +1 -0
  230. package/dist/ui-kit/shell/back-to-top.js +1 -1
  231. package/dist/ui-kit/shell/back-to-top.js.map +1 -1
  232. package/dist/ui-kit/shell/current-link.d.ts +21 -5
  233. package/dist/ui-kit/shell/current-link.d.ts.map +1 -1
  234. package/dist/ui-kit/shell/current-link.js +16 -5
  235. package/dist/ui-kit/shell/current-link.js.map +1 -1
  236. package/dist/ui-kit/shell/drawer-client.js +1 -1
  237. package/dist/ui-kit/shell/drawer-client.js.map +1 -1
  238. package/dist/ui-kit/shell/intent-prefetch.d.ts.map +1 -1
  239. package/dist/ui-kit/shell/intent-prefetch.js +3 -2
  240. package/dist/ui-kit/shell/intent-prefetch.js.map +1 -1
  241. package/dist/ui-kit/shell/mobile-call-bar.d.ts +6 -1
  242. package/dist/ui-kit/shell/mobile-call-bar.d.ts.map +1 -1
  243. package/dist/ui-kit/shell/mobile-call-bar.js +6 -3
  244. package/dist/ui-kit/shell/mobile-call-bar.js.map +1 -1
  245. package/dist/ui-kit/shell/mobile-drawer.d.ts +7 -3
  246. package/dist/ui-kit/shell/mobile-drawer.d.ts.map +1 -1
  247. package/dist/ui-kit/shell/mobile-drawer.js +21 -5
  248. package/dist/ui-kit/shell/mobile-drawer.js.map +1 -1
  249. package/dist/ui-kit/shell/shell-quote.d.ts +10 -0
  250. package/dist/ui-kit/shell/shell-quote.d.ts.map +1 -0
  251. package/dist/ui-kit/shell/shell-quote.js +13 -0
  252. package/dist/ui-kit/shell/shell-quote.js.map +1 -0
  253. package/dist/ui-kit/shell/site-header.d.ts +5 -2
  254. package/dist/ui-kit/shell/site-header.d.ts.map +1 -1
  255. package/dist/ui-kit/shell/site-header.js +9 -9
  256. package/dist/ui-kit/shell/site-header.js.map +1 -1
  257. package/dist/ui-kit/shell/social-links.d.ts +1 -2
  258. package/dist/ui-kit/shell/social-links.d.ts.map +1 -1
  259. package/dist/ui-kit/shell/social-links.js +6 -3
  260. package/dist/ui-kit/shell/social-links.js.map +1 -1
  261. package/dist/ui-kit/shell/utility-bar.d.ts +4 -1
  262. package/dist/ui-kit/shell/utility-bar.d.ts.map +1 -1
  263. package/dist/ui-kit/shell/utility-bar.js +2 -2
  264. package/dist/ui-kit/shell/utility-bar.js.map +1 -1
  265. package/dist/ui-kit/skin-index.d.ts +2 -1
  266. package/dist/ui-kit/skin-index.d.ts.map +1 -1
  267. package/dist/ui-kit/skin-index.js +2 -1
  268. package/dist/ui-kit/skin-index.js.map +1 -1
  269. package/dist/ui-kit/skin.d.ts +21 -4
  270. package/dist/ui-kit/skin.d.ts.map +1 -1
  271. package/dist/ui-kit/skin.js +14 -1
  272. package/dist/ui-kit/skin.js.map +1 -1
  273. package/dist/ui-kit/structure.css +793 -10
  274. package/package.json +6 -2
@@ -97,11 +97,10 @@
97
97
 
98
98
  [data-bl='stars'] {
99
99
  display: inline-flex;
100
- gap: 0.125rem;
101
100
  color: var(--bl-color-star, #f5b301);
102
101
  }
103
- [data-bl='stars'] [data-slot='star'] svg {
104
- width: 1em;
102
+ [data-bl='stars'] > svg {
103
+ width: 5.4em;
105
104
  height: 1em;
106
105
  }
107
106
  [data-bl='stars'] [data-slot='star'][data-state='off'] {
@@ -120,6 +119,198 @@
120
119
  }
121
120
  }
122
121
 
122
+ /* 05-media.css */
123
+ /* MediaFrame and Media (F13), the library's one image path: the frame holds the image at its own shape, or cropped to
124
+ an allowed ratio around the focal point (inline object-position); a caption flows under it. An AI image's
125
+ "Illustration" label (inside the figcaption) sits over the image's top corner; the site colours it. */
126
+
127
+ [data-bl='media'] {
128
+ position: relative;
129
+ margin: 0;
130
+ }
131
+ [data-bl='media'] > img {
132
+ display: block;
133
+ max-width: 100%;
134
+ height: auto;
135
+ }
136
+ [data-bl='media'][data-fit='fluid'] > img {
137
+ width: 100%;
138
+ }
139
+ [data-bl='media'][data-ratio] > img {
140
+ width: 100%;
141
+ height: 100%;
142
+ object-fit: cover;
143
+ }
144
+ [data-bl='media'][data-ratio='16:9'] > img {
145
+ aspect-ratio: 16 / 9;
146
+ }
147
+ [data-bl='media'][data-ratio='4:5'] > img {
148
+ aspect-ratio: 4 / 5;
149
+ }
150
+ [data-bl='media'][data-ratio='4:3'] > img {
151
+ aspect-ratio: 4 / 3;
152
+ }
153
+ [data-bl='media'][data-ratio='3:2'] > img {
154
+ aspect-ratio: 3 / 2;
155
+ }
156
+ [data-bl='media'] [data-slot='label'] {
157
+ position: absolute;
158
+ inset-block-start: 0.5rem;
159
+ inset-inline-start: 0.5rem;
160
+ padding: 0.125rem 0.5rem;
161
+ background: var(--bl-color-surface, Canvas);
162
+ color: var(--bl-color-ink, CanvasText);
163
+ font-size: 0.8125rem;
164
+ line-height: 1.4;
165
+ }
166
+ /* Behind the page header's text, the figure fills its media slot. */
167
+ :where([data-bl-section] [data-slot='media']) > [data-bl='media'][data-ratio] {
168
+ height: 100%;
169
+ }
170
+
171
+ /* 05-primitives.css */
172
+ /* Primitives (3.14.0): Button, Eyebrow, TickList, LinkList, Card, Badge and Chip, Stat, MediaFrame. Layout only. */
173
+
174
+ button[data-bl='button'] {
175
+ font: inherit;
176
+ cursor: pointer;
177
+ }
178
+ button[data-bl='button']:disabled {
179
+ cursor: not-allowed;
180
+ }
181
+
182
+ [data-bl='eyebrow'] {
183
+ margin: 0;
184
+ }
185
+
186
+ /* TickList: one column, or two from the first width up (the hero checklist). */
187
+ [data-bl='tick-list'] {
188
+ margin: 0;
189
+ padding: 0;
190
+ list-style: none;
191
+ display: grid;
192
+ gap: 0.5rem 1.5rem;
193
+ }
194
+ [data-bl='tick-list'][data-columns='2'] {
195
+ grid-template-columns: repeat(2, minmax(0, 1fr));
196
+ }
197
+ [data-bl='tick-list'] [data-slot='item'] {
198
+ display: flex;
199
+ align-items: flex-start;
200
+ gap: 0.5rem;
201
+ }
202
+ [data-bl='tick-list'] [data-slot='tick'] {
203
+ color: var(--bl-color-action, currentColor);
204
+ }
205
+ [data-bl='tick-list'] [data-slot='tick'] svg {
206
+ width: 1.25em;
207
+ height: 1.25em;
208
+ }
209
+ /* tick: 'rule': no svg, a short rule on the first line's centre (AA's ruled lists). */
210
+ [data-bl='tick-list'][data-tick='rule'] [data-slot='tick'] {
211
+ flex: none;
212
+ width: 0.875em;
213
+ height: 2px;
214
+ margin-top: 0.7em;
215
+ background: currentColor;
216
+ }
217
+
218
+ /* LinkList: plain entries, one column on phones, two from 40rem, the chosen count from 64rem. */
219
+ [data-bl='link-list'] {
220
+ margin: 0;
221
+ padding: 0;
222
+ list-style: none;
223
+ display: grid;
224
+ column-gap: 2.5rem;
225
+ }
226
+ [data-bl='link-list'] > li > a {
227
+ display: flex;
228
+ align-items: center;
229
+ min-height: 44px;
230
+ }
231
+ @media (min-width: 40rem) {
232
+ [data-bl='link-list']:not([data-columns='1']) {
233
+ grid-template-columns: repeat(2, minmax(0, 1fr));
234
+ }
235
+ }
236
+ @media (min-width: 64rem) {
237
+ [data-bl='link-list'][data-columns='3'] {
238
+ grid-template-columns: repeat(3, minmax(0, 1fr));
239
+ }
240
+ [data-bl='link-list'][data-columns='4'] {
241
+ grid-template-columns: repeat(4, minmax(0, 1fr));
242
+ }
243
+ }
244
+
245
+ /* Card: media then body; a linked card is one hit area through its title link. */
246
+ [data-bl='card'] {
247
+ position: relative;
248
+ display: flex;
249
+ flex-direction: column;
250
+ }
251
+ [data-bl='card'] [data-slot='title'] {
252
+ margin: 0;
253
+ }
254
+ [data-bl='card'] [data-slot='link']::after {
255
+ content: '';
256
+ position: absolute;
257
+ inset: 0;
258
+ }
259
+ @media (min-width: 40rem) {
260
+ [data-bl='card'][data-media='start'] {
261
+ flex-direction: row;
262
+ }
263
+ [data-bl='card'][data-media='start'] > [data-slot='media'] {
264
+ flex: 0 0 40%;
265
+ }
266
+ }
267
+
268
+ [data-bl='badge'],
269
+ [data-bl='chip'] {
270
+ display: inline-flex;
271
+ align-items: center;
272
+ gap: 0.375em;
273
+ }
274
+ :where([data-bl='badge'], [data-bl='chip']) [data-slot='icon'] svg {
275
+ width: 1em;
276
+ height: 1em;
277
+ }
278
+
279
+ [data-bl='stat'] {
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 0.25rem;
283
+ }
284
+ [data-bl='stat'] [data-slot='link'] {
285
+ display: inline-flex;
286
+ align-items: center;
287
+ min-height: 44px;
288
+ }
289
+
290
+ /* 06-breadcrumbs.css */
291
+ /* Breadcrumbs (F11): one wrapping line; the separator is drawn here (no element per crumb) with empty alternative
292
+ text, so assistive technology reads the list alone. A skin may restyle or replace it on the same selector. */
293
+
294
+ [data-bl='breadcrumbs'] [data-slot='list'] {
295
+ display: flex;
296
+ flex-wrap: wrap;
297
+ align-items: center;
298
+ gap: 0.25rem 0.5rem;
299
+ margin: 0;
300
+ padding: 0;
301
+ list-style: none;
302
+ }
303
+ [data-bl='breadcrumbs'] [data-slot='item'] {
304
+ display: inline-flex;
305
+ align-items: center;
306
+ gap: 0.5rem;
307
+ }
308
+ [data-bl='breadcrumbs'] [data-slot='item'] + [data-slot='item']::before {
309
+ content: '/';
310
+ content: '/' / '';
311
+ opacity: 0.6;
312
+ }
313
+
123
314
  /* 10-header.css */
124
315
  /*
125
316
  * F2 header and F3 panels: sticky and solid, modes by the header's own width, panels always in the HTML. The drawer's
@@ -194,7 +385,7 @@
194
385
  height: var(--bl-logo-h-phone, 40px);
195
386
  }
196
387
 
197
- /* The menu: hidden below 1280 px (the drawer takes over). */
388
+ /* The menu: hidden below 1200 px (the drawer takes over). */
198
389
  [data-bl='header'] [data-slot='inner'] > [data-slot='nav'] {
199
390
  display: none;
200
391
  flex: 1;
@@ -368,7 +559,7 @@
368
559
  height: 1.25rem;
369
560
  }
370
561
 
371
- /* 1024 to 1279 px: the compact band. Logo, phone with its number, quote and Menu. */
562
+ /* 1024 to 1199 px: the compact band. Logo, phone with its number, quote and Menu. The phone stays from 1024 px up. */
372
563
  @container bl-header (min-width: 1024px) {
373
564
  [data-bl='header'] > [data-slot='bar'] > [data-slot='inner'] {
374
565
  min-height: var(--bl-header-bar, 5rem);
@@ -408,8 +599,8 @@
408
599
  }
409
600
  }
410
601
 
411
- /* 1280 px and up: the full menu. */
412
- @container bl-header (min-width: 1280px) {
602
+ /* 1200 px and up: the full menu, with the phone and quote still beside it. */
603
+ @container bl-header (min-width: 1200px) {
413
604
  [data-bl='header'] [data-slot='inner'] > [data-slot='nav'] {
414
605
  display: block;
415
606
  }
@@ -643,13 +834,22 @@
643
834
  color: var(--bl-color-ink, CanvasText);
644
835
  transition: translate 200ms ease, visibility 0s;
645
836
  }
646
- [data-bl='callbar'] > :is([data-bl='phone-link'], [data-bl='quote-button']) {
647
- flex: 1 1 0;
837
+ /*
838
+ * One line each down to 360 px (3.15.0): the buttons size to their content, the number never wraps, and the inline
839
+ * padding (`--bl-callbar-button-padding`) outranks a skin's general button padding, so a skin tunes it by the token.
840
+ */
841
+ [data-bl='callbar'][data-variant] > :is([data-bl='phone-link'], [data-bl='quote-button']) {
842
+ flex: 1 1 auto;
648
843
  justify-content: center;
649
844
  min-width: 0;
650
845
  min-height: 48px;
846
+ padding-inline: var(--bl-callbar-button-padding, 0.75rem);
847
+ white-space: nowrap;
651
848
  text-decoration: none;
652
849
  }
850
+ [data-bl='callbar'] [data-bl='phone-link'] [data-slot='number'] {
851
+ white-space: nowrap;
852
+ }
653
853
  [data-bl='callbar'][data-variant='float'] {
654
854
  inset-inline: auto 0;
655
855
  justify-content: flex-end;
@@ -658,6 +858,25 @@
658
858
  [data-bl='callbar'][data-variant='float'] > :is([data-bl='phone-link'], [data-bl='quote-button']) {
659
859
  flex: none;
660
860
  }
861
+ /*
862
+ * Narrow phones: the verb before the number is visually hidden (the link's name still reads "Call 0497 777 735"), and
863
+ * a quote button with a compact label draws it from the attribute with empty alternative text, so its name stays the
864
+ * full label, which contains it (WCAG 2.5.3).
865
+ */
866
+ @media (max-width: 419.98px) {
867
+ [data-bl='callbar'] [data-bl='phone-link'] [data-slot='label'],
868
+ [data-bl='callbar'] [data-slot='label'][data-compact-label] > [data-bl-full-label] {
869
+ position: absolute;
870
+ width: 1px;
871
+ height: 1px;
872
+ overflow: hidden;
873
+ clip-path: inset(50%);
874
+ white-space: nowrap;
875
+ }
876
+ [data-bl='callbar'] [data-slot='label'][data-compact-label]::after {
877
+ content: attr(data-compact-label) / '';
878
+ }
879
+ }
661
880
  [data-bl='callbar'][data-state='hidden'] {
662
881
  visibility: hidden;
663
882
  translate: 0 100%;
@@ -670,7 +889,10 @@
670
889
  }
671
890
 
672
891
  /* 14-back-to-top.css */
673
- /* F7 back-to-top: a 44 px button in a bottom corner, above the call bar while it shows. */
892
+ /*
893
+ * F7 back-to-top: a 44 px button in a bottom corner. The hook hides it while the phone call bar shows (3.15.0); the
894
+ * bottom offset still clears the bar's height while the bar slides away.
895
+ */
674
896
 
675
897
  [data-bl='back-to-top'] {
676
898
  --bl-back-to-top-offset: 1.25rem;
@@ -911,6 +1133,103 @@
911
1133
  padding: 1rem var(--bl-gutter, 1.25rem) var(--bl-gutter, 1.25rem);
912
1134
  }
913
1135
 
1136
+ /* 29-hero.css */
1137
+ /* S1 Hero (3.14.0): layout only. Phones stack in source order (text, actions, checklist, photo at 4:3, form). From
1138
+ 1024 px of the hero's own width, `split` puts the text and form on one side and the photo on the other, and
1139
+ `full-bleed` puts the photo behind both, under the skin's scrim, with the form as a card beside the text. */
1140
+
1141
+ [data-bl-section='hero'] {
1142
+ container: bl-hero / inline-size;
1143
+ isolation: isolate;
1144
+ }
1145
+ [data-bl-section='hero'] :where(h1, p) {
1146
+ margin: 0;
1147
+ }
1148
+ [data-bl-section='hero'] > [data-slot='inner'] {
1149
+ display: grid;
1150
+ gap: 1.5rem;
1151
+ }
1152
+ [data-bl-section='hero'] [data-slot='content'] {
1153
+ display: grid;
1154
+ align-content: start;
1155
+ gap: 1rem;
1156
+ }
1157
+ [data-bl-section='hero'] [data-slot='actions'] {
1158
+ display: flex;
1159
+ flex-wrap: wrap;
1160
+ align-items: center;
1161
+ gap: 0.75rem;
1162
+ }
1163
+ [data-bl-section='hero'] [data-slot='scrim'] {
1164
+ display: none;
1165
+ }
1166
+ /* The root is the bl-hero container, and a container never matches its own query, so the full-bleed root is set up
1167
+ here: it holds the absolute photo and scrim from 1024 px. */
1168
+ [data-bl-section='hero'][data-variant='full-bleed'] {
1169
+ position: relative;
1170
+ overflow: hidden;
1171
+ }
1172
+
1173
+ @container bl-hero (min-width: 1024px) {
1174
+ [data-bl-section='hero'][data-height='tall'] > [data-slot='inner'] {
1175
+ padding-block: calc(var(--bl-space-section, 4rem) * 1.5);
1176
+ }
1177
+ [data-bl-section='hero'] > [data-slot='inner'] {
1178
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
1179
+ grid-template-areas:
1180
+ 'content media'
1181
+ 'form media';
1182
+ grid-template-rows: auto 1fr;
1183
+ column-gap: 3rem;
1184
+ align-items: start;
1185
+ }
1186
+ [data-bl-section='hero'][data-media-side='start'] > [data-slot='inner'] {
1187
+ grid-template-areas:
1188
+ 'media content'
1189
+ 'media form';
1190
+ }
1191
+ [data-bl-section='hero'] [data-slot='content'] {
1192
+ grid-area: content;
1193
+ }
1194
+ [data-bl-section='hero'] > [data-slot='inner'] > [data-slot='media'] {
1195
+ grid-area: media;
1196
+ align-self: stretch;
1197
+ }
1198
+ [data-bl-section='hero'] > [data-slot='inner'] > [data-slot='form'] {
1199
+ grid-area: form;
1200
+ }
1201
+ /* The photo fills its side: no white gaps beside it (Romie, Gabrael and H&R). */
1202
+ [data-bl-section='hero'] [data-slot='media'] > [data-bl='media'] {
1203
+ height: 100%;
1204
+ }
1205
+ [data-bl-section='hero'] [data-slot='media'] > [data-bl='media'] > img {
1206
+ height: 100%;
1207
+ min-height: 24rem;
1208
+ aspect-ratio: auto;
1209
+ }
1210
+
1211
+ /* full-bleed: the photo behind the whole hero; text and the form card side by side over it. */
1212
+ [data-bl-section='hero'][data-variant='full-bleed'] > [data-slot='inner'] {
1213
+ position: static;
1214
+ grid-template-columns: minmax(0, 1fr) minmax(0, 28rem);
1215
+ grid-template-areas: 'content form';
1216
+ grid-template-rows: auto;
1217
+ }
1218
+ [data-bl-section='hero'][data-variant='full-bleed'] > [data-slot='inner'] > [data-slot='media'] {
1219
+ position: absolute;
1220
+ inset: 0;
1221
+ z-index: -1;
1222
+ }
1223
+ [data-bl-section='hero'][data-variant='full-bleed'] [data-slot='media'] > [data-bl='media'] > img {
1224
+ min-height: 0;
1225
+ }
1226
+ [data-bl-section='hero'][data-variant='full-bleed'] [data-slot='scrim'] {
1227
+ display: block;
1228
+ position: absolute;
1229
+ inset: 0;
1230
+ }
1231
+ }
1232
+
914
1233
  /* 30-reviews.css */
915
1234
  /* S7 reviews band and the rating chip: layout only. Colours, fonts and shapes come from each site's skin. */
916
1235
 
@@ -1480,4 +1799,468 @@
1480
1799
  color: var(--bl-color-on-band, inherit);
1481
1800
  }
1482
1801
 
1802
+ /* 39-services.css */
1803
+ /* Services grid (S4). `rows`: text beside the photo from 1024 px of its own width, the photo alternating sides by
1804
+ default. `cards`: a grid of up to 4 columns, the photo on top. `compact`: a lean, wrapping list of links. Lists
1805
+ styled without bullets carry role="list", so Safari keeps announcing them as lists. */
1806
+
1807
+ [data-bl-section='services'] {
1808
+ container: bl-services / inline-size;
1809
+ }
1810
+ [data-bl-section='services'] [data-slot='list'] {
1811
+ margin: 0;
1812
+ padding: 0;
1813
+ list-style: none;
1814
+ }
1815
+ [data-bl-section='services'] [data-slot='list'] [data-slot='points'] {
1816
+ margin: 0;
1817
+ padding: 0;
1818
+ list-style: none;
1819
+ }
1820
+ [data-bl-section='services'] [data-slot='list'] [data-slot='title'] {
1821
+ margin: 0;
1822
+ }
1823
+
1824
+ /* Rows: text first in reading order; the photo above it on phones. */
1825
+ [data-bl-section='services'][data-variant='rows'] [data-slot='list'] > [data-slot='item'] {
1826
+ display: grid;
1827
+ gap: 1.25rem;
1828
+ padding-block: 2rem;
1829
+ }
1830
+ [data-bl-section='services'][data-variant='rows'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'] {
1831
+ order: -1;
1832
+ }
1833
+
1834
+ /* Cards: the photo on top. */
1835
+ [data-bl-section='services'][data-variant='cards'] [data-slot='list'] {
1836
+ display: grid;
1837
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
1838
+ gap: var(--bl-gutter, 1.25rem);
1839
+ }
1840
+ [data-bl-section='services'][data-variant='cards'] [data-slot='list'] > [data-slot='item'] {
1841
+ display: flex;
1842
+ flex-direction: column;
1843
+ gap: 0.75rem;
1844
+ }
1845
+ [data-bl-section='services'][data-variant='cards'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'] {
1846
+ order: -1;
1847
+ }
1848
+
1849
+ /* Compact: every service as one link, in columns. */
1850
+ [data-bl-section='services'][data-variant='compact'] [data-slot='list'] {
1851
+ display: grid;
1852
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 14rem), 1fr));
1853
+ gap: 0 var(--bl-gutter, 1.25rem);
1854
+ }
1855
+ [data-bl-section='services'][data-variant='compact'] [data-slot='list'] > [data-slot='item'] > [data-slot='link'] {
1856
+ display: flex;
1857
+ align-items: center;
1858
+ min-height: 44px;
1859
+ }
1860
+
1861
+ @container bl-services (min-width: 1024px) {
1862
+ [data-bl-section='services'][data-variant='rows'] [data-slot='list'] > [data-slot='item']:has(> [data-slot='media']) {
1863
+ grid-template-columns: 1fr 1fr;
1864
+ align-items: center;
1865
+ column-gap: clamp(3rem, 6cqi, 5rem);
1866
+ }
1867
+ [data-bl-section='services'][data-variant='rows'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'] {
1868
+ grid-row: 1;
1869
+ grid-column: 1;
1870
+ }
1871
+ [data-bl-section='services'][data-variant='rows'] [data-slot='list'] > [data-slot='item']:has(> [data-slot='media']) > [data-slot='body'] {
1872
+ grid-row: 1;
1873
+ grid-column: 2;
1874
+ }
1875
+ [data-bl-section='services'][data-variant='rows'][data-media-side='end'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'],
1876
+ [data-bl-section='services'][data-variant='rows'][data-media-side='alternate'] [data-slot='list'] > [data-slot='item']:nth-child(even) > [data-slot='media'] {
1877
+ grid-column: 2;
1878
+ }
1879
+ [data-bl-section='services'][data-variant='rows'][data-media-side='end'] [data-slot='list'] > [data-slot='item']:has(> [data-slot='media']) > [data-slot='body'],
1880
+ [data-bl-section='services'][data-variant='rows'][data-media-side='alternate'] [data-slot='list'] > [data-slot='item']:nth-child(even):has(> [data-slot='media']) > [data-slot='body'] {
1881
+ grid-column: 1;
1882
+ }
1883
+ [data-bl-section='services'][data-variant='cards'][data-columns='2'] [data-slot='list'] {
1884
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1885
+ }
1886
+ [data-bl-section='services'][data-variant='cards'][data-columns='3'] [data-slot='list'] {
1887
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1888
+ }
1889
+ [data-bl-section='services'][data-variant='cards'][data-columns='4'] [data-slot='list'] {
1890
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1891
+ }
1892
+ }
1893
+
1894
+ /* 40-location.css */
1895
+ /* Location sections (3.15.0): LocalFacts, CouncilRules, NearbyJobs, NearbyAreas, Coverage and RelatedServices. Layout
1896
+ only; the link lists are `LinkList`s (05-primitives.css) and the job and service cards follow 39-services.css. Lists
1897
+ styled without bullets carry role="list", so Safari keeps announcing them as lists. */
1898
+
1899
+ [data-bl-section='local-facts'] [data-slot='facts'],
1900
+ [data-bl-section='local-facts'] [data-slot='fees'],
1901
+ [data-bl-section='council-rules'] [data-slot='fees'],
1902
+ [data-bl-section='nearby-jobs'] [data-slot='list'],
1903
+ [data-bl-section='related-services'] [data-slot='list'] {
1904
+ margin: 0;
1905
+ padding: 0;
1906
+ list-style: none;
1907
+ }
1908
+ [data-bl-section='local-facts'] [data-slot='source'] > a,
1909
+ [data-bl-section='council-rules'] [data-slot='source'] > a,
1910
+ [data-bl-section='local-facts'] [data-slot='councilLink'] > a {
1911
+ display: inline-block;
1912
+ padding-block: 0.25rem;
1913
+ }
1914
+
1915
+ /* Nearby jobs: the photo on top of each card; a grid of up to 3 columns, or a scrolling rail. */
1916
+ [data-bl-section='nearby-jobs'] {
1917
+ container: bl-nearby-jobs / inline-size;
1918
+ }
1919
+ [data-bl-section='nearby-jobs'] [data-slot='list'] > [data-slot='item'] {
1920
+ display: flex;
1921
+ flex-direction: column;
1922
+ gap: 0.75rem;
1923
+ }
1924
+ [data-bl-section='nearby-jobs'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'] {
1925
+ order: -1;
1926
+ }
1927
+ [data-bl-section='nearby-jobs'] [data-slot='list'] [data-slot='title'] {
1928
+ margin: 0;
1929
+ }
1930
+ [data-bl-section='nearby-jobs'][data-variant='grid'] [data-slot='list'] {
1931
+ display: grid;
1932
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
1933
+ gap: var(--bl-gutter, 1.25rem);
1934
+ }
1935
+ [data-bl-section='nearby-jobs'][data-variant='rail'] [data-slot='list'] {
1936
+ display: grid;
1937
+ grid-auto-flow: column;
1938
+ grid-auto-columns: minmax(16rem, 80%);
1939
+ gap: var(--bl-gutter, 1.25rem);
1940
+ overflow-x: auto;
1941
+ scroll-snap-type: x mandatory;
1942
+ }
1943
+ [data-bl-section='nearby-jobs'][data-variant='rail'] [data-slot='list'] > [data-slot='item'] {
1944
+ scroll-snap-align: start;
1945
+ }
1946
+ @container bl-nearby-jobs (min-width: 1024px) {
1947
+ [data-bl-section='nearby-jobs'][data-variant='grid'][data-columns='2'] [data-slot='list'] {
1948
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1949
+ }
1950
+ [data-bl-section='nearby-jobs'][data-variant='grid'][data-columns='3'] [data-slot='list'] {
1951
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1952
+ }
1953
+ [data-bl-section='nearby-jobs'][data-variant='rail'] [data-slot='list'] {
1954
+ grid-auto-columns: minmax(16rem, 1fr);
1955
+ }
1956
+ }
1957
+
1958
+ /* Nearby areas as chips: the links wrap in a row. */
1959
+ [data-bl-section='nearby-areas'][data-variant='chips'] [data-bl='link-list'] {
1960
+ display: flex;
1961
+ flex-wrap: wrap;
1962
+ gap: 0.5rem;
1963
+ }
1964
+
1965
+ /* Coverage: one block per group, its heading above its list. */
1966
+ [data-bl-section='coverage'] [data-slot='groups'] {
1967
+ display: grid;
1968
+ gap: 2rem;
1969
+ }
1970
+ [data-bl-section='coverage'] [data-slot='groups'] > [data-slot='group'] > [data-slot='groupHeading'] {
1971
+ margin: 0 0 0.75rem;
1972
+ }
1973
+
1974
+ /* Related services as cards: the photo on top. */
1975
+ [data-bl-section='related-services'][data-variant='cards'] [data-slot='list'] {
1976
+ display: grid;
1977
+ grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr));
1978
+ gap: var(--bl-gutter, 1.25rem);
1979
+ }
1980
+ [data-bl-section='related-services'][data-variant='cards'] [data-slot='list'] > [data-slot='item'] {
1981
+ display: flex;
1982
+ flex-direction: column;
1983
+ gap: 0.75rem;
1984
+ }
1985
+ [data-bl-section='related-services'][data-variant='cards'] [data-slot='list'] > [data-slot='item'] > [data-slot='media'] {
1986
+ order: -1;
1987
+ }
1988
+ [data-bl-section='related-services'][data-variant='cards'] [data-slot='list'] [data-slot='title'] {
1989
+ margin: 0;
1990
+ }
1991
+
1992
+ /* 40-projects.css */
1993
+ /* Projects and Gallery (3.15.0): a grid of cards or photos, one column on phones, two from 640 px and the skin's
1994
+ columns from 1024 px of the section's own width. Lists styled without bullets carry role="list". */
1995
+
1996
+ [data-bl-section='projects'],
1997
+ [data-bl-section='gallery'] {
1998
+ container: bl-proof-grid / inline-size;
1999
+ }
2000
+ [data-bl-section='projects'] [data-slot='list'],
2001
+ [data-bl-section='gallery'] [data-slot='list'] {
2002
+ display: grid;
2003
+ grid-template-columns: minmax(0, 1fr);
2004
+ gap: var(--bl-gutter, 1.25rem);
2005
+ margin: 0;
2006
+ padding: 0;
2007
+ list-style: none;
2008
+ }
2009
+ [data-bl-section='gallery'] [data-slot='list'] > [data-slot='item'] > [data-slot='link'] {
2010
+ display: block;
2011
+ }
2012
+
2013
+ @container bl-proof-grid (min-width: 640px) {
2014
+ [data-bl-section='projects'] [data-slot='list'],
2015
+ [data-bl-section='gallery'] [data-slot='list'] {
2016
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2017
+ }
2018
+ }
2019
+ @container bl-proof-grid (min-width: 1024px) {
2020
+ [data-bl-section='projects'][data-columns='3'] [data-slot='list'],
2021
+ [data-bl-section='gallery'][data-columns='3'] [data-slot='list'] {
2022
+ grid-template-columns: repeat(3, minmax(0, 1fr));
2023
+ }
2024
+ [data-bl-section='projects'][data-columns='4'] [data-slot='list'],
2025
+ [data-bl-section='gallery'][data-columns='4'] [data-slot='list'] {
2026
+ grid-template-columns: repeat(4, minmax(0, 1fr));
2027
+ }
2028
+ }
2029
+
2030
+ /* 41-before-after.css */
2031
+ /* Before and after (3.15.0): each pair's two frames stacked on phones and side by side from 640 px of the section's
2032
+ width (`data-arrange="side"`), before first. Both frames share one crop, so they line up. */
2033
+
2034
+ [data-bl-section='before-after'] {
2035
+ container: bl-before-after / inline-size;
2036
+ }
2037
+ [data-bl-section='before-after'] [data-slot='list'] {
2038
+ display: grid;
2039
+ gap: calc(var(--bl-gutter, 1.25rem) * 2);
2040
+ margin: 0;
2041
+ padding: 0;
2042
+ list-style: none;
2043
+ }
2044
+ [data-bl-section='before-after'] [data-slot='list'] [data-slot='frames'] {
2045
+ display: grid;
2046
+ grid-template-columns: minmax(0, 1fr);
2047
+ gap: var(--bl-gutter, 1.25rem);
2048
+ }
2049
+
2050
+ @container bl-before-after (min-width: 640px) {
2051
+ [data-bl-section='before-after'][data-arrange='side'] [data-slot='list'] [data-slot='frames'] {
2052
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2053
+ }
2054
+ }
2055
+
2056
+ /* 42-licences.css */
2057
+ /* Licences (3.15.0): a ruled ledger, the label above its value on phones and beside it from 640 px of the section's
2058
+ width. The skin draws the rules and type. */
2059
+
2060
+ [data-bl-section='licences'] {
2061
+ container: bl-licences / inline-size;
2062
+ }
2063
+ [data-bl-section='licences'] [data-slot='list'] {
2064
+ margin: 0;
2065
+ }
2066
+ [data-bl-section='licences'] [data-slot='list'] > [data-slot='row'] {
2067
+ display: grid;
2068
+ gap: 0.25rem 2rem;
2069
+ padding-block: 1rem;
2070
+ }
2071
+ [data-bl-section='licences'] [data-slot='list'] [data-slot='row'] > dd {
2072
+ margin: 0;
2073
+ }
2074
+ [data-bl-section='licences'] [data-slot='list'] [data-slot='classes'] > ul {
2075
+ margin: 0;
2076
+ padding: 0;
2077
+ list-style: none;
2078
+ }
2079
+
2080
+ @container bl-licences (min-width: 640px) {
2081
+ [data-bl-section='licences'] [data-slot='list'] > [data-slot='row'] {
2082
+ grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
2083
+ }
2084
+ [data-bl-section='licences'] [data-slot='list'] > [data-slot='row'] > dt {
2085
+ grid-column: 1;
2086
+ grid-row: 1;
2087
+ }
2088
+ [data-bl-section='licences'] [data-slot='list'] > [data-slot='row'] > dd {
2089
+ grid-column: 2;
2090
+ }
2091
+ }
2092
+
2093
+ /* 43-quote-checklist.css */
2094
+ /* Quote checklist (3.15.0): heading, list, then the quote button; the list's columns are the TickList's. */
2095
+
2096
+ [data-bl='quote-checklist'] {
2097
+ display: grid;
2098
+ gap: 1rem;
2099
+ justify-items: start;
2100
+ }
2101
+ [data-bl='quote-checklist'] > [data-bl='tick-list'] {
2102
+ justify-self: stretch;
2103
+ }
2104
+ [data-bl='quote-checklist'] > p {
2105
+ margin: 0;
2106
+ }
2107
+
2108
+ /* 44-emergency.css */
2109
+ /* Emergency band (3.15.0): heading and summary, then the actions (phone first), side by side from 768 px of the
2110
+ band's width. The skin colours it. */
2111
+
2112
+ [data-bl-section='emergency'] {
2113
+ container: bl-emergency / inline-size;
2114
+ }
2115
+ [data-bl-section='emergency'] > [data-slot='inner'] {
2116
+ display: grid;
2117
+ gap: 1rem;
2118
+ }
2119
+ [data-bl-section='emergency'] [data-slot='actions'] {
2120
+ display: flex;
2121
+ flex-wrap: wrap;
2122
+ gap: 0.75rem;
2123
+ align-items: center;
2124
+ }
2125
+
2126
+ @container bl-emergency (min-width: 768px) {
2127
+ [data-bl-section='emergency'] > [data-slot='inner'] {
2128
+ grid-template-columns: minmax(0, 1fr) auto;
2129
+ align-items: center;
2130
+ column-gap: 2rem;
2131
+ }
2132
+ }
2133
+
2134
+ /* 45-area-map.css */
2135
+ /* Area map (3.15.0): the map and its place list, side by side from 768 px of the section's width (`data-list="beside"`)
2136
+ or stacked. The SVG's layers are `<use>` references into the base file, coloured here from the site's `--bl-map-*`
2137
+ tokens (falling back to its colour tokens); on narrow widths the frame shows the model's phone crop. */
2138
+
2139
+ [data-bl-section='area-map'] {
2140
+ container: bl-area-map / inline-size;
2141
+ }
2142
+ [data-bl-section='area-map'] [data-slot='body'] {
2143
+ display: grid;
2144
+ gap: var(--bl-gutter, 1.25rem);
2145
+ }
2146
+ [data-bl-section='area-map'] [data-slot='figure'] {
2147
+ margin: 0;
2148
+ display: grid;
2149
+ gap: 0.5rem;
2150
+ }
2151
+ [data-bl-section='area-map'] [data-slot='frame'] {
2152
+ position: relative;
2153
+ overflow: hidden;
2154
+ aspect-ratio: var(--bl-map-ratio, 1);
2155
+ }
2156
+ [data-bl-section='area-map'] [data-slot='map'] {
2157
+ display: block;
2158
+ width: 100%;
2159
+ height: auto;
2160
+ }
2161
+ [data-bl-section='area-map'] [data-slot='caption'] {
2162
+ display: grid;
2163
+ gap: 0.25rem;
2164
+ }
2165
+ [data-bl-section='area-map'] [data-slot='legend'] {
2166
+ display: flex;
2167
+ flex-wrap: wrap;
2168
+ gap: 0.25rem 1rem;
2169
+ }
2170
+ /* Each legend line starts with the marker it names, drawn in the same layer as the map's (3.15.0). */
2171
+ [data-bl-section='area-map'] :is([data-slot='legendJobs'], [data-slot='legendBase']) {
2172
+ display: inline-flex;
2173
+ align-items: center;
2174
+ gap: 0.4em;
2175
+ }
2176
+ [data-bl-section='area-map'] :is([data-slot='legendJobs'], [data-slot='legendBase']) > svg {
2177
+ width: 0.9em;
2178
+ height: 0.9em;
2179
+ }
2180
+ [data-bl-section='area-map'] [data-slot='places'] {
2181
+ display: grid;
2182
+ align-content: start;
2183
+ gap: 0.75rem;
2184
+ }
2185
+ [data-bl-section='area-map'] [data-slot='placesTitle'],
2186
+ [data-bl-section='area-map'] [data-slot='places'] > p {
2187
+ margin: 0;
2188
+ }
2189
+
2190
+ /* The layers. */
2191
+ [data-bl-section='area-map'] [data-layer='water'] {
2192
+ fill: var(--bl-map-water, transparent);
2193
+ }
2194
+ [data-bl-section='area-map'] [data-layer='land'] {
2195
+ fill: var(--bl-map-land, var(--bl-color-surface, Canvas));
2196
+ }
2197
+ [data-bl-section='area-map'] [data-layer='served'] {
2198
+ fill: var(--bl-map-served, var(--bl-color-canvas, Canvas));
2199
+ }
2200
+ [data-bl-section='area-map'] [data-layer='focus'] {
2201
+ fill: var(--bl-map-focus, var(--bl-color-action, Highlight));
2202
+ }
2203
+ [data-bl-section='area-map'] [data-layer='linked'] use {
2204
+ fill: var(--bl-map-linked, var(--bl-color-canvas, Canvas));
2205
+ }
2206
+ [data-bl-section='area-map'] [data-layer='linked'] a:hover use {
2207
+ fill: var(--bl-map-linked-hover, var(--bl-color-surface, Canvas));
2208
+ }
2209
+ [data-bl-section='area-map'] [data-layer='outline'] {
2210
+ stroke: var(--bl-map-outline, currentColor);
2211
+ stroke-opacity: 0.35;
2212
+ stroke-width: 1px;
2213
+ }
2214
+ [data-bl-section='area-map'] [data-layer='names'] {
2215
+ fill: var(--bl-map-name, var(--bl-color-ink, CanvasText));
2216
+ stroke: var(--bl-map-name-halo, var(--bl-color-canvas, Canvas));
2217
+ paint-order: stroke;
2218
+ text-anchor: middle;
2219
+ pointer-events: none;
2220
+ }
2221
+ [data-bl-section='area-map'] [data-layer='names'] [data-state='focus'] {
2222
+ font-weight: 700;
2223
+ }
2224
+ [data-bl-section='area-map'] [data-layer='jobs'] {
2225
+ fill: var(--bl-map-job, var(--bl-color-action, Highlight));
2226
+ stroke: var(--bl-color-canvas, Canvas);
2227
+ pointer-events: none;
2228
+ }
2229
+ [data-bl-section='area-map'] [data-layer='base'] {
2230
+ fill: var(--bl-map-base, var(--bl-color-ink, CanvasText));
2231
+ stroke: var(--bl-color-canvas, Canvas);
2232
+ pointer-events: none;
2233
+ }
2234
+
2235
+ /* Narrow widths: the phone crop around the served area. */
2236
+ @container bl-area-map (max-width: 639px) {
2237
+ [data-bl-section='area-map'] [data-slot='frame'] {
2238
+ aspect-ratio: var(--bl-map-crop-ratio, var(--bl-map-ratio, 1));
2239
+ }
2240
+ [data-bl-section='area-map'] [data-slot='map'] {
2241
+ position: absolute;
2242
+ width: var(--bl-map-crop-size, 100%);
2243
+ max-width: none;
2244
+ left: var(--bl-map-crop-x, 0);
2245
+ top: var(--bl-map-crop-y, 0);
2246
+ }
2247
+ }
2248
+
2249
+ /*
2250
+ * Beside a place list the map takes three fifths of the width. A region or overview map with no list fills the body
2251
+ * (3.15.0); a locator keeps its column. Names on a map that wide draw at 70%, so they read at about the same size.
2252
+ */
2253
+ @container bl-area-map (min-width: 768px) {
2254
+ [data-bl-section='area-map'][data-list='beside'] [data-slot='body']:has(> [data-slot='places']),
2255
+ [data-bl-section='area-map'][data-variant='locator'][data-list='beside'] [data-slot='body'] {
2256
+ grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
2257
+ align-items: start;
2258
+ }
2259
+ }
2260
+ @container bl-area-map (min-width: 960px) {
2261
+ [data-bl-section='area-map']:not([data-variant='locator']) [data-slot='body']:not(:has(> [data-slot='places'])) [data-layer='names'] text {
2262
+ font-size: 70%;
2263
+ }
2264
+ }
2265
+
1483
2266
  }