@conduction/nextcloud-vue 2.78.0 → 2.80.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 (259) hide show
  1. package/dist/bundled-packages.json +0 -2
  2. package/dist/esm/bundled-packages.json +0 -2
  3. package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
  5. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
  6. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
  7. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  8. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +115 -104
  9. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +12 -2
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  13. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +39 -3
  14. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  15. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  16. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +158 -0
  17. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  18. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +157 -96
  19. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  20. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +139 -1
  21. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  22. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +140 -92
  23. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  24. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +77 -0
  25. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  26. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +5 -2
  27. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  28. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +62 -4
  29. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  30. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  31. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +85 -1
  32. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  33. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
  34. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  35. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
  36. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
  37. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +736 -0
  38. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
  39. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
  40. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
  41. package/dist/esm/components/CnFactsWidget/index.js +30 -0
  42. package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
  43. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
  44. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
  45. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +551 -0
  46. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
  47. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +183 -0
  48. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
  49. package/dist/esm/components/CnFieldListWidget/index.js +29 -0
  50. package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
  51. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +173 -5
  52. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  53. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +181 -99
  54. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  55. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +29 -11
  56. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  57. package/dist/esm/components/CnFilesBrowser/openRegisterSource.js +252 -0
  58. package/dist/esm/components/CnFilesBrowser/openRegisterSource.js.map +1 -0
  59. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +66 -18
  60. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  61. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
  62. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  63. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +18 -3
  64. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  65. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  66. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +330 -74
  67. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  68. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +34 -15
  69. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  70. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
  71. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
  72. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
  73. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
  74. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
  75. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
  76. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +100 -3
  77. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  78. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -2
  79. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  80. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
  81. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
  82. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
  83. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +3 -2
  84. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
  85. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
  86. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
  87. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
  88. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +387 -0
  89. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
  90. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +169 -0
  91. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
  92. package/dist/esm/components/CnRecordListWidget/index.js +31 -0
  93. package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
  94. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
  95. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js +1 -1
  96. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
  97. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
  98. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
  99. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
  100. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
  101. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
  102. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
  103. package/dist/esm/components/CnSectionsWidget/index.js +35 -0
  104. package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
  105. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
  106. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  107. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  108. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  109. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
  110. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  111. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +152 -8
  112. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  113. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +84 -23
  114. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  115. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
  116. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  117. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
  118. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  119. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  120. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +106 -2
  121. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  122. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +105 -53
  123. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  124. package/dist/esm/composables/useAppManifest.js +8 -3
  125. package/dist/esm/composables/useAppManifest.js.map +1 -1
  126. package/dist/esm/composables/useFormDraft.js +140 -9
  127. package/dist/esm/composables/useFormDraft.js.map +1 -1
  128. package/dist/esm/index.js +5 -0
  129. package/dist/esm/index.js.map +1 -1
  130. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
  131. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  132. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
  133. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  134. package/dist/esm/integrations/builtin/field-inspection.js +21 -0
  135. package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
  136. package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
  137. package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
  138. package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
  139. package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
  140. package/dist/esm/integrations/offline/index.js +2 -1
  141. package/dist/esm/integrations/offline/index.js.map +1 -1
  142. package/dist/esm/integrations/offline/offlineDb.js +6 -1
  143. package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
  144. package/dist/esm/integrations/offline/syncReplayService.js +8 -2
  145. package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
  146. package/dist/esm/l10n/en.json.js +72 -1
  147. package/dist/esm/l10n/en.json.js.map +1 -1
  148. package/dist/esm/l10n/nl.json.js +120 -2
  149. package/dist/esm/l10n/nl.json.js.map +1 -1
  150. package/dist/esm/nextcloud-vue.css +1314 -74
  151. package/dist/esm/utils/boardDate.js +193 -0
  152. package/dist/esm/utils/boardDate.js.map +1 -0
  153. package/dist/esm/utils/detailActionModel.js +60 -3
  154. package/dist/esm/utils/detailActionModel.js.map +1 -1
  155. package/dist/esm/utils/dynamicProperties.js +5 -1
  156. package/dist/esm/utils/dynamicProperties.js.map +1 -1
  157. package/dist/esm/utils/fillTemplate.js +114 -0
  158. package/dist/esm/utils/fillTemplate.js.map +1 -0
  159. package/dist/esm/utils/libraryWidgetKeys.js +4 -0
  160. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  161. package/dist/esm/utils/queryPresets.js +96 -0
  162. package/dist/esm/utils/queryPresets.js.map +1 -0
  163. package/dist/esm/utils/resolveFilterTokens.js +11 -0
  164. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  165. package/dist/esm/utils/schema.js +21 -0
  166. package/dist/esm/utils/schema.js.map +1 -1
  167. package/dist/esm/utils/sentinelTokens.js +3 -3
  168. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  169. package/dist/esm/utils/validateManifestV2.compiled.js +57 -6
  170. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  171. package/dist/esm/utils/widgetDispatch.js +7 -1
  172. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  173. package/dist/nextcloud-vue.cjs.js +14278 -8169
  174. package/dist/nextcloud-vue.cjs.js.map +2 -2
  175. package/dist/nextcloud-vue.css +1314 -74
  176. package/l10n/en.json +72 -1
  177. package/l10n/nl.json +120 -2
  178. package/package.json +1 -1
  179. package/scripts/build-validators.js +26 -0
  180. package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
  181. package/src/components/CnActionsBar/CnActionsBar.md +4 -0
  182. package/src/components/CnActionsBar/CnActionsBar.vue +83 -42
  183. package/src/components/CnAppRoot/CnAppRoot.vue +12 -2
  184. package/src/components/CnBannerWidget/CnBannerWidget.vue +39 -3
  185. package/src/components/CnCellRenderer/CnCellRenderer.vue +306 -2
  186. package/src/components/CnDashboardPage/CnDashboardPage.vue +219 -4
  187. package/src/components/CnDataTable/CnDataTable.md +2 -0
  188. package/src/components/CnDataTable/CnDataTable.vue +82 -2
  189. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  190. package/src/components/CnDetailPage/CnDetailPage.vue +63 -3
  191. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +127 -1
  192. package/src/components/CnFactsWidget/CnFactsWidget.vue +1050 -0
  193. package/src/components/CnFactsWidget/index.js +29 -0
  194. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +746 -0
  195. package/src/components/CnFieldListWidget/index.js +28 -0
  196. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +232 -11
  197. package/src/components/CnFilesBrowser/filesBrowser.js +43 -2
  198. package/src/components/CnFilesBrowser/index.js +1 -0
  199. package/src/components/CnFilesBrowser/openRegisterSource.js +248 -0
  200. package/src/components/CnFormDialog/CnFormDialog.md +9 -3
  201. package/src/components/CnFormDialog/CnFormDialog.vue +70 -22
  202. package/src/components/CnFormPage/CnFormPage.vue +18 -3
  203. package/src/components/CnIndexPage/CnIndexPage.vue +281 -9
  204. package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
  205. package/src/components/CnObjectSidebar/CnFilesTab.vue +103 -4
  206. package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
  207. package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +3 -2
  208. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +603 -0
  209. package/src/components/CnRecordListWidget/index.js +30 -0
  210. package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +1 -1
  211. package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
  212. package/src/components/CnSectionsWidget/index.js +34 -0
  213. package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
  214. package/src/components/CnStatWidget/CnStatWidget.vue +1 -1
  215. package/src/components/CnTabsWidget/CnTabsWidget.vue +214 -9
  216. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +4 -0
  217. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
  218. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +188 -4
  219. package/src/components/index.js +5 -1
  220. package/src/composables/__tests__/useFormDraft.spec.js +69 -0
  221. package/src/composables/useAppManifest.js +8 -3
  222. package/src/composables/useFormDraft.js +139 -8
  223. package/src/css/form-field.css +14 -0
  224. package/src/css/index-page.css +71 -0
  225. package/src/css/kpi-card.css +32 -0
  226. package/src/css/look-board-detail.css +87 -0
  227. package/src/css/look-board-index.css +143 -14
  228. package/src/css/look-board.css +114 -2
  229. package/src/css/table.css +56 -0
  230. package/src/index.js +8 -0
  231. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
  232. package/src/integrations/builtin/field-inspection.js +21 -0
  233. package/src/integrations/offline/checklistSubmission.js +137 -0
  234. package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
  235. package/src/integrations/offline/index.js +3 -0
  236. package/src/integrations/offline/offlineDb.js +6 -1
  237. package/src/integrations/offline/syncReplayService.js +8 -2
  238. package/src/schemas/app-manifest-v2.schema.json +149 -5
  239. package/src/utils/boardDate.js +189 -0
  240. package/src/utils/detailActionModel.js +59 -2
  241. package/src/utils/dynamicProperties.js +5 -1
  242. package/src/utils/fillTemplate.js +110 -0
  243. package/src/utils/libraryWidgetKeys.js +4 -0
  244. package/src/utils/queryPresets.js +93 -0
  245. package/src/utils/resolveFilterTokens.js +11 -0
  246. package/src/utils/schema.js +21 -0
  247. package/src/utils/sentinelTokens.js +3 -3
  248. package/src/utils/validateManifestV2.compiled.js +57 -2
  249. package/src/utils/widgetDispatch.js +7 -1
  250. package/dist/esm/_virtual/equal.js +0 -4
  251. package/dist/esm/_virtual/equal.js.map +0 -1
  252. package/dist/esm/_virtual/ucs2length.js +0 -4
  253. package/dist/esm/_virtual/ucs2length.js.map +0 -1
  254. package/dist/esm/node_modules/ajv/dist/runtime/equal.js +0 -9
  255. package/dist/esm/node_modules/ajv/dist/runtime/equal.js.map +0 -1
  256. package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js +0 -25
  257. package/dist/esm/node_modules/ajv/dist/runtime/ucs2length.js.map +0 -1
  258. package/dist/esm/node_modules/fast-deep-equal/index.js +0 -47
  259. package/dist/esm/node_modules/fast-deep-equal/index.js.map +0 -1
@@ -79,9 +79,14 @@
79
79
  * counterpart default to one.
80
80
  */
81
81
  .cn-look-board {
82
- /* Page content area: padding, max width, gap between blocks. */
82
+ /* Page content area: padding, max width, gap between blocks. The content
83
+ spans the whole content area (screens-one-scroller-parity): grids grow
84
+ with the window and shrink only when the sidebar takes its share. A
85
+ 1240px cap left dead space right of the content, and on a dashboard,
86
+ which scrolled itself, put the scrollbar beside the content instead of
87
+ at the window edge. */
83
88
  --cn-board-content-padding: 24px 28px;
84
- --cn-board-content-max-width: 1240px;
89
+ --cn-board-content-max-width: none;
85
90
  --cn-board-section-gap: 20px;
86
91
  /* Buttons and inputs. */
87
92
  --cn-board-control-height: 40px;
@@ -121,6 +126,15 @@
121
126
  gap: var(--cn-board-section-gap);
122
127
  }
123
128
 
129
+ /* One scroller: the content area. CnDashboardPage scrolls itself
130
+ (`height: 100%; overflow-y: auto`), which nested a second scrollbar inside
131
+ NcAppContent's; under the board look the page grows with its widgets and
132
+ NcAppContent, which already spans to the window edge, scrolls it. */
133
+ .cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) {
134
+ height: auto;
135
+ overflow-y: visible;
136
+ }
137
+
124
138
  .cn-look-board .cn-index-page:not(.cn-look-nextcloud *) .cn-page-header,
125
139
  .cn-look-board .cn-settings-page:not(.cn-look-nextcloud *) .cn-page-header,
126
140
  .cn-look-board .cn-index-page:not(.cn-look-nextcloud *) .cn-index-page__below-header,
@@ -213,6 +227,14 @@
213
227
  margin-inline-start: -264px;
214
228
  }
215
229
 
230
+ /* The navigation draws the line between it and the content. NcContent draws a
231
+ second one on the content while the navigation is open, which doubled the
232
+ line and put the page 1px further from the navigation than the board's 28px.
233
+ Outranks NcContent's rule (six classes) with seven. */
234
+ .cn-look-board .app-navigation[data-testid="cn-nav"]:not(.app-navigation--closed):not(.app-navigation--close) ~ .app-content.app-content {
235
+ border-inline-start: none;
236
+ }
237
+
216
238
  .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__content {
217
239
  box-sizing: border-box;
218
240
  gap: 20px;
@@ -222,6 +244,52 @@
222
244
  .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list {
223
245
  height: auto;
224
246
  flex: 1 1 auto;
247
+ margin: 0;
248
+ gap: 2px;
249
+ }
250
+
251
+ /* No scrollbars inside the navigation (screens-one-scroller-parity).
252
+ NcAppNavigation gives the region above the list `overflow-y: scroll`, an
253
+ always-on track (with arrow buttons on classic scrollbars) beside the
254
+ primary action that has nothing to scroll. It takes its content's height
255
+ instead. A menu taller than the window still scrolls (wheel, touch, focus),
256
+ without drawing a bar of its own; the one visible scrollbar is the page's. */
257
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body:not(.app-navigation__body--no-list) {
258
+ flex-shrink: 0;
259
+ overflow: visible;
260
+ }
261
+
262
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list,
263
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body--no-list {
264
+ scrollbar-width: none;
265
+ }
266
+
267
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list::-webkit-scrollbar,
268
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__body--no-list::-webkit-scrollbar {
269
+ display: none;
270
+ }
271
+
272
+ /* The board's vertical rhythm (AppZijbalk): the primary action 20px from the
273
+ top, the list 20px under it, entries 2px apart. An empty search slot is a
274
+ flex child too and pushed everything 20px down, so it goes. */
275
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__search:empty {
276
+ display: none;
277
+ }
278
+
279
+ /* A caption is a 12px label with 6px under it, 20px after the group above
280
+ and 2px before its first entry. NcAppNavigationCaption gives its name a
281
+ 15px font on a 34px line, which made it 44px high. */
282
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation__list > .app-navigation-caption:not(:first-child) {
283
+ margin-top: 18px;
284
+ }
285
+
286
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-caption .app-navigation-caption__name {
287
+ margin: 0;
288
+ padding: 0;
289
+ font-size: inherit;
290
+ font-weight: inherit;
291
+ line-height: normal;
292
+ color: inherit;
225
293
  }
226
294
 
227
295
  .cn-look-board .app-navigation[data-testid="cn-nav"] .app-navigation-entry,
@@ -306,6 +374,43 @@
306
374
  font-size: 15px;
307
375
  }
308
376
 
377
+ /* The footer of the board: Help and Advanced as two 40px rows at weight 400,
378
+ 2px apart. The Help row kept the 42px of a list entry, and the Advanced
379
+ foldout drew a 34px button inside 4px of padding, 20px under Help. */
380
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list {
381
+ gap: 2px;
382
+ }
383
+
384
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list .app-navigation-entry,
385
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list .app-navigation-entry-link {
386
+ min-height: 40px;
387
+ font-weight: 400;
388
+ }
389
+
390
+ .cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] {
391
+ padding: 0;
392
+ }
393
+
394
+ .cn-look-board .app-navigation[data-testid="cn-nav"] .cn-app-nav__footer-list + [data-testid="cn-nav-settings"] {
395
+ margin-top: -18px;
396
+ }
397
+
398
+ .cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] > :first-child {
399
+ margin: 0;
400
+ }
401
+
402
+ .cn-look-board .app-navigation[data-testid="cn-nav"] [data-testid="cn-nav-settings"] > :first-child .button-vue {
403
+ box-sizing: border-box;
404
+ width: 100%;
405
+ height: 40px;
406
+ min-height: 40px;
407
+ padding: 0 10px;
408
+ border-radius: 8px;
409
+ font-size: 15px;
410
+ font-weight: 400;
411
+ justify-content: flex-start;
412
+ }
413
+
309
414
  /* The card above the footer, pushed down. */
310
415
  .cn-look-board .cn-app-nav__card {
311
416
  order: 0;
@@ -510,6 +615,13 @@
510
615
  .cn-look-board .cn-status-badge--primary:not(.cn-status-badge--solid):not(.cn-look-nextcloud *) {
511
616
  color: var(--color-primary-element-light-text);
512
617
  }
618
+
619
+ /* ---- Date and age cells (screens-cell-date-parity) ---------------------- */
620
+ /* The board sets every waiting time ("3 dagen", "4 uur") in weight 600; a
621
+ late one is red through its variant class. */
622
+ .cn-look-board .cn-cell-renderer__age:not(.cn-look-nextcloud *) {
623
+ font-weight: 600;
624
+ }
513
625
  /*
514
626
  * The board dialog (screens-dialog-parity, canon section 5).
515
627
  *
@@ -797,6 +909,20 @@
797
909
  min-height: var(--cn-field-height);
798
910
  }
799
911
 
912
+ /* NcTextField draws its input inside `.input-field__main-wrapper`, which has a
913
+ FIXED height (`--default-clickable-area`, 34px on Nextcloud 34) and a 2px
914
+ padding ring for the focus outline. The min-height above makes the input
915
+ 40px, so without this the input overflowed its wrapper by 6px and the help
916
+ line under it, which starts at the wrapper's bottom edge, sat behind the
917
+ input's lower border. NcSelect grows with its content, which is why only
918
+ plain inputs showed it. The wrapper now takes the field height plus its
919
+ padding ring, so the input fits and the help line starts below it.
920
+ @spec openspec/changes/form-draft-on-change-and-help-text-spacing/specs/form-draft-on-change-and-help-text-spacing/spec.md#requirement-help-text-starts-below-every-input */
921
+ .cn-look-board .cn-form-dialog__field .input-field__main-wrapper,
922
+ .cn-look-board .cn-form-page__field .input-field__main-wrapper {
923
+ height: calc(var(--cn-field-height) + 2 * var(--border-width-input-focused, 2px));
924
+ }
925
+
800
926
  .cn-look-board .cn-form-dialog__field textarea,
801
927
  .cn-look-board .cn-form-page__field textarea {
802
928
  padding: 10px 12px;
@@ -1262,16 +1388,27 @@
1262
1388
  margin-inline-start: 0;
1263
1389
  }
1264
1390
 
1265
- /* The first of Save view, Filter and the view switch takes the free space, so
1266
- the three sit at the end of row 1. */
1267
- .cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > :is(.cn-saved-views__save, .cn-actions-bar__filter-button, .cn-actions-bar__view-toggle) {
1391
+ /* The first of Save view and the Filter + view switch unit takes the free
1392
+ space (the board's `flex: 1` spacer), so they sit at the end of row 1.
1393
+ When the line is full the unit wraps as one to the START of the next line
1394
+ while Save view stays at the end of row 1 (DqZaken); without Save view the
1395
+ unit sits at the end of row 1 (PqTickets, PqLeads, PtPortals). */
1396
+ .cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > :is(.cn-saved-views__save, .cn-actions-bar__view-controls) {
1268
1397
  margin-inline-start: auto;
1269
1398
  }
1270
1399
 
1271
- .cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > :is(.cn-saved-views__save, .cn-actions-bar__filter-button, .cn-actions-bar__view-toggle) ~ :is(.cn-saved-views__save, .cn-actions-bar__filter-button, .cn-actions-bar__view-toggle) {
1400
+ .cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--views > .cn-saved-views__save ~ .cn-actions-bar__view-controls {
1272
1401
  margin-inline-start: 0;
1273
1402
  }
1274
1403
 
1404
+ .cn-look-board .cn-actions-bar--board .cn-actions-bar__view-controls {
1405
+ display: flex;
1406
+ flex: 0 0 auto;
1407
+ flex-wrap: nowrap;
1408
+ align-items: center;
1409
+ gap: 8px;
1410
+ }
1411
+
1275
1412
  /* Row 2: the search field and the active filters on a line of their own. */
1276
1413
  .cn-look-board .cn-actions-bar--board > .cn-actions-bar__row--search {
1277
1414
  display: flex;
@@ -1357,16 +1494,39 @@
1357
1494
  color: var(--color-primary-element-text);
1358
1495
  }
1359
1496
 
1360
- /* Save view: 34px, radius 17, on the light primary tint. */
1497
+ /* Save view: a ghost button, 34px, radius 17, no border, on the light primary
1498
+ tint, a 14px icon 6px before the label, on one line. */
1361
1499
  .cn-look-board .cn-saved-views__save .button-vue {
1362
1500
  min-height: 34px;
1363
1501
  height: 34px;
1364
- padding: 0 14px;
1502
+ padding: 0 12px;
1503
+ border: 0;
1365
1504
  border-radius: 17px;
1366
1505
  background: var(--color-primary-element-light);
1367
1506
  color: var(--color-primary-element-light-text);
1368
1507
  font-size: 13px;
1369
1508
  font-weight: 600;
1509
+ white-space: nowrap;
1510
+ }
1511
+
1512
+ .cn-look-board .cn-saved-views__save .button-vue:hover {
1513
+ background: var(--color-primary-element-light-hover);
1514
+ }
1515
+
1516
+ .cn-look-board .cn-saved-views__save .button-vue .button-vue__wrapper {
1517
+ gap: 6px;
1518
+ }
1519
+
1520
+ .cn-look-board .cn-saved-views__save .button-vue .button-vue__icon {
1521
+ width: auto;
1522
+ min-width: 0;
1523
+ height: auto;
1524
+ min-height: 0;
1525
+ }
1526
+
1527
+ .cn-look-board .cn-saved-views__save .button-vue .button-vue__text {
1528
+ margin: 0;
1529
+ padding: 0;
1370
1530
  }
1371
1531
 
1372
1532
  /* Filter: a labelled secondary button, 36px, radius 8, with the active count. */
@@ -1422,6 +1582,15 @@
1422
1582
  color: var(--color-main-text);
1423
1583
  }
1424
1584
 
1585
+ /* A segment the page cannot open: drawn, as the boards do, but faded and inert. */
1586
+ .cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled,
1587
+ .cn-look-board .cn-actions-bar--board .cn-actions-bar__view-toggle .cn-actions-bar__view-toggle-btn--disabled:hover {
1588
+ background: transparent !important;
1589
+ color: var(--color-text-maxcontrast);
1590
+ opacity: 0.5;
1591
+ cursor: not-allowed;
1592
+ }
1593
+
1425
1594
  /* The search field: 40px, radius 8, not a pill. */
1426
1595
  .cn-look-board .cn-actions-bar--board .cn-actions-bar__search {
1427
1596
  flex: 1 1 260px;
@@ -1569,6 +1738,48 @@
1569
1738
  border-bottom: 0;
1570
1739
  }
1571
1740
 
1741
+ /* The table fits its card (screens-index-table-fit-parity). Under the auto
1742
+ layout every one-line cell asked for its whole text up to the 22rem cap, so
1743
+ seven text columns made a 1500px table in a 1118px card at a 1440px
1744
+ viewport: the last columns and the row menus sat past the card's edge. The
1745
+ fixed layout shares the card's width: the selection and menu columns keep
1746
+ their own width, the first data column takes 18%, the others split the
1747
+ rest, and a value that does not fit is cut with an ellipsis (its full text
1748
+ stays in the cell's tooltip). A column's own `width` still wins. */
1749
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table {
1750
+ table-layout: fixed;
1751
+ width: 100%;
1752
+ }
1753
+
1754
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title {
1755
+ width: 18%;
1756
+ }
1757
+
1758
+ /* The board's data cells sit 12px apart (PqTickets), the first one 18px from
1759
+ the selection column; the selection and menu columns keep 16px. */
1760
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon),
1761
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td:not(.cn-table-col--checkbox):not(.cn-table-col--actions):not(.cn-table-col--icon) {
1762
+ padding-inline: 12px;
1763
+ }
1764
+
1765
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th.cn-table-head--title,
1766
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td.cn-table-col--title {
1767
+ padding-inline-start: 18px;
1768
+ }
1769
+
1770
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table td > .cn-cell-renderer {
1771
+ display: block;
1772
+ min-width: 0;
1773
+ overflow: hidden;
1774
+ text-overflow: ellipsis;
1775
+ white-space: nowrap;
1776
+ }
1777
+
1778
+ /* A narrow header cuts its label, not its filter funnel. */
1779
+ .cn-look-board .cn-index-page__main--table .cn-table-container--board .cn-data-table th .cn-table-header__sort:has(~ .cn-table-header__filter) {
1780
+ max-width: calc(100% - 26px);
1781
+ }
1782
+
1572
1783
  /* The selection column: 28px, 18px checkboxes. */
1573
1784
  .cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox {
1574
1785
  box-sizing: content-box;
@@ -1598,6 +1809,29 @@
1598
1809
  text-decoration: none;
1599
1810
  }
1600
1811
 
1812
+ /* Only the title is underlined (DqZaken). An underline set on the cell
1813
+ reaches every in-flow child whatever its own text-decoration, so the
1814
+ secondary lines become inline blocks on a line of their own: an atomic
1815
+ inline box is the one thing the underline does not reach. */
1816
+ .cn-look-board .cn-table-container--board .cn-data-table td.cn-table-col--title .cn-table-cell__secondary {
1817
+ display: inline-block;
1818
+ width: 100%;
1819
+ vertical-align: top;
1820
+ }
1821
+
1822
+ /* `rowTitle: "plain"` (PqTickets, OcPublicaties): the title is bold text in
1823
+ the main text colour without an underline, the secondary line 13px muted,
1824
+ 2px under it. The row stays clickable through its stretched row link. */
1825
+ .cn-look-board .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title {
1826
+ font-weight: 700;
1827
+ text-decoration: none;
1828
+ }
1829
+
1830
+ .cn-look-board .cn-table-container--board.cn-table-container--title-plain .cn-data-table td.cn-table-col--title .cn-table-cell__secondary {
1831
+ margin-top: 2px;
1832
+ font-size: 13px;
1833
+ }
1834
+
1601
1835
  /* A status pill: 3px 10px, radius 12, 13px weight 600. The colours stay the
1602
1836
  status colour map's. */
1603
1837
  .cn-look-board .cn-table-container--board .cn-data-table .cn-status-badge {
@@ -1620,15 +1854,36 @@
1620
1854
  --default-clickable-area: 34px;
1621
1855
  }
1622
1856
 
1857
+ /* The row menu: a 34px square, three dots, a grey border on the main
1858
+ background (DqZaken, PqTickets). A theme that styles every secondary button
1859
+ with `!important` (the nldesign theme: a primary border, 8px 16px padding,
1860
+ `min-width: max-content`) would otherwise turn it into a 64px wide button
1861
+ with a blue border, so the board values are `!important` too. */
1862
+ .cn-look-board .cn-row-actions--board .button-vue,
1863
+ .cn-look-board .cn-row-actions--board .button-vue:hover,
1864
+ .cn-look-board .cn-row-actions--board .button-vue:focus {
1865
+ box-sizing: border-box !important;
1866
+ width: 34px !important;
1867
+ min-width: 34px !important;
1868
+ height: 34px !important;
1869
+ min-height: 34px !important;
1870
+ padding: 0 !important;
1871
+ border: 1px solid var(--color-border-dark) !important;
1872
+ border-radius: 8px !important;
1873
+ color: var(--cn-board-text-soft) !important;
1874
+ }
1875
+
1623
1876
  .cn-look-board .cn-row-actions--board .button-vue {
1624
- width: 34px;
1625
- min-width: 34px;
1626
- height: 34px;
1627
- min-height: 34px;
1628
- padding: 0;
1629
- border: 1px solid var(--color-border-dark);
1630
- border-radius: 8px;
1631
- background: var(--color-main-background);
1877
+ background: var(--color-main-background) !important;
1878
+ }
1879
+
1880
+ .cn-look-board .cn-row-actions--board .button-vue:hover {
1881
+ background: var(--color-background-hover) !important;
1882
+ }
1883
+
1884
+ .cn-look-board .cn-row-actions--board .button-vue:focus-visible {
1885
+ outline: 2px solid var(--color-main-text);
1886
+ outline-offset: 2px;
1632
1887
  }
1633
1888
 
1634
1889
  /* ------------------------------------------------------------------ footer */
@@ -2188,6 +2443,53 @@
2188
2443
  min-width: 0;
2189
2444
  }
2190
2445
 
2446
+ /* Fit to the container (CnDataTable's `fitWidth`, on in CnWidgetObjectTable).
2447
+
2448
+ In a narrow tile the auto layout made the table as wide as its one-line
2449
+ cells, so it ran past the tile and clipped the trailing column (a date).
2450
+ Here every column but one takes the width of its content (`width: 1%` asks
2451
+ for as little as the content allows), and the grow column takes what is
2452
+ left. `max-width: 0` is what lets that column go below its content's width:
2453
+ the table no longer counts its text, so the text is cut with an ellipsis
2454
+ instead of widening the table. The full value stays in the cell's tooltip. */
2455
+ .cn-data-table--fit {
2456
+ width: 100%;
2457
+ }
2458
+
2459
+ .cn-data-table--fit th,
2460
+ .cn-data-table--fit td {
2461
+ width: 1%;
2462
+ }
2463
+
2464
+ .cn-data-table--fit th.cn-table-col--grow,
2465
+ .cn-data-table--fit td.cn-table-col--grow {
2466
+ width: auto;
2467
+ min-width: 0;
2468
+ max-width: 0;
2469
+ overflow: hidden;
2470
+ text-overflow: ellipsis;
2471
+ white-space: nowrap;
2472
+ }
2473
+
2474
+ /* The secondary line of the growing column ("2026-0004" under a case title)
2475
+ is a line of its own with its own ellipsis. The cell does not wrap, so in
2476
+ the board look, where the secondary line is an inline block (the title
2477
+ underline cannot reach an atomic inline box), it stayed on the title's line
2478
+ and ran out of the tile. A full-width float is a block (computed `display:
2479
+ block`) that always starts under the line before it, and, being out of the
2480
+ flow, the cell's underline does not reach it either. The cell is a table
2481
+ cell, which contains its floats, so the row grows to hold the line.
2482
+ @spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-the-secondary-line-of-a-narrow-tables-growing-column-sits-under-the-value */
2483
+ .cn-data-table.cn-data-table--fit td.cn-table-col--grow .cn-table-cell__secondary {
2484
+ float: inline-start;
2485
+ clear: both;
2486
+ box-sizing: border-box;
2487
+ width: 100%;
2488
+ overflow: hidden;
2489
+ text-overflow: ellipsis;
2490
+ white-space: nowrap;
2491
+ }
2492
+
2191
2493
  .cn-data-table th {
2192
2494
  background: var(--color-background-dark);
2193
2495
  font-weight: 500;
@@ -2536,6 +2838,15 @@
2536
2838
  color: var(--color-text-maxcontrast);
2537
2839
  }
2538
2840
 
2841
+ /* The empty row holds a sentence (the empty text, or why a lens cannot
2842
+ answer), not a cell value: it wraps instead of being cut to one line. The
2843
+ selector carries the table class so it outranks the one-line cell rule. */
2844
+ .cn-data-table .cn-table-empty td {
2845
+ max-width: none;
2846
+ white-space: normal;
2847
+ overflow-wrap: anywhere;
2848
+ }
2849
+
2539
2850
  /* ========================================
2540
2851
  Backwards compatibility aliases
2541
2852
  (legacy OpenRegister CSS class names)
@@ -3377,6 +3688,38 @@ a.cn-kpi-card--stacked:focus-visible {
3377
3688
  font-weight: 400;
3378
3689
  }
3379
3690
 
3691
+ /* A caption on a line of its own wraps, up to two lines (DqDashboard: "haalden
3692
+ hun termijn, naar doorlooptijd" runs over two lines in a narrow tile). The
3693
+ one-line rule of `.cn-kpi-card__label` is for a caption BESIDE the number,
3694
+ where a second line would push the tile taller; this line has the width of
3695
+ the tile to itself. The clamp is safe here because the element is a plain
3696
+ span, not a flex row (compare the title note above).
3697
+ @spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-a-kpi-tiles-caption-and-board-label-wrap-to-two-lines */
3698
+ .cn-kpi-card--stacked .cn-kpi-card__caption-line {
3699
+ display: -webkit-box;
3700
+ -webkit-box-orient: vertical;
3701
+ -webkit-line-clamp: 2;
3702
+ line-clamp: 2;
3703
+ white-space: normal;
3704
+ overflow-wrap: break-word;
3705
+ }
3706
+
3707
+ /* Board look: the label wraps too, up to two lines, beside its icon badge
3708
+ ("Afgehandeld deze maand"). The clamp sits on the label's own span
3709
+ (`cn-kpi-card__title-text`), not on the title row, which stays the flex row
3710
+ that carries the badge or the range select. */
3711
+ .cn-kpi-card--board .cn-kpi-card__title-text {
3712
+ flex: 1 1 auto;
3713
+ min-width: 0;
3714
+ display: -webkit-box;
3715
+ -webkit-box-orient: vertical;
3716
+ -webkit-line-clamp: 2;
3717
+ line-clamp: 2;
3718
+ overflow: hidden;
3719
+ white-space: normal;
3720
+ overflow-wrap: break-word;
3721
+ }
3722
+
3380
3723
  /* The 18px glyph before the label, drawn only on a link tile. */
3381
3724
  .cn-kpi-card--board .cn-kpi-card__title {
3382
3725
  display: flex;
@@ -4669,6 +5012,77 @@ a.cn-kpi-card--board * {
4669
5012
  color: var(--color-text-maxcontrast);
4670
5013
  font-size: 0.9em;
4671
5014
  }
5015
+
5016
+ /* An index page with cards beside its list (`sidePanel`,
5017
+ screens-index-stat-row): the header rows span the page, the toolbar and the
5018
+ list take the first column and the side panel the second (300px, 20px
5019
+ apart), spanning both. Every other child (dialogs, the inline sidebar) sits
5020
+ in a zero-height area after them. The list row is the flexible one, so a
5021
+ side panel taller than the toolbar never opens a gap under the toolbar.
5022
+ Below 1024px the panel moves above the toolbar. */
5023
+ .cn-index-page--with-side-panel {
5024
+ display: grid;
5025
+ grid-template-columns: minmax(0, 1fr) var(--cn-index-side-panel-width, 300px);
5026
+ grid-template-rows: auto auto auto auto minmax(0, 1fr) auto;
5027
+ grid-template-areas:
5028
+ "head head"
5029
+ "below below"
5030
+ "stats stats"
5031
+ "bar side"
5032
+ "body side"
5033
+ "extra extra";
5034
+ column-gap: 20px;
5035
+ align-content: start;
5036
+ }
5037
+
5038
+ .cn-index-page--with-side-panel > * {
5039
+ grid-area: extra;
5040
+ min-width: 0;
5041
+ }
5042
+
5043
+ .cn-index-page--with-side-panel > :first-child {
5044
+ grid-area: head;
5045
+ }
5046
+
5047
+ .cn-index-page--with-side-panel > .cn-index-page__below-header {
5048
+ grid-area: below;
5049
+ }
5050
+
5051
+ .cn-index-page--with-side-panel > .cn-index-page__stat-row {
5052
+ grid-area: stats;
5053
+ }
5054
+
5055
+ .cn-index-page--with-side-panel > .cn-actions-bar {
5056
+ grid-area: bar;
5057
+ }
5058
+
5059
+ .cn-index-page--with-side-panel > .cn-index-page__body {
5060
+ grid-area: body;
5061
+ }
5062
+
5063
+ .cn-index-page--with-side-panel > .cn-index-page__side-panel {
5064
+ grid-area: side;
5065
+ align-self: start;
5066
+ }
5067
+
5068
+ @media (max-width: 1024px) {
5069
+ .cn-index-page--with-side-panel {
5070
+ grid-template-columns: minmax(0, 1fr);
5071
+ grid-template-areas:
5072
+ "head"
5073
+ "below"
5074
+ "stats"
5075
+ "side"
5076
+ "bar"
5077
+ "body"
5078
+ "extra";
5079
+ grid-template-rows: auto auto auto auto auto minmax(0, 1fr) auto;
5080
+ }
5081
+
5082
+ .cn-index-page--with-side-panel > .cn-index-page__side-panel {
5083
+ margin-bottom: 20px;
5084
+ }
5085
+ }
4672
5086
  /* CnIndexSidebar — NcAppSidebar wrapper styles */
4673
5087
 
4674
5088
  /* Tab content: limit height to container so overflow shows a scrollbar */
@@ -5667,6 +6081,61 @@ a.cn-kpi-card--board * {
5667
6081
  margin-bottom: 0;
5668
6082
  }
5669
6083
 
6084
+ /* The breadcrumb is a line of 14px text between the pills and the meta, as
6085
+ the boards draw it (screens-detail-header-row-parity). NcBreadcrumbs grows to
6086
+ the full row and draws each crumb as a 34px tertiary button, which pushed the
6087
+ pills above it and the meta under it. The doubled class outranks its scoped
6088
+ rules. */
6089
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs.cn-detail-page__breadcrumbs {
6090
+ flex: 0 1 auto;
6091
+ height: auto;
6092
+ min-height: 0;
6093
+ min-width: 0;
6094
+ width: auto;
6095
+ }
6096
+
6097
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .breadcrumb__crumbs {
6098
+ gap: 8px;
6099
+ margin: 0;
6100
+ min-height: 0;
6101
+ padding: 0;
6102
+ vertical-align: middle;
6103
+ }
6104
+
6105
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb.vue-crumb {
6106
+ gap: 8px;
6107
+ height: auto;
6108
+ min-height: 0;
6109
+ min-width: 0;
6110
+ }
6111
+
6112
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue.button-vue {
6113
+ background: transparent;
6114
+ border: 0;
6115
+ font-size: 14px;
6116
+ font-weight: 400;
6117
+ height: auto;
6118
+ min-height: 0;
6119
+ min-width: 0;
6120
+ padding: 0;
6121
+ }
6122
+
6123
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue__text {
6124
+ font-weight: inherit;
6125
+ line-height: 20px;
6126
+ padding: 0;
6127
+ }
6128
+
6129
+ /* The list is the link; the record's own crumb is plain muted text. */
6130
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb .button-vue[aria-current='page'] {
6131
+ color: var(--color-text-maxcontrast);
6132
+ cursor: default;
6133
+ }
6134
+
6135
+ .cn-look-board .cn-detail-page__header-row2 .cn-detail-page__breadcrumbs .vue-crumb__separator {
6136
+ margin: 0;
6137
+ }
6138
+
5670
6139
  .cn-look-board .cn-detail-page__header-dot,
5671
6140
  .cn-look-board .cn-detail-page__header-meta {
5672
6141
  color: var(--color-text-maxcontrast);
@@ -5692,6 +6161,16 @@ a.cn-kpi-card--board * {
5692
6161
  gap: 20px;
5693
6162
  }
5694
6163
 
6164
+ /* GridStack insets every cell by its 12px margin, the outer edge included, so
6165
+ the tab strip started 12px below the top of the body column and stopped 12px
6166
+ short of its end, while the side column started at the top. Pulling the grid
6167
+ out by that margin puts its first card on the column's edges: the side column
6168
+ is level with the strip, and the strip ends where the body column ends. */
6169
+ .cn-look-board.cn-detail-page--with-side > .cn-detail-page__body > .cn-detail-page__grid {
6170
+ margin: -12px;
6171
+ width: auto;
6172
+ }
6173
+
5695
6174
  /* ---- Folder tabs ------------------------------------------------------- */
5696
6175
 
5697
6176
  /* The strip draws no line of its own (design-system pull request 147). The card under it
@@ -5799,6 +6278,22 @@ a.cn-kpi-card--board * {
5799
6278
  border-radius: 0;
5800
6279
  }
5801
6280
 
6281
+ /* A tab that holds a stack (`widgetIds`, screens-relation-pages): the panel
6282
+ draws no frame and no padding; each widget is its own card. The first card
6283
+ joins the open tab (the first-card rule above), the next ones stand 20px
6284
+ apart, as the Overzicht of DqContact and PqOrganisatie draws them. */
6285
+ .cn-look-board .cn-tabs--board.cn-tabs-widget__tabs .cn-tabs__content:has(> .cn-tab:not([hidden]) > .cn-tabs-widget__stack) {
6286
+ background: transparent;
6287
+ border: 0;
6288
+ border-radius: 0;
6289
+ padding: 0;
6290
+ }
6291
+
6292
+ /* The stack's next cards are whole cards, not joined to the strip. */
6293
+ .cn-look-board .cn-tabs--board .cn-tabs__content .cn-tab .cn-tabs-widget__stack-item .cn-widget-wrapper {
6294
+ border-radius: var(--cn-board-card-radius);
6295
+ }
6296
+
5802
6297
  /* ---- Body cards and side cards ----------------------------------------- */
5803
6298
 
5804
6299
  .cn-look-board .cn-detail-page .cn-widget-wrapper,
@@ -5878,6 +6373,12 @@ a.cn-kpi-card--board * {
5878
6373
  display: none;
5879
6374
  }
5880
6375
 
6376
+ /* A side card whose widget reports a header action (screens-relation-pages:
6377
+ the "+ Toevoegen" of Contactkanalen and Relaties) keeps that one button. */
6378
+ .cn-look-board .cn-detail-page__side .cn-widget-wrapper__actions:has(.cn-detail-page__catalog-action) {
6379
+ display: flex;
6380
+ }
6381
+
5881
6382
  /* The notice at the top of the side column: radius 12, padding 14px 16px. */
5882
6383
  .cn-look-board .cn-detail-page__side-item--notice .cn-widget-wrapper,
5883
6384
  .cn-look-board .cn-detail-page__side-item--notice .cn-banner-widget,
@@ -9236,9 +9737,95 @@ svg.leaflet-image-layer.leaflet-interactive path {
9236
9737
  does not rest on colour alone. */
9237
9738
  .cn-cell-renderer__date--success[data-v-37d7b88f],
9238
9739
  .cn-cell-renderer__date--warning[data-v-37d7b88f],
9239
- .cn-cell-renderer__date--error[data-v-37d7b88f] {
9740
+ .cn-cell-renderer__date--error[data-v-37d7b88f],
9741
+ .cn-cell-renderer__age--success[data-v-37d7b88f],
9742
+ .cn-cell-renderer__age--warning[data-v-37d7b88f],
9743
+ .cn-cell-renderer__age--error[data-v-37d7b88f] {
9240
9744
  font-weight: 600;
9241
9745
  }
9746
+ .cn-cell-renderer__age[data-v-37d7b88f] {
9747
+ white-space: nowrap;
9748
+ }
9749
+
9750
+ /* The progress cell (abstract-progress-cell): a 56 x 8 bar, the percentage
9751
+ 8px beside it in the bar's tone, and an optional age badge after them, as
9752
+ PqLeads' Winkans column. The value is bold, so the tone is not the only signal. */
9753
+ .cn-cell-renderer__progress[data-v-37d7b88f] {
9754
+ display: inline-flex;
9755
+ flex-wrap: wrap;
9756
+ align-items: center;
9757
+ gap: 4px 8px;
9758
+ }
9759
+ .cn-cell-renderer__progress-line[data-v-37d7b88f] {
9760
+ display: inline-flex;
9761
+ align-items: center;
9762
+ gap: 8px;
9763
+ white-space: nowrap;
9764
+ }
9765
+ .cn-cell-renderer__progress-bar[data-v-37d7b88f] {
9766
+ display: inline-block;
9767
+ width: 56px;
9768
+ height: 8px;
9769
+ border-radius: 4px;
9770
+ background: var(--color-background-dark);
9771
+ overflow: hidden;
9772
+ }
9773
+ .cn-cell-renderer__progress-fill[data-v-37d7b88f] {
9774
+ display: block;
9775
+ height: 100%;
9776
+ }
9777
+ .cn-cell-renderer__progress-fill--success[data-v-37d7b88f] {
9778
+ background: var(--color-element-success, var(--color-success));
9779
+ }
9780
+ .cn-cell-renderer__progress-fill--warning[data-v-37d7b88f] {
9781
+ background: var(--color-element-warning, var(--color-warning));
9782
+ }
9783
+ .cn-cell-renderer__progress-fill--error[data-v-37d7b88f] {
9784
+ background: var(--color-element-error, var(--color-error));
9785
+ }
9786
+ .cn-cell-renderer__progress-value[data-v-37d7b88f] {
9787
+ font-size: 14px;
9788
+ font-weight: 700;
9789
+ }
9790
+ .cn-cell-renderer__progress-value--success[data-v-37d7b88f] {
9791
+ color: var(--color-text-success, var(--color-success-text));
9792
+ }
9793
+ .cn-cell-renderer__progress-value--warning[data-v-37d7b88f] {
9794
+ color: var(--color-text-warning, var(--color-warning-text));
9795
+ }
9796
+ .cn-cell-renderer__progress-value--error[data-v-37d7b88f] {
9797
+ color: var(--color-text-error, var(--color-error-text));
9798
+ }
9799
+ .cn-cell-renderer__progress-badge[data-v-37d7b88f] {
9800
+ display: inline-block;
9801
+ padding: 3px 10px;
9802
+ border-radius: 12px;
9803
+ font-size: 13px;
9804
+ font-weight: 600;
9805
+ white-space: nowrap;
9806
+ }
9807
+ .cn-cell-renderer__progress-badge--error[data-v-37d7b88f] {
9808
+ color: var(--color-text-error, var(--color-error-text));
9809
+ background: var(--color-error-hover, var(--color-background-dark));
9810
+ background: color-mix(in srgb, var(--color-error) 12%, transparent);
9811
+ }
9812
+ .cn-cell-renderer__progress-badge--warning[data-v-37d7b88f] {
9813
+ color: var(--color-text-warning, var(--color-warning-text));
9814
+ background: color-mix(in srgb, var(--color-warning) 14%, transparent);
9815
+ }
9816
+ .cn-cell-renderer__progress-badge--success[data-v-37d7b88f] {
9817
+ color: var(--color-text-success, var(--color-success-text));
9818
+ background: color-mix(in srgb, var(--color-success) 12%, transparent);
9819
+ }
9820
+ .cn-cell-renderer__age--success[data-v-37d7b88f] {
9821
+ color: var(--color-text-success, var(--color-success-text));
9822
+ }
9823
+ .cn-cell-renderer__age--warning[data-v-37d7b88f] {
9824
+ color: var(--color-text-warning, var(--color-warning-text));
9825
+ }
9826
+ .cn-cell-renderer__age--error[data-v-37d7b88f] {
9827
+ color: var(--color-text-error, var(--color-error-text));
9828
+ }
9242
9829
  .cn-cell-renderer__date--success[data-v-37d7b88f] {
9243
9830
  color: var(--color-text-success, var(--color-success-text));
9244
9831
  }
@@ -9534,6 +10121,53 @@ svg.leaflet-image-layer.leaflet-interactive path {
9534
10121
  min-width: 0;
9535
10122
  }
9536
10123
 
10124
+ /* Fit to the container (CnDataTable's `fitWidth`, on in CnWidgetObjectTable).
10125
+
10126
+ In a narrow tile the auto layout made the table as wide as its one-line
10127
+ cells, so it ran past the tile and clipped the trailing column (a date).
10128
+ Here every column but one takes the width of its content (`width: 1%` asks
10129
+ for as little as the content allows), and the grow column takes what is
10130
+ left. `max-width: 0` is what lets that column go below its content's width:
10131
+ the table no longer counts its text, so the text is cut with an ellipsis
10132
+ instead of widening the table. The full value stays in the cell's tooltip. */
10133
+ .cn-data-table--fit {
10134
+ width: 100%;
10135
+ }
10136
+
10137
+ .cn-data-table--fit th,
10138
+ .cn-data-table--fit td {
10139
+ width: 1%;
10140
+ }
10141
+
10142
+ .cn-data-table--fit th.cn-table-col--grow,
10143
+ .cn-data-table--fit td.cn-table-col--grow {
10144
+ width: auto;
10145
+ min-width: 0;
10146
+ max-width: 0;
10147
+ overflow: hidden;
10148
+ text-overflow: ellipsis;
10149
+ white-space: nowrap;
10150
+ }
10151
+
10152
+ /* The secondary line of the growing column ("2026-0004" under a case title)
10153
+ is a line of its own with its own ellipsis. The cell does not wrap, so in
10154
+ the board look, where the secondary line is an inline block (the title
10155
+ underline cannot reach an atomic inline box), it stayed on the title's line
10156
+ and ran out of the tile. A full-width float is a block (computed `display:
10157
+ block`) that always starts under the line before it, and, being out of the
10158
+ flow, the cell's underline does not reach it either. The cell is a table
10159
+ cell, which contains its floats, so the row grows to hold the line.
10160
+ @spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-the-secondary-line-of-a-narrow-tables-growing-column-sits-under-the-value */
10161
+ .cn-data-table.cn-data-table--fit td.cn-table-col--grow .cn-table-cell__secondary {
10162
+ float: inline-start;
10163
+ clear: both;
10164
+ box-sizing: border-box;
10165
+ width: 100%;
10166
+ overflow: hidden;
10167
+ text-overflow: ellipsis;
10168
+ white-space: nowrap;
10169
+ }
10170
+
9537
10171
  .cn-data-table th {
9538
10172
  background: var(--color-background-dark);
9539
10173
  font-weight: 500;
@@ -9882,6 +10516,15 @@ svg.leaflet-image-layer.leaflet-interactive path {
9882
10516
  color: var(--color-text-maxcontrast);
9883
10517
  }
9884
10518
 
10519
+ /* The empty row holds a sentence (the empty text, or why a lens cannot
10520
+ answer), not a cell value: it wraps instead of being cut to one line. The
10521
+ selector carries the table class so it outranks the one-line cell rule. */
10522
+ .cn-data-table .cn-table-empty td {
10523
+ max-width: none;
10524
+ white-space: normal;
10525
+ overflow-wrap: anywhere;
10526
+ }
10527
+
9885
10528
  /* ========================================
9886
10529
  Backwards compatibility aliases
9887
10530
  (legacy OpenRegister CSS class names)
@@ -14545,6 +15188,13 @@ button.cn-files-card__open[data-v-46f7e3c9]:hover {
14545
15188
  min-width: 0;
14546
15189
  flex: 1 1 auto;
14547
15190
  }
15191
+
15192
+ /* The crumbs give way, the controls do not: a long crumb (a folder named
15193
+ after a uuid) shrank the upload button to "Bestanden..." while the crumbs
15194
+ kept their width. */
15195
+ .cn-files-browser__bar[data-v-f5bdd9e2] > :not(.cn-files-browser__crumbs) {
15196
+ flex-shrink: 0;
15197
+ }
14548
15198
  .cn-files-browser__file-input[data-v-f5bdd9e2] {
14549
15199
  display: none;
14550
15200
  }
@@ -20949,6 +21599,38 @@ a.cn-kpi-card--stacked:focus-visible {
20949
21599
  font-weight: 400;
20950
21600
  }
20951
21601
 
21602
+ /* A caption on a line of its own wraps, up to two lines (DqDashboard: "haalden
21603
+ hun termijn, naar doorlooptijd" runs over two lines in a narrow tile). The
21604
+ one-line rule of `.cn-kpi-card__label` is for a caption BESIDE the number,
21605
+ where a second line would push the tile taller; this line has the width of
21606
+ the tile to itself. The clamp is safe here because the element is a plain
21607
+ span, not a flex row (compare the title note above).
21608
+ @spec openspec/changes/dashboard-tile-text-fits/specs/dashboard-tile-text-fits/spec.md#requirement-a-kpi-tiles-caption-and-board-label-wrap-to-two-lines */
21609
+ .cn-kpi-card--stacked .cn-kpi-card__caption-line {
21610
+ display: -webkit-box;
21611
+ -webkit-box-orient: vertical;
21612
+ -webkit-line-clamp: 2;
21613
+ line-clamp: 2;
21614
+ white-space: normal;
21615
+ overflow-wrap: break-word;
21616
+ }
21617
+
21618
+ /* Board look: the label wraps too, up to two lines, beside its icon badge
21619
+ ("Afgehandeld deze maand"). The clamp sits on the label's own span
21620
+ (`cn-kpi-card__title-text`), not on the title row, which stays the flex row
21621
+ that carries the badge or the range select. */
21622
+ .cn-kpi-card--board .cn-kpi-card__title-text {
21623
+ flex: 1 1 auto;
21624
+ min-width: 0;
21625
+ display: -webkit-box;
21626
+ -webkit-box-orient: vertical;
21627
+ -webkit-line-clamp: 2;
21628
+ line-clamp: 2;
21629
+ overflow: hidden;
21630
+ white-space: normal;
21631
+ overflow-wrap: break-word;
21632
+ }
21633
+
20952
21634
  /* The 18px glyph before the label, drawn only on a link tile. */
20953
21635
  .cn-kpi-card--board .cn-kpi-card__title {
20954
21636
  display: flex;
@@ -22978,6 +23660,27 @@ button.cn-stepper__step[data-v-19697746] {
22978
23660
  }
22979
23661
 
22980
23662
 
23663
+ .cn-detail-page__catalog-action[data-v-76c1b60f] {
23664
+ align-items: center;
23665
+ background: var(--color-primary-element-light);
23666
+ border: 0;
23667
+ border-radius: 16px;
23668
+ color: var(--color-primary-element-light-text, var(--color-primary-element));
23669
+ cursor: pointer;
23670
+ display: inline-flex;
23671
+ font: inherit;
23672
+ font-size: 13px;
23673
+ font-weight: 700;
23674
+ gap: 6px;
23675
+ min-height: 32px;
23676
+ padding: 0 14px;
23677
+ white-space: nowrap;
23678
+ }
23679
+ .cn-detail-page__catalog-note[data-v-76c1b60f] {
23680
+ color: var(--color-text-maxcontrast);
23681
+ font-size: 14px;
23682
+ white-space: nowrap;
23683
+ }
22981
23684
  .cn-detail-widget-host[data-v-76c1b60f],
22982
23685
  .cn-detail-widget-host[data-v-76c1b60f] > * {
22983
23686
  height: 100%;
@@ -23267,6 +23970,13 @@ button.cn-stepper__step[data-v-19697746] {
23267
23970
  }
23268
23971
 
23269
23972
 
23973
+ /* A stack (`widgetIds`): the panel's widget, then cards 20px apart. */
23974
+ .cn-tabs-widget__stack[data-v-1dbd6122] {
23975
+ display: flex;
23976
+ flex-direction: column;
23977
+ gap: 20px;
23978
+ }
23979
+
23270
23980
  /* The panel is the card; the strip is not inside it. There is no title bar
23271
23981
  above the tabs either: the open tab names the panel, so a title row would
23272
23982
  say the same thing twice and cost a row of height on a card that is mostly
@@ -27349,6 +28059,441 @@ a.cn-flow-runs-widget__row-content:hover .cn-flow-runs-widget__name[data-v-75628
27349
28059
  }
27350
28060
 
27351
28061
 
28062
+ .cn-sections-widget[data-v-ea4f8722] {
28063
+ min-width: 0;
28064
+ }
28065
+ .cn-sections-widget__column[data-v-ea4f8722] {
28066
+ display: flex;
28067
+ flex-direction: column;
28068
+ gap: calc(var(--default-grid-baseline, 4px) * 4);
28069
+ min-width: 0;
28070
+ }
28071
+
28072
+ /* A main and a side column (the settings boards: 1fr and 418px, 20px apart). */
28073
+ .cn-sections-widget--two-column[data-v-ea4f8722] {
28074
+ display: grid;
28075
+ grid-template-columns: minmax(0, 1fr) minmax(280px, 418px);
28076
+ gap: 20px;
28077
+ align-items: start;
28078
+ }
28079
+ @media (max-width: 1024px) {
28080
+ .cn-sections-widget--two-column[data-v-ea4f8722] {
28081
+ grid-template-columns: minmax(0, 1fr);
28082
+ }
28083
+ }
28084
+
28085
+ /* A host page may space every <section>; these sections are spaced by the column gap only. */
28086
+ .cn-sections-widget__section[data-v-ea4f8722] {
28087
+ margin: 0;
28088
+ min-width: 0;
28089
+ }
28090
+
28091
+ /* A rule above a section that follows a shown one. */
28092
+ .cn-sections-widget:not(.cn-sections-widget--cards) .cn-sections-widget__section:not(.cn-sections-widget__section--empty) ~ .cn-sections-widget__section[data-v-ea4f8722] {
28093
+ padding-top: calc(var(--default-grid-baseline, 4px) * 4);
28094
+ border-top: 1px solid var(--color-border);
28095
+ }
28096
+
28097
+ /*
28098
+ * An empty section keeps its host mounted (display: none still mounts it, so
28099
+ * the widget fetches and can fill later) but takes no space, gap or rule.
28100
+ */
28101
+ .cn-sections-widget__section--empty[data-v-ea4f8722] {
28102
+ display: none;
28103
+ }
28104
+ .cn-sections-widget__heading[data-v-ea4f8722] {
28105
+ margin: 0 0 calc(var(--default-grid-baseline, 4px) * 2);
28106
+ font-size: 16px;
28107
+ font-weight: 600;
28108
+ color: var(--color-main-text);
28109
+ }
28110
+ .cn-sections-widget__description[data-v-ea4f8722] {
28111
+ margin: calc(var(--default-grid-baseline, 4px) * -1) 0 calc(var(--default-grid-baseline, 4px) * 3);
28112
+ color: var(--color-text-maxcontrast);
28113
+ }
28114
+
28115
+ /* One card per section. */
28116
+ .cn-sections-widget--cards .cn-sections-widget__column[data-v-ea4f8722] {
28117
+ gap: 20px;
28118
+ }
28119
+ .cn-sections-widget--cards .cn-sections-widget__section[data-v-ea4f8722] {
28120
+ background: var(--color-main-background);
28121
+ border: 1px solid var(--color-border);
28122
+ border-radius: var(--cn-board-card-radius, var(--border-radius-large, 12px));
28123
+ padding: var(--cn-board-card-padding, 16px 20px);
28124
+ }
28125
+ .cn-sections-widget--cards .cn-sections-widget__heading[data-v-ea4f8722] {
28126
+ font-size: 18px;
28127
+ margin-bottom: 12px;
28128
+ }
28129
+
28130
+
28131
+ .cn-facts-widget[data-v-2ca63011] {
28132
+ display: flex;
28133
+ flex-direction: column;
28134
+ gap: 10px;
28135
+ min-width: 0;
28136
+ }
28137
+ .cn-facts-widget__rows[data-v-2ca63011] {
28138
+ display: grid;
28139
+ grid-template-columns: max-content 1fr;
28140
+ gap: 8px 16px;
28141
+ margin: 0;
28142
+ font-size: 14px;
28143
+ }
28144
+
28145
+ /* Each row is a grid of its own children: the wrapper takes no box. */
28146
+ .cn-facts-widget__row[data-v-2ca63011] {
28147
+ display: contents;
28148
+ }
28149
+ .cn-facts-widget__label[data-v-2ca63011] {
28150
+ color: var(--color-text-maxcontrast);
28151
+ }
28152
+ .cn-facts-widget__value[data-v-2ca63011] {
28153
+ margin: 0;
28154
+ font-weight: 500;
28155
+ min-width: 0;
28156
+ overflow-wrap: anywhere;
28157
+ }
28158
+ .cn-facts-widget__title[data-v-2ca63011] {
28159
+ font-size: 15px;
28160
+ font-weight: 600;
28161
+ color: var(--color-main-text);
28162
+ }
28163
+ .cn-facts-widget__line[data-v-2ca63011] {
28164
+ font-size: 13px;
28165
+ color: var(--color-text-maxcontrast);
28166
+ }
28167
+ .cn-facts-widget__muted[data-v-2ca63011] {
28168
+ margin: 0;
28169
+ color: var(--color-text-maxcontrast);
28170
+ }
28171
+ .cn-facts-widget__label .hidden-visually[data-v-2ca63011] {
28172
+ clip-path: inset(50%);
28173
+ height: 1px;
28174
+ overflow: hidden;
28175
+ position: absolute;
28176
+ white-space: nowrap;
28177
+ width: 1px;
28178
+ }
28179
+ .cn-facts-widget__label--icon[data-v-2ca63011] {
28180
+ align-items: center;
28181
+ display: flex;
28182
+ }
28183
+ .cn-facts-widget__value-link[data-v-2ca63011] {
28184
+ color: var(--color-primary-element);
28185
+ text-decoration: underline;
28186
+ }
28187
+ .cn-facts-widget__inline-button[data-v-2ca63011],
28188
+ .cn-facts-widget__icon-button[data-v-2ca63011],
28189
+ .cn-facts-widget__action[data-v-2ca63011] {
28190
+ align-items: center;
28191
+ cursor: pointer;
28192
+ display: inline-flex;
28193
+ font: inherit;
28194
+ }
28195
+ .cn-facts-widget__inline-button[data-v-2ca63011] {
28196
+ background: var(--color-main-background);
28197
+ border: 1px solid var(--color-border-dark);
28198
+ border-radius: 16px;
28199
+ font-size: 13px;
28200
+ font-weight: 600;
28201
+ gap: 4px;
28202
+ margin-inline-start: 8px;
28203
+ min-height: 28px;
28204
+ padding: 0 10px;
28205
+ }
28206
+ .cn-facts-widget__icon-button[data-v-2ca63011] {
28207
+ background: transparent;
28208
+ border: 0;
28209
+ border-radius: 6px;
28210
+ color: var(--color-text-maxcontrast);
28211
+ margin-inline-start: 4px;
28212
+ padding: 2px;
28213
+ vertical-align: middle;
28214
+ }
28215
+ .cn-facts-widget__icon-button[data-v-2ca63011]:hover,
28216
+ .cn-facts-widget__icon-button[data-v-2ca63011]:focus-visible {
28217
+ background: var(--color-background-hover);
28218
+ color: var(--color-main-text);
28219
+ }
28220
+ .cn-facts-widget__text[data-v-2ca63011] {
28221
+ color: var(--color-main-text);
28222
+ font-size: 15px;
28223
+ }
28224
+
28225
+ /* A lead: an icon tile or initials beside a bold title and a muted subtitle. */
28226
+ .cn-facts-widget__lead[data-v-2ca63011] {
28227
+ align-items: center;
28228
+ display: flex;
28229
+ gap: 12px;
28230
+ }
28231
+ .cn-facts-widget__lead-tile[data-v-2ca63011] {
28232
+ align-items: center;
28233
+ background: var(--color-background-dark);
28234
+ border-radius: 8px;
28235
+ color: var(--color-main-text);
28236
+ display: flex;
28237
+ flex: none;
28238
+ font-size: 14px;
28239
+ font-weight: 700;
28240
+ height: 40px;
28241
+ justify-content: center;
28242
+ width: 40px;
28243
+ }
28244
+ .cn-facts-widget__lead-tile--success[data-v-2ca63011] {
28245
+ background: color-mix(in srgb, var(--color-success) 14%, var(--color-main-background));
28246
+ border-radius: 50%;
28247
+ color: var(--color-success-text, var(--color-success));
28248
+ }
28249
+ .cn-facts-widget__lead-tile--info[data-v-2ca63011] {
28250
+ background: var(--color-primary-element-light);
28251
+ border-radius: 50%;
28252
+ color: var(--color-primary-element-light-text, var(--color-primary-element));
28253
+ }
28254
+ .cn-facts-widget__lead-text[data-v-2ca63011] {
28255
+ display: flex;
28256
+ flex-direction: column;
28257
+ min-width: 0;
28258
+ }
28259
+ .cn-facts-widget__lead-title[data-v-2ca63011] {
28260
+ font-size: 15px;
28261
+ }
28262
+ .cn-facts-widget__lead-subtitle[data-v-2ca63011] {
28263
+ color: var(--color-text-maxcontrast);
28264
+ font-size: 13px;
28265
+ }
28266
+ .cn-facts-widget__action[data-v-2ca63011] {
28267
+ align-self: flex-start;
28268
+ background: var(--color-primary-element-light);
28269
+ border: 0;
28270
+ border-radius: 16px;
28271
+ color: var(--color-primary-element-light-text, var(--color-primary-element));
28272
+ font-size: 13px;
28273
+ font-weight: 700;
28274
+ gap: 6px;
28275
+ min-height: 32px;
28276
+ padding: 0 14px;
28277
+ }
28278
+ .cn-facts-widget__action[data-v-2ca63011]:hover,
28279
+ .cn-facts-widget__action[data-v-2ca63011]:focus-visible {
28280
+ background: var(--color-primary-element-light-hover, var(--color-primary-element-light));
28281
+ }
28282
+ .cn-facts-widget__link[data-v-2ca63011] {
28283
+ font-size: 14px;
28284
+ font-weight: 600;
28285
+ color: var(--color-primary-element);
28286
+ text-decoration: underline;
28287
+ }
28288
+
28289
+
28290
+ .cn-field-list-widget[data-v-0f29a833] {
28291
+ display: flex;
28292
+ flex-direction: column;
28293
+ gap: 12px;
28294
+ min-width: 0;
28295
+ }
28296
+ .cn-field-list-widget__rows[data-v-0f29a833] {
28297
+ list-style: none;
28298
+ margin: 0;
28299
+ padding: 0;
28300
+ display: flex;
28301
+ flex-direction: column;
28302
+ }
28303
+ .cn-field-list-widget__row[data-v-0f29a833] {
28304
+ padding: 10px 0;
28305
+ border-top: 1px solid var(--color-border);
28306
+ }
28307
+ .cn-field-list-widget__row[data-v-0f29a833]:first-child {
28308
+ border-top: none;
28309
+ padding-top: 0;
28310
+ }
28311
+ .cn-field-list-widget__line[data-v-0f29a833] {
28312
+ display: flex;
28313
+ align-items: center;
28314
+ gap: 12px;
28315
+ min-width: 0;
28316
+ }
28317
+ .cn-field-list-widget__avatar[data-v-0f29a833] {
28318
+ flex: 0 0 auto;
28319
+ display: inline-flex;
28320
+ align-items: center;
28321
+ justify-content: center;
28322
+ width: 32px;
28323
+ height: 32px;
28324
+ border-radius: 50%;
28325
+ background: var(--color-primary-element-light);
28326
+ color: var(--color-primary-element-light-text, var(--color-main-text));
28327
+ font-size: 12px;
28328
+ font-weight: 700;
28329
+ }
28330
+ .cn-field-list-widget__main[data-v-0f29a833] {
28331
+ display: flex;
28332
+ flex-direction: column;
28333
+ flex: 1 1 auto;
28334
+ min-width: 0;
28335
+ }
28336
+ .cn-field-list-widget__title[data-v-0f29a833] {
28337
+ font-weight: 600;
28338
+ overflow-wrap: anywhere;
28339
+ }
28340
+ .cn-field-list-widget__meta[data-v-0f29a833],
28341
+ .cn-field-list-widget__aside[data-v-0f29a833],
28342
+ .cn-field-list-widget__detail[data-v-0f29a833],
28343
+ .cn-field-list-widget__hint[data-v-0f29a833],
28344
+ .cn-field-list-widget__empty[data-v-0f29a833] {
28345
+ color: var(--color-text-maxcontrast);
28346
+ }
28347
+ .cn-field-list-widget__meta[data-v-0f29a833],
28348
+ .cn-field-list-widget__aside[data-v-0f29a833],
28349
+ .cn-field-list-widget__detail[data-v-0f29a833] {
28350
+ font-size: 13px;
28351
+ }
28352
+ .cn-field-list-widget__aside[data-v-0f29a833] {
28353
+ white-space: nowrap;
28354
+ }
28355
+ .cn-field-list-widget__detail[data-v-0f29a833],
28356
+ .cn-field-list-widget__hint[data-v-0f29a833],
28357
+ .cn-field-list-widget__empty[data-v-0f29a833] {
28358
+ margin: 4px 0 0;
28359
+ overflow-wrap: anywhere;
28360
+ }
28361
+ .cn-field-list-widget__add[data-v-0f29a833] {
28362
+ display: flex;
28363
+ flex-wrap: wrap;
28364
+ align-items: flex-end;
28365
+ gap: 8px 12px;
28366
+ }
28367
+ .cn-field-list-widget__add[data-v-0f29a833] > * {
28368
+ flex: 1 1 180px;
28369
+ }
28370
+ .cn-field-list-widget__add > button[data-v-0f29a833] {
28371
+ flex: 0 0 auto;
28372
+ }
28373
+
28374
+
28375
+ .cn-record-list__list[data-v-7073b362] {
28376
+ list-style: none;
28377
+ margin: 0;
28378
+ padding: 0;
28379
+ }
28380
+ .cn-record-list__empty[data-v-7073b362],
28381
+ .cn-record-list__error[data-v-7073b362] {
28382
+ color: var(--color-text-maxcontrast);
28383
+ margin: 0;
28384
+ }
28385
+ .cn-record-list__loading[data-v-7073b362] {
28386
+ display: flex;
28387
+ justify-content: center;
28388
+ padding: 8px 0;
28389
+ }
28390
+
28391
+ /* rows */
28392
+ .cn-record-list--rows .cn-record-list__item + .cn-record-list__item[data-v-7073b362] {
28393
+ border-top: 1px solid var(--color-border);
28394
+ }
28395
+ .cn-record-list__row[data-v-7073b362] {
28396
+ align-items: center;
28397
+ color: var(--color-main-text);
28398
+ display: flex;
28399
+ gap: 16px;
28400
+ padding: 12px 0;
28401
+ text-decoration: none;
28402
+ }
28403
+ .cn-record-list__row--link:hover .cn-record-list__title[data-v-7073b362],
28404
+ .cn-record-list__row--link:focus-visible .cn-record-list__title[data-v-7073b362] {
28405
+ text-decoration: underline;
28406
+ }
28407
+ .cn-record-list__main[data-v-7073b362] {
28408
+ display: flex;
28409
+ flex: 1 1 auto;
28410
+ flex-direction: column;
28411
+ gap: 2px;
28412
+ min-width: 0;
28413
+ }
28414
+ .cn-record-list__title[data-v-7073b362] {
28415
+ font-size: 15px;
28416
+ font-weight: 700;
28417
+ }
28418
+ .cn-record-list__meta[data-v-7073b362] {
28419
+ color: var(--color-text-maxcontrast);
28420
+ font-size: 13px;
28421
+ }
28422
+ .cn-record-list__aside[data-v-7073b362] {
28423
+ align-items: center;
28424
+ display: flex;
28425
+ flex: none;
28426
+ gap: 16px;
28427
+ }
28428
+ .cn-record-list__trailing[data-v-7073b362] {
28429
+ font-size: 14px;
28430
+ white-space: nowrap;
28431
+ }
28432
+ .cn-record-list__chevron[data-v-7073b362] {
28433
+ color: var(--color-text-maxcontrast);
28434
+ flex: none;
28435
+ }
28436
+
28437
+ /* feed */
28438
+ .cn-record-list--feed .cn-record-list__item + .cn-record-list__item[data-v-7073b362] {
28439
+ border-top: 1px solid var(--color-border);
28440
+ }
28441
+ .cn-record-list__feed-row[data-v-7073b362] {
28442
+ align-items: flex-start;
28443
+ display: flex;
28444
+ gap: 14px;
28445
+ padding: 12px 0;
28446
+ }
28447
+ .cn-record-list__feed-icon[data-v-7073b362] {
28448
+ align-items: center;
28449
+ background: var(--color-primary-element-light);
28450
+ border-radius: 50%;
28451
+ color: var(--color-primary-element-light-text, var(--color-primary-element));
28452
+ display: flex;
28453
+ flex: none;
28454
+ height: 36px;
28455
+ justify-content: center;
28456
+ width: 36px;
28457
+ }
28458
+ .cn-record-list__text[data-v-7073b362] {
28459
+ font-size: 15px;
28460
+ }
28461
+ .cn-record-list--feed .cn-record-list__main[data-v-7073b362] {
28462
+ color: var(--color-main-text);
28463
+ text-decoration: none;
28464
+ }
28465
+
28466
+ /* inline */
28467
+ .cn-record-list__inline-row[data-v-7073b362] {
28468
+ padding: 4px 0;
28469
+ }
28470
+ .cn-record-list__label[data-v-7073b362] {
28471
+ margin-inline-end: 4px;
28472
+ }
28473
+ .cn-record-list__inline-title[data-v-7073b362] {
28474
+ color: var(--color-main-text);
28475
+ }
28476
+ a.cn-record-list__inline-title[data-v-7073b362] {
28477
+ color: var(--color-primary-element);
28478
+ text-decoration: underline;
28479
+ }
28480
+
28481
+
28482
+ /* In a narrow side column a row stacks: title, meta, then pill and date. */
28483
+ .cn-detail-page__side .cn-record-list__row {
28484
+ align-items: flex-start;
28485
+ flex-direction: column;
28486
+ gap: 6px;
28487
+ }
28488
+ .cn-detail-page__side .cn-record-list__row .cn-record-list__title {
28489
+ color: var(--color-primary-element);
28490
+ text-decoration: underline;
28491
+ }
28492
+ .cn-detail-page__side .cn-record-list__chevron {
28493
+ display: none;
28494
+ }
28495
+
28496
+
27352
28497
  .cn-notepad-widget-form[data-v-c752df66] {
27353
28498
  display: flex;
27354
28499
  flex-direction: column;
@@ -27659,6 +28804,40 @@ a.cn-flow-runs-widget__row-content:hover .cn-flow-runs-widget__name[data-v-75628
27659
28804
  flex-direction: column;
27660
28805
  gap: 2px;
27661
28806
  }
28807
+
28808
+ /* The start card: text left, control (and link) right, as PqDashboard's "Contact starten". */
28809
+ .cn-workspace-filter-widget--start[data-v-f0d5c1c6] {
28810
+ flex-direction: row;
28811
+ flex-wrap: wrap;
28812
+ align-items: center;
28813
+ gap: 16px 24px;
28814
+ }
28815
+ .cn-workspace-filter-widget__text[data-v-f0d5c1c6] {
28816
+ flex: 1 1 320px;
28817
+ min-width: 0;
28818
+ }
28819
+ .cn-workspace-filter-widget__title[data-v-f0d5c1c6] {
28820
+ margin: 0 0 4px;
28821
+ font-size: 17px;
28822
+ font-weight: 700;
28823
+ color: var(--color-main-text);
28824
+ }
28825
+ .cn-workspace-filter-widget__description[data-v-f0d5c1c6] {
28826
+ margin: 0;
28827
+ max-width: 420px;
28828
+ color: var(--color-text-maxcontrast);
28829
+ }
28830
+ .cn-workspace-filter-widget--start .cn-workspace-filter-widget__control[data-v-f0d5c1c6],
28831
+ .cn-workspace-filter-widget--start > .v-select[data-v-f0d5c1c6] {
28832
+ flex: 0 1 480px;
28833
+ min-width: 240px;
28834
+ }
28835
+ .cn-workspace-filter-widget__link[data-v-f0d5c1c6] {
28836
+ font-weight: 600;
28837
+ color: var(--color-primary-element);
28838
+ text-decoration: underline;
28839
+ white-space: nowrap;
28840
+ }
27662
28841
  .cn-workspace-filter-widget__count[data-v-f0d5c1c6] {
27663
28842
  margin-inline-start: 6px;
27664
28843
  padding: 0 6px;
@@ -32554,6 +33733,86 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
32554
33733
  }
32555
33734
 
32556
33735
 
33736
+ /*
33737
+ * Layout only — this component draws no KPI of its own; the tiles inside it do
33738
+ * (src/css/kpi-card.css). What it DOES owe the canonical look is the rhythm
33739
+ * around those tiles, so the gutter is the card's own `--cn-kpi-grid-gap`
33740
+ * rather than a number picked here. A grid whose gutter disagrees with the
33741
+ * card's padding reads as a different design even when every tile is
33742
+ * identical.
33743
+ */
33744
+ .cn-kpi-grid[data-v-e31696e2] {
33745
+ display: grid;
33746
+ gap: var(--cn-kpi-grid-gap, 16px);
33747
+ margin-bottom: 24px;
33748
+ }
33749
+
33750
+ /*
33751
+ * `minmax(0, 1fr)`, not `1fr`. A grid track's default minimum is `auto`, which
33752
+ * refuses to shrink below its content — and the canonical KPI value is
33753
+ * deliberately `white-space: nowrap`, so a long number (a formatted currency
33754
+ * amount, a six-figure count) pushes its track wider than its share and the
33755
+ * whole row overflows the page. With a 0 minimum the track holds its share and
33756
+ * the card's own `overflow: hidden` clips instead.
33757
+ */
33758
+ .cn-kpi-grid--cols-2[data-v-e31696e2] {
33759
+ grid-template-columns: repeat(2, minmax(0, 1fr));
33760
+ }
33761
+ .cn-kpi-grid--cols-3[data-v-e31696e2] {
33762
+ grid-template-columns: repeat(3, minmax(0, 1fr));
33763
+ }
33764
+ .cn-kpi-grid--cols-4[data-v-e31696e2] {
33765
+ grid-template-columns: repeat(4, minmax(0, 1fr));
33766
+ }
33767
+
33768
+ /* Auto: as many 200px columns as fit (screens-dashboard-parity). */
33769
+ .cn-kpi-grid--cols-auto[data-v-e31696e2] {
33770
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
33771
+ }
33772
+
33773
+ /* Responsive breakpoints */
33774
+ @media (max-width: 1200px) {
33775
+ .cn-kpi-grid--cols-4[data-v-e31696e2] {
33776
+ grid-template-columns: repeat(2, minmax(0, 1fr));
33777
+ }
33778
+ }
33779
+ @media (max-width: 900px) {
33780
+ .cn-kpi-grid--cols-3[data-v-e31696e2] {
33781
+ grid-template-columns: repeat(2, minmax(0, 1fr));
33782
+ }
33783
+ }
33784
+ @media (max-width: 600px) {
33785
+ .cn-kpi-grid--cols-2[data-v-e31696e2],
33786
+ .cn-kpi-grid--cols-3[data-v-e31696e2],
33787
+ .cn-kpi-grid--cols-4[data-v-e31696e2] {
33788
+ grid-template-columns: minmax(0, 1fr);
33789
+ }
33790
+ }
33791
+
33792
+
33793
+ .cn-index-page-widgets--stat-row[data-v-5ec0c5bc] {
33794
+ margin-bottom: var(--cn-board-section-gap, 20px);
33795
+ }
33796
+ .cn-index-page-widgets__cell[data-v-5ec0c5bc] {
33797
+ display: flex;
33798
+ min-width: 0;
33799
+ }
33800
+ .cn-index-page-widgets__cell[data-v-5ec0c5bc] > * {
33801
+ flex: 1 1 auto;
33802
+ min-width: 0;
33803
+ }
33804
+
33805
+ /* The side panel column (DqTeamwachtrij: 300px, 16px between cards). Its
33806
+ place beside the toolbar and the list is set by CnIndexPage
33807
+ (`cn-index-page--with-side-panel`, index-page.css). */
33808
+ .cn-index-page-widgets--side-panel[data-v-5ec0c5bc] {
33809
+ display: flex;
33810
+ flex-direction: column;
33811
+ gap: 16px;
33812
+ min-width: 0;
33813
+ }
33814
+
33815
+
32557
33816
  .cn-advanced-form-dialog__json-editor[data-v-733de04c] {
32558
33817
  display: flex;
32559
33818
  flex-direction: column;
@@ -33829,63 +35088,6 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
33829
35088
  }
33830
35089
 
33831
35090
 
33832
- /*
33833
- * Layout only — this component draws no KPI of its own; the tiles inside it do
33834
- * (src/css/kpi-card.css). What it DOES owe the canonical look is the rhythm
33835
- * around those tiles, so the gutter is the card's own `--cn-kpi-grid-gap`
33836
- * rather than a number picked here. A grid whose gutter disagrees with the
33837
- * card's padding reads as a different design even when every tile is
33838
- * identical.
33839
- */
33840
- .cn-kpi-grid[data-v-e31696e2] {
33841
- display: grid;
33842
- gap: var(--cn-kpi-grid-gap, 16px);
33843
- margin-bottom: 24px;
33844
- }
33845
-
33846
- /*
33847
- * `minmax(0, 1fr)`, not `1fr`. A grid track's default minimum is `auto`, which
33848
- * refuses to shrink below its content — and the canonical KPI value is
33849
- * deliberately `white-space: nowrap`, so a long number (a formatted currency
33850
- * amount, a six-figure count) pushes its track wider than its share and the
33851
- * whole row overflows the page. With a 0 minimum the track holds its share and
33852
- * the card's own `overflow: hidden` clips instead.
33853
- */
33854
- .cn-kpi-grid--cols-2[data-v-e31696e2] {
33855
- grid-template-columns: repeat(2, minmax(0, 1fr));
33856
- }
33857
- .cn-kpi-grid--cols-3[data-v-e31696e2] {
33858
- grid-template-columns: repeat(3, minmax(0, 1fr));
33859
- }
33860
- .cn-kpi-grid--cols-4[data-v-e31696e2] {
33861
- grid-template-columns: repeat(4, minmax(0, 1fr));
33862
- }
33863
-
33864
- /* Auto: as many 200px columns as fit (screens-dashboard-parity). */
33865
- .cn-kpi-grid--cols-auto[data-v-e31696e2] {
33866
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
33867
- }
33868
-
33869
- /* Responsive breakpoints */
33870
- @media (max-width: 1200px) {
33871
- .cn-kpi-grid--cols-4[data-v-e31696e2] {
33872
- grid-template-columns: repeat(2, minmax(0, 1fr));
33873
- }
33874
- }
33875
- @media (max-width: 900px) {
33876
- .cn-kpi-grid--cols-3[data-v-e31696e2] {
33877
- grid-template-columns: repeat(2, minmax(0, 1fr));
33878
- }
33879
- }
33880
- @media (max-width: 600px) {
33881
- .cn-kpi-grid--cols-2[data-v-e31696e2],
33882
- .cn-kpi-grid--cols-3[data-v-e31696e2],
33883
- .cn-kpi-grid--cols-4[data-v-e31696e2] {
33884
- grid-template-columns: minmax(0, 1fr);
33885
- }
33886
- }
33887
-
33888
-
33889
35091
  .cn-export-wizard__description[data-v-59983562] {
33890
35092
  color: var(--color-text-maxcontrast);
33891
35093
  margin-bottom: 12px;
@@ -35021,6 +36223,44 @@ button.cn-object-calendar__overflow[data-v-bea31862] {
35021
36223
  height: var(--cn-board-control-height, 40px);
35022
36224
  }
35023
36225
 
36226
+ /* The switch row under the header (screens-dashboard-greeting-header): the
36227
+ view switch left, the `viewLinks` pills right (DqMijnWerk: pills 34px high,
36228
+ radius 17, 13px/600, a 14px icon, primary light on primary deep). */
36229
+ .cn-dashboard-page__switch-row[data-v-824052fe] {
36230
+ display: flex;
36231
+ flex-wrap: wrap;
36232
+ align-items: center;
36233
+ gap: 10px;
36234
+ margin-bottom: var(--cn-board-section-gap, 20px);
36235
+ }
36236
+ .cn-dashboard-page__switch-row-spacer[data-v-824052fe] {
36237
+ flex: 1 1 auto;
36238
+ }
36239
+ .cn-dashboard-page__view-link[data-v-824052fe] {
36240
+ display: inline-flex;
36241
+ align-items: center;
36242
+ gap: 6px;
36243
+ height: 34px;
36244
+ padding: 0 12px;
36245
+ border-radius: 17px;
36246
+ background: var(--color-primary-element-light);
36247
+ color: var(--color-primary-element-light-text);
36248
+ font-size: 13px;
36249
+ font-weight: 600;
36250
+ white-space: nowrap;
36251
+ text-decoration: none !important;
36252
+ }
36253
+ .cn-dashboard-page__view-link[data-v-824052fe]:hover {
36254
+ background: var(--color-primary-element-light-hover, var(--color-primary-element-light));
36255
+ }
36256
+ .cn-dashboard-page__view-link[data-v-824052fe]:focus-visible {
36257
+ outline: 2px solid var(--color-main-text);
36258
+ outline-offset: 2px;
36259
+ }
36260
+ .cn-dashboard-page__view-link-icon[data-v-824052fe] {
36261
+ display: inline-flex;
36262
+ }
36263
+
35024
36264
  /* The period group, in a row of its own between the header and the KPI row. */
35025
36265
  .cn-dashboard-page__date-range--segmented[data-v-824052fe] {
35026
36266
  margin-bottom: 16px;