ngwr 15.6.0 → 15.7.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 (328) hide show
  1. package/animations/aurora/styles/_index.scss +44 -0
  2. package/animations/blur-reveal/styles/_index.scss +70 -0
  3. package/animations/click-sparks/styles/_index.scss +88 -0
  4. package/animations/confetti/styles/_index.scss +35 -0
  5. package/animations/core/styles/_mixins.scss +21 -0
  6. package/animations/decode/styles/_index.scss +68 -0
  7. package/animations/destruct/styles/_index.scss +31 -0
  8. package/animations/dot-grid/styles/_index.scss +41 -0
  9. package/animations/falling-letters/styles/_index.scss +72 -0
  10. package/animations/flow-lines/styles/_index.scss +39 -0
  11. package/animations/fluid-cursor/styles/_index.scss +44 -0
  12. package/animations/glitch/styles/_index.scss +189 -0
  13. package/animations/glow-border/styles/_index.scss +89 -0
  14. package/animations/gradient-flow/styles/_index.scss +101 -0
  15. package/animations/marquee/styles/_index.scss +179 -0
  16. package/animations/orbit/styles/_index.scss +77 -0
  17. package/animations/reveal/styles/_index.scss +96 -0
  18. package/animations/ripple-grid/styles/_index.scss +42 -0
  19. package/animations/rotate-reveal/styles/_index.scss +132 -0
  20. package/animations/shimmer/styles/_index.scss +102 -0
  21. package/animations/spotlight/styles/_index.scss +119 -0
  22. package/animations/thread-lines/styles/_index.scss +41 -0
  23. package/animations/typewriter/styles/_index.scss +94 -0
  24. package/date-picker/styles/_index.scss +28 -13
  25. package/fesm2022/ngwr-affix.mjs +3 -3
  26. package/fesm2022/ngwr-alert.mjs +3 -3
  27. package/fesm2022/ngwr-anchor.mjs +3 -3
  28. package/fesm2022/ngwr-animations-aurora.mjs +1000 -0
  29. package/fesm2022/ngwr-animations-aurora.mjs.map +1 -0
  30. package/fesm2022/ngwr-animations-blur-reveal.mjs +227 -0
  31. package/fesm2022/ngwr-animations-blur-reveal.mjs.map +1 -0
  32. package/fesm2022/ngwr-animations-click-sparks.mjs +145 -0
  33. package/fesm2022/ngwr-animations-click-sparks.mjs.map +1 -0
  34. package/fesm2022/ngwr-animations-confetti.mjs +233 -0
  35. package/fesm2022/ngwr-animations-confetti.mjs.map +1 -0
  36. package/fesm2022/ngwr-animations-core.mjs +343 -0
  37. package/fesm2022/ngwr-animations-core.mjs.map +1 -0
  38. package/fesm2022/ngwr-animations-decode.mjs +301 -0
  39. package/fesm2022/ngwr-animations-decode.mjs.map +1 -0
  40. package/fesm2022/ngwr-animations-destruct.mjs +232 -0
  41. package/fesm2022/ngwr-animations-destruct.mjs.map +1 -0
  42. package/fesm2022/ngwr-animations-dot-grid.mjs +330 -0
  43. package/fesm2022/ngwr-animations-dot-grid.mjs.map +1 -0
  44. package/fesm2022/ngwr-animations-falling-letters.mjs +526 -0
  45. package/fesm2022/ngwr-animations-falling-letters.mjs.map +1 -0
  46. package/fesm2022/ngwr-animations-flow-lines.mjs +1102 -0
  47. package/fesm2022/ngwr-animations-flow-lines.mjs.map +1 -0
  48. package/fesm2022/ngwr-animations-fluid-cursor.mjs +1187 -0
  49. package/fesm2022/ngwr-animations-fluid-cursor.mjs.map +1 -0
  50. package/fesm2022/ngwr-animations-glitch.mjs +164 -0
  51. package/fesm2022/ngwr-animations-glitch.mjs.map +1 -0
  52. package/fesm2022/ngwr-animations-glow-border.mjs +81 -0
  53. package/fesm2022/ngwr-animations-glow-border.mjs.map +1 -0
  54. package/fesm2022/ngwr-animations-gradient-flow.mjs +81 -0
  55. package/fesm2022/ngwr-animations-gradient-flow.mjs.map +1 -0
  56. package/fesm2022/ngwr-animations-marquee.mjs +321 -0
  57. package/fesm2022/ngwr-animations-marquee.mjs.map +1 -0
  58. package/fesm2022/ngwr-animations-orbit.mjs +264 -0
  59. package/fesm2022/ngwr-animations-orbit.mjs.map +1 -0
  60. package/fesm2022/ngwr-animations-reveal.mjs +279 -0
  61. package/fesm2022/ngwr-animations-reveal.mjs.map +1 -0
  62. package/fesm2022/ngwr-animations-ripple-grid.mjs +320 -0
  63. package/fesm2022/ngwr-animations-ripple-grid.mjs.map +1 -0
  64. package/fesm2022/ngwr-animations-rotate-reveal.mjs +285 -0
  65. package/fesm2022/ngwr-animations-rotate-reveal.mjs.map +1 -0
  66. package/fesm2022/ngwr-animations-shimmer.mjs +121 -0
  67. package/fesm2022/ngwr-animations-shimmer.mjs.map +1 -0
  68. package/fesm2022/ngwr-animations-spotlight.mjs +90 -0
  69. package/fesm2022/ngwr-animations-spotlight.mjs.map +1 -0
  70. package/fesm2022/ngwr-animations-thread-lines.mjs +926 -0
  71. package/fesm2022/ngwr-animations-thread-lines.mjs.map +1 -0
  72. package/fesm2022/ngwr-animations-tilt.mjs +134 -0
  73. package/fesm2022/ngwr-animations-tilt.mjs.map +1 -0
  74. package/fesm2022/ngwr-animations-typewriter.mjs +335 -0
  75. package/fesm2022/ngwr-animations-typewriter.mjs.map +1 -0
  76. package/fesm2022/ngwr-avatar.mjs +3 -3
  77. package/fesm2022/ngwr-back-top.mjs +3 -3
  78. package/fesm2022/ngwr-badge.mjs +6 -6
  79. package/fesm2022/ngwr-breadcrumbs.mjs +6 -6
  80. package/fesm2022/ngwr-burger.mjs +3 -3
  81. package/fesm2022/ngwr-button.mjs +6 -6
  82. package/fesm2022/ngwr-calendar.mjs +3 -3
  83. package/fesm2022/ngwr-card.mjs +9 -9
  84. package/fesm2022/ngwr-carousel.mjs +6 -6
  85. package/fesm2022/ngwr-cascader.mjs +3 -3
  86. package/fesm2022/ngwr-charts-bar-chart.mjs +3 -3
  87. package/fesm2022/ngwr-charts-boxplot-chart.mjs +3 -3
  88. package/fesm2022/ngwr-charts-bullet-chart.mjs +3 -3
  89. package/fesm2022/ngwr-charts-calendar-heatmap.mjs +3 -3
  90. package/fesm2022/ngwr-charts-candlestick-chart.mjs +3 -3
  91. package/fesm2022/ngwr-charts-chart-legend.mjs +6 -6
  92. package/fesm2022/ngwr-charts-core.mjs +3 -3
  93. package/fesm2022/ngwr-charts-donut-chart.mjs +3 -3
  94. package/fesm2022/ngwr-charts-funnel-chart.mjs +3 -3
  95. package/fesm2022/ngwr-charts-gauge.mjs +3 -3
  96. package/fesm2022/ngwr-charts-heatmap-chart.mjs +3 -3
  97. package/fesm2022/ngwr-charts-line-chart.mjs +3 -3
  98. package/fesm2022/ngwr-charts-meter-group.mjs +3 -3
  99. package/fesm2022/ngwr-charts-radar-chart.mjs +3 -3
  100. package/fesm2022/ngwr-charts-scatter-chart.mjs +3 -3
  101. package/fesm2022/ngwr-charts-sparkline.mjs +3 -3
  102. package/fesm2022/ngwr-charts-treemap-chart.mjs +3 -3
  103. package/fesm2022/ngwr-charts-waterfall-chart.mjs +3 -3
  104. package/fesm2022/ngwr-checkbox.mjs +6 -6
  105. package/fesm2022/ngwr-clipboard.mjs +7 -4
  106. package/fesm2022/ngwr-clipboard.mjs.map +1 -1
  107. package/fesm2022/ngwr-collapse.mjs +9 -9
  108. package/fesm2022/ngwr-color-picker.mjs +11 -9
  109. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  110. package/fesm2022/ngwr-command-palette.mjs +7 -6
  111. package/fesm2022/ngwr-command-palette.mjs.map +1 -1
  112. package/fesm2022/ngwr-comment.mjs +6 -6
  113. package/fesm2022/ngwr-compare.mjs +3 -3
  114. package/fesm2022/ngwr-context-menu.mjs +17 -15
  115. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  116. package/fesm2022/ngwr-cookie.mjs +3 -3
  117. package/fesm2022/ngwr-counter.mjs +6 -6
  118. package/fesm2022/ngwr-date-picker.mjs +34 -26
  119. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  120. package/fesm2022/ngwr-date.mjs +6 -6
  121. package/fesm2022/ngwr-density.mjs +6 -6
  122. package/fesm2022/ngwr-descriptions.mjs +6 -6
  123. package/fesm2022/ngwr-dialog.mjs +24 -22
  124. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  125. package/fesm2022/ngwr-directives.mjs +16 -13
  126. package/fesm2022/ngwr-directives.mjs.map +1 -1
  127. package/fesm2022/ngwr-divider.mjs +3 -3
  128. package/fesm2022/ngwr-drawer.mjs +27 -24
  129. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  130. package/fesm2022/ngwr-dropdown.mjs +15 -13
  131. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  132. package/fesm2022/ngwr-editor.mjs +4 -4
  133. package/fesm2022/ngwr-empty.mjs +3 -3
  134. package/fesm2022/ngwr-event-calendar.mjs +7 -7
  135. package/fesm2022/ngwr-file-upload.mjs +3 -3
  136. package/fesm2022/ngwr-form.mjs +9 -9
  137. package/fesm2022/ngwr-graph.mjs +6 -6
  138. package/fesm2022/ngwr-hotkey.mjs +6 -6
  139. package/fesm2022/ngwr-i18n-ar.mjs +6 -1
  140. package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
  141. package/fesm2022/ngwr-i18n-cs.mjs +6 -1
  142. package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
  143. package/fesm2022/ngwr-i18n-de.mjs +6 -1
  144. package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
  145. package/fesm2022/ngwr-i18n-en.mjs +6 -1
  146. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  147. package/fesm2022/ngwr-i18n-es.mjs +6 -1
  148. package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
  149. package/fesm2022/ngwr-i18n-fr.mjs +6 -1
  150. package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
  151. package/fesm2022/ngwr-i18n-he.mjs +6 -1
  152. package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
  153. package/fesm2022/ngwr-i18n-hi.mjs +6 -1
  154. package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
  155. package/fesm2022/ngwr-i18n-id.mjs +6 -1
  156. package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
  157. package/fesm2022/ngwr-i18n-it.mjs +6 -1
  158. package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
  159. package/fesm2022/ngwr-i18n-ja.mjs +6 -1
  160. package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
  161. package/fesm2022/ngwr-i18n-ko.mjs +6 -1
  162. package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
  163. package/fesm2022/ngwr-i18n-nl.mjs +6 -1
  164. package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
  165. package/fesm2022/ngwr-i18n-pl.mjs +6 -1
  166. package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
  167. package/fesm2022/ngwr-i18n-pt.mjs +6 -1
  168. package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
  169. package/fesm2022/ngwr-i18n-ru.mjs +6 -1
  170. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  171. package/fesm2022/ngwr-i18n-sv.mjs +6 -1
  172. package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
  173. package/fesm2022/ngwr-i18n-tr.mjs +6 -1
  174. package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
  175. package/fesm2022/ngwr-i18n-uk.mjs +6 -1
  176. package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
  177. package/fesm2022/ngwr-i18n-vi.mjs +6 -1
  178. package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
  179. package/fesm2022/ngwr-i18n-zh-tw.mjs +6 -1
  180. package/fesm2022/ngwr-i18n-zh-tw.mjs.map +1 -1
  181. package/fesm2022/ngwr-i18n-zh.mjs +6 -1
  182. package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
  183. package/fesm2022/ngwr-i18n.mjs +9 -9
  184. package/fesm2022/ngwr-icon.mjs +6 -6
  185. package/fesm2022/ngwr-image-cropper.mjs +3 -3
  186. package/fesm2022/ngwr-input-number.mjs +3 -3
  187. package/fesm2022/ngwr-input-otp.mjs +3 -3
  188. package/fesm2022/ngwr-input.mjs +15 -15
  189. package/fesm2022/ngwr-keyboard.mjs +3 -3
  190. package/fesm2022/ngwr-knob.mjs +3 -3
  191. package/fesm2022/ngwr-layout.mjs +15 -15
  192. package/fesm2022/ngwr-lightbox.mjs +7 -6
  193. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  194. package/fesm2022/ngwr-list.mjs +6 -6
  195. package/fesm2022/ngwr-load-state.mjs +15 -15
  196. package/fesm2022/ngwr-loading-bar.mjs +6 -6
  197. package/fesm2022/ngwr-mention.mjs +6 -6
  198. package/fesm2022/ngwr-meta.mjs +6 -6
  199. package/fesm2022/ngwr-overlay.mjs +27 -7
  200. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  201. package/fesm2022/ngwr-page-header.mjs +3 -3
  202. package/fesm2022/ngwr-pagination.mjs +3 -3
  203. package/fesm2022/ngwr-pipes.mjs +27 -27
  204. package/fesm2022/ngwr-platform.mjs +9 -9
  205. package/fesm2022/ngwr-popconfirm.mjs +12 -10
  206. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  207. package/fesm2022/ngwr-popover.mjs +15 -15
  208. package/fesm2022/ngwr-popover.mjs.map +1 -1
  209. package/fesm2022/ngwr-progress.mjs +3 -3
  210. package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
  211. package/fesm2022/ngwr-qr.mjs +3 -3
  212. package/fesm2022/ngwr-radio.mjs +6 -6
  213. package/fesm2022/ngwr-rating.mjs +3 -3
  214. package/fesm2022/ngwr-result.mjs +12 -12
  215. package/fesm2022/ngwr-schema-form.mjs +3 -3
  216. package/fesm2022/ngwr-scroll.mjs +3 -3
  217. package/fesm2022/ngwr-segmented.mjs +3 -3
  218. package/fesm2022/ngwr-select.mjs +16 -16
  219. package/fesm2022/ngwr-sidebar.mjs +3 -3
  220. package/fesm2022/ngwr-skeleton.mjs +3 -3
  221. package/fesm2022/ngwr-slider.mjs +3 -3
  222. package/fesm2022/ngwr-sortable-list.mjs +9 -9
  223. package/fesm2022/ngwr-speed-dial.mjs +3 -3
  224. package/fesm2022/ngwr-spinner.mjs +3 -3
  225. package/fesm2022/ngwr-splitter.mjs +3 -3
  226. package/fesm2022/ngwr-statistic.mjs +9 -9
  227. package/fesm2022/ngwr-stepper.mjs +6 -6
  228. package/fesm2022/ngwr-storage.mjs +3 -3
  229. package/fesm2022/ngwr-switch.mjs +3 -3
  230. package/fesm2022/ngwr-table.mjs +19 -19
  231. package/fesm2022/ngwr-tabs-router.mjs +3 -3
  232. package/fesm2022/ngwr-tabs.mjs +6 -6
  233. package/fesm2022/ngwr-textarea.mjs +3 -3
  234. package/fesm2022/ngwr-theme.mjs +3 -3
  235. package/fesm2022/ngwr-timeline.mjs +6 -6
  236. package/fesm2022/ngwr-toast.mjs +17 -15
  237. package/fesm2022/ngwr-toast.mjs.map +1 -1
  238. package/fesm2022/ngwr-toolbar.mjs +3 -3
  239. package/fesm2022/ngwr-tour.mjs +7 -7
  240. package/fesm2022/ngwr-transfer.mjs +4 -4
  241. package/fesm2022/ngwr-tree.mjs +3 -3
  242. package/fesm2022/ngwr-typography.mjs +3 -3
  243. package/fesm2022/ngwr-utils-router.mjs +3 -3
  244. package/fesm2022/ngwr-utils.mjs +5 -1
  245. package/fesm2022/ngwr-utils.mjs.map +1 -1
  246. package/fesm2022/ngwr-version.mjs +1 -1
  247. package/fesm2022/ngwr-version.mjs.map +1 -1
  248. package/fesm2022/ngwr-virtual-scroll.mjs +5 -5
  249. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  250. package/fesm2022/ngwr-window.mjs +17 -16
  251. package/fesm2022/ngwr-window.mjs.map +1 -1
  252. package/i18n/ar.json +7 -0
  253. package/i18n/cs.json +7 -0
  254. package/i18n/de.json +7 -0
  255. package/i18n/en.json +7 -0
  256. package/i18n/es.json +7 -0
  257. package/i18n/fr.json +7 -0
  258. package/i18n/he.json +7 -0
  259. package/i18n/hi.json +7 -0
  260. package/i18n/id.json +7 -0
  261. package/i18n/it.json +7 -0
  262. package/i18n/ja.json +7 -0
  263. package/i18n/ko.json +7 -0
  264. package/i18n/nl.json +7 -0
  265. package/i18n/pl.json +7 -0
  266. package/i18n/pt.json +7 -0
  267. package/i18n/ru.json +7 -0
  268. package/i18n/sv.json +7 -0
  269. package/i18n/tr.json +7 -0
  270. package/i18n/uk.json +7 -0
  271. package/i18n/vi.json +7 -0
  272. package/i18n/zh-TW.json +7 -0
  273. package/i18n/zh.json +7 -0
  274. package/llms-full.txt +162 -2
  275. package/llms.txt +1 -0
  276. package/package.json +119 -1
  277. package/schematics/use/rule.js +1 -0
  278. package/schematics/use/symbol-map.json +23 -0
  279. package/skills/ngwr/SKILL.md +3 -2
  280. package/skills/ngwr/references/catalog.md +23 -0
  281. package/theme/_index.scss +7 -1
  282. package/theme/styles/_index.scss +1 -0
  283. package/theme/styles/_scrollbar.scss +69 -0
  284. package/theme/styles/_variables.scss +8 -0
  285. package/types/ngwr-animations-aurora.d.ts +186 -0
  286. package/types/ngwr-animations-blur-reveal.d.ts +84 -0
  287. package/types/ngwr-animations-click-sparks.d.ts +67 -0
  288. package/types/ngwr-animations-confetti.d.ts +93 -0
  289. package/types/ngwr-animations-core.d.ts +294 -0
  290. package/types/ngwr-animations-decode.d.ts +104 -0
  291. package/types/ngwr-animations-destruct.d.ts +96 -0
  292. package/types/ngwr-animations-dot-grid.d.ts +87 -0
  293. package/types/ngwr-animations-falling-letters.d.ts +165 -0
  294. package/types/ngwr-animations-flow-lines.d.ts +208 -0
  295. package/types/ngwr-animations-fluid-cursor.d.ts +183 -0
  296. package/types/ngwr-animations-glitch.d.ts +86 -0
  297. package/types/ngwr-animations-glow-border.d.ts +29 -0
  298. package/types/ngwr-animations-gradient-flow.d.ts +38 -0
  299. package/types/ngwr-animations-marquee.d.ts +148 -0
  300. package/types/ngwr-animations-orbit.d.ts +112 -0
  301. package/types/ngwr-animations-reveal.d.ts +134 -0
  302. package/types/ngwr-animations-ripple-grid.d.ts +74 -0
  303. package/types/ngwr-animations-rotate-reveal.d.ts +134 -0
  304. package/types/ngwr-animations-shimmer.d.ts +68 -0
  305. package/types/ngwr-animations-spotlight.d.ts +36 -0
  306. package/types/ngwr-animations-thread-lines.d.ts +155 -0
  307. package/types/ngwr-animations-tilt.d.ts +49 -0
  308. package/types/ngwr-animations-typewriter.d.ts +144 -0
  309. package/types/ngwr-clipboard.d.ts +1 -0
  310. package/types/ngwr-color-picker.d.ts +1 -0
  311. package/types/ngwr-command-palette.d.ts +1 -0
  312. package/types/ngwr-compare.d.ts +1 -1
  313. package/types/ngwr-context-menu.d.ts +1 -0
  314. package/types/ngwr-dialog.d.ts +1 -0
  315. package/types/ngwr-directives.d.ts +1 -0
  316. package/types/ngwr-drawer.d.ts +9 -2
  317. package/types/ngwr-dropdown.d.ts +1 -0
  318. package/types/ngwr-lightbox.d.ts +1 -0
  319. package/types/ngwr-overlay.d.ts +19 -0
  320. package/types/ngwr-popconfirm.d.ts +1 -0
  321. package/types/ngwr-sortable-list.d.ts +1 -1
  322. package/types/ngwr-splitter.d.ts +1 -1
  323. package/types/ngwr-stepper.d.ts +1 -1
  324. package/types/ngwr-timeline.d.ts +1 -1
  325. package/types/ngwr-utils.d.ts +11 -6
  326. package/types/ngwr-version.d.ts +1 -1
  327. package/types/ngwr-window.d.ts +1 -0
  328. package/virtual-scroll/styles/_rules.scss +5 -9
@@ -0,0 +1,189 @@
1
+ @use '../../../theme/styles' as theme;
2
+ @include theme.loaded('animations/glitch');
3
+
4
+ // `[wrGlitch]`: while a pointer is over a short text, or focus is in it, the
5
+ // text looks like a broken signal: two tinted copies of it, cut into thin
6
+ // horizontal slices, jump sideways a few pixels while the text leans and
7
+ // shifts a little; the moment the pointer leaves, everything snaps back. At
8
+ // rest the block declares only its hooks and `position: relative`, the anchor
9
+ // for the copies, so the target looks the way its own rules say; the copies
10
+ // and `--live` exist only while it plays. The directive owns the state (under
11
+ // a pointer or not); the sheet owns the paint and the cadence.
12
+ .wr-glitch {
13
+ // One pass of the loop: six held steps, each a different slice of each
14
+ // copy. At 1.2 s a step is 200 ms, which reads as a signal breaking up, not
15
+ // a flicker, and keeps the flash budget below: see the keyframes.
16
+ --wr-glitch-cycle: 1.2s;
17
+ // How far a slice and the text jump, in `em`: 2.4px on the 24px result
18
+ // title, a smear rather than a tear, and the same share of any heading.
19
+ --wr-glitch-shift: 0.1em;
20
+ // How far the text leans at its worst frame.
21
+ --wr-glitch-skew: 2deg;
22
+ // The two copies' colours: theme inks, each the intent as text on the
23
+ // surface, at reduced strength over `transparent`. Primary and danger sit
24
+ // far apart in hue, so the two fringes read as a split signal, and at this
25
+ // strength a copy over the text darkens or lightens a glyph pixel by well
26
+ // under the full ink: a faint fringe, never a strobe, and the text under it
27
+ // keeps its own colour in every frame. Inks, never ramp steps.
28
+ --wr-glitch-strength: 55%;
29
+ --wr-glitch-tint-a: color-mix(in srgb, var(--wr-color-primary-ink) var(--wr-glitch-strength), transparent);
30
+ --wr-glitch-tint-b: color-mix(in srgb, var(--wr-color-danger-ink) var(--wr-glitch-strength), transparent);
31
+
32
+ // The anchor for the copies. A transform never moves the box, so a centred
33
+ // title stays centred while it leans.
34
+ position: relative;
35
+
36
+ // One copy: the same text over the same box, so it inherits the font, the
37
+ // alignment and the line height and its glyphs land exactly over the real
38
+ // ones. Out of flow, out of the selection, under no pointer. Clipped to
39
+ // nothing until its animation says otherwise, so a copy that is somehow
40
+ // present at rest paints nothing.
41
+ &__copy {
42
+ position: absolute;
43
+ inset: 0;
44
+ color: var(--wr-glitch-tint-a);
45
+ clip-path: inset(100% 0 0 0);
46
+ pointer-events: none;
47
+ user-select: none;
48
+ }
49
+
50
+ &__copy--b {
51
+ color: var(--wr-glitch-tint-b);
52
+ }
53
+
54
+ @media (prefers-reduced-motion: no-preference) and (forced-colors: none) {
55
+ // `steps(1, end)` holds each keyframe's value until the next keyframe, so
56
+ // a slice jumps from one place to the next instead of sliding: six holds
57
+ // per cycle, each a different slice at a different offset, round and
58
+ // round while `--live` is on. The directive takes the copies out when the
59
+ // pointer leaves, so no late frame is left on screen.
60
+ &--live {
61
+ animation: wr-glitch-lean var(--wr-glitch-cycle) steps(1, end) infinite;
62
+ }
63
+
64
+ &--live &__copy--a {
65
+ animation: wr-glitch-slice-a var(--wr-glitch-cycle) steps(1, end) infinite;
66
+ }
67
+
68
+ &--live &__copy--b {
69
+ animation: wr-glitch-slice-b var(--wr-glitch-cycle) steps(1, end) infinite;
70
+ }
71
+ }
72
+
73
+ // Belt and braces: the directive adds no copy under either, but a preference
74
+ // flipped mid-play must not leave a fringe behind.
75
+ @media (prefers-reduced-motion: reduce), (forced-colors: active) {
76
+ &__copy {
77
+ display: none;
78
+ }
79
+ }
80
+ }
81
+
82
+ // The text itself: a lean and a shift of a fraction of the slice jump, so the
83
+ // real glyphs stay where the eye expects them while the fringes jump around.
84
+ // Physical on purpose: a broken signal has no reading direction.
85
+ @keyframes wr-glitch-lean {
86
+ 0% {
87
+ transform: skewX(calc(var(--wr-glitch-skew) * -1)) translateX(calc(var(--wr-glitch-shift) * 0.3));
88
+ }
89
+
90
+ 17% {
91
+ transform: none;
92
+ }
93
+
94
+ 33% {
95
+ transform: skewX(var(--wr-glitch-skew)) translateX(calc(var(--wr-glitch-shift) * -0.3));
96
+ }
97
+
98
+ 50% {
99
+ transform: translateX(calc(var(--wr-glitch-shift) * 0.5));
100
+ }
101
+
102
+ 67% {
103
+ transform: skewX(calc(var(--wr-glitch-skew) * -0.5));
104
+ }
105
+
106
+ 83% {
107
+ transform: none;
108
+ }
109
+ }
110
+
111
+ // The flash budget (WCAG 2.3.1: no more than three flashes in any second,
112
+ // a flash being a pair of opposing luminance changes). The line is cut into
113
+ // twelve bands of 8%, with 2% left at the top and bottom: copy A owns the
114
+ // odd bands and copy B the even ones, and each copy visits each of its six
115
+ // bands once per cycle, in a scrambled order. So no point of the text is
116
+ // lit by a copy more than once per cycle, and with the cycle at a second or
117
+ // more, any one-second window lights a point at most twice: once at the end
118
+ // of a cycle and once at the start of the next. `inset(top 0 bottom 0)`
119
+ // keeps one horizontal band of the copy; the rest is clipped, so what shows
120
+ // is a strip of tinted glyphs beside the real ones. `glitch.spec.ts` reads
121
+ // these keyframes and holds the bands disjoint.
122
+
123
+ // Copy A: bands 34-42, 2-10, 66-74, 18-26, 82-90, 50-58, pushed toward the start first.
124
+ @keyframes wr-glitch-slice-a {
125
+ 0% {
126
+ clip-path: inset(34% 0 58% 0);
127
+ transform: translateX(calc(var(--wr-glitch-shift) * -1));
128
+ }
129
+
130
+ 17% {
131
+ clip-path: inset(2% 0 90% 0);
132
+ transform: translateX(calc(var(--wr-glitch-shift) * 0.6));
133
+ }
134
+
135
+ 33% {
136
+ clip-path: inset(66% 0 26% 0);
137
+ transform: translateX(calc(var(--wr-glitch-shift) * -0.8));
138
+ }
139
+
140
+ 50% {
141
+ clip-path: inset(18% 0 74% 0);
142
+ transform: translateX(calc(var(--wr-glitch-shift) * 1.2));
143
+ }
144
+
145
+ 67% {
146
+ clip-path: inset(82% 0 10% 0);
147
+ transform: translateX(calc(var(--wr-glitch-shift) * -0.5));
148
+ }
149
+
150
+ 83% {
151
+ clip-path: inset(50% 0 42% 0);
152
+ transform: translateX(calc(var(--wr-glitch-shift) * 0.9));
153
+ }
154
+ }
155
+
156
+ // Copy B: bands 74-82, 26-34, 90-98, 10-18, 58-66, 42-50, pushed the other
157
+ // way, so the two fringes never cover the same band and the text between
158
+ // them stays clean.
159
+ @keyframes wr-glitch-slice-b {
160
+ 0% {
161
+ clip-path: inset(74% 0 18% 0);
162
+ transform: translateX(var(--wr-glitch-shift));
163
+ }
164
+
165
+ 17% {
166
+ clip-path: inset(26% 0 66% 0);
167
+ transform: translateX(calc(var(--wr-glitch-shift) * -0.7));
168
+ }
169
+
170
+ 33% {
171
+ clip-path: inset(90% 0 2% 0);
172
+ transform: translateX(calc(var(--wr-glitch-shift) * 0.9));
173
+ }
174
+
175
+ 50% {
176
+ clip-path: inset(10% 0 82% 0);
177
+ transform: translateX(calc(var(--wr-glitch-shift) * -1.1));
178
+ }
179
+
180
+ 67% {
181
+ clip-path: inset(58% 0 34% 0);
182
+ transform: translateX(calc(var(--wr-glitch-shift) * 0.4));
183
+ }
184
+
185
+ 83% {
186
+ clip-path: inset(42% 0 50% 0);
187
+ transform: translateX(calc(var(--wr-glitch-shift) * -0.6));
188
+ }
189
+ }
@@ -0,0 +1,89 @@
1
+ @use '../../../theme/styles' as theme;
2
+ @include theme.loaded('animations/glow-border');
3
+
4
+ // `[wrGlowBorder]`: a short arc of brand light running round the host's edge,
5
+ // with a soft glow spilling outward. Two pseudo-elements carry one conic
6
+ // gradient turned by a registered angle: `::before` is the arc itself, masked
7
+ // down to the ring; `::after` is a wider, blurred copy sitting UNDER the host
8
+ // (negative z-index), so only what spills past the edge shows. The host's
9
+ // stacking parent isolates itself (`isolation: isolate`), which keeps that
10
+ // copy above the page background; the host itself must not form a stacking
11
+ // context, or the copy would paint over its own fill.
12
+
13
+ // Registered so the angle interpolates. Only the angle: a colour hook is never
14
+ // registered.
15
+ @property --wr-glow-border-angle {
16
+ syntax: '<angle>';
17
+ inherits: false;
18
+ initial-value: 0deg;
19
+ }
20
+
21
+ .wr-glow-border {
22
+ // The arc's centre, and its two edges mixed from it toward danger and
23
+ // success, so one hook recolours the whole arc and the edges still lean
24
+ // warm and cool. A role, never a step.
25
+ --wr-glow-border-color: var(--wr-color-primary);
26
+ --wr-glow-border-warm: color-mix(in oklch, var(--wr-glow-border-color) 70%, var(--wr-color-danger));
27
+ --wr-glow-border-cool: color-mix(in oklch, var(--wr-glow-border-color) 70%, var(--wr-color-success));
28
+ --wr-glow-border-width: 1.5px;
29
+ --wr-glow-border-blur: 14px;
30
+ --wr-glow-border-strength: 0.6;
31
+ --wr-glow-border-period: 4.5s;
32
+
33
+ &::before,
34
+ &::after {
35
+ content: '';
36
+ position: absolute;
37
+ inset: -1px;
38
+ border-radius: inherit;
39
+ pointer-events: none;
40
+ }
41
+
42
+ &::before {
43
+ padding: var(--wr-glow-border-width);
44
+ background: conic-gradient(
45
+ from var(--wr-glow-border-angle),
46
+ transparent 0deg,
47
+ var(--wr-glow-border-cool) 5deg,
48
+ var(--wr-glow-border-color) 7.5deg,
49
+ var(--wr-glow-border-warm) 10deg,
50
+ transparent 15deg
51
+ );
52
+ mask:
53
+ linear-gradient(#000 0 0) content-box,
54
+ linear-gradient(#000 0 0);
55
+ mask-composite: exclude;
56
+ }
57
+
58
+ &::after {
59
+ z-index: -1;
60
+ background: conic-gradient(
61
+ from var(--wr-glow-border-angle),
62
+ transparent 0deg,
63
+ var(--wr-glow-border-cool) 8deg,
64
+ var(--wr-glow-border-color) 12deg,
65
+ var(--wr-glow-border-warm) 16deg,
66
+ transparent 24deg
67
+ );
68
+ filter: blur(var(--wr-glow-border-blur));
69
+ opacity: var(--wr-glow-border-strength);
70
+ }
71
+
72
+ &--live::before,
73
+ &--live::after {
74
+ animation: wr-glow-border var(--wr-glow-border-period) linear infinite;
75
+ }
76
+
77
+ @media (prefers-reduced-motion: reduce) {
78
+ &--live::before,
79
+ &--live::after {
80
+ animation: none;
81
+ }
82
+ }
83
+ }
84
+
85
+ @keyframes wr-glow-border {
86
+ to {
87
+ --wr-glow-border-angle: 360deg;
88
+ }
89
+ }
@@ -0,0 +1,101 @@
1
+ @use '../../../theme/styles' as theme;
2
+ @include theme.loaded('animations/gradient-flow');
3
+
4
+ // `[wrGradientFlow]`: a short piece of text filled with a gradient of theme
5
+ // inks that drifts along it, forever, as a seamless loop. The static gradient
6
+ // is the block itself, so a server render and a reader with reduced motion get
7
+ // the final colours from CSS alone; the drift is one paused animation on the
8
+ // host that the directive's `--run` sets running while the text is on screen.
9
+ .wr-gradient-flow {
10
+ // The colour the loop starts and ends on, and the stops in between, in
11
+ // reading order. Inks, not bare intents: `-ink` is each intent as TEXT on the
12
+ // surface, calibrated to 5:1 in both schemes (7:1 under `prefers-contrast:
13
+ // more`), and the inks mix toward the surface's own ink, so a blend of two
14
+ // of them is at least as readable as the paler one. Sampled every 5% of
15
+ // each ramp, the default set never falls below 5.2:1 against the surface or
16
+ // its 7% primary wash in either scheme. Primary is the brand and the
17
+ // chip beside the name; success is what a check that passes wears, which is
18
+ // what ngtrue is for; info sits between them in hue, so the blue phase is
19
+ // longer and the green reads as a wave passing rather than half the word.
20
+ --wr-gradient-flow-from: var(--wr-color-primary-ink);
21
+ --wr-gradient-flow-via: var(--wr-color-info-ink), var(--wr-color-success-ink);
22
+ // One full loop. The image is two text widths, so a wave crosses the word in
23
+ // half of this: 4 s reads as a drift, not a shimmer, and the word never looks
24
+ // stuck between two colours.
25
+ --wr-gradient-flow-cycle: 8s;
26
+ // The slide is stepped, not continuous: a 100px word moves its gradient by
27
+ // 0.4px per frame at 60 fps, below a pixel, so most frames repaint for
28
+ // nothing. 120 steps per cycle is 15 repaints a second, each moving the
29
+ // image by under 2% of a ramp, which no eye reads as a jump.
30
+ --wr-gradient-flow-steps: 120;
31
+ // What the glyphs are filled with while selected: the gradient sits under
32
+ // the highlight, so the selected text needs a solid fill of its own.
33
+ --wr-gradient-flow-selected: var(--wr-color-on-surface);
34
+
35
+ // The gradient, clipped to the glyphs. The image is twice the host wide and
36
+ // closes on the colour it opened with, so under `repeat` the tile is
37
+ // continuous and one tile of travel lands on the same picture: that is the
38
+ // seam-free loop. The glyph paint goes transparent through
39
+ // `-webkit-text-fill-color`, not `color`, which a host's own colour rule
40
+ // would outrank, and which keeps the host's `color` for `currentColor`.
41
+ background-image: linear-gradient(
42
+ 90deg,
43
+ var(--wr-gradient-flow-from),
44
+ var(--wr-gradient-flow-via),
45
+ var(--wr-gradient-flow-from)
46
+ );
47
+ background-size: 200% 100%;
48
+ // rtl-ok: the keyframes below slide this; `:dir(rtl)` reverses them
49
+ background-position-x: 0%;
50
+ -webkit-background-clip: text;
51
+ background-clip: text;
52
+ -webkit-text-fill-color: transparent;
53
+
54
+ // Chrome and Safari read the fill colour here, Firefox the colour.
55
+ &::selection {
56
+ color: var(--wr-gradient-flow-selected);
57
+ -webkit-text-fill-color: var(--wr-gradient-flow-selected);
58
+ }
59
+
60
+ // The drift: declared on the block, paused, so `--run` only flips the play
61
+ // state and the phase survives a pause. Not under reduced motion, where the
62
+ // gradient stays as colour and nothing moves.
63
+ @media (prefers-reduced-motion: no-preference) and (forced-colors: none) {
64
+ animation-name: wr-gradient-flow-drift;
65
+ animation-duration: var(--wr-gradient-flow-cycle);
66
+ animation-timing-function: steps(var(--wr-gradient-flow-steps), end);
67
+ animation-iteration-count: infinite;
68
+ animation-play-state: paused;
69
+
70
+ // The wave travels the reading direction; the keyframes are physical, so
71
+ // RTL plays them backwards.
72
+ &:dir(rtl) {
73
+ animation-direction: reverse;
74
+ }
75
+
76
+ &--run {
77
+ animation-play-state: running;
78
+ }
79
+ }
80
+
81
+ // Plain text in the system colour: the UA drops the gradient image, and the
82
+ // fill has to come back with it or the glyphs stay transparent.
83
+ @media (forced-colors: active) {
84
+ background-image: none;
85
+ -webkit-text-fill-color: currentColor;
86
+ }
87
+ }
88
+
89
+ // One tile of travel. With an image twice the host wide a percentage position
90
+ // is read against the negative free space, so -200% is a slide of two host
91
+ // widths toward the inline end: exactly one tile, exactly the start picture.
92
+ // rtl-ok: background-position-x is physical by nature; `:dir(rtl)` above reverses the run
93
+ @keyframes wr-gradient-flow-drift {
94
+ from {
95
+ background-position-x: 0%;
96
+ }
97
+
98
+ to {
99
+ background-position-x: -200%;
100
+ }
101
+ }
@@ -0,0 +1,179 @@
1
+ @use '../../../theme/styles' as theme;
2
+ @use '../../../button/styles' as button-styles; // WrButton
3
+ @include theme.loaded('animations/marquee');
4
+
5
+ // `<wr-marquee>`: a row of links gliding sideways in an endless loop. The
6
+ // belt holds the list twice and one CSS animation slides it by exactly one
7
+ // copy's width, which the component measures and writes as
8
+ // `--wr-marquee-shift` with the duration beside it, so the frame the cycle
9
+ // ends on is the frame it began on. The animation is declared paused on the
10
+ // belt and `--run` only flips the play state, so a pause keeps the phase.
11
+ // Without the component (the server, reduced motion) the row is one copy,
12
+ // still, scrolling natively, under the same fade.
13
+ .wr-marquee {
14
+ // The air on each side of the dot between two names.
15
+ --wr-marquee-gap: 1.25rem;
16
+ // How far from each end an item is fully in: the width of the fade.
17
+ --wr-marquee-fade: 3rem;
18
+ // A name at rest, and under the pointer or focus. Muted prose reads the muted
19
+ // role; the active state reads primary as text, so `-ink`.
20
+ --wr-marquee-color: var(--wr-color-on-surface-muted);
21
+ --wr-marquee-color-active: var(--wr-color-primary-ink);
22
+ --wr-marquee-dot: var(--wr-border-strong);
23
+ // Which way the belt travels: toward the inline start, so names enter at
24
+ // the end of the line and leave at its start, the way the line is read.
25
+ --wr-marquee-dir: -1;
26
+ // Written by the component on the belt, not hooks: one copy's measured width
27
+ // and the time one copy takes. Reset here so a marquee inside an item
28
+ // template of another never inherits the outer belt's numbers.
29
+ --wr-marquee-shift: initial;
30
+ --wr-marquee-duration: initial;
31
+
32
+ display: flex;
33
+ align-items: center;
34
+ gap: var(--wr-space-sm);
35
+ padding-block: var(--wr-space-md);
36
+ color: var(--wr-marquee-color);
37
+ font-size: var(--wr-text-sm);
38
+ font-weight: var(--wr-font-weight-medium);
39
+
40
+ &:dir(rtl) {
41
+ --wr-marquee-dir: 1;
42
+ }
43
+
44
+ // The window the belt moves in. Scrollable by default, which is what the
45
+ // still row needs; the loop hides the overflow instead. The fade is a mask,
46
+ // symmetric, so it is the same picture in both directions. The block padding
47
+ // is room for a link's focus ring, which the overflow would otherwise clip.
48
+ &__viewport {
49
+ flex: 1 1 auto;
50
+ min-width: 0;
51
+ padding-block: 0.375rem;
52
+ overflow-x: auto;
53
+ overflow-y: hidden;
54
+ scroll-padding-inline: var(--wr-marquee-fade);
55
+ mask-image: linear-gradient(
56
+ to right,
57
+ transparent,
58
+ #000 var(--wr-marquee-fade),
59
+ #000 calc(100% - var(--wr-marquee-fade)),
60
+ transparent
61
+ );
62
+
63
+ @include theme.scrollbar;
64
+ }
65
+
66
+ &--loop:not(&--static) &__viewport {
67
+ overflow: hidden;
68
+ }
69
+
70
+ // Both copies, side by side, as wide as they are. The animation is declared
71
+ // paused here, under the loop, so `--run` only flips its play state.
72
+ &__belt {
73
+ display: flex;
74
+ width: max-content;
75
+ }
76
+
77
+ &--loop &__belt {
78
+ animation: wr-marquee-run var(--wr-marquee-duration, 60s) linear infinite paused;
79
+ }
80
+
81
+ &--run &__belt {
82
+ animation-play-state: running;
83
+ }
84
+
85
+ // Focus in the belt: no motion, and the first and last names stand clear
86
+ // of the fade, so the one with focus is whole. The same under reduced
87
+ // motion, below, from CSS alone, so the row is right before any script.
88
+ &--static &__belt {
89
+ animation: none;
90
+ padding-inline: var(--wr-marquee-fade);
91
+ }
92
+
93
+ &__track {
94
+ display: flex;
95
+ flex: none;
96
+ margin: 0;
97
+ padding: 0;
98
+ list-style: none;
99
+ white-space: nowrap;
100
+ }
101
+
102
+ &__item {
103
+ display: flex;
104
+ align-items: center;
105
+ }
106
+
107
+ // The dot between two names, decorative. Every name but the first of the
108
+ // row carries one before it, the first of the copy included, so the seam
109
+ // between the copies is spaced like any other gap.
110
+ &__item + &__item::before,
111
+ &__track--copy &__item:first-child::before {
112
+ content: '';
113
+ flex: none;
114
+ width: 3px;
115
+ height: 3px;
116
+ margin-inline: var(--wr-marquee-gap);
117
+ border-radius: 50%;
118
+ background: var(--wr-marquee-dot);
119
+ }
120
+
121
+ // An item may carry an icon before its name: the link lays the two out on
122
+ // one line with a small gap, and the icon takes the link's colour.
123
+ &__link {
124
+ display: inline-flex;
125
+ align-items: center;
126
+ gap: var(--wr-space-xs);
127
+ padding: 0.125rem 0.25rem;
128
+ border-radius: var(--wr-border-radius-sm);
129
+ color: inherit;
130
+ text-decoration: none;
131
+ transition: color var(--wr-transition-base);
132
+
133
+ &:hover,
134
+ &:focus-visible {
135
+ color: var(--wr-marquee-color-active);
136
+ }
137
+
138
+ &:focus-visible {
139
+ @include theme.focus-ring;
140
+ }
141
+ }
142
+
143
+ // The pause button. Its glyph is a bare SVG projected into the label, so the
144
+ // button cannot see an empty label and square itself the way `wr-btn` does for
145
+ // an `icon`-only button: the same square is made here, from the button's own
146
+ // hooks, so the toggle sits as any icon-only `wr-btn` of its size would.
147
+ &__toggle {
148
+ flex: none;
149
+ padding-inline: calc(var(--wr-btn-padding-y) * var(--wr-density-y, 1));
150
+ }
151
+
152
+ &__glyph {
153
+ display: inline-flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ width: var(--wr-btn-line-height);
157
+ height: var(--wr-btn-line-height);
158
+
159
+ .wr-icon__svg {
160
+ width: var(--wr-btn-icon-size);
161
+ height: var(--wr-btn-icon-size);
162
+ }
163
+ }
164
+
165
+ @media (prefers-reduced-motion: reduce) {
166
+ &__belt {
167
+ animation: none;
168
+ padding-inline: var(--wr-marquee-fade);
169
+ }
170
+ }
171
+ }
172
+
173
+ // One copy of travel. The keyframe reads the belt's own `--wr-marquee-shift`
174
+ // and the host's direction, so one set of keyframes serves both directions.
175
+ @keyframes wr-marquee-run {
176
+ to {
177
+ translate: calc(var(--wr-marquee-dir) * var(--wr-marquee-shift, 0px));
178
+ }
179
+ }
@@ -0,0 +1,77 @@
1
+ @use '../../../theme/styles' as theme;
2
+ @include theme.loaded('animations/orbit');
3
+
4
+ // `<wr-orbit>`: a short label set around a circle, like a seal,
5
+ // turning slowly, with a mark in the middle that does not turn. The ring is
6
+ // static SVG: a `<textPath>` on a circle, stretched to the circumference by
7
+ // `textLength`, so the server and a still page draw the finished, even ring
8
+ // from the markup alone. The component writes one transform on the `<svg>`
9
+ // per frame while `--run` is on the host; nothing here moves on its own.
10
+ .wr-orbit {
11
+ // The `size` input's channel. Reset on every block, so a ring projected into
12
+ // another ring's slot never inherits the outer one's size.
13
+ --wr-orbit-input-size: initial;
14
+ // The box. A square: the ring fills it and the slot sits in its middle.
15
+ --wr-orbit-size: 6rem;
16
+ // The glyphs' fill. `currentColor`, so the ring reads in the colour of the
17
+ // text around it: muted in a footer, ink in a heading, `-contrast` on a fill.
18
+ --wr-orbit-color: currentColor;
19
+ // In user units of the 100-unit drawing, so it scales with the box: 9 of
20
+ // 100 is 8.6px on a 6rem ring, the size of a seal's legend. The baseline
21
+ // circle leaves 9 units outside it; a larger font clips at the box edge.
22
+ --wr-orbit-font-size: 9px;
23
+ --wr-orbit-weight: var(--wr-font-weight-semibold);
24
+
25
+ display: inline-grid;
26
+ place-items: center;
27
+ // The `size` input first, written under its own name so an unset input
28
+ // never wipes a value the author set on the element, then the hook.
29
+ inline-size: var(--wr-orbit-input-size, var(--wr-orbit-size));
30
+ block-size: var(--wr-orbit-input-size, var(--wr-orbit-size));
31
+ // A decorative ring: a drag across the page should not pick up the legend,
32
+ // and a double-click on the seal should not highlight a word of it.
33
+ user-select: none;
34
+ -webkit-user-select: none;
35
+
36
+ // The ring and the slot share the one cell, the slot on top.
37
+ &__ring,
38
+ &__centre {
39
+ grid-area: 1 / 1;
40
+ }
41
+
42
+ &__ring {
43
+ display: block;
44
+ inline-size: 100%;
45
+ block-size: 100%;
46
+ // An outer `<svg>` is a CSS box and turns about its centre by default;
47
+ // said anyway, because the whole effect rests on it.
48
+ transform-origin: 50% 50%;
49
+ // A glyph that overhangs the drawing's edge is drawn, not cut.
50
+ overflow: visible;
51
+ }
52
+
53
+ // Only while the component turns it: a promoted layer costs memory, and a
54
+ // still ring has no reason to hold one.
55
+ &--run &__ring {
56
+ will-change: transform;
57
+ }
58
+
59
+ // The legend. The glyphs' advance is the browser's business: `textLength`
60
+ // spreads them over the circumference, so no tracking is set here, and a
61
+ // tracking set from outside would be absorbed into the same total.
62
+ // `white-space: pre`, with `xml:space` in the markup, keeps the trailing
63
+ // blank the author ends the text with: it is the gap at the seam.
64
+ &__text {
65
+ fill: var(--wr-orbit-color);
66
+ font-family: var(--wr-font-family-base);
67
+ font-size: var(--wr-orbit-font-size);
68
+ font-weight: var(--wr-orbit-weight);
69
+ text-transform: uppercase;
70
+ white-space: pre;
71
+ }
72
+
73
+ &__centre {
74
+ display: grid;
75
+ place-items: center;
76
+ }
77
+ }